52
52
mkdir(dirname, mode)
57
def _declare_state(vartype, **kw):
59
for name, val in kw.iteritems():
61
_state_vars[name] = vartype
66
for k, v in _state_vars.iteritems():
67
state[k] = g['_sget_'+v](g[k])
70
def __setstate__(state):
72
for k, v in state.iteritems():
73
g['_sset_'+_state_vars[k]](k, g[k], v)
79
def _sset_dict(key, ob, state):
83
def _sget_object(val):
84
return val.__getstate__()
86
def _sset_object(key, ob, state):
87
ob.__setstate__(state)
89
_sget_none = _sset_none = lambda *args: None
672
708
for callback in self.callbacks:
711
def __getstate__(self):
712
return (self.entries[:], self.entry_keys.copy(), self.by_key.copy(),
715
def __setstate__(self, (entries, keys, by_key, callbacks)):
716
self.entries = entries[:]
717
self.entry_keys = keys.copy()
718
self.by_key = by_key.copy()
719
self.callbacks = callbacks[:]
1699
1746
# scan for .egg and .egg-info in directory
1700
1747
for entry in os.listdir(path_item):
1701
1748
lower = entry.lower()
1702
if lower.endswith('.egg-info'):
1749
if lower.endswith('.egg-info') or lower.endswith('.dist-info'):
1703
1750
fullpath = os.path.join(path_item, entry)
1704
1751
if os.path.isdir(fullpath):
1705
1752
# egg-info directory, allow getting metadata
1721
1768
register_finder(ImpWrapper,find_on_path)
1723
_namespace_handlers = {}
1724
_namespace_packages = {}
1772
import _frozen_importlib
1776
register_finder(_frozen_importlib.FileFinder, find_on_path)
1778
_declare_state('dict', _namespace_handlers={})
1779
_declare_state('dict', _namespace_packages={})
1726
1782
def register_namespace_handler(importer_type, namespace_handler):
1727
1783
"""Register `namespace_handler` to declare namespace packages
1817
1874
register_namespace_handler(ImpWrapper,file_ns_handler)
1818
1875
register_namespace_handler(zipimport.zipimporter,file_ns_handler)
1879
import _frozen_importlib
1883
register_namespace_handler(_frozen_importlib.FileFinder, file_ns_handler)
1821
1886
def null_ns_handler(importer, path_item, packageName, module):
1875
1940
def _parse_version_parts(s):
1876
1941
for part in component_re.split(s):
1877
1942
part = replace(part,part)
1878
if not part or part=='.':
1943
if part in ['', '.']:
1880
1945
if part[:1] in '0123456789':
1881
1946
yield part.zfill(8) # pad for numeric comparison
2057
2120
class Distribution(object):
2058
2121
"""Wrap an actual or potential sys.path entry w/metadata"""
2122
PKG_INFO = 'PKG-INFO'
2059
2124
def __init__(self,
2060
2125
location=None, metadata=None, project_name=None, version=None,
2061
2126
py_version=PY_MAJOR, platform=None, precedence = EGG_DIST
2073
2138
def from_location(cls,location,basename,metadata=None,**kw):
2074
2139
project_name, version, py_version, platform = [None]*4
2075
2140
basename, ext = os.path.splitext(basename)
2076
if ext.lower() in (".egg",".egg-info"):
2141
if ext.lower() in _distributionImpl:
2142
# .dist-info gets much metadata differently
2077
2143
match = EGG_NAME(basename)
2079
2145
project_name, version, py_version, platform = match.group(
2080
2146
'name','ver','pyver','plat'
2148
cls = _distributionImpl[ext.lower()]
2083
2150
location, metadata, project_name=project_name, version=version,
2084
2151
py_version=py_version, platform=platform, **kw
2142
2209
return self._version
2143
2210
except AttributeError:
2144
for line in self._get_metadata('PKG-INFO'):
2211
for line in self._get_metadata(self.PKG_INFO):
2145
2212
if line.lower().startswith('version:'):
2146
2213
self._version = safe_version(line.split(':',1)[1].strip())
2147
2214
return self._version
2149
2216
raise ValueError(
2150
"Missing 'Version:' header and/or PKG-INFO file", self
2217
"Missing 'Version:' header and/or %s file" % self.PKG_INFO, self
2152
2219
version = property(version)
2378
2445
extras = property(extras)
2448
class DistInfoDistribution(Distribution):
2449
"""Wrap an actual or potential sys.path entry w/metadata, .dist-info style"""
2450
PKG_INFO = 'METADATA'
2451
EQEQ = re.compile(r"([\(,])\s*(\d.*?)\s*([,\)])")
2454
def _parsed_pkg_info(self):
2455
"""Parse and cache metadata"""
2457
return self._pkg_info
2458
except AttributeError:
2459
from email.parser import Parser
2460
self._pkg_info = Parser().parsestr(self.get_metadata(self.PKG_INFO))
2461
return self._pkg_info
2466
return self.__dep_map
2467
except AttributeError:
2468
self.__dep_map = self._compute_dependencies()
2469
return self.__dep_map
2471
def _preparse_requirement(self, requires_dist):
2472
"""Convert 'Foobar (1); baz' to ('Foobar ==1', 'baz')
2473
Split environment marker, add == prefix to version specifiers as
2474
necessary, and remove parenthesis.
2476
parts = requires_dist.split(';', 1) + ['']
2477
distvers = parts[0].strip()
2478
mark = parts[1].strip()
2479
distvers = re.sub(self.EQEQ, r"\1==\2\3", distvers)
2480
distvers = distvers.replace('(', '').replace(')', '')
2481
return (distvers, mark)
2483
def _compute_dependencies(self):
2484
"""Recompute this distribution's dependencies."""
2485
def dummy_marker(marker):
2486
def marker_fn(environment=None, override=None):
2488
marker_fn.__doc__ = marker
2491
from markerlib import as_function
2493
as_function = dummy_marker
2494
dm = self.__dep_map = {None: []}
2497
# Including any condition expressions
2498
for req in self._parsed_pkg_info.get_all('Requires-Dist') or []:
2499
distvers, mark = self._preparse_requirement(req)
2500
parsed = parse_requirements(distvers).next()
2501
parsed.marker_fn = as_function(mark)
2504
def reqs_for_extra(extra):
2506
if req.marker_fn(override={'extra':extra}):
2509
common = set(reqs_for_extra(None))
2510
dm[None].extend(common)
2512
for extra in self._parsed_pkg_info.get_all('Provides-Extra') or []:
2513
extra = safe_extra(extra.strip())
2514
dm[extra] = list(set(reqs_for_extra(extra)) - common)
2519
_distributionImpl = {'.egg': Distribution,
2520
'.egg-info': Distribution,
2521
'.dist-info': DistInfoDistribution }
2381
2524
def issue_warning(*args,**kw):