Bug 1680802: Bump vendored virtualenv package r=firefox-build-system-reviewers,sheehan,glandium

The `wheel` package was failing with Mac Big Sur.
It's been updated, but our `virtualenv` package
has its own vendored `wheel` package that is out-of-date.

This should solve "assert len(base_version) == 2" and
"would build wheel with unsupported tag" errors.

Differential Revision: https://phabricator.services.mozilla.com/D99482
This commit is contained in:
Mitchell Hentges 2020-12-15 20:52:15 +00:00
Родитель 2ea65ad1e2
Коммит 9f175925f2
116 изменённых файлов: 2759 добавлений и 645 удалений

2
third_party/python/virtualenv/__main__.py поставляемый
Просмотреть файл

@ -4,7 +4,7 @@ import sys
import zipfile import zipfile
ABS_HERE = os.path.abspath(os.path.dirname(__file__)) ABS_HERE = os.path.abspath(os.path.dirname(__file__))
NEW_IMPORT_SYSTEM = sys.version_info[0:2] > (3, 4) NEW_IMPORT_SYSTEM = sys.version_info[0] == 3
class VersionPlatformSelect(object): class VersionPlatformSelect(object):

Просмотреть файл

@ -1,6 +1,6 @@
filelock.py,sha256=5DQTtOaQq7-vgLkZzvOhqhVMh_umfydWgSA8Vuzmf8M,13229 filelock.py,sha256=5DQTtOaQq7-vgLkZzvOhqhVMh_umfydWgSA8Vuzmf8M,13229
filelock-3.0.12.dist-info/LICENSE,sha256=iNm062BXnBkew5HKBMFhMFctfu3EqG2qWL8oxuFMm80,1210 filelock-3.0.12.dist-info/LICENSE,sha256=iNm062BXnBkew5HKBMFhMFctfu3EqG2qWL8oxuFMm80,1210
filelock-3.0.12.dist-info/METADATA,sha256=gjzbv9nxtD-Rj2ysjUuG7SLZCHUQl5hMy68Jij8soPw,4343 filelock-3.0.12.dist-info/METADATA,sha256=gjzbv9nxtD-Rj2ysjUuG7SLZCHUQl5hMy68Jij8soPw,4343
filelock-3.0.12.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92 filelock-3.0.12.dist-info/WHEEL,sha256=EVRjI69F5qVjm_YgqcTXPnTAv3BfSUr0WVAHuSP3Xoo,92
filelock-3.0.12.dist-info/top_level.txt,sha256=NDrf9i5BNogz4hEdsr6Hi7Ws3TlSSKY4Q2Y9_-i2GwU,9 filelock-3.0.12.dist-info/top_level.txt,sha256=NDrf9i5BNogz4hEdsr6Hi7Ws3TlSSKY4Q2Y9_-i2GwU,9
filelock-3.0.12.dist-info/RECORD,, filelock-3.0.12.dist-info/RECORD,,

Просмотреть файл

@ -1,5 +1,5 @@
Wheel-Version: 1.0 Wheel-Version: 1.0
Generator: bdist_wheel (0.34.2) Generator: bdist_wheel (0.35.1)
Root-Is-Purelib: true Root-Is-Purelib: true
Tag: py3-none-any Tag: py3-none-any

Просмотреть файл

@ -1,21 +0,0 @@
importlib_metadata/__init__.py,sha256=phnrEcGP-8cF-_ZZ5peJL4cUVAANOK0CpSWC-0-IVAs,18961
importlib_metadata/_compat.py,sha256=DnM55BbJKFCcZmJOkArmyO76-0g7pA6HEfzSYWXN88k,4417
importlib_metadata/docs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
importlib_metadata/docs/changelog.rst,sha256=6EZfl84T0SQHzAXNlTiTegG0cBTa9wiMt0od0ht2n_8,8739
importlib_metadata/docs/conf.py,sha256=m-b6Mju5gFkpSHh-lyJ4iwqf_8t4LjYYFRumtutQSZc,5578
importlib_metadata/docs/index.rst,sha256=rbXrDkLAKLIDccqME5u9CCMEfMKprqzQOkIOuwOnfz4,1907
importlib_metadata/docs/using.rst,sha256=k_L4Hwwsf10ap9xWejyC-_gLz_WtvRfDOzuJA3o7Zw0,9504
importlib_metadata/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
importlib_metadata/tests/fixtures.py,sha256=Ua_PqyqBhFqkkNGFsXtgMah6vXKQjeqKo1KhhzYdn-w,5752
importlib_metadata/tests/test_api.py,sha256=YMAGTsRENrtvpw2CSLmRndJMBeT4q_M0GSe-QsnnMZ4,5544
importlib_metadata/tests/test_integration.py,sha256=ykJpwjSkVwvWHG4gUw4RUrZzU_7JKX8vZyPf_kFIrLE,1579
importlib_metadata/tests/test_main.py,sha256=dcsDqyxTRtard2j5ysDDvVwfK6vvXdRtZCaQ0QljSR8,9026
importlib_metadata/tests/test_zip.py,sha256=lOCNPyfJSm9nz0-2RQndM7OQV-_gRjJzyRnvMqXqRSI,2675
importlib_metadata/tests/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
importlib_metadata/tests/data/example-21.12-py3-none-any.whl,sha256=I-kYufETid-tDYyR8f1OFJ3t5u_Io23k0cbQxJTUN4I,1455
importlib_metadata/tests/data/example-21.12-py3.6.egg,sha256=-EeugFAijkdUO9xyQHTZkQwZoFXK0_QxICBj6R5AAJo,1497
importlib_metadata-1.7.0.dist-info/LICENSE,sha256=wNe6dAchmJ1VvVB8D9oTc-gHHadCuaSBAev36sYEM6U,571
importlib_metadata-1.7.0.dist-info/METADATA,sha256=AvM2AcUhNbF_2Yyo8ttyVBCh_qGbRHaRE3MVgrHYDVw,2144
importlib_metadata-1.7.0.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110
importlib_metadata-1.7.0.dist-info/top_level.txt,sha256=CO3fD9yylANiXkrMo4qHLV_mqXL2sC5JFKgt1yWAT-A,19
importlib_metadata-1.7.0.dist-info/RECORD,,

Просмотреть файл

@ -1,10 +1,10 @@
Metadata-Version: 2.1 Metadata-Version: 2.1
Name: importlib-metadata Name: importlib-metadata
Version: 1.7.0 Version: 2.1.1
Summary: Read metadata from Python packages Summary: Read metadata from Python packages
Home-page: http://importlib-metadata.readthedocs.io/ Home-page: http://importlib-metadata.readthedocs.io/
Author: Barry Warsaw Author: Jason R. Coombs
Author-email: barry@python.org Author-email: jaraco@jaraco.com
License: Apache Software License License: Apache Software License
Platform: UNKNOWN Platform: UNKNOWN
Classifier: Development Status :: 3 - Alpha Classifier: Development Status :: 3 - Alpha
@ -24,14 +24,21 @@ Requires-Dist: rst.linker ; extra == 'docs'
Provides-Extra: testing Provides-Extra: testing
Requires-Dist: packaging ; extra == 'testing' Requires-Dist: packaging ; extra == 'testing'
Requires-Dist: pep517 ; extra == 'testing' Requires-Dist: pep517 ; extra == 'testing'
Requires-Dist: unittest2 ; (python_version < "3") and extra == 'testing'
Requires-Dist: importlib-resources (>=1.3) ; (python_version < "3.9") and extra == 'testing' Requires-Dist: importlib-resources (>=1.3) ; (python_version < "3.9") and extra == 'testing'
========================= =========================
``importlib_metadata`` ``importlib_metadata``
========================= =========================
``importlib_metadata`` is a library to access the metadata for a Python ``importlib_metadata`` is a library to access the metadata for a
package. It is intended to be ported to Python 3.8. Python package.
As of Python 3.8, this functionality has been added to the
`Python standard library
<https://docs.python.org/3/library/importlib.metadata.html>`_.
This package supplies backports of that functionality including
improvements added to subsequent Python versions.
Usage Usage
@ -58,9 +65,9 @@ tools (or other conforming packages). It does not support:
Project details Project details
=============== ===============
* Project home: https://gitlab.com/python-devs/importlib_metadata * Project home: https://github.com/python/importlib_metadata
* Report bugs at: https://gitlab.com/python-devs/importlib_metadata/issues * Report bugs at: https://github.com/python/importlib_metadata/issues
* Code hosting: https://gitlab.com/python-devs/importlib_metadata.git * Code hosting: https://github.com/python/importlib_metadata
* Documentation: http://importlib_metadata.readthedocs.io/ * Documentation: https://importlib_metadata.readthedocs.io/

Просмотреть файл

@ -0,0 +1,7 @@
importlib_metadata/__init__.py,sha256=uaN7KDLs3-irvgwsxg4VZIuY3ZEo3jhu1dShjE7fR88,19587
importlib_metadata/_compat.py,sha256=DnM55BbJKFCcZmJOkArmyO76-0g7pA6HEfzSYWXN88k,4417
importlib_metadata-2.1.1.dist-info/LICENSE,sha256=wNe6dAchmJ1VvVB8D9oTc-gHHadCuaSBAev36sYEM6U,571
importlib_metadata-2.1.1.dist-info/METADATA,sha256=gBf5nX-Ff6_Ue9dSH4dkWg2FCNHHtQrs6mhunTAac8k,2421
importlib_metadata-2.1.1.dist-info/WHEEL,sha256=ADKeyaGyKF5DwBNE0sRE5pvW-bSkFMJfBuhzZ3rceP4,110
importlib_metadata-2.1.1.dist-info/top_level.txt,sha256=CO3fD9yylANiXkrMo4qHLV_mqXL2sC5JFKgt1yWAT-A,19
importlib_metadata-2.1.1.dist-info/RECORD,,

Просмотреть файл

@ -462,43 +462,67 @@ class FastPath:
for child in names for child in names
) )
def is_egg(self, search):
base = self.base
return (
base == search.versionless_egg_name
or base.startswith(search.prefix)
and base.endswith('.egg'))
def search(self, name): def search(self, name):
for child in self.children(): return (
n_low = child.lower() self.joinpath(child)
if (n_low in name.exact_matches for child in self.children()
or n_low.startswith(name.prefix) if name.matches(child, self.base)
and n_low.endswith(name.suffixes) )
# legacy case:
or self.is_egg(name) and n_low == 'egg-info'):
yield self.joinpath(child)
class Prepared: class Prepared:
""" """
A prepared search for metadata on a possibly-named package. A prepared search for metadata on a possibly-named package.
""" """
normalized = '' normalized = None
prefix = ''
suffixes = '.dist-info', '.egg-info' suffixes = '.dist-info', '.egg-info'
exact_matches = [''][:0] exact_matches = [''][:0]
versionless_egg_name = ''
def __init__(self, name): def __init__(self, name):
self.name = name self.name = name
if name is None: if name is None:
return return
self.normalized = name.lower().replace('-', '_') self.normalized = self.normalize(name)
self.prefix = self.normalized + '-'
self.exact_matches = [ self.exact_matches = [
self.normalized + suffix for suffix in self.suffixes] self.normalized + suffix for suffix in self.suffixes]
self.versionless_egg_name = self.normalized + '.egg'
@staticmethod
def normalize(name):
"""
PEP 503 normalization plus dashes as underscores.
"""
return re.sub(r"[-_.]+", "-", name).lower().replace('-', '_')
@staticmethod
def legacy_normalize(name):
"""
Normalize the package name as found in the convention in
older packaging tools versions and specs.
"""
return name.lower().replace('-', '_')
def matches(self, cand, base):
low = cand.lower()
pre, ext = os.path.splitext(low)
name, sep, rest = pre.partition('-')
return (
low in self.exact_matches
or ext in self.suffixes and (
not self.normalized or
name.replace('.', '_') == self.normalized
)
# legacy case:
or self.is_egg(base) and low == 'egg-info'
)
def is_egg(self, base):
normalized = self.legacy_normalize(self.name or '')
prefix = normalized + '-' if normalized else ''
versionless_egg_name = normalized + '.egg' if self.name else ''
return (
base == versionless_egg_name
or base.startswith(prefix)
and base.endswith('.egg'))
@install @install
@ -618,6 +642,3 @@ def requires(distribution_name):
packaging.requirement.Requirement. packaging.requirement.Requirement.
""" """
return distribution(distribution_name).requires return distribution(distribution_name).requires
__version__ = version(__name__)

Просмотреть файл

@ -0,0 +1,13 @@
Copyright 2017-2019 Jason R. Coombs, Barry Warsaw
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Просмотреть файл

@ -0,0 +1,94 @@
Metadata-Version: 2.1
Name: importlib-metadata
Version: 3.1.1
Summary: Read metadata from Python packages
Home-page: https://github.com/python/importlib_metadata
Author: Jason R. Coombs
Author-email: jaraco@jaraco.com
License: UNKNOWN
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Requires-Python: >=3.6
Requires-Dist: zipp (>=0.5)
Provides-Extra: docs
Requires-Dist: sphinx ; extra == 'docs'
Requires-Dist: jaraco.packaging (>=3.2) ; extra == 'docs'
Requires-Dist: rst.linker (>=1.9) ; extra == 'docs'
Provides-Extra: testing
Requires-Dist: pytest (!=3.7.3,>=3.5) ; extra == 'testing'
Requires-Dist: pytest-checkdocs (>=1.2.3) ; extra == 'testing'
Requires-Dist: pytest-flake8 ; extra == 'testing'
Requires-Dist: pytest-cov ; extra == 'testing'
Requires-Dist: jaraco.test (>=3.2.0) ; extra == 'testing'
Requires-Dist: packaging ; extra == 'testing'
Requires-Dist: pep517 ; extra == 'testing'
Requires-Dist: pyfakefs ; extra == 'testing'
Requires-Dist: flufl.flake8 ; extra == 'testing'
Requires-Dist: pytest-black (>=0.3.7) ; (platform_python_implementation != "PyPy") and extra == 'testing'
Requires-Dist: pytest-mypy ; (platform_python_implementation != "PyPy") and extra == 'testing'
Requires-Dist: importlib-resources (>=1.3) ; (python_version < "3.9") and extra == 'testing'
.. image:: https://img.shields.io/pypi/v/importlib_metadata.svg
:target: `PyPI link`_
.. image:: https://img.shields.io/pypi/pyversions/importlib_metadata.svg
:target: `PyPI link`_
.. _PyPI link: https://pypi.org/project/importlib_metadata
.. image:: https://github.com/python/importlib_metadata/workflows/Automated%20Tests/badge.svg
:target: https://github.com/python/importlib_metadata/actions?query=workflow%3A%22Automated+Tests%22
:alt: Automated Tests
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/psf/black
:alt: Code style: Black
.. image:: https://readthedocs.org/projects/importlib-metadata/badge/?version=latest
:target: https://importlib-metadata.readthedocs.io/en/latest/?badge=latest
``importlib_metadata`` is a library to access the metadata for a
Python package.
As of Python 3.8, this functionality has been added to the
`Python standard library
<https://docs.python.org/3/library/importlib.metadata.html>`_.
This package supplies backports of that functionality including
improvements added to subsequent Python versions.
Usage
=====
See the `online documentation <https://importlib_metadata.readthedocs.io/>`_
for usage details.
`Finder authors
<https://docs.python.org/3/reference/import.html#finders-and-loaders>`_ can
also add support for custom package installers. See the above documentation
for details.
Caveats
=======
This project primarily supports third-party packages installed by PyPA
tools (or other conforming packages). It does not support:
- Packages in the stdlib.
- Packages installed without metadata.
Project details
===============
* Project home: https://github.com/python/importlib_metadata
* Report bugs at: https://github.com/python/importlib_metadata/issues
* Code hosting: https://github.com/python/importlib_metadata
* Documentation: https://importlib_metadata.readthedocs.io/

Просмотреть файл

@ -0,0 +1,7 @@
importlib_metadata/__init__.py,sha256=QM4Oo096u6JYeokkDUwHgazI_h3o0w9tISPjHtVko_U,19266
importlib_metadata/_compat.py,sha256=OS4joET_vaQClxhumw0NWYdS5N3FX1Ii895aZXLpQaA,2028
importlib_metadata-3.1.1.dist-info/LICENSE,sha256=wNe6dAchmJ1VvVB8D9oTc-gHHadCuaSBAev36sYEM6U,571
importlib_metadata-3.1.1.dist-info/METADATA,sha256=rdblRVlpAdjDcYkqWhn2yVNwrpBqpamdKvxrgA6EWE0,3442
importlib_metadata-3.1.1.dist-info/WHEEL,sha256=gm79cMopkncyn0iSnI0vQNiDJ8t9on0H4_iz-CrpXMk,92
importlib_metadata-3.1.1.dist-info/top_level.txt,sha256=CO3fD9yylANiXkrMo4qHLV_mqXL2sC5JFKgt1yWAT-A,19
importlib_metadata-3.1.1.dist-info/RECORD,,

Просмотреть файл

@ -1,5 +1,5 @@
Wheel-Version: 1.0 Wheel-Version: 1.0
Generator: bdist_wheel (0.34.2) Generator: bdist_wheel (0.36.0)
Root-Is-Purelib: true Root-Is-Purelib: true
Tag: py3-none-any Tag: py3-none-any

Просмотреть файл

@ -0,0 +1 @@
importlib_metadata

Просмотреть файл

@ -0,0 +1,631 @@
import io
import os
import re
import abc
import csv
import sys
import zipp
import email
import pathlib
import operator
import functools
import itertools
import posixpath
import collections
from ._compat import (
NullFinder,
PyPy_repr,
install,
)
from configparser import ConfigParser
from contextlib import suppress
from importlib import import_module
from importlib.abc import MetaPathFinder
from itertools import starmap
__all__ = [
'Distribution',
'DistributionFinder',
'PackageNotFoundError',
'distribution',
'distributions',
'entry_points',
'files',
'metadata',
'requires',
'version',
]
class PackageNotFoundError(ModuleNotFoundError):
"""The package was not found."""
def __str__(self):
tmpl = "No package metadata was found for {self.name}"
return tmpl.format(**locals())
@property
def name(self):
(name,) = self.args
return name
class EntryPoint(
PyPy_repr, collections.namedtuple('EntryPointBase', 'name value group')
):
"""An entry point as defined by Python packaging conventions.
See `the packaging docs on entry points
<https://packaging.python.org/specifications/entry-points/>`_
for more information.
"""
pattern = re.compile(
r'(?P<module>[\w.]+)\s*'
r'(:\s*(?P<attr>[\w.]+))?\s*'
r'(?P<extras>\[.*\])?\s*$'
)
"""
A regular expression describing the syntax for an entry point,
which might look like:
- module
- package.module
- package.module:attribute
- package.module:object.attribute
- package.module:attr [extra1, extra2]
Other combinations are possible as well.
The expression is lenient about whitespace around the ':',
following the attr, and following any extras.
"""
def load(self):
"""Load the entry point from its definition. If only a module
is indicated by the value, return that module. Otherwise,
return the named object.
"""
match = self.pattern.match(self.value)
module = import_module(match.group('module'))
attrs = filter(None, (match.group('attr') or '').split('.'))
return functools.reduce(getattr, attrs, module)
@property
def module(self):
match = self.pattern.match(self.value)
return match.group('module')
@property
def attr(self):
match = self.pattern.match(self.value)
return match.group('attr')
@property
def extras(self):
match = self.pattern.match(self.value)
return list(re.finditer(r'\w+', match.group('extras') or ''))
@classmethod
def _from_config(cls, config):
return [
cls(name, value, group)
for group in config.sections()
for name, value in config.items(group)
]
@classmethod
def _from_text(cls, text):
config = ConfigParser(delimiters='=')
# case sensitive: https://stackoverflow.com/q/1611799/812183
config.optionxform = str
try:
config.read_string(text)
except AttributeError: # pragma: nocover
# Python 2 has no read_string
config.readfp(io.StringIO(text))
return EntryPoint._from_config(config)
def __iter__(self):
"""
Supply iter so one may construct dicts of EntryPoints easily.
"""
return iter((self.name, self))
def __reduce__(self):
return (
self.__class__,
(self.name, self.value, self.group),
)
class PackagePath(pathlib.PurePosixPath):
"""A reference to a path in a package"""
def read_text(self, encoding='utf-8'):
with self.locate().open(encoding=encoding) as stream:
return stream.read()
def read_binary(self):
with self.locate().open('rb') as stream:
return stream.read()
def locate(self):
"""Return a path-like object for this path"""
return self.dist.locate_file(self)
class FileHash:
def __init__(self, spec):
self.mode, _, self.value = spec.partition('=')
def __repr__(self):
return '<FileHash mode: {} value: {}>'.format(self.mode, self.value)
class Distribution:
"""A Python distribution package."""
@abc.abstractmethod
def read_text(self, filename):
"""Attempt to load metadata file given by the name.
:param filename: The name of the file in the distribution info.
:return: The text if found, otherwise None.
"""
@abc.abstractmethod
def locate_file(self, path):
"""
Given a path to a file in this distribution, return a path
to it.
"""
@classmethod
def from_name(cls, name):
"""Return the Distribution for the given package name.
:param name: The name of the distribution package to search for.
:return: The Distribution instance (or subclass thereof) for the named
package, if found.
:raises PackageNotFoundError: When the named package's distribution
metadata cannot be found.
"""
for resolver in cls._discover_resolvers():
dists = resolver(DistributionFinder.Context(name=name))
dist = next(iter(dists), None)
if dist is not None:
return dist
else:
raise PackageNotFoundError(name)
@classmethod
def discover(cls, **kwargs):
"""Return an iterable of Distribution objects for all packages.
Pass a ``context`` or pass keyword arguments for constructing
a context.
:context: A ``DistributionFinder.Context`` object.
:return: Iterable of Distribution objects for all packages.
"""
context = kwargs.pop('context', None)
if context and kwargs:
raise ValueError("cannot accept context and kwargs")
context = context or DistributionFinder.Context(**kwargs)
return itertools.chain.from_iterable(
resolver(context) for resolver in cls._discover_resolvers()
)
@staticmethod
def at(path):
"""Return a Distribution for the indicated metadata path
:param path: a string or path-like object
:return: a concrete Distribution instance for the path
"""
return PathDistribution(pathlib.Path(path))
@staticmethod
def _discover_resolvers():
"""Search the meta_path for resolvers."""
declared = (
getattr(finder, 'find_distributions', None) for finder in sys.meta_path
)
return filter(None, declared)
@classmethod
def _local(cls, root='.'):
from pep517 import build, meta
system = build.compat_system(root)
builder = functools.partial(
meta.build,
source_dir=root,
system=system,
)
return PathDistribution(zipp.Path(meta.build_as_zip(builder)))
@property
def metadata(self):
"""Return the parsed metadata for this Distribution.
The returned object will have keys that name the various bits of
metadata. See PEP 566 for details.
"""
text = (
self.read_text('METADATA')
or self.read_text('PKG-INFO')
# This last clause is here to support old egg-info files. Its
# effect is to just end up using the PathDistribution's self._path
# (which points to the egg-info file) attribute unchanged.
or self.read_text('')
)
return email.message_from_string(text)
@property
def version(self):
"""Return the 'Version' metadata for the distribution package."""
return self.metadata['Version']
@property
def entry_points(self):
return EntryPoint._from_text(self.read_text('entry_points.txt'))
@property
def files(self):
"""Files in this distribution.
:return: List of PackagePath for this distribution or None
Result is `None` if the metadata file that enumerates files
(i.e. RECORD for dist-info or SOURCES.txt for egg-info) is
missing.
Result may be empty if the metadata exists but is empty.
"""
file_lines = self._read_files_distinfo() or self._read_files_egginfo()
def make_file(name, hash=None, size_str=None):
result = PackagePath(name)
result.hash = FileHash(hash) if hash else None
result.size = int(size_str) if size_str else None
result.dist = self
return result
return file_lines and list(starmap(make_file, csv.reader(file_lines)))
def _read_files_distinfo(self):
"""
Read the lines of RECORD
"""
text = self.read_text('RECORD')
return text and text.splitlines()
def _read_files_egginfo(self):
"""
SOURCES.txt might contain literal commas, so wrap each line
in quotes.
"""
text = self.read_text('SOURCES.txt')
return text and map('"{}"'.format, text.splitlines())
@property
def requires(self):
"""Generated requirements specified for this Distribution"""
reqs = self._read_dist_info_reqs() or self._read_egg_info_reqs()
return reqs and list(reqs)
def _read_dist_info_reqs(self):
return self.metadata.get_all('Requires-Dist')
def _read_egg_info_reqs(self):
source = self.read_text('requires.txt')
return source and self._deps_from_requires_text(source)
@classmethod
def _deps_from_requires_text(cls, source):
section_pairs = cls._read_sections(source.splitlines())
sections = {
section: list(map(operator.itemgetter('line'), results))
for section, results in itertools.groupby(
section_pairs, operator.itemgetter('section')
)
}
return cls._convert_egg_info_reqs_to_simple_reqs(sections)
@staticmethod
def _read_sections(lines):
section = None
for line in filter(None, lines):
section_match = re.match(r'\[(.*)\]$', line)
if section_match:
section = section_match.group(1)
continue
yield locals()
@staticmethod
def _convert_egg_info_reqs_to_simple_reqs(sections):
"""
Historically, setuptools would solicit and store 'extra'
requirements, including those with environment markers,
in separate sections. More modern tools expect each
dependency to be defined separately, with any relevant
extras and environment markers attached directly to that
requirement. This method converts the former to the
latter. See _test_deps_from_requires_text for an example.
"""
def make_condition(name):
return name and 'extra == "{name}"'.format(name=name)
def parse_condition(section):
section = section or ''
extra, sep, markers = section.partition(':')
if extra and markers:
markers = '({markers})'.format(markers=markers)
conditions = list(filter(None, [markers, make_condition(extra)]))
return '; ' + ' and '.join(conditions) if conditions else ''
for section, deps in sections.items():
for dep in deps:
yield dep + parse_condition(section)
class DistributionFinder(MetaPathFinder):
"""
A MetaPathFinder capable of discovering installed distributions.
"""
class Context:
"""
Keyword arguments presented by the caller to
``distributions()`` or ``Distribution.discover()``
to narrow the scope of a search for distributions
in all DistributionFinders.
Each DistributionFinder may expect any parameters
and should attempt to honor the canonical
parameters defined below when appropriate.
"""
name = None
"""
Specific name for which a distribution finder should match.
A name of ``None`` matches all distributions.
"""
def __init__(self, **kwargs):
vars(self).update(kwargs)
@property
def path(self):
"""
The path that a distribution finder should search.
Typically refers to Python package paths and defaults
to ``sys.path``.
"""
return vars(self).get('path', sys.path)
@abc.abstractmethod
def find_distributions(self, context=Context()):
"""
Find distributions.
Return an iterable of all Distribution instances capable of
loading the metadata for packages matching the ``context``,
a DistributionFinder.Context instance.
"""
class FastPath:
"""
Micro-optimized class for searching a path for
children.
"""
def __init__(self, root):
self.root = str(root)
self.base = os.path.basename(self.root).lower()
def joinpath(self, child):
return pathlib.Path(self.root, child)
def children(self):
with suppress(Exception):
return os.listdir(self.root or '')
with suppress(Exception):
return self.zip_children()
return []
def zip_children(self):
zip_path = zipp.Path(self.root)
names = zip_path.root.namelist()
self.joinpath = zip_path.joinpath
return dict.fromkeys(child.split(posixpath.sep, 1)[0] for child in names)
def search(self, name):
return (
self.joinpath(child)
for child in self.children()
if name.matches(child, self.base)
)
class Prepared:
"""
A prepared search for metadata on a possibly-named package.
"""
normalized = None
suffixes = '.dist-info', '.egg-info'
exact_matches = [''][:0]
def __init__(self, name):
self.name = name
if name is None:
return
self.normalized = self.normalize(name)
self.exact_matches = [self.normalized + suffix for suffix in self.suffixes]
@staticmethod
def normalize(name):
"""
PEP 503 normalization plus dashes as underscores.
"""
return re.sub(r"[-_.]+", "-", name).lower().replace('-', '_')
@staticmethod
def legacy_normalize(name):
"""
Normalize the package name as found in the convention in
older packaging tools versions and specs.
"""
return name.lower().replace('-', '_')
def matches(self, cand, base):
low = cand.lower()
pre, ext = os.path.splitext(low)
name, sep, rest = pre.partition('-')
return (
low in self.exact_matches
or ext in self.suffixes
and (not self.normalized or name.replace('.', '_') == self.normalized)
# legacy case:
or self.is_egg(base)
and low == 'egg-info'
)
def is_egg(self, base):
normalized = self.legacy_normalize(self.name or '')
prefix = normalized + '-' if normalized else ''
versionless_egg_name = normalized + '.egg' if self.name else ''
return (
base == versionless_egg_name
or base.startswith(prefix)
and base.endswith('.egg')
)
@install
class MetadataPathFinder(NullFinder, DistributionFinder):
"""A degenerate finder for distribution packages on the file system.
This finder supplies only a find_distributions() method for versions
of Python that do not have a PathFinder find_distributions().
"""
def find_distributions(self, context=DistributionFinder.Context()):
"""
Find distributions.
Return an iterable of all Distribution instances capable of
loading the metadata for packages matching ``context.name``
(or all names if ``None`` indicated) along the paths in the list
of directories ``context.path``.
"""
found = self._search_paths(context.name, context.path)
return map(PathDistribution, found)
@classmethod
def _search_paths(cls, name, paths):
"""Find metadata directories in paths heuristically."""
return itertools.chain.from_iterable(
path.search(Prepared(name)) for path in map(FastPath, paths)
)
class PathDistribution(Distribution):
def __init__(self, path):
"""Construct a distribution from a path to the metadata directory.
:param path: A pathlib.Path or similar object supporting
.joinpath(), __div__, .parent, and .read_text().
"""
self._path = path
def read_text(self, filename):
with suppress(
FileNotFoundError,
IsADirectoryError,
KeyError,
NotADirectoryError,
PermissionError,
):
return self._path.joinpath(filename).read_text(encoding='utf-8')
read_text.__doc__ = Distribution.read_text.__doc__
def locate_file(self, path):
return self._path.parent / path
def distribution(distribution_name):
"""Get the ``Distribution`` instance for the named package.
:param distribution_name: The name of the distribution package as a string.
:return: A ``Distribution`` instance (or subclass thereof).
"""
return Distribution.from_name(distribution_name)
def distributions(**kwargs):
"""Get all ``Distribution`` instances in the current environment.
:return: An iterable of ``Distribution`` instances.
"""
return Distribution.discover(**kwargs)
def metadata(distribution_name):
"""Get the metadata for the named package.
:param distribution_name: The name of the distribution package to query.
:return: An email.Message containing the parsed metadata.
"""
return Distribution.from_name(distribution_name).metadata
def version(distribution_name):
"""Get the version string for the named package.
:param distribution_name: The name of the distribution package to query.
:return: The version string for the package as defined in the package's
"Version" metadata key.
"""
return distribution(distribution_name).version
def entry_points():
"""Return EntryPoint objects for all installed packages.
:return: EntryPoint objects for all installed packages.
"""
eps = itertools.chain.from_iterable(dist.entry_points for dist in distributions())
by_group = operator.attrgetter('group')
ordered = sorted(eps, key=by_group)
grouped = itertools.groupby(ordered, by_group)
return {group: tuple(eps) for group, eps in grouped}
def files(distribution_name):
"""Return a list of files for the named package.
:param distribution_name: The name of the distribution package to query.
:return: List of files composing the distribution.
"""
return distribution(distribution_name).files
def requires(distribution_name):
"""
Return a list of requirements for the named package.
:return: An iterator of requirements, suitable for
packaging.requirement.Requirement.
"""
return distribution(distribution_name).requires

