зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
2ea65ad1e2
Коммит
9f175925f2
|
@ -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
|
631
third_party/python/virtualenv/__virtualenv__/importlib_metadata-3.1.1-py3-none-any/importlib_metadata/__init__.py
поставляемый
Normal file
631
third_party/python/virtualenv/__virtualenv__/importlib_metadata-3.1.1-py3-none-any/importlib_metadata/__init__.py
поставляемый
Normal file
|
@ -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
|
75
third_party/python/virtualenv/__virtualenv__/importlib_metadata-3.1.1-py3-none-any/importlib_metadata/_compat.py
поставляемый
Normal file
75
third_party/python/virtualenv/__virtualenv__/importlib_metadata-3.1.1-py3-none-any/importlib_metadata/_compat.py
поставляемый
Normal file
|
@ -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)
|
107
third_party/python/virtualenv/__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/_py2.py
поставляемый
Normal file
107
third_party/python/virtualenv/__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/_py2.py
поставляемый
Normal file
|
@ -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())
|
160
third_party/python/virtualenv/__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/_py3.py
поставляемый
Normal file
160
third_party/python/virtualenv/__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/_py3.py
поставляемый
Normal file
|
@ -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
|
142
third_party/python/virtualenv/__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/abc.py
поставляемый
Normal file
142
third_party/python/virtualenv/__virtualenv__/importlib_resources-3.3.0-py2.py3-none-any/importlib_resources/abc.py
поставляемый
Normal file
|
@ -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
|
||||||
|
|
6
third_party/python/virtualenv/__virtualenv__/zipp-3.4.0-py3-none-any/zipp-3.4.0.dist-info/RECORD
поставляемый
Normal file
6
third_party/python/virtualenv/__virtualenv__/zipp-3.4.0-py3-none-any/zipp-3.4.0.dist-info/RECORD
поставляемый
Normal file
|
@ -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,,
|
5
third_party/python/virtualenv/__virtualenv__/zipp-3.4.0-py3-none-any/zipp-3.4.0.dist-info/WHEEL
поставляемый
Normal file
5
third_party/python/virtualenv/__virtualenv__/zipp-3.4.0-py3-none-any/zipp-3.4.0.dist-info/WHEEL
поставляемый
Normal file
|
@ -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"
|
||||||
},
|
},
|
||||||
|
|
|
@ -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):
|
||||||
""""""
|
""""""
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче