diff options
| author | PJ Eby <distutils-sig@python.org> | 2006-02-14 19:05:04 +0000 |
|---|---|---|
| committer | PJ Eby <distutils-sig@python.org> | 2006-02-14 19:05:04 +0000 |
| commit | 38aa9be2b1edfa477277d4c1494642061cf43a0f (patch) | |
| tree | 622d8895245d5cceed05da865a7f8bac9479b92a /pkg_resources.py | |
| parent | f4be07202e3e615ba7fc0e2256d236356cdc6902 (diff) | |
| download | python-setuptools-git-38aa9be2b1edfa477277d4c1494642061cf43a0f.tar.gz | |
Added the ``extras`` attribute to ``Distribution``, the ``find_plugins()``
method to ``WorkingSet``, and the ``__add__()`` and ``__iadd__()`` methods
to ``Environment``.
--HG--
branch : setuptools
extra : convert_revision : svn%3A6015fed2-1504-0410-9fe1-9d1591cc4771/sandbox/trunk/setuptools%4042358
Diffstat (limited to 'pkg_resources.py')
| -rw-r--r-- | pkg_resources.py | 137 |
1 files changed, 130 insertions, 7 deletions
diff --git a/pkg_resources.py b/pkg_resources.py index efda22ca..a221a086 100644 --- a/pkg_resources.py +++ b/pkg_resources.py @@ -490,6 +490,88 @@ class WorkingSet(object): return to_activate # return list of distros to activate + def find_plugins(self, + plugin_env, full_env=None, installer=None, fallback=True + ): + """Find all activatable distributions in `plugin_env` + + Example usage:: + + distributions, errors = working_set.find_plugins( + Environment(plugin_dirlist) + ) + map(working_set.add, distributions) # add plugins+libs to sys.path + print "Couldn't load", errors # display errors + + The `plugin_env` should be an ``Environment`` instance that contains + only distributions that are in the project's "plugin directory" or + directories. The `full_env`, if supplied, should be an ``Environment`` + contains all currently-available distributions. If `full_env` is not + supplied, one is created automatically from the ``WorkingSet`` this + method is called on, which will typically mean that every directory on + ``sys.path`` will be scanned for distributions. + + `installer` is a standard installer callback as used by the + ``resolve()`` method. The `fallback` flag indicates whether we should + attempt to resolve older versions of a plugin if the newest version + cannot be resolved. + + This method returns a 2-tuple: (`distributions`, `error_info`), where + `distributions` is a list of the distributions found in `plugin_env` + that were loadable, along with any other distributions that are needed + to resolve their dependencies. `error_info` is a dictionary mapping + unloadable plugin distributions to an exception instance describing the + error that occurred. Usually this will be a ``DistributionNotFound`` or + ``VersionConflict`` instance. + """ + + plugin_projects = list(plugin_env) + plugin_projects.sort() # scan project names in alphabetic order + + error_info = {} + distributions = {} + + if full_env is None: + env = Environment(self.entries) + env += plugin_env + else: + env = full_env + plugin_env + + shadow_set = self.__class__([]) + map(shadow_set.add, self) # put all our entries in shadow_set + + for project_name in plugin_projects: + + for dist in plugin_env[project_name]: + + req = [dist.as_requirement()] + + try: + resolvees = shadow_set.resolve(req, env, installer) + + except ResolutionError,v: + error_info[dist] = v # save error info + if fallback: + continue # try the next older version of project + else: + break # give up on this project, keep going + + else: + map(shadow_set.add, resolvees) + distributions.update(dict.fromkeys(resolvees)) + + # success, no need to try any more versions of this project + break + + distributions = list(distributions) + distributions.sort() + + return distributions, error_info + + + + + def require(self, *requirements): """Ensure that distributions matching `requirements` are activated @@ -651,9 +733,50 @@ class Environment(object): for key in self._distmap.keys(): if self[key]: yield key + + + + def __iadd__(self, other): + """In-place addition of a distribution or environment""" + if isinstance(other,Distribution): + self.add(other) + elif isinstance(other,Environment): + for project in other: + for dist in other[project]: + self.add(dist) + else: + raise TypeError("Can't add %r to environment" % (other,)) + return self + + def __add__(self, other): + """Add an environment or distribution to an environment""" + new = self.__class__([], platform=None, python=None) + for env in self, other: + new += env + return new + + AvailableDistributions = Environment # XXX backward compatibility + + + + + + + + + + + + + + + + + + class ResourceManager: """Manage resource extraction and packages""" extraction_path = None @@ -1373,7 +1496,7 @@ def find_on_path(importer, path_item, only=False): lower = entry.lower() if lower.endswith('.egg-info'): fullpath = os.path.join(path_item, entry) - if os.path.isdir(fullpath): + if os.path.isdir(fullpath): # egg-info directory, allow getting metadata metadata = PathMetadata(path_item, fullpath) else: @@ -1966,6 +2089,12 @@ class Distribution(object): + #@property + def extras(self): + return [dep for dep in self._dep_map if dep] + extras = property(extras) + + def issue_warning(*args,**kw): level = 1 g = globals() @@ -2001,12 +2130,6 @@ def issue_warning(*args,**kw): - - - - - - def parse_requirements(strs): """Yield ``Requirement`` objects for each specification in `strs` |
