summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBernát Gábor <gaborjbernat@gmail.com>2022-07-25 00:33:42 -0700
committerGitHub <noreply@github.com>2022-07-25 00:33:42 -0700
commitb85542c31ca8afcff317e618da434f59fa06d122 (patch)
tree450066fe494d366c03da70b0de10899d5738d425 /src
parent3c57468470c292b235a67b27cec9468cc913f268 (diff)
downloadvirtualenv-b85542c31ca8afcff317e618da434f59fa06d122.tar.gz
Drop support of running under Python 2.7 (#2382)
Diffstat (limited to 'src')
-rw-r--r--src/virtualenv/__init__.py6
-rw-r--r--src/virtualenv/__main__.py31
-rw-r--r--src/virtualenv/activation/__init__.py2
-rw-r--r--src/virtualenv/activation/activator.py16
-rw-r--r--src/virtualenv/activation/bash/__init__.py9
-rw-r--r--src/virtualenv/activation/batch/__init__.py12
-rw-r--r--src/virtualenv/activation/cshell/__init__.py9
-rw-r--r--src/virtualenv/activation/fish/__init__.py9
-rw-r--r--src/virtualenv/activation/nushell/__init__.py19
-rw-r--r--src/virtualenv/activation/powershell/__init__.py9
-rw-r--r--src/virtualenv/activation/python/__init__.py17
-rw-r--r--src/virtualenv/activation/python/activate_this.py1
-rw-r--r--src/virtualenv/activation/via_template.py23
-rw-r--r--src/virtualenv/app_data/__init__.py7
-rw-r--r--src/virtualenv/app_data/base.py15
-rw-r--r--src/virtualenv/app_data/na.py16
-rw-r--r--src/virtualenv/app_data/read_only.py13
-rw-r--r--src/virtualenv/app_data/via_disk_folder.py37
-rw-r--r--src/virtualenv/app_data/via_tempdir.py9
-rw-r--r--src/virtualenv/config/__init__.py1
-rw-r--r--src/virtualenv/config/cli/__init__.py1
-rw-r--r--src/virtualenv/config/cli/parser.py30
-rw-r--r--src/virtualenv/config/convert.py12
-rw-r--r--src/virtualenv/config/env_var.py14
-rw-r--r--src/virtualenv/config/ini.py38
-rw-r--r--src/virtualenv/create/__init__.py1
-rw-r--r--src/virtualenv/create/creator.py76
-rw-r--r--src/virtualenv/create/describe.py52
-rw-r--r--src/virtualenv/create/pyenv_cfg.py17
-rw-r--r--src/virtualenv/create/via_global_ref/api.py30
-rw-r--r--src/virtualenv/create/via_global_ref/builtin/builtin_way.py12
-rw-r--r--src/virtualenv/create/via_global_ref/builtin/cpython/__init__.py1
-rw-r--r--src/virtualenv/create/via_global_ref/builtin/cpython/common.py29
-rw-r--r--src/virtualenv/create/via_global_ref/builtin/cpython/cpython2.py40
-rw-r--r--src/virtualenv/create/via_global_ref/builtin/cpython/cpython3.py33
-rw-r--r--src/virtualenv/create/via_global_ref/builtin/cpython/mac_os.py70
-rw-r--r--src/virtualenv/create/via_global_ref/builtin/pypy/common.py31
-rw-r--r--src/virtualenv/create/via_global_ref/builtin/pypy/pypy2.py37
-rw-r--r--src/virtualenv/create/via_global_ref/builtin/pypy/pypy3.py26
-rw-r--r--src/virtualenv/create/via_global_ref/builtin/python2/python2.py25
-rw-r--r--src/virtualenv/create/via_global_ref/builtin/ref.py34
-rw-r--r--src/virtualenv/create/via_global_ref/builtin/via_global_self_do.py34
-rw-r--r--src/virtualenv/create/via_global_ref/store.py8
-rw-r--r--src/virtualenv/create/via_global_ref/venv.py20
-rw-r--r--src/virtualenv/discovery/__init__.py1
-rw-r--r--src/virtualenv/discovery/builtin.py39
-rw-r--r--src/virtualenv/discovery/cached_py_info.py50
-rw-r--r--src/virtualenv/discovery/discover.py14
-rw-r--r--src/virtualenv/discovery/py_spec.py29
-rw-r--r--src/virtualenv/discovery/windows/__init__.py10
-rw-r--r--src/virtualenv/discovery/windows/pep514.py46
-rw-r--r--src/virtualenv/info.py11
-rw-r--r--src/virtualenv/report.py14
-rw-r--r--src/virtualenv/run/__init__.py12
-rw-r--r--src/virtualenv/run/plugin/activators.py13
-rw-r--r--src/virtualenv/run/plugin/base.py14
-rw-r--r--src/virtualenv/run/plugin/creators.py24
-rw-r--r--src/virtualenv/run/plugin/discovery.py10
-rw-r--r--src/virtualenv/run/plugin/seeders.py13
-rw-r--r--src/virtualenv/run/session.py24
-rw-r--r--src/virtualenv/seed/__init__.py1
-rw-r--r--src/virtualenv/seed/embed/base_embed.py51
-rw-r--r--src/virtualenv/seed/embed/pip_invoke.py15
-rw-r--r--src/virtualenv/seed/embed/via_app_data/pip_install/base.py44
-rw-r--r--src/virtualenv/seed/embed/via_app_data/pip_install/copy.py21
-rw-r--r--src/virtualenv/seed/embed/via_app_data/pip_install/symlink.py30
-rw-r--r--src/virtualenv/seed/embed/via_app_data/via_app_data.py37
-rw-r--r--src/virtualenv/seed/seeder.py13
-rw-r--r--src/virtualenv/seed/wheels/__init__.py6
-rw-r--r--src/virtualenv/seed/wheels/acquire.py40
-rw-r--r--src/virtualenv/seed/wheels/bundle.py13
-rw-r--r--src/virtualenv/seed/wheels/embed/__init__.py7
-rw-r--r--src/virtualenv/seed/wheels/periodic_update.py58
-rw-r--r--src/virtualenv/seed/wheels/util.py28
-rw-r--r--src/virtualenv/util/__init__.py11
-rw-r--r--src/virtualenv/util/error.py3
-rw-r--r--src/virtualenv/util/lock.py26
-rw-r--r--src/virtualenv/util/path/__init__.py8
-rw-r--r--src/virtualenv/util/path/_pathlib/__init__.py17
-rw-r--r--src/virtualenv/util/path/_pathlib/via_os_path.py160
-rw-r--r--src/virtualenv/util/path/_permission.py6
-rw-r--r--src/virtualenv/util/path/_sync.py37
-rw-r--r--src/virtualenv/util/path/_win.py5
-rw-r--r--src/virtualenv/util/six.py50
-rw-r--r--src/virtualenv/util/subprocess/__init__.py20
-rw-r--r--src/virtualenv/util/subprocess/_win_subprocess.py176
-rw-r--r--src/virtualenv/util/zipapp.py11
87 files changed, 787 insertions, 1363 deletions
diff --git a/src/virtualenv/__init__.py b/src/virtualenv/__init__.py
index 5f74e3e..e40e8b7 100644
--- a/src/virtualenv/__init__.py
+++ b/src/virtualenv/__init__.py
@@ -1,10 +1,8 @@
-from __future__ import absolute_import, unicode_literals
-
from .run import cli_run, session_via_cli
from .version import __version__
-__all__ = (
+__all__ = [
"__version__",
"cli_run",
"session_via_cli",
-)
+]
diff --git a/src/virtualenv/__main__.py b/src/virtualenv/__main__.py
index 3b06fd7..c3c5adf 100644
--- a/src/virtualenv/__main__.py
+++ b/src/virtualenv/__main__.py
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, print_function, unicode_literals
-
import logging
import os
import sys
@@ -18,41 +16,32 @@ def run(args=None, options=None, env=None):
session = cli_run(args, options, env)
logging.warning(LogSession(session, start))
except ProcessCallFailed as exception:
- print("subprocess call failed for {} with code {}".format(exception.cmd, exception.code))
+ print(f"subprocess call failed for {exception.cmd} with code {exception.code}")
print(exception.out, file=sys.stdout, end="")
print(exception.err, file=sys.stderr, end="")
raise SystemExit(exception.code)
-class LogSession(object):
+class LogSession:
def __init__(self, session, start):
self.session = session
self.start = start
def __str__(self):
- from virtualenv.util.six import ensure_text
-
spec = self.session.creator.interpreter.spec
elapsed = (datetime.now() - self.start).total_seconds() * 1000
lines = [
- "created virtual environment {} in {:.0f}ms".format(spec, elapsed),
- " creator {}".format(ensure_text(str(self.session.creator))),
+ f"created virtual environment {spec} in {elapsed:.0f}ms",
+ f" creator {str(self.session.creator)}",
]
if self.session.seeder.enabled:
- lines += (
- " seeder {}".format(ensure_text(str(self.session.seeder))),
- " added seed packages: {}".format(
- ", ".join(
- sorted(
- "==".join(i.stem.split("-"))
- for i in self.session.creator.purelib.iterdir()
- if i.suffix == ".dist-info"
- ),
- ),
- ),
- )
+ lines.append(f" seeder {str(self.session.seeder)}")
+ path = self.session.creator.purelib.iterdir()
+ packages = sorted("==".join(i.stem.split("-")) for i in path if i.suffix == ".dist-info")
+ lines.append(f" added seed packages: {', '.join(packages)}")
+
if self.session.activators:
- lines.append(" activators {}".format(",".join(i.__class__.__name__ for i in self.session.activators)))
+ lines.append(f" activators {','.join(i.__class__.__name__ for i in self.session.activators)}")
return "\n".join(lines)
diff --git a/src/virtualenv/activation/__init__.py b/src/virtualenv/activation/__init__.py
index e9296d8..99984bc 100644
--- a/src/virtualenv/activation/__init__.py
+++ b/src/virtualenv/activation/__init__.py
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, unicode_literals
-
from .bash import BashActivator
from .batch import BatchActivator
from .cshell import CShellActivator
diff --git a/src/virtualenv/activation/activator.py b/src/virtualenv/activation/activator.py
index 80d7e47..ad9d9e0 100644
--- a/src/virtualenv/activation/activator.py
+++ b/src/virtualenv/activation/activator.py
@@ -1,14 +1,9 @@
-from __future__ import absolute_import, unicode_literals
-
import os
from abc import ABCMeta, abstractmethod
-from six import add_metaclass
-
-@add_metaclass(ABCMeta)
-class Activator(object):
- """Generates an activate script for the virtual environment"""
+class Activator(metaclass=ABCMeta):
+ """Generates activate script for the virtual environment"""
def __init__(self, options):
"""Create a new activator generator.
@@ -37,9 +32,14 @@ class Activator(object):
@abstractmethod
def generate(self, creator):
- """Generate the activate script for the given creator.
+ """Generate activate script for the given creator.
:param creator: the creator (based of :class:`virtualenv.create.creator.Creator`) we used to create this \
virtual environment
"""
raise NotImplementedError
+
+
+__all__ = [
+ "Activator",
+]
diff --git a/src/virtualenv/activation/bash/__init__.py b/src/virtualenv/activation/bash/__init__.py
index 22c90c3..e704126 100644
--- a/src/virtualenv/activation/bash/__init__.py
+++ b/src/virtualenv/activation/bash/__init__.py
@@ -1,6 +1,4 @@
-from __future__ import absolute_import, unicode_literals
-
-from virtualenv.util.path import Path
+from pathlib import Path
from ..via_template import ViaTemplateActivator
@@ -11,3 +9,8 @@ class BashActivator(ViaTemplateActivator):
def as_name(self, template):
return template.stem
+
+
+__all__ = [
+ "BashActivator",
+]
diff --git a/src/virtualenv/activation/batch/__init__.py b/src/virtualenv/activation/batch/__init__.py
index 4149712..6c35337 100644
--- a/src/virtualenv/activation/batch/__init__.py
+++ b/src/virtualenv/activation/batch/__init__.py
@@ -1,8 +1,5 @@
-from __future__ import absolute_import, unicode_literals
-
import os
-
-from virtualenv.util.path import Path
+from pathlib import Path
from ..via_template import ViaTemplateActivator
@@ -19,5 +16,10 @@ class BatchActivator(ViaTemplateActivator):
def instantiate_template(self, replacements, template, creator):
# ensure the text has all newlines as \r\n - required by batch
- base = super(BatchActivator, self).instantiate_template(replacements, template, creator)
+ base = super().instantiate_template(replacements, template, creator)
return base.replace(os.linesep, "\n").replace("\n", os.linesep)
+
+
+__all__ = [
+ "BatchActivator",
+]
diff --git a/src/virtualenv/activation/cshell/__init__.py b/src/virtualenv/activation/cshell/__init__.py
index b25c602..b225ba3 100644
--- a/src/virtualenv/activation/cshell/__init__.py
+++ b/src/virtualenv/activation/cshell/__init__.py
@@ -1,6 +1,4 @@
-from __future__ import absolute_import, unicode_literals
-
-from virtualenv.util.path import Path
+from pathlib import Path
from ..via_template import ViaTemplateActivator
@@ -12,3 +10,8 @@ class CShellActivator(ViaTemplateActivator):
def templates(self):
yield Path("activate.csh")
+
+
+__all__ = [
+ "CShellActivator",
+]
diff --git a/src/virtualenv/activation/fish/__init__.py b/src/virtualenv/activation/fish/__init__.py
index 8d0e19c..4b24042 100644
--- a/src/virtualenv/activation/fish/__init__.py
+++ b/src/virtualenv/activation/fish/__init__.py
@@ -1,6 +1,4 @@
-from __future__ import absolute_import, unicode_literals
-
-from virtualenv.util.path import Path
+from pathlib import Path
from ..via_template import ViaTemplateActivator
@@ -8,3 +6,8 @@ from ..via_template import ViaTemplateActivator
class FishActivator(ViaTemplateActivator):
def templates(self):
yield Path("activate.fish")
+
+
+__all__ = [
+ "FishActivator",
+]
diff --git a/src/virtualenv/activation/nushell/__init__.py b/src/virtualenv/activation/nushell/__init__.py
index 994c1fb..839c19c 100644
--- a/src/virtualenv/activation/nushell/__init__.py
+++ b/src/virtualenv/activation/nushell/__init__.py
@@ -1,9 +1,5 @@
-from __future__ import absolute_import, unicode_literals
-
import os
-
-from virtualenv.util.path import Path
-from virtualenv.util.six import ensure_text
+from pathlib import Path
from ..via_template import ViaTemplateActivator
@@ -20,9 +16,14 @@ class NushellActivator(ViaTemplateActivator):
return {
"__VIRTUAL_PROMPT__": "" if self.flag_prompt is None else self.flag_prompt,
- "__VIRTUAL_ENV__": ensure_text(str(creator.dest)),
+ "__VIRTUAL_ENV__": str(creator.dest),
"__VIRTUAL_NAME__": creator.env_name,
- "__BIN_NAME__": ensure_text(str(creator.bin_dir.relative_to(creator.dest))),
- "__PATH_SEP__": ensure_text(os.pathsep),
- "__DEACTIVATE_PATH__": ensure_text(str(Path(dest_folder) / "deactivate.nu")),
+ "__BIN_NAME__": str(creator.bin_dir.relative_to(creator.dest)),
+ "__PATH_SEP__": os.pathsep,
+ "__DEACTIVATE_PATH__": str(Path(dest_folder) / "deactivate.nu"),
}
+
+
+__all__ = [
+ "NushellActivator",
+]
diff --git a/src/virtualenv/activation/powershell/__init__.py b/src/virtualenv/activation/powershell/__init__.py
index 4fadc63..6d561bf 100644
--- a/src/virtualenv/activation/powershell/__init__.py
+++ b/src/virtualenv/activation/powershell/__init__.py
@@ -1,6 +1,4 @@
-from __future__ import absolute_import, unicode_literals
-
-from virtualenv.util.path import Path
+from pathlib import Path
from ..via_template import ViaTemplateActivator
@@ -8,3 +6,8 @@ from ..via_template import ViaTemplateActivator
class PowerShellActivator(ViaTemplateActivator):
def templates(self):
yield Path("activate.ps1")
+
+
+__all__ = [
+ "PowerShellActivator",
+]
diff --git a/src/virtualenv/activation/python/__init__.py b/src/virtualenv/activation/python/__init__.py
index 9e57912..ad38201 100644
--- a/src/virtualenv/activation/python/__init__.py
+++ b/src/virtualenv/activation/python/__init__.py
@@ -1,11 +1,7 @@
-from __future__ import absolute_import, unicode_literals
-
import os
import sys
from collections import OrderedDict
-
-from virtualenv.util.path import Path
-from virtualenv.util.six import ensure_text
+from pathlib import Path
from ..via_template import ViaTemplateActivator
@@ -15,12 +11,12 @@ class PythonActivator(ViaTemplateActivator):
yield Path("activate_this.py")
def replacements(self, creator, dest_folder):
- replacements = super(PythonActivator, self).replacements(creator, dest_folder)
+ replacements = super().replacements(creator, dest_folder)
lib_folders = OrderedDict((os.path.relpath(str(i), str(dest_folder)), None) for i in creator.libs)
win_py2 = creator.interpreter.platform == "win32" and creator.interpreter.version_info.major == 2
replacements.update(
{
- "__LIB_FOLDERS__": ensure_text(os.pathsep.join(lib_folders.keys())),
+ "__LIB_FOLDERS__": os.pathsep.join(lib_folders.keys()),
"__DECODE_PATH__": ("yes" if win_py2 else ""),
},
)
@@ -31,5 +27,10 @@ class PythonActivator(ViaTemplateActivator):
py2 = creator.interpreter.version_info.major == 2
if py2: # on Python 2 we need to encode this into explicit utf-8, py3 supports unicode literals
start = 2 if sys.version_info[0] == 3 else 1
- value = ensure_text(repr(value.encode("utf-8"))[start:-1])
+ value = repr(value.encode("utf-8"))[start:-1]
return value
+
+
+__all__ = [
+ "PythonActivator",
+]
diff --git a/src/virtualenv/activation/python/activate_this.py b/src/virtualenv/activation/python/activate_this.py
index 29debe3..e8eeb84 100644
--- a/src/virtualenv/activation/python/activate_this.py
+++ b/src/virtualenv/activation/python/activate_this.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""Activate virtualenv for current interpreter:
Use exec(open(this_file).read(), {'__file__': this_file}).
diff --git a/src/virtualenv/activation/via_template.py b/src/virtualenv/activation/via_template.py
index 14f0979..75ecd83 100644
--- a/src/virtualenv/activation/via_template.py
+++ b/src/virtualenv/activation/via_template.py
@@ -1,13 +1,7 @@
-from __future__ import absolute_import, unicode_literals
-
import os
import sys
from abc import ABCMeta, abstractmethod
-from six import add_metaclass
-
-from virtualenv.util.six import ensure_text
-
from .activator import Activator
if sys.version_info >= (3, 7):
@@ -16,8 +10,7 @@ else:
from importlib_resources import read_binary
-@add_metaclass(ABCMeta)
-class ViaTemplateActivator(Activator):
+class ViaTemplateActivator(Activator, metaclass=ABCMeta):
@abstractmethod
def templates(self):
raise NotImplementedError
@@ -33,10 +26,10 @@ class ViaTemplateActivator(Activator):
def replacements(self, creator, dest_folder):
return {
"__VIRTUAL_PROMPT__": "" if self.flag_prompt is None else self.flag_prompt,
- "__VIRTUAL_ENV__": ensure_text(str(creator.dest)),
+ "__VIRTUAL_ENV__": str(creator.dest),
"__VIRTUAL_NAME__": creator.env_name,
- "__BIN_NAME__": ensure_text(str(creator.bin_dir.relative_to(creator.dest))),
- "__PATH_SEP__": ensure_text(os.pathsep),
+ "__BIN_NAME__": str(creator.bin_dir.relative_to(creator.dest)),
+ "__PATH_SEP__": os.pathsep,
}
def _generate(self, replacements, templates, to_folder, creator):
@@ -63,5 +56,9 @@ class ViaTemplateActivator(Activator):
@staticmethod
def _repr_unicode(creator, value):
- # by default we just let it be unicode
- return value
+ return value # by default we just let it be unicode
+
+
+__all__ = [
+ "ViaTemplateActivator",
+]
diff --git a/src/virtualenv/app_data/__init__.py b/src/virtualenv/app_data/__init__.py
index e56e63d..262ac07 100644
--- a/src/virtualenv/app_data/__init__.py
+++ b/src/virtualenv/app_data/__init__.py
@@ -1,7 +1,6 @@
"""
Application data stored by virtualenv.
"""
-from __future__ import absolute_import, unicode_literals
import logging
import os
@@ -15,7 +14,7 @@ from .via_tempdir import TempAppData
def _default_app_data_dir(env):
- key = str("VIRTUALENV_OVERRIDE_APP_DATA")
+ key = "VIRTUALENV_OVERRIDE_APP_DATA"
if key in env:
return env[key]
else:
@@ -23,7 +22,7 @@ def _default_app_data_dir(env):
def make_app_data(folder, **kwargs):
- read_only = kwargs.pop("read_only")
+ is_read_only = kwargs.pop("read_only")
env = kwargs.pop("env")
if kwargs: # py3+ kwonly
raise TypeError("unexpected keywords: {}")
@@ -32,7 +31,7 @@ def make_app_data(folder, **kwargs):
folder = _default_app_data_dir(env)
folder = os.path.abspath(folder)
- if read_only:
+ if is_read_only:
return ReadOnlyAppData(folder)
if not os.path.isdir(folder):
diff --git a/src/virtualenv/app_data/base.py b/src/virtualenv/app_data/base.py
index 4ea54d9..bc28b23 100644
--- a/src/virtualenv/app_data/base.py
+++ b/src/virtualenv/app_data/base.py
@@ -1,18 +1,14 @@
"""
Application data stored by virtualenv.
"""
-from __future__ import absolute_import, unicode_literals
from abc import ABCMeta, abstractmethod
from contextlib import contextmanager
-import six
-
from virtualenv.info import IS_ZIPAPP
-@six.add_metaclass(ABCMeta)
-class AppData(object):
+class AppData(metaclass=ABCMeta):
"""Abstract storage interface for the virtualenv application"""
@abstractmethod
@@ -71,8 +67,7 @@ class AppData(object):
raise NotImplementedError
-@six.add_metaclass(ABCMeta)
-class ContentStore(object):
+class ContentStore(metaclass=ABCMeta):
@abstractmethod
def exists(self):
raise NotImplementedError
@@ -93,3 +88,9 @@ class ContentStore(object):
@contextmanager
def locked(self):
pass
+
+
+__all__ = [
+ "ContentStore",
+ "AppData",
+]
diff --git a/src/virtualenv/app_data/na.py b/src/virtualenv/app_data/na.py
index d589787..da45f58 100644
--- a/src/virtualenv/app_data/na.py
+++ b/src/virtualenv/app_data/na.py
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, unicode_literals
-
from contextlib import contextmanager
from .base import AppData, ContentStore
@@ -44,7 +42,7 @@ class AppDataDisabled(AppData):
raise self.error
def py_info_clear(self):
- """ """
+ """nothing to clear"""
class ContentStoreNA(ContentStore):
@@ -52,15 +50,21 @@ class ContentStoreNA(ContentStore):
return False
def read(self):
- """ """
+ """nothing to read"""
return None
def write(self, content):
- """ """
+ """nothing to write"""
def remove(self):
- """ """
+ """nothing to remove"""
@contextmanager
def locked(self):
yield
+
+
+__all__ = [
+ "AppDataDisabled",
+ "ContentStoreNA",
+]
diff --git a/src/virtualenv/app_data/read_only.py b/src/virtualenv/app_data/read_only.py
index 858978c..2663731 100644
--- a/src/virtualenv/app_data/read_only.py
+++ b/src/virtualenv/app_data/read_only.py
@@ -8,15 +8,16 @@ from .via_disk_folder import AppDataDiskFolder, PyInfoStoreDisk
class ReadOnlyAppData(AppDataDiskFolder):
can_update = False
- def __init__(self, folder): # type: (str) -> None
+ def __init__(self, folder: str) -> None:
if not os.path.isdir(folder):
- raise RuntimeError("read-only app data directory {} does not exist".format(folder))
+ raise RuntimeError(f"read-only app data directory {folder} does not exist")
+ super().__init__(folder)
self.lock = NoOpFileLock(folder)
- def reset(self): # type: () -> None
+ def reset(self) -> None:
raise RuntimeError("read-only app data does not support reset")
- def py_info_clear(self): # type: () -> None
+ def py_info_clear(self) -> None:
raise NotImplementedError
def py_info(self, path):
@@ -31,4 +32,6 @@ class _PyInfoStoreDiskReadOnly(PyInfoStoreDisk):
raise RuntimeError("read-only app data python info cannot be updated")
-__all__ = ("ReadOnlyAppData",)
+__all__ = [
+ "ReadOnlyAppData",
+]
diff --git a/src/virtualenv/app_data/via_disk_folder.py b/src/virtualenv/app_data/via_disk_folder.py
index 3f6afd5..94c4def 100644
--- a/src/virtualenv/app_data/via_disk_folder.py
+++ b/src/virtualenv/app_data/via_disk_folder.py
@@ -1,12 +1,11 @@
-# -*- coding: utf-8 -*-
"""
A rough layout of the current storage goes as:
virtualenv-app-data
├── py - <version> <cache information about python interpreters>
-│   └── *.json/lock
+│ └── *.json/lock
├── wheel <cache wheels used for seeding>
-│   ├── house
+│ ├── house
│ │ └── *.whl <wheels downloaded go here>
│ └── <python major.minor> -> 3.9
│ ├── img-<version>
@@ -22,7 +21,6 @@ virtualenv-app-data
├── debug.py
└── _virtualenv.py
"""
-from __future__ import absolute_import, unicode_literals
import json
import logging
@@ -30,11 +28,8 @@ from abc import ABCMeta
from contextlib import contextmanager
from hashlib import sha256
-import six
-
from virtualenv.util.lock import ReentrantFileLock
from virtualenv.util.path import safe_delete
-from virtualenv.util.six import ensure_text
from virtualenv.util.zipapp import extract
from virtualenv.version import __version__
@@ -53,7 +48,7 @@ class AppDataDiskFolder(AppData):
self.lock = ReentrantFileLock(folder)
def __repr__(self):
- return "{}({})".format(type(self).__name__, self.lock.path)
+ return f"{type(self).__name__}({self.lock.path})"
def __str__(self):
return str(self.lock.path)
@@ -113,8 +108,7 @@ class AppDataDiskFolder(AppData):
return self.lock.path / "wheel" / for_py_version / "image" / "1" / name
-@six.add_metaclass(ABCMeta)
-class JSONStoreDisk(ContentStore):
+class JSONStoreDisk(ContentStore, metaclass=ABCMeta):
def __init__(self, in_folder, key, msg, msg_args):
self.in_folder = in_folder
self.key = key
@@ -123,7 +117,7 @@ class JSONStoreDisk(ContentStore):
@property
def file(self):
- return self.in_folder.path / "{}.json".format(self.key)
+ return self.in_folder.path / f"{self.key}.json"
def exists(self):
return self.file.exists()
@@ -132,7 +126,7 @@ class JSONStoreDisk(ContentStore):
data, bad_format = None, False
try:
data = json.loads(self.file.read_text())
- logging.debug("got {} from %s".format(self.msg), *self.msg_args)
+ logging.debug(f"got {self.msg} from %s", *self.msg_args)
return data
except ValueError:
bad_format = True
@@ -147,7 +141,7 @@ class JSONStoreDisk(ContentStore):
def remove(self):
self.file.unlink()
- logging.debug("removed {} at %s".format(self.msg), *self.msg_args)
+ logging.debug(f"removed {self.msg} at %s", *self.msg_args)
@contextmanager
def locked(self):
@@ -157,21 +151,28 @@ class JSONStoreDisk(ContentStore):
def write(self, content):
folder = self.file.parent
folder.mkdir(parents=True, exist_ok=True)
- 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)
+ self.file.write_text(json.dumps(content, sort_keys=True, indent=2))
+ logging.debug(f"wrote {self.msg} at %s", *self.msg_args)
class PyInfoStoreDisk(JSONStoreDisk):
def __init__(self, in_folder, path):
- key = sha256(str(path).encode("utf-8") if six.PY3 else str(path)).hexdigest()
- super(PyInfoStoreDisk, self).__init__(in_folder, key, "python info of %s", (path,))
+ key = sha256(str(path).encode("utf-8")).hexdigest()
+ super().__init__(in_folder, key, "python info of %s", (path,))
class EmbedDistributionUpdateStoreDisk(JSONStoreDisk):
def __init__(self, in_folder, distribution):
- super(EmbedDistributionUpdateStoreDisk, self).__init__(
+ super().__init__(
in_folder,
distribution,
"embed update of distribution %s",
(distribution,),
)
+
+
+__all__ = [
+ "AppDataDiskFolder",
+ "JSONStoreDisk",
+ "PyInfoStoreDisk",
+]
diff --git a/src/virtualenv/app_data/via_tempdir.py b/src/virtualenv/app_data/via_tempdir.py
index 112a3fe..c15741a 100644
--- a/src/virtualenv/app_data/via_tempdir.py
+++ b/src/virtualenv/app_data/via_tempdir.py
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, unicode_literals
-
import logging
from tempfile import mkdtemp
@@ -13,7 +11,7 @@ class TempAppData(AppDataDiskFolder):
can_update = False
def __init__(self):
- super(TempAppData, self).__init__(folder=mkdtemp())
+ super().__init__(folder=mkdtemp())
logging.debug("created temporary app data folder %s", self.lock.path)
def reset(self):
@@ -25,3 +23,8 @@ class TempAppData(AppDataDiskFolder):
def embed_update_log(self, distribution, for_py_version):
raise NotImplementedError
+
+
+__all__ = [
+ "TempAppData",
+]
diff --git a/src/virtualenv/config/__init__.py b/src/virtualenv/config/__init__.py
index 01e6d4f..e69de29 100644
--- a/src/virtualenv/config/__init__.py
+++ b/src/virtualenv/config/__init__.py
@@ -1 +0,0 @@
-from __future__ import absolute_import, unicode_literals
diff --git a/src/virtualenv/config/cli/__init__.py b/src/virtualenv/config/cli/__init__.py
index 01e6d4f..e69de29 100644
--- a/src/virtualenv/config/cli/__init__.py
+++ b/src/virtualenv/config/cli/__init__.py
@@ -1 +0,0 @@
-from __future__ import absolute_import, unicode_literals
diff --git a/src/virtualenv/config/cli/parser.py b/src/virtualenv/config/cli/parser.py
index c8e2f55..5ab4fbd 100644
--- a/src/virtualenv/config/cli/parser.py
+++ b/src/virtualenv/config/cli/parser.py
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, unicode_literals
-
import os
from argparse import SUPPRESS, ArgumentDefaultsHelpFormatter, ArgumentParser, Namespace
from collections import OrderedDict
@@ -12,7 +10,7 @@ from ..ini import IniConfig
class VirtualEnvOptions(Namespace):
def __init__(self, **kwargs):
- super(VirtualEnvOptions, self).__init__(**kwargs)
+ super().__init__(**kwargs)
self._src = None
self._sources = {}
@@ -25,7 +23,7 @@ class VirtualEnvOptions(Namespace):
def __setattr__(self, key, value):
if getattr(self, "_src", None) is not None:
self._sources[key] = self._src
- super(VirtualEnvOptions, self).__setattr__(key, value)
+ super().__setattr__(key, value)
def get_source(self, key):
return self._sources.get(key)
@@ -37,10 +35,7 @@ class VirtualEnvOptions(Namespace):
return max(self.verbose - self.quiet, 0)
def __repr__(self):
- return "{}({})".format(
- type(self).__name__,
- ", ".join("{}={}".format(k, v) for k, v in vars(self).items() if not k.startswith("_")),
- )
+ return f"{type(self).__name__}({', '.join(f'{k}={v}' for k, v in vars(self).items() if not k.startswith('_'))})"
class VirtualEnvConfigParser(ArgumentParser):
@@ -57,7 +52,7 @@ class VirtualEnvConfigParser(ArgumentParser):
kwargs["add_help"] = False
kwargs["formatter_class"] = HelpFormatter
kwargs["prog"] = "virtualenv"
- super(VirtualEnvConfigParser, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
self._fixed = set()
if options is not None and not isinstance(options, VirtualEnvOptions):
raise TypeError("options must be of type VirtualEnvOptions")
@@ -105,20 +100,27 @@ class VirtualEnvConfigParser(ArgumentParser):
self.options._src = "cli"
try:
namespace.env = self.env
- return super(VirtualEnvConfigParser, self).parse_known_args(args, namespace=namespace)
+ return super().parse_known_args(args, namespace=namespace)
finally:
self.options._src = None
class HelpFormatter(ArgumentDefaultsHelpFormatter):
def __init__(self, prog):
- super(HelpFormatter, self).__init__(prog, max_help_position=32, width=240)
+ super().__init__(prog, max_help_position=32, width=240)
def _get_help_string(self, action):
- # noinspection PyProtectedMember
- text = super(HelpFormatter, self)._get_help_string(action)
+
+ text = super()._get_help_string(action)
if hasattr(action, "default_source"):
default = " (default: %(default)s)"
if text.endswith(default):
- text = "{} (default: %(default)s -> from %(default_source)s)".format(text[: -len(default)])
+ text = f"{text[: -len(default)]} (default: %(default)s -> from %(default_source)s)"
return text
+
+
+__all__ = [
+ "HelpFormatter",
+ "VirtualEnvConfigParser",
+ "VirtualEnvOptions",
+]
diff --git a/src/virtualenv/config/convert.py b/src/virtualenv/config/convert.py
index df40866..52f722e 100644
--- a/src/virtualenv/config/convert.py
+++ b/src/virtualenv/config/convert.py
@@ -1,16 +1,14 @@
-from __future__ import absolute_import, unicode_literals
-
import logging
import os
-class TypeData(object):
+class TypeData:
def __init__(self, default_type, as_type):
self.default_type = default_type
self.as_type = as_type
def __repr__(self):
- return "{}(base={}, as={})".format(self.__class__.__name__, self.default_type, self.as_type)
+ return f"{self.__class__.__name__}(base={self.default_type}, as={self.as_type})"
def convert(self, value):
return self.default_type(value)
@@ -30,7 +28,7 @@ class BoolType(TypeData):
def convert(self, value):
if value.lower() not in self.BOOLEAN_STATES:
- raise ValueError("Not a boolean: %s" % value)
+ raise ValueError(f"Not a boolean: {value}")
return self.BOOLEAN_STATES[value.lower()]
@@ -92,7 +90,7 @@ def get_type(action):
return _CONVERT.get(default_type, TypeData)(default_type, as_type)
-__all__ = (
+__all__ = [
"convert",
"get_type",
-)
+]
diff --git a/src/virtualenv/config/env_var.py b/src/virtualenv/config/env_var.py
index 8f6211c..5dc0c1d 100644
--- a/src/virtualenv/config/env_var.py
+++ b/src/virtualenv/config/env_var.py
@@ -1,7 +1,3 @@
-from __future__ import absolute_import, unicode_literals
-
-from virtualenv.util.six import ensure_str, ensure_text
-
from .convert import convert
@@ -13,16 +9,18 @@ def get_env_var(key, as_type, env):
:param env: environment variables to use
:return:
"""
- environ_key = ensure_str("VIRTUALENV_{}".format(key.upper()))
+ environ_key = f"VIRTUALENV_{key.upper()}"
if env.get(environ_key):
value = env[environ_key]
- # noinspection PyBroadException
+
try:
- source = "env var {}".format(ensure_text(environ_key))
+ source = f"env var {environ_key}"
as_type = convert(value, as_type, source)
return as_type, source
except Exception: # note the converter already logs a warning when failures happen
pass
-__all__ = ("get_env_var",)
+__all__ = [
+ "get_env_var",
+]
diff --git a/src/virtualenv/config/ini.py b/src/virtualenv/config/ini.py
index 0d945ee..50da884 100644
--- a/src/virtualenv/config/ini.py
+++ b/src/virtualenv/config/ini.py
@@ -1,20 +1,15 @@
-from __future__ import absolute_import, unicode_literals
-
import logging
import os
+from configparser import ConfigParser
+from pathlib import Path
from platformdirs import user_config_dir
-from virtualenv.info import PY3
-from virtualenv.util import ConfigParser
-from virtualenv.util.path import Path
-from virtualenv.util.six import ensure_str
-
from .convert import convert
-class IniConfig(object):
- VIRTUALENV_CONFIG_FILE_ENV_VAR = ensure_str("VIRTUALENV_CONFIG_FILE")
+class IniConfig:
+ VIRTUALENV_CONFIG_FILE_ENV_VAR = "VIRTUALENV_CONFIG_FILE"
STATE = {None: "failed to parse", True: "active", False: "missing"}
section = "virtualenv"
@@ -23,11 +18,10 @@ class IniConfig(object):
env = os.environ if env is None else env
config_file = env.get(self.VIRTUALENV_CONFIG_FILE_ENV_VAR, None)
self.is_env_var = config_file is not None
- config_file = (
- Path(config_file)
- if config_file is not None
- else Path(user_config_dir(appname="virtualenv", appauthor="pypa")) / "virtualenv.ini"
- )
+ if config_file is None:
+ config_file = Path(user_config_dir(appname="virtualenv", appauthor="pypa")) / "virtualenv.ini"
+ else:
+ config_file = Path(config_file)
self.config_file = config_file
self._cache = {}
@@ -40,7 +34,7 @@ class IniConfig(object):
else:
if self.has_config_file:
self.config_file = self.config_file.resolve()
- self.config_parser = ConfigParser.ConfigParser()
+ self.config_parser = ConfigParser()
try:
self._load()
self.has_virtualenv_section = self.config_parser.has_section(self.section)
@@ -51,14 +45,12 @@ class IniConfig(object):
def _load(self):
with self.config_file.open("rt") as file_handler:
- reader = getattr(self.config_parser, "read_file" if PY3 else "readfp")
- reader(file_handler)
+ return self.config_parser.read_file(file_handler)
def get(self, key, as_type):
cache_key = key, as_type
if cache_key in self._cache:
return self._cache[cache_key]
- # noinspection PyBroadException
try:
source = "file"
raw_value = self.config_parser.get(self.section, key.lower())
@@ -74,11 +66,7 @@ class IniConfig(object):
@property
def epilog(self):
- msg = "{}config file {} {} (change{} via env var {})"
- return msg.format(
- "\n",
- self.config_file,
- self.STATE[self.has_config_file],
- "d" if self.is_env_var else "",
- self.VIRTUALENV_CONFIG_FILE_ENV_VAR,
+ return (
+ f"\nconfig file {self.config_file} {self.STATE[self.has_config_file]} "
+ f"(change{'d' if self.is_env_var else ''} via env var {self.VIRTUALENV_CONFIG_FILE_ENV_VAR})"
)
diff --git a/src/virtualenv/create/__init__.py b/src/virtualenv/create/__init__.py
index 01e6d4f..e69de29 100644
--- a/src/virtualenv/create/__init__.py
+++ b/src/virtualenv/create/__init__.py
@@ -1 +0,0 @@
-from __future__ import absolute_import, unicode_literals
diff --git a/src/virtualenv/create/creator.py b/src/virtualenv/create/creator.py
index f7b8554..ad41bfe 100644
--- a/src/virtualenv/create/creator.py
+++ b/src/virtualenv/create/creator.py
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, print_function, unicode_literals
-
import json
import logging
import os
@@ -8,14 +6,10 @@ from abc import ABCMeta, abstractmethod
from argparse import ArgumentTypeError
from ast import literal_eval
from collections import OrderedDict
-from textwrap import dedent
-
-from six import add_metaclass
+from pathlib import Path
from virtualenv.discovery.cached_py_info import LogCmd
-from virtualenv.info import WIN_CPYTHON_2
-from virtualenv.util.path import Path, safe_delete
-from virtualenv.util.six import ensure_str, ensure_text
+from virtualenv.util.path import safe_delete
from virtualenv.util.subprocess import run_cmd
from virtualenv.version import __version__
@@ -25,13 +19,12 @@ HERE = Path(os.path.abspath(__file__)).parent
DEBUG_SCRIPT = HERE / "debug.py"
-class CreatorMeta(object):
+class CreatorMeta:
def __init__(self):
self.error = None
-@add_metaclass(ABCMeta)
-class Creator(object):
+class Creator(metaclass=ABCMeta):
"""A class that given a python Interpreter creates a virtual environment"""
def __init__(self, options, interpreter):
@@ -50,14 +43,11 @@ class Creator(object):
self.env = options.env
def __repr__(self):
- return ensure_str(self.__unicode__())
-
- def __unicode__(self):
- return "{}({})".format(self.__class__.__name__, ", ".join("{}={}".format(k, v) for k, v in self._args()))
+ return f"{self.__class__.__name__}({', '.join(f'{k}={v}' for k, v in self._args())})"
def _args(self):
return [
- ("dest", ensure_text(str(self.dest))),
+ ("dest", str(self.dest)),
("clear", self.clear),
("no_vcs_ignore", self.no_vcs_ignore),
]
@@ -112,16 +102,14 @@ class Creator(object):
def non_write_able(dest, value):
common = Path(*os.path.commonprefix([value.parts, dest.parts]))
- raise ArgumentTypeError(
- "the destination {} is not write-able at {}".format(dest.relative_to(common), common),
- )
+ raise ArgumentTypeError(f"the destination {dest.relative_to(common)} is not write-able at {common}")
# the file system must be able to encode
# note in newer CPython this is always utf-8 https://www.python.org/dev/peps/pep-0529/
encoding = sys.getfilesystemencoding()
refused = OrderedDict()
kwargs = {"errors": "ignore"} if encoding != "mbcs" else {}
- for char in ensure_text(raw_value):
+ for char in str(raw_value):
try:
trip = char.encode(encoding, **kwargs).decode(encoding)
if trip == char:
@@ -130,23 +118,17 @@ class Creator(object):
except ValueError:
refused[char] = None
if refused:
- raise ArgumentTypeError(
- "the file system codec ({}) cannot handle characters {!r} within {!r}".format(
- encoding,
- "".join(refused.keys()),
- raw_value,
- ),
- )
+ bad = "".join(refused.keys())
+ msg = f"the file system codec ({encoding}) cannot handle characters {bad!r} within {raw_value!r}"
+ raise ArgumentTypeError(msg)
if os.pathsep in raw_value:
- raise ArgumentTypeError(
- "destination {!r} must not contain the path separator ({}) as this would break "
- "the activation scripts".format(raw_value, os.pathsep),
- )
+ msg = f"destination {raw_value!r} must not contain the path separator ({os.pathsep})"
+ raise ArgumentTypeError(f"{msg} as this would break the activation scripts")
value = Path(raw_value)
if value.exists() and value.is_file():
- raise ArgumentTypeError("the destination {} already exists and is a file".format(value))
- if (3, 3) <= sys.version_info <= (3, 6):
+ raise ArgumentTypeError(f"the destination {value} already exists and is a file")
+ if sys.version_info <= (3, 6):
# pre 3.6 resolve is always strict, aka must exists, sidestep by using os.path operation
dest = Path(os.path.realpath(raw_value))
else:
@@ -154,7 +136,7 @@ class Creator(object):
value = dest
while dest:
if dest.exists():
- if os.access(ensure_text(str(dest)), os.W_OK):
+ if os.access(str(dest), os.W_OK):
break
else:
non_write_able(dest, value)
@@ -185,14 +167,7 @@ class Creator(object):
# mark this folder to be ignored by VCS, handle https://www.python.org/dev/peps/pep-0610/#registered-vcs
git_ignore = self.dest / ".gitignore"
if not git_ignore.exists():
- git_ignore.write_text(
- dedent(
- """
- # created by virtualenv automatically
- *
- """,
- ).lstrip(),
- )
+ git_ignore.write_text("# created by virtualenv automatically\n*\n")
# Mercurial - does not support the .hgignore file inside a subdirectory directly, but only if included via the
# subinclude directive from root, at which point on might as well ignore the directory itself, see
# https://www.selenic.com/mercurial/hgignore.5.html for more details
@@ -208,23 +183,20 @@ class Creator(object):
self._debug = get_env_debug_info(self.exe, self.debug_script(), self.app_data, self.env)
return self._debug
- # noinspection PyMethodMayBeStatic
- def debug_script(self):
+ @staticmethod
+ def debug_script():
return DEBUG_SCRIPT
def get_env_debug_info(env_exe, debug_script, app_data, env):
env = env.copy()
- env.pop(str("PYTHONPATH"), None)
+ env.pop("PYTHONPATH", None)
with app_data.ensure_extracted(debug_script) as debug_script:
cmd = [str(env_exe), str(debug_script)]
- if WIN_CPYTHON_2:
- cmd = [ensure_text(i) for i in cmd]
- logging.debug(str("debug via %r"), LogCmd(cmd))
+ logging.debug("debug via %r", LogCmd(cmd))
code, out, err = run_cmd(cmd)
- # noinspection PyBroadException
try:
if code != 0:
if out:
@@ -243,3 +215,9 @@ def get_env_debug_info(env_exe, debug_script, app_data, env):
if "sys" in result and "path" in result["sys"]:
del result["sys"]["path"][0]
return result
+
+
+__all__ = [
+ "Creator",
+ "CreatorMeta",
+]
diff --git a/src/virtualenv/create/describe.py b/src/virtualenv/create/describe.py
index 6f05ff1..fade5c4 100644
--- a/src/virtualenv/create/describe.py
+++ b/src/virtualenv/create/describe.py
@@ -1,17 +1,11 @@
-from __future__ import absolute_import, print_function, unicode_literals
-
from abc import ABCMeta
from collections import OrderedDict
-
-from six import add_metaclass
+from pathlib import Path
from virtualenv.info import IS_WIN
-from virtualenv.util.path import Path
-from virtualenv.util.six import ensure_text
-@add_metaclass(ABCMeta)
-class Describe(object):
+class Describe(metaclass=ABCMeta):
"""Given a host interpreter tell us information about what the created interpreter might look like"""
suffix = ".exe" if IS_WIN else ""
@@ -59,13 +53,12 @@ class Describe(object):
@property
def _config_vars(self):
if self._conf_vars is None:
- self._conf_vars = self._calc_config_vars(ensure_text(str(self.dest)))
+ self._conf_vars = self._calc_config_vars(self.dest)
return self._conf_vars
def _calc_config_vars(self, to):
- return {
- k: (to if v.startswith(self.interpreter.prefix) else v) for k, v in self.interpreter.sysconfig_vars.items()
- }
+ sys_vars = self.interpreter.sysconfig_vars
+ return {k: (to if v.startswith(self.interpreter.prefix) else v) for k, v in sys_vars.items()}
@classmethod
def can_describe(cls, interpreter):
@@ -74,11 +67,11 @@ class Describe(object):
@property
def env_name(self):
- return ensure_text(self.dest.parts[-1])
+ return self.dest.parts[-1]
@property
def exe(self):
- return self.bin_dir / "{}{}".format(self.exe_stem(), self.suffix)
+ return self.bin_dir / f"{self.exe_stem()}{self.suffix}"
@classmethod
def exe_stem(cls):
@@ -86,32 +79,37 @@ class Describe(object):
raise NotImplementedError
def script(self, name):
- return self.script_dir / "{}{}".format(name, self.suffix)
+ return self.script_dir / f"{name}{self.suffix}"
-@add_metaclass(ABCMeta)
-class Python2Supports(Describe):
+class Python2Supports(Describe, metaclass=ABCMeta):
@classmethod
def can_describe(cls, interpreter):
- return interpreter.version_info.major == 2 and super(Python2Supports, cls).can_describe(interpreter)
+ return interpreter.version_info.major == 2 and super().can_describe(interpreter)
-@add_metaclass(ABCMeta)
-class Python3Supports(Describe):
+class Python3Supports(Describe, metaclass=ABCMeta):
@classmethod
def can_describe(cls, interpreter):
- return interpreter.version_info.major == 3 and super(Python3Supports, cls).can_describe(interpreter)
+ return interpreter.version_info.major == 3 and super().can_describe(interpreter)
-@add_metaclass(ABCMeta)
-class PosixSupports(Describe):
+class PosixSupports(Describe, metaclass=ABCMeta):
@classmethod
def can_describe(cls, interpreter):
- return interpreter.os == "posix" and super(PosixSupports, cls).can_describe(interpreter)
+ return interpreter.os == "posix" and super().can_describe(interpreter)
-@add_metaclass(ABCMeta)
-class WindowsSupports(Describe):
+class WindowsSupports(Describe, metaclass=ABCMeta):
@classmethod
def can_describe(cls, interpreter):
- return interpreter.os == "nt" and super(WindowsSupports, cls).can_describe(interpreter)
+ return interpreter.os == "nt" and super().can_describe(interpreter)
+
+
+__all__ = [
+ "Describe",
+ "Python2Supports",
+ "Python3Supports",
+ "PosixSupports",
+ "WindowsSupports",
+]
diff --git a/src/virtualenv/create/pyenv_cfg.py b/src/virtualenv/create/pyenv_cfg.py
index 1a8d824..9193a28 100644
--- a/src/virtualenv/create/pyenv_cfg.py
+++ b/src/virtualenv/create/pyenv_cfg.py
@@ -1,12 +1,8 @@
-from __future__ import absolute_import, unicode_literals
-
import logging
from collections import OrderedDict
-from virtualenv.util.six import ensure_text
-
-class PyEnvCfg(object):
+class PyEnvCfg:
def __init__(self, content, path):
self.content = content
self.path = path
@@ -31,10 +27,10 @@ class PyEnvCfg(object):
return content
def write(self):
- logging.debug("write %s", ensure_text(str(self.path)))
+ logging.debug("write %s", self.path)
text = ""
for key, value in self.content.items():
- line = "{} = {}".format(key, value)
+ line = f"{key} = {value}"
logging.debug("\t%s", line)
text += line
text += "\n"
@@ -58,4 +54,9 @@ class PyEnvCfg(object):
return self
def __repr__(self):
- return "{}(path={})".format(self.__class__.__name__, self.path)
+ return f"{self.__class__.__name__}(path={self.path})"
+
+
+__all__ = [
+ "PyEnvCfg",
+]
diff --git a/src/virtualenv/create/via_global_ref/api.py b/src/virtualenv/create/via_global_ref/api.py
index 6f296f4..7a4086f 100644
--- a/src/virtualenv/create/via_global_ref/api.py
+++ b/src/virtualenv/create/via_global_ref/api.py
@@ -1,21 +1,16 @@
-from __future__ import absolute_import, unicode_literals
-
import logging
import os
from abc import ABCMeta
-
-from six import add_metaclass
+from pathlib import Path
from virtualenv.info import fs_supports_symlink
-from virtualenv.util.path import Path
-from virtualenv.util.six import ensure_text
from ..creator import Creator, CreatorMeta
class ViaGlobalRefMeta(CreatorMeta):
def __init__(self):
- super(ViaGlobalRefMeta, self).__init__()
+ super().__init__()
self.copy_error = None
self.symlink_error = None
if not fs_supports_symlink():
@@ -30,10 +25,9 @@ class ViaGlobalRefMeta(CreatorMeta):
return not self.symlink_error
-@add_metaclass(ABCMeta)
-class ViaGlobalRefApi(Creator):
+class ViaGlobalRefApi(Creator, metaclass=ABCMeta):
def __init__(self, options, interpreter):
- super(ViaGlobalRefApi, self).__init__(options, interpreter)
+ super().__init__(options, interpreter)
self.symlinks = self._should_symlink(options)
self.enable_system_site_package = options.system_site
@@ -56,7 +50,7 @@ class ViaGlobalRefApi(Creator):
@classmethod
def add_parser_arguments(cls, parser, interpreter, meta, app_data):
- super(ViaGlobalRefApi, cls).add_parser_arguments(parser, interpreter, meta, app_data)
+ super().add_parser_arguments(parser, interpreter, meta, app_data)
parser.add_argument(
"--system-site-packages",
default=False,
@@ -92,10 +86,10 @@ class ViaGlobalRefApi(Creator):
text = self.env_patch_text()
if text:
pth = self.purelib / "_virtualenv.pth"
- logging.debug("create virtualenv import hook file %s", ensure_text(str(pth)))
+ logging.debug("create virtualenv import hook file %s", pth)
pth.write_text("import _virtualenv")
dest_path = self.purelib / "_virtualenv.py"
- logging.debug("create %s", ensure_text(str(dest_path)))
+ logging.debug("create %s", dest_path)
dest_path.write_text(text)
def env_patch_text(self):
@@ -105,8 +99,14 @@ class ViaGlobalRefApi(Creator):
return text.replace('"__SCRIPT_DIR__"', repr(os.path.relpath(str(self.script_dir), str(self.purelib))))
def _args(self):
- return super(ViaGlobalRefApi, self)._args() + [("global", self.enable_system_site_package)]
+ return super()._args() + [("global", self.enable_system_site_package)]
def set_pyenv_cfg(self):
- super(ViaGlobalRefApi, self).set_pyenv_cfg()
+ super().set_pyenv_cfg()
self.pyenv_cfg["include-system-site-packages"] = "true" if self.enable_system_site_package else "false"
+
+
+__all__ = [
+ "ViaGlobalRefMeta",
+ "ViaGlobalRefApi",
+]
diff --git a/src/virtualenv/create/via_global_ref/builtin/builtin_way.py b/src/virtualenv/create/via_global_ref/builtin/builtin_way.py
index 279ee80..e321593 100644
--- a/src/virtualenv/create/via_global_ref/builtin/builtin_way.py
+++ b/src/virtualenv/create/via_global_ref/builtin/builtin_way.py
@@ -1,17 +1,17 @@
-from __future__ import absolute_import, unicode_literals
-
from abc import ABCMeta
-from six import add_metaclass
-
from virtualenv.create.creator import Creator
from virtualenv.create.describe import Describe
-@add_metaclass(ABCMeta)
-class VirtualenvBuiltin(Creator, Describe):
+class VirtualenvBuiltin(Creator, Describe, metaclass=ABCMeta):
"""A creator that does operations itself without delegation, if we can create it we can also describe it"""
def __init__(self, options, interpreter):
Creator.__init__(self, options, interpreter)
Describe.__init__(self, self.dest, interpreter)
+
+
+__all__ = [
+ "VirtualenvBuiltin",
+]
diff --git a/src/virtualenv/create/via_global_ref/builtin/cpython/__init__.py b/src/virtualenv/create/via_global_ref/builtin/cpython/__init__.py
index 01e6d4f..e69de29 100644
--- a/src/virtualenv/create/via_global_ref/builtin/cpython/__init__.py
+++ b/src/virtualenv/create/via_global_ref/builtin/cpython/__init__.py
@@ -1 +0,0 @@
-from __future__ import absolute_import, unicode_literals
diff --git a/src/virtualenv/create/via_global_ref/builtin/cpython/common.py b/src/virtualenv/create/via_global_ref/builtin/cpython/common.py
index c93f9f3..b2f7944 100644
--- a/src/virtualenv/create/via_global_ref/builtin/cpython/common.py
+++ b/src/virtualenv/create/via_global_ref/builtin/cpython/common.py
@@ -1,45 +1,36 @@
-from __future__ import absolute_import, unicode_literals
-
from abc import ABCMeta
from collections import OrderedDict
-
-from six import add_metaclass
+from pathlib import Path
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 ..via_global_self_do import ViaGlobalRefVirtualenvBuiltin
-@add_metaclass(ABCMeta)
-class CPython(ViaGlobalRefVirtualenvBuiltin):
+class CPython(ViaGlobalRefVirtualenvBuiltin, metaclass=ABCMeta):
@classmethod
def can_describe(cls, interpreter):
- return interpreter.implementation == "CPython" and super(CPython, cls).can_describe(interpreter)
+ return interpreter.implementation == "CPython" and super().can_describe(interpreter)
@classmethod
def exe_stem(cls):
return "python"
-@add_metaclass(ABCMeta)
-class CPythonPosix(CPython, PosixSupports):
+class CPythonPosix(CPython, PosixSupports, metaclass=ABCMeta):
"""Create a CPython virtual environment on POSIX platforms"""
@classmethod
def _executables(cls, interpreter):
host_exe = Path(interpreter.system_executable)
major, minor = interpreter.version_info.major, interpreter.version_info.minor
- targets = OrderedDict(
- (i, None) for i in ["python", "python{}".format(major), "python{}.{}".format(major, minor), host_exe.name]
- )
+ targets = OrderedDict((i, None) for i in ["python", f"python{major}", f"python{major}.{minor}", host_exe.name])
must = RefMust.COPY if interpreter.version_info.major == 2 else RefMust.NA
yield host_exe, list(targets.keys()), must, RefWhen.ANY
-@add_metaclass(ABCMeta)
-class CPythonWindows(CPython, WindowsSupports):
+class CPythonWindows(CPython, WindowsSupports, metaclass=ABCMeta):
@classmethod
def _executables(cls, interpreter):
# symlink of the python executables does not work reliably, copy always instead
@@ -63,3 +54,11 @@ def is_mac_os_framework(interpreter):
value = "Python3" if interpreter.version_info.major == 3 else "Python"
return framework_var == value
return False
+
+
+__all__ = [
+ "CPython",
+ "CPythonPosix",
+ "CPythonWindows",
+ "is_mac_os_framework",
+]
diff --git a/src/virtualenv/create/via_global_ref/builtin/cpython/cpython2.py b/src/virtualenv/create/via_global_ref/builtin/cpython/cpython2.py
index dc822bc..5a9eb85 100644
--- a/src/virtualenv/create/via_global_ref/builtin/cpython/cpython2.py
+++ b/src/virtualenv/create/via_global_ref/builtin/cpython/cpython2.py
@@ -1,25 +1,19 @@
-from __future__ import absolute_import, unicode_literals
-
import abc
import logging
-
-from six import add_metaclass
+from pathlib import Path
from virtualenv.create.via_global_ref.builtin.ref import PathRefToDest
-from virtualenv.util.path import Path
from ..python2.python2 import Python2
from .common import CPython, CPythonPosix, CPythonWindows, is_mac_os_framework
-@add_metaclass(abc.ABCMeta)
-class CPython2(CPython, Python2):
+class CPython2(CPython, Python2, metaclass=abc.ABCMeta):
"""Create a CPython version 2 virtual environment"""
@classmethod
def sources(cls, interpreter):
- for src in super(CPython2, cls).sources(interpreter):
- yield src
+ yield from super().sources(interpreter)
# include folder needed on Python 2 as we don't have pyenv.cfg
host_include_marker = cls.host_include_marker(interpreter)
if host_include_marker.exists():
@@ -40,12 +34,10 @@ class CPython2(CPython, Python2):
@classmethod
def modules(cls):
- return [
- "os", # landmark to set sys.prefix
- ]
+ return ["os"] # landmark to set sys.prefix
def ensure_directories(self):
- dirs = super(CPython2, self).ensure_directories()
+ dirs = super().ensure_directories()
host_include_marker = self.host_include_marker(self.interpreter)
if host_include_marker.exists():
dirs.add(self.include.parent)
@@ -54,14 +46,12 @@ class CPython2(CPython, Python2):
return dirs
-@add_metaclass(abc.ABCMeta)
-class CPython2PosixBase(CPython2, CPythonPosix):
+class CPython2PosixBase(CPython2, CPythonPosix, metaclass=abc.ABCMeta):
"""common to macOs framework builds and other posix CPython2"""
@classmethod
def sources(cls, interpreter):
- for src in super(CPython2PosixBase, cls).sources(interpreter):
- yield src
+ yield from super().sources(interpreter)
# check if the makefile exists and if so make it available under the virtual environment
make_file = Path(interpreter.sysconfig["makefile_filename"])
@@ -75,12 +65,11 @@ class CPython2Posix(CPython2PosixBase):
@classmethod
def can_describe(cls, interpreter):
- return is_mac_os_framework(interpreter) is False and super(CPython2Posix, cls).can_describe(interpreter)
+ return is_mac_os_framework(interpreter) is False and super().can_describe(interpreter)
@classmethod
def sources(cls, interpreter):
- for src in super(CPython2Posix, cls).sources(interpreter):
- yield src
+ yield from super().sources(interpreter)
# landmark for exec_prefix
exec_marker_file, to_path, _ = cls.from_stdlib(cls.mappings(interpreter), "lib-dynload")
yield PathRefToDest(exec_marker_file, dest=to_path)
@@ -91,8 +80,7 @@ class CPython2Windows(CPython2, CPythonWindows):
@classmethod
def sources(cls, interpreter):
- for src in super(CPython2Windows, cls).sources(interpreter):
- yield src
+ yield from super().sources(interpreter)
py27_dll = Path(interpreter.system_executable).parent / "python27.dll"
if py27_dll.exists(): # this might be global in the Windows folder in which case it's alright to be missing
yield PathRefToDest(py27_dll, dest=cls.to_bin)
@@ -100,3 +88,11 @@ class CPython2Windows(CPython2, CPythonWindows):
libs = Path(interpreter.system_prefix) / "libs"
if libs.exists():
yield PathRefToDest(libs, dest=lambda self, s: self.dest / s.name)
+
+
+__all__ = [
+ "CPython2",
+ "CPython2PosixBase",
+ "CPython2Posix",
+ "CPython2Windows",
+]
diff --git a/src/virtualenv/create/via_global_ref/builtin/cpython/cpython3.py b/src/virtualenv/create/via_global_ref/builtin/cpython/cpython3.py
index 03d3097..433dc4a 100644
--- a/src/virtualenv/create/via_global_ref/builtin/cpython/cpython3.py
+++ b/src/virtualenv/create/via_global_ref/builtin/cpython/cpython3.py
@@ -1,33 +1,28 @@
-from __future__ import absolute_import, unicode_literals
-
import abc
import fnmatch
from itertools import chain
from operator import methodcaller as method
+from pathlib import Path
from textwrap import dedent
-from six import add_metaclass
-
from virtualenv.create.describe import Python3Supports
from virtualenv.create.via_global_ref.builtin.ref import PathRefToDest
from virtualenv.create.via_global_ref.store import is_store_python
-from virtualenv.util.path import Path
from .common import CPython, CPythonPosix, CPythonWindows, is_mac_os_framework
-@add_metaclass(abc.ABCMeta)
-class CPython3(CPython, Python3Supports):
- """ """
+class CPython3(CPython, Python3Supports, metaclass=abc.ABCMeta):
+ """CPython 3 or later"""
class CPython3Posix(CPythonPosix, CPython3):
@classmethod
def can_describe(cls, interpreter):
- return is_mac_os_framework(interpreter) is False and super(CPython3Posix, cls).can_describe(interpreter)
+ return is_mac_os_framework(interpreter) is False and super().can_describe(interpreter)
def env_patch_text(self):
- text = super(CPython3Posix, self).env_patch_text()
+ text = super().env_patch_text()
if self.pyvenv_launch_patch_active(self.interpreter):
text += dedent(
"""
@@ -52,7 +47,7 @@ class CPython3Windows(CPythonWindows, CPython3):
def setup_meta(cls, interpreter):
if is_store_python(interpreter): # store python is not supported here
return None
- return super(CPython3Windows, cls).setup_meta(interpreter)
+ return super().setup_meta(interpreter)
@classmethod
def sources(cls, interpreter):
@@ -64,12 +59,11 @@ class CPython3Windows(CPythonWindows, CPython3):
cls.dll_and_pyd(interpreter),
cls.python_zip(interpreter),
)
- for ref in refs:
- yield ref
+ yield from refs
@classmethod
def executables(cls, interpreter):
- return super(CPython3Windows, cls).sources(interpreter)
+ return super().sources(interpreter)
@classmethod
def has_shim(cls, interpreter):
@@ -88,7 +82,7 @@ class CPython3Windows(CPythonWindows, CPython3):
# 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 cls.shim(interpreter)
- return super(CPython3Windows, cls).host_python(interpreter)
+ return super().host_python(interpreter)
@classmethod
def dll_and_pyd(cls, interpreter):
@@ -119,10 +113,17 @@ class CPython3Windows(CPythonWindows, CPython3):
move/rename *zip* file and edit `sys.path` by editing *_pth* file.
Here the `pattern` is used only for the default *zip* file name!
"""
- pattern = "*python{}.zip".format(interpreter.version_nodot)
+ pattern = f"*python{interpreter.version_nodot}.zip"
matches = fnmatch.filter(interpreter.path, pattern)
matched_paths = map(Path, matches)
existing_paths = filter(method("exists"), matched_paths)
path = next(existing_paths, None)
if path is not None:
yield PathRefToDest(path, cls.to_bin)
+
+
+__all__ = [
+ "CPython3",
+ "CPython3Posix",
+ "CPython3Windows",
+]
diff --git a/src/virtualenv/create/via_global_ref/builtin/cpython/mac_os.py b/src/virtualenv/create/via_global_ref/builtin/cpython/mac_os.py
index d64f0d9..16da661 100644
--- a/src/virtualenv/create/via_global_ref/builtin/cpython/mac_os.py
+++ b/src/virtualenv/create/via_global_ref/builtin/cpython/mac_os.py
@@ -1,32 +1,27 @@
-# -*- coding: utf-8 -*-
"""The Apple Framework builds require their own customization"""
import logging
import os
import struct
import subprocess
from abc import ABCMeta, abstractmethod
+from pathlib import Path
from textwrap import dedent
-from six import add_metaclass, text_type
-
from virtualenv.create.via_global_ref.builtin.ref import ExePathRefToDest, PathRefToDest, RefMust
from virtualenv.info import IS_MAC_ARM64
-from virtualenv.util.path import Path
-from virtualenv.util.six import ensure_text
from .common import CPython, CPythonPosix, is_mac_os_framework
from .cpython2 import CPython2PosixBase
from .cpython3 import CPython3
-@add_metaclass(ABCMeta)
-class CPythonmacOsFramework(CPython):
+class CPythonmacOsFramework(CPython, metaclass=ABCMeta):
@classmethod
def can_describe(cls, interpreter):
- return is_mac_os_framework(interpreter) and super(CPythonmacOsFramework, cls).can_describe(interpreter)
+ return is_mac_os_framework(interpreter) and super().can_describe(interpreter)
def create(self):
- super(CPythonmacOsFramework, self).create()
+ super().create()
# change the install_name of the copied python executables
target = self.desired_mach_o_image_path()
@@ -42,7 +37,7 @@ class CPythonmacOsFramework(CPython):
@classmethod
def _executables(cls, interpreter):
- for _, targets, must, when in super(CPythonmacOsFramework, cls)._executables(interpreter):
+ for _, targets, must, when in super()._executables(interpreter):
# Make sure we use the embedded interpreter inside the framework, even if sys.executable points to the
# stub executable in ${sys.prefix}/bin.
# See http://groups.google.com/group/python-virtualenv/browse_thread/thread/17cab2f85da75951
@@ -61,8 +56,8 @@ class CPythonmacOsFramework(CPython):
class CPython2macOsFramework(CPythonmacOsFramework, CPython2PosixBase):
@classmethod
def can_create(cls, interpreter):
- if not IS_MAC_ARM64 and super(CPython2macOsFramework, cls).can_describe(interpreter):
- return super(CPython2macOsFramework, cls).can_create(interpreter)
+ if not IS_MAC_ARM64 and super().can_describe(interpreter):
+ return super().can_create(interpreter)
return False
def current_mach_o_image_path(self):
@@ -73,8 +68,7 @@ class CPython2macOsFramework(CPythonmacOsFramework, CPython2PosixBase):
@classmethod
def sources(cls, interpreter):
- for src in super(CPython2macOsFramework, cls).sources(interpreter):
- yield src
+ yield from super().sources(interpreter)
# landmark for exec_prefix
exec_marker_file, to_path, _ = cls.from_stdlib(cls.mappings(interpreter), "lib-dynload")
yield PathRefToDest(exec_marker_file, dest=to_path)
@@ -89,21 +83,19 @@ class CPython2macOsFramework(CPythonmacOsFramework, CPython2PosixBase):
@property
def reload_code(self):
- result = super(CPython2macOsFramework, self).reload_code
+ result = super().reload_code
result = dedent(
- """
+ f"""
# the bundled site.py always adds the global site package if we're on python framework build, escape this
import sysconfig
config = sysconfig.get_config_vars()
before = config["PYTHONFRAMEWORK"]
try:
config["PYTHONFRAMEWORK"] = ""
- {}
+ {result}
finally:
config["PYTHONFRAMEWORK"] = before
- """.format(
- result,
- ),
+ """,
)
return result
@@ -132,11 +124,11 @@ class CPython2macOsArmFramework(CPython2macOsFramework, CPythonmacOsFramework, C
# Reset the signing on Darwin since the exe has been modified.
# Note codesign fails on the original exe, it needs to be copied and moved back.
bak_dir.mkdir(parents=True, exist_ok=True)
- subprocess.check_call(["cp", text_type(exe), text_type(bak_dir)])
- subprocess.check_call(["mv", text_type(bak_dir / exe.name), text_type(exe)])
+ subprocess.check_call(["cp", str(exe), str(bak_dir)])
+ subprocess.check_call(["mv", str(bak_dir / exe.name), str(exe)])
bak_dir.rmdir()
metadata = "--preserve-metadata=identifier,entitlements,flags,runtime"
- cmd = ["codesign", "-s", "-", metadata, "-f", text_type(exe)]
+ cmd = ["codesign", "-s", "-", metadata, "-f", str(exe)]
logging.debug("Changing Signature: %s", cmd)
subprocess.check_call(cmd)
except Exception:
@@ -153,8 +145,7 @@ class CPython3macOsFramework(CPythonmacOsFramework, CPython3, CPythonPosix):
@classmethod
def sources(cls, interpreter):
- for src in super(CPython3macOsFramework, cls).sources(interpreter):
- yield src
+ yield from super().sources(interpreter)
# add a symlink to the host python image
exe = Path(interpreter.prefix) / "Python3"
@@ -162,20 +153,18 @@ class CPython3macOsFramework(CPythonmacOsFramework, CPython3, CPythonPosix):
@property
def reload_code(self):
- result = super(CPython3macOsFramework, self).reload_code
+ result = super().reload_code
result = dedent(
- """
+ f"""
# the bundled site.py always adds the global site package if we're on python framework build, escape this
import sys
before = sys._framework
try:
sys._framework = None
- {}
+ {result}
finally:
sys._framework = before
- """.format(
- result,
- ),
+ """,
)
return result
@@ -205,7 +194,7 @@ def fix_mach_o(exe, current, new, max_size):
unneeded bits of information, however Mac OS X 10.5 and earlier cannot read this new Link Edit table format.
"""
try:
- logging.debug("change Mach-O for %s from %s to %s", ensure_text(exe), current, ensure_text(new))
+ logging.debug("change Mach-O for %s from %s to %s", exe, current, new)
_builtin_change_mach_o(max_size)(exe, current, new)
except Exception as e:
logging.warning("Could not call _builtin_change_mac_o: %s. " "Trying to call install_name_tool instead.", e)
@@ -227,7 +216,7 @@ def _builtin_change_mach_o(maxint):
LITTLE_ENDIAN = "<"
LC_LOAD_DYLIB = 0xC
- class FileView(object):
+ class FileView:
"""A proxy for file-like objects that exposes a given view of a file. Modified from macholib."""
def __init__(self, file_obj, start=0, size=maxint):
@@ -240,15 +229,15 @@ def _builtin_change_mach_o(maxint):
self._pos = 0
def __repr__(self):
- return "<fileview [{:d}, {:d}] {!r}>".format(self._start, self._end, self._file_obj)
+ return f"<fileview [{self._start:d}, {self._end:d}] {self._file_obj!r}>"
def tell(self):
return self._pos
def _checkwindow(self, seek_to, op):
if not (self._start <= seek_to <= self._end):
- msg = "{} to offset {:d} is outside window [{:d}, {:d}]".format(op, seek_to, self._start, self._end)
- raise IOError(msg)
+ msg = f"{op} to offset {seek_to:d} is outside window [{self._start:d}, {self._end:d}]"
+ raise OSError(msg)
def seek(self, offset, whence=0):
seek_to = offset
@@ -259,7 +248,7 @@ def _builtin_change_mach_o(maxint):
elif whence == os.SEEK_END:
seek_to += self._end
else:
- raise IOError("Invalid whence argument to seek: {!r}".format(whence))
+ raise OSError(f"Invalid whence argument to seek: {whence!r}")
self._checkwindow(seek_to, "seek")
self._file_obj.seek(seek_to)
self._pos = seek_to - self._start
@@ -345,3 +334,10 @@ def _builtin_change_mach_o(maxint):
do_file(f)
return mach_o_change
+
+
+__all__ = [
+ "CPythonmacOsFramework",
+ "CPython2macOsFramework",
+ "CPython3macOsFramework",
+]
diff --git a/src/virtualenv/create/via_global_ref/builtin/pypy/common.py b/src/virtualenv/create/via_global_ref/builtin/pypy/common.py
index 4504d81..97fa963 100644
--- a/src/virtualenv/create/via_global_ref/builtin/pypy/common.py
+++ b/src/virtualenv/create/via_global_ref/builtin/pypy/common.py
@@ -1,46 +1,39 @@
-from __future__ import absolute_import, unicode_literals
-
import abc
-
-from six import add_metaclass
+from pathlib import Path
from virtualenv.create.via_global_ref.builtin.ref import PathRefToDest, RefMust, RefWhen
-from virtualenv.util.path import Path
from ..via_global_self_do import ViaGlobalRefVirtualenvBuiltin
-@add_metaclass(abc.ABCMeta)
-class PyPy(ViaGlobalRefVirtualenvBuiltin):
+class PyPy(ViaGlobalRefVirtualenvBuiltin, metaclass=abc.ABCMeta):
@classmethod
def can_describe(cls, interpreter):
- return interpreter.implementation == "PyPy" and super(PyPy, cls).can_describe(interpreter)
+ return interpreter.implementation == "PyPy" and super().can_describe(interpreter)
@classmethod
def _executables(cls, interpreter):
host = Path(interpreter.system_executable)
- targets = sorted("{}{}".format(name, PyPy.suffix) for name in cls.exe_names(interpreter))
+ targets = sorted(f"{name}{PyPy.suffix}" for name in cls.exe_names(interpreter))
must = RefMust.COPY if interpreter.version_info.major == 2 else RefMust.NA
yield host, targets, must, RefWhen.ANY
@classmethod
def executables(cls, interpreter):
- for src in super(PyPy, cls).sources(interpreter):
- yield src
+ yield from super().sources(interpreter)
@classmethod
def exe_names(cls, interpreter):
return {
cls.exe_stem(),
"python",
- "python{}".format(interpreter.version_info.major),
- "python{}.{}".format(*interpreter.version_info),
+ f"python{interpreter.version_info.major}",
+ f"python{interpreter.version_info.major}.{interpreter.version_info.minor}",
}
@classmethod
def sources(cls, interpreter):
- for exe in cls.executables(interpreter):
- yield exe
+ yield from cls.executables(interpreter)
for host in cls._add_shared_libs(interpreter):
yield PathRefToDest(host, dest=lambda self, s: self.bin_dir / s.name)
@@ -48,9 +41,13 @@ class PyPy(ViaGlobalRefVirtualenvBuiltin):
def _add_shared_libs(cls, interpreter):
# https://bitbucket.org/pypy/pypy/issue/1922/future-proofing-virtualenv
python_dir = Path(interpreter.system_executable).resolve().parent
- for src in cls._shared_libs(python_dir):
- yield src
+ yield from cls._shared_libs(python_dir)
@classmethod
def _shared_libs(cls, python_dir):
raise NotImplementedError
+
+
+__all__ = [
+ "PyPy",
+]
diff --git a/src/virtualenv/create/via_global_ref/builtin/pypy/pypy2.py b/src/virtualenv/create/via_global_ref/builtin/pypy/pypy2.py
index 78349d4..9f2343f 100644
--- a/src/virtualenv/create/via_global_ref/builtin/pypy/pypy2.py
+++ b/src/virtualenv/create/via_global_ref/builtin/pypy/pypy2.py
@@ -1,22 +1,17 @@
-from __future__ import absolute_import, unicode_literals
-
import abc
import logging
import os
-
-from six import add_metaclass
+from pathlib import Path
from virtualenv.create.describe import PosixSupports, WindowsSupports
from virtualenv.create.via_global_ref.builtin.ref import PathRefToDest
-from virtualenv.util.path import Path
from ..python2.python2 import Python2
from .common import PyPy
-@add_metaclass(abc.ABCMeta)
-class PyPy2(PyPy, Python2):
- """ """
+class PyPy2(PyPy, Python2, metaclass=abc.ABCMeta):
+ """PyPy 2"""
@classmethod
def exe_stem(cls):
@@ -24,8 +19,7 @@ class PyPy2(PyPy, Python2):
@classmethod
def sources(cls, interpreter):
- for src in super(PyPy2, cls).sources(interpreter):
- yield src
+ yield from super().sources(interpreter)
# include folder needed on Python 2 as we don't have pyenv.cfg
host_include_marker = cls.host_include_marker(interpreter)
if host_include_marker.exists():
@@ -46,7 +40,7 @@ class PyPy2(PyPy, Python2):
@classmethod
def modules(cls):
# pypy2 uses some modules before the site.py loads, so we need to include these too
- return super(PyPy2, cls).modules() + [
+ return super().modules() + [
"os",
"copy_reg",
"genericpath",
@@ -61,7 +55,7 @@ class PyPy2(PyPy, Python2):
return self.dest / "lib_pypy"
def ensure_directories(self):
- dirs = super(PyPy2, self).ensure_directories()
+ dirs = super().ensure_directories()
dirs.add(self.lib_pypy)
host_include_marker = self.host_include_marker(self.interpreter)
if host_include_marker.exists():
@@ -76,7 +70,7 @@ class PyPy2(PyPy, Python2):
PyPy2 built-in imports are handled by this path entry, don't overwrite to not disable it
see: https://github.com/pypa/virtualenv/issues/1652
"""
- return 'or path.endswith("lib_pypy{}__extensions__") # PyPy2 built-in import marker'.format(os.sep)
+ return f'or path.endswith("lib_pypy{os.sep}__extensions__") # PyPy2 built-in import marker'
class PyPy2Posix(PyPy2, PosixSupports):
@@ -84,7 +78,7 @@ class PyPy2Posix(PyPy2, PosixSupports):
@classmethod
def modules(cls):
- return super(PyPy2Posix, cls).modules() + ["posixpath"]
+ return super().modules() + ["posixpath"]
@classmethod
def _shared_libs(cls, python_dir):
@@ -96,8 +90,7 @@ class PyPy2Posix(PyPy2, PosixSupports):
@classmethod
def sources(cls, interpreter):
- for src in super(PyPy2Posix, cls).sources(interpreter):
- yield src
+ yield from super().sources(interpreter)
host_lib = Path(interpreter.system_prefix) / "lib"
if host_lib.exists():
yield PathRefToDest(host_lib, dest=lambda self, _: self.lib)
@@ -108,7 +101,7 @@ class Pypy2Windows(PyPy2, WindowsSupports):
@classmethod
def modules(cls):
- return super(Pypy2Windows, cls).modules() + ["ntpath"]
+ return super().modules() + ["ntpath"]
@classmethod
def _shared_libs(cls, python_dir):
@@ -120,6 +113,12 @@ class Pypy2Windows(PyPy2, WindowsSupports):
@classmethod
def sources(cls, interpreter):
- for src in super(Pypy2Windows, cls).sources(interpreter):
- yield src
+ yield from super().sources(interpreter)
yield PathRefToDest(Path(interpreter.system_prefix) / "libs", dest=lambda self, s: self.dest / s.name)
+
+
+__all__ = [
+ "PyPy2",
+ "PyPy2Posix",
+ "Pypy2Windows",
+]
diff --git a/src/virtualenv/create/via_global_ref/builtin/pypy/pypy3.py b/src/virtualenv/create/via_global_ref/builtin/pypy/pypy3.py
index 06e15a5..ca5778c 100644
--- a/src/virtualenv/create/via_global_ref/builtin/pypy/pypy3.py
+++ b/src/virtualenv/create/via_global_ref/builtin/pypy/pypy3.py
@@ -1,25 +1,20 @@
-from __future__ import absolute_import, unicode_literals
-
import abc
-
-from six import add_metaclass
+from pathlib import Path
from virtualenv.create.describe import PosixSupports, Python3Supports, WindowsSupports
from virtualenv.create.via_global_ref.builtin.ref import PathRefToDest
-from virtualenv.util.path import Path
from .common import PyPy
-@add_metaclass(abc.ABCMeta)
-class PyPy3(PyPy, Python3Supports):
+class PyPy3(PyPy, Python3Supports, metaclass=abc.ABCMeta):
@classmethod
def exe_stem(cls):
return "pypy3"
@classmethod
def exe_names(cls, interpreter):
- return super(PyPy3, cls).exe_names(interpreter) | {"pypy"}
+ return super().exe_names(interpreter) | {"pypy"}
class PyPy3Posix(PyPy3, PosixSupports):
@@ -28,7 +23,7 @@ class PyPy3Posix(PyPy3, PosixSupports):
@property
def stdlib(self):
"""PyPy3 respects sysconfig only for the host python, virtual envs is instead lib/pythonx.y/site-packages"""
- return self.dest / "lib" / "pypy{}".format(self.interpreter.version_release_str) / "site-packages"
+ return self.dest / "lib" / f"pypy{self.interpreter.version_release_str}" / "site-packages"
@classmethod
def _shared_libs(cls, python_dir):
@@ -40,8 +35,7 @@ class PyPy3Posix(PyPy3, PosixSupports):
@classmethod
def sources(cls, interpreter):
- for src in super(PyPy3Posix, cls).sources(interpreter):
- yield src
+ yield from super().sources(interpreter)
# PyPy >= 3.8 supports a standard prefix installation, where older
# versions always used a portable/development style installation.
# If this is a standard prefix installation, skip the below:
@@ -87,5 +81,11 @@ class Pypy3Windows(PyPy3, WindowsSupports):
# glob for libpypy*.dll and libffi*.dll
for pattern in ["libpypy*.dll", "libffi*.dll"]:
srcs = python_dir.glob(pattern)
- for src in srcs:
- yield src
+ yield from srcs
+
+
+__all__ = [
+ "PyPy3",
+ "PyPy3Posix",
+ "Pypy3Windows",
+]
diff --git a/src/virtualenv/create/via_global_ref/builtin/python2/python2.py b/src/virtualenv/create/via_global_ref/builtin/python2/python2.py
index cacd56e..9b963b3 100644
--- a/src/virtualenv/create/via_global_ref/builtin/python2/python2.py
+++ b/src/virtualenv/create/via_global_ref/builtin/python2/python2.py
@@ -1,16 +1,11 @@
-from __future__ import absolute_import, unicode_literals
-
import abc
import json
import os
-
-from six import add_metaclass
+from pathlib import Path
from virtualenv.create.describe import Python2Supports
from virtualenv.create.via_global_ref.builtin.ref import PathRefToDest
from virtualenv.info import IS_ZIPAPP
-from virtualenv.util.path import Path
-from virtualenv.util.six import ensure_text
from virtualenv.util.zipapp import read as read_from_zipapp
from ..via_global_self_do import ViaGlobalRefVirtualenvBuiltin
@@ -18,11 +13,10 @@ from ..via_global_self_do import ViaGlobalRefVirtualenvBuiltin
HERE = Path(os.path.abspath(__file__)).parent
-@add_metaclass(abc.ABCMeta)
-class Python2(ViaGlobalRefVirtualenvBuiltin, Python2Supports):
+class Python2(ViaGlobalRefVirtualenvBuiltin, Python2Supports, metaclass=abc.ABCMeta):
def create(self):
"""Perform operations needed to make the created environment work on Python 2"""
- super(Python2, self).create()
+ super().create()
# install a patched site-package, the default Python 2 site.py is not smart enough to understand pyvenv.cfg,
# so we inject a small shim that can do this, the location of this depends where it's on host
sys_std_plat = Path(self.interpreter.system_stdlib_platform)
@@ -38,14 +32,14 @@ class Python2(ViaGlobalRefVirtualenvBuiltin, Python2Supports):
custom_site_text = read_from_zipapp(custom_site)
else:
custom_site_text = custom_site.read_text()
- expected = json.dumps([os.path.relpath(ensure_text(str(i)), ensure_text(str(site_py))) for i in self.libs])
+ expected = json.dumps([os.path.relpath(str(i), str(site_py)) for i in self.libs])
custom_site_text = custom_site_text.replace("___EXPECTED_SITE_PACKAGES___", expected)
- reload_code = os.linesep.join(" {}".format(i) for i in self.reload_code.splitlines()).lstrip()
+ reload_code = os.linesep.join(f" {i}" for i in self.reload_code.splitlines()).lstrip()
custom_site_text = custom_site_text.replace("# ___RELOAD_CODE___", reload_code)
- skip_rewrite = os.linesep.join(" {}".format(i) for i in self.skip_rewrite.splitlines()).lstrip()
+ skip_rewrite = os.linesep.join(f" {i}" for i in self.skip_rewrite.splitlines()).lstrip()
custom_site_text = custom_site_text.replace("# ___SKIP_REWRITE____", skip_rewrite)
site_py.write_text(custom_site_text)
@@ -60,8 +54,7 @@ class Python2(ViaGlobalRefVirtualenvBuiltin, Python2Supports):
@classmethod
def sources(cls, interpreter):
- for src in super(Python2, cls).sources(interpreter):
- yield src
+ yield from super().sources(interpreter)
# install files needed to run site.py, either from stdlib or stdlib_platform, at least pyc, but both if exists
# if neither exists return the module file to trigger failure
mappings, needs_py_module = (
@@ -69,8 +62,8 @@ class Python2(ViaGlobalRefVirtualenvBuiltin, Python2Supports):
cls.needs_stdlib_py_module(),
)
for req in cls.modules():
- module_file, to_module, module_exists = cls.from_stdlib(mappings, "{}.py".format(req))
- compiled_file, to_compiled, compiled_exists = cls.from_stdlib(mappings, "{}.pyc".format(req))
+ module_file, to_module, module_exists = cls.from_stdlib(mappings, f"{req}.py")
+ compiled_file, to_compiled, compiled_exists = cls.from_stdlib(mappings, f"{req}.pyc")
if needs_py_module or module_exists or not compiled_exists:
yield PathRefToDest(module_file, dest=to_module)
if compiled_exists:
diff --git a/src/virtualenv/create/via_global_ref/builtin/ref.py b/src/virtualenv/create/via_global_ref/builtin/ref.py
index 69f243b..fb1cf2e 100644
--- a/src/virtualenv/create/via_global_ref/builtin/ref.py
+++ b/src/virtualenv/create/via_global_ref/builtin/ref.py
@@ -3,34 +3,29 @@ Virtual environments in the traditional sense are built as reference to the host
references to elements on the file system, allowing our system to automatically detect what modes it can support given
the constraints: e.g. can the file system symlink, can the files be read, executed, etc.
"""
-from __future__ import absolute_import, unicode_literals
import os
from abc import ABCMeta, abstractmethod
from collections import OrderedDict
from stat import S_IXGRP, S_IXOTH, S_IXUSR
-from six import add_metaclass
-
from virtualenv.info import fs_is_case_sensitive, fs_supports_symlink
from virtualenv.util.path import copy, make_exe, symlink
-from virtualenv.util.six import ensure_text
-class RefMust(object):
+class RefMust:
NA = "NA"
COPY = "copy"
SYMLINK = "symlink"
-class RefWhen(object):
+class RefWhen:
ANY = "ANY"
COPY = "copy"
SYMLINK = "symlink"
-@add_metaclass(ABCMeta)
-class PathRef(object):
+class PathRef(metaclass=ABCMeta):
"""Base class that checks if a file reference can be symlink/copied"""
FS_SUPPORTS_SYMLINK = fs_supports_symlink()
@@ -49,7 +44,7 @@ class PathRef(object):
self._can_symlink = None if self.exists else False
def __repr__(self):
- return "{}(src={})".format(self.__class__.__name__, self.src)
+ return f"{self.__class__.__name__}(src={self.src})"
@property
def can_read(self):
@@ -61,7 +56,7 @@ class PathRef(object):
except OSError:
self._can_read = False
else:
- self._can_read = os.access(ensure_text(str(self.src)), os.R_OK)
+ self._can_read = os.access(str(self.src), os.R_OK)
return self._can_read
@property
@@ -94,12 +89,11 @@ class PathRef(object):
return symlink if symlinks else copy
-@add_metaclass(ABCMeta)
-class ExePathRef(PathRef):
+class ExePathRef(PathRef, metaclass=ABCMeta):
"""Base class that checks if a executable can be references via symlink/copy"""
def __init__(self, src, must=RefMust.NA, when=RefWhen.ANY):
- super(ExePathRef, self).__init__(src, must, when)
+ super().__init__(src, must, when)
self._can_run = None
@property
@@ -125,7 +119,7 @@ class PathRefToDest(PathRef):
"""Link a path on the file system"""
def __init__(self, src, dest, must=RefMust.NA, when=RefWhen.ANY):
- super(PathRefToDest, self).__init__(src, must, when)
+ super().__init__(src, must, when)
self.dest = dest
def run(self, creator, symlinks):
@@ -169,4 +163,14 @@ class ExePathRefToDest(PathRefToDest, ExePathRef):
make_exe(link_file)
def __repr__(self):
- return "{}(src={}, alias={})".format(self.__class__.__name__, self.src, self.aliases)
+ return f"{self.__class__.__name__}(src={self.src}, alias={self.aliases})"
+
+
+__all__ = [
+ "ExePathRef",
+ "ExePathRefToDest",
+ "PathRefToDest",
+ "PathRef",
+ "RefWhen",
+ "RefMust",
+]
diff --git a/src/virtualenv/create/via_global_ref/builtin/via_global_self_do.py b/src/virtualenv/create/via_global_ref/builtin/via_global_self_do.py
index 863ae16..2d491cc 100644
--- a/src/virtualenv/create/via_global_ref/builtin/via_global_self_do.py
+++ b/src/virtualenv/create/via_global_ref/builtin/via_global_self_do.py
@@ -1,9 +1,5 @@
-from __future__ import absolute_import, unicode_literals
-
from abc import ABCMeta
-from six import add_metaclass
-
from virtualenv.create.via_global_ref.builtin.ref import ExePathRefToDest, RefMust, RefWhen
from virtualenv.util.path import ensure_dir
@@ -13,19 +9,18 @@ from .builtin_way import VirtualenvBuiltin
class BuiltinViaGlobalRefMeta(ViaGlobalRefMeta):
def __init__(self):
- super(BuiltinViaGlobalRefMeta, self).__init__()
+ super().__init__()
self.sources = []
-@add_metaclass(ABCMeta)
-class ViaGlobalRefVirtualenvBuiltin(ViaGlobalRefApi, VirtualenvBuiltin):
+class ViaGlobalRefVirtualenvBuiltin(ViaGlobalRefApi, VirtualenvBuiltin, metaclass=ABCMeta):
def __init__(self, options, interpreter):
- super(ViaGlobalRefVirtualenvBuiltin, self).__init__(options, interpreter)
+ super().__init__(options, interpreter)
self._sources = getattr(options.meta, "sources", None) # if we're created as a describer this might be missing
@classmethod
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
if not cls.can_describe(interpreter):
return None
@@ -39,11 +34,11 @@ class ViaGlobalRefVirtualenvBuiltin(ViaGlobalRefApi, VirtualenvBuiltin):
for src in cls.sources(interpreter):
if src.exists:
if meta.can_copy and not src.can_copy:
- meta.copy_error = "cannot copy {}".format(src)
+ meta.copy_error = f"cannot copy {src}"
if meta.can_symlink and not src.can_symlink:
- meta.symlink_error = "cannot symlink {}".format(src)
+ meta.symlink_error = f"cannot symlink {src}"
else:
- msg = "missing required file {}".format(src)
+ msg = f"missing required file {src}"
if src.when == RefMust.NA:
meta.error = msg
elif src.when == RefMust.COPY:
@@ -51,10 +46,7 @@ class ViaGlobalRefVirtualenvBuiltin(ViaGlobalRefApi, VirtualenvBuiltin):
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,
- )
+ meta.error = f"neither copy or symlink supported, copy: {meta.copy_error} symlink: {meta.symlink_error}"
if meta.error:
break
meta.sources.append(src)
@@ -98,7 +90,7 @@ class ViaGlobalRefVirtualenvBuiltin(ViaGlobalRefApi, VirtualenvBuiltin):
finally:
if true_system_site != self.enable_system_site_package:
self.enable_system_site_package = true_system_site
- super(ViaGlobalRefVirtualenvBuiltin, self).create()
+ super().create()
def ensure_directories(self):
return {self.dest, self.bin_dir, self.script_dir, self.stdlib} | set(self.libs)
@@ -108,7 +100,13 @@ class ViaGlobalRefVirtualenvBuiltin(ViaGlobalRefApi, VirtualenvBuiltin):
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)
"""
- super(ViaGlobalRefVirtualenvBuiltin, self).set_pyenv_cfg()
+ super().set_pyenv_cfg()
self.pyenv_cfg["base-prefix"] = self.interpreter.system_prefix
self.pyenv_cfg["base-exec-prefix"] = self.interpreter.system_exec_prefix
self.pyenv_cfg["base-executable"] = self.interpreter.system_executable
+
+
+__all__ = [
+ "BuiltinViaGlobalRefMeta",
+ "ViaGlobalRefVirtualenvBuiltin",
+]
diff --git a/src/virtualenv/create/via_global_ref/store.py b/src/virtualenv/create/via_global_ref/store.py
index 134a535..a9c559c 100644
--- a/src/virtualenv/create/via_global_ref/store.py
+++ b/src/virtualenv/create/via_global_ref/store.py
@@ -1,6 +1,4 @@
-from __future__ import absolute_import, unicode_literals
-
-from virtualenv.util.path import Path
+from pathlib import Path
def handle_store_python(meta, interpreter):
@@ -20,7 +18,7 @@ def is_store_python(interpreter):
)
-__all__ = (
+__all__ = [
"handle_store_python",
"is_store_python",
-)
+]
diff --git a/src/virtualenv/create/via_global_ref/venv.py b/src/virtualenv/create/via_global_ref/venv.py
index d9fe9eb..071375a 100644
--- a/src/virtualenv/create/via_global_ref/venv.py
+++ b/src/virtualenv/create/via_global_ref/venv.py
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, unicode_literals
-
import logging
from copy import copy
@@ -16,14 +14,13 @@ from .builtin.pypy.pypy3 import Pypy3Windows
class Venv(ViaGlobalRefApi):
def __init__(self, options, interpreter):
self.describe = options.describe
- super(Venv, self).__init__(options, interpreter)
- self.can_be_inline = (
- interpreter is PythonInfo.current() and interpreter.executable == interpreter.system_executable
- )
+ super().__init__(options, interpreter)
+ current = PythonInfo.current()
+ self.can_be_inline = interpreter is current and interpreter.executable == interpreter.system_executable
self._context = None
def _args(self):
- return super(Venv, self)._args() + ([("describe", self.describe.__class__.__name__)] if self.describe else [])
+ return super()._args() + ([("describe", self.describe.__class__.__name__)] if self.describe else [])
@classmethod
def can_create(cls, interpreter):
@@ -41,7 +38,7 @@ class Venv(ViaGlobalRefApi):
self.create_via_sub_process()
for lib in self.libs:
ensure_dir(lib)
- super(Venv, self).create()
+ super().create()
self.executables_for_win_pypy_less_v37()
def executables_for_win_pypy_less_v37(self):
@@ -84,7 +81,7 @@ class Venv(ViaGlobalRefApi):
def set_pyenv_cfg(self):
# prefer venv options over ours, but keep our extra
venv_content = copy(self.pyenv_cfg.refresh())
- super(Venv, self).set_pyenv_cfg()
+ super().set_pyenv_cfg()
self.pyenv_cfg.update(venv_content)
def __getattribute__(self, item):
@@ -94,3 +91,8 @@ class Venv(ViaGlobalRefApi):
if not callable(element) or item in ("script",):
return element
return object.__getattribute__(self, item)
+
+
+__all__ = [
+ "Venv",
+]
diff --git a/src/virtualenv/discovery/__init__.py b/src/virtualenv/discovery/__init__.py
index 01e6d4f..e69de29 100644
--- a/src/virtualenv/discovery/__init__.py
+++ b/src/virtualenv/discovery/__init__.py
@@ -1 +0,0 @@
-from __future__ import absolute_import, unicode_literals
diff --git a/src/virtualenv/discovery/builtin.py b/src/virtualenv/discovery/builtin.py
index 52f7398..40320d3 100644
--- a/src/virtualenv/discovery/builtin.py
+++ b/src/virtualenv/discovery/builtin.py
@@ -1,11 +1,8 @@
-from __future__ import absolute_import, unicode_literals
-
import logging
import os
import sys
from virtualenv.info import IS_WIN
-from virtualenv.util.six import ensure_str, ensure_text
from .discover import Discover
from .py_info import PythonInfo
@@ -14,7 +11,7 @@ from .py_spec import PythonSpec
class Builtin(Discover):
def __init__(self, options):
- super(Builtin, self).__init__(options)
+ super().__init__(options)
self.python_spec = options.python if options.python else [sys.executable]
self.app_data = options.app_data
self.try_first_with = options.try_first_with
@@ -50,11 +47,8 @@ class Builtin(Discover):
return None
def __repr__(self):
- return ensure_str(self.__unicode__())
-
- def __unicode__(self):
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)
+ return f"{self.__class__.__name__} discover of python_spec={spec!r}"
def get_interpreter(key, try_first_with, app_data=None, env=None):
@@ -110,10 +104,10 @@ def propose_interpreters(spec, try_first_with, app_data, env=None):
paths = get_paths(env)
tested_exes = set()
for pos, path in enumerate(paths):
- path = ensure_text(path)
- logging.debug(LazyPathDump(pos, path, env))
+ path_str = str(path)
+ logging.debug(LazyPathDump(pos, path_str, env))
for candidate, match in possible_specs(spec):
- found = check_path(candidate, path)
+ found = check_path(candidate, path_str)
if found is not None:
exe = os.path.abspath(found)
if exe not in tested_exes:
@@ -124,7 +118,7 @@ def propose_interpreters(spec, try_first_with, app_data, env=None):
def get_paths(env):
- path = env.get(str("PATH"), None)
+ path = env.get("PATH", None)
if path is None:
try:
path = os.confstr("CS_PATH")
@@ -137,18 +131,15 @@ def get_paths(env):
return paths
-class LazyPathDump(object):
+class LazyPathDump:
def __init__(self, pos, path, env):
self.pos = pos
self.path = path
self.env = env
def __repr__(self):
- return ensure_str(self.__unicode__())
-
- def __unicode__(self):
- content = "discover PATH[{}]={}".format(self.pos, self.path)
- if self.env.get(str("_VIRTUALENV_DEBUG")): # this is the over the board debug
+ content = f"discover PATH[{self.pos}]={self.path}"
+ if self.env.get("_VIRTUALENV_DEBUG"): # this is the over the board debug
content += " with =>"
for file_name in os.listdir(self.path):
try:
@@ -178,9 +169,15 @@ def possible_specs(spec):
# 4. then maybe it's something exact on PATH - if it was direct lookup implementation no longer counts
yield spec.str_spec, False
# 5. or from the spec we can deduce a name on path that matches
- for exe, match in spec.generate_names():
- yield exe, match
+ yield from spec.generate_names()
class PathPythonInfo(PythonInfo):
- """ """
+ """python info from path"""
+
+
+__all__ = [
+ "get_interpreter",
+ "Builtin",
+ "PathPythonInfo",
+]
diff --git a/src/virtualenv/discovery/cached_py_info.py b/src/virtualenv/discovery/cached_py_info.py
index 7eb4161..22ad249 100644
--- a/src/virtualenv/discovery/cached_py_info.py
+++ b/src/virtualenv/discovery/cached_py_info.py
@@ -4,26 +4,20 @@ We acquire the python information by running an interrogation script via subproc
cheap, especially not on Windows. To not have to pay this hefty cost every time we apply multiple levels of
caching.
"""
-from __future__ import absolute_import, unicode_literals
import logging
import os
import random
import sys
from collections import OrderedDict
+from pathlib import Path
+from shlex import quote
from string import ascii_lowercase, ascii_uppercase, digits
+from subprocess import Popen
from virtualenv.app_data import AppDataDisabled
from virtualenv.discovery.py_info import PythonInfo
-from virtualenv.info import PY2
-from virtualenv.util.path import Path
-from virtualenv.util.six import ensure_text
-from virtualenv.util.subprocess import Popen, subprocess
-
-if PY2:
- from pipes import quote
-else:
- from shlex import quote
+from virtualenv.util.subprocess import subprocess
_CACHE = OrderedDict()
_CACHE[Path(sys.executable)] = PythonInfo()
@@ -36,7 +30,7 @@ def from_exe(cls, app_data, exe, env=None, raise_on_error=True, ignore_cache=Fal
if raise_on_error:
raise result
else:
- logging.info("%s", str(result))
+ logging.info("%s", result)
result = None
return result
@@ -57,7 +51,7 @@ def _get_from_cache(cls, app_data, exe, env, ignore_cache=True):
def _get_via_file_cache(cls, app_data, path, exe, env):
- path_text = ensure_text(str(path))
+ path_text = str(path)
try:
path_modified = path.stat().st_mtime
except OSError:
@@ -87,7 +81,7 @@ def _get_via_file_cache(cls, app_data, path, exe, env):
return py_info
-COOKIE_LENGTH = 32 # type: int
+COOKIE_LENGTH: int = 32
def gen_cookie():
@@ -150,46 +144,30 @@ def _run_subprocess(cls, exe, app_data, env):
result = cls._from_json(out)
result.executable = exe # keep original executable as this may contain initialization code
else:
- msg = "failed to query {} with code {}{}{}".format(
- exe,
- code,
- " out: {!r}".format(out) if out else "",
- " err: {!r}".format(err) if err else "",
- )
- failure = RuntimeError(msg)
+ msg = f"{exe} with code {code}{f' out: {out!r}' if out else ''}{f' err: {err!r}' if err else ''}"
+ failure = RuntimeError(f"failed to query {msg}")
return failure, result
-class LogCmd(object):
+class LogCmd:
def __init__(self, cmd, env=None):
self.cmd = cmd
self.env = env
def __repr__(self):
- def e(v):
- return v.decode("utf-8") if isinstance(v, bytes) else v
-
- cmd_repr = e(" ").join(quote(e(c)) for c in self.cmd)
+ cmd_repr = " ".join(quote(str(c)) for c in self.cmd)
if self.env is not None:
- cmd_repr += e(" env of {!r}").format(self.env)
- if PY2:
- return cmd_repr.encode("utf-8")
+ cmd_repr = f"{cmd_repr} env of {self.env!r}"
return cmd_repr
- def __unicode__(self):
- raw = repr(self)
- if PY2:
- return raw.decode("utf-8")
- return raw
-
def clear(app_data):
app_data.py_info_clear()
_CACHE.clear()
-___all___ = (
+___all___ = [
"from_exe",
"clear",
"LogCmd",
-)
+]
diff --git a/src/virtualenv/discovery/discover.py b/src/virtualenv/discovery/discover.py
index 72748c3..8950a55 100644
--- a/src/virtualenv/discovery/discover.py
+++ b/src/virtualenv/discovery/discover.py
@@ -1,12 +1,7 @@
-from __future__ import absolute_import, unicode_literals
-
from abc import ABCMeta, abstractmethod
-from six import add_metaclass
-
-@add_metaclass(ABCMeta)
-class Discover(object):
+class Discover(metaclass=ABCMeta):
"""Discover and provide the requested Python interpreter"""
@classmethod
@@ -17,7 +12,6 @@ class Discover(object):
"""
raise NotImplementedError
- # noinspection PyUnusedLocal
def __init__(self, options):
"""Create a new discovery mechanism.
@@ -31,7 +25,6 @@ class Discover(object):
def run(self):
"""Discovers an interpreter.
-
:return: the interpreter ready to use for virtual environment creation
"""
raise NotImplementedError
@@ -45,3 +38,8 @@ class Discover(object):
self._interpreter = self.run()
self._has_run = True
return self._interpreter
+
+
+__all__ = [
+ "Discover",
+]
diff --git a/src/virtualenv/discovery/py_spec.py b/src/virtualenv/discovery/py_spec.py
index cb63e15..058d8be 100644
--- a/src/virtualenv/discovery/py_spec.py
+++ b/src/virtualenv/discovery/py_spec.py
@@ -1,19 +1,15 @@
-"""A Python specification is an abstract requirement definition of a interpreter"""
-from __future__ import absolute_import, unicode_literals
+"""A Python specification is an abstract requirement definition of an interpreter"""
import os
import re
-import sys
from collections import OrderedDict
from virtualenv.info import fs_is_case_sensitive
-from virtualenv.util.six import ensure_str
PATTERN = re.compile(r"^(?P<impl>[a-zA-Z]+)?(?P<version>[0-9.]+)?(?:-(?P<arch>32|64))?$")
-IS_WIN = sys.platform == "win32"
-class PythonSpec(object):
+class PythonSpec:
"""Contains specification about a Python Interpreter"""
def __init__(self, str_spec, implementation, major, minor, micro, architecture, path):
@@ -87,7 +83,7 @@ class PythonSpec(object):
for impl, match in impls.items():
for at in range(len(version), -1, -1):
cur_ver = version[0:at]
- spec = "{}{}".format(impl, ".".join(str(i) for i in cur_ver))
+ spec = f"{impl}{'.'.join(str(i) for i in cur_ver)}"
yield spec, match
@property
@@ -108,15 +104,12 @@ class PythonSpec(object):
return False
return True
- def __unicode__(self):
- return "{}({})".format(
- type(self).__name__,
- ", ".join(
- "{}={}".format(k, getattr(self, k))
- for k in ("implementation", "major", "minor", "micro", "architecture", "path")
- if getattr(self, k) is not None
- ),
- )
-
def __repr__(self):
- return ensure_str(self.__unicode__())
+ name = type(self).__name__
+ params = "implementation", "major", "minor", "micro", "architecture", "path"
+ return f"{name}({', '.join(f'{k}={getattr(self, k)}' for k in params if getattr(self, k) is not None)})"
+
+
+__all__ = [
+ "PythonSpec",
+]
diff --git a/src/virtualenv/discovery/windows/__init__.py b/src/virtualenv/discovery/windows/__init__.py
index 259be97..4663a3a 100644
--- a/src/virtualenv/discovery/windows/__init__.py
+++ b/src/virtualenv/discovery/windows/__init__.py
@@ -1,12 +1,10 @@
-from __future__ import absolute_import, unicode_literals
-
from ..py_info import PythonInfo
from ..py_spec import PythonSpec
from .pep514 import discover_pythons
class Pep514PythonInfo(PythonInfo):
- """ """
+ """A Python information acquired from PEP-514"""
def propose_interpreters(spec, cache_dir, env):
@@ -29,3 +27,9 @@ def propose_interpreters(spec, cache_dir, env):
if interpreter is not None:
if interpreter.satisfies(spec, impl_must_match=True):
yield interpreter
+
+
+__all__ = [
+ "Pep514PythonInfo",
+ "propose_interpreters",
+]
diff --git a/src/virtualenv/discovery/windows/pep514.py b/src/virtualenv/discovery/windows/pep514.py
index 048436a..beb1d81 100644
--- a/src/virtualenv/discovery/windows/pep514.py
+++ b/src/virtualenv/discovery/windows/pep514.py
@@ -1,18 +1,10 @@
"""Implement https://www.python.org/dev/peps/pep-0514/ to discover interpreters - Windows only"""
-from __future__ import absolute_import, print_function, unicode_literals
import os
import re
+import winreg
from logging import basicConfig, getLogger
-import six
-
-if six.PY3:
- import winreg
-else:
- # noinspection PyUnresolvedReferences
- import _winreg as winreg
-
LOGGER = getLogger(__name__)
@@ -39,8 +31,7 @@ def discover_pythons():
(winreg.HKEY_LOCAL_MACHINE, "HKEY_LOCAL_MACHINE", r"Software\Python", winreg.KEY_WOW64_64KEY, 64),
(winreg.HKEY_LOCAL_MACHINE, "HKEY_LOCAL_MACHINE", r"Software\Python", winreg.KEY_WOW64_32KEY, 32),
]:
- for spec in process_set(hive, hive_name, key, flags, default_arch):
- yield spec
+ yield from process_set(hive, hive_name, key, flags, default_arch)
def process_set(hive, hive_name, key, flags, default_arch):
@@ -49,8 +40,7 @@ def process_set(hive, hive_name, key, flags, default_arch):
for company in enum_keys(root_key):
if company == "PyLauncher": # reserved
continue
- for spec in process_company(hive_name, company, root_key, default_arch):
- yield spec
+ yield from process_company(hive_name, company, root_key, default_arch)
except OSError:
pass
@@ -77,9 +67,9 @@ def process_tag(hive_name, company, company_key, tag, default_arch):
def load_exe(hive_name, company, company_key, tag):
- key_path = "{}/{}/{}".format(hive_name, company, tag)
+ key_path = f"{hive_name}/{company}/{tag}"
try:
- with winreg.OpenKeyEx(company_key, r"{}\InstallPath".format(tag)) as ip_key:
+ with winreg.OpenKeyEx(company_key, rf"{tag}\InstallPath") as ip_key:
with ip_key:
exe = get_value(ip_key, "ExecutablePath")
if exe is None:
@@ -88,21 +78,21 @@ def load_exe(hive_name, company, company_key, tag):
msg(key_path, "no ExecutablePath or default for it")
else:
- exe = os.path.join(ip, str("python.exe"))
+ exe = os.path.join(ip, "python.exe")
if exe is not None and os.path.exists(exe):
args = get_value(ip_key, "ExecutableArguments")
return exe, args
else:
- msg(key_path, "could not load exe with value {}".format(exe))
+ msg(key_path, f"could not load exe with value {exe}")
except OSError:
- msg("{}/{}".format(key_path, "InstallPath"), "missing")
+ msg(f"{key_path}/InstallPath", "missing")
return None
def load_arch_data(hive_name, company, tag, tag_key, default_arch):
arch_str = get_value(tag_key, "SysArchitecture")
if arch_str is not None:
- key_path = "{}/{}/{}/SysArchitecture".format(hive_name, company, tag)
+ key_path = f"{hive_name}/{company}/{tag}/SysArchitecture"
try:
return parse_arch(arch_str)
except ValueError as sys_arch:
@@ -111,20 +101,20 @@ def load_arch_data(hive_name, company, tag, tag_key, default_arch):
def parse_arch(arch_str):
- if isinstance(arch_str, six.string_types):
+ if isinstance(arch_str, str):
match = re.match(r"^(\d+)bit$", arch_str)
if match:
return int(next(iter(match.groups())))
- error = "invalid format {}".format(arch_str)
+ error = f"invalid format {arch_str}"
else:
- error = "arch is not string: {}".format(repr(arch_str))
+ error = f"arch is not string: {repr(arch_str)}"
raise ValueError(error)
def load_version_data(hive_name, company, tag, tag_key):
for candidate, key_path in [
- (get_value(tag_key, "SysVersion"), "{}/{}/{}/SysVersion".format(hive_name, company, tag)),
- (tag, "{}/{}/{}".format(hive_name, company, tag)),
+ (get_value(tag_key, "SysVersion"), f"{hive_name}/{company}/{tag}/SysVersion"),
+ (tag, f"{hive_name}/{company}/{tag}"),
]:
if candidate is not None:
try:
@@ -135,18 +125,18 @@ def load_version_data(hive_name, company, tag, tag_key):
def parse_version(version_str):
- if isinstance(version_str, six.string_types):
+ if isinstance(version_str, str):
match = re.match(r"^(\d+)(?:\.(\d+))?(?:\.(\d+))?$", version_str)
if match:
return tuple(int(i) if i is not None else None for i in match.groups())
- error = "invalid format {}".format(version_str)
+ error = f"invalid format {version_str}"
else:
- error = "version is not string: {}".format(repr(version_str))
+ error = f"version is not string: {version_str!r}"
raise ValueError(error)
def msg(path, what):
- LOGGER.warning("PEP-514 violation in Windows Registry at {} error: {}".format(path, what))
+ LOGGER.warning(f"PEP-514 violation in Windows Registry at {path} error: {what}")
def _run():
diff --git a/src/virtualenv/info.py b/src/virtualenv/info.py
index 7d5e86d..a4fc4bf 100644
--- a/src/virtualenv/info.py
+++ b/src/virtualenv/info.py
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, unicode_literals
-
import logging
import os
import platform
@@ -9,13 +7,10 @@ import tempfile
IMPLEMENTATION = platform.python_implementation()
IS_PYPY = IMPLEMENTATION == "PyPy"
IS_CPYTHON = IMPLEMENTATION == "CPython"
-PY3 = sys.version_info[0] == 3
-PY2 = sys.version_info[0] == 2
IS_WIN = sys.platform == "win32"
IS_MAC_ARM64 = sys.platform == "darwin" and platform.machine() == "arm64"
ROOT = os.path.realpath(os.path.join(os.path.abspath(__file__), os.path.pardir, os.path.pardir))
IS_ZIPAPP = os.path.isfile(ROOT)
-WIN_CPYTHON_2 = IS_CPYTHON and IS_WIN and PY2
_CAN_SYMLINK = _FS_CASE_SENSITIVE = _CFG_DIR = _DATA_DIR = None
@@ -39,7 +34,7 @@ def fs_supports_symlink():
if IS_WIN:
with tempfile.NamedTemporaryFile(prefix="TmP") as tmp_file:
temp_dir = os.path.dirname(tmp_file.name)
- dest = os.path.join(temp_dir, "{}-{}".format(tmp_file.name, "b"))
+ dest = os.path.join(temp_dir, f"{tmp_file.name}-{'b'}")
try:
os.symlink(tmp_file.name, dest)
can = True
@@ -55,12 +50,10 @@ def fs_supports_symlink():
__all__ = (
"IS_PYPY",
"IS_CPYTHON",
- "PY3",
- "PY2",
"IS_WIN",
"fs_is_case_sensitive",
"fs_supports_symlink",
"ROOT",
"IS_ZIPAPP",
- "WIN_CPYTHON_2",
+ "IS_MAC_ARM64",
)
diff --git a/src/virtualenv/report.py b/src/virtualenv/report.py
index 2a2954f..0236f21 100644
--- a/src/virtualenv/report.py
+++ b/src/virtualenv/report.py
@@ -1,10 +1,6 @@
-from __future__ import absolute_import, unicode_literals
-
import logging
import sys
-from virtualenv.util.six import ensure_str
-
LEVELS = {
0: logging.CRITICAL,
1: logging.ERROR,
@@ -26,10 +22,10 @@ def setup_report(verbosity, show_pid=False):
msg_format = "%(message)s"
if level <= logging.DEBUG:
locate = "module"
- msg_format = "%(relativeCreated)d {} [%(levelname)s %({})s:%(lineno)d]".format(msg_format, locate)
+ msg_format = f"%(relativeCreated)d {msg_format} [%(levelname)s %({locate})s:%(lineno)d]"
if show_pid:
- msg_format = "[%(process)d] " + msg_format
- formatter = logging.Formatter(ensure_str(msg_format))
+ msg_format = f"[%(process)d] {msg_format}"
+ formatter = logging.Formatter(msg_format)
stream_handler = logging.StreamHandler(stream=sys.stdout)
stream_handler.setLevel(level)
LOGGER.setLevel(logging.NOTSET)
@@ -46,8 +42,8 @@ def _clean_handlers(log):
log.removeHandler(log_handler)
-__all__ = (
+__all__ = [
"LEVELS",
"MAX_LEVEL",
"setup_report",
-)
+]
diff --git a/src/virtualenv/run/__init__.py b/src/virtualenv/run/__init__.py
index e8e7ab1..8f18cd9 100644
--- a/src/virtualenv/run/__init__.py
+++ b/src/virtualenv/run/__init__.py
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, unicode_literals
-
import logging
import os
from functools import partial
@@ -69,7 +67,7 @@ def build_parser(args=None, options=None, setup_logging=True, env=None):
discover = get_discover(parser, args)
parser._interpreter = interpreter = discover.interpreter
if interpreter is None:
- raise RuntimeError("failed to find interpreter for {}".format(discover))
+ raise RuntimeError(f"failed to find interpreter for {discover}")
elements = [
CreatorSelector(interpreter, parser),
SeederSelector(interpreter, parser),
@@ -130,13 +128,13 @@ def add_version_flag(parser):
parser.add_argument(
"--version",
action="version",
- version="%(prog)s {} from {}".format(__version__, virtualenv.__file__),
+ version=f"%(prog)s {__version__} from {virtualenv.__file__}",
help="display the version of the virtualenv package and its location, then exit",
)
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(f"{logging.getLevelName(l)}={c}" for c, l in sorted(list(LEVELS.items())))
msg = "verbosity = verbose - quiet, default {}, mapping => {}"
verbosity_group = parser.add_argument_group(
title="verbosity",
@@ -150,7 +148,7 @@ def _do_report_setup(parser, args, setup_logging):
setup_report(option.verbosity)
-__all__ = (
+__all__ = [
"cli_run",
"session_via_cli",
-)
+]
diff --git a/src/virtualenv/run/plugin/activators.py b/src/virtualenv/run/plugin/activators.py
index 8180981..320cae7 100644
--- a/src/virtualenv/run/plugin/activators.py
+++ b/src/virtualenv/run/plugin/activators.py
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, unicode_literals
-
from argparse import ArgumentTypeError
from collections import OrderedDict
@@ -12,14 +10,14 @@ class ActivationSelector(ComponentBuilder):
possible = OrderedDict(
(k, v) for k, v in self.options("virtualenv.activate").items() if v.supports(interpreter)
)
- super(ActivationSelector, self).__init__(interpreter, parser, "activators", possible)
+ super().__init__(interpreter, parser, "activators", possible)
self.parser.description = "options for activation scripts"
self.active = None
def add_selector_arg_parse(self, name, choices):
self.default = ",".join(choices)
self.parser.add_argument(
- "--{}".format(name),
+ f"--{name}",
default=self.default,
metavar="comma_sep_list",
required=False,
@@ -31,7 +29,7 @@ class ActivationSelector(ComponentBuilder):
elements = [e.strip() for e in entered_str.split(",") if e.strip()]
missing = [e for e in elements if e not in self.possible]
if missing:
- raise ArgumentTypeError("the following activators are not available {}".format(",".join(missing)))
+ raise ArgumentTypeError(f"the following activators are not available {','.join(missing)}")
return elements
def handle_selected_arg_parse(self, options):
@@ -54,3 +52,8 @@ class ActivationSelector(ComponentBuilder):
def create(self, options):
return [activator_class(options) for activator_class in self.active.values()]
+
+
+__all__ = [
+ "ActivationSelector",
+]
diff --git a/src/virtualenv/run/plugin/base.py b/src/virtualenv/run/plugin/base.py
index 048c76a..5fbf81b 100644
--- a/src/virtualenv/run/plugin/base.py
+++ b/src/virtualenv/run/plugin/base.py
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, unicode_literals
-
import sys
from collections import OrderedDict
@@ -13,7 +11,7 @@ else:
importlib_metadata_version = tuple(int(i) for i in version("importlib_metadata").split(".")[:2])
-class PluginLoader(object):
+class PluginLoader:
_OPTIONS = None
_ENTRY_POINTS = None
@@ -52,14 +50,20 @@ class ComponentBuilder(PluginLoader):
def handle_selected_arg_parse(self, options):
selected = getattr(options, self.name)
if selected not in self.possible:
- raise RuntimeError("No implementation for {}".format(self.interpreter))
+ raise RuntimeError(f"No implementation for {self.interpreter}")
self._impl_class = self.possible[selected]
self.populate_selected_argparse(selected, options.app_data)
return selected
def populate_selected_argparse(self, selected, app_data):
- self.parser.description = "options for {} {}".format(self.name, selected)
+ self.parser.description = f"options for {self.name} {selected}"
self._impl_class.add_parser_arguments(self.parser, self.interpreter, app_data)
def create(self, options):
return self._impl_class(options, self.interpreter)
+
+
+__all__ = [
+ "PluginLoader",
+ "ComponentBuilder",
+]
diff --git a/src/virtualenv/run/plugin/creators.py b/src/virtualenv/run/plugin/creators.py
index ef4177a..8953064 100644
--- a/src/virtualenv/run/plugin/creators.py
+++ b/src/virtualenv/run/plugin/creators.py
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, unicode_literals
-
from collections import OrderedDict, defaultdict, namedtuple
from virtualenv.create.describe import Describe
@@ -13,7 +11,7 @@ CreatorInfo = namedtuple("CreatorInfo", ["key_to_class", "key_to_meta", "describ
class CreatorSelector(ComponentBuilder):
def __init__(self, interpreter, parser):
creators, self.key_to_meta, self.describe, self.builtin_key = self.for_interpreter(interpreter)
- super(CreatorSelector, self).__init__(interpreter, parser, "creator", creators)
+ super().__init__(interpreter, parser, "creator", creators)
@classmethod
def for_interpreter(cls, interpreter):
@@ -37,10 +35,10 @@ class CreatorSelector(ComponentBuilder):
describe = creator_class
if not key_to_meta:
if errors:
- rows = ["{} for creators {}".format(k, ", ".join(i.__name__ for i in v)) for k, v in errors.items()]
+ rows = [f"{k} for creators {', '.join(i.__name__ for i in v)}" for k, v in errors.items()]
raise RuntimeError("\n".join(rows))
else:
- raise RuntimeError("No virtualenv implementation for {}".format(interpreter))
+ raise RuntimeError(f"No virtualenv implementation for {interpreter}")
return CreatorInfo(
key_to_class=key_to_class,
key_to_meta=key_to_meta,
@@ -53,13 +51,11 @@ class CreatorSelector(ComponentBuilder):
choices = sorted(choices, key=lambda a: 0 if a == "builtin" else 1)
default_value = self._get_default(choices)
self.parser.add_argument(
- "--{}".format(name),
+ f"--{name}",
choices=choices,
default=default_value,
required=False,
- help="create environment via{}".format(
- "" if self.builtin_key is None else " (builtin = {})".format(self.builtin_key),
- ),
+ help=f"create environment via{'' if self.builtin_key is None else f' (builtin = {self.builtin_key})'}",
)
@staticmethod
@@ -67,11 +63,17 @@ class CreatorSelector(ComponentBuilder):
return next(iter(choices))
def populate_selected_argparse(self, selected, app_data):
- self.parser.description = "options for {} {}".format(self.name, selected)
+ self.parser.description = f"options for {self.name} {selected}"
self._impl_class.add_parser_arguments(self.parser, self.interpreter, self.key_to_meta[selected], app_data)
def create(self, options):
options.meta = self.key_to_meta[getattr(options, self.name)]
if not issubclass(self._impl_class, Describe):
options.describe = self.describe(options, self.interpreter)
- return super(CreatorSelector, self).create(options)
+ return super().create(options)
+
+
+__all__ = [
+ "CreatorSelector",
+ "CreatorInfo",
+]
diff --git a/src/virtualenv/run/plugin/discovery.py b/src/virtualenv/run/plugin/discovery.py
index ac9b7f5..13f39ed 100644
--- a/src/virtualenv/run/plugin/discovery.py
+++ b/src/virtualenv/run/plugin/discovery.py
@@ -1,10 +1,8 @@
-from __future__ import absolute_import, unicode_literals
-
from .base import PluginLoader
class Discovery(PluginLoader):
- """ """
+ """Discovery plugins"""
def get_discover(parser, args):
@@ -33,3 +31,9 @@ def get_discover(parser, args):
def _get_default_discovery(discover_types):
return list(discover_types.keys())
+
+
+__all__ = [
+ "get_discover",
+ "Discovery",
+]
diff --git a/src/virtualenv/run/plugin/seeders.py b/src/virtualenv/run/plugin/seeders.py
index d182c6f..1a51d2e 100644
--- a/src/virtualenv/run/plugin/seeders.py
+++ b/src/virtualenv/run/plugin/seeders.py
@@ -1,16 +1,14 @@
-from __future__ import absolute_import, unicode_literals
-
from .base import ComponentBuilder
class SeederSelector(ComponentBuilder):
def __init__(self, interpreter, parser):
possible = self.options("virtualenv.seed")
- super(SeederSelector, self).__init__(interpreter, parser, "seeder", possible)
+ super().__init__(interpreter, parser, "seeder", possible)
def add_selector_arg_parse(self, name, choices):
self.parser.add_argument(
- "--{}".format(name),
+ f"--{name}",
choices=choices,
default=self._get_default(),
required=False,
@@ -29,7 +27,12 @@ class SeederSelector(ComponentBuilder):
return "app-data"
def handle_selected_arg_parse(self, options):
- return super(SeederSelector, self).handle_selected_arg_parse(options)
+ return super().handle_selected_arg_parse(options)
def create(self, options):
return self._impl_class(options)
+
+
+__all__ = [
+ "SeederSelector",
+]
diff --git a/src/virtualenv/run/session.py b/src/virtualenv/run/session.py
index 24836d2..84777fe 100644
--- a/src/virtualenv/run/session.py
+++ b/src/virtualenv/run/session.py
@@ -1,12 +1,8 @@
-from __future__ import absolute_import, unicode_literals
-
import json
import logging
-from virtualenv.util.six import ensure_text
-
-class Session(object):
+class Session:
"""Represents a virtual environment creation session"""
def __init__(self, verbosity, app_data, interpreter, creator, seeder, activators):
@@ -49,7 +45,7 @@ class Session(object):
self.creator.pyenv_cfg.write()
def _create(self):
- logging.info("create virtual environment via %s", ensure_text(str(self.creator)))
+ logging.info("create virtual environment via %s", self.creator)
self.creator.run()
logging.debug(_DEBUG_MARKER)
logging.debug("%s", _Debug(self.creator))
@@ -61,10 +57,8 @@ class Session(object):
def _activate(self):
if self.activators:
- logging.info(
- "add activators for %s",
- ", ".join(type(i).__name__.replace("Activator", "") for i in self.activators),
- )
+ active = ", ".join(type(i).__name__.replace("Activator", "") for i in self.activators)
+ logging.info("add activators for %s", active)
for activator in self.activators:
activator.generate(self.creator)
@@ -78,14 +72,16 @@ class Session(object):
_DEBUG_MARKER = "=" * 30 + " target debug " + "=" * 30
-class _Debug(object):
+class _Debug:
"""lazily populate debug"""
def __init__(self, creator):
self.creator = creator
- def __unicode__(self):
- return ensure_text(repr(self))
-
def __repr__(self):
return json.dumps(self.creator.debug, indent=2)
+
+
+__all__ = [
+ "Session",
+]
diff --git a/src/virtualenv/seed/__init__.py b/src/virtualenv/seed/__init__.py
index 01e6d4f..e69de29 100644
--- a/src/virtualenv/seed/__init__.py
+++ b/src/virtualenv/seed/__init__.py
@@ -1 +0,0 @@
-from __future__ import absolute_import, unicode_literals
diff --git a/src/virtualenv/seed/embed/base_embed.py b/src/virtualenv/seed/embed/base_embed.py
index c794e83..b0bcbc3 100644
--- a/src/virtualenv/seed/embed/base_embed.py
+++ b/src/virtualenv/seed/embed/base_embed.py
@@ -1,11 +1,5 @@
-from __future__ import absolute_import, unicode_literals
-
from abc import ABCMeta
-
-from six import add_metaclass
-
-from virtualenv.util.path import Path
-from virtualenv.util.six import ensure_str, ensure_text
+from pathlib import Path
from ..seeder import Seeder
from ..wheels import Version
@@ -13,10 +7,9 @@ from ..wheels import Version
PERIODIC_UPDATE_ON_BY_DEFAULT = True
-@add_metaclass(ABCMeta)
-class BaseEmbed(Seeder):
+class BaseEmbed(Seeder, metaclass=ABCMeta):
def __init__(self, options):
- super(BaseEmbed, self).__init__(options, enabled=options.no_seed is False)
+ super().__init__(options, enabled=options.no_seed is False)
self.download = options.download
self.extra_search_dir = [i.resolve() for i in options.extra_search_dir if i.exists()]
@@ -44,9 +37,9 @@ class BaseEmbed(Seeder):
def distribution_to_versions(self):
return {
- distribution: getattr(self, "{}_version".format(distribution))
+ distribution: getattr(self, f"{distribution}_version")
for distribution in self.distributions()
- if getattr(self, "no_{}".format(distribution)) is False
+ if getattr(self, f"no_{distribution}") is False
}
@classmethod
@@ -57,14 +50,14 @@ class BaseEmbed(Seeder):
"--never-download",
dest="download",
action="store_false",
- help="pass to disable download of the latest {} from PyPI".format("/".join(cls.distributions())),
+ help=f"pass to disable download of the latest {'/'.join(cls.distributions())} from PyPI",
default=True,
)
group.add_argument(
"--download",
dest="download",
action="store_true",
- help="pass to enable download of the latest {} from PyPI".format("/".join(cls.distributions())),
+ help=f"pass to enable download of the latest {'/'.join(cls.distributions())} from PyPI",
default=False,
)
parser.add_argument(
@@ -77,18 +70,18 @@ class BaseEmbed(Seeder):
)
for distribution, default in cls.distributions().items():
parser.add_argument(
- "--{}".format(distribution),
+ f"--{distribution}",
dest=distribution,
metavar="version",
- help="version of {} to install as seed: embed, bundle or exact version".format(distribution),
+ help=f"version of {distribution} to install as seed: embed, bundle or exact version",
default=default,
)
for distribution in cls.distributions():
parser.add_argument(
- "--no-{}".format(distribution),
- dest="no_{}".format(distribution),
+ f"--no-{distribution}",
+ dest=f"no_{distribution}",
action="store_true",
- help="do not install {}".format(distribution),
+ help=f"do not install {distribution}",
default=False,
)
parser.add_argument(
@@ -99,20 +92,20 @@ class BaseEmbed(Seeder):
default=not PERIODIC_UPDATE_ON_BY_DEFAULT,
)
- def __unicode__(self):
+ def __repr__(self):
result = self.__class__.__name__
result += "("
if self.extra_search_dir:
- result += "extra_search_dir={},".format(", ".join(ensure_text(str(i)) for i in self.extra_search_dir))
- result += "download={},".format(self.download)
+ result += f"extra_search_dir={', '.join(str(i) for i in self.extra_search_dir)},"
+ result += f"download={self.download},"
for distribution in self.distributions():
- if getattr(self, "no_{}".format(distribution)):
+ if getattr(self, f"no_{distribution}"):
continue
- result += " {}{},".format(
- distribution,
- "={}".format(getattr(self, "{}_version".format(distribution), None) or "latest"),
- )
+ ver = f"={getattr(self, f'{distribution}_version', None) or 'latest'}"
+ result += f" {distribution}{ver},"
return result[:-1] + ")"
- def __repr__(self):
- return ensure_str(self.__unicode__())
+
+__all__ = [
+ "BaseEmbed",
+]
diff --git a/src/virtualenv/seed/embed/pip_invoke.py b/src/virtualenv/seed/embed/pip_invoke.py
index c935c02..2ca9438 100644
--- a/src/virtualenv/seed/embed/pip_invoke.py
+++ b/src/virtualenv/seed/embed/pip_invoke.py
@@ -1,18 +1,16 @@
-from __future__ import absolute_import, unicode_literals
-
import logging
from contextlib import contextmanager
+from subprocess import Popen
from virtualenv.discovery.cached_py_info import LogCmd
from virtualenv.seed.embed.base_embed import BaseEmbed
-from virtualenv.util.subprocess import Popen
from ..wheels import Version, get_wheel, pip_wheel_env_run
class PipInvoke(BaseEmbed):
def __init__(self, options):
- super(PipInvoke, self).__init__(options)
+ super().__init__(options)
def run(self, creator):
if not self.enabled:
@@ -28,7 +26,7 @@ class PipInvoke(BaseEmbed):
process = Popen(cmd, env=env)
process.communicate()
if process.returncode != 0:
- raise RuntimeError("failed seed with code {}".format(process.returncode))
+ raise RuntimeError(f"failed seed with code {process.returncode}")
return process
@contextmanager
@@ -49,9 +47,14 @@ class PipInvoke(BaseEmbed):
env=self.env,
)
if wheel is None:
- raise RuntimeError("could not get wheel for distribution {}".format(dist))
+ raise RuntimeError(f"could not get wheel for distribution {dist}")
folders.add(str(wheel.path.parent))
cmd.append(Version.as_pip_req(dist, wheel.version))
for folder in sorted(folders):
cmd.extend(["--find-links", str(folder)])
yield cmd
+
+
+__all__ = [
+ "PipInvoke",
+]
diff --git a/src/virtualenv/seed/embed/via_app_data/pip_install/base.py b/src/virtualenv/seed/embed/via_app_data/pip_install/base.py
index 35e0cca..3c44b77 100644
--- a/src/virtualenv/seed/embed/via_app_data/pip_install/base.py
+++ b/src/virtualenv/seed/embed/via_app_data/pip_install/base.py
@@ -1,23 +1,19 @@
-from __future__ import absolute_import, unicode_literals
-
import logging
import os
import re
import zipfile
from abc import ABCMeta, abstractmethod
+from configparser import ConfigParser
from itertools import chain
+from pathlib import Path
from tempfile import mkdtemp
from distlib.scripts import ScriptMaker, enquote_executable
-from six import PY3, add_metaclass
-from virtualenv.util import ConfigParser
-from virtualenv.util.path import Path, safe_delete
-from virtualenv.util.six import ensure_text
+from virtualenv.util.path import safe_delete
-@add_metaclass(ABCMeta)
-class PipInstall(object):
+class PipInstall(metaclass=ABCMeta):
def __init__(self, wheel, creator, image_folder):
self._wheel = wheel
self._creator = creator
@@ -71,10 +67,7 @@ class PipInstall(object):
self._image_dir = Path(to_folder)
def _records_text(self, files):
- record_data = "\n".join(
- "{},,".format(os.path.relpath(ensure_text(str(rec)), ensure_text(str(self._image_dir)))) for rec in files
- )
- return record_data
+ return "\n".join(f"{os.path.relpath(str(rec), str(self._image_dir))},," for rec in files)
def _generate_new_files(self):
new_files = set()
@@ -82,17 +75,17 @@ class PipInstall(object):
installer.write_text("pip\n")
new_files.add(installer)
# inject a no-op root element, as workaround for bug in https://github.com/pypa/pip/issues/7226
- marker = self._image_dir / "{}.virtualenv".format(self._dist_info.stem)
+ marker = self._image_dir / f"{self._dist_info.stem}.virtualenv"
marker.write_text("")
new_files.add(marker)
folder = mkdtemp()
try:
to_folder = Path(folder)
- rel = os.path.relpath(ensure_text(str(self._creator.script_dir)), ensure_text(str(self._creator.purelib)))
+ rel = os.path.relpath(str(self._creator.script_dir), str(self._creator.purelib))
version_info = self._creator.interpreter.version_info
for name, module in self._console_scripts.items():
new_files.update(
- Path(os.path.normpath(ensure_text(str(self._image_dir / rel / i.name))))
+ Path(os.path.normpath(str(self._image_dir / rel / i.name)))
for i in self._create_console_entry_point(name, module, to_folder, version_info)
)
finally:
@@ -111,8 +104,7 @@ class PipInstall(object):
self.__dist_info = filename
break
else:
- msg = "no .dist-info at {}, has {}".format(self._image_dir, ", ".join(files)) # pragma: no cover
- raise RuntimeError(msg) # pragma: no cover
+ raise RuntimeError(f"no .dist-info at {self._image_dir}, has {', '.join(files)}") # pragma: no cover
return self.__dist_info
@abstractmethod
@@ -127,10 +119,9 @@ class PipInstall(object):
self._console_entry_points = {}
entry_points = self._dist_info / "entry_points.txt"
if entry_points.exists():
- parser = ConfigParser.ConfigParser()
+ parser = ConfigParser()
with entry_points.open() as file_handler:
- reader = getattr(parser, "read_file" if PY3 else "readfp")
- reader(file_handler)
+ parser.read_file(file_handler)
if "console_scripts" in parser.sections():
for name, value in parser.items("console_scripts"):
match = re.match(r"(.*?)-?\d\.?\d*", name)
@@ -142,7 +133,7 @@ class PipInstall(object):
def _create_console_entry_point(self, name, value, to_folder, version_info):
result = []
maker = ScriptMakerCustom(to_folder, version_info, self._creator.exe, name)
- specification = "{} = {}".format(name, value)
+ specification = f"{name} = {value}"
new_files = maker.make(specification)
result.extend(Path(i) for i in new_files)
return result
@@ -187,7 +178,7 @@ class PipInstall(object):
class ScriptMakerCustom(ScriptMaker):
def __init__(self, target_dir, version_info, executable, name):
- super(ScriptMakerCustom, self).__init__(None, str(target_dir))
+ super().__init__(None, str(target_dir))
self.clobber = True # overwrite
self.set_mode = True # ensure they are executable
self.executable = enquote_executable(str(executable))
@@ -196,5 +187,10 @@ class ScriptMakerCustom(ScriptMaker):
self._name = name
def _write_script(self, names, shebang, script_bytes, filenames, ext):
- names.add("{}{}.{}".format(self._name, *self.version_info))
- super(ScriptMakerCustom, self)._write_script(names, shebang, script_bytes, filenames, ext)
+ names.add(f"{self._name}{self.version_info[0]}.{self.version_info[1]}")
+ super()._write_script(names, shebang, script_bytes, filenames, ext)
+
+
+__all__ = [
+ "PipInstall",
+]
diff --git a/src/virtualenv/seed/embed/via_app_data/pip_install/copy.py b/src/virtualenv/seed/embed/via_app_data/pip_install/copy.py
index 29d0bc8..f5717e1 100644
--- a/src/virtualenv/seed/embed/via_app_data/pip_install/copy.py
+++ b/src/virtualenv/seed/embed/via_app_data/pip_install/copy.py
@@ -1,9 +1,7 @@
-from __future__ import absolute_import, unicode_literals
-
import os
+from pathlib import Path
-from virtualenv.util.path import Path, copy
-from virtualenv.util.six import ensure_text
+from virtualenv.util.path import copy
from .base import PipInstall
@@ -14,22 +12,27 @@ class CopyPipInstall(PipInstall):
def _generate_new_files(self):
# create the pyc files
- new_files = super(CopyPipInstall, self)._generate_new_files()
+ new_files = super()._generate_new_files()
new_files.update(self._cache_files())
return new_files
def _cache_files(self):
version = self._creator.interpreter.version_info
- py_c_ext = ".{}-{}{}.pyc".format(self._creator.interpreter.implementation.lower(), version.major, version.minor)
- for root, dirs, files in os.walk(ensure_text(str(self._image_dir)), topdown=True):
+ py_c_ext = f".{self._creator.interpreter.implementation.lower()}-{version.major}{version.minor}.pyc"
+ for root, dirs, files in os.walk(str(self._image_dir), topdown=True):
root_path = Path(root)
for name in files:
if name.endswith(".py"):
- yield root_path / "{}{}".format(name[:-3], py_c_ext)
+ yield root_path / f"{name[:-3]}{py_c_ext}"
for name in dirs:
yield root_path / name / "__pycache__"
def _fix_records(self, new_files):
extra_record_data_str = self._records_text(new_files)
- with open(ensure_text(str(self._dist_info / "RECORD")), "ab") as file_handler:
+ with (self._dist_info / "RECORD").open("ab") as file_handler:
file_handler.write(extra_record_data_str.encode("utf-8"))
+
+
+__all__ = [
+ "CopyPipInstall",
+]
diff --git a/src/virtualenv/seed/embed/via_app_data/pip_install/symlink.py b/src/virtualenv/seed/embed/via_app_data/pip_install/symlink.py
index f958b65..4695de5 100644
--- a/src/virtualenv/seed/embed/via_app_data/pip_install/symlink.py
+++ b/src/virtualenv/seed/embed/via_app_data/pip_install/symlink.py
@@ -1,29 +1,20 @@
-from __future__ import absolute_import, unicode_literals
-
import os
-import subprocess
from stat import S_IREAD, S_IRGRP, S_IROTH
+from subprocess import PIPE, Popen
from virtualenv.util.path import safe_delete, set_tree
-from virtualenv.util.six import ensure_text
-from virtualenv.util.subprocess import Popen
from .base import PipInstall
class SymlinkPipInstall(PipInstall):
def _sync(self, src, dst):
- src_str = ensure_text(str(src))
- dest_str = ensure_text(str(dst))
- os.symlink(src_str, dest_str)
+ os.symlink(str(src), str(dst))
def _generate_new_files(self):
# create the pyc files, as the build image will be R/O
- process = Popen(
- [ensure_text(str(self._creator.exe)), "-m", "compileall", ensure_text(str(self._image_dir))],
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- )
+ cmd = [str(self._creator.exe), "-m", "compileall", str(self._image_dir)]
+ process = Popen(cmd, stdout=PIPE, stderr=PIPE)
process.communicate()
# the root pyc is shared, so we'll not symlink that - but still add the pyc files to the RECORD for close
root_py_cache = self._image_dir / "__pycache__"
@@ -32,7 +23,7 @@ class SymlinkPipInstall(PipInstall):
new_files.update(root_py_cache.iterdir())
new_files.add(root_py_cache)
safe_delete(root_py_cache)
- core_new_files = super(SymlinkPipInstall, self)._generate_new_files()
+ core_new_files = super()._generate_new_files()
# remove files that are within the image folder deeper than one level (as these will be not linked directly)
for file in core_new_files:
try:
@@ -47,15 +38,20 @@ class SymlinkPipInstall(PipInstall):
def _fix_records(self, new_files):
new_files.update(i for i in self._image_dir.iterdir())
extra_record_data_str = self._records_text(sorted(new_files, key=str))
- with open(ensure_text(str(self._dist_info / "RECORD")), "wb") as file_handler:
+ with open(str(self._dist_info / "RECORD"), "wb") as file_handler:
file_handler.write(extra_record_data_str.encode("utf-8"))
def build_image(self):
- super(SymlinkPipInstall, self).build_image()
+ super().build_image()
# protect the image by making it read only
set_tree(self._image_dir, S_IREAD | S_IRGRP | S_IROTH)
def clear(self):
if self._image_dir.exists():
safe_delete(self._image_dir)
- super(SymlinkPipInstall, self).clear()
+ super().clear()
+
+
+__all__ = [
+ "SymlinkPipInstall",
+]
diff --git a/src/virtualenv/seed/embed/via_app_data/via_app_data.py b/src/virtualenv/seed/embed/via_app_data/via_app_data.py
index 9a98a70..743ed15 100644
--- a/src/virtualenv/seed/embed/via_app_data/via_app_data.py
+++ b/src/virtualenv/seed/embed/via_app_data/via_app_data.py
@@ -1,17 +1,16 @@
"""Bootstrap"""
-from __future__ import absolute_import, unicode_literals
import logging
import sys
import traceback
from contextlib import contextmanager
+from pathlib import Path
from subprocess import CalledProcessError
from threading import Lock, Thread
from virtualenv.info import fs_supports_symlink
from virtualenv.seed.embed.base_embed import BaseEmbed
from virtualenv.seed.wheels import get_wheel
-from virtualenv.util.path import Path
from .pip_install.copy import CopyPipInstall
from .pip_install.symlink import SymlinkPipInstall
@@ -19,20 +18,19 @@ from .pip_install.symlink import SymlinkPipInstall
class FromAppData(BaseEmbed):
def __init__(self, options):
- super(FromAppData, self).__init__(options)
+ super().__init__(options)
self.symlinks = options.symlink_app_data
@classmethod
def add_parser_arguments(cls, parser, interpreter, app_data):
- super(FromAppData, cls).add_parser_arguments(parser, interpreter, app_data)
+ super().add_parser_arguments(parser, interpreter, app_data)
can_symlink = app_data.transient is False and fs_supports_symlink()
+ sym = "" if can_symlink else "not supported - "
parser.add_argument(
"--symlink-app-data",
dest="symlink_app_data",
action="store_true" if can_symlink else "store_false",
- help="{} symlink the python packages from the app-data folder (requires seed pip>=19.3)".format(
- "" if can_symlink else "not supported - ",
- ),
+ help=f"{sym} symlink the python packages from the app-data folder (requires seed pip>=19.3)",
default=False,
)
@@ -64,7 +62,7 @@ class FromAppData(BaseEmbed):
for thread in threads:
thread.join()
if exceptions:
- messages = ["failed to build image {} because:".format(", ".join(exceptions.keys()))]
+ messages = [f"failed to build image {', '.join(exceptions.keys())} because:"]
for value in exceptions.values():
exc_type, exc_value, exc_traceback = value
messages.append("".join(traceback.format_exception(exc_type, exc_value, exc_traceback)))
@@ -98,11 +96,11 @@ class FromAppData(BaseEmbed):
failure = exception
if failure:
if isinstance(failure, CalledProcessError):
- msg = "failed to download {}".format(distribution)
+ msg = f"failed to download {distribution}"
if version is not None:
- msg += " version {}".format(version)
- msg += ", pip download exit code {}".format(failure.returncode)
- output = failure.output if sys.version_info < (3, 5) else (failure.output + failure.stderr)
+ msg += f" version {version}"
+ msg += f", pip download exit code {failure.returncode}"
+ output = failure.output + failure.stderr
if output:
msg += "\n"
msg += output
@@ -124,7 +122,7 @@ class FromAppData(BaseEmbed):
for thread in threads:
thread.join()
if fail:
- raise RuntimeError("seed failed due to failing to download wheels {}".format(", ".join(fail.keys())))
+ raise RuntimeError(f"seed failed due to failing to download wheels {', '.join(fail.keys())}")
yield name_to_whl
def installer_class(self, pip_version_tuple):
@@ -134,7 +132,12 @@ class FromAppData(BaseEmbed):
return SymlinkPipInstall
return CopyPipInstall
- def __unicode__(self):
- base = super(FromAppData, self).__unicode__()
- msg = ", via={}, app_data_dir={}".format("symlink" if self.symlinks else "copy", self.app_data)
- return base[:-1] + msg + base[-1]
+ def __repr__(self):
+ msg = f", via={'symlink' if self.symlinks else 'copy'}, app_data_dir={self.app_data}"
+ base = super().__repr__()
+ return f"{base[:-1]}{msg}{base[-1]}"
+
+
+__all__ = [
+ "FromAppData",
+]
diff --git a/src/virtualenv/seed/seeder.py b/src/virtualenv/seed/seeder.py
index 852e852..a14e483 100644
--- a/src/virtualenv/seed/seeder.py
+++ b/src/virtualenv/seed/seeder.py
@@ -1,15 +1,9 @@
-from __future__ import absolute_import, unicode_literals
-
from abc import ABCMeta, abstractmethod
-from six import add_metaclass
-
-@add_metaclass(ABCMeta)
-class Seeder(object):
+class Seeder(metaclass=ABCMeta):
"""A seeder will install some seed packages into a virtual environment."""
- # noinspection PyUnusedLocal
def __init__(self, options, enabled):
"""
@@ -38,3 +32,8 @@ class Seeder(object):
virtual environment
"""
raise NotImplementedError
+
+
+__all__ = [
+ "Seeder",
+]
diff --git a/src/virtualenv/seed/wheels/__init__.py b/src/virtualenv/seed/wheels/__init__.py
index dbffe2e..c563181 100644
--- a/src/virtualenv/seed/wheels/__init__.py
+++ b/src/virtualenv/seed/wheels/__init__.py
@@ -1,11 +1,9 @@
-from __future__ import absolute_import, unicode_literals
-
from .acquire import get_wheel, pip_wheel_env_run
from .util import Version, Wheel
-__all__ = (
+__all__ = [
"get_wheel",
"pip_wheel_env_run",
"Version",
"Wheel",
-)
+]
diff --git a/src/virtualenv/seed/wheels/acquire.py b/src/virtualenv/seed/wheels/acquire.py
index 3744026..d8e8d1e 100644
--- a/src/virtualenv/seed/wheels/acquire.py
+++ b/src/virtualenv/seed/wheels/acquire.py
@@ -1,13 +1,10 @@
"""Bootstrap"""
-from __future__ import absolute_import, unicode_literals
import logging
import sys
from operator import eq, lt
-
-from virtualenv.util.path import Path
-from virtualenv.util.six import ensure_str
-from virtualenv.util.subprocess import Popen, subprocess
+from pathlib import Path
+from subprocess import PIPE, CalledProcessError, Popen
from .bundle import from_bundle
from .periodic_update import add_wheel_to_update_log
@@ -43,7 +40,7 @@ def get_wheel(distribution, version, for_py_version, search_dirs, download, app_
def download_wheel(distribution, version_spec, for_py_version, search_dirs, app_data, to_folder, env):
- to_download = "{}{}".format(distribution, version_spec or "")
+ to_download = f"{distribution}{version_spec or ''}"
logging.debug("download wheel %s %s to %s", to_download, for_py_version, to_folder)
cmd = [
sys.executable,
@@ -63,15 +60,11 @@ def download_wheel(distribution, version_spec, for_py_version, search_dirs, app_
]
# pip has no interface in python - must be a new sub-process
env = pip_wheel_env_run(search_dirs, app_data, env)
- process = Popen(cmd, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
+ process = Popen(cmd, env=env, stdout=PIPE, stderr=PIPE, universal_newlines=True)
out, err = process.communicate()
if process.returncode != 0:
- kwargs = {"output": out}
- if sys.version_info < (3, 5):
- kwargs["output"] += err
- else:
- kwargs["stderr"] = err
- raise subprocess.CalledProcessError(process.returncode, cmd, **kwargs)
+ kwargs = {"output": out, "stderr": err}
+ raise CalledProcessError(process.returncode, cmd, **kwargs)
result = _find_downloaded_wheel(distribution, version_spec, for_py_version, to_folder, out)
logging.debug("downloaded wheel %s", result.name)
return result
@@ -83,7 +76,7 @@ def _find_downloaded_wheel(distribution, version_spec, for_py_version, to_folder
for marker in ("Saved ", "File was already downloaded "):
if line.startswith(marker):
return Wheel(Path(line[len(marker) :]).absolute())
- # if for some reason the output does not match fallback to latest version with that spec
+ # if for some reason the output does not match fallback to the latest version with that spec
return find_compatible_in_house(distribution, version_spec, for_py_version, to_folder)
@@ -104,18 +97,12 @@ def find_compatible_in_house(distribution, version_spec, for_py_version, in_fold
def pip_wheel_env_run(search_dirs, app_data, env):
- for_py_version = "{}.{}".format(*sys.version_info[0:2])
env = env.copy()
- env.update(
- {
- ensure_str(k): str(v) # python 2 requires these to be string only (non-unicode)
- for k, v in {"PIP_USE_WHEEL": "1", "PIP_USER": "0", "PIP_NO_INPUT": "1"}.items()
- },
- )
+ env.update({"PIP_USE_WHEEL": "1", "PIP_USER": "0", "PIP_NO_INPUT": "1"})
wheel = get_wheel(
distribution="pip",
version=None,
- for_py_version=for_py_version,
+ for_py_version=f"{sys.version_info.major}.{sys.version_info.minor}",
search_dirs=search_dirs,
download=False,
app_data=app_data,
@@ -124,5 +111,12 @@ def pip_wheel_env_run(search_dirs, app_data, env):
)
if wheel is None:
raise RuntimeError("could not find the embedded pip")
- env[str("PYTHONPATH")] = str(wheel.path)
+ env["PYTHONPATH"] = str(wheel.path)
return env
+
+
+__all__ = [
+ "get_wheel",
+ "download_wheel",
+ "pip_wheel_env_run",
+]
diff --git a/src/virtualenv/seed/wheels/bundle.py b/src/virtualenv/seed/wheels/bundle.py
index 39cd3d3..66bbe56 100644
--- a/src/virtualenv/seed/wheels/bundle.py
+++ b/src/virtualenv/seed/wheels/bundle.py
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, unicode_literals
-
from ..wheels.embed import get_embed_wheel
from .periodic_update import periodic_update
from .util import Version, Wheel, discover_wheels
@@ -15,9 +13,8 @@ def from_bundle(distribution, version, for_py_version, search_dirs, app_data, do
if version != Version.embed:
# 2. check if we have upgraded embed
if app_data.can_update:
- wheel = periodic_update(
- distribution, of_version, for_py_version, wheel, search_dirs, app_data, do_periodic_update, env
- )
+ per = do_periodic_update
+ wheel = periodic_update(distribution, of_version, for_py_version, wheel, search_dirs, app_data, per, env)
# 3. acquire from extra search dir
found_wheel = from_dir(distribution, of_version, for_py_version, search_dirs)
@@ -49,3 +46,9 @@ def from_dir(distribution, version, for_py_version, directories):
for wheel in discover_wheels(folder, distribution, version, for_py_version):
return wheel
return None
+
+
+__all__ = [
+ "load_embed_wheel",
+ "from_bundle",
+]
diff --git a/src/virtualenv/seed/wheels/embed/__init__.py b/src/virtualenv/seed/wheels/embed/__init__.py
index 3ae80b5..3062176 100644
--- a/src/virtualenv/seed/wheels/embed/__init__.py
+++ b/src/virtualenv/seed/wheels/embed/__init__.py
@@ -1,7 +1,6 @@
-from __future__ import absolute_import, unicode_literals
+from pathlib import Path
from virtualenv.seed.wheels.util import Wheel
-from virtualenv.util.path import Path
BUNDLE_FOLDER = Path(__file__).absolute().parent
BUNDLE_SUPPORT = {
@@ -54,9 +53,9 @@ def get_embed_wheel(distribution, for_py_version):
return Wheel.from_path(path)
-__all__ = (
+__all__ = [
"get_embed_wheel",
"BUNDLE_SUPPORT",
"MAX",
"BUNDLE_FOLDER",
-)
+]
diff --git a/src/virtualenv/seed/wheels/periodic_update.py b/src/virtualenv/seed/wheels/periodic_update.py
index 4f0336b..ec95bf5 100644
--- a/src/virtualenv/seed/wheels/periodic_update.py
+++ b/src/virtualenv/seed/wheels/periodic_update.py
@@ -2,40 +2,28 @@
Periodically update bundled versions.
"""
-from __future__ import absolute_import, unicode_literals
import json
import logging
import os
import ssl
-import subprocess
import sys
from datetime import datetime, timedelta
from itertools import groupby
+from pathlib import Path
from shutil import copy2
+from subprocess import PIPE, Popen
from textwrap import dedent
from threading import Thread
-
-from six.moves.urllib.error import URLError
-from six.moves.urllib.request import urlopen
+from urllib.error import URLError
+from urllib.request import urlopen
from virtualenv.app_data import AppDataDiskFolder
-from virtualenv.info import PY2
-from virtualenv.util.path import Path
-from virtualenv.util.subprocess import CREATE_NO_WINDOW, Popen
+from virtualenv.util.subprocess import CREATE_NO_WINDOW
from ..wheels.embed import BUNDLE_SUPPORT
from ..wheels.util import Wheel
-if PY2:
- # on Python 2 datetime.strptime throws the error below if the import did not trigger on main thread
- # Failed to import _strptime because the import lock is held by
- try:
- import _strptime # noqa
- except ImportError: # pragma: no cov
- pass # pragma: no cov
-
-
GRACE_PERIOD_CI = timedelta(hours=1) # prevent version switch in the middle of a CI run
GRACE_PERIOD_MINOR = timedelta(days=28)
UPDATE_PERIOD = timedelta(days=14)
@@ -106,7 +94,7 @@ def load_datetime(value):
return None if value is None else datetime.strptime(value, DATETIME_FMT)
-class NewVersion(object):
+class NewVersion:
def __init__(self, filename, found_date, release_date, source):
self.filename = filename
self.found_date = found_date
@@ -142,12 +130,9 @@ class NewVersion(object):
return False
def __repr__(self):
- return "{}(filename={}), found_date={}, release_date={}, source={})".format(
- self.__class__.__name__,
- self.filename,
- self.found_date,
- self.release_date,
- self.source,
+ return (
+ f"{self.__class__.__name__}(filename={self.filename}), found_date={self.found_date}, "
+ f"release_date={self.release_date}, source={self.source})"
)
def __eq__(self, other):
@@ -163,7 +148,7 @@ class NewVersion(object):
return Wheel(Path(self.filename))
-class UpdateLog(object):
+class UpdateLog:
def __init__(self, started, completed, versions, periodic):
self.started = started
self.completed = completed
@@ -224,8 +209,8 @@ def trigger_update(distribution, for_py_version, wheel, search_dirs, app_data, e
.strip()
.format(distribution, for_py_version, wheel_path, str(app_data), [str(p) for p in search_dirs], periodic),
]
- debug = env.get(str("_VIRTUALENV_PERIODIC_UPDATE_INLINE")) == str("1")
- pipe = None if debug else subprocess.PIPE
+ debug = env.get("_VIRTUALENV_PERIODIC_UPDATE_INLINE") == "1"
+ pipe = None if debug else PIPE
kwargs = {"stdout": pipe, "stderr": pipe}
if not debug and sys.platform == "win32":
kwargs["creationflags"] = CREATE_NO_WINDOW
@@ -233,7 +218,7 @@ def trigger_update(distribution, for_py_version, wheel, search_dirs, app_data, e
logging.info(
"triggered periodic upgrade of %s%s (for python %s) via background process having PID %d",
distribution,
- "" if wheel is None else "=={}".format(wheel.version),
+ "" if wheel is None else f"=={wheel.version}",
for_py_version,
process.pid,
)
@@ -286,7 +271,7 @@ def _run_do_update(app_data, distribution, embed_filename, for_py_version, perio
download_time = datetime.now()
dest = acquire.download_wheel(
distribution=distribution,
- version_spec=None if last_version is None else "<{}".format(last_version),
+ version_spec=None if last_version is None else f"<{last_version}",
for_py_version=for_py_version,
search_dirs=search_dirs,
app_data=app_data,
@@ -346,7 +331,7 @@ def _pypi_get_distribution_info_cached(distribution):
def _pypi_get_distribution_info(distribution):
- content, url = None, "https://pypi.org/pypi/{}/json".format(distribution)
+ content, url = None, f"https://pypi.org/pypi/{distribution}/json"
try:
for context in _request_context():
try:
@@ -401,20 +386,19 @@ def _run_manual_upgrade(app_data, distribution, for_py_version, env):
search_dirs=[],
periodic=False,
)
- msg = "upgraded %s for python %s in %s {}".format(
- "new entries found:\n%s" if versions else "no new versions found",
- )
+
args = [
distribution,
for_py_version,
datetime.now() - start,
]
if versions:
- args.append("\n".join("\t{}".format(v) for v in versions))
- logging.warning(msg, *args)
+ args.append("\n".join(f"\t{v}" for v in versions))
+ ver_update = "new entries found:\n%s" if versions else "no new versions found"
+ logging.warning(f"upgraded %s for python %s in %s {ver_update}", *args)
-__all__ = (
+__all__ = [
"add_wheel_to_update_log",
"periodic_update",
"do_update",
@@ -425,4 +409,4 @@ __all__ = (
"dump_datetime",
"trigger_update",
"release_date_for_wheel_path",
-)
+]
diff --git a/src/virtualenv/seed/wheels/util.py b/src/virtualenv/seed/wheels/util.py
index 1240eb2..f09d873 100644
--- a/src/virtualenv/seed/wheels/util.py
+++ b/src/virtualenv/seed/wheels/util.py
@@ -1,12 +1,8 @@
-from __future__ import absolute_import, unicode_literals
-
from operator import attrgetter
from zipfile import ZipFile
-from virtualenv.util.six import ensure_text
-
-class Wheel(object):
+class Wheel:
def __init__(self, path):
# https://www.python.org/dev/peps/pep-0427/#file-name-convention
# The wheel filename is {distribution}-{version}(-{build tag})?-{python tag}-{abi tag}-{platform tag}.whl
@@ -48,8 +44,8 @@ class Wheel(object):
return self.path.name
def support_py(self, py_version):
- name = "{}.dist-info/METADATA".format("-".join(self.path.stem.split("-")[0:2]))
- with ZipFile(ensure_text(str(self.path)), "r") as zip_file:
+ name = f"{'-'.join(self.path.stem.split('-')[0:2])}.dist-info/METADATA"
+ with ZipFile(str(self.path), "r") as zip_file:
metadata = zip_file.read(name).decode("utf-8")
marker = "Requires-Python:"
requires = next((i[len(marker) :] for i in metadata.splitlines() if i.startswith(marker)), None)
@@ -75,7 +71,7 @@ class Wheel(object):
return True
def __repr__(self):
- return "{}({})".format(self.__class__.__name__, self.path)
+ return f"{self.__class__.__name__}({self.path})"
def __str__(self):
return str(self.path)
@@ -97,10 +93,7 @@ class Version:
bundle = "bundle"
embed = "embed"
#: custom version handlers
- non_version = (
- bundle,
- embed,
- )
+ non_version = (bundle, embed)
@staticmethod
def of_version(value):
@@ -108,9 +101,16 @@ class Version:
@staticmethod
def as_pip_req(distribution, version):
- return "{}{}".format(distribution, Version.as_version_spec(version))
+ return f"{distribution}{Version.as_version_spec(version)}"
@staticmethod
def as_version_spec(version):
of_version = Version.of_version(version)
- return "" if of_version is None else "=={}".format(of_version)
+ return "" if of_version is None else f"=={of_version}"
+
+
+__all__ = [
+ "discover_wheels",
+ "Version",
+ "Wheel",
+]
diff --git a/src/virtualenv/util/__init__.py b/src/virtualenv/util/__init__.py
index 32d0292..e69de29 100644
--- a/src/virtualenv/util/__init__.py
+++ b/src/virtualenv/util/__init__.py
@@ -1,11 +0,0 @@
-from __future__ import absolute_import, unicode_literals
-
-import sys
-
-if sys.version_info[0] == 3:
- import configparser as ConfigParser
-else:
- import ConfigParser
-
-
-__all__ = ("ConfigParser",)
diff --git a/src/virtualenv/util/error.py b/src/virtualenv/util/error.py
index ac5aa50..945a25e 100644
--- a/src/virtualenv/util/error.py
+++ b/src/virtualenv/util/error.py
@@ -1,12 +1,11 @@
"""Errors"""
-from __future__ import absolute_import, unicode_literals
class ProcessCallFailed(RuntimeError):
"""Failed a process call"""
def __init__(self, code, out, err, cmd):
- super(ProcessCallFailed, self).__init__(code, out, err, cmd)
+ super().__init__(code, out, err, cmd)
self.code = code
self.out = out
self.err = err
diff --git a/src/virtualenv/util/lock.py b/src/virtualenv/util/lock.py
index 1cf968b..04c9f9c 100644
--- a/src/virtualenv/util/lock.py
+++ b/src/virtualenv/util/lock.py
@@ -1,16 +1,13 @@
"""holds locking functionality that works across processes"""
-from __future__ import absolute_import, unicode_literals
import logging
import os
from abc import ABCMeta, abstractmethod
from contextlib import contextmanager
+from pathlib import Path
from threading import Lock, RLock
from filelock import FileLock, Timeout
-from six import add_metaclass
-
-from virtualenv.util.path import Path
class _CountedFileLock(FileLock):
@@ -21,20 +18,20 @@ class _CountedFileLock(FileLock):
os.makedirs(parent)
except OSError:
pass
- super(_CountedFileLock, self).__init__(lock_file)
+ super().__init__(lock_file)
self.count = 0
self.thread_safe = RLock()
def acquire(self, timeout=None, poll_interval=0.05):
with self.thread_safe:
if self.count == 0:
- super(_CountedFileLock, self).acquire(timeout, poll_interval)
+ super().acquire(timeout, poll_interval)
self.count += 1
def release(self, force=False):
with self.thread_safe:
if self.count == 1:
- super(_CountedFileLock, self).release(force=force)
+ super().release(force=force)
self.count = max(self.count - 1, 0)
@@ -42,14 +39,13 @@ _lock_store = {}
_store_lock = Lock()
-@add_metaclass(ABCMeta)
-class PathLockBase(object):
+class PathLockBase(metaclass=ABCMeta):
def __init__(self, folder):
path = Path(folder)
self.path = path.resolve() if path.exists() else path
def __repr__(self):
- return "{}({})".format(self.__class__.__name__, self.path)
+ return f"{self.__class__.__name__}({self.path})"
def __div__(self, other):
return type(self)(self.path / other)
@@ -78,11 +74,11 @@ class PathLockBase(object):
class ReentrantFileLock(PathLockBase):
def __init__(self, folder):
- super(ReentrantFileLock, self).__init__(folder)
+ super().__init__(folder)
self._lock = None
def _create_lock(self, name=""):
- lock_file = str(self.path / "{}.lock".format(name))
+ lock_file = str(self.path / f"{name}.lock")
with _store_lock:
if lock_file not in _lock_store:
_lock_store[lock_file] = _CountedFileLock(lock_file)
@@ -144,7 +140,7 @@ class ReentrantFileLock(PathLockBase):
@contextmanager
def non_reentrant_lock_for_key(self, name):
- with _CountedFileLock(str(self.path / "{}.lock".format(name))):
+ with _CountedFileLock(str(self.path / f"{name}.lock")):
yield
@@ -164,8 +160,8 @@ class NoOpFileLock(PathLockBase):
yield
-__all__ = (
+__all__ = [
"NoOpFileLock",
"ReentrantFileLock",
"Timeout",
-)
+]
diff --git a/src/virtualenv/util/path/__init__.py b/src/virtualenv/util/path/__init__.py
index dc628de..39a8db7 100644
--- a/src/virtualenv/util/path/__init__.py
+++ b/src/virtualenv/util/path/__init__.py
@@ -1,18 +1,14 @@
-from __future__ import absolute_import, unicode_literals
-
-from ._pathlib import Path
from ._permission import make_exe, set_tree
from ._sync import copy, copytree, ensure_dir, safe_delete, symlink
from ._win import get_short_path_name
-__all__ = (
+__all__ = [
"ensure_dir",
"symlink",
"copy",
"copytree",
- "Path",
"make_exe",
"set_tree",
"safe_delete",
"get_short_path_name",
-)
+]
diff --git a/src/virtualenv/util/path/_pathlib/__init__.py b/src/virtualenv/util/path/_pathlib/__init__.py
deleted file mode 100644
index 746c8ae..0000000
--- a/src/virtualenv/util/path/_pathlib/__init__.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from __future__ import absolute_import, unicode_literals
-
-import sys
-
-import six
-
-if six.PY3:
- from pathlib import Path
-else:
- if sys.platform == "win32":
- # workaround for https://github.com/mcmtroffaes/pathlib2/issues/56
- from .via_os_path import Path
- else:
- from pathlib2 import Path
-
-
-__all__ = ("Path",)
diff --git a/src/virtualenv/util/path/_pathlib/via_os_path.py b/src/virtualenv/util/path/_pathlib/via_os_path.py
deleted file mode 100644
index c2b8a0d..0000000
--- a/src/virtualenv/util/path/_pathlib/via_os_path.py
+++ /dev/null
@@ -1,160 +0,0 @@
-from __future__ import absolute_import, unicode_literals
-
-import fnmatch
-import os
-import platform
-from contextlib import contextmanager
-
-from virtualenv.util.six import ensure_str, ensure_text
-
-IS_PYPY = platform.python_implementation() == "PyPy"
-
-
-class Path(object):
- def __init__(self, path=""):
- if isinstance(path, Path):
- _path = path._path
- else:
- _path = ensure_text(path)
- if IS_PYPY:
- _path = _path.encode("utf-8")
- self._path = _path
-
- def __repr__(self):
- return ensure_str("Path({})".format(ensure_text(self._path)))
-
- def __unicode__(self):
- return ensure_text(self._path)
-
- def __str__(self):
- return ensure_str(self._path)
-
- def __div__(self, other):
- if isinstance(other, Path):
- right = other._path
- else:
- right = ensure_text(other)
- if IS_PYPY:
- right = right.encode("utf-8")
- return Path(os.path.join(self._path, right))
-
- def __truediv__(self, other):
- return self.__div__(other)
-
- def __eq__(self, other):
- return self._path == (other._path if isinstance(other, Path) else None)
-
- def __ne__(self, other):
- return not (self == other)
-
- def __hash__(self):
- return hash(self._path)
-
- def as_posix(self):
- return str(self).replace(os.sep, "/")
-
- def exists(self):
- return os.path.exists(self._path)
-
- @property
- def parent(self):
- return Path(os.path.abspath(os.path.join(self._path, os.path.pardir)))
-
- def resolve(self):
- return Path(os.path.realpath(self._path))
-
- @property
- def name(self):
- return os.path.basename(self._path)
-
- @property
- def parts(self):
- return self._path.split(os.sep)
-
- def is_file(self):
- return os.path.isfile(self._path)
-
- def is_dir(self):
- return os.path.isdir(self._path)
-
- def mkdir(self, parents=True, exist_ok=True):
- try:
- os.makedirs(self._path)
- except OSError:
- if not exist_ok:
- raise
-
- def read_text(self, encoding="utf-8"):
- return self.read_bytes().decode(encoding)
-
- def read_bytes(self):
- with open(self._path, "rb") as file_handler:
- return file_handler.read()
-
- def write_bytes(self, content):
- with open(self._path, "wb") as file_handler:
- file_handler.write(content)
-
- def write_text(self, text, encoding="utf-8"):
- self.write_bytes(text.encode(encoding))
-
- def iterdir(self):
- for p in os.listdir(self._path):
- yield Path(os.path.join(self._path, p))
-
- @property
- def suffix(self):
- _, ext = os.path.splitext(self.name)
- return ext
-
- @property
- def stem(self):
- base, _ = os.path.splitext(self.name)
- return base
-
- @contextmanager
- def open(self, mode="r"):
- with open(self._path, mode) as file_handler:
- yield file_handler
-
- @property
- def parents(self):
- result = []
- parts = self.parts
- for i in range(len(parts) - 1):
- result.append(Path(os.sep.join(parts[0 : i + 1])))
- return result[::-1]
-
- def unlink(self):
- os.remove(self._path)
-
- def with_name(self, name):
- return self.parent / name
-
- def is_symlink(self):
- return os.path.islink(self._path)
-
- def relative_to(self, other):
- if not self._path.startswith(other._path):
- raise ValueError("{} does not start with {}".format(self._path, other._path))
- return Path(os.sep.join(self.parts[len(other.parts) :]))
-
- def stat(self):
- return os.stat(self._path)
-
- def chmod(self, mode):
- os.chmod(self._path, mode)
-
- def absolute(self):
- return Path(os.path.abspath(self._path))
-
- def rglob(self, pattern):
- """
- Rough emulation of the origin method. Just for searching fixture files.
- """
- for root, _dirs, files in os.walk(self._path):
- for filename in fnmatch.filter(files, pattern):
- yield Path(os.path.join(root, filename))
-
-
-__all__ = ("Path",)
diff --git a/src/virtualenv/util/path/_permission.py b/src/virtualenv/util/path/_permission.py
index 73bb6e8..ca92314 100644
--- a/src/virtualenv/util/path/_permission.py
+++ b/src/virtualenv/util/path/_permission.py
@@ -1,10 +1,6 @@
-from __future__ import absolute_import, unicode_literals
-
import os
from stat import S_IXGRP, S_IXOTH, S_IXUSR
-from virtualenv.util.six import ensure_text
-
def make_exe(filename):
original_mode = filename.stat().st_mode
@@ -21,7 +17,7 @@ def make_exe(filename):
def set_tree(folder, stat):
- for root, _, files in os.walk(ensure_text(str(folder))):
+ for root, _, files in os.walk(str(folder)):
for filename in files:
os.chmod(os.path.join(root, filename), stat)
diff --git a/src/virtualenv/util/path/_sync.py b/src/virtualenv/util/path/_sync.py
index 05f19d0..10c793d 100644
--- a/src/virtualenv/util/path/_sync.py
+++ b/src/virtualenv/util/path/_sync.py
@@ -1,33 +1,18 @@
-from __future__ import absolute_import, unicode_literals
-
import logging
import os
import shutil
from stat import S_IWUSR
-from six import PY2
-
-from virtualenv.info import IS_CPYTHON, IS_WIN
-from virtualenv.util.six import ensure_text
-
-if PY2 and IS_CPYTHON and IS_WIN: # CPython2 on Windows supports unicode paths if passed as unicode
-
- def norm(src):
- return ensure_text(str(src))
-
-else:
- norm = str
-
def ensure_dir(path):
if not path.exists():
- logging.debug("create folder %s", ensure_text(str(path)))
- os.makedirs(norm(path))
+ logging.debug("create folder %s", str(path))
+ os.makedirs(str(path))
def ensure_safe_to_do(src, dest):
if src == dest:
- raise ValueError("source and destination is the same {}".format(src))
+ raise ValueError(f"source and destination is the same {src}")
if not dest.exists():
return
if dest.is_dir() and not dest.is_symlink():
@@ -49,7 +34,7 @@ def copy(src, dest):
is_dir = src.is_dir()
method = copytree if is_dir else shutil.copy
logging.debug("copy %s", _Debug(src, dest))
- method(norm(src), norm(dest))
+ method(str(src), str(dest))
def copytree(src, dest):
@@ -71,27 +56,23 @@ def safe_delete(dest):
else:
raise
- shutil.rmtree(ensure_text(str(dest)), ignore_errors=True, onerror=onerror)
+ shutil.rmtree(str(dest), ignore_errors=True, onerror=onerror)
-class _Debug(object):
+class _Debug:
def __init__(self, src, dest):
self.src = src
self.dest = dest
def __str__(self):
- return "{}{} to {}".format(
- "directory " if self.src.is_dir() else "",
- ensure_text(str(self.src)),
- ensure_text(str(self.dest)),
- )
+ return f"{'directory ' if self.src.is_dir() else ''}{str(self.src)} to {str(self.dest)}"
-__all__ = (
+__all__ = [
"ensure_dir",
"symlink",
"copy",
"symlink",
"copytree",
"safe_delete",
-)
+]
diff --git a/src/virtualenv/util/path/_win.py b/src/virtualenv/util/path/_win.py
index 02e16d0..8dd81c9 100644
--- a/src/virtualenv/util/path/_win.py
+++ b/src/virtualenv/util/path/_win.py
@@ -17,3 +17,8 @@ def get_short_path_name(long_name):
return output_buf.value
else:
output_buf_size = needed
+
+
+__all__ = [
+ "get_short_path_name",
+]
diff --git a/src/virtualenv/util/six.py b/src/virtualenv/util/six.py
deleted file mode 100644
index 199cbed..0000000
--- a/src/virtualenv/util/six.py
+++ /dev/null
@@ -1,50 +0,0 @@
-"""Backward compatibility layer with older version of six.
-
-This is used to avoid virtualenv requiring a version of six newer than what
-the system may have.
-"""
-from __future__ import absolute_import
-
-from six import PY2, PY3, binary_type, text_type
-
-try:
- from six import ensure_text
-except ImportError:
-
- def ensure_text(s, encoding="utf-8", errors="strict"):
- """Coerce *s* to six.text_type.
- For Python 2:
- - `unicode` -> `unicode`
- - `str` -> `unicode`
- For Python 3:
- - `str` -> `str`
- - `bytes` -> decoded to `str`
- """
- if isinstance(s, binary_type):
- return s.decode(encoding, errors)
- elif isinstance(s, text_type):
- return s
- else:
- raise TypeError("not expecting type '%s'" % type(s))
-
-
-try:
- from six import ensure_str
-except ImportError:
-
- def ensure_str(s, encoding="utf-8", errors="strict"):
- """Coerce *s* to `str`.
- For Python 2:
- - `unicode` -> encoded to `str`
- - `str` -> `str`
- For Python 3:
- - `str` -> `str`
- - `bytes` -> decoded to `str`
- """
- if not isinstance(s, (text_type, binary_type)):
- raise TypeError("not expecting type '%s'" % type(s))
- if PY2 and isinstance(s, text_type):
- s = s.encode(encoding, errors)
- elif PY3 and isinstance(s, binary_type):
- s = s.decode(encoding, errors)
- return s
diff --git a/src/virtualenv/util/subprocess/__init__.py b/src/virtualenv/util/subprocess/__init__.py
index 9f6ffd7..bc6ec4d 100644
--- a/src/virtualenv/util/subprocess/__init__.py
+++ b/src/virtualenv/util/subprocess/__init__.py
@@ -1,24 +1,11 @@
-from __future__ import absolute_import, unicode_literals
-
import subprocess
-import sys
-
-import six
-
-if six.PY2 and sys.platform == "win32":
- from . import _win_subprocess
-
- Popen = _win_subprocess.Popen
-else:
- Popen = subprocess.Popen
-
CREATE_NO_WINDOW = 0x80000000
def run_cmd(cmd):
try:
- process = Popen(
+ process = subprocess.Popen(
cmd,
universal_newlines=True,
stdin=subprocess.PIPE,
@@ -30,14 +17,11 @@ def run_cmd(cmd):
except OSError as error:
code, out, err = error.errno, "", error.strerror
if code == 2 and "file" in err:
- # FileNotFoundError in Python >= 3.3
- err = str(error)
+ err = str(error) # FileNotFoundError in Python >= 3.3
return code, out, err
__all__ = (
- "subprocess",
- "Popen",
"run_cmd",
"CREATE_NO_WINDOW",
)
diff --git a/src/virtualenv/util/subprocess/_win_subprocess.py b/src/virtualenv/util/subprocess/_win_subprocess.py
deleted file mode 100644
index ce53197..0000000
--- a/src/virtualenv/util/subprocess/_win_subprocess.py
+++ /dev/null
@@ -1,176 +0,0 @@
-# flake8: noqa
-# fmt: off
-## issue: https://bugs.python.org/issue19264
-
-import ctypes
-import os
-import platform
-import subprocess
-from ctypes import Structure, WinError, byref, c_char_p, c_void_p, c_wchar, c_wchar_p, sizeof, windll
-from ctypes.wintypes import BOOL, BYTE, DWORD, HANDLE, LPCWSTR, LPVOID, LPWSTR, WORD
-
-import _subprocess
-
-##
-## Types
-##
-
-CREATE_UNICODE_ENVIRONMENT = 0x00000400
-LPCTSTR = c_char_p
-LPTSTR = c_wchar_p
-LPSECURITY_ATTRIBUTES = c_void_p
-LPBYTE = ctypes.POINTER(BYTE)
-
-class STARTUPINFOW(Structure):
- _fields_ = [
- ("cb", DWORD), ("lpReserved", LPWSTR),
- ("lpDesktop", LPWSTR), ("lpTitle", LPWSTR),
- ("dwX", DWORD), ("dwY", DWORD),
- ("dwXSize", DWORD), ("dwYSize", DWORD),
- ("dwXCountChars", DWORD), ("dwYCountChars", DWORD),
- ("dwFillAtrribute", DWORD), ("dwFlags", DWORD),
- ("wShowWindow", WORD), ("cbReserved2", WORD),
- ("lpReserved2", LPBYTE), ("hStdInput", HANDLE),
- ("hStdOutput", HANDLE), ("hStdError", HANDLE),
- ]
-
-LPSTARTUPINFOW = ctypes.POINTER(STARTUPINFOW)
-
-
-class PROCESS_INFORMATION(Structure):
- _fields_ = [
- ("hProcess", HANDLE), ("hThread", HANDLE),
- ("dwProcessId", DWORD), ("dwThreadId", DWORD),
- ]
-
-LPPROCESS_INFORMATION = ctypes.POINTER(PROCESS_INFORMATION)
-
-
-class DUMMY_HANDLE(ctypes.c_void_p):
-
- def __init__(self, *a, **kw):
- super(DUMMY_HANDLE, self).__init__(*a, **kw)
- self.closed = False
-
- def Close(self):
- if not self.closed:
- windll.kernel32.CloseHandle(self)
- self.closed = True
-
- def __int__(self):
- return self.value
-
-
-CreateProcessW = windll.kernel32.CreateProcessW
-CreateProcessW.argtypes = [
- LPCWSTR, LPWSTR, LPSECURITY_ATTRIBUTES,
- LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCWSTR,
- LPSTARTUPINFOW, LPPROCESS_INFORMATION,
-]
-CreateProcessW.restype = BOOL
-
-
-##
-## Patched functions/classes
-##
-
-def CreateProcess(
- executable, args, _p_attr, _t_attr,
- inherit_handles, creation_flags, env, cwd,
- startup_info,
-):
- """Create a process supporting unicode executable and args for win32
-
- Python implementation of CreateProcess using CreateProcessW for Win32
-
- """
-
- si = STARTUPINFOW(
- dwFlags=startup_info.dwFlags,
- wShowWindow=startup_info.wShowWindow,
- cb=sizeof(STARTUPINFOW),
- ## XXXvlab: not sure of the casting here to ints.
- hStdInput=startup_info.hStdInput if startup_info.hStdInput is None else int(startup_info.hStdInput),
- hStdOutput=startup_info.hStdOutput if startup_info.hStdOutput is None else int(startup_info.hStdOutput),
- hStdError=startup_info.hStdError if startup_info.hStdError is None else int(startup_info.hStdError),
- )
-
- wenv = None
- if env is not None:
- ## LPCWSTR seems to be c_wchar_p, so let's say CWSTR is c_wchar
- env = (
- unicode("").join([
- unicode("%s=%s\0") % (k, v)
- for k, v in env.items()
- ])
- ) + unicode("\0")
- wenv = (c_wchar * len(env))()
- wenv.value = env
-
- wcwd = None
- if cwd is not None:
- wcwd = unicode(cwd)
-
- pi = PROCESS_INFORMATION()
- creation_flags |= CREATE_UNICODE_ENVIRONMENT
-
- if CreateProcessW(
- executable, args, None, None,
- inherit_handles, creation_flags,
- wenv, wcwd, byref(si), byref(pi),
- ):
- return (
- DUMMY_HANDLE(pi.hProcess), DUMMY_HANDLE(pi.hThread),
- pi.dwProcessId, pi.dwThreadId,
- )
- raise WinError()
-
-
-class Popen(subprocess.Popen):
- """This superseeds Popen and corrects a bug in cPython 2.7 implem"""
-
- def _execute_child(
- self, args, executable, preexec_fn, close_fds,
- cwd, env, universal_newlines,
- startupinfo, creationflags, shell, to_close,
- p2cread, p2cwrite,
- c2pread, c2pwrite,
- errread, errwrite,
- ):
- """Code from part of _execute_child from Python 2.7 (9fbb65e)
-
- There are only 2 little changes concerning the construction of
- the the final string in shell mode: we preempt the creation of
- the command string when shell is True, because original function
- will try to encode unicode args which we want to avoid to be able to
- sending it as-is to ``CreateProcess``.
-
- """
- if startupinfo is None:
- startupinfo = subprocess.STARTUPINFO()
- if not isinstance(args, subprocess.types.StringTypes):
- args = [i if isinstance(i, bytes) else i.encode('utf-8') for i in args]
- args = subprocess.list2cmdline(args)
- if platform.python_implementation() == "CPython":
- args = args.decode('utf-8')
- startupinfo.dwFlags |= _subprocess.STARTF_USESHOWWINDOW
- startupinfo.wShowWindow = _subprocess.SW_HIDE
- env = os.environ if env is None else env
- comspec = env.get("COMSPEC", unicode("cmd.exe"))
- if (
- _subprocess.GetVersion() >= 0x80000000 or
- os.path.basename(comspec).lower() == "command.com"
- ):
- w9xpopen = self._find_w9xpopen()
- args = unicode('"%s" %s') % (w9xpopen, args)
- creationflags |= _subprocess.CREATE_NEW_CONSOLE
-
- super(Popen, self)._execute_child(
- args, executable,
- preexec_fn, close_fds, cwd, env, universal_newlines,
- startupinfo, creationflags, False, to_close, p2cread,
- p2cwrite, c2pread, c2pwrite, errread, errwrite,
- )
-
-_subprocess.CreateProcess = CreateProcess
-# fmt: on
diff --git a/src/virtualenv/util/zipapp.py b/src/virtualenv/util/zipapp.py
index 85d9294..e7578c4 100644
--- a/src/virtualenv/util/zipapp.py
+++ b/src/virtualenv/util/zipapp.py
@@ -1,11 +1,8 @@
-from __future__ import absolute_import, unicode_literals
-
import logging
import os
import zipfile
from virtualenv.info import IS_WIN, ROOT
-from virtualenv.util.six import ensure_text
def read(full_path):
@@ -21,7 +18,7 @@ def extract(full_path, dest):
with zipfile.ZipFile(ROOT, "r") as zip_file:
info = zip_file.getinfo(sub_file)
info.filename = dest.name
- zip_file.extract(info, ensure_text(str(dest.parent)))
+ zip_file.extract(info, str(dest.parent))
def _get_path_within_zip(full_path):
@@ -31,3 +28,9 @@ def _get_path_within_zip(full_path):
# paths are always UNIX separators, even on Windows, though __file__ still follows platform default
sub_file = sub_file.replace(os.sep, "/")
return sub_file
+
+
+__all__ = [
+ "read",
+ "extract",
+]