[Python-checkins] distutils2: Basic caching support added to pkgutil

tarek.ziade python-checkins at python.org
Sun Aug 8 11:50:45 CEST 2010


tarek.ziade pushed 969b80c7655a to distutils2:

http://hg.python.org/distutils2/rev/969b80c7655a
changeset:   423:969b80c7655a
parent:      214:d5d979a9145a
user:        Josip Djolonga
date:        Tue Jun 22 19:16:11 2010 +0200
summary:     Basic caching support added to pkgutil
files:       src/distutils2/_backport/pkgutil.py

diff --git a/src/distutils2/_backport/pkgutil.py b/src/distutils2/_backport/pkgutil.py
--- a/src/distutils2/_backport/pkgutil.py
+++ b/src/distutils2/_backport/pkgutil.py
@@ -29,7 +29,6 @@
     'provides_distribution', 'obsoletes_distribution',
 ]
 
-
 def read_code(stream):
     # This helper is needed in order for the :pep:`302` emulation to
     # correctly handle compiled files
@@ -613,6 +612,49 @@
 
 DIST_FILES = ('INSTALLER', 'METADATA', 'RECORD', 'REQUESTED',)
 
+# Cache
+_cache_name = {} # maps names to Distribution instances
+_cache_name_egg = {} # maps names to EggInfoDistribution instances
+_cache_path = {} # maps paths to Distribution instances
+_cache_path_egg = {} # maps paths to EggInfoDistribution instances
+_cache_generated = False
+
+def clear_cache():
+    global _cache_name, _cache_name_egg, cache_path, _cache_path_egg, \
+           _cache_generated
+
+    _cache_name = {}
+    _cache_name_egg = {}
+    _cache_path = {}
+    _cache_path_egg = {}
+    _cache_generated = False
+
+def _generate_cache():
+    clear_cache()
+
+    global _cache_generated
+
+    for path in sys.path:
+        realpath = os.path.realpath(path)
+        if not os.path.isdir(realpath):
+            continue
+        for dir in os.listdir(realpath):
+            dist_path = os.path.join(realpath, dir)
+            if dir.endswith('.dist-info'):
+                dist = Distribution(dist_path)
+                _cache_path[dist_path] = dist
+                if not dist.name in _cache_name:
+                    _cache_name[dist.name] = []
+                _cache_name[dist.name].append(dist)
+            elif dir.endswith('.egg-info') or dir.endswith('.egg'):
+                dist = EggInfoDistribution(dist_path)
+                _cache_path_egg[dist_path] = dist
+                if not dist.name in _cache_name_egg:
+                    _cache_name_egg[dist.name] = []
+                _cache_name_egg[dist.name].append(dist)
+    _cache_generated = True
+
+
 
 class Distribution(object):
     """Created with the *path* of the ``.dist-info`` directory provided to the
@@ -631,11 +673,18 @@
     (in other words, whether the package was installed by user request)."""
 
     def __init__(self, path):
+        if path in _cache_path:
+            self.metadata = _cache_path[path].metadata
+        else:
+            metadata_path = os.path.join(path, 'METADATA')
+            self.metadata = DistributionMetadata(path=metadata_path)
+
         self.path = path
-        metadata_path = os.path.join(path, 'METADATA')
-        self.metadata = DistributionMetadata(path=metadata_path)
         self.name = self.metadata['name']
 
+        if not path in _cache_path:
+            _cache_path[path] = self
+
     def _get_records(self, local=False):
         RECORD = os.path.join(self.path, 'RECORD')
         record_reader = csv_reader(open(RECORD, 'rb'), delimiter=',')
@@ -753,6 +802,11 @@
     def __init__(self, path):
         self.path = path
 
+        if path in _cache_path_egg:
+            self.metadata = _cache_path_egg[path].metadata
+            self.name = self.metadata['Name']
+            return
+
         # reused from Distribute's pkg_resources
         def yield_lines(strs):
             """Yield non-empty/non-comment lines of a ``basestring`` or sequence"""
@@ -784,7 +838,7 @@
                     requires = zipf.get_data('EGG-INFO/requires.txt')
                 except IOError:
                     requires = None
-            self.name = self.metadata['name']
+            self.name = self.metadata['Name']
         elif path.endswith('.egg-info'):
             if os.path.isdir(path):
                 path = os.path.join(path, 'PKG-INFO')
@@ -837,6 +891,8 @@
             else:
                 self.metadata['Requires'] += reqs
 
+            _cache_path_egg[path] = self
+
     def get_installed_files(self, local=False):
         return []
 
@@ -847,13 +903,11 @@
         return isinstance(other, EggInfoDistribution) and \
                self.path == other.path
 
-
 def _normalize_dist_name(name):
     """Returns a normalized name from the given *name*.
     :rtype: string"""
     return name.replace('-', '_')
 
-
 def distinfo_dirname(name, version):
     """
     The *name* and *version* parameters are converted into their
@@ -892,19 +946,13 @@
 
     :rtype: iterator of :class:`Distribution` and :class:`EggInfoDistribution`
             instances"""
-    for path in sys.path:
-        realpath = os.path.realpath(path)
-        if not os.path.isdir(realpath):
-            continue
-        for dir in os.listdir(realpath):
-            if dir.endswith('.dist-info'):
-                dist = Distribution(os.path.join(realpath, dir))
-                yield dist
-            elif use_egg_info and (dir.endswith('.egg-info') or
-                                   dir.endswith('.egg')):
-                dist = EggInfoDistribution(os.path.join(realpath, dir))
-                yield dist
-
+    if not _cache_generated:
+        _generate_cache()
+    for dist in _cache_path.itervalues():
+        yield dist
+    if use_egg_info:
+        for dist in _cache_path_egg.itervalues():
+            yield dist
 
 def get_distribution(name, use_egg_info=False):
     """
@@ -922,17 +970,15 @@
     value is expected. If the directory is not found, ``None`` is returned.
 
     :rtype: :class:`Distribution` or :class:`EggInfoDistribution` or None"""
-    found = None
-    for dist in get_distributions():
-        if dist.name == name:
-            found = dist
-            break
-    if use_egg_info:
-        for dist in get_distributions(True):
-            if dist.name == name:
-                found = dist
-                break
-    return found
+    if not _cache_generated:
+        _generate_cache()
+
+    if name in _cache_name:
+        return _cache_name[name][0]
+    elif use_egg_info and name in _cache_name_egg:
+        return _cache_name_egg[name][0]
+    else:
+        return None
 
 
 def obsoletes_distribution(name, version=None, use_egg_info=False):

--
Repository URL: http://hg.python.org/distutils2


More information about the Python-checkins mailing list