Просмотреть файл

@ -0,0 +1,75 @@
import sys
__all__ = ['install', 'NullFinder', 'PyPy_repr']
def install(cls):
"""
Class decorator for installation on sys.meta_path.
Adds the backport DistributionFinder to sys.meta_path and
attempts to disable the finder functionality of the stdlib
DistributionFinder.
"""
sys.meta_path.append(cls())
disable_stdlib_finder()
return cls
def disable_stdlib_finder():
"""
Give the backport primacy for discovering path-based distributions
by monkey-patching the stdlib O_O.
See #91 for more background for rationale on this sketchy
behavior.
"""
def matches(finder):
return getattr(
finder, '__module__', None
) == '_frozen_importlib_external' and hasattr(finder, 'find_distributions')
for finder in filter(matches, sys.meta_path): # pragma: nocover
del finder.find_distributions
class NullFinder:
"""
A "Finder" (aka "MetaClassFinder") that never finds any modules,
but may find distributions.
"""
@staticmethod
def find_spec(*args, **kwargs):
return None
# In Python 2, the import system requires finders
# to have a find_module() method, but this usage
# is deprecated in Python 3 in favor of find_spec().
# For the purposes of this finder (i.e. being present
# on sys.meta_path but having no other import
# system functionality), the two methods are identical.
find_module = find_spec
class PyPy_repr:
"""
Override repr for EntryPoint objects on PyPy to avoid __iter__ access.
Ref #97, #102.
"""
affected = hasattr(sys, 'pypy_version_info')
def __compat_repr__(self): # pragma: nocover
def make_param(name):
value = getattr(self, name)
return '{name}={value!r}'.format(**locals())
params = ', '.join(map(make_param, self._fields))
return 'EntryPoint({params})'.format(**locals())
if affected: # pragma: nocover
__repr__ = __compat_repr__
del affected

Просмотреть файл

@ -1,41 +0,0 @@
from . import abc
from ._compat import Path, ZipPath
class FileReader(abc.TraversableResources):
def __init__(self, loader):
self.path = Path(loader.path).parent
def resource_path(self, resource):
"""
Return the file system path to prevent
`resources.path()` from creating a temporary
copy.
"""
return str(self.path.joinpath(resource))
def files(self):
return self.path
class ZipReader(abc.TraversableResources):
def __init__(self, loader, module):
_, _, name = module.rpartition('.')
prefix = loader.prefix.replace('\\', '/') + name + '/'
self.path = ZipPath(loader.archive, prefix)
def open_resource(self, resource):
try:
return super().open_resource(resource)
except KeyError as exc:
raise FileNotFoundError(exc.args[0])
def is_resource(self, path):
# workaround for `zipfile.Path.is_file` returning true
# for non-existent paths.
target = self.files().joinpath(path)
return target.is_file() and target.exists()
def files(self):
return self.path

Просмотреть файл

@ -1,11 +1,12 @@
Metadata-Version: 2.1 Metadata-Version: 2.1
Name: importlib-resources Name: importlib-resources
Version: 3.0.0 Version: 3.2.1
Summary: Read resources from Python packages Summary: Read resources from Python packages
Home-page: http://importlib-resources.readthedocs.io/ Home-page: https://github.com/python/importlib_resources
Author: Barry Warsaw Author: Barry Warsaw
Author-email: barry@python.org Author-email: barry@python.org
License: UNKNOWN License: UNKNOWN
Project-URL: Documentation, https://importlib-resources.readthedocs.io/
Platform: UNKNOWN Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Developers
@ -24,10 +25,6 @@ Requires-Dist: sphinx ; extra == 'docs'
Requires-Dist: rst.linker ; extra == 'docs' Requires-Dist: rst.linker ; extra == 'docs'
Requires-Dist: jaraco.packaging ; extra == 'docs' Requires-Dist: jaraco.packaging ; extra == 'docs'
=========================
``importlib_resources``
=========================
``importlib_resources`` is a backport of Python standard library ``importlib_resources`` is a backport of Python standard library
`importlib.resources `importlib.resources
<https://docs.python.org/3.9/library/importlib.html#module-importlib.resources>`_ <https://docs.python.org/3.9/library/importlib.html#module-importlib.resources>`_
@ -42,12 +39,3 @@ reading resources included in packages easier, with more stable and consistent
semantics. semantics.
Project details
===============
* Project home: https://gitlab.com/python-devs/importlib_resources
* Report bugs at: https://gitlab.com/python-devs/importlib_resources/issues
* Code hosting: https://gitlab.com/python-devs/importlib_resources.git
* Documentation: https://importlib-resources.readthedocs.io/

Просмотреть файл

@ -1,19 +1,22 @@
importlib_resources/__init__.py,sha256=hswDmLAH0IUlLWwmdHXPN2mgus2bk5IwDP-BFzg7VKo,977 importlib_resources/__init__.py,sha256=hswDmLAH0IUlLWwmdHXPN2mgus2bk5IwDP-BFzg7VKo,977
importlib_resources/_common.py,sha256=jXVqgKZ1bt8IbZiErvjIeb69BjqsMSCSt9AwV4bHnE8,3157 importlib_resources/_common.py,sha256=RN8cXOZtlygvlbyTewd-ni9wC1hwXpfbZnrl7kbx0nI,3121
importlib_resources/_compat.py,sha256=5nvS1tAZIl_6VqrFSScNVW2wtBGaRXGxcpDXMskruoA,3233 importlib_resources/_compat.py,sha256=NDCXOf1097aDJJx-_pQ0UIktzVx2G1aPIQTRFGx0FHI,3694
importlib_resources/_py2.py,sha256=G9M5mv1ILl8NARGdNX0v9_F_Hb4HUKCS-FCNK63Ajvw,4146 importlib_resources/_py2.py,sha256=G9M5mv1ILl8NARGdNX0v9_F_Hb4HUKCS-FCNK63Ajvw,4146
importlib_resources/_py3.py,sha256=2wJYfjLG8nd9mT1HLBtX96m6zlu9-Tocte9wFl9q_bY,5474 importlib_resources/_py3.py,sha256=5_FhUUHWFG1c3HcLrmDy65ZFB7EYxmHfOV3ybv4uTHM,5710
importlib_resources/abc.py,sha256=6PX4Nprv39YnAht3NymhHIuSso0ocAKqDJZf-A6BgIw,3894 importlib_resources/abc.py,sha256=6PX4Nprv39YnAht3NymhHIuSso0ocAKqDJZf-A6BgIw,3894
importlib_resources/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 importlib_resources/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
importlib_resources/readers.py,sha256=S0DsGQB1li6w5USiZQtiy-5HXe4UAxt-zmKo8QlAxsI,1155 importlib_resources/readers.py,sha256=fGuSBoMeeERUVrscN9Grhp0s-wKMy7nMVbCx92vIlGs,3674
importlib_resources/trees.py,sha256=U3FlQSI5--eF4AdzOjBvW4xnjL21OFX8ivk82Quwv_M,117 importlib_resources/trees.py,sha256=U3FlQSI5--eF4AdzOjBvW4xnjL21OFX8ivk82Quwv_M,117
importlib_resources/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 importlib_resources/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
importlib_resources/tests/_compat.py,sha256=geKWJe8UGXjC181JxmtxR3A_o5VrR4yxolS0xbnxMlw,801
importlib_resources/tests/py27compat.py,sha256=9lDJkGV2swPVQJg6isOorRNFWuP6KeoWd4D2bFNmzLI,965
importlib_resources/tests/test_files.py,sha256=91rf4C74_aJsKNSt-a-03slVpY9QSAuCbogFWnsaPjE,1017 importlib_resources/tests/test_files.py,sha256=91rf4C74_aJsKNSt-a-03slVpY9QSAuCbogFWnsaPjE,1017
importlib_resources/tests/test_open.py,sha256=yDXmTGXQspByj6WU0prnoVwab1yWWEA3fwz_XIx7TQU,2288 importlib_resources/tests/test_open.py,sha256=pIYWvuTDpQOJKX0SEuOKGotssZcEeY_xNPDqLGCvP_U,2565
importlib_resources/tests/test_path.py,sha256=GnUOu-338o9offnC8xwbXjH9JIQJpD7JujgQkGB106Q,1548 importlib_resources/tests/test_path.py,sha256=GnUOu-338o9offnC8xwbXjH9JIQJpD7JujgQkGB106Q,1548
importlib_resources/tests/test_read.py,sha256=DpA7tzxSQlU0_YQuWibB3E5PDL9fQUdzeKoEUGnAx78,2046 importlib_resources/tests/test_read.py,sha256=DpA7tzxSQlU0_YQuWibB3E5PDL9fQUdzeKoEUGnAx78,2046
importlib_resources/tests/test_resource.py,sha256=X77DzU2BRoM6d59iEh74zDHHw3pKOBGLCg3lP3dH4BI,6467 importlib_resources/tests/test_reader.py,sha256=yEO0xyrYDcGRmsBC6A1n99GXiTZpVvp-uGA313s6aao,4638
importlib_resources/tests/util.py,sha256=f0RZU-RkEkybJjXRd7C5HcWMsoLFRWJL4FIUF1CJ2wo,6980 importlib_resources/tests/test_resource.py,sha256=GbrMeHJ74N6KJG38TDodCp--nsRnFHXJc7NrAEqUPaU,8766
importlib_resources/tests/util.py,sha256=8hBFwqIZRJFNvkboEB7aWsCqTtgUjlWI_iQ0KV158Yk,5914
importlib_resources/tests/data01/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 importlib_resources/tests/data01/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
importlib_resources/tests/data01/binary.file,sha256=BU7ewdAhH2JP7Qy8qdT5QAsOSRxDdCryxbCr6_DJkNg,4 importlib_resources/tests/data01/binary.file,sha256=BU7ewdAhH2JP7Qy8qdT5QAsOSRxDdCryxbCr6_DJkNg,4
importlib_resources/tests/data01/utf-16.file,sha256=t5q9qhxX0rYqItBOM8D3ylwG-RHrnOYteTLtQr6sF7g,44 importlib_resources/tests/data01/utf-16.file,sha256=t5q9qhxX0rYqItBOM8D3ylwG-RHrnOYteTLtQr6sF7g,44
@ -25,16 +28,15 @@ importlib_resources/tests/data02/one/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeu
importlib_resources/tests/data02/one/resource1.txt,sha256=10flKac7c-XXFzJ3t-AB5MJjlBy__dSZvPE_dOm2q6U,13 importlib_resources/tests/data02/one/resource1.txt,sha256=10flKac7c-XXFzJ3t-AB5MJjlBy__dSZvPE_dOm2q6U,13
importlib_resources/tests/data02/two/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 importlib_resources/tests/data02/two/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
importlib_resources/tests/data02/two/resource2.txt,sha256=lt2jbN3TMn9QiFKM832X39bU_62UptDdUkoYzkvEbl0,13 importlib_resources/tests/data02/two/resource2.txt,sha256=lt2jbN3TMn9QiFKM832X39bU_62UptDdUkoYzkvEbl0,13
importlib_resources/tests/data03/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 importlib_resources/tests/namespacedata01/binary.file,sha256=BU7ewdAhH2JP7Qy8qdT5QAsOSRxDdCryxbCr6_DJkNg,4
importlib_resources/tests/data03/namespace/resource1.txt,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 importlib_resources/tests/namespacedata01/utf-16.file,sha256=t5q9qhxX0rYqItBOM8D3ylwG-RHrnOYteTLtQr6sF7g,44
importlib_resources/tests/data03/namespace/portion1/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 importlib_resources/tests/namespacedata01/utf-8.file,sha256=kwWgYG4yQ-ZF2X_WA66EjYPmxJRn-w8aSOiS9e8tKYY,20
importlib_resources/tests/data03/namespace/portion2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
importlib_resources/tests/zipdata01/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 importlib_resources/tests/zipdata01/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
importlib_resources/tests/zipdata01/ziptestdata.zip,sha256=AYf51fj80OKCRis93v2DlZjt5rM-VQOPptSHJbFtkXw,1131 importlib_resources/tests/zipdata01/ziptestdata.zip,sha256=AYf51fj80OKCRis93v2DlZjt5rM-VQOPptSHJbFtkXw,1131
importlib_resources/tests/zipdata02/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 importlib_resources/tests/zipdata02/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
importlib_resources/tests/zipdata02/ziptestdata.zip,sha256=e6HXvTEObXvJcNxyX5I8tu5M8_6mSN8ALahHfqE7ADA,698 importlib_resources/tests/zipdata02/ziptestdata.zip,sha256=e6HXvTEObXvJcNxyX5I8tu5M8_6mSN8ALahHfqE7ADA,698
importlib_resources-3.0.0.dist-info/LICENSE,sha256=uWRjFdYGataJX2ziXk048ItUglQmjng3GWBALaWA36U,568 importlib_resources-3.2.1.dist-info/LICENSE,sha256=uWRjFdYGataJX2ziXk048ItUglQmjng3GWBALaWA36U,568
importlib_resources-3.0.0.dist-info/METADATA,sha256=BIalQpWJG-Av5ZUNQXdFsv6M8s8EdYiymu6GaoEL1Rk,2100 importlib_resources-3.2.1.dist-info/METADATA,sha256=d_tMNLHsZ_lPU-wq04MWr0yEfpwbNFKgfO_CU5GCC9g,1783
importlib_resources-3.0.0.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110 importlib_resources-3.2.1.dist-info/WHEEL,sha256=ADKeyaGyKF5DwBNE0sRE5pvW-bSkFMJfBuhzZ3rceP4,110
importlib_resources-3.0.0.dist-info/top_level.txt,sha256=fHIjHU1GZwAjvcydpmUnUrTnbvdiWjG4OEVZK8by0TQ,20 importlib_resources-3.2.1.dist-info/top_level.txt,sha256=fHIjHU1GZwAjvcydpmUnUrTnbvdiWjG4OEVZK8by0TQ,20
importlib_resources-3.0.0.dist-info/RECORD,, importlib_resources-3.2.1.dist-info/RECORD,,

Просмотреть файл

@ -1,5 +1,5 @@
Wheel-Version: 1.0 Wheel-Version: 1.0
Generator: bdist_wheel (0.34.2) Generator: bdist_wheel (0.35.1)
Root-Is-Purelib: true Root-Is-Purelib: true
Tag: py2-none-any Tag: py2-none-any
Tag: py3-none-any Tag: py3-none-any

Просмотреть файл

@ -93,6 +93,7 @@ def _tempfile(reader, suffix=''):
try: try:
os.write(fd, reader()) os.write(fd, reader())
os.close(fd) os.close(fd)
del reader
yield Path(raw_path) yield Path(raw_path)
finally: finally:
try: try:
@ -102,14 +103,12 @@ def _tempfile(reader, suffix=''):
@singledispatch @singledispatch
@contextlib.contextmanager
def as_file(path): def as_file(path):
""" """
Given a Traversable object, return that object as a Given a Traversable object, return that object as a
path on the local file system in a context manager. path on the local file system in a context manager.
""" """
with _tempfile(path.read_bytes, suffix=path.name) as local: return _tempfile(path.read_bytes, suffix=path.name)
yield local
@as_file.register(Path) @as_file.register(Path)

Просмотреть файл

@ -36,6 +36,12 @@ except NameError:
FileNotFoundError = OSError # type: ignore FileNotFoundError = OSError # type: ignore
try:
NotADirectoryError = NotADirectoryError # type: ignore
except NameError:
NotADirectoryError = OSError # type: ignore
try: try:
from zipfile import Path as ZipPath # type: ignore from zipfile import Path as ZipPath # type: ignore
except ImportError: except ImportError:
@ -93,6 +99,10 @@ class LoaderAdapter:
with suppress(AttributeError): with suppress(AttributeError):
return readers.ZipReader(spec.loader, spec.name) return readers.ZipReader(spec.loader, spec.name)
def _namespace_reader(spec):
with suppress(AttributeError, ValueError):
return readers.NamespaceReader(spec.submodule_search_locations)
def _available_reader(spec): def _available_reader(spec):
with suppress(AttributeError): with suppress(AttributeError):
return spec.loader.get_resource_reader(spec.name) return spec.loader.get_resource_reader(spec.name)
@ -106,6 +116,8 @@ class LoaderAdapter:
_native_reader(self.spec) or _native_reader(self.spec) or
# local ZipReader if a zip module # local ZipReader if a zip module
_zip_reader(self.spec) or _zip_reader(self.spec) or
# local NamespaceReader if a namespace module
_namespace_reader(self.spec) or
# local FileReader # local FileReader
readers.FileReader(self) readers.FileReader(self)
) )

Просмотреть файл

