Commits

ta...@MacZiade  committed f3f46f1

changed container api+reflect changes on pep 376

  • Participants
  • Parent commits fbf7c9b

Comments (0)

Files changed (3)

+^lib$
+^bin$
+^include$
+.*\.pyc$
+^\.Python$
+^\.hgignore$
+

File docs/pep-0376

 - a new `.egg-info` structure using a directory, based on the `EggFormats`
   standard from `setuptools` [#eggformats]_.
 - new APIs in `pkgutil` to be able to query the information of installed
-  projects. 
+  projects.
 - a de-facto replacement for PEP 262
 - an uninstall function in Distutils.
 
 The egg-info directory name is created using a new function called
 ``egg_info_dirname(name, version)`` added to ``pkgutil``. ``name`` is
 converted to a standard distribution name any runs of non-alphanumeric
-characters are replaced with a single '-'. ``version`` is converted 
-to a standard version string. Spaces become dots, and all other 
-non-alphanumeric characters become dashes, with runs of multiple dashes 
-condensed to a single dash. Both attributes are then converted into their 
+characters are replaced with a single '-'. ``version`` is converted
+to a standard version string. Spaces become dots, and all other
+non-alphanumeric characters become dashes, with runs of multiple dashes
+condensed to a single dash. Both attributes are then converted into their
 filename-escaped form. Any '-' characters are currently replaced with '_'.
 
 Examples::
 To use the `.egg-info` directory content, we need to add in the standard
 library a set of APIs. The best place to put these APIs seems to be `pkgutil`.
 
+The API is organized in three classes:
+
+- ``EggInfo``: manages an `.egg-info` directory.
+- ``EggInfoDirectory``: manages a directory that contains some `.egg-info`
+  directories.
+- ``EggInfoDirectories``: manages ``EggInfoDirectory`` instances.
+
 EggInfo class
 -------------
 
-A new class called ``EggInfo`` is created, which provides the following
-attributes:
+A new class called ``EggInfo`` is created with a the path of the `.egg-info`
+directory provided to the contructor. It reads the metadata contained in
+`PKG-INFO` when it is instanciated.
+
+``EggInfo`` provides the following attributes:
 
 - ``name``: The name of the project
 
 - ``metadata``: A ``DistributionMetadata`` instance loaded with the project's
   PKG-INFO file
 
-The following methods are provided:
+And following methods:
 
 - ``get_installed_files(local=False)`` -> iterator of (path, md5, size)
 
-  Iterates over the `RECORD` entries and return a tuple ``(path, md5, size)`` 
-  for each line. If ``local`` is ``True``, the path is transformed into a 
+  Iterates over the `RECORD` entries and return a tuple ``(path, md5, size)``
+  for each line. If ``local`` is ``True``, the path is transformed into a
   local absolute path. Otherwise the raw value from `RECORD` is returned.
 
 - ``uses(path)`` -> Boolean
   Returns ``True`` if ``path`` is listed in `RECORD`. ``path``
   can be a local absolute path or a relative '/'-separated path.
 
-- ``owns(path)`` -> Boolean
-
-  Returns ``True`` if ``path`` is owned by the project.
-  Owned means that the path is used only by this project and is not used
-  by any other project. ``path`` can be a local absolute path or a relative
-  '/'-separated path.
-
 - ``get_file(path, binary=False)`` -> file object
 
-  Returns a ``file`` instance for the file pointed by ``path``. ``path`` can be 
-  a local absolute path or a relative '/'-separated path. If ``binary`` is 
+  Returns a ``file`` instance for the file pointed by ``path``. ``path`` can be
+  a local absolute path or a relative '/'-separated path. If ``binary`` is
   ``True``, opens the file in binary mode.
 
+EggInfoDirectory class
+----------------------
+
+A new class called ``EggInfoDirectory`` is created with a path corresponding
+to a directory. For each `.egg-info` directory founded in `path`, the class
+creates a corresponding ``EggInfo``.
+
+The class is iterable, and returns every ``EggInfo`` instance created.
+
+It also provides two methods:
+
+- ``file_users(self, path)`` -> Iterator of ``EggInfo``.
+
+  Returns all ``EggInfo`` which uses ``path``, by calling
+  ``EggInfo.uses(path)`` on all ``EggInfo`` instances.
+
+- ``owner(self, path)`` -> ``EggInfo`` instance or None
+
+  If ``path`` is used by only one ``EggInfo`` instance, returns it.
+  Otherwise returns None.
+
+EggInfoDirectories class
+-------------------------
+
+A new class called ``EggInfoDirectories`` is created. It's a collection of
+``EggInfoDirectory`` instances. The constructor takes one optional
+argument ``use_cache`` set to ``True`` by default. When ``True``,
+``EggInfoDirectories`` will use a global cache to reduce the numbers of I/O
+accesses and speed up the lookups.
+
+The cache is a global mapping containing ``EggInfoDirectory`` instances.
+When an ``EggInfoDirectories`` object is created, it will use the cache to
+add an entry for each path it visits, or reuse existing entries. The cache
+usage can be disabled at any time with the `use_cache` attribute.
+
+The cache can also be emptied with the global ``purge_cache`` function.
+
+The class is iterable, and returns every ``EggInfo`` instance from every
+``EggInfoDirectory`` instance it contains.
+
+``EggInfoDirectories`` also provides the following container and helper
+methods::
+
+- ``append(path)``
+
+  Creates an ``EggInfoDirectory`` instance. for ``path`` appends it.
+
+- ``remove(egg_info_dir)``
+
+  Removes the ``EggInfoDirectory`` instance for the given ``path``.
+
+- ``clear()``
+
+  Removes all elements.
+
+- ``load(paths)``
+
+  Creates and adds ``EggInfoDirectory`` instances corresponding to ``paths``.
+
+- ``reload()``
+
+  Reloads existing entries.
+
+- ``get_egg_infos()`` -> Iterator of ``EggInfo`` instances.
+
+  Iterates over all ``EggInfo`` contained in ``EggInfoDirectory`` instances.
+
+- ``get_egg_info(project_name)`` -> ``EggInfo`` or None.
+
+  Returns an EggInfo instance for the given project name.
+  If not found, returns None.
+
+- ``get_file_users(path)`` -> Iterator of ``EggInfo`` instances.
+
+  Iterates over all projects to find out which project uses the file.
+  Returns ``EggInfo`` instances.
+
 .egg-info functions
 -------------------
 
 The new functions added in the ``pkgutil`` are :
 
-- ``get_egg_infos()`` -> iterator
+- ``get_egg_infos(paths=sys.path)`` -> iterator
 
   Provides an iterator that looks for ``.egg-info`` directories in ``sys.path``
   and returns ``EggInfo`` instances for each one of them.
 
-- ``get_egg_info(project_name)`` -> path or None
+- ``get_egg_info(project_name, paths=sys.path)`` -> path or None
 
   Scans all elements in ``sys.path`` and looks for all directories ending with
   ``.egg-info``. Returns an ``EggInfo`` corresponding to the ``.egg-info``
   Notice that there should be at most one result. The first result founded
   will be returned. If the directory is not found, returns None.
 
-- ``get_file_users(path)`` -> iterator of ``EggInfo`` instances.
+- ``get_file_users(path, paths=sys.path)`` -> iterator of ``EggInfo`` instances.
 
   Iterates over all projects to find out which project uses ``path``.
   ``path`` can be a local absolute path or a relative '/'-separated path.
 
-Cache functions
----------------
-
-The functions from the previous section work with a global memory cache to
-reduce the numbers of I/O accesses and speed up the lookups.
-
-The cache can be managed with these functions:
-
-- ``purge_cache``: removes all entries from cache.
-- ``cache_enabled``: returns ``True`` if the cache is enabled.
-- ``enable_cache``: enables the cache.
-- ``disable_cache``: disables the cache.
+All these functions use the same global instance of ``EggInfoDirectories`` to
+use the cache. Notice that the cache is never emptied explicitely so it keeps
+on growing everytime it is used with new paths.
 
 Example
 -------
     def __iter__(self):
         return iter(self._egg_info_dirs)
 
-    def append(self, egg_info):
-        self._egg_info_dirs.append(egg_info)
-        self._paths.append(egg_info.path)
-        if self.use_cache:
-            _CACHED_DIRS[egg_info.path] = egg_info
+    def append(self, path):
+        if self.use_cache and path in _CACHED_DIRS:
+            egg_info_dir = _CACHED_DIRS[path]
+        else:
+            egg_info_dir = EggInfoDirectory(path)
+            if self.use_cache:
+                _CACHED_DIRS[path] = egg_info_dir
+
+        self._egg_info_dirs.append(egg_info_dir)
+        self._paths.append(path)
 
     def clear(self):
         self._egg_info_dirs.clear()
         self._paths.clear()
 
-    def remove(self, egg_info):
-        self._egg_info_dirs.remove(egg_info)
-        self._paths.remove(egg_info.path)
+    def remove(self, egg_info_dir):
+        self._egg_info_dirs.remove(egg_info_dir)
+        self._paths.remove(egg_info_dir.path)
 
     #
     # public APIs
     #
     def load(self, paths):
         for path in paths:
-            if path in self._paths:
+            if path in self._paths or not os.path.isdir(path):
                 continue
-            if self.use_cache and path in _CACHED_DIRS:
-                self.append(_CACHED_DIRS[path])
-            elif os.path.isdir(path):
-                self.append(EggInfoDirectory(path))
+            self.append(path)
 
     def reload(self):
         paths = [d.path for d in self]