Merge lp:~jml/launchpad/import-fascist-tweaks into lp:launchpad
- import-fascist-tweaks
- Merge into devel
Proposed by
Jonathan Lange
Status: | Merged |
---|---|
Approved by: | Muharem Hrnjadovic |
Approved revision: | not available |
Merged at revision: | not available |
Proposed branch: | lp:~jml/launchpad/import-fascist-tweaks |
Merge into: | lp:launchpad |
Diff against target: |
375 lines (+90/-54) 13 files modified
lib/canonical/launchpad/fields/__init__.py (+2/-0) lib/lp/bugs/model/bugwatch.py (+1/-2) lib/lp/buildmaster/interfaces/buildfarmjobbehavior.py (+1/-0) lib/lp/registry/interfaces/mailinglist.py (+1/-1) lib/lp/registry/interfaces/teammembership.py (+1/-0) lib/lp/registry/model/structuralsubscription.py (+3/-1) lib/lp/scripts/utilities/importfascist.py (+66/-39) lib/lp/services/job/interfaces/job.py (+1/-0) lib/lp/soyuz/model/archive.py (+8/-4) lib/lp/soyuz/model/archivesubscriber.py (+2/-2) lib/lp/soyuz/model/builder.py (+2/-3) lib/lp/soyuz/model/distroarchseries.py (+1/-2) lib/lp/soyuz/model/files.py (+1/-0) |
To merge this branch: | bzr merge lp:~jml/launchpad/import-fascist-tweaks |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Muharem Hrnjadovic (community) | Approve | ||
Review via email: mp+16560@code.launchpad.net |
Commit message
importfascist now checks 'lp' package and is now more data-driven. Many dodgy imports fixed.
Description of the change
To post a comment you must log in.
Revision history for this message
Jonathan Lange (jml) wrote : | # |
Revision history for this message
Muharem Hrnjadovic (al-maisan) wrote : | # |
Nice branch, approved with the changes in http://
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/canonical/launchpad/fields/__init__.py' |
2 | --- lib/canonical/launchpad/fields/__init__.py 2009-12-09 23:11:31 +0000 |
3 | +++ lib/canonical/launchpad/fields/__init__.py 2009-12-24 08:18:19 +0000 |
4 | @@ -32,9 +32,11 @@ |
5 | 'LocationField', |
6 | 'LogoImageUpload', |
7 | 'MugshotImageUpload', |
8 | + 'NoneableDescription', |
9 | 'NoneableTextLine', |
10 | 'ParticipatingPersonChoice', |
11 | 'PasswordField', |
12 | + 'PersonChoice', |
13 | 'PillarAliases', |
14 | 'PillarNameField', |
15 | 'PrivateMembershipTeamNotAllowed', |
16 | |
17 | === modified file 'lib/lp/bugs/model/bugwatch.py' |
18 | --- lib/lp/bugs/model/bugwatch.py 2009-12-15 17:28:51 +0000 |
19 | +++ lib/lp/bugs/model/bugwatch.py 2009-12-24 08:18:19 +0000 |
20 | @@ -35,10 +35,9 @@ |
21 | from canonical.launchpad.webapp import urlappend, urlsplit |
22 | from canonical.launchpad.webapp.interfaces import NotFoundError |
23 | |
24 | -from lp.bugs.interfaces.bug import IBugWatch |
25 | from lp.bugs.interfaces.bugtracker import BugTrackerType, IBugTrackerSet |
26 | from lp.bugs.interfaces.bugwatch import ( |
27 | - BugWatchErrorType, IBugWatchSet, NoBugTrackerFound, |
28 | + BugWatchErrorType, IBugWatch, IBugWatchSet, NoBugTrackerFound, |
29 | UnrecognizedBugTrackerURL) |
30 | from lp.bugs.model.bugmessage import BugMessage |
31 | from lp.bugs.model.bugset import BugSetBase |
32 | |
33 | === modified file 'lib/lp/buildmaster/interfaces/buildfarmjobbehavior.py' |
34 | --- lib/lp/buildmaster/interfaces/buildfarmjobbehavior.py 2009-12-03 14:38:48 +0000 |
35 | +++ lib/lp/buildmaster/interfaces/buildfarmjobbehavior.py 2009-12-24 08:18:19 +0000 |
36 | @@ -8,6 +8,7 @@ |
37 | __metaclass__ = type |
38 | |
39 | __all__ = [ |
40 | + 'BuildBehaviorMismatch', |
41 | 'IBuildFarmJobBehavior', |
42 | ] |
43 | |
44 | |
45 | === modified file 'lib/lp/registry/interfaces/mailinglist.py' |
46 | --- lib/lp/registry/interfaces/mailinglist.py 2009-12-03 19:12:02 +0000 |
47 | +++ lib/lp/registry/interfaces/mailinglist.py 2009-12-24 08:18:19 +0000 |
48 | @@ -31,7 +31,7 @@ |
49 | |
50 | from canonical.launchpad import _ |
51 | from canonical.launchpad.fields import PublicPersonChoice |
52 | -from lp.registry.interfaces.person import IEmailAddress |
53 | +from canonical.launchpad.interfaces.emailaddress import IEmailAddress |
54 | from canonical.launchpad.interfaces.librarian import ILibraryFileAlias |
55 | from canonical.launchpad.interfaces.message import IMessage |
56 | from lp.registry.interfaces.person import IPerson |
57 | |
58 | === modified file 'lib/lp/registry/interfaces/teammembership.py' |
59 | --- lib/lp/registry/interfaces/teammembership.py 2009-12-19 22:19:12 +0000 |
60 | +++ lib/lp/registry/interfaces/teammembership.py 2009-12-24 08:18:19 +0000 |
61 | @@ -14,6 +14,7 @@ |
62 | 'ITeamMembershipSet', |
63 | 'ITeamParticipation', |
64 | 'TeamMembershipStatus', |
65 | + 'UserCannotChangeMembershipSilently', |
66 | ] |
67 | |
68 | from zope.schema import Bool, Choice, Datetime, Int, Text |
69 | |
70 | === modified file 'lib/lp/registry/model/structuralsubscription.py' |
71 | --- lib/lp/registry/model/structuralsubscription.py 2009-12-05 18:37:28 +0000 |
72 | +++ lib/lp/registry/model/structuralsubscription.py 2009-12-24 08:18:19 +0000 |
73 | @@ -17,9 +17,11 @@ |
74 | |
75 | from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities |
76 | from lp.registry.interfaces.distribution import IDistribution |
77 | +from lp.registry.interfaces.distributionsourcepackage import ( |
78 | + IDistributionSourcePackage) |
79 | from lp.registry.interfaces.distroseries import IDistroSeries |
80 | from lp.registry.interfaces.milestone import IMilestone |
81 | -from lp.registry.interfaces.product import IDistributionSourcePackage, IProduct |
82 | +from lp.registry.interfaces.product import IProduct |
83 | from lp.registry.interfaces.productseries import IProductSeries |
84 | from lp.registry.interfaces.project import IProject |
85 | from lp.registry.interfaces.structuralsubscription import ( |
86 | |
87 | === modified file 'lib/lp/scripts/utilities/importfascist.py' |
88 | --- lib/lp/scripts/utilities/importfascist.py 2009-08-27 01:32:01 +0000 |
89 | +++ lib/lp/scripts/utilities/importfascist.py 2009-12-24 08:18:19 +0000 |
90 | @@ -52,6 +52,17 @@ |
91 | """) |
92 | |
93 | |
94 | +# Sometimes, third-party modules don't export all of their public APIs through |
95 | +# __all__. The following dict maps from such modules to a list of attributes |
96 | +# that are allowed to be imported, whether or not they are in __all__. |
97 | +valid_imports_not_in_all = { |
98 | + 'cookielib': set(['domain_match']), |
99 | + 'email.Utils': set(['mktime_tz']), |
100 | + 'textwrap': set(['dedent']), |
101 | + 'zope.component': set(['adapter', 'provideHandler']), |
102 | + } |
103 | + |
104 | + |
105 | def database_import_allowed_into(module_path): |
106 | """Return True if database code is allowed to be imported into the given |
107 | module path. Otherwise, returns False. |
108 | @@ -156,11 +167,11 @@ |
109 | |
110 | |
111 | # pylint: disable-msg=W0102,W0602 |
112 | -def import_fascist(name, globals={}, locals={}, fromlist=[]): |
113 | +def import_fascist(module_name, globals={}, locals={}, from_list=[]): |
114 | global naughty_imports |
115 | |
116 | try: |
117 | - module = original_import(name, globals, locals, fromlist) |
118 | + module = original_import(module_name, globals, locals, from_list) |
119 | except ImportError: |
120 | # XXX sinzui 2008-04-17 bug=277274: |
121 | # import_fascist screws zope configuration module which introspects |
122 | @@ -170,19 +181,18 @@ |
123 | # time doesn't exist and dies a horrible death because of the import |
124 | # fascist. That's the long explanation for why we special case this |
125 | # module. |
126 | - if name.startswith('zope.app.layers.'): |
127 | - name = name[16:] |
128 | - module = original_import(name, globals, locals, fromlist) |
129 | + if module_name.startswith('zope.app.layers.'): |
130 | + module_name = module_name[16:] |
131 | + module = original_import(module_name, globals, locals, from_list) |
132 | else: |
133 | raise |
134 | # Python's re module imports some odd stuff every time certain regexes |
135 | # are used. Let's optimize this. |
136 | - # Also, 'dedent' is not in textwrap.__all__. |
137 | - if name == 'sre' or name == 'textwrap': |
138 | + if module_name == 'sre': |
139 | return module |
140 | |
141 | # Mailman 2.1 code base is originally circa 1998, so yeah, no __all__'s. |
142 | - if name.startswith('Mailman'): |
143 | + if module_name.startswith('Mailman'): |
144 | return module |
145 | |
146 | # Some uses of __import__ pass None for globals, so handle that. |
147 | @@ -195,13 +205,17 @@ |
148 | # We could find out by jumping up the stack a frame. |
149 | # Let's not for now. |
150 | import_into = '__import__ hook' |
151 | + |
152 | + # Check the "NotFoundError" policy. |
153 | if (import_into.startswith('canonical.launchpad.database') and |
154 | - name == 'zope.exceptions'): |
155 | - if fromlist and 'NotFoundError' in fromlist: |
156 | + module_name == 'zope.exceptions'): |
157 | + if from_list and 'NotFoundError' in from_list: |
158 | raise NotFoundPolicyViolation(import_into) |
159 | - if (name.startswith(database_root) and |
160 | + |
161 | + # Check the database import policy. |
162 | + if (module_name.startswith(database_root) and |
163 | not database_import_allowed_into(import_into)): |
164 | - error = DatabaseImportPolicyViolation(import_into, name) |
165 | + error = DatabaseImportPolicyViolation(import_into, module_name) |
166 | naughty_imports.add(error) |
167 | # Raise an error except in the case of browser.traversers. |
168 | # This exception to raising an error is only temporary, until |
169 | @@ -209,34 +223,48 @@ |
170 | if import_into not in warned_database_imports: |
171 | raise error |
172 | |
173 | - if fromlist is not None and import_into.startswith('canonical'): |
174 | + # Check the import from __all__ policy. |
175 | + if from_list is not None and ( |
176 | + import_into.startswith('canonical') or import_into.startswith('lp')): |
177 | # We only want to warn about "from foo import bar" violations in our |
178 | # own code. |
179 | - if list(fromlist) == ['*'] and not hasattr(module, '__all__'): |
180 | - # "from foo import *" is naughty if foo has no __all__ |
181 | - error = FromStarPolicyViolation(import_into, name) |
182 | - naughty_imports.add(error) |
183 | - raise error |
184 | - elif (list(fromlist) != ['*'] and hasattr(module, '__all__') and |
185 | - not is_test_module(import_into)): |
186 | - # "from foo import bar" is naughty if bar isn't in foo.__all__ |
187 | - # (and foo actually has an __all__). Unless foo is within a tests |
188 | - # or ftests module or bar is itself a module. |
189 | - for attrname in fromlist: |
190 | - if (attrname in ('adapter', 'provideHandler') |
191 | - and module.__name__ == 'zope.component'): |
192 | - # 'adapter' and 'provideHandler' are not in |
193 | - # zope.component.__all__, but that's where they should be |
194 | - # imported from. |
195 | - continue |
196 | - if attrname != '__doc__' and attrname not in module.__all__: |
197 | - if not isinstance( |
198 | - getattr(module, attrname, None), types.ModuleType): |
199 | - error = NotInModuleAllPolicyViolation( |
200 | - import_into, name, attrname) |
201 | - naughty_imports.add(error) |
202 | - # Not raising on NotInModuleAllPolicyViolation yet. |
203 | - #raise error |
204 | + from_list = list(from_list) |
205 | + module_all = getattr(module, '__all__', None) |
206 | + if module_all is None: |
207 | + if from_list == ['*']: |
208 | + # "from foo import *" is naughty if foo has no __all__ |
209 | + error = FromStarPolicyViolation(import_into, module_name) |
210 | + naughty_imports.add(error) |
211 | + raise error |
212 | + else: |
213 | + if from_list == ['*']: |
214 | + # "from foo import *" is allowed if foo has an __all__ |
215 | + return module |
216 | + if is_test_module(import_into): |
217 | + # We don't bother checking imports into test modules. |
218 | + return module |
219 | + allowed_from_list = valid_imports_not_in_all.get( |
220 | + module_name, set()) |
221 | + for attrname in from_list: |
222 | + # Check that each thing we are importing into the module is |
223 | + # either in __all__, is a module itself, or is a specific |
224 | + # exception. |
225 | + if attrname == '__doc__': |
226 | + # You can always import __doc__. |
227 | + continue |
228 | + if isinstance( |
229 | + getattr(module, attrname, None), types.ModuleType): |
230 | + # You can import modules even when they aren't declared in |
231 | + # __all__. |
232 | + continue |
233 | + if attrname in allowed_from_list: |
234 | + # Some things can be imported even if they aren't in |
235 | + # __all__. |
236 | + continue |
237 | + if attrname not in module_all: |
238 | + error = NotInModuleAllPolicyViolation( |
239 | + import_into, module_name, attrname) |
240 | + naughty_imports.add(error) |
241 | return module |
242 | |
243 | |
244 | @@ -244,7 +272,6 @@ |
245 | if naughty_imports: |
246 | |
247 | print '** %d import policy violations **' % len(naughty_imports) |
248 | - current_type = None |
249 | |
250 | database_violations = [] |
251 | fromstar_violations = [] |
252 | |
253 | === modified file 'lib/lp/services/job/interfaces/job.py' |
254 | --- lib/lp/services/job/interfaces/job.py 2009-09-02 21:09:48 +0000 |
255 | +++ lib/lp/services/job/interfaces/job.py 2009-12-24 08:18:19 +0000 |
256 | @@ -9,6 +9,7 @@ |
257 | |
258 | __all__ = [ |
259 | 'IJob', |
260 | + 'IRunnableJob', |
261 | 'JobStatus', |
262 | 'LeaseHeld', |
263 | ] |
264 | |
265 | === modified file 'lib/lp/soyuz/model/archive.py' |
266 | --- lib/lp/soyuz/model/archive.py 2009-12-08 15:40:23 +0000 |
267 | +++ lib/lp/soyuz/model/archive.py 2009-12-24 08:18:19 +0000 |
268 | @@ -54,7 +54,7 @@ |
269 | from lp.registry.model.teammembership import TeamParticipation |
270 | from lp.soyuz.interfaces.archive import ( |
271 | AlreadySubscribed, ArchiveDependencyError, ArchiveNotPrivate, |
272 | - ArchivePurpose, DistroSeriesNotFound, IArchive, IArchiveSet, |
273 | + ArchivePurpose, CannotCopy, DistroSeriesNotFound, IArchive, IArchiveSet, |
274 | IDistributionArchive, InvalidComponent, IPPA, MAIN_ARCHIVE_PURPOSES, |
275 | NoSuchPPA, PocketNotFound, VersionRequiresName, default_name_by_purpose) |
276 | from lp.soyuz.interfaces.archiveauthtoken import IArchiveAuthTokenSet |
277 | @@ -77,7 +77,7 @@ |
278 | from lp.soyuz.interfaces.publishing import ( |
279 | active_publishing_status, PackagePublishingStatus, IPublishingSet) |
280 | from lp.registry.interfaces.sourcepackagename import ISourcePackageNameSet |
281 | -from lp.soyuz.scripts.packagecopier import CannotCopy, do_copy |
282 | +from lp.soyuz.scripts.packagecopier import do_copy |
283 | from canonical.launchpad.webapp.interfaces import ( |
284 | IStoreSelector, MAIN_STORE, DEFAULT_FLAVOR) |
285 | from canonical.launchpad.webapp.url import urlappend |
286 | @@ -1096,7 +1096,9 @@ |
287 | # Find and validate the source package names in source_names. |
288 | sources = [] |
289 | for name in source_names: |
290 | - source_package_name = getUtility(ISourcePackageNameSet)[name] |
291 | + # Check to see if the source package exists, and raise a useful |
292 | + # error if it doesn't. |
293 | + getUtility(ISourcePackageNameSet)[name] |
294 | # Grabbing the item at index 0 ensures it's the most recent |
295 | # publication. |
296 | sources.append( |
297 | @@ -1108,8 +1110,10 @@ |
298 | def syncSource(self, source_name, version, from_archive, to_pocket, |
299 | to_series=None, include_binaries=False): |
300 | """See `IArchive`.""" |
301 | + # Check to see if the source package exists, and raise a useful error |
302 | + # if it doesn't. |
303 | + getUtility(ISourcePackageNameSet)[source_name] |
304 | # Find and validate the source package version required. |
305 | - source_package_name = getUtility(ISourcePackageNameSet)[source_name] |
306 | source = from_archive.getPublishedSources( |
307 | name=source_name, version=version, exact_match=True)[0] |
308 | |
309 | |
310 | === modified file 'lib/lp/soyuz/model/archivesubscriber.py' |
311 | --- lib/lp/soyuz/model/archivesubscriber.py 2009-07-17 00:26:05 +0000 |
312 | +++ lib/lp/soyuz/model/archivesubscriber.py 2009-12-24 08:18:19 +0000 |
313 | @@ -20,8 +20,8 @@ |
314 | |
315 | from canonical.database.constants import UTC_NOW |
316 | from canonical.database.enumcol import DBEnum |
317 | -from lp.soyuz.model.archiveauthtoken import ( |
318 | - ArchiveAuthToken, IArchiveAuthTokenSet) |
319 | +from lp.soyuz.interfaces.archiveauthtoken import IArchiveAuthTokenSet |
320 | +from lp.soyuz.model.archiveauthtoken import ArchiveAuthToken |
321 | from lp.registry.interfaces.person import ( |
322 | validate_person_not_private_membership) |
323 | from lp.registry.model.teammembership import TeamParticipation |
324 | |
325 | === modified file 'lib/lp/soyuz/model/builder.py' |
326 | --- lib/lp/soyuz/model/builder.py 2009-12-04 12:49:25 +0000 |
327 | +++ lib/lp/soyuz/model/builder.py 2009-12-24 08:18:19 +0000 |
328 | @@ -42,8 +42,7 @@ |
329 | from lp.registry.interfaces.person import validate_public_person |
330 | from lp.registry.interfaces.pocket import PackagePublishingPocket |
331 | from canonical.launchpad.helpers import filenameToContentType |
332 | -from canonical.launchpad.interfaces._schema_circular_imports import ( |
333 | - IHasBuildRecords) |
334 | +from lp.soyuz.interfaces.buildrecords import IHasBuildRecords |
335 | from lp.soyuz.interfaces.distroarchseries import IDistroArchSeriesSet |
336 | from canonical.launchpad.interfaces.librarian import ILibraryFileAliasSet |
337 | from canonical.launchpad.webapp.interfaces import NotFoundError |
338 | @@ -380,7 +379,7 @@ |
339 | return False |
340 | try: |
341 | slavestatus = self.slaveStatusSentence() |
342 | - except (xmlrpclib.Fault, socket.error), info: |
343 | + except (xmlrpclib.Fault, socket.error): |
344 | return False |
345 | if slavestatus[0] != BuilderStatus.IDLE: |
346 | return False |
347 | |
348 | === modified file 'lib/lp/soyuz/model/distroarchseries.py' |
349 | --- lib/lp/soyuz/model/distroarchseries.py 2009-08-28 07:34:44 +0000 |
350 | +++ lib/lp/soyuz/model/distroarchseries.py 2009-12-24 08:18:19 +0000 |
351 | @@ -23,12 +23,11 @@ |
352 | |
353 | from canonical.launchpad.components.decoratedresultset import ( |
354 | DecoratedResultSet) |
355 | -from canonical.launchpad.interfaces._schema_circular_imports import ( |
356 | - IHasBuildRecords) |
357 | from lp.registry.interfaces.pocket import PackagePublishingPocket |
358 | from lp.soyuz.interfaces.binarypackagename import IBinaryPackageName |
359 | from lp.soyuz.interfaces.binarypackagerelease import IBinaryPackageReleaseSet |
360 | from lp.soyuz.interfaces.build import IBuildSet |
361 | +from lp.soyuz.interfaces.buildrecords import IHasBuildRecords |
362 | from lp.soyuz.interfaces.distroarchseries import ( |
363 | IDistroArchSeries, IDistroArchSeriesSet, IPocketChroot) |
364 | from lp.soyuz.interfaces.publishing import ( |
365 | |
366 | === modified file 'lib/lp/soyuz/model/files.py' |
367 | --- lib/lp/soyuz/model/files.py 2009-11-25 23:41:34 +0000 |
368 | +++ lib/lp/soyuz/model/files.py 2009-12-24 08:18:19 +0000 |
369 | @@ -7,6 +7,7 @@ |
370 | __all__ = [ |
371 | 'BinaryPackageFile', |
372 | 'BinaryPackageFileSet', |
373 | + 'SourceFileMixin', |
374 | 'SourcePackageReleaseFile', |
375 | ] |
376 |
This branch does a few different things, all to do with the import fascist. The patch:
* restructures the logic to be a bit clearer.
* provides a data-driven approach for allowing imports that aren't in __all__
* makes importfascist check packages in 'lp' and not just 'canonical'
* stops the warnings that we were all getting when running the tests
* fixes a whole bunch of warnings that we weren't getting because of 'lp' being ignored
* cleans up random pyflakes
Merry Christmas