@ -1,8 +1,9 @@
import os import os
import sys import sys
import io
from . import _common from . import _common
from contextlib import contextmanager, suppress from contextlib import suppress
from importlib.abc import ResourceLoader from importlib.abc import ResourceLoader
from io import BytesIO, TextIOWrapper from io import BytesIO, TextIOWrapper
from pathlib import Path from pathlib import Path
@ -10,6 +11,8 @@ from types import ModuleType
from typing import Iterable, Iterator, Optional, Set, Union # noqa: F401 from typing import Iterable, Iterator, Optional, Set, Union # noqa: F401
from typing import cast from typing import cast
from typing.io import BinaryIO, TextIO from typing.io import BinaryIO, TextIO
from collections.abc import Sequence
from ._compat import singledispatch
if False: # TYPE_CHECKING if False: # TYPE_CHECKING
from typing import ContextManager from typing import ContextManager
@ -30,27 +33,29 @@ def open_binary(package: Package, resource: Resource) -> BinaryIO:
return reader.open_resource(resource) return reader.open_resource(resource)
# Using pathlib doesn't work well here due to the lack of 'strict' # Using pathlib doesn't work well here due to the lack of 'strict'
# argument for pathlib.Path.resolve() prior to Python 3.6. # argument for pathlib.Path.resolve() prior to Python 3.6.
absolute_package_path = os.path.abspath( if package.__spec__.submodule_search_locations is not None:
package.__spec__.origin or 'non-existent file') paths = package.__spec__.submodule_search_locations
package_path = os.path.dirname(absolute_package_path) elif package.__spec__.origin is not None:
full_path = os.path.join(package_path, resource) paths = [os.path.dirname(os.path.abspath(package.__spec__.origin))]
try:
return open(full_path, mode='rb') for package_path in paths:
except OSError: full_path = os.path.join(package_path, resource)
# Just assume the loader is a resource loader; all the relevant try:
# importlib.machinery loaders are and an AttributeError for return open(full_path, mode='rb')
# get_data() will make it clear what is needed from the loader. except OSError:
loader = cast(ResourceLoader, package.__spec__.loader) # Just assume the loader is a resource loader; all the relevant
data = None # importlib.machinery loaders are and an AttributeError for
if hasattr(package.__spec__.loader, 'get_data'): # get_data() will make it clear what is needed from the loader.
with suppress(OSError): loader = cast(ResourceLoader, package.__spec__.loader)
data = loader.get_data(full_path) data = None
if data is None: if hasattr(package.__spec__.loader, 'get_data'):
package_name = package.__spec__.name with suppress(OSError):
message = '{!r} resource not found in {!r}'.format( data = loader.get_data(full_path)
resource, package_name) if data is not None:
raise FileNotFoundError(message) return BytesIO(data)
return BytesIO(data)
raise FileNotFoundError('{!r} resource not found in {!r}'.format(
resource, package.__spec__.name))
def open_text(package: Package, def open_text(package: Package,
@ -94,22 +99,26 @@ def path(
""" """
reader = _common.get_resource_reader(_common.get_package(package)) reader = _common.get_resource_reader(_common.get_package(package))
return ( return (
_path_from_reader(reader, resource) _path_from_reader(reader, _common.normalize_path(resource))
if reader else if reader else
_common.as_file( _common.as_file(
_common.files(package).joinpath(_common.normalize_path(resource))) _common.files(package).joinpath(_common.normalize_path(resource)))
) )
@contextmanager
def _path_from_reader(reader, resource): def _path_from_reader(reader, resource):
norm_resource = _common.normalize_path(resource) return _path_from_resource_path(reader, resource) or \
_path_from_open_resource(reader, resource)
def _path_from_resource_path(reader, resource):
with suppress(FileNotFoundError): with suppress(FileNotFoundError):
yield Path(reader.resource_path(norm_resource)) return Path(reader.resource_path(resource))
return
opener_reader = reader.open_resource(norm_resource)
with _common._tempfile(opener_reader.read, suffix=norm_resource) as res: def _path_from_open_resource(reader, resource):
yield res saved = io.BytesIO(reader.open_resource(resource).read())
return _common._tempfile(saved.read, suffix=resource)
def is_resource(package: Package, name: str) -> bool: def is_resource(package: Package, name: str) -> bool:
@ -138,13 +147,18 @@ def contents(package: Package) -> Iterable[str]:
package = _common.get_package(package) package = _common.get_package(package)
reader = _common.get_resource_reader(package) reader = _common.get_resource_reader(package)
if reader is not None: if reader is not None:
return reader.contents() return _ensure_sequence(reader.contents())
# Is the package a namespace package? By definition, namespace packages transversable = _common.from_package(package)
# cannot have resources. if transversable.is_dir():
namespace = ( return list(item.name for item in transversable.iterdir())
package.__spec__.origin is None or return []
package.__spec__.origin == 'namespace'
)
if namespace or not package.__spec__.has_location: @singledispatch
return () def _ensure_sequence(iterable):
return list(item.name for item in _common.from_package(package).iterdir()) return list(iterable)
@_ensure_sequence.register(Sequence)
def _(iterable):
return iterable

Просмотреть файл

@ -0,0 +1,123 @@
import os.path
from collections import OrderedDict
from . import abc
from ._compat import Path, ZipPath
from ._compat import FileNotFoundError, NotADirectoryError
class FileReader(abc.TraversableResources):
def __init__(self, loader):
self.path = Path(loader.path).parent
def resource_path(self, resource):
"""
Return the file system path to prevent
`resources.path()` from creating a temporary
copy.
"""
return str(self.path.joinpath(resource))
def files(self):
return self.path
class ZipReader(abc.TraversableResources):
def __init__(self, loader, module):
_, _, name = module.rpartition('.')
self.prefix = loader.prefix.replace('\\', '/') + name + '/'
self.archive = loader.archive
def open_resource(self, resource):
try:
return super().open_resource(resource)
except KeyError as exc:
raise FileNotFoundError(exc.args[0])
def is_resource(self, path):
# workaround for `zipfile.Path.is_file` returning true
# for non-existent paths.
target = self.files().joinpath(path)
return target.is_file() and target.exists()
def files(self):
return ZipPath(self.archive, self.prefix)
class MultiplexedPath(abc.Traversable):
"""
Given a series of Traversable objects, implement a merged
version of the interface across all objects. Useful for
namespace packages which may be multihomed at a single
name.
"""
def __init__(self, *paths):
paths = list(OrderedDict.fromkeys(paths)) # remove duplicates
self._paths = list(map(Path, paths))
if not self._paths:
message = 'MultiplexedPath must contain at least one path'
raise FileNotFoundError(message)
if any(not path.is_dir() for path in self._paths):
raise NotADirectoryError(
'MultiplexedPath only supports directories')
def iterdir(self):
visited = []
for path in self._paths:
for file in path.iterdir():
if file.name in visited:
continue
visited.append(file.name)
yield file
def read_bytes(self):
raise FileNotFoundError('{} is not a file'.format(self))
def read_text(self, *args, **kwargs):
raise FileNotFoundError('{} is not a file'.format(self))
def is_dir(self):
return True
def is_file(self):
return False
def joinpath(self, child):
# first try to find child in current paths
for file in self.iterdir():
if file.name == child:
return file
# if it does not exist, construct it with the first path
return self._paths[0] / child
__truediv__ = joinpath
def open(self, *args, **kwargs):
raise FileNotFoundError('{} is not a file'.format(self))
def name(self):
return os.path.basename(self._paths[0])
def __repr__(self):
return 'MultiplexedPath({})'.format(
', '.join("'{}'".format(path) for path in self._paths))
class NamespaceReader(abc.TraversableResources):
def __init__(self, namespace_path):
if 'NamespacePath' not in str(namespace_path):
raise ValueError('Invalid path')
self.path = MultiplexedPath(*list(namespace_path))
def resource_path(self, resource):
"""
Return the file system path to prevent
`resources.path()` from creating a temporary
copy.
"""
return str(self.path.joinpath(resource))
def files(self):
return self.path

Просмотреть файл

@ -0,0 +1,13 @@
Copyright 2017-2019 Brett Cannon, Barry Warsaw
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Просмотреть файл

@ -0,0 +1,41 @@
Metadata-Version: 2.1
Name: importlib-resources
Version: 3.3.0
Summary: Read resources from Python packages
Home-page: https://github.com/python/importlib_resources
Author: Barry Warsaw
Author-email: barry@python.org
License: UNKNOWN
Project-URL: Documentation, https://importlib-resources.readthedocs.io/
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Topic :: Software Development :: Libraries
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7
Requires-Dist: pathlib2 ; python_version < "3"
Requires-Dist: contextlib2 ; python_version < "3"
Requires-Dist: singledispatch ; python_version < "3.4"
Requires-Dist: typing ; python_version < "3.5"
Requires-Dist: zipp (>=0.4) ; python_version < "3.8"
Provides-Extra: docs
Requires-Dist: sphinx ; extra == 'docs'
Requires-Dist: rst.linker ; extra == 'docs'
Requires-Dist: jaraco.packaging ; extra == 'docs'
``importlib_resources`` is a backport of Python standard library
`importlib.resources
<https://docs.python.org/3.9/library/importlib.html#module-importlib.resources>`_
module for Python 2.7, and 3.4 through 3.8. Users of Python 3.9 and beyond
should use the standard library module, since for these versions,
``importlib_resources`` just delegates to that module.
The key goal of this module is to replace parts of `pkg_resources
<https://setuptools.readthedocs.io/en/latest/pkg_resources.html>`_ with a
solution in Python's stdlib that relies on well-defined APIs. This makes
reading resources included in packages easier, with more stable and consistent
semantics.

Просмотреть файл

@ -0,0 +1,42 @@
importlib_resources/__init__.py,sha256=hswDmLAH0IUlLWwmdHXPN2mgus2bk5IwDP-BFzg7VKo,977
importlib_resources/_common.py,sha256=RN8cXOZtlygvlbyTewd-ni9wC1hwXpfbZnrl7kbx0nI,3121
importlib_resources/_compat.py,sha256=NDCXOf1097aDJJx-_pQ0UIktzVx2G1aPIQTRFGx0FHI,3694
importlib_resources/_py2.py,sha256=G9M5mv1ILl8NARGdNX0v9_F_Hb4HUKCS-FCNK63Ajvw,4146
importlib_resources/_py3.py,sha256=Bc-p0UYfPVWXFJ21HLNfVvbVrPJFXBA0g80rqPInkq8,5564
importlib_resources/abc.py,sha256=6PX4Nprv39YnAht3NymhHIuSso0ocAKqDJZf-A6BgIw,3894
importlib_resources/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
importlib_resources/readers.py,sha256=fGuSBoMeeERUVrscN9Grhp0s-wKMy7nMVbCx92vIlGs,3674
importlib_resources/trees.py,sha256=U3FlQSI5--eF4AdzOjBvW4xnjL21OFX8ivk82Quwv_M,117
importlib_resources/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
importlib_resources/tests/_compat.py,sha256=geKWJe8UGXjC181JxmtxR3A_o5VrR4yxolS0xbnxMlw,801
importlib_resources/tests/py27compat.py,sha256=9lDJkGV2swPVQJg6isOorRNFWuP6KeoWd4D2bFNmzLI,965
importlib_resources/tests/test_files.py,sha256=91rf4C74_aJsKNSt-a-03slVpY9QSAuCbogFWnsaPjE,1017
importlib_resources/tests/test_open.py,sha256=pIYWvuTDpQOJKX0SEuOKGotssZcEeY_xNPDqLGCvP_U,2565
importlib_resources/tests/test_path.py,sha256=GnUOu-338o9offnC8xwbXjH9JIQJpD7JujgQkGB106Q,1548
importlib_resources/tests/test_read.py,sha256=DpA7tzxSQlU0_YQuWibB3E5PDL9fQUdzeKoEUGnAx78,2046
importlib_resources/tests/test_reader.py,sha256=yEO0xyrYDcGRmsBC6A1n99GXiTZpVvp-uGA313s6aao,4638
importlib_resources/tests/test_resource.py,sha256=GbrMeHJ74N6KJG38TDodCp--nsRnFHXJc7NrAEqUPaU,8766
importlib_resources/tests/util.py,sha256=8hBFwqIZRJFNvkboEB7aWsCqTtgUjlWI_iQ0KV158Yk,5914
importlib_resources/tests/data01/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
importlib_resources/tests/data01/binary.file,sha256=BU7ewdAhH2JP7Qy8qdT5QAsOSRxDdCryxbCr6_DJkNg,4
importlib_resources/tests/data01/utf-16.file,sha256=t5q9qhxX0rYqItBOM8D3ylwG-RHrnOYteTLtQr6sF7g,44
importlib_resources/tests/data01/utf-8.file,sha256=kwWgYG4yQ-ZF2X_WA66EjYPmxJRn-w8aSOiS9e8tKYY,20
importlib_resources/tests/data01/subdirectory/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
importlib_resources/tests/data01/subdirectory/binary.file,sha256=BU7ewdAhH2JP7Qy8qdT5QAsOSRxDdCryxbCr6_DJkNg,4
importlib_resources/tests/data02/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
importlib_resources/tests/data02/one/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
importlib_resources/tests/data02/one/resource1.txt,sha256=10flKac7c-XXFzJ3t-AB5MJjlBy__dSZvPE_dOm2q6U,13
importlib_resources/tests/data02/two/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
importlib_resources/tests/data02/two/resource2.txt,sha256=lt2jbN3TMn9QiFKM832X39bU_62UptDdUkoYzkvEbl0,13
importlib_resources/tests/namespacedata01/binary.file,sha256=BU7ewdAhH2JP7Qy8qdT5QAsOSRxDdCryxbCr6_DJkNg,4
importlib_resources/tests/namespacedata01/utf-16.file,sha256=t5q9qhxX0rYqItBOM8D3ylwG-RHrnOYteTLtQr6sF7g,44
importlib_resources/tests/namespacedata01/utf-8.file,sha256=kwWgYG4yQ-ZF2X_WA66EjYPmxJRn-w8aSOiS9e8tKYY,20
importlib_resources/tests/zipdata01/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
importlib_resources/tests/zipdata01/ziptestdata.zip,sha256=AYf51fj80OKCRis93v2DlZjt5rM-VQOPptSHJbFtkXw,1131
importlib_resources/tests/zipdata02/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
importlib_resources/tests/zipdata02/ziptestdata.zip,sha256=e6HXvTEObXvJcNxyX5I8tu5M8_6mSN8ALahHfqE7ADA,698
importlib_resources-3.3.0.dist-info/LICENSE,sha256=uWRjFdYGataJX2ziXk048ItUglQmjng3GWBALaWA36U,568
importlib_resources-3.3.0.dist-info/METADATA,sha256=GxPMbCwUwlCuHNCiPJvP4IC_mTKqP4b_W7UqqNidcF4,1791
importlib_resources-3.3.0.dist-info/WHEEL,sha256=ADKeyaGyKF5DwBNE0sRE5pvW-bSkFMJfBuhzZ3rceP4,110
importlib_resources-3.3.0.dist-info/top_level.txt,sha256=fHIjHU1GZwAjvcydpmUnUrTnbvdiWjG4OEVZK8by0TQ,20
importlib_resources-3.3.0.dist-info/RECORD,,

Просмотреть файл

@ -1,5 +1,5 @@
Wheel-Version: 1.0 Wheel-Version: 1.0
Generator: bdist_wheel (0.34.2) Generator: bdist_wheel (0.35.1)
Root-Is-Purelib: true Root-Is-Purelib: true
Tag: py2-none-any Tag: py2-none-any
Tag: py3-none-any Tag: py3-none-any

Просмотреть файл

@ -0,0 +1 @@
importlib_resources

Просмотреть файл

@ -0,0 +1,53 @@
"""Read resources contained within a package."""
import sys
from ._common import (
as_file, files,
)
# For compatibility. Ref #88.
# Also requires hook-importlib_resources.py (Ref #101).
__import__('importlib_resources.trees')
__all__ = [
'Package',
'Resource',
'ResourceReader',
'as_file',
'contents',
'files',
'is_resource',
'open_binary',
'open_text',
'path',
'read_binary',
'read_text',
]
if sys.version_info >= (3,):
from importlib_resources._py3 import (
Package,
Resource,
contents,
is_resource,
open_binary,
open_text,
path,
read_binary,
read_text,
)
from importlib_resources.abc import ResourceReader
else:
from importlib_resources._py2 import (
contents,
is_resource,
open_binary,
open_text,
path,
read_binary,
read_text,
)
del __all__[:3]

Просмотреть файл

@ -0,0 +1,120 @@
from __future__ import absolute_import
import os
import tempfile
import contextlib
import types
import importlib
from ._compat import (
Path, FileNotFoundError,
singledispatch, package_spec,
)
if False: # TYPE_CHECKING
from typing import Union, Any, Optional
from .abc import ResourceReader
Package = Union[types.ModuleType, str]
def files(package):
"""
Get a Traversable resource from a package
"""
return from_package(get_package(package))
def normalize_path(path):
# type: (Any) -> str
"""Normalize a path by ensuring it is a string.
If the resulting string contains path separators, an exception is raised.
"""
str_path = str(path)
parent, file_name = os.path.split(str_path)
if parent:
raise ValueError('{!r} must be only a file name'.format(path))
return file_name
def get_resource_reader(package):
# type: (types.ModuleType) -> Optional[ResourceReader]
"""
Return the package's loader if it's a ResourceReader.
"""
# We can't use
# a issubclass() check here because apparently abc.'s __subclasscheck__()
# hook wants to create a weak reference to the object, but
# zipimport.zipimporter does not support weak references, resulting in a
# TypeError. That seems terrible.
spec = package.__spec__
reader = getattr(spec.loader, 'get_resource_reader', None)
if reader is None:
return None
return reader(spec.name)
def resolve(cand):
# type: (Package) -> types.ModuleType
return (
cand if isinstance(cand, types.ModuleType)
else importlib.import_module(cand)
)
def get_package(package):
# type: (Package) -> types.ModuleType
"""Take a package name or module object and return the module.
Raise an exception if the resolved module is not a package.
"""
resolved = resolve(package)
if package_spec(resolved).submodule_search_locations is None:
raise TypeError('{!r} is not a package'.format(package))
return resolved
def from_package(package):
"""
Return a Traversable object for the given package.
"""
spec = package_spec(package)
reader = spec.loader.get_resource_reader(spec.name)
return reader.files()
@contextlib.contextmanager
def _tempfile(reader, suffix=''):
# Not using tempfile.NamedTemporaryFile as it leads to deeper 'try'
# blocks due to the need to close the temporary file to work on Windows
# properly.
fd, raw_path = tempfile.mkstemp(suffix=suffix)
try:
os.write(fd, reader())
os.close(fd)
del reader
yield Path(raw_path)
finally:
try:
os.remove(raw_path)
except FileNotFoundError:
pass
@singledispatch
def as_file(path):
"""
Given a Traversable object, return that object as a
path on the local file system in a context manager.
"""
return _tempfile(path.read_bytes, suffix=path.name)
@as_file.register(Path)
@contextlib.contextmanager
def _(path):
"""
Degenerate behavior for pathlib.Path objects.
"""
yield path

Просмотреть файл

@ -0,0 +1,139 @@
from __future__ import absolute_import
import sys
# flake8: noqa
if sys.version_info > (3,5):
from pathlib import Path, PurePath
else:
from pathlib2 import Path, PurePath # type: ignore
if sys.version_info > (3,):
from contextlib import suppress
else:
from contextlib2 import suppress # type: ignore
try:
from functools import singledispatch
except ImportError:
from singledispatch import singledispatch # type: ignore
try:
from abc import ABC # type: ignore
except ImportError:
from abc import ABCMeta
class ABC(object): # type: ignore
__metaclass__ = ABCMeta
try:
FileNotFoundError = FileNotFoundError # type: ignore
except NameError:
FileNotFoundError = OSError # type: ignore
try:
NotADirectoryError = NotADirectoryError # type: ignore
except NameError:
NotADirectoryError = OSError # type: ignore
try:
from zipfile import Path as ZipPath # type: ignore
except ImportError:
from zipp import Path as ZipPath # type: ignore
try:
from typing import runtime_checkable # type: ignore
except ImportError:
def runtime_checkable(cls): # type: ignore
return cls
try:
from typing import Protocol # type: ignore
except ImportError:
Protocol = ABC # type: ignore
__metaclass__ = type
class PackageSpec:
def __init__(self, **kwargs):
vars(self).update(kwargs)
class TraversableResourcesAdapter:
def __init__(self, spec):
self.spec = spec
self.loader = LoaderAdapter(spec)
def __getattr__(self, name):
return getattr(self.spec, name)
class LoaderAdapter:
"""
Adapt loaders to provide TraversableResources and other
compatibility.
"""
def __init__(self, spec):
self.spec = spec
@property
def path(self):
# Python < 3
return self.spec.origin
def get_resource_reader(self, name):
# Python < 3.9
from . import readers
def _zip_reader(spec):
with suppress(AttributeError):
return readers.ZipReader(spec.loader, spec.name)
def _namespace_reader(spec):
with suppress(AttributeError, ValueError):
return readers.NamespaceReader(spec.submodule_search_locations)
def _available_reader(spec):
with suppress(AttributeError):
return spec.loader.get_resource_reader(spec.name)
def _native_reader(spec):
reader = _available_reader(spec)
return reader if hasattr(reader, 'files') else None
return (
# native reader if it supplies 'files'
_native_reader(self.spec) or
# local ZipReader if a zip module
_zip_reader(self.spec) or
# local NamespaceReader if a namespace module
_namespace_reader(self.spec) or
# local FileReader
readers.FileReader(self)
)
def package_spec(package):
"""
Construct a minimal package spec suitable for
matching the interfaces this library relies upon
in later Python versions.
"""
spec = getattr(package, '__spec__', None) or \
PackageSpec(
origin=package.__file__,
loader=getattr(package, '__loader__', None),
name=package.__name__,
submodule_search_locations=getattr(package, '__path__', None),
)
return TraversableResourcesAdapter(spec)

Просмотреть файл

@ -0,0 +1,107 @@
import os
import errno
from . import _common
from ._compat import FileNotFoundError
from io import BytesIO, TextIOWrapper, open as io_open
def open_binary(package, resource):
"""Return a file-like object opened for binary reading of the resource."""
resource = _common.normalize_path(resource)
package = _common.get_package(package)
# Using pathlib doesn't work well here due to the lack of 'strict' argument
# for pathlib.Path.resolve() prior to Python 3.6.
package_path = os.path.dirname(package.__file__)
relative_path = os.path.join(package_path, resource)
full_path = os.path.abspath(relative_path)
try:
return io_open(full_path, 'rb')
except IOError:
# This might be a package in a zip file. zipimport provides a loader
# with a functioning get_data() method, however we have to strip the
# archive (i.e. the .zip file's name) off the front of the path. This
# is because the zipimport loader in Python 2 doesn't actually follow
# PEP 302. It should allow the full path, but actually requires that
# the path be relative to the zip file.
try:
loader = package.__loader__
full_path = relative_path[len(loader.archive)+1:]
data = loader.get_data(full_path)
except (IOError, AttributeError):
package_name = package.__name__
message = '{!r} resource not found in {!r}'.format(
resource, package_name)
raise FileNotFoundError(message)
return BytesIO(data)
def open_text(package, resource, encoding='utf-8', errors='strict'):
"""Return a file-like object opened for text reading of the resource."""
return TextIOWrapper(
open_binary(package, resource), encoding=encoding, errors=errors)
def read_binary(package, resource):
"""Return the binary contents of the resource."""
with open_binary(package, resource) as fp:
return fp.read()
def read_text(package, resource, encoding='utf-8', errors='strict'):
"""Return the decoded string of the resource.
The decoding-related arguments have the same semantics as those of
bytes.decode().
"""
with open_text(package, resource, encoding, errors) as fp:
return fp.read()
def path(package, resource):
"""A context manager providing a file path object to the resource.
If the resource does not already exist on its own on the file system,
a temporary file will be created. If the file was created, the file
will be deleted upon exiting the context manager (no exception is
raised if the file was deleted prior to the context manager
exiting).
"""
path = _common.files(package).joinpath(_common.normalize_path(resource))
if not path.is_file():
raise FileNotFoundError(path)
return _common.as_file(path)
def is_resource(package, name):
"""True if name is a resource inside package.
Directories are *not* resources.
"""
package = _common.get_package(package)
_common.normalize_path(name)
try:
package_contents = set(contents(package))
except OSError as error:
if error.errno not in (errno.ENOENT, errno.ENOTDIR):
# We won't hit this in the Python 2 tests, so it'll appear
# uncovered. We could mock os.listdir() to return a non-ENOENT or
# ENOTDIR, but then we'd have to depend on another external
# library since Python 2 doesn't have unittest.mock. It's not
# worth it.
raise # pragma: nocover
return False
if name not in package_contents:
return False
return (_common.from_package(package) / name).is_file()
def contents(package):
"""Return an iterable of entries in `package`.
Note that not all entries are resources. Specifically, directories are
not considered resources. Use `is_resource()` on each entry returned here
to check if it is a resource or not.
"""
package = _common.get_package(package)
return list(item.name for item in _common.from_package(package).iterdir())

Просмотреть файл

@ -0,0 +1,160 @@
import os
import io
from . import _common
from contextlib import suppress
from importlib.abc import ResourceLoader
from io import BytesIO, TextIOWrapper
from pathlib import Path
from types import ModuleType
from typing import Iterable, Iterator, Optional, Set, Union # noqa: F401
from typing import cast
from typing.io import BinaryIO, TextIO
from collections.abc import Sequence
from functools import singledispatch
if False: # TYPE_CHECKING
from typing import ContextManager
Package = Union[ModuleType, str]
Resource = Union[str, os.PathLike]
def open_binary(package: Package, resource: Resource) -> BinaryIO:
"""Return a file-like object opened for binary reading of the resource."""
resource = _common.normalize_path(resource)
package = _common.get_package(package)
reader = _common.get_resource_reader(package)
if reader is not None:
return reader.open_resource(resource)
# Using pathlib doesn't work well here due to the lack of 'strict'
# argument for pathlib.Path.resolve() prior to Python 3.6.
if package.__spec__.submodule_search_locations is not None:
paths = package.__spec__.submodule_search_locations
elif package.__spec__.origin is not None:
paths = [os.path.dirname(os.path.abspath(package.__spec__.origin))]
for package_path in paths:
full_path = os.path.join(package_path, resource)
try:
return open(full_path, mode='rb')
except OSError:
# Just assume the loader is a resource loader; all the relevant
# importlib.machinery loaders are and an AttributeError for
# get_data() will make it clear what is needed from the loader.
loader = cast(ResourceLoader, package.__spec__.loader)
data = None
if hasattr(package.__spec__.loader, 'get_data'):
with suppress(OSError):
data = loader.get_data(full_path)
if data is not None:
return BytesIO(data)
raise FileNotFoundError('{!r} resource not found in {!r}'.format(
resource, package.__spec__.name))
def open_text(package: Package,
resource: Resource,
encoding: str = 'utf-8',
errors: str = 'strict') -> TextIO:
"""Return a file-like object opened for text reading of the resource."""
return TextIOWrapper(
open_binary(package, resource), encoding=encoding, errors=errors)
def read_binary(package: Package, resource: Resource) -> bytes:
"""Return the binary contents of the resource."""
with open_binary(package, resource) as fp:
return fp.read()
def read_text(package: Package,
resource: Resource,
encoding: str = 'utf-8',
errors: str = 'strict') -> str:
"""Return the decoded string of the resource.
The decoding-related arguments have the same semantics as those of
bytes.decode().
"""
with open_text(package, resource, encoding, errors) as fp:
return fp.read()
def path(
package: Package, resource: Resource,
) -> 'ContextManager[Path]':
"""A context manager providing a file path object to the resource.
If the resource does not already exist on its own on the file system,
a temporary file will be created. If the file was created, the file
will be deleted upon exiting the context manager (no exception is
raised if the file was deleted prior to the context manager
exiting).
"""
reader = _common.get_resource_reader(_common.get_package(package))
return (
_path_from_reader(reader, _common.normalize_path(resource))
if reader else
_common.as_file(
_common.files(package).joinpath(_common.normalize_path(resource)))
)
def _path_from_reader(reader, resource):
return _path_from_resource_path(reader, resource) or \
_path_from_open_resource(reader, resource)
def _path_from_resource_path(reader, resource):
with suppress(FileNotFoundError):
return Path(reader.resource_path(resource))
def _path_from_open_resource(reader, resource):
saved = io.BytesIO(reader.open_resource(resource).read())
return _common._tempfile(saved.read, suffix=resource)
def is_resource(package: Package, name: str) -> bool:
"""True if `name` is a resource inside `package`.
Directories are *not* resources.
"""
package = _common.get_package(package)
_common.normalize_path(name)
reader = _common.get_resource_reader(package)
if reader is not None:
return reader.is_resource(name)
package_contents = set(contents(package))
if name not in package_contents:
return False
return (_common.from_package(package) / name).is_file()
def contents(package: Package) -> Iterable[str]:
"""Return an iterable of entries in `package`.
Note that not all entries are resources. Specifically, directories are
not considered resources. Use `is_resource()` on each entry returned here
to check if it is a resource or not.
"""
package = _common.get_package(package)
reader = _common.get_resource_reader(package)
if reader is not None:
return _ensure_sequence(reader.contents())
transversable = _common.from_package(package)
if transversable.is_dir():
return list(item.name for item in transversable.iterdir())
return []
@singledispatch
def _ensure_sequence(iterable):
return list(iterable)
@_ensure_sequence.register(Sequence)
def _(iterable):
return iterable

Просмотреть файл

@ -0,0 +1,142 @@
from __future__ import absolute_import
import abc
from ._compat import ABC, FileNotFoundError, runtime_checkable, Protocol
# Use mypy's comment syntax for Python 2 compatibility
try:
from typing import BinaryIO, Iterable, Text
except ImportError:
pass
class ResourceReader(ABC):
"""Abstract base class for loaders to provide resource reading support."""
@abc.abstractmethod
def open_resource(self, resource):
# type: (Text) -> BinaryIO
"""Return an opened, file-like object for binary reading.
The 'resource' argument is expected to represent only a file name.
If the resource cannot be found, FileNotFoundError is raised.
"""
# This deliberately raises FileNotFoundError instead of
# NotImplementedError so that if this method is accidentally called,
# it'll still do the right thing.
raise FileNotFoundError
@abc.abstractmethod
def resource_path(self, resource):
# type: (Text) -> Text
"""Return the file system path to the specified resource.
The 'resource' argument is expected to represent only a file name.
If the resource does not exist on the file system, raise
FileNotFoundError.
"""
# This deliberately raises FileNotFoundError instead of
# NotImplementedError so that if this method is accidentally called,
# it'll still do the right thing.
raise FileNotFoundError
@abc.abstractmethod
def is_resource(self, path):
# type: (Text) -> bool
"""Return True if the named 'path' is a resource.
Files are resources, directories are not.
"""
raise FileNotFoundError
@abc.abstractmethod
def contents(self):
# type: () -> Iterable[str]
"""Return an iterable of entries in `package`."""
raise FileNotFoundError
@runtime_checkable
class Traversable(Protocol):
"""
An object with a subset of pathlib.Path methods suitable for
traversing directories and opening files.
"""
@abc.abstractmethod
def iterdir(self):
"""
Yield Traversable objects in self
"""
@abc.abstractmethod
def read_bytes(self):
"""
Read contents of self as bytes
"""
@abc.abstractmethod
def read_text(self, encoding=None):
"""
Read contents of self as bytes
"""
@abc.abstractmethod
def is_dir(self):
"""
Return True if self is a dir
"""
@abc.abstractmethod
def is_file(self):
"""
Return True if self is a file
"""
@abc.abstractmethod
def joinpath(self, child):
"""
Return Traversable child in self
"""
@abc.abstractmethod
def __truediv__(self, child):
"""
Return Traversable child in self
"""
@abc.abstractmethod
def open(self, mode='r', *args, **kwargs):
"""
mode may be 'r' or 'rb' to open as text or binary. Return a handle
suitable for reading (same as pathlib.Path.open).
When opening as text, accepts encoding parameters such as those
accepted by io.TextIOWrapper.
"""
@abc.abstractproperty
def name(self):
# type: () -> str
"""
The base name of this object without any parent references.
"""
class TraversableResources(ResourceReader):
@abc.abstractmethod
def files(self):
"""Return a Traversable object for the loaded package."""
def open_resource(self, resource):
return self.files().joinpath(resource).open('rb')
def resource_path(self, resource):
raise FileNotFoundError(resource)
def is_resource(self, path):
return self.files().joinpath(path).is_file()
def contents(self):
return (item.name for item in self.files().iterdir())

Просмотреть файл

Просмотреть файл

@ -0,0 +1,123 @@
import os.path
from collections import OrderedDict
from . import abc
from ._compat import Path, ZipPath
from ._compat import FileNotFoundError, NotADirectoryError
class FileReader(abc.TraversableResources):
def __init__(self, loader):
self.path = Path(loader.path).parent
def resource_path(self, resource):
"""
Return the file system path to prevent
`resources.path()` from creating a temporary
copy.
"""
return str(self.path.joinpath(resource))
def files(self):
return self.path
class ZipReader(abc.TraversableResources):
def __init__(self, loader, module):
_, _, name = module.rpartition('.')
self.prefix = loader.prefix.replace('\\', '/') + name + '/'
self.archive = loader.archive
def open_resource(self, resource):
try:
return super().open_resource(resource)
except KeyError as exc:
raise FileNotFoundError(exc.args[0])
def is_resource(self, path):
# workaround for `zipfile.Path.is_file` returning true
# for non-existent paths.
target = self.files().joinpath(path)
return target.is_file() and target.exists()
def files(self):
return ZipPath(self.archive, self.prefix)
class MultiplexedPath(abc.Traversable):
"""
Given a series of Traversable objects, implement a merged
version of the interface across all objects. Useful for
namespace packages which may be multihomed at a single
name.
"""
def __init__(self, *paths):
paths = list(OrderedDict.fromkeys(paths)) # remove duplicates
self._paths = list(map(Path, paths))
if not self._paths:
message = 'MultiplexedPath must contain at least one path'
raise FileNotFoundError(message)
if any(not path.is_dir() for path in self._paths):
raise NotADirectoryError(
'MultiplexedPath only supports directories')
def iterdir(self):
visited = []
for path in self._paths:
for file in path.iterdir():
if file.name in visited:
continue
visited.append(file.name)
yield file
def read_bytes(self):
raise FileNotFoundError('{} is not a file'.format(self))
def read_text(self, *args, **kwargs):
raise FileNotFoundError('{} is not a file'.format(self))
def is_dir(self):
return True
def is_file(self):
return False
def joinpath(self, child):
# first try to find child in current paths
for file in self.iterdir():
if file.name == child:
return file
# if it does not exist, construct it with the first path
return self._paths[0] / child
__truediv__ = joinpath
def open(self, *args, **kwargs):
raise FileNotFoundError('{} is not a file'.format(self))
def name(self):
return os.path.basename(self._paths[0])
def __repr__(self):
return 'MultiplexedPath({})'.format(
', '.join("'{}'".format(path) for path in self._paths))
class NamespaceReader(abc.TraversableResources):
def __init__(self, namespace_path):
if 'NamespacePath' not in str(namespace_path):
raise ValueError('Invalid path')
self.path = MultiplexedPath(*list(namespace_path))
def resource_path(self, resource):
"""
Return the file system path to prevent
`resources.path()` from creating a temporary
copy.
"""
return str(self.path.joinpath(resource))
def files(self):
return self.path

Просмотреть файл

@ -0,0 +1,6 @@
# for compatibility with 1.1, continue to expose as_file here.
from ._common import as_file
__all__ = ['as_file']

Просмотреть файл

@ -1,5 +0,0 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.34.2)
Root-Is-Purelib: false
Tag: cp38-cp38-macosx_10_15_x86_64

Просмотреть файл

@ -1,7 +1,6 @@
_scandir.cpython-38-darwin.so,sha256=3a2UitVjb1MS0I7WSOp7jPGHsKf-ctNYTrBvDmPupOg,27780
scandir.py,sha256=97C2AQInuKk-Phb3aXM7fJomhc-00pZMcBur23NUmrE,24827 scandir.py,sha256=97C2AQInuKk-Phb3aXM7fJomhc-00pZMcBur23NUmrE,24827
scandir-1.10.0.dist-info/LICENSE.txt,sha256=peL73COXREGdKUB828knk8TZwdlWwXT3y3-W-m0FjIY,1464 scandir-1.10.0.dist-info/LICENSE.txt,sha256=peL73COXREGdKUB828knk8TZwdlWwXT3y3-W-m0FjIY,1464
scandir-1.10.0.dist-info/METADATA,sha256=cv1fZ5DeC3DJqnMByWGiprvGhLpQCkWOZiJduweakGk,9559 scandir-1.10.0.dist-info/METADATA,sha256=cv1fZ5DeC3DJqnMByWGiprvGhLpQCkWOZiJduweakGk,9559
scandir-1.10.0.dist-info/WHEEL,sha256=NqgkTkAaRJaCuArPZklUp2tBwn6obHN9aMIfdfLfNkU,110 scandir-1.10.0.dist-info/WHEEL,sha256=WO4o60shExe_A5pkiO6Yb-8OHLGhlAGcs2oJ7aUuE5Q,110
scandir-1.10.0.dist-info/top_level.txt,sha256=Ixze5mNjmis99ql7JEtAYc9-djJMbfRx-FFw3R_zZf8,17 scandir-1.10.0.dist-info/top_level.txt,sha256=Ixze5mNjmis99ql7JEtAYc9-djJMbfRx-FFw3R_zZf8,17
scandir-1.10.0.dist-info/RECORD,, scandir-1.10.0.dist-info/RECORD,,

Просмотреть файл

@ -0,0 +1,5 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.35.1)
Root-Is-Purelib: false
Tag: cp39-cp39-macosx_10_15_x86_64

Просмотреть файл

@ -1,6 +0,0 @@
zipp.py,sha256=o8W25XfoR5DD_krEQLbYrNMmK-x26JvaqeKuboC91YY,7121
zipp-3.1.0.dist-info/LICENSE,sha256=2z8CRrH5J48VhFuZ_sR4uLUG63ZIeZNyL4xuJUKF-vg,1050
zipp-3.1.0.dist-info/METADATA,sha256=EbCdCb8ZzwzYDA7RF8R830VeruipjOKnj32zpMxPsFM,1899
zipp-3.1.0.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92
zipp-3.1.0.dist-info/top_level.txt,sha256=iAbdoSHfaGqBfVb2XuR9JqSQHCoOsOtG6y9C_LSpqFw,5
zipp-3.1.0.dist-info/RECORD,,

Просмотреть файл

@ -1,6 +1,6 @@
Metadata-Version: 2.1 Metadata-Version: 2.1
Name: zipp Name: zipp
Version: 3.1.0 Version: 3.4.0
Summary: Backport of pathlib-compatible object wrapper for zip files Summary: Backport of pathlib-compatible object wrapper for zip files
Home-page: https://github.com/jaraco/zipp Home-page: https://github.com/jaraco/zipp
Author: Jason R. Coombs Author: Jason R. Coombs
@ -18,8 +18,15 @@ Requires-Dist: sphinx ; extra == 'docs'
Requires-Dist: jaraco.packaging (>=3.2) ; extra == 'docs' Requires-Dist: jaraco.packaging (>=3.2) ; extra == 'docs'
Requires-Dist: rst.linker (>=1.9) ; extra == 'docs' Requires-Dist: rst.linker (>=1.9) ; extra == 'docs'
Provides-Extra: testing Provides-Extra: testing
Requires-Dist: pytest (!=3.7.3,>=3.5) ; extra == 'testing'
Requires-Dist: pytest-checkdocs (>=1.2.3) ; extra == 'testing'
Requires-Dist: pytest-flake8 ; extra == 'testing'
Requires-Dist: pytest-cov ; extra == 'testing'
Requires-Dist: jaraco.test (>=3.2.0) ; extra == 'testing'
Requires-Dist: jaraco.itertools ; extra == 'testing' Requires-Dist: jaraco.itertools ; extra == 'testing'
Requires-Dist: func-timeout ; extra == 'testing' Requires-Dist: func-timeout ; extra == 'testing'
Requires-Dist: pytest-black (>=0.3.7) ; (platform_python_implementation != "PyPy") and extra == 'testing'
Requires-Dist: pytest-mypy ; (platform_python_implementation != "PyPy") and extra == 'testing'
.. image:: https://img.shields.io/pypi/v/zipp.svg .. image:: https://img.shields.io/pypi/v/zipp.svg
:target: `PyPI link`_ :target: `PyPI link`_
@ -29,19 +36,14 @@ Requires-Dist: func-timeout ; extra == 'testing'
.. _PyPI link: https://pypi.org/project/zipp .. _PyPI link: https://pypi.org/project/zipp
.. image:: https://dev.azure.com/jaraco/zipp/_apis/build/status/jaraco.zipp?branchName=master .. image:: https://github.com/jaraco/zipp/workflows/Automated%20Tests/badge.svg
:target: https://dev.azure.com/jaraco/zipp/_build/latest?definitionId=1&branchName=master :target: https://github.com/jaraco/zipp/actions?query=workflow%3A%22Automated+Tests%22
:alt: Automated Tests
.. image:: https://img.shields.io/travis/jaraco/zipp/master.svg
:target: https://travis-ci.org/jaraco/zipp
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg .. image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/psf/black :target: https://github.com/psf/black
:alt: Code style: Black :alt: Code style: Black
.. image:: https://img.shields.io/appveyor/ci/jaraco/zipp/master.svg
:target: https://ci.appveyor.com/project/jaraco/zipp/branch/master
.. .. image:: https://readthedocs.org/projects/zipp/badge/?version=latest .. .. image:: https://readthedocs.org/projects/zipp/badge/?version=latest
.. :target: https://zipp.readthedocs.io/en/latest/?badge=latest .. :target: https://zipp.readthedocs.io/en/latest/?badge=latest

Просмотреть файл

@ -0,0 +1,6 @@
zipp.py,sha256=wMSoYxAIPgYnqJAW0JcAl5sWaIcFc5xk3dNjf6ElGgU,8089
zipp-3.4.0.dist-info/LICENSE,sha256=2z8CRrH5J48VhFuZ_sR4uLUG63ZIeZNyL4xuJUKF-vg,1050
zipp-3.4.0.dist-info/METADATA,sha256=noSfks-ReGCmOSTxll7TELBJy0P_yAvVLa0FCFyhMeM,2134
zipp-3.4.0.dist-info/WHEEL,sha256=EVRjI69F5qVjm_YgqcTXPnTAv3BfSUr0WVAHuSP3Xoo,92
zipp-3.4.0.dist-info/top_level.txt,sha256=iAbdoSHfaGqBfVb2XuR9JqSQHCoOsOtG6y9C_LSpqFw,5
zipp-3.4.0.dist-info/RECORD,,

Просмотреть файл

@ -0,0 +1,5 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.35.1)
Root-Is-Purelib: true
Tag: py3-none-any

