[Checkins] SVN: z3c.autoinclude/trunk/src/z3c/autoinclude/utils.py
Reimplement distributionForPackage; its tests now pass.
Ethan Jucovy
ejucovy at openplans.org
Sat Apr 19 16:18:29 EDT 2008
Log message for revision 85492:
Reimplement distributionForPackage; its tests now pass.
As suspected, the old algorithm was faulty because it assumed that a module object's __file__ correctly reflected the filepath to that module; however, namespace packages which extend that module's namespace will clobber __file__ so that is unreliable. The new algorithm is roughly::
* Given a module_dottedname to find the distribution of ... for every entry in sys.path:
* Reject any entry that's not an egg.
* Find all distributions contained within the path.
* For every distribution contained within the path:
* Reject any distribution that doesn't have module_dottedname in its contained packages
* Reject any distribution that DOES have module_dottedname in its namespace_packages (declared in the egg metadata)
* Hope that only one candidate remains unrejected, and return that candidate as correct.
This is much more robust; thanks to dcrosta for helping with it.
Changed:
U z3c.autoinclude/trunk/src/z3c/autoinclude/utils.py
-=-
Modified: z3c.autoinclude/trunk/src/z3c/autoinclude/utils.py
===================================================================
--- z3c.autoinclude/trunk/src/z3c/autoinclude/utils.py 2008-04-19 20:10:42 UTC (rev 85491)
+++ z3c.autoinclude/trunk/src/z3c/autoinclude/utils.py 2008-04-19 20:18:29 UTC (rev 85492)
@@ -1,6 +1,7 @@
import logging
import os
from pkg_resources import find_distributions
+from setuptools import find_packages
import sys
from zope.dottedname.resolve import resolve
@@ -60,14 +61,27 @@
return False
def distributionForPackage(package):
-
package_filename = package.__file__
+ package_dottedname = package.__name__
+ valid_dists_for_package = []
for path in sys.path:
- if package_filename.startswith(path):
- break
- dists = list(find_distributions(path, True))
- assert dists, "No distributions found for package %s/%s" % (path, package_filename)
- return dists[0]
+ dists = find_distributions(path, True)
+ for dist in dists:
+ if not os.path.isdir(dist.location):
+ continue
+ packages = find_packages(dist.location)
+ try:
+ ns_packages = dist.get_metadata_lines('namespace_packages.txt')
+ except IOError:
+ ns_packages = []
+ if package_dottedname in ns_packages:
+ continue
+ if package_dottedname not in packages:
+ continue
+ valid_dists_for_package.append(dist)
+ assert valid_dists_for_package, "No distributions found for package %s." % package_filename
+ assert len(valid_dists_for_package) == 1, "Multiple distributions found for package %s; z3c.autoinclude cowardly refuses to guess." % package_filename
+ return valid_dists_for_package[0]
def distributionForDottedName(dotted_name):
return distributionForPackage(resolve(dotted_name))
More information about the Checkins
mailing list