[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