Просмотреть файл

@ -4,6 +4,7 @@ import zipfile
import itertools import itertools
import contextlib import contextlib
import sys import sys
import pathlib
if sys.version_info < (3, 7): if sys.version_info < (3, 7):
from collections import OrderedDict from collections import OrderedDict
@ -105,13 +106,12 @@ class CompleteDirs(zipfile.ZipFile):
if not isinstance(source, zipfile.ZipFile): if not isinstance(source, zipfile.ZipFile):
return cls(_pathlib_compat(source)) return cls(_pathlib_compat(source))
# Only allow for FastPath when supplied zipfile is read-only # Only allow for FastLookup when supplied zipfile is read-only
if 'r' not in source.mode: if 'r' not in source.mode:
cls = CompleteDirs cls = CompleteDirs
res = cls.__new__(cls) source.__class__ = cls
vars(res).update(vars(source)) return source
return res
class FastLookup(CompleteDirs): class FastLookup(CompleteDirs):
@ -119,6 +119,7 @@ class FastLookup(CompleteDirs):
ZipFile subclass to ensure implicit ZipFile subclass to ensure implicit
dirs exist and are resolved rapidly. dirs exist and are resolved rapidly.
""" """
def namelist(self): def namelist(self):
with contextlib.suppress(AttributeError): with contextlib.suppress(AttributeError):
return self.__names return self.__names
@ -161,7 +162,7 @@ class Path:
>>> zf.writestr('a.txt', 'content of a') >>> zf.writestr('a.txt', 'content of a')
>>> zf.writestr('b/c.txt', 'content of c') >>> zf.writestr('b/c.txt', 'content of c')
>>> zf.writestr('b/d/e.txt', 'content of e') >>> zf.writestr('b/d/e.txt', 'content of e')
>>> zf.filename = 'abcde.zip' >>> zf.filename = 'mem/abcde.zip'
Path accepts the zipfile object itself or a filename Path accepts the zipfile object itself or a filename
@ -173,9 +174,9 @@ class Path:
>>> a, b = root.iterdir() >>> a, b = root.iterdir()
>>> a >>> a
Path('abcde.zip', 'a.txt') Path('mem/abcde.zip', 'a.txt')
>>> b >>> b
Path('abcde.zip', 'b/') Path('mem/abcde.zip', 'b/')
name property: name property:
@ -186,7 +187,7 @@ class Path:
>>> c = b / 'c.txt' >>> c = b / 'c.txt'
>>> c >>> c
Path('abcde.zip', 'b/c.txt') Path('mem/abcde.zip', 'b/c.txt')
>>> c.name >>> c.name
'c.txt' 'c.txt'
@ -204,13 +205,35 @@ class Path:
Coercion to string: Coercion to string:
>>> str(c) >>> import os
'abcde.zip/b/c.txt' >>> str(c).replace(os.sep, posixpath.sep)
'mem/abcde.zip/b/c.txt'
At the root, ``name``, ``filename``, and ``parent``
resolve to the zipfile. Note these attributes are not
valid and will raise a ``ValueError`` if the zipfile
has no filename.
>>> root.name
'abcde.zip'
>>> str(root.filename).replace(os.sep, posixpath.sep)
'mem/abcde.zip'
>>> str(root.parent)
'mem'
""" """
__repr = "{self.__class__.__name__}({self.root.filename!r}, {self.at!r})" __repr = "{self.__class__.__name__}({self.root.filename!r}, {self.at!r})"
def __init__(self, root, at=""): def __init__(self, root, at=""):
"""
Construct a Path from a ZipFile or filename.
Note: When the source is an existing ZipFile object,
its type (__class__) will be mutated to a
specialized type. If the caller wishes to retain the
original type, the caller should either create a
separate ZipFile object or pass a filename.
"""
self.root = FastLookup.make(root) self.root = FastLookup.make(root)
self.at = at self.at = at
@ -234,7 +257,11 @@ class Path:
@property @property
def name(self): def name(self):
return posixpath.basename(self.at.rstrip("/")) return pathlib.Path(self.at).name or self.filename.name
@property
def filename(self):
return pathlib.Path(self.root.filename).joinpath(self.at)
def read_text(self, *args, **kwargs): def read_text(self, *args, **kwargs):
with self.open('r', *args, **kwargs) as strm: with self.open('r', *args, **kwargs) as strm:
@ -248,13 +275,13 @@ class Path:
return posixpath.dirname(path.at.rstrip("/")) == self.at.rstrip("/") return posixpath.dirname(path.at.rstrip("/")) == self.at.rstrip("/")
def _next(self, at): def _next(self, at):
return Path(self.root, at) return self.__class__(self.root, at)
def is_dir(self): def is_dir(self):
return not self.at or self.at.endswith("/") return not self.at or self.at.endswith("/")
def is_file(self): def is_file(self):
return not self.is_dir() return self.exists() and not self.is_dir()
def exists(self): def exists(self):
return self.at in self.root._name_set() return self.at in self.root._name_set()
@ -271,14 +298,16 @@ class Path:
def __repr__(self): def __repr__(self):
return self.__repr.format(self=self) return self.__repr.format(self=self)
def joinpath(self, add): def joinpath(self, *other):
next = posixpath.join(self.at, _pathlib_compat(add)) next = posixpath.join(self.at, *map(_pathlib_compat, other))
return self._next(self.root.resolve_dir(next)) return self._next(self.root.resolve_dir(next))
__truediv__ = joinpath __truediv__ = joinpath
@property @property
def parent(self): def parent(self):
if not self.at:
return self.filename.parent
parent_at = posixpath.dirname(self.at.rstrip('/')) parent_at = posixpath.dirname(self.at.rstrip('/'))
if parent_at: if parent_at:
parent_at += '/' parent_at += '/'

Просмотреть файл

@ -21,8 +21,8 @@
"distlib": "__virtualenv__/distlib-0.3.1-py2.py3-none-any/distlib-0.3.1.dist-info", "distlib": "__virtualenv__/distlib-0.3.1-py2.py3-none-any/distlib-0.3.1.dist-info",
"filelock": "__virtualenv__/filelock-3.0.12-py3-none-any/filelock-3.0.12.dist-info", "filelock": "__virtualenv__/filelock-3.0.12-py3-none-any/filelock-3.0.12.dist-info",
"six": "__virtualenv__/six-1.15.0-py2.py3-none-any/six-1.15.0.dist-info", "six": "__virtualenv__/six-1.15.0-py2.py3-none-any/six-1.15.0.dist-info",
"importlib_metadata": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata-1.7.0.dist-info", "importlib_metadata": "__virtualenv__/importlib_metadata-3.1.1-py3-none-any/importlib_metadata-3.1.1.dist-info",
"zipp": "__virtualenv__/zipp-3.1.0-py3-none-any/zipp-3.1.0.dist-info" "zipp": "__virtualenv__/zipp-3.4.0-py3-none-any/zipp-3.4.0.dist-info"
} }
}, },
"3.6": { "3.6": {
@ -31,9 +31,9 @@
"distlib": "__virtualenv__/distlib-0.3.1-py2.py3-none-any/distlib-0.3.1.dist-info", "distlib": "__virtualenv__/distlib-0.3.1-py2.py3-none-any/distlib-0.3.1.dist-info",
"filelock": "__virtualenv__/filelock-3.0.12-py3-none-any/filelock-3.0.12.dist-info", "filelock": "__virtualenv__/filelock-3.0.12-py3-none-any/filelock-3.0.12.dist-info",
"six": "__virtualenv__/six-1.15.0-py2.py3-none-any/six-1.15.0.dist-info", "six": "__virtualenv__/six-1.15.0-py2.py3-none-any/six-1.15.0.dist-info",
"importlib_metadata": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata-1.7.0.dist-info", "importlib_metadata": "__virtualenv__/importlib_metadata-3.1.1-py3-none-any/importlib_metadata-3.1.1.dist-info",
"zipp": "__virtualenv__/zipp-3.1.0-py3-none-any/zipp-3.1.0.dist-info", "zipp": "__virtualenv__/zipp-3.4.0-py3-none-any/zipp-3.4.0.dist-info",
"importlib_resources": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources-3.0.0.dist-info" "importlib_resources": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources-3.3.0.dist-info"
} }
}, },
"3.5": { "3.5": {
@ -42,9 +42,9 @@
"distlib": "__virtualenv__/distlib-0.3.1-py2.py3-none-any/distlib-0.3.1.dist-info", "distlib": "__virtualenv__/distlib-0.3.1-py2.py3-none-any/distlib-0.3.1.dist-info",
"filelock": "__virtualenv__/filelock-3.0.12-py3-none-any/filelock-3.0.12.dist-info", "filelock": "__virtualenv__/filelock-3.0.12-py3-none-any/filelock-3.0.12.dist-info",
"six": "__virtualenv__/six-1.15.0-py2.py3-none-any/six-1.15.0.dist-info", "six": "__virtualenv__/six-1.15.0-py2.py3-none-any/six-1.15.0.dist-info",
"importlib_metadata": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata-1.7.0.dist-info", "importlib_metadata": "__virtualenv__/importlib_metadata-2.1.1-py2.py3-none-any/importlib_metadata-2.1.1.dist-info",
"zipp": "__virtualenv__/zipp-1.2.0-py2.py3-none-any/zipp-1.2.0.dist-info", "zipp": "__virtualenv__/zipp-1.2.0-py2.py3-none-any/zipp-1.2.0.dist-info",
"importlib_resources": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources-3.0.0.dist-info" "importlib_resources": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources-3.2.1.dist-info"
} }
}, },
"3.4": { "3.4": {
@ -58,7 +58,7 @@
"importlib_resources": "__virtualenv__/importlib_resources-1.0.2-py2.py3-none-any/importlib_resources-1.0.2.dist-info", "importlib_resources": "__virtualenv__/importlib_resources-1.0.2-py2.py3-none-any/importlib_resources-1.0.2.dist-info",
"typing": "__virtualenv__/typing-3.7.4.1-py3-none-any/typing-3.7.4.1.dist-info", "typing": "__virtualenv__/typing-3.7.4.1-py3-none-any/typing-3.7.4.1.dist-info",
"pathlib2": "__virtualenv__/pathlib2-2.3.5-py2.py3-none-any/pathlib2-2.3.5.dist-info", "pathlib2": "__virtualenv__/pathlib2-2.3.5-py2.py3-none-any/pathlib2-2.3.5.dist-info",
"scandir": "__virtualenv__/scandir-1.10.0-cp38-cp38-macosx_10_15_x86_64/scandir-1.10.0.dist-info" "scandir": "__virtualenv__/scandir-1.10.0-cp39-cp39-macosx_10_15_x86_64/scandir-1.10.0.dist-info"
} }
}, },
"2.7": { "2.7": {
@ -72,7 +72,7 @@
"importlib_resources": "__virtualenv__/importlib_resources-1.0.2-py2.py3-none-any/importlib_resources-1.0.2.dist-info", "importlib_resources": "__virtualenv__/importlib_resources-1.0.2-py2.py3-none-any/importlib_resources-1.0.2.dist-info",
"typing": "__virtualenv__/typing-3.7.4.3-py2-none-any/typing-3.7.4.3.dist-info", "typing": "__virtualenv__/typing-3.7.4.3-py2-none-any/typing-3.7.4.3.dist-info",
"pathlib2": "__virtualenv__/pathlib2-2.3.5-py2.py3-none-any/pathlib2-2.3.5.dist-info", "pathlib2": "__virtualenv__/pathlib2-2.3.5-py2.py3-none-any/pathlib2-2.3.5.dist-info",
"scandir": "__virtualenv__/scandir-1.10.0-cp38-cp38-macosx_10_15_x86_64/scandir-1.10.0.dist-info", "scandir": "__virtualenv__/scandir-1.10.0-cp39-cp39-macosx_10_15_x86_64/scandir-1.10.0.dist-info",
"contextlib2": "__virtualenv__/contextlib2-0.6.0.post1-py2.py3-none-any/contextlib2-0.6.0.post1.dist-info", "contextlib2": "__virtualenv__/contextlib2-0.6.0.post1-py2.py3-none-any/contextlib2-0.6.0.post1.dist-info",
"configparser": "__virtualenv__/configparser-4.0.2-py2.py3-none-any/configparser-4.0.2.dist-info" "configparser": "__virtualenv__/configparser-4.0.2-py2.py3-none-any/configparser-4.0.2.dist-info"
}, },

147
third_party/python/virtualenv/modules.json поставляемый
Просмотреть файл

@ -72,18 +72,9 @@
"distlib._backport.tarfile": "__virtualenv__/distlib-0.3.1-py2.py3-none-any/distlib/_backport/tarfile.py", "distlib._backport.tarfile": "__virtualenv__/distlib-0.3.1-py2.py3-none-any/distlib/_backport/tarfile.py",
"filelock": "__virtualenv__/filelock-3.0.12-py3-none-any/filelock.py", "filelock": "__virtualenv__/filelock-3.0.12-py3-none-any/filelock.py",
"six": "__virtualenv__/six-1.15.0-py2.py3-none-any/six.py", "six": "__virtualenv__/six-1.15.0-py2.py3-none-any/six.py",
"importlib_metadata": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/__init__.py", "importlib_metadata": "__virtualenv__/importlib_metadata-3.1.1-py3-none-any/importlib_metadata/__init__.py",
"importlib_metadata._compat": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/_compat.py", "importlib_metadata._compat": "__virtualenv__/importlib_metadata-3.1.1-py3-none-any/importlib_metadata/_compat.py",
"importlib_metadata.docs": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/docs/__init__.py", "zipp": "__virtualenv__/zipp-3.4.0-py3-none-any/zipp.py"
"importlib_metadata.docs.conf": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/docs/conf.py",
"importlib_metadata.tests": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/__init__.py",
"importlib_metadata.tests.fixtures": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/fixtures.py",
"importlib_metadata.tests.test_api": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/test_api.py",
"importlib_metadata.tests.test_integration": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/test_integration.py",
"importlib_metadata.tests.test_main": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/test_main.py",
"importlib_metadata.tests.test_zip": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/test_zip.py",
"importlib_metadata.tests.data": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/data/__init__.py",
"zipp": "__virtualenv__/zipp-3.1.0-py3-none-any/zipp.py"
} }
}, },
"3.6": { "3.6": {
@ -109,43 +100,34 @@
"distlib._backport.tarfile": "__virtualenv__/distlib-0.3.1-py2.py3-none-any/distlib/_backport/tarfile.py", "distlib._backport.tarfile": "__virtualenv__/distlib-0.3.1-py2.py3-none-any/distlib/_backport/tarfile.py",
"filelock": "__virtualenv__/filelock-3.0.12-py3-none-any/filelock.py", "filelock": "__virtualenv__/filelock-3.0.12-py3-none-any/filelock.py",
"six": "__virtualenv__/six-1.15.0-py2.py3-none-any/six.py", "six": "__virtualenv__/six-1.15.0-py2.py3-none-any/six.py",
"importlib_metadata": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/__init__.py", "importlib_metadata": "__virtualenv__/importlib_metadata-3.1.1-py3-none-any/importlib_metadata/__init__.py",
"importlib_metadata._compat": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/_compat.py", "importlib_metadata._compat": "__virtualenv__/importlib_metadata-3.1.1-py3-none-any/importlib_metadata/_compat.py",
"importlib_metadata.docs": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/docs/__init__.py", "zipp": "__virtualenv__/zipp-3.4.0-py3-none-any/zipp.py",
"importlib_metadata.docs.conf": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/docs/conf.py", "importlib_resources": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/__init__.py",
"importlib_metadata.tests": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/__init__.py", "importlib_resources._common": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/_common.py",
"importlib_metadata.tests.fixtures": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/fixtures.py", "importlib_resources._compat": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/_compat.py",
"importlib_metadata.tests.test_api": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/test_api.py", "importlib_resources._py2": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/_py2.py",
"importlib_metadata.tests.test_integration": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/test_integration.py", "importlib_resources._py3": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/_py3.py",
"importlib_metadata.tests.test_main": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/test_main.py", "importlib_resources.abc": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/abc.py",
"importlib_metadata.tests.test_zip": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/test_zip.py", "importlib_resources.readers": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/readers.py",
"importlib_metadata.tests.data": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/data/__init__.py", "importlib_resources.trees": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/trees.py",
"zipp": "__virtualenv__/zipp-3.1.0-py3-none-any/zipp.py", "importlib_resources.tests": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/__init__.py",
"importlib_resources": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/__init__.py", "importlib_resources.tests._compat": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/_compat.py",
"importlib_resources._common": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/_common.py", "importlib_resources.tests.py27compat": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/py27compat.py",
"importlib_resources._compat": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/_compat.py", "importlib_resources.tests.test_files": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/test_files.py",
"importlib_resources._py2": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/_py2.py", "importlib_resources.tests.test_open": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/test_open.py",
"importlib_resources._py3": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/_py3.py", "importlib_resources.tests.test_path": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/test_path.py",
"importlib_resources.abc": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/abc.py", "importlib_resources.tests.test_read": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/test_read.py",
"importlib_resources.readers": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/readers.py", "importlib_resources.tests.test_reader": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/test_reader.py",
"importlib_resources.trees": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/trees.py", "importlib_resources.tests.test_resource": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/test_resource.py",
"importlib_resources.tests": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/__init__.py", "importlib_resources.tests.util": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/util.py",
"importlib_resources.tests.test_files": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/test_files.py", "importlib_resources.tests.data01": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/data01/__init__.py",
"importlib_resources.tests.test_open": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/test_open.py", "importlib_resources.tests.data01.subdirectory": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/data01/subdirectory/__init__.py",
"importlib_resources.tests.test_path": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/test_path.py", "importlib_resources.tests.data02": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/data02/__init__.py",
"importlib_resources.tests.test_read": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/test_read.py", "importlib_resources.tests.data02.one": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/data02/one/__init__.py",
"importlib_resources.tests.test_resource": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/test_resource.py", "importlib_resources.tests.data02.two": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/data02/two/__init__.py",
"importlib_resources.tests.util": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/util.py", "importlib_resources.tests.zipdata01": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/zipdata01/__init__.py",
"importlib_resources.tests.data01": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data01/__init__.py", "importlib_resources.tests.zipdata02": "__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/tests/zipdata02/__init__.py"
"importlib_resources.tests.data01.subdirectory": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data01/subdirectory/__init__.py",
"importlib_resources.tests.data02": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data02/__init__.py",
"importlib_resources.tests.data02.one": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data02/one/__init__.py",
"importlib_resources.tests.data02.two": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data02/two/__init__.py",
"importlib_resources.tests.data03": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data03/__init__.py",
"importlib_resources.tests.data03.namespace.portion1": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data03/namespace/portion1/__init__.py",
"importlib_resources.tests.data03.namespace.portion2": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data03/namespace/portion2/__init__.py",
"importlib_resources.tests.zipdata01": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/zipdata01/__init__.py",
"importlib_resources.tests.zipdata02": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/zipdata02/__init__.py"
} }
}, },
"3.5": { "3.5": {
@ -171,43 +153,34 @@
"distlib._backport.tarfile": "__virtualenv__/distlib-0.3.1-py2.py3-none-any/distlib/_backport/tarfile.py", "distlib._backport.tarfile": "__virtualenv__/distlib-0.3.1-py2.py3-none-any/distlib/_backport/tarfile.py",
"filelock": "__virtualenv__/filelock-3.0.12-py3-none-any/filelock.py", "filelock": "__virtualenv__/filelock-3.0.12-py3-none-any/filelock.py",
"six": "__virtualenv__/six-1.15.0-py2.py3-none-any/six.py", "six": "__virtualenv__/six-1.15.0-py2.py3-none-any/six.py",
"importlib_metadata": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/__init__.py", "importlib_metadata": "__virtualenv__/importlib_metadata-2.1.1-py2.py3-none-any/importlib_metadata/__init__.py",
"importlib_metadata._compat": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/_compat.py", "importlib_metadata._compat": "__virtualenv__/importlib_metadata-2.1.1-py2.py3-none-any/importlib_metadata/_compat.py",
"importlib_metadata.docs": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/docs/__init__.py",
"importlib_metadata.docs.conf": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/docs/conf.py",
"importlib_metadata.tests": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/__init__.py",
"importlib_metadata.tests.fixtures": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/fixtures.py",
"importlib_metadata.tests.test_api": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/test_api.py",
"importlib_metadata.tests.test_integration": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/test_integration.py",
"importlib_metadata.tests.test_main": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/test_main.py",
"importlib_metadata.tests.test_zip": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/test_zip.py",
"importlib_metadata.tests.data": "__virtualenv__/importlib_metadata-1.7.0-py2.py3-none-any/importlib_metadata/tests/data/__init__.py",
"zipp": "__virtualenv__/zipp-1.2.0-py2.py3-none-any/zipp.py", "zipp": "__virtualenv__/zipp-1.2.0-py2.py3-none-any/zipp.py",
"importlib_resources": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/__init__.py", "importlib_resources": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/__init__.py",
"importlib_resources._common": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/_common.py", "importlib_resources._common": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/_common.py",
"importlib_resources._compat": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/_compat.py", "importlib_resources._compat": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/_compat.py",
"importlib_resources._py2": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/_py2.py", "importlib_resources._py2": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/_py2.py",
"importlib_resources._py3": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/_py3.py", "importlib_resources._py3": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/_py3.py",
"importlib_resources.abc": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/abc.py", "importlib_resources.abc": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/abc.py",
"importlib_resources.readers": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/readers.py", "importlib_resources.readers": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/readers.py",
"importlib_resources.trees": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/trees.py", "importlib_resources.trees": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/trees.py",
"importlib_resources.tests": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/__init__.py", "importlib_resources.tests": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/__init__.py",
"importlib_resources.tests.test_files": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/test_files.py", "importlib_resources.tests._compat": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/_compat.py",
"importlib_resources.tests.test_open": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/test_open.py", "importlib_resources.tests.py27compat": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/py27compat.py",
"importlib_resources.tests.test_path": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/test_path.py", "importlib_resources.tests.test_files": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/test_files.py",
"importlib_resources.tests.test_read": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/test_read.py", "importlib_resources.tests.test_open": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/test_open.py",
"importlib_resources.tests.test_resource": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/test_resource.py", "importlib_resources.tests.test_path": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/test_path.py",
"importlib_resources.tests.util": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/util.py", "importlib_resources.tests.test_read": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/test_read.py",
"importlib_resources.tests.data01": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data01/__init__.py", "importlib_resources.tests.test_reader": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/test_reader.py",
"importlib_resources.tests.data01.subdirectory": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data01/subdirectory/__init__.py", "importlib_resources.tests.test_resource": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/test_resource.py",
"importlib_resources.tests.data02": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data02/__init__.py", "importlib_resources.tests.util": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/util.py",
"importlib_resources.tests.data02.one": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data02/one/__init__.py", "importlib_resources.tests.data01": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/data01/__init__.py",
"importlib_resources.tests.data02.two": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data02/two/__init__.py", "importlib_resources.tests.data01.subdirectory": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/data01/subdirectory/__init__.py",
"importlib_resources.tests.data03": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data03/__init__.py", "importlib_resources.tests.data02": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/data02/__init__.py",
"importlib_resources.tests.data03.namespace.portion1": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data03/namespace/portion1/__init__.py", "importlib_resources.tests.data02.one": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/data02/one/__init__.py",
"importlib_resources.tests.data03.namespace.portion2": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/data03/namespace/portion2/__init__.py", "importlib_resources.tests.data02.two": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/data02/two/__init__.py",
"importlib_resources.tests.zipdata01": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/zipdata01/__init__.py", "importlib_resources.tests.zipdata01": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/zipdata01/__init__.py",
"importlib_resources.tests.zipdata02": "__virtualenv__/importlib_resources-3.0.0-py2.py3-none-any/importlib_resources/tests/zipdata02/__init__.py" "importlib_resources.tests.zipdata02": "__virtualenv__/importlib_resources-3.2.1-py2.py3-none-any/importlib_resources/tests/zipdata02/__init__.py"
} }
}, },
"3.4": { "3.4": {
@ -267,7 +240,7 @@
"importlib_resources.tests.zipdata02": "__virtualenv__/importlib_resources-1.0.2-py2.py3-none-any/importlib_resources/tests/zipdata02/__init__.py", "importlib_resources.tests.zipdata02": "__virtualenv__/importlib_resources-1.0.2-py2.py3-none-any/importlib_resources/tests/zipdata02/__init__.py",
"typing": "__virtualenv__/typing-3.7.4.1-py3-none-any/typing.py", "typing": "__virtualenv__/typing-3.7.4.1-py3-none-any/typing.py",
"pathlib2": "__virtualenv__/pathlib2-2.3.5-py2.py3-none-any/pathlib2/__init__.py", "pathlib2": "__virtualenv__/pathlib2-2.3.5-py2.py3-none-any/pathlib2/__init__.py",
"scandir": "__virtualenv__/scandir-1.10.0-cp38-cp38-macosx_10_15_x86_64/scandir.py" "scandir": "__virtualenv__/scandir-1.10.0-cp39-cp39-macosx_10_15_x86_64/scandir.py"
} }
}, },
"2.7": { "2.7": {
@ -327,7 +300,7 @@
"importlib_resources.tests.zipdata02": "__virtualenv__/importlib_resources-1.0.2-py2.py3-none-any/importlib_resources/tests/zipdata02/__init__.py", "importlib_resources.tests.zipdata02": "__virtualenv__/importlib_resources-1.0.2-py2.py3-none-any/importlib_resources/tests/zipdata02/__init__.py",
"typing": "__virtualenv__/typing-3.7.4.3-py2-none-any/typing.py", "typing": "__virtualenv__/typing-3.7.4.3-py2-none-any/typing.py",
"pathlib2": "__virtualenv__/pathlib2-2.3.5-py2.py3-none-any/pathlib2/__init__.py", "pathlib2": "__virtualenv__/pathlib2-2.3.5-py2.py3-none-any/pathlib2/__init__.py",
"scandir": "__virtualenv__/scandir-1.10.0-cp38-cp38-macosx_10_15_x86_64/scandir.py", "scandir": "__virtualenv__/scandir-1.10.0-cp39-cp39-macosx_10_15_x86_64/scandir.py",
"contextlib2": "__virtualenv__/contextlib2-0.6.0.post1-py2.py3-none-any/contextlib2.py", "contextlib2": "__virtualenv__/contextlib2-0.6.0.post1-py2.py3-none-any/contextlib2.py",
"configparser": "__virtualenv__/configparser-4.0.2-py2.py3-none-any/configparser.py", "configparser": "__virtualenv__/configparser-4.0.2-py2.py3-none-any/configparser.py",
"backports": "__virtualenv__/configparser-4.0.2-py2.py3-none-any/backports/__init__.py", "backports": "__virtualenv__/configparser-4.0.2-py2.py3-none-any/backports/__init__.py",

Просмотреть файл

@ -1,6 +1,6 @@
Metadata-Version: 2.1 Metadata-Version: 2.1
Name: virtualenv Name: virtualenv
Version: 20.0.31 Version: 20.2.2
Summary: Virtual Python Environment builder Summary: Virtual Python Environment builder
Home-page: https://virtualenv.pypa.io/ Home-page: https://virtualenv.pypa.io/
Author: Bernat Gabor Author: Bernat Gabor
@ -26,6 +26,7 @@ Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Software Development :: Libraries Classifier: Topic :: Software Development :: Libraries
@ -39,7 +40,7 @@ Requires-Dist: filelock (<4,>=3.0.0)
Requires-Dist: six (<2,>=1.9.0) Requires-Dist: six (<2,>=1.9.0)
Requires-Dist: pathlib2 (<3,>=2.3.3) ; python_version < "3.4" and sys_platform != "win32" Requires-Dist: pathlib2 (<3,>=2.3.3) ; python_version < "3.4" and sys_platform != "win32"
Requires-Dist: importlib-resources (>=1.0) ; python_version < "3.7" Requires-Dist: importlib-resources (>=1.0) ; python_version < "3.7"
Requires-Dist: importlib-metadata (<2,>=0.12) ; python_version < "3.8" Requires-Dist: importlib-metadata (>=0.12) ; python_version < "3.8"
Provides-Extra: docs Provides-Extra: docs
Requires-Dist: proselint (>=0.10.2) ; extra == 'docs' Requires-Dist: proselint (>=0.10.2) ; extra == 'docs'
Requires-Dist: sphinx (>=3) ; extra == 'docs' Requires-Dist: sphinx (>=3) ; extra == 'docs'
@ -47,7 +48,7 @@ Requires-Dist: sphinx-argparse (>=0.2.5) ; extra == 'docs'
Requires-Dist: sphinx-rtd-theme (>=0.4.3) ; extra == 'docs' Requires-Dist: sphinx-rtd-theme (>=0.4.3) ; extra == 'docs'
Requires-Dist: towncrier (>=19.9.0rc1) ; extra == 'docs' Requires-Dist: towncrier (>=19.9.0rc1) ; extra == 'docs'
Provides-Extra: testing Provides-Extra: testing
Requires-Dist: coverage (>=5) ; extra == 'testing' Requires-Dist: coverage (>=4) ; extra == 'testing'
Requires-Dist: coverage-enable-subprocess (>=1) ; extra == 'testing' Requires-Dist: coverage-enable-subprocess (>=1) ; extra == 'testing'
Requires-Dist: flaky (>=3) ; extra == 'testing' Requires-Dist: flaky (>=3) ; extra == 'testing'
Requires-Dist: pytest (>=4) ; extra == 'testing' Requires-Dist: pytest (>=4) ; extra == 'testing'
@ -69,8 +70,8 @@ Requires-Dist: xonsh (>=0.9.16) ; (python_version > "3.4" and python_version !=
[![Gitter Chat](https://img.shields.io/gitter/room/pypa/virtualenv?color=FF004F&style=flat-square)](https://gitter.im/pypa/virtualenv) [![Gitter Chat](https://img.shields.io/gitter/room/pypa/virtualenv?color=FF004F&style=flat-square)](https://gitter.im/pypa/virtualenv)
[![PyPI - Downloads](https://img.shields.io/pypi/dm/virtualenv?style=flat-square)](https://pypistats.org/packages/virtualenv) [![PyPI - Downloads](https://img.shields.io/pypi/dm/virtualenv?style=flat-square)](https://pypistats.org/packages/virtualenv)
[![PyPI - License](https://img.shields.io/pypi/l/virtualenv?style=flat-square)](https://opensource.org/licenses/MIT) [![PyPI - License](https://img.shields.io/pypi/l/virtualenv?style=flat-square)](https://opensource.org/licenses/MIT)
[![Build Status](https://github.com/pypa/virtualenv/workflows/check/badge.svg?branch=master&event=push)](https://github.com/pypa/virtualenv/actions?query=workflow%3Acheck) [![Build Status](https://github.com/pypa/virtualenv/workflows/check/badge.svg?branch=main&event=push)](https://github.com/pypa/virtualenv/actions?query=workflow%3Acheck)
[![codecov](https://codecov.io/gh/pypa/virtualenv/branch/master/graph/badge.svg)](https://codecov.io/gh/pypa/virtualenv) [![codecov](https://codecov.io/gh/pypa/virtualenv/branch/main/graph/badge.svg)](https://codecov.io/gh/pypa/virtualenv)
[![Code style: [![Code style:
black](https://img.shields.io/badge/code%20style-black-000000.svg?style=flat-square)](https://github.com/psf/black) black](https://img.shields.io/badge/code%20style-black-000000.svg?style=flat-square)](https://github.com/psf/black)

Просмотреть файл

@ -2,12 +2,12 @@ virtualenv/__init__.py,sha256=SMvpjz4VJ3vJ_yfDDPzJAdi2GJOYd_UBXXuvImO07gk,205
virtualenv/__main__.py,sha256=QMwDqrR4QbhEivl8yoRmAr6G1BY92gr4n1ConcDIxc4,2770 virtualenv/__main__.py,sha256=QMwDqrR4QbhEivl8yoRmAr6G1BY92gr4n1ConcDIxc4,2770
virtualenv/info.py,sha256=-2pI_kyC9fNj5OR8AQWkKjlpOk4_96Lmbco3atYYBdY,1921 virtualenv/info.py,sha256=-2pI_kyC9fNj5OR8AQWkKjlpOk4_96Lmbco3atYYBdY,1921
virtualenv/report.py,sha256=M2OHHCWdOHZsn74tj1MYYKmaI3QRJF8VA1FZIdkQTMQ,1594 virtualenv/report.py,sha256=M2OHHCWdOHZsn74tj1MYYKmaI3QRJF8VA1FZIdkQTMQ,1594
virtualenv/version.py,sha256=3ieAw0XY11zpShwBdavzQZAO60AeVi5FVy0KWrcxwUY,66 virtualenv/version.py,sha256=T9L0FIrWWe1IEvi_PNtZQcEIf_WbHAtFeLA1_hwZ07I,65
virtualenv/activation/__init__.py,sha256=jLIERxJXMnHq2fH49RdWqBoaiASres4CTKMdUJOeos0,480 virtualenv/activation/__init__.py,sha256=jLIERxJXMnHq2fH49RdWqBoaiASres4CTKMdUJOeos0,480
virtualenv/activation/activator.py,sha256=CXomkRvhzcAeygYlDwQdDjfPyZQG85aBab5GIVQPv2M,1341 virtualenv/activation/activator.py,sha256=CXomkRvhzcAeygYlDwQdDjfPyZQG85aBab5GIVQPv2M,1341
virtualenv/activation/via_template.py,sha256=B88RGc0qoGc46DmKJmLJuzcCJU_iXWhdD93r6KLuYHQ,2204 virtualenv/activation/via_template.py,sha256=U8LgH-lyTjXIQBUdbd0xOZpXNICpiKhsfpiZwzQg7tU,2372
virtualenv/activation/bash/__init__.py,sha256=7aC1WfvyzgFrIQs13jOuESuAbuiAnTsKkOe0iReRoaE,312 virtualenv/activation/bash/__init__.py,sha256=7aC1WfvyzgFrIQs13jOuESuAbuiAnTsKkOe0iReRoaE,312
virtualenv/activation/bash/activate.sh,sha256=xkIDykLyI5CO3K7eeAujgPiBP2eleYDTFsqhaXsOUG4,2249 virtualenv/activation/bash/activate.sh,sha256=aHia5vyXg2JwymkvRXCp29Aswcg88Mz5UrssXbX9Jjc,2398
virtualenv/activation/batch/__init__.py,sha256=K0gVfwuXV7uoaMDL7moWGCq7uTDzI64giZzQQ8s2qnU,733 virtualenv/activation/batch/__init__.py,sha256=K0gVfwuXV7uoaMDL7moWGCq7uTDzI64giZzQQ8s2qnU,733
virtualenv/activation/batch/activate.bat,sha256=PeQnWWsjvHT-jIWhYI7hbdzkDBZx5UOstnsCmq5PYtw,1031 virtualenv/activation/batch/activate.bat,sha256=PeQnWWsjvHT-jIWhYI7hbdzkDBZx5UOstnsCmq5PYtw,1031
virtualenv/activation/batch/deactivate.bat,sha256=6OznnO-HC2wnWUN7YAT-bj815zeKMXEPC0keyBYwKUU,510 virtualenv/activation/batch/deactivate.bat,sha256=6OznnO-HC2wnWUN7YAT-bj815zeKMXEPC0keyBYwKUU,510
@ -17,104 +17,106 @@ virtualenv/activation/cshell/activate.csh,sha256=jYwms8OTiVu9MJwXltuEm43HU09BJUq
virtualenv/activation/fish/__init__.py,sha256=hDkJq1P1wK2qm6BXydXWA9GMkBpj-TaejbKSceFnGZU,251 virtualenv/activation/fish/__init__.py,sha256=hDkJq1P1wK2qm6BXydXWA9GMkBpj-TaejbKSceFnGZU,251
virtualenv/activation/fish/activate.fish,sha256=V7nVwSI_nsFEMlJjSQxCayNWkjubXi1KSgSw1bEakh8,3099 virtualenv/activation/fish/activate.fish,sha256=V7nVwSI_nsFEMlJjSQxCayNWkjubXi1KSgSw1bEakh8,3099
virtualenv/activation/powershell/__init__.py,sha256=EA-73s5TUMkgxAhLwucFg3gsBwW5huNh7qB4I7uEU-U,256 virtualenv/activation/powershell/__init__.py,sha256=EA-73s5TUMkgxAhLwucFg3gsBwW5huNh7qB4I7uEU-U,256
virtualenv/activation/powershell/activate.ps1,sha256=qXTD2IZIPXIr3HZbNahnym8l3FFwa1o_pyB8cSmxeg0,1867 virtualenv/activation/powershell/activate.ps1,sha256=jVw_FwfVJzcByQ3Sku-wlnOo_a0-OSpAQ8R17kXVgIM,1807
virtualenv/activation/python/__init__.py,sha256=Uv53LqOrIT_2dO1FXcUYAnwH1eypG8CJ2InhSx1GRI4,1323 virtualenv/activation/python/__init__.py,sha256=Uv53LqOrIT_2dO1FXcUYAnwH1eypG8CJ2InhSx1GRI4,1323
virtualenv/activation/python/activate_this.py,sha256=Xpz7exdGSjmWk0KfwHLofIpDPUtazNSNGrxT0-5ZG_s,1208 virtualenv/activation/python/activate_this.py,sha256=Xpz7exdGSjmWk0KfwHLofIpDPUtazNSNGrxT0-5ZG_s,1208
virtualenv/activation/xonsh/__init__.py,sha256=7NUevd5EpHRMZdSyR1KgFTe9QQBO94zZOwFH6MR6zjo,355 virtualenv/activation/xonsh/__init__.py,sha256=7NUevd5EpHRMZdSyR1KgFTe9QQBO94zZOwFH6MR6zjo,355
virtualenv/activation/xonsh/activate.xsh,sha256=qkKgWfrUjYKrgrmhf45VuBz99EMadtiNU8GMfHZZ7AU,1172 virtualenv/activation/xonsh/activate.xsh,sha256=qkKgWfrUjYKrgrmhf45VuBz99EMadtiNU8GMfHZZ7AU,1172
virtualenv/app_data/__init__.py,sha256=mOgHrNxZ320NcDvl2EU9Uhaq9XSwnJwkldKAWtrMCKo,1882 virtualenv/app_data/__init__.py,sha256=nwgqY-Our_SYcDisLfRLmWrTSPytDkjck9-lzg-pOI8,1462
virtualenv/app_data/base.py,sha256=wtoduyV2lc020XNdOwt5gu1lkUJd0n_LMrgT8nifAwo,2054 virtualenv/app_data/base.py,sha256=dbS5Maob1-Cqs6EVqTmmbjAGeNYA1iw3pmdgYPWCJak,2129
virtualenv/app_data/na.py,sha256=fCISMfJt3opkAqCmJBZTW9tody6ECfVPXtSrY5ZJueY,1321 virtualenv/app_data/na.py,sha256=iMRVpCe4m5Q5WM5bC3ee1wYyfkfHvkcQ-8tgIw4druc,1306
virtualenv/app_data/via_disk_folder.py,sha256=bJxZIXTAqQekwRZuoYgAE1fvwQ6w1dBR2IJFe09OIjE,5404 virtualenv/app_data/read_only.py,sha256=MD-4Bl2SZZiGw0g8qZy0YLBGZGCuFYXnAEvWboF1PSc,1006
virtualenv/app_data/via_tempdir.py,sha256=vt4I1wAaNouOeFSTFX5DPbA3zPZ1ikVGzXBDsNLNHRM,771 virtualenv/app_data/via_disk_folder.py,sha256=CdNXQkenyH178MtSs2Ve6uDUs30-oZpkOz_1guTtTz0,5597
virtualenv/app_data/via_tempdir.py,sha256=Z_-PoU7qeZe-idzi3nqys4FX0rfsRgOQ9_7XwX3hxSA,770
virtualenv/config/__init__.py,sha256=8ArZTco6Meo0W9i4dqnwmDO8BJYTaHX7oQx1o06vCm4,57 virtualenv/config/__init__.py,sha256=8ArZTco6Meo0W9i4dqnwmDO8BJYTaHX7oQx1o06vCm4,57
virtualenv/config/convert.py,sha256=msrkiG2Vq9gYQXf1C5W4n3b0ZTv6weFANV-mLUq6uMo,2091 virtualenv/config/convert.py,sha256=WYGjMRKVriZkfTH3z1fI0sDQRZxCxAedqWbOGsaquyg,2693
virtualenv/config/env_var.py,sha256=48XpOurSLLjMX-kXjvOpZuAoOUP-LvnbotTlmebhhFk,844 virtualenv/config/env_var.py,sha256=48XpOurSLLjMX-kXjvOpZuAoOUP-LvnbotTlmebhhFk,844
virtualenv/config/ini.py,sha256=neMqXrA6IOkLF_M_MCQWQSeqNm4CT8tj_h3GdbJv1Cg,2783 virtualenv/config/ini.py,sha256=neMqXrA6IOkLF_M_MCQWQSeqNm4CT8tj_h3GdbJv1Cg,2783
virtualenv/config/cli/__init__.py,sha256=8ArZTco6Meo0W9i4dqnwmDO8BJYTaHX7oQx1o06vCm4,57 virtualenv/config/cli/__init__.py,sha256=8ArZTco6Meo0W9i4dqnwmDO8BJYTaHX7oQx1o06vCm4,57
virtualenv/config/cli/parser.py,sha256=y5IqHccLBqFpocpE75X611nVrP8v394VW94a9GAojvE,4524 virtualenv/config/cli/parser.py,sha256=y5IqHccLBqFpocpE75X611nVrP8v394VW94a9GAojvE,4524
virtualenv/create/__init__.py,sha256=8ArZTco6Meo0W9i4dqnwmDO8BJYTaHX7oQx1o06vCm4,57 virtualenv/create/__init__.py,sha256=8ArZTco6Meo0W9i4dqnwmDO8BJYTaHX7oQx1o06vCm4,57
virtualenv/create/creator.py,sha256=D2YsK817anGhHxjh_ew7MlRCGjPPzW95lroRPlzblGk,8437 virtualenv/create/creator.py,sha256=4jxxEGXCWd6tInT37QNt-13_yDtcIJdPB6EkoYzDkbM,8889
virtualenv/create/debug.py,sha256=ETOke8w4Ib8fiufAHVeOkH3v0zrztljw3WjGvZyE0Mk,3342 virtualenv/create/debug.py,sha256=ETOke8w4Ib8fiufAHVeOkH3v0zrztljw3WjGvZyE0Mk,3342
virtualenv/create/describe.py,sha256=bm0V2wpFOjdN_MkzZuJAEBSttmi5YGPVwxtwGYU5zQU,3561 virtualenv/create/describe.py,sha256=bm0V2wpFOjdN_MkzZuJAEBSttmi5YGPVwxtwGYU5zQU,3561
virtualenv/create/pyenv_cfg.py,sha256=VsOGfzUpaVCO3J29zrhIeip4jZ4b7llbe45iOQAIRGg,1717 virtualenv/create/pyenv_cfg.py,sha256=VsOGfzUpaVCO3J29zrhIeip4jZ4b7llbe45iOQAIRGg,1717
virtualenv/create/via_global_ref/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 virtualenv/create/via_global_ref/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
virtualenv/create/via_global_ref/_virtualenv.py,sha256=aEuMB5MrpKhKwuWumv5J7wTpK6w9jUGR1FXPCdCT5fw,5662 virtualenv/create/via_global_ref/_virtualenv.py,sha256=aEuMB5MrpKhKwuWumv5J7wTpK6w9jUGR1FXPCdCT5fw,5662
virtualenv/create/via_global_ref/api.py,sha256=uAQjwBRJ-u4d6A24QuxeB-khIrSGiP7-W_SQxNdE-Sk,4277 virtualenv/create/via_global_ref/api.py,sha256=5MPq3XJBuUOBj53oIigeWWPm68M-J_E644WWbz37qOU,4357
virtualenv/create/via_global_ref/store.py,sha256=cqLBEhQ979xHnlidqmxlDjsvj2Wr-mBo7shvGQSEBxU,685 virtualenv/create/via_global_ref/store.py,sha256=cqLBEhQ979xHnlidqmxlDjsvj2Wr-mBo7shvGQSEBxU,685
virtualenv/create/via_global_ref/venv.py,sha256=A6XrGu3oco_ZIHv0s-TybW7lErAomgLOYDMtgpdACc0,2919 virtualenv/create/via_global_ref/venv.py,sha256=p5RkDcXhr1pmOwnl1dpS06UYHmfNVy2ld4sTwsYjYWU,2955
virtualenv/create/via_global_ref/builtin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 virtualenv/create/via_global_ref/builtin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
virtualenv/create/via_global_ref/builtin/builtin_way.py,sha256=hO22nT-itVoYiy8wXrXXYzHw86toCp_Uq-cURR7w6ck,546 virtualenv/create/via_global_ref/builtin/builtin_way.py,sha256=hO22nT-itVoYiy8wXrXXYzHw86toCp_Uq-cURR7w6ck,546
virtualenv/create/via_global_ref/builtin/ref.py,sha256=-r9sJSW9X9rHxThk2yyJJRA5KkmJPW_axuffYBsFDIU,5501 virtualenv/create/via_global_ref/builtin/ref.py,sha256=xCTICJhE-OiopBxl6ymo1P1NqgK3KEF8ZUOtQDtDTVA,5477
virtualenv/create/via_global_ref/builtin/via_global_self_do.py,sha256=9aH07lmA6SMvtynv7ZTO6Gh2aDDFdUiDQrlbtT9xze4,4057 virtualenv/create/via_global_ref/builtin/via_global_self_do.py,sha256=d569fX7fjq5vHvGGXDjo-1Xi__HhqU2xjDJOuYrmGjw,4552
virtualenv/create/via_global_ref/builtin/cpython/__init__.py,sha256=8ArZTco6Meo0W9i4dqnwmDO8BJYTaHX7oQx1o06vCm4,57 virtualenv/create/via_global_ref/builtin/cpython/__init__.py,sha256=8ArZTco6Meo0W9i4dqnwmDO8BJYTaHX7oQx1o06vCm4,57
virtualenv/create/via_global_ref/builtin/cpython/common.py,sha256=_ycHGl1I4Pr7RfsXlUP0otJw9VQ0L744lTpPTTxPo6w,1909 virtualenv/create/via_global_ref/builtin/cpython/common.py,sha256=U7EvB9-2DlOQTGrTyPrEcItEbJ1sFBzo1EAOcAIjQ5Q,2392
virtualenv/create/via_global_ref/builtin/cpython/cpython2.py,sha256=p41H2g6wAqhJzeUU48nH3u05-yWEbwCzhyj4pn8rnm4,3757 virtualenv/create/via_global_ref/builtin/cpython/cpython2.py,sha256=p41H2g6wAqhJzeUU48nH3u05-yWEbwCzhyj4pn8rnm4,3757
virtualenv/create/via_global_ref/builtin/cpython/cpython3.py,sha256=9sY098at5Wp1Fhu1Aux1y06wH2ecbGj3bRucl4CGSQY,2473 virtualenv/create/via_global_ref/builtin/cpython/cpython3.py,sha256=gguQAhTQb0PH7Xg-G-mgQm5LlhyyW0V0piV3LwI-PeM,3111
virtualenv/create/via_global_ref/builtin/cpython/mac_os.py,sha256=Hc9FVoQPuf8IV5j17LVj49lH7nyCep2nh_lWlZm49YI,12318 virtualenv/create/via_global_ref/builtin/cpython/mac_os.py,sha256=B0Lqgo8geZBSKSpHWUB46lDYRggW4Kg2AZUp3Z7xn9M,12382
virtualenv/create/via_global_ref/builtin/pypy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 virtualenv/create/via_global_ref/builtin/pypy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
virtualenv/create/via_global_ref/builtin/pypy/common.py,sha256=KagqBNEuysqqO-n-VCCpuMvBK8MiZFMJQRWbWW12c6g,1696 virtualenv/create/via_global_ref/builtin/pypy/common.py,sha256=-t-TZxCTJwpIh_oRsDyv5IilH19jKqJrZa27zWN_8Ws,1816
virtualenv/create/via_global_ref/builtin/pypy/pypy2.py,sha256=bmMY_KJZ1iD_ifq-X9ZBOlOpJ1aN7839qigBgnWRIdA,3535 virtualenv/create/via_global_ref/builtin/pypy/pypy2.py,sha256=bmMY_KJZ1iD_ifq-X9ZBOlOpJ1aN7839qigBgnWRIdA,3535
virtualenv/create/via_global_ref/builtin/pypy/pypy3.py,sha256=ti6hmOIC4HiTBnEYKytO-d9wH-eLeMoQxQ0kZRhnNrw,1751 virtualenv/create/via_global_ref/builtin/pypy/pypy3.py,sha256=ti6hmOIC4HiTBnEYKytO-d9wH-eLeMoQxQ0kZRhnNrw,1751
virtualenv/create/via_global_ref/builtin/python2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 virtualenv/create/via_global_ref/builtin/python2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
virtualenv/create/via_global_ref/builtin/python2/python2.py,sha256=jkJwmkeJVTzwzo95eMIptTfdBA-qmyIqZcpt48iOitU,4276 virtualenv/create/via_global_ref/builtin/python2/python2.py,sha256=jkJwmkeJVTzwzo95eMIptTfdBA-qmyIqZcpt48iOitU,4276
virtualenv/create/via_global_ref/builtin/python2/site.py,sha256=mp-Y1VLSXqhIeOojQefy8ffIylWqfq20jEfc2UwMTYU,6120 virtualenv/create/via_global_ref/builtin/python2/site.py,sha256=4uguJDuWPmB25yBmpsMYKLOnIVXkerck0UO8CP8F2c4,6078
virtualenv/discovery/__init__.py,sha256=8ArZTco6Meo0W9i4dqnwmDO8BJYTaHX7oQx1o06vCm4,57 virtualenv/discovery/__init__.py,sha256=8ArZTco6Meo0W9i4dqnwmDO8BJYTaHX7oQx1o06vCm4,57
virtualenv/discovery/builtin.py,sha256=1c4Py9DnkiCLrbHp7bffvQtJI9HkxfVyFedt6IFMKEs,5079 virtualenv/discovery/builtin.py,sha256=rB6XaQwuK1HfvJsrla3BoSQUH9QkJnwKHGWBdbK4QGM,5432
virtualenv/discovery/cached_py_info.py,sha256=vQiAFDoBjR13zrdmc5q97z4upBxWzUG6H6IHJZjqjeU,5007 virtualenv/discovery/cached_py_info.py,sha256=l2lELE8YkwKXCNopImY2VjmpHPTawh1d3qmdsXMtkRs,5043
virtualenv/discovery/discover.py,sha256=evJYn4APkwjNmdolNeIBSHiOudkvN59c5oVYI2Zsjlg,1209 virtualenv/discovery/discover.py,sha256=evJYn4APkwjNmdolNeIBSHiOudkvN59c5oVYI2Zsjlg,1209
virtualenv/discovery/py_info.py,sha256=PMbQIitL6ELOJpAZF3rrMxPxM8oOmTK9aDvb4YHTDEw,21783 virtualenv/discovery/py_info.py,sha256=QtZFq0xav1tEpKI5seEJaEOkc_FXer21Gzgl_Ccqy98,21793
virtualenv/discovery/py_spec.py,sha256=wQhLzCfXoSPsAAO9nm5-I2lNolVDux4W2vPSUfJGjlc,4790 virtualenv/discovery/py_spec.py,sha256=wQhLzCfXoSPsAAO9nm5-I2lNolVDux4W2vPSUfJGjlc,4790
virtualenv/discovery/windows/__init__.py,sha256=TPbnzCtRyw47pRVHTO8ikwljNcczxmSLDdWtwasxvQU,1036 virtualenv/discovery/windows/__init__.py,sha256=TPbnzCtRyw47pRVHTO8ikwljNcczxmSLDdWtwasxvQU,1036
virtualenv/discovery/windows/pep514.py,sha256=YYiaJzo-XuMtO78BMFMAudqkeJiLQkFnUTOuQZ5lJz8,5451 virtualenv/discovery/windows/pep514.py,sha256=YYiaJzo-XuMtO78BMFMAudqkeJiLQkFnUTOuQZ5lJz8,5451
virtualenv/run/__init__.py,sha256=REhXScKzirtvWjFpTZdepZCKIxcjsRHZtt3q5mDsrMQ,5771 virtualenv/run/__init__.py,sha256=lVIiIq_LoMHUGYkrTSx0tpFG_aYywy_u6GWUReHRcUA,5777
virtualenv/run/session.py,sha256=mzXJyVQlXXgj_kO9IJDor44Co7WKiyFGnZ0mCTIy5x0,2547 virtualenv/run/session.py,sha256=S4NZiHzij1vp895mN9s9ZwYobJjjdP37QOHCb1o-Ufo,2563
virtualenv/run/plugin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 virtualenv/run/plugin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
virtualenv/run/plugin/activators.py,sha256=kmHShj36eHfbnsiAJzX0U5LYvGhe0WkRYjbuKDz6gVM,2117 virtualenv/run/plugin/activators.py,sha256=kmHShj36eHfbnsiAJzX0U5LYvGhe0WkRYjbuKDz6gVM,2117
virtualenv/run/plugin/base.py,sha256=-2185C01PaxOG7gnMbWWyZlo24n_FYo5J5_naeNZw8s,1934 virtualenv/run/plugin/base.py,sha256=-2185C01PaxOG7gnMbWWyZlo24n_FYo5J5_naeNZw8s,1934
virtualenv/run/plugin/creators.py,sha256=5L7G5mk2GIOIaZVvDZszd2VVBSUM3jkAR4aBO0OkOXY,3517 virtualenv/run/plugin/creators.py,sha256=PIxJ85KmrQU7lUO-r8Znxbb4lTEzwHggc9lcDqmt2tc,3494
virtualenv/run/plugin/discovery.py,sha256=ba9szD21er0-AkuMXrdFOjFEDsIekRWljXdXkj_-8EM,994 virtualenv/run/plugin/discovery.py,sha256=3ykxRvPA1FJMkqsbr2TV0LBRPT5UCFeJdzEHfuEjxRM,1002
virtualenv/run/plugin/seeders.py,sha256=XVKaikuOC4JUO4lirHzowEJ6d0pI1pFfywCx3heE70g,1026 virtualenv/run/plugin/seeders.py,sha256=c1mhzu0HNzKdif6YUV35fuAOS0XHFJz3TtccLW5fWG0,1074
virtualenv/seed/__init__.py,sha256=8ArZTco6Meo0W9i4dqnwmDO8BJYTaHX7oQx1o06vCm4,57 virtualenv/seed/__init__.py,sha256=8ArZTco6Meo0W9i4dqnwmDO8BJYTaHX7oQx1o06vCm4,57
virtualenv/seed/seeder.py,sha256=DSGE_8Ycj01vj8mkppUBA9h7JG76XsVBMt-5MWlMF6k,1178 virtualenv/seed/seeder.py,sha256=DSGE_8Ycj01vj8mkppUBA9h7JG76XsVBMt-5MWlMF6k,1178
virtualenv/seed/embed/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 virtualenv/seed/embed/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
virtualenv/seed/embed/base_embed.py,sha256=j4qcALcc-ylU0bKjVxiELPqk4MJ8f0pmbe_lVYVH_5Q,4166 virtualenv/seed/embed/base_embed.py,sha256=46mWtqWj_MjOQEqMJyosL0RWGL6HwrHAL2r1Jxc9DuI,4182
virtualenv/seed/embed/pip_invoke.py,sha256=EMVwIeoW15SuorJ8z_-vBxPXwQJLS0ILA0Va9zNoOLI,2127 virtualenv/seed/embed/pip_invoke.py,sha256=EMVwIeoW15SuorJ8z_-vBxPXwQJLS0ILA0Va9zNoOLI,2127
virtualenv/seed/embed/via_app_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 virtualenv/seed/embed/via_app_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
virtualenv/seed/embed/via_app_data/via_app_data.py,sha256=quofMFCWc-OxvxdAJwZTWS5mOugnYB7wRqSJZxmkl-E,6053 virtualenv/seed/embed/via_app_data/via_app_data.py,sha256=NkVhEFv4iuKG0qvEg4AAmucMwmQgNaPLB-Syepzgps0,5994
virtualenv/seed/embed/via_app_data/pip_install/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 virtualenv/seed/embed/via_app_data/pip_install/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
virtualenv/seed/embed/via_app_data/pip_install/base.py,sha256=rnR60JzM7G04cPDo2eH-aR8-iQuFXBgHJ2lQnSf0Gfs,6355 virtualenv/seed/embed/via_app_data/pip_install/base.py,sha256=rnR60JzM7G04cPDo2eH-aR8-iQuFXBgHJ2lQnSf0Gfs,6355
virtualenv/seed/embed/via_app_data/pip_install/copy.py,sha256=gG2NePFHOYh-bsCf6TpsaQ_qrYhdBy67k0RWuwHSAwo,1307 virtualenv/seed/embed/via_app_data/pip_install/copy.py,sha256=gG2NePFHOYh-bsCf6TpsaQ_qrYhdBy67k0RWuwHSAwo,1307
virtualenv/seed/embed/via_app_data/pip_install/symlink.py,sha256=wHCpfKobvjjaZLUSwM3FSCblZfiBFw4IQYsxwlfEEu0,2362 virtualenv/seed/embed/via_app_data/pip_install/symlink.py,sha256=wHCpfKobvjjaZLUSwM3FSCblZfiBFw4IQYsxwlfEEu0,2362
virtualenv/seed/wheels/__init__.py,sha256=1J7el7lNjAwGxM4dmricrbVhSbYxs5sPzv9PTx2A6qA,226 virtualenv/seed/wheels/__init__.py,sha256=1J7el7lNjAwGxM4dmricrbVhSbYxs5sPzv9PTx2A6qA,226
virtualenv/seed/wheels/acquire.py,sha256=Iq_QPJgUPCyHfrS3t2EUUj8fieymfcKNve1JbJQ5Uyc,4420 virtualenv/seed/wheels/acquire.py,sha256=qchqlIynLi2VP2VtdAfVfZJHbUPcLY2Ui5r7Eh-aZz8,4426
virtualenv/seed/wheels/bundle.py,sha256=xYbhh5nQEwec2vnqNJWNVtDL3VyjGkgDWVXSuXzXB-Y,1961 virtualenv/seed/wheels/bundle.py,sha256=W0uVjClv9IBa50jRvPKm0jMwWnrYTEfDny2Z6bw2W7c,1835
virtualenv/seed/wheels/periodic_update.py,sha256=A9l7ZpjtWzGrq2nh39y8g5OppUryHb7_W3bCR7TAnPc,12756 virtualenv/seed/wheels/periodic_update.py,sha256=HNVEuU2OYdWHW7lVO0h3NkpLkC8bu-5R7igJRXBnGDc,12792
virtualenv/seed/wheels/util.py,sha256=Zdo76KEDqbNmM5u9JTuyu5uzEN_fQ4oj6qHOt0h0o1M,3960 virtualenv/seed/wheels/util.py,sha256=Zdo76KEDqbNmM5u9JTuyu5uzEN_fQ4oj6qHOt0h0o1M,3960
virtualenv/seed/wheels/embed/__init__.py,sha256=qc4QGDYH6J4ikiW1GPSkgjpapQDB7TpPd6TTr21jvbU,1995 virtualenv/seed/wheels/embed/__init__.py,sha256=CLMKoeveDRyiNAdZjEtD38cepgNXkg65xzFu5OSHEus,1995
virtualenv/seed/wheels/embed/pip-19.1.1-py2.py3-none-any.whl,sha256=mTE08EdUcbkUUsoCnUOQ3I8pisY6cSgU8QHNG220ZnY,1360957 virtualenv/seed/wheels/embed/pip-19.1.1-py2.py3-none-any.whl,sha256=mTE08EdUcbkUUsoCnUOQ3I8pisY6cSgU8QHNG220ZnY,1360957
virtualenv/seed/wheels/embed/pip-20.2.2-py2.py3-none-any.whl,sha256=UkTlFJT10d-7idpJLUJQywf5JGZEc20Q7WxF3rGkhQA,1503623 virtualenv/seed/wheels/embed/pip-20.3.1-py2.py3-none-any.whl,sha256=Ql55sgk5q7_6djOpEVGogq7cd1ZNkxPjWE6wQWwoxVg,1518513
virtualenv/seed/wheels/embed/setuptools-43.0.0-py2.py3-none-any.whl,sha256=pn-qUVGe8ozYJhr_DiIbbkw3D4-4utqKo-etiUUZmWM,583228 virtualenv/seed/wheels/embed/setuptools-43.0.0-py2.py3-none-any.whl,sha256=pn-qUVGe8ozYJhr_DiIbbkw3D4-4utqKo-etiUUZmWM,583228
virtualenv/seed/wheels/embed/setuptools-44.1.1-py2.py3-none-any.whl,sha256=J6cUwJJTE05gpvpoEw94xwN-VWLE8h-PMY8q6QDRUtU,583493 virtualenv/seed/wheels/embed/setuptools-44.1.1-py2.py3-none-any.whl,sha256=J6cUwJJTE05gpvpoEw94xwN-VWLE8h-PMY8q6QDRUtU,583493
virtualenv/seed/wheels/embed/setuptools-49.6.0-py3-none-any.whl,sha256=TdW7CgoM_3e0bKXdOoSFfuSMg-giOIa1VmE8ckmUBz8,803275 virtualenv/seed/wheels/embed/setuptools-50.3.2-py3-none-any.whl,sha256=LCQqCFb7rX775WDfSnrdkyTzQM9I30NlHpYEkkRmeUo,785194
virtualenv/seed/wheels/embed/setuptools-51.0.0-py3-none-any.whl,sha256=jBd5NiFZRcmjfvgJraD6s2UZGVL3oSNhhDK7-sNTxSk,785164
virtualenv/seed/wheels/embed/wheel-0.33.6-py2.py3-none-any.whl,sha256=9NoXY9O-zy4s2SoUp8kg8PAOyjD93p6pksg2aFufryg,21556 virtualenv/seed/wheels/embed/wheel-0.33.6-py2.py3-none-any.whl,sha256=9NoXY9O-zy4s2SoUp8kg8PAOyjD93p6pksg2aFufryg,21556
virtualenv/seed/wheels/embed/wheel-0.35.1-py2.py3-none-any.whl,sha256=SXrdU1JdFsFzwsHHM7j2VVEOkJ6njMDinTdCQ1RLd6I,33174 virtualenv/seed/wheels/embed/wheel-0.36.1-py2.py3-none-any.whl,sha256=kGhk-3IsCrXy-cNbLGXjrzwAlALBCKcJwKyie8LJGHs,34788
virtualenv/util/__init__.py,sha256=om6Hs2lH5igf5lkcSmQFiU7iMZ0Wx4dmSlMc6XW_Llg,199 virtualenv/util/__init__.py,sha256=om6Hs2lH5igf5lkcSmQFiU7iMZ0Wx4dmSlMc6XW_Llg,199
virtualenv/util/error.py,sha256=SRSZlXvMYQuJwxoUfNhlAyo3VwrAnIsZemSwPOxpjns,352 virtualenv/util/error.py,sha256=SRSZlXvMYQuJwxoUfNhlAyo3VwrAnIsZemSwPOxpjns,352
virtualenv/util/lock.py,sha256=AyYqRMsz5YnLNDLNTrutjLqS8m0lkLqNNDpxW565b44,3550 virtualenv/util/lock.py,sha256=oFa0FcbE_TVDHOol44Mgtfa4D3ZjnVy-HSQx-y7ERKQ,4727
virtualenv/util/six.py,sha256=_8KWXUWi3-AaFmz4LkdyNra-uNuf70vlxwjN7oeRo8g,1463 virtualenv/util/six.py,sha256=_8KWXUWi3-AaFmz4LkdyNra-uNuf70vlxwjN7oeRo8g,1463
virtualenv/util/zipapp.py,sha256=jtf4Vn7XBnjPs_B_ObIQv_x4pFlIlPKAWHYLFV59h6U,1054 virtualenv/util/zipapp.py,sha256=jtf4Vn7XBnjPs_B_ObIQv_x4pFlIlPKAWHYLFV59h6U,1054
virtualenv/util/path/__init__.py,sha256=YaBAxtzGBdMu0uUtppe0ZeCHw5HhO-5zjeb3-fzyMoI,336 virtualenv/util/path/__init__.py,sha256=YaBAxtzGBdMu0uUtppe0ZeCHw5HhO-5zjeb3-fzyMoI,336
virtualenv/util/path/_permission.py,sha256=XpO2vGAk_92_biD4MEQcAQq2Zc8_rpm3M3n_hMUA1rw,745 virtualenv/util/path/_permission.py,sha256=XpO2vGAk_92_biD4MEQcAQq2Zc8_rpm3M3n_hMUA1rw,745
virtualenv/util/path/_sync.py,sha256=7oEmxJB5fc7NIsVgPJTJ4mpVPjNaNHAdhqlgIFSDfm0,2370 virtualenv/util/path/_sync.py,sha256=rheUrGsCqmhMwNs-uc5rDthNSUlsOrBJPoK8KZj3O1o,2393
virtualenv/util/path/_pathlib/__init__.py,sha256=evaey395zOuDc3FlukUeJ8SzRqLx1xWOKmg-TEPsRd4,1446 virtualenv/util/path/_pathlib/__init__.py,sha256=FjKCi8scB5MnHg2fLX5REoE0bOPkMXqpBEILVTeJZGQ,2130
virtualenv/util/path/_pathlib/via_os_path.py,sha256=wlnf0MIktEP01kG9z8iKOI86levXmkX7UX1LMLK7A-E,3701 virtualenv/util/path/_pathlib/via_os_path.py,sha256=fYDFAX483zVvC9hAOAC9FYtrGdZethS0vtYtKsL5r-s,3772
virtualenv/util/subprocess/__init__.py,sha256=2H-ZQ74OKq60eSpxfRWD-8gVUydczkrKSexl18DzOXI,753 virtualenv/util/subprocess/__init__.py,sha256=1UmFrdBv2sVeUfZbDcO2yZpe28AE0ULOu9dRKlpJaa0,801
virtualenv/util/subprocess/_win_subprocess.py,sha256=0-eJVcxBs1Fe76OVTQnUVLaLzB4tlJxEZ-vZECQ4xL4,5576 virtualenv/util/subprocess/_win_subprocess.py,sha256=SChkXAKVbpehyrHod1ld76RSdTIalrgME1rtz5jUfm0,5655
virtualenv-20.0.31.dist-info/LICENSE,sha256=XBWRk3jFsqqrexnOpw2M3HX3aHnjJFTkwDmfi3HRcek,1074 virtualenv-20.2.2.dist-info/LICENSE,sha256=XBWRk3jFsqqrexnOpw2M3HX3aHnjJFTkwDmfi3HRcek,1074
virtualenv-20.0.31.dist-info/METADATA,sha256=Pwhk7KR7q09ZjMUtWXYwzvuWD1mY4hxS1e9eqpsjRs8,4923 virtualenv-20.2.2.dist-info/METADATA,sha256=OWyC_GXU3AvST-YiGhmI2iE4ntdcBm-6Q1yCaU9Bx_U,4965
virtualenv-20.0.31.dist-info/WHEEL,sha256=ADKeyaGyKF5DwBNE0sRE5pvW-bSkFMJfBuhzZ3rceP4,110 virtualenv-20.2.2.dist-info/WHEEL,sha256=oh0NKYrTcu1i1-wgrI1cnhkjYIi8WJ-8qd9Jrr5_y4E,110
virtualenv-20.0.31.dist-info/entry_points.txt,sha256=1DALKzYOcffJa7Q15TQlMQu0yeFXEy5W124y0aJEfYU,1615 virtualenv-20.2.2.dist-info/entry_points.txt,sha256=1DALKzYOcffJa7Q15TQlMQu0yeFXEy5W124y0aJEfYU,1615
virtualenv-20.0.31.dist-info/top_level.txt,sha256=JV-LVlC8YeIw1DgiYI0hEot7tgFy5IWdKVcSG7NyzaI,11 virtualenv-20.2.2.dist-info/top_level.txt,sha256=JV-LVlC8YeIw1DgiYI0hEot7tgFy5IWdKVcSG7NyzaI,11
virtualenv-20.0.31.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 virtualenv-20.2.2.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
virtualenv-20.0.31.dist-info/RECORD,, virtualenv-20.2.2.dist-info/RECORD,,

Просмотреть файл

@ -0,0 +1,6 @@
Wheel-Version: 1.0
Generator: bdist_wheel (0.36.1)
Root-Is-Purelib: true
Tag: py2-none-any
Tag: py3-none-any

Просмотреть файл

@ -47,6 +47,9 @@ deactivate () {
deactivate nondestructive deactivate nondestructive
VIRTUAL_ENV='__VIRTUAL_ENV__' VIRTUAL_ENV='__VIRTUAL_ENV__'
if ([ "$OSTYPE" = "cygwin" ] || [ "$OSTYPE" = "msys" ]) && $(command -v cygpath &> /dev/null) ; then
VIRTUAL_ENV=$(cygpath -u "$VIRTUAL_ENV")
fi
export VIRTUAL_ENV export VIRTUAL_ENV
_OLD_VIRTUAL_PATH="$PATH" _OLD_VIRTUAL_PATH="$PATH"

Просмотреть файл

@ -1,60 +1,60 @@
$script:THIS_PATH = $myinvocation.mycommand.path $script:THIS_PATH = $myinvocation.mycommand.path
$script:BASE_DIR = Split-Path (Resolve-Path "$THIS_PATH/..") -Parent $script:BASE_DIR = Split-Path (Resolve-Path "$THIS_PATH/..") -Parent
function global:deactivate([switch] $NonDestructive) { function global:deactivate([switch] $NonDestructive) {
if (Test-Path variable:_OLD_VIRTUAL_PATH) { if (Test-Path variable:_OLD_VIRTUAL_PATH) {
$env:PATH = $variable:_OLD_VIRTUAL_PATH $env:PATH = $variable:_OLD_VIRTUAL_PATH
Remove-Variable "_OLD_VIRTUAL_PATH" -Scope global Remove-Variable "_OLD_VIRTUAL_PATH" -Scope global
} }
if (Test-Path function:_old_virtual_prompt) { if (Test-Path function:_old_virtual_prompt) {
$function:prompt = $function:_old_virtual_prompt $function:prompt = $function:_old_virtual_prompt
Remove-Item function:\_old_virtual_prompt Remove-Item function:\_old_virtual_prompt
} }
if ($env:VIRTUAL_ENV) { if ($env:VIRTUAL_ENV) {
Remove-Item env:VIRTUAL_ENV -ErrorAction SilentlyContinue Remove-Item env:VIRTUAL_ENV -ErrorAction SilentlyContinue
} }
if (!$NonDestructive) { if (!$NonDestructive) {
# Self destruct! # Self destruct!
Remove-Item function:deactivate Remove-Item function:deactivate
Remove-Item function:pydoc Remove-Item function:pydoc
} }
} }
function global:pydoc { function global:pydoc {
python -m pydoc $args python -m pydoc $args
} }
# unset irrelevant variables # unset irrelevant variables
deactivate -nondestructive deactivate -nondestructive
$VIRTUAL_ENV = $BASE_DIR $VIRTUAL_ENV = $BASE_DIR
$env:VIRTUAL_ENV = $VIRTUAL_ENV $env:VIRTUAL_ENV = $VIRTUAL_ENV
New-Variable -Scope global -Name _OLD_VIRTUAL_PATH -Value $env:PATH New-Variable -Scope global -Name _OLD_VIRTUAL_PATH -Value $env:PATH
$env:PATH = "$env:VIRTUAL_ENV/__BIN_NAME____PATH_SEP__" + $env:PATH $env:PATH = "$env:VIRTUAL_ENV/__BIN_NAME____PATH_SEP__" + $env:PATH
if (!$env:VIRTUAL_ENV_DISABLE_PROMPT) { if (!$env:VIRTUAL_ENV_DISABLE_PROMPT) {
function global:_old_virtual_prompt { function global:_old_virtual_prompt {
"" ""
} }
$function:_old_virtual_prompt = $function:prompt $function:_old_virtual_prompt = $function:prompt
if ("__VIRTUAL_PROMPT__" -ne "") { if ("__VIRTUAL_PROMPT__" -ne "") {
function global:prompt { function global:prompt {
# Add the custom prefix to the existing prompt # Add the custom prefix to the existing prompt
$previous_prompt_value = & $function:_old_virtual_prompt $previous_prompt_value = & $function:_old_virtual_prompt
("__VIRTUAL_PROMPT__" + $previous_prompt_value) ("__VIRTUAL_PROMPT__" + $previous_prompt_value)
} }
} }
else { else {
function global:prompt { function global:prompt {
# Add a prefix to the current prompt, but don't discard it. # Add a prefix to the current prompt, but don't discard it.
$previous_prompt_value = & $function:_old_virtual_prompt $previous_prompt_value = & $function:_old_virtual_prompt
$new_prompt_value = "($( Split-Path $env:VIRTUAL_ENV -Leaf )) " $new_prompt_value = "($( Split-Path $env:VIRTUAL_ENV -Leaf )) "
($new_prompt_value + $previous_prompt_value) ($new_prompt_value + $previous_prompt_value)
} }
} }
} }

Просмотреть файл

@ -11,9 +11,9 @@ from virtualenv.util.six import ensure_text
from .activator import Activator from .activator import Activator
if sys.version_info >= (3, 7): if sys.version_info >= (3, 7):
from importlib.resources import read_text from importlib.resources import read_binary
else: else:
from importlib_resources import read_text from importlib_resources import read_binary
@add_metaclass(ABCMeta) @add_metaclass(ABCMeta)
@ -44,7 +44,8 @@ class ViaTemplateActivator(Activator):
for template in templates: for template in templates:
text = self.instantiate_template(replacements, template, creator) text = self.instantiate_template(replacements, template, creator)
dest = to_folder / self.as_name(template) dest = to_folder / self.as_name(template)
dest.write_text(text, encoding="utf-8") # use write_bytes to avoid platform specific line normalization (\n -> \r\n)
dest.write_bytes(text.encode("utf-8"))
generated.append(dest) generated.append(dest)
return generated return generated
@ -52,8 +53,9 @@ class ViaTemplateActivator(Activator):
return template.name return template.name
def instantiate_template(self, replacements, template, creator): def instantiate_template(self, replacements, template, creator):
# read text and do replacements # read content as binary to avoid platform specific line normalization (\n -> \r\n)
text = read_text(self.__module__, str(template), encoding="utf-8", errors="strict") binary = read_binary(self.__module__, str(template))
text = binary.decode("utf-8", errors="strict")
for key, value in replacements.items(): for key, value in replacements.items():
value = self._repr_unicode(creator, value) value = self._repr_unicode(creator, value)
text = text.replace(key, value) text = text.replace(key, value)

Просмотреть файл

@ -5,58 +5,53 @@ from __future__ import absolute_import, unicode_literals
import logging import logging
import os import os
from argparse import Action, ArgumentError
from appdirs import user_data_dir from appdirs import user_data_dir
from .na import AppDataDisabled from .na import AppDataDisabled
from .read_only import ReadOnlyAppData
from .via_disk_folder import AppDataDiskFolder from .via_disk_folder import AppDataDiskFolder
from .via_tempdir import TempAppData from .via_tempdir import TempAppData
class AppDataAction(Action): def _default_app_data_dir(): # type: () -> str
def __call__(self, parser, namespace, values, option_string=None): key = str("VIRTUALENV_OVERRIDE_APP_DATA")
folder = self._check_folder(values) if key in os.environ:
if folder is None: return os.environ[key]
raise ArgumentError("app data path {} is not valid".format(values)) else:
setattr(namespace, self.dest, AppDataDiskFolder(folder)) return user_data_dir(appname="virtualenv", appauthor="pypa")
@staticmethod
def _check_folder(folder): def make_app_data(folder, **kwargs):
folder = os.path.abspath(folder) read_only = kwargs.pop("read_only")
if not os.path.exists(folder): if kwargs: # py3+ kwonly
try: raise TypeError("unexpected keywords: {}")
os.makedirs(folder)
logging.debug("created app data folder %s", folder) if folder is None:
except OSError as exception: folder = _default_app_data_dir()
logging.info("could not create app data folder %s due to %r", folder, exception) folder = os.path.abspath(folder)
return None
write_enabled = os.access(folder, os.W_OK) if read_only:
if write_enabled: return ReadOnlyAppData(folder)
return folder
if not os.path.isdir(folder):
try:
os.makedirs(folder)
logging.debug("created app data folder %s", folder)
except OSError as exception:
logging.info("could not create app data folder %s due to %r", folder, exception)
if os.access(folder, os.W_OK):
return AppDataDiskFolder(folder)
else:
logging.debug("app data folder %s has no write access", folder) logging.debug("app data folder %s has no write access", folder)
return None return TempAppData()
@staticmethod
def default():
for folder in AppDataAction._app_data_candidates():
folder = AppDataAction._check_folder(folder)
if folder is not None:
return AppDataDiskFolder(folder)
return AppDataDisabled()
@staticmethod
def _app_data_candidates():
key = str("VIRTUALENV_OVERRIDE_APP_DATA")
if key in os.environ:
yield os.environ[key]
else:
yield user_data_dir(appname="virtualenv", appauthor="pypa")
__all__ = ( __all__ = (
"AppDataDiskFolder",
"TempAppData",
"AppDataAction",
"AppDataDisabled", "AppDataDisabled",
"AppDataDiskFolder",
"ReadOnlyAppData",
"TempAppData",
"make_app_data",
) )

Просмотреть файл

@ -31,6 +31,10 @@ class AppData(object):
def py_info_clear(self): def py_info_clear(self):
raise NotImplementedError raise NotImplementedError
@property
def can_update(self):
raise NotImplementedError
@abstractmethod @abstractmethod
def embed_update_log(self, distribution, for_py_version): def embed_update_log(self, distribution, for_py_version):
raise NotImplementedError raise NotImplementedError

Просмотреть файл

@ -8,6 +8,9 @@ from .base import AppData, ContentStore
class AppDataDisabled(AppData): class AppDataDisabled(AppData):
"""No application cache available (most likely as we don't have write permissions)""" """No application cache available (most likely as we don't have write permissions)"""
transient = True
can_update = False
def __init__(self): def __init__(self):
pass pass
@ -40,10 +43,6 @@ class AppDataDisabled(AppData):
def wheel_image(self, for_py_version, name): def wheel_image(self, for_py_version, name):
raise self.error raise self.error
@property
def transient(self):
return True
def py_info_clear(self): def py_info_clear(self):
"""""" """"""

34
third_party/python/virtualenv/virtualenv/app_data/read_only.py поставляемый Normal file
Просмотреть файл

@ -0,0 +1,34 @@
import os.path
from virtualenv.util.lock import NoOpFileLock
from .via_disk_folder import AppDataDiskFolder, PyInfoStoreDisk
class ReadOnlyAppData(AppDataDiskFolder):
can_update = False
def __init__(self, folder): # type: (str) -> None
if not os.path.isdir(folder):
raise RuntimeError("read-only app data directory {} does not exist".format(folder))
self.lock = NoOpFileLock(folder)
def reset(self): # type: () -> None
raise RuntimeError("read-only app data does not support reset")
def py_info_clear(self): # type: () -> None
raise NotImplementedError
def py_info(self, path):
return _PyInfoStoreDiskReadOnly(self.py_info_at, path)
def embed_update_log(self, distribution, for_py_version):
raise NotImplementedError
class _PyInfoStoreDiskReadOnly(PyInfoStoreDisk):
def write(self, content):
raise RuntimeError("read-only app data python info cannot be updated")
__all__ = ("ReadOnlyAppData",)

Просмотреть файл

@ -46,15 +46,17 @@ class AppDataDiskFolder(AppData):
Store the application data on the disk within a folder layout. Store the application data on the disk within a folder layout.
""" """
transient = False
can_update = True
def __init__(self, folder): def __init__(self, folder):
self.lock = ReentrantFileLock(folder) self.lock = ReentrantFileLock(folder)
def __repr__(self): def __repr__(self):
return "{}".format(self.lock.path) return "{}({})".format(type(self).__name__, self.lock.path)
@property def __str__(self):
def transient(self): return str(self.lock.path)
return False
def reset(self): def reset(self):
logging.debug("reset app data folder %s", self.lock.path) logging.debug("reset app data folder %s", self.lock.path)
@ -137,7 +139,10 @@ class JSONStoreDisk(ContentStore):
except Exception: # noqa except Exception: # noqa
pass pass
if bad_format: if bad_format:
self.remove() try:
self.remove()
except OSError: # reading and writing on the same file may cause race on multiple processes
pass
return None return None
def remove(self): def remove(self):
@ -151,10 +156,7 @@ class JSONStoreDisk(ContentStore):
def write(self, content): def write(self, content):
folder = self.file.parent folder = self.file.parent
try: folder.mkdir(parents=True, exist_ok=True)
folder.mkdir(parents=True, exist_ok=True)
except OSError:
pass
self.file.write_text(ensure_text(json.dumps(content, sort_keys=True, indent=2))) self.file.write_text(ensure_text(json.dumps(content, sort_keys=True, indent=2)))
logging.debug("wrote {} at %s".format(self.msg), *self.msg_args) logging.debug("wrote {} at %s".format(self.msg), *self.msg_args)
@ -168,5 +170,8 @@ class PyInfoStoreDisk(JSONStoreDisk):
class EmbedDistributionUpdateStoreDisk(JSONStoreDisk): class EmbedDistributionUpdateStoreDisk(JSONStoreDisk):
def __init__(self, in_folder, distribution): def __init__(self, in_folder, distribution):
super(EmbedDistributionUpdateStoreDisk, self).__init__( super(EmbedDistributionUpdateStoreDisk, self).__init__(
in_folder, distribution, "embed update of distribution %s", (distribution,), in_folder,
distribution,
"embed update of distribution %s",
(distribution,),
) )

Просмотреть файл

@ -9,6 +9,9 @@ from .via_disk_folder import AppDataDiskFolder
class TempAppData(AppDataDiskFolder): class TempAppData(AppDataDiskFolder):
transient = True
can_update = False
def __init__(self): def __init__(self):
super(TempAppData, self).__init__(folder=mkdtemp()) super(TempAppData, self).__init__(folder=mkdtemp())
logging.debug("created temporary app data folder %s", self.lock.path) logging.debug("created temporary app data folder %s", self.lock.path)
@ -21,8 +24,4 @@ class TempAppData(AppDataDiskFolder):
safe_delete(self.lock.path) safe_delete(self.lock.path)
def embed_update_log(self, distribution, for_py_version): def embed_update_log(self, distribution, for_py_version):
return None raise NotImplementedError
@property
def transient(self):
return True

Просмотреть файл

@ -46,9 +46,7 @@ class ListType(TypeData):
"""""" """"""
def convert(self, value, flatten=True): def convert(self, value, flatten=True):
if isinstance(value, (str, bytes)): values = self.split_values(value)
value = filter(None, [x.strip() for x in value.splitlines()])
values = list(value)
result = [] result = []
for value in values: for value in values:
sub_values = value.split(os.pathsep) sub_values = value.split(os.pathsep)
@ -56,6 +54,25 @@ class ListType(TypeData):
converted = [self.as_type(i) for i in result] converted = [self.as_type(i) for i in result]
return converted return converted
def split_values(self, value):
"""Split the provided value into a list.
First this is done by newlines. If there were no newlines in the text,
then we next try to split by comma.
"""
if isinstance(value, (str, bytes)):
# Use `splitlines` rather than a custom check for whether there is
# more than one line. This ensures that the full `splitlines()`
# logic is supported here.
values = value.splitlines()
if len(values) <= 1:
values = value.split(",")
values = filter(None, [x.strip() for x in values])
else:
values = list(value)
return values
def convert(value, as_type, source): def convert(value, as_type, source):
"""Convert the value as a given type where the value comes from the given source""" """Convert the value as a given type where the value comes from the given source"""

Просмотреть файл

@ -44,6 +44,7 @@ class Creator(object):
self._debug = None self._debug = None
self.dest = Path(options.dest) self.dest = Path(options.dest)
self.clear = options.clear self.clear = options.clear
self.no_vcs_ignore = options.no_vcs_ignore
self.pyenv_cfg = PyEnvCfg.from_folder(self.dest) self.pyenv_cfg = PyEnvCfg.from_folder(self.dest)
self.app_data = options.app_data self.app_data = options.app_data
@ -57,6 +58,7 @@ class Creator(object):
return [ return [
("dest", ensure_text(str(self.dest))), ("dest", ensure_text(str(self.dest))),
("clear", self.clear), ("clear", self.clear),
("no_vcs_ignore", self.no_vcs_ignore),
] ]
@classmethod @classmethod
@ -79,7 +81,9 @@ class Creator(object):
:param meta: value as returned by :meth:`can_create` :param meta: value as returned by :meth:`can_create`
""" """
parser.add_argument( parser.add_argument(
"dest", help="directory to create virtualenv at", type=cls.validate_dest, "dest",
help="directory to create virtualenv at",
type=cls.validate_dest,
) )
parser.add_argument( parser.add_argument(
"--clear", "--clear",
@ -88,6 +92,13 @@ class Creator(object):
help="remove the destination directory if exist before starting (will overwrite files otherwise)", help="remove the destination directory if exist before starting (will overwrite files otherwise)",
default=False, default=False,
) )
parser.add_argument(
"--no-vcs-ignore",
dest="no_vcs_ignore",
action="store_true",
help="don't create VCS ignore directive in the destination directory",
default=False,
)
@abstractmethod @abstractmethod
def create(self): def create(self):
@ -120,7 +131,9 @@ class Creator(object):
if refused: if refused:
raise ArgumentTypeError( raise ArgumentTypeError(
"the file system codec ({}) cannot handle characters {!r} within {!r}".format( "the file system codec ({}) cannot handle characters {!r} within {!r}".format(
encoding, "".join(refused.keys()), raw_value, encoding,
"".join(refused.keys()),
raw_value,
), ),
) )
if os.pathsep in raw_value: if os.pathsep in raw_value:
@ -156,7 +169,8 @@ class Creator(object):
safe_delete(self.dest) safe_delete(self.dest)
self.create() self.create()
self.set_pyenv_cfg() self.set_pyenv_cfg()
self.setup_ignore_vcs() if not self.no_vcs_ignore:
self.setup_ignore_vcs()
def set_pyenv_cfg(self): def set_pyenv_cfg(self):
self.pyenv_cfg.content = OrderedDict() self.pyenv_cfg.content = OrderedDict()

Просмотреть файл

@ -8,6 +8,7 @@ from six import add_metaclass
from virtualenv.info import fs_supports_symlink from virtualenv.info import fs_supports_symlink
from virtualenv.util.path import Path from virtualenv.util.path import Path
from virtualenv.util.six import ensure_text
from ..creator import Creator, CreatorMeta from ..creator import Creator, CreatorMeta
@ -91,10 +92,10 @@ class ViaGlobalRefApi(Creator):
text = self.env_patch_text() text = self.env_patch_text()
if text: if text:
pth = self.purelib / "_virtualenv.pth" pth = self.purelib / "_virtualenv.pth"
logging.debug("create virtualenv import hook file %s", pth) logging.debug("create virtualenv import hook file %s", ensure_text(str(pth)))
pth.write_text("import _virtualenv") pth.write_text("import _virtualenv")
dest_path = self.purelib / "_virtualenv.py" dest_path = self.purelib / "_virtualenv.py"
logging.debug("create %s", dest_path) logging.debug("create %s", ensure_text(str(dest_path)))
dest_path.write_text(text) dest_path.write_text(text)
def env_patch_text(self): def env_patch_text(self):

Просмотреть файл

@ -6,6 +6,7 @@ from collections import OrderedDict
from six import add_metaclass from six import add_metaclass
from virtualenv.create.describe import PosixSupports, WindowsSupports from virtualenv.create.describe import PosixSupports, WindowsSupports
from virtualenv.create.via_global_ref.builtin.ref import RefMust, RefWhen
from virtualenv.util.path import Path from virtualenv.util.path import Path
from ..via_global_self_do import ViaGlobalRefVirtualenvBuiltin from ..via_global_self_do import ViaGlobalRefVirtualenvBuiltin
@ -33,19 +34,27 @@ class CPythonPosix(CPython, PosixSupports):
targets = OrderedDict( targets = OrderedDict(
(i, None) for i in ["python", "python{}".format(major), "python{}.{}".format(major, minor), host_exe.name] (i, None) for i in ["python", "python{}".format(major), "python{}.{}".format(major, minor), host_exe.name]
) )
yield host_exe, list(targets.keys()) must = RefMust.COPY if interpreter.version_info.major == 2 else RefMust.NA
yield host_exe, list(targets.keys()), must, RefWhen.ANY
@add_metaclass(ABCMeta) @add_metaclass(ABCMeta)
class CPythonWindows(CPython, WindowsSupports): class CPythonWindows(CPython, WindowsSupports):
@classmethod @classmethod
def _executables(cls, interpreter): def _executables(cls, interpreter):
host = Path(interpreter.system_executable) # symlink of the python executables does not work reliably, copy always instead
# - https://bugs.python.org/issue42013
# - venv
host = cls.host_python(interpreter)
for path in (host.parent / n for n in {"python.exe", host.name}): for path in (host.parent / n for n in {"python.exe", host.name}):
yield host, [path.name] yield host, [path.name], RefMust.COPY, RefWhen.ANY
# for more info on pythonw.exe see https://stackoverflow.com/a/30313091 # for more info on pythonw.exe see https://stackoverflow.com/a/30313091
python_w = host.parent / "pythonw.exe" python_w = host.parent / "pythonw.exe"
yield python_w, [python_w.name] yield python_w, [python_w.name], RefMust.COPY, RefWhen.ANY
@classmethod
def host_python(cls, interpreter):
return Path(interpreter.system_executable)
def is_mac_os_framework(interpreter): def is_mac_os_framework(interpreter):

Просмотреть файл

@ -55,8 +55,21 @@ class CPython3Windows(CPythonWindows, CPython3):
def sources(cls, interpreter): def sources(cls, interpreter):
for src in super(CPython3Windows, cls).sources(interpreter): for src in super(CPython3Windows, cls).sources(interpreter):
yield src yield src
for src in cls.include_dll_and_pyd(interpreter): if not cls.venv_37p(interpreter):
yield src for src in cls.include_dll_and_pyd(interpreter):
yield src
@staticmethod
def venv_37p(interpreter):
return interpreter.version_info.minor >= 7
@classmethod
def host_python(cls, interpreter):
if cls.venv_37p(interpreter):
# starting with CPython 3.7 Windows ships with a venvlauncher.exe that avoids the need for dll/pyd copies
# it also means the wrapper must be copied to avoid bugs such as https://bugs.python.org/issue42013
return Path(interpreter.system_stdlib) / "venv" / "scripts" / "nt" / "python.exe"
return super(CPython3Windows, cls).host_python(interpreter)
@classmethod @classmethod
def include_dll_and_pyd(cls, interpreter): def include_dll_and_pyd(cls, interpreter):

Просмотреть файл

@ -9,7 +9,7 @@ from textwrap import dedent
from six import add_metaclass from six import add_metaclass
from virtualenv.create.via_global_ref.builtin.ref import ExePathRefToDest, PathRefToDest from virtualenv.create.via_global_ref.builtin.ref import ExePathRefToDest, PathRefToDest, RefMust
from virtualenv.util.path import Path from virtualenv.util.path import Path
from virtualenv.util.six import ensure_text from virtualenv.util.six import ensure_text
@ -29,7 +29,8 @@ class CPythonmacOsFramework(CPython):
for src in super(CPythonmacOsFramework, cls).sources(interpreter): for src in super(CPythonmacOsFramework, cls).sources(interpreter):
yield src yield src
# add a symlink to the host python image # add a symlink to the host python image
ref = PathRefToDest(cls.image_ref(interpreter), dest=lambda self, _: self.dest / ".Python", must_symlink=True) exe = cls.image_ref(interpreter)
ref = PathRefToDest(exe, dest=lambda self, _: self.dest / ".Python", must=RefMust.SYMLINK)
yield ref yield ref
def create(self): def create(self):
@ -40,7 +41,7 @@ class CPythonmacOsFramework(CPython):
current = self.current_mach_o_image_path() current = self.current_mach_o_image_path()
for src in self._sources: for src in self._sources:
if isinstance(src, ExePathRefToDest): if isinstance(src, ExePathRefToDest):
if src.must_copy or not self.symlinks: if src.must == RefMust.COPY or not self.symlinks:
exes = [self.bin_dir / src.base] exes = [self.bin_dir / src.base]
if not self.symlinks: if not self.symlinks:
exes.extend(self.bin_dir / a for a in src.aliases) exes.extend(self.bin_dir / a for a in src.aliases)
@ -49,12 +50,12 @@ class CPythonmacOsFramework(CPython):
@classmethod @classmethod
def _executables(cls, interpreter): def _executables(cls, interpreter):
for _, targets in super(CPythonmacOsFramework, cls)._executables(interpreter): for _, targets, must, when in super(CPythonmacOsFramework, cls)._executables(interpreter):
# Make sure we use the embedded interpreter inside the framework, even if sys.executable points to the # Make sure we use the embedded interpreter inside the framework, even if sys.executable points to the
# stub executable in ${sys.prefix}/bin. # stub executable in ${sys.prefix}/bin.
# See http://groups.google.com/group/python-virtualenv/browse_thread/thread/17cab2f85da75951 # See http://groups.google.com/group/python-virtualenv/browse_thread/thread/17cab2f85da75951
fixed_host_exe = Path(interpreter.prefix) / "Resources" / "Python.app" / "Contents" / "MacOS" / "Python" fixed_host_exe = Path(interpreter.prefix) / "Resources" / "Python.app" / "Contents" / "MacOS" / "Python"
yield fixed_host_exe, targets yield fixed_host_exe, targets, must, when
@abstractmethod @abstractmethod
def current_mach_o_image_path(self): def current_mach_o_image_path(self):
@ -241,7 +242,7 @@ def _builtin_change_mach_o(maxint):
def mach_o_change(at_path, what, value): def mach_o_change(at_path, what, value):
"""Replace a given name (what) in any LC_LOAD_DYLIB command found in the given binary with a new name (value), """Replace a given name (what) in any LC_LOAD_DYLIB command found in the given binary with a new name (value),
provided it's shorter.""" provided it's shorter."""
def do_macho(file, bits, endian): def do_macho(file, bits, endian):
# Read Mach-O header (the magic number is assumed read by the caller) # Read Mach-O header (the magic number is assumed read by the caller)

Просмотреть файл

@ -4,7 +4,7 @@ import abc
from six import add_metaclass from six import add_metaclass
from virtualenv.create.via_global_ref.builtin.ref import PathRefToDest from virtualenv.create.via_global_ref.builtin.ref import PathRefToDest, RefMust, RefWhen
from virtualenv.util.path import Path from virtualenv.util.path import Path
from ..via_global_self_do import ViaGlobalRefVirtualenvBuiltin from ..via_global_self_do import ViaGlobalRefVirtualenvBuiltin
@ -20,7 +20,8 @@ class PyPy(ViaGlobalRefVirtualenvBuiltin):
def _executables(cls, interpreter): def _executables(cls, interpreter):
host = Path(interpreter.system_executable) host = Path(interpreter.system_executable)
targets = sorted("{}{}".format(name, PyPy.suffix) for name in cls.exe_names(interpreter)) targets = sorted("{}{}".format(name, PyPy.suffix) for name in cls.exe_names(interpreter))
yield host, targets must = RefMust.COPY if interpreter.version_info.major == 2 else RefMust.NA
yield host, targets, must, RefWhen.ANY
@classmethod @classmethod
def exe_names(cls, interpreter): def exe_names(cls, interpreter):

Просмотреть файл

@ -52,8 +52,7 @@ def load_host_site():
add_site_dir = sys.modules["site"].addsitedir add_site_dir = sys.modules["site"].addsitedir
for path in json.loads(site_packages): for path in json.loads(site_packages):
full_path = os.path.abspath(os.path.join(here, path.encode("utf-8"))) full_path = os.path.abspath(os.path.join(here, path.encode("utf-8")))
if full_path not in sys.path: add_site_dir(full_path)
add_site_dir(full_path)
sep = "\\" if sys.platform == "win32" else "/" # no os module here yet - poor mans version sep = "\\" if sys.platform == "win32" else "/" # no os module here yet - poor mans version

Просмотреть файл

@ -17,6 +17,18 @@ from virtualenv.util.path import copy, make_exe, symlink
from virtualenv.util.six import ensure_text from virtualenv.util.six import ensure_text
class RefMust(object):
NA = "NA"
COPY = "copy"
SYMLINK = "symlink"
class RefWhen(object):
ANY = "ANY"
COPY = "copy"
SYMLINK = "symlink"
@add_metaclass(ABCMeta) @add_metaclass(ABCMeta)
class PathRef(object): class PathRef(object):
"""Base class that checks if a file reference can be symlink/copied""" """Base class that checks if a file reference can be symlink/copied"""
@ -24,9 +36,9 @@ class PathRef(object):
FS_SUPPORTS_SYMLINK = fs_supports_symlink() FS_SUPPORTS_SYMLINK = fs_supports_symlink()
FS_CASE_SENSITIVE = fs_is_case_sensitive() FS_CASE_SENSITIVE = fs_is_case_sensitive()
def __init__(self, src, must_symlink, must_copy): def __init__(self, src, must=RefMust.NA, when=RefWhen.ANY):
self.must_symlink = must_symlink self.must = must
self.must_copy = must_copy self.when = when
self.src = src self.src = src
try: try:
self.exists = src.exists() self.exists = src.exists()
@ -35,8 +47,6 @@ class PathRef(object):
self._can_read = None if self.exists else False self._can_read = None if self.exists else False
self._can_copy = None if self.exists else False self._can_copy = None if self.exists else False
self._can_symlink = None if self.exists else False self._can_symlink = None if self.exists else False
if self.must_copy is True and self.must_symlink is True:
raise ValueError("can copy and symlink at the same time")
def __repr__(self): def __repr__(self):
return "{}(src={})".format(self.__class__.__name__, self.src) return "{}(src={})".format(self.__class__.__name__, self.src)
@ -57,7 +67,7 @@ class PathRef(object):
@property @property
def can_copy(self): def can_copy(self):
if self._can_copy is None: if self._can_copy is None:
if self.must_symlink: if self.must == RefMust.SYMLINK:
self._can_copy = self.can_symlink self._can_copy = self.can_symlink
else: else:
self._can_copy = self.can_read self._can_copy = self.can_read
@ -66,7 +76,7 @@ class PathRef(object):
@property @property
def can_symlink(self): def can_symlink(self):
if self._can_symlink is None: if self._can_symlink is None:
if self.must_copy: if self.must == RefMust.COPY:
self._can_symlink = self.can_copy self._can_symlink = self.can_copy
else: else:
self._can_symlink = self.FS_SUPPORTS_SYMLINK and self.can_read self._can_symlink = self.FS_SUPPORTS_SYMLINK and self.can_read
@ -77,9 +87,9 @@ class PathRef(object):
raise NotImplementedError raise NotImplementedError
def method(self, symlinks): def method(self, symlinks):
if self.must_symlink: if self.must == RefMust.SYMLINK:
return symlink return symlink
if self.must_copy: if self.must == RefMust.COPY:
return copy return copy
return symlink if symlinks else copy return symlink if symlinks else copy
@ -88,8 +98,8 @@ class PathRef(object):
class ExePathRef(PathRef): class ExePathRef(PathRef):
"""Base class that checks if a executable can be references via symlink/copy""" """Base class that checks if a executable can be references via symlink/copy"""
def __init__(self, src, must_symlink, must_copy): def __init__(self, src, must=RefMust.NA, when=RefWhen.ANY):
super(ExePathRef, self).__init__(src, must_symlink, must_copy) super(ExePathRef, self).__init__(src, must, when)
self._can_run = None self._can_run = None
@property @property
@ -114,8 +124,8 @@ class ExePathRef(PathRef):
class PathRefToDest(PathRef): class PathRefToDest(PathRef):
"""Link a path on the file system""" """Link a path on the file system"""
def __init__(self, src, dest, must_symlink=False, must_copy=False): def __init__(self, src, dest, must=RefMust.NA, when=RefWhen.ANY):
super(PathRefToDest, self).__init__(src, must_symlink, must_copy) super(PathRefToDest, self).__init__(src, must, when)
self.dest = dest self.dest = dest
def run(self, creator, symlinks): def run(self, creator, symlinks):
@ -131,15 +141,14 @@ class PathRefToDest(PathRef):
class ExePathRefToDest(PathRefToDest, ExePathRef): class ExePathRefToDest(PathRefToDest, ExePathRef):
"""Link a exe path on the file system""" """Link a exe path on the file system"""
def __init__(self, src, targets, dest, must_symlink=False, must_copy=False): def __init__(self, src, targets, dest, must=RefMust.NA, when=RefWhen.ANY):
ExePathRef.__init__(self, src, must_symlink, must_copy) ExePathRef.__init__(self, src, must, when)
PathRefToDest.__init__(self, src, dest, must_symlink, must_copy) PathRefToDest.__init__(self, src, dest, must, when)
if not self.FS_CASE_SENSITIVE: if not self.FS_CASE_SENSITIVE:
targets = list(OrderedDict((i.lower(), None) for i in targets).keys()) targets = list(OrderedDict((i.lower(), None) for i in targets).keys())
self.base = targets[0] self.base = targets[0]
self.aliases = targets[1:] self.aliases = targets[1:]
self.dest = dest self.dest = dest
self.must_copy = must_copy
def run(self, creator, symlinks): def run(self, creator, symlinks):
bin_dir = self.dest(creator, self.src).parent bin_dir = self.dest(creator, self.src).parent

Просмотреть файл

@ -4,7 +4,7 @@ from abc import ABCMeta
from six import add_metaclass from six import add_metaclass
from virtualenv.create.via_global_ref.builtin.ref import ExePathRefToDest from virtualenv.create.via_global_ref.builtin.ref import ExePathRefToDest, RefMust, RefWhen
from virtualenv.util.path import ensure_dir from virtualenv.util.path import ensure_dir
from ..api import ViaGlobalRefApi, ViaGlobalRefMeta from ..api import ViaGlobalRefApi, ViaGlobalRefMeta
@ -27,26 +27,37 @@ class ViaGlobalRefVirtualenvBuiltin(ViaGlobalRefApi, VirtualenvBuiltin):
def can_create(cls, interpreter): def can_create(cls, interpreter):
"""By default all built-in methods assume that if we can describe it we can create it""" """By default all built-in methods assume that if we can describe it we can create it"""
# first we must be able to describe it # first we must be able to describe it
if cls.can_describe(interpreter): if not cls.can_describe(interpreter):
meta = cls.setup_meta(interpreter) return None
if meta is not None and meta: meta = cls.setup_meta(interpreter)
for src in cls.sources(interpreter): if meta is not None and meta:
if src.exists: cls._sources_can_be_applied(interpreter, meta)
if meta.can_copy and not src.can_copy: return meta
meta.copy_error = "cannot copy {}".format(src)
if meta.can_symlink and not src.can_symlink: @classmethod
meta.symlink_error = "cannot symlink {}".format(src) def _sources_can_be_applied(cls, interpreter, meta):
if not meta.can_copy and not meta.can_symlink: for src in cls.sources(interpreter):
meta.error = "neither copy or symlink supported, copy: {} symlink: {}".format( if src.exists:
meta.copy_error, meta.symlink_error, if meta.can_copy and not src.can_copy:
) meta.copy_error = "cannot copy {}".format(src)
else: if meta.can_symlink and not src.can_symlink:
meta.error = "missing required file {}".format(src) meta.symlink_error = "cannot symlink {}".format(src)
if meta.error: else:
break msg = "missing required file {}".format(src)
meta.sources.append(src) if src.when == RefMust.NA:
return meta meta.error = msg
return None elif src.when == RefMust.COPY:
meta.copy_error = msg
elif src.when == RefMust.SYMLINK:
meta.symlink_error = msg
if not meta.can_copy and not meta.can_symlink:
meta.error = "neither copy or symlink supported, copy: {} symlink: {}".format(
meta.copy_error,
meta.symlink_error,
)
if meta.error:
break
meta.sources.append(src)
@classmethod @classmethod
def setup_meta(cls, interpreter): def setup_meta(cls, interpreter):
@ -54,9 +65,8 @@ class ViaGlobalRefVirtualenvBuiltin(ViaGlobalRefApi, VirtualenvBuiltin):
@classmethod @classmethod
def sources(cls, interpreter): def sources(cls, interpreter):
is_py2 = interpreter.version_info.major == 2 for host_exe, targets, must, when in cls._executables(interpreter):
for host_exe, targets in cls._executables(interpreter): yield ExePathRefToDest(host_exe, dest=cls.to_bin, targets=targets, must=must, when=when)
yield ExePathRefToDest(host_exe, dest=cls.to_bin, targets=targets, must_copy=is_py2)
def to_bin(self, src): def to_bin(self, src):
return self.bin_dir / src.name return self.bin_dir / src.name
@ -79,7 +89,12 @@ class ViaGlobalRefVirtualenvBuiltin(ViaGlobalRefApi, VirtualenvBuiltin):
try: try:
self.enable_system_site_package = False self.enable_system_site_package = False
for src in self._sources: for src in self._sources:
src.run(self, self.symlinks) if (
src.when == RefWhen.ANY
or (src.when == RefWhen.SYMLINK and self.symlinks is True)
or (src.when == RefWhen.COPY and self.symlinks is False)
):
src.run(self, self.symlinks)
finally: finally:
if true_system_site != self.enable_system_site_package: if true_system_site != self.enable_system_site_package:
self.enable_system_site_package = true_system_site self.enable_system_site_package = true_system_site
@ -92,7 +107,7 @@ class ViaGlobalRefVirtualenvBuiltin(ViaGlobalRefApi, VirtualenvBuiltin):
""" """
We directly inject the base prefix and base exec prefix to avoid site.py needing to discover these We directly inject the base prefix and base exec prefix to avoid site.py needing to discover these
from home (which usually is done within the interpreter itself) from home (which usually is done within the interpreter itself)
""" """
super(ViaGlobalRefVirtualenvBuiltin, self).set_pyenv_cfg() super(ViaGlobalRefVirtualenvBuiltin, self).set_pyenv_cfg()
self.pyenv_cfg["base-prefix"] = self.interpreter.system_prefix self.pyenv_cfg["base-prefix"] = self.interpreter.system_prefix
self.pyenv_cfg["base-exec-prefix"] = self.interpreter.system_exec_prefix self.pyenv_cfg["base-exec-prefix"] = self.interpreter.system_exec_prefix

Просмотреть файл

@ -46,7 +46,10 @@ class Venv(ViaGlobalRefApi):
from venv import EnvBuilder from venv import EnvBuilder
builder = EnvBuilder( builder = EnvBuilder(
system_site_packages=self.enable_system_site_package, clear=False, symlinks=self.symlinks, with_pip=False, system_site_packages=self.enable_system_site_package,
clear=False,
symlinks=self.symlinks,
with_pip=False,
) )
builder.create(str(self.dest)) builder.create(str(self.dest))

Просмотреть файл

@ -15,7 +15,7 @@ from .py_spec import PythonSpec
class Builtin(Discover): class Builtin(Discover):
def __init__(self, options): def __init__(self, options):
super(Builtin, self).__init__(options) super(Builtin, self).__init__(options)
self.python_spec = options.python self.python_spec = options.python if options.python else [sys.executable]
self.app_data = options.app_data self.app_data = options.app_data
@classmethod @classmethod
@ -25,18 +25,26 @@ class Builtin(Discover):
"--python", "--python",
dest="python", dest="python",
metavar="py", metavar="py",
help="target interpreter for which to create a virtual (either absolute path or identifier string)", type=str,
default=sys.executable, action="append",
default=[],
help="interpreter based on what to create environment (path/identifier) "
"- by default use the interpreter where the tool is installed - first found wins",
) )
def run(self): def run(self):
return get_interpreter(self.python_spec, self.app_data) for python_spec in self.python_spec:
result = get_interpreter(python_spec, self.app_data)
if result is not None:
return result
return None
def __repr__(self): def __repr__(self):
return ensure_str(self.__unicode__()) return ensure_str(self.__unicode__())
def __unicode__(self): def __unicode__(self):
return "{} discover of python_spec={!r}".format(self.__class__.__name__, self.python_spec) spec = self.python_spec[0] if len(self.python_spec) == 1 else self.python_spec
return "{} discover of python_spec={!r}".format(self.__class__.__name__, spec)
def get_interpreter(key, app_data=None): def get_interpreter(key, app_data=None):

Просмотреть файл

@ -104,7 +104,10 @@ def _run_subprocess(cls, exe, app_data):
result.executable = exe # keep original executable as this may contain initialization code result.executable = exe # keep original executable as this may contain initialization code
else: else:
msg = "failed to query {} with code {}{}{}".format( msg = "failed to query {} with code {}{}{}".format(
exe, code, " out: {!r}".format(out) if out else "", " err: {!r}".format(err) if err else "", exe,
code,
" out: {!r}".format(out) if out else "",
" err: {!r}".format(err) if err else "",
) )
failure = RuntimeError(msg) failure = RuntimeError(msg)
return failure, result return failure, result

Просмотреть файл

@ -120,7 +120,7 @@ class PythonInfo(object):
@staticmethod @staticmethod
def _distutils_install(): def _distutils_install():
# follow https://github.com/pypa/pip/blob/master/src/pip/_internal/locations.py#L95 # follow https://github.com/pypa/pip/blob/main/src/pip/_internal/locations.py#L95
# note here we don't import Distribution directly to allow setuptools to patch it # note here we don't import Distribution directly to allow setuptools to patch it
d = dist.Distribution({"script_args": "--no-user-cfg"}) # conf files not parsed so they do not hijack paths d = dist.Distribution({"script_args": "--no-user-cfg"}) # conf files not parsed so they do not hijack paths
if hasattr(sys, "_framework"): if hasattr(sys, "_framework"):
@ -198,7 +198,8 @@ class PythonInfo(object):
def __repr__(self): def __repr__(self):
return "{}({!r})".format( return "{}({!r})".format(
self.__class__.__name__, {k: v for k, v in self.__dict__.items() if not k.startswith("_")}, self.__class__.__name__,
{k: v for k, v in self.__dict__.items() if not k.startswith("_")},
) )
def __str__(self): def __str__(self):

Просмотреть файл

@ -1,8 +1,9 @@
from __future__ import absolute_import, unicode_literals from __future__ import absolute_import, unicode_literals
import logging import logging
from functools import partial
from ..app_data import AppDataAction, AppDataDisabled, TempAppData from ..app_data import make_app_data
from ..config.cli.parser import VirtualEnvConfigParser from ..config.cli.parser import VirtualEnvConfigParser
from ..report import LEVELS, setup_report from ..report import LEVELS, setup_report
from ..run.session import Session from ..run.session import Session
@ -88,32 +89,31 @@ def handle_extra_commands(options):
def load_app_data(args, parser, options): def load_app_data(args, parser, options):
parser.add_argument(
"--read-only-app-data",
action="store_true",
help="use app data folder in read-only mode (write operations will fail with error)",
)
options, _ = parser.parse_known_args(args, namespace=options)
# here we need a write-able application data (e.g. the zipapp might need this for discovery cache) # here we need a write-able application data (e.g. the zipapp might need this for discovery cache)
default_app_data = AppDataAction.default()
parser.add_argument( parser.add_argument(
"--app-data", "--app-data",
dest="app_data",
action=AppDataAction,
default="<temp folder>" if isinstance(default_app_data, AppDataDisabled) else default_app_data,
help="a data folder used as cache by the virtualenv", help="a data folder used as cache by the virtualenv",
type=partial(make_app_data, read_only=options.read_only_app_data),
default=make_app_data(None, read_only=options.read_only_app_data),
) )
parser.add_argument( parser.add_argument(
"--reset-app-data", "--reset-app-data",
dest="reset_app_data",
action="store_true", action="store_true",
help="start with empty app data folder", help="start with empty app data folder",
default=False,
) )
parser.add_argument( parser.add_argument(
"--upgrade-embed-wheels", "--upgrade-embed-wheels",
dest="upgrade_embed_wheels",
action="store_true", action="store_true",
help="trigger a manual update of the embedded wheels", help="trigger a manual update of the embedded wheels",
default=False,
) )
options, _ = parser.parse_known_args(args, namespace=options) options, _ = parser.parse_known_args(args, namespace=options)
if options.app_data == "<temp folder>":
options.app_data = TempAppData()
if options.reset_app_data: if options.reset_app_data:
options.app_data.reset() options.app_data.reset()
return options return options
@ -134,7 +134,8 @@ def _do_report_setup(parser, args, setup_logging):
level_map = ", ".join("{}={}".format(logging.getLevelName(l), c) for c, l in sorted(list(LEVELS.items()))) level_map = ", ".join("{}={}".format(logging.getLevelName(l), c) for c, l in sorted(list(LEVELS.items())))
msg = "verbosity = verbose - quiet, default {}, mapping => {}" msg = "verbosity = verbose - quiet, default {}, mapping => {}"
verbosity_group = parser.add_argument_group( verbosity_group = parser.add_argument_group(
title="verbosity", description=msg.format(logging.getLevelName(LEVELS[3]), level_map), title="verbosity",
description=msg.format(logging.getLevelName(LEVELS[3]), level_map),
) )
verbosity = verbosity_group.add_mutually_exclusive_group() verbosity = verbosity_group.add_mutually_exclusive_group()
verbosity.add_argument("-v", "--verbose", action="count", dest="verbose", help="increase verbosity", default=2) verbosity.add_argument("-v", "--verbose", action="count", dest="verbose", help="increase verbosity", default=2)

Просмотреть файл

@ -18,14 +18,14 @@ class CreatorSelector(ComponentBuilder):
@classmethod @classmethod
def for_interpreter(cls, interpreter): def for_interpreter(cls, interpreter):
key_to_class, key_to_meta, builtin_key, describe = OrderedDict(), {}, None, None key_to_class, key_to_meta, builtin_key, describe = OrderedDict(), {}, None, None
errored = defaultdict(list) errors = defaultdict(list)
for key, creator_class in cls.options("virtualenv.create").items(): for key, creator_class in cls.options("virtualenv.create").items():
if key == "builtin": if key == "builtin":
raise RuntimeError("builtin creator is a reserved name") raise RuntimeError("builtin creator is a reserved name")
meta = creator_class.can_create(interpreter) meta = creator_class.can_create(interpreter)
if meta: if meta:
if meta.error: if meta.error:
errored[meta.error].append(creator_class) errors[meta.error].append(creator_class)
else: else:
if "builtin" not in key_to_class and issubclass(creator_class, VirtualenvBuiltin): if "builtin" not in key_to_class and issubclass(creator_class, VirtualenvBuiltin):
builtin_key = key builtin_key = key
@ -36,16 +36,16 @@ class CreatorSelector(ComponentBuilder):
if describe is None and issubclass(creator_class, Describe) and creator_class.can_describe(interpreter): if describe is None and issubclass(creator_class, Describe) and creator_class.can_describe(interpreter):
describe = creator_class describe = creator_class
if not key_to_meta: if not key_to_meta:
if errored: if errors:
raise RuntimeError( rows = ["{} for creators {}".format(k, ", ".join(i.__name__ for i in v)) for k, v in errors.items()]
"\n".join( raise RuntimeError("\n".join(rows))
"{} for creators {}".format(k, ", ".join(i.__name__ for i in v)) for k, v in errored.items()
),
)
else: else:
raise RuntimeError("No virtualenv implementation for {}".format(interpreter)) raise RuntimeError("No virtualenv implementation for {}".format(interpreter))
return CreatorInfo( return CreatorInfo(
key_to_class=key_to_class, key_to_meta=key_to_meta, describe=describe, builtin_key=builtin_key, key_to_class=key_to_class,
key_to_meta=key_to_meta,
describe=describe,
builtin_key=builtin_key,
) )
def add_selector_arg_parse(self, name, choices): def add_selector_arg_parse(self, name, choices):

Просмотреть файл

@ -10,7 +10,8 @@ class Discovery(PluginLoader):
def get_discover(parser, args): def get_discover(parser, args):
discover_types = Discovery.entry_points_for("virtualenv.discovery") discover_types = Discovery.entry_points_for("virtualenv.discovery")
discovery_parser = parser.add_argument_group( discovery_parser = parser.add_argument_group(
title="discovery", description="discover and provide a target interpreter", title="discovery",
description="discover and provide a target interpreter",
) )
discovery_parser.add_argument( discovery_parser.add_argument(
"--discovery", "--discovery",

Просмотреть файл

@ -17,7 +17,11 @@ class SeederSelector(ComponentBuilder):
help="seed packages install method", help="seed packages install method",
) )
self.parser.add_argument( self.parser.add_argument(
"--no-seed", "--without-pip", help="do not install seed packages", action="store_true", dest="no_seed", "--no-seed",
"--without-pip",
help="do not install seed packages",
action="store_true",
dest="no_seed",
) )
@staticmethod @staticmethod

Просмотреть файл

@ -62,7 +62,8 @@ class Session(object):
def _activate(self): def _activate(self):
if self.activators: if self.activators:
logging.info( logging.info(
"add activators for %s", ", ".join(type(i).__name__.replace("Activator", "") for i in self.activators), "add activators for %s",
", ".join(type(i).__name__.replace("Activator", "") for i in self.activators),
) )
for activator in self.activators: for activator in self.activators:
activator.generate(self.creator) activator.generate(self.creator)

Просмотреть файл

@ -109,7 +109,8 @@ class BaseEmbed(Seeder):
if getattr(self, "no_{}".format(distribution)): if getattr(self, "no_{}".format(distribution)):
continue continue
result += " {}{},".format( result += " {}{},".format(
distribution, "={}".format(getattr(self, "{}_version".format(distribution), None) or "latest"), distribution,
"={}".format(getattr(self, "{}_version".format(distribution), None) or "latest"),
) )
return result[:-1] + ")" return result[:-1] + ")"

Просмотреть файл

@ -8,14 +8,10 @@ from contextlib import contextmanager
from subprocess import CalledProcessError from subprocess import CalledProcessError
from threading import Lock, Thread from threading import Lock, Thread
import six
from virtualenv.info import fs_supports_symlink from virtualenv.info import fs_supports_symlink
from virtualenv.seed.embed.base_embed import BaseEmbed from virtualenv.seed.embed.base_embed import BaseEmbed
from virtualenv.seed.wheels import get_wheel from virtualenv.seed.wheels import get_wheel
from virtualenv.util.lock import _CountedFileLock
from virtualenv.util.path import Path from virtualenv.util.path import Path
from virtualenv.util.six import ensure_text
from .pip_install.copy import CopyPipInstall from .pip_install.copy import CopyPipInstall
from .pip_install.symlink import SymlinkPipInstall from .pip_install.symlink import SymlinkPipInstall
@ -54,7 +50,8 @@ class FromAppData(BaseEmbed):
key = Path(installer_class.__name__) / wheel.path.stem key = Path(installer_class.__name__) / wheel.path.stem
wheel_img = self.app_data.wheel_image(creator.interpreter.version_release_str, key) wheel_img = self.app_data.wheel_image(creator.interpreter.version_release_str, key)
installer = installer_class(wheel.path, creator, wheel_img) installer = installer_class(wheel.path, creator, wheel_img)
with _CountedFileLock(ensure_text(str(wheel_img.parent / "{}.lock".format(wheel_img.name)))): parent = self.app_data.lock / wheel_img.parent
with parent.non_reentrant_lock_for_key(wheel_img.name):
if not installer.has_image(): if not installer.has_image():
installer.build_image() installer.build_image()
installer.install(creator.interpreter.version_info) installer.install(creator.interpreter.version_info)
@ -104,7 +101,7 @@ class FromAppData(BaseEmbed):
if version is not None: if version is not None:
msg += " version {}".format(version) msg += " version {}".format(version)
msg += ", pip download exit code {}".format(failure.returncode) msg += ", pip download exit code {}".format(failure.returncode)
output = failure.output if six.PY2 else (failure.output + failure.stderr) output = failure.output if sys.version_info < (3, 5) else (failure.output + failure.stderr)
if output: if output:
msg += "\n" msg += "\n"
msg += output msg += output

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше