diff --git a/setup.cfg b/setup.cfg index b69ff82..9d615bf 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,20 +20,17 @@ classifier = Intended Audience :: Developers License :: OSI Approved :: MIT License Operating System :: OS Independent - Programming Language :: Python :: 2 - Programming Language :: Python :: 2.7 - Programming Language :: Python :: 3 - Programming Language :: Python :: 3.4 - Programming Language :: Python :: 3.5 - Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 Topic :: Software Development :: Build Tools Topic :: Software Development :: Libraries :: Python Modules Topic :: Utilities [options] zip_safe = true -python_requires = >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.* +python_requires = !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.* setup_requires = setuptools>=41.0 include_package_data = true package_data = @@ -42,10 +39,7 @@ package_data = install_requires = attrs cached-property - six packaging - backports.functools_lru_cache;python_version=="2.7" - pathlib2;python_version<"3.5" [options.packages.find] where = src diff --git a/src/pythonfinder/compat.py b/src/pythonfinder/compat.py index f1ac227..51fca95 100644 --- a/src/pythonfinder/compat.py +++ b/src/pythonfinder/compat.py @@ -1,21 +1,10 @@ # -*- coding=utf-8 -*- import sys -import six +from pathlib import Path -if sys.version_info[:2] <= (3, 4): - from pathlib2 import Path # type: ignore # noqa -else: - from pathlib import Path - -if six.PY3: - from builtins import TimeoutError - from functools import lru_cache -else: - from backports.functools_lru_cache import lru_cache # type: ignore # noqa - - class TimeoutError(OSError): - pass +from builtins import TimeoutError +from functools import lru_cache def getpreferredencoding(): @@ -24,10 +13,6 @@ def getpreferredencoding(): # Borrowed from Invoke # (see https://github.com/pyinvoke/invoke/blob/93af29d/invoke/runners.py#L881) _encoding = locale.getpreferredencoding(False) - if six.PY2 and not sys.platform == "win32": - _default_encoding = locale.getdefaultlocale()[1] - if _default_encoding is not None: - _encoding = _default_encoding return _encoding diff --git a/src/pythonfinder/models/__init__.py b/src/pythonfinder/models/__init__.py index 1a1f2db..e949709 100644 --- a/src/pythonfinder/models/__init__.py +++ b/src/pythonfinder/models/__init__.py @@ -5,8 +5,6 @@ import operator from itertools import chain -import six - from ..utils import KNOWN_EXTS, unnest from .path import SystemPath from .python import PythonVersion diff --git a/src/pythonfinder/models/mixins.py b/src/pythonfinder/models/mixins.py index 197a685..3faee14 100644 --- a/src/pythonfinder/models/mixins.py +++ b/src/pythonfinder/models/mixins.py @@ -6,7 +6,6 @@ from collections import defaultdict import attr -import six from ..compat import fs_str from ..environment import MYPY_RUNNING @@ -378,8 +377,7 @@ def find_python_version( return next(iter(r[0] for r in results if r is not None), None) -@six.add_metaclass(abc.ABCMeta) -class BaseFinder(object): +class BaseFinder(object, metaclass=abc.ABCMeta): def __init__(self): #: Maps executable paths to PathEntries from .path import PathEntry diff --git a/src/pythonfinder/models/path.py b/src/pythonfinder/models/path.py index 2297dda..555b590 100644 --- a/src/pythonfinder/models/path.py +++ b/src/pythonfinder/models/path.py @@ -1,5 +1,4 @@ # -*- coding=utf-8 -*- -from __future__ import absolute_import, print_function import errno import operator @@ -10,7 +9,6 @@ from itertools import chain import attr -import six from cached_property import cached_property from ..compat import Path, fs_str @@ -740,9 +738,9 @@ def _gen_children(self): pass_name = self.name != self.path.name pass_args = {"is_root": False, "only_python": self.only_python} if pass_name: - if self.name is not None and isinstance(self.name, six.string_types): + if self.name is not None and isinstance(self.name, str): pass_args["name"] = self.name # type: ignore - elif self.path is not None and isinstance(self.path.name, six.string_types): + elif self.path is not None and isinstance(self.path.name, str): pass_args["name"] = self.path.name # type: ignore if not self.is_dir: diff --git a/src/pythonfinder/models/python.py b/src/pythonfinder/models/python.py index 4a14ff7..3cabca4 100644 --- a/src/pythonfinder/models/python.py +++ b/src/pythonfinder/models/python.py @@ -1,5 +1,4 @@ # -*- coding=utf-8 -*- -from __future__ import absolute_import, print_function import logging import operator @@ -9,7 +8,6 @@ from collections import defaultdict import attr -import six from packaging.version import Version from ..compat import Path, lru_cache @@ -62,7 +60,7 @@ def overload(f): @attr.s(slots=True) -class PythonFinder(BaseFinder, BasePath): +class PythonFinder(BasePath, BaseFinder): root = attr.ib(default=None, validator=optional_instance_of(Path), type=Path) # should come before versions, because its value is used in versions's default initializer. #: Whether to ignore any paths which raise exceptions and are not actually python @@ -133,7 +131,7 @@ def get_version_order(self): def get_bin_dir(self, base): # type: (Union[Path, str]) -> Path - if isinstance(base, six.string_types): + if isinstance(base, str): base = Path(base) if os.name == "nt": return base @@ -374,7 +372,7 @@ def __getattribute__(self, key): elif self.comes_from: executable = self.comes_from.path.as_posix() if executable is not None: - if not isinstance(executable, six.string_types): + if not isinstance(executable, str): executable = executable.as_posix() instance_dict = self.parse_executable(executable) for k in instance_dict.keys(): @@ -614,7 +612,7 @@ def parse_executable(cls, path): result_version = None # type: Optional[str] if path is None: raise TypeError("Must pass a valid path to parse.") - if not isinstance(path, six.string_types): + if not isinstance(path, str): path = path.as_posix() # if not looks_like_python(path): # raise ValueError("Path %r does not look like a valid python path" % path) diff --git a/src/pythonfinder/pythonfinder.py b/src/pythonfinder/pythonfinder.py index 668cd72..3d466ba 100644 --- a/src/pythonfinder/pythonfinder.py +++ b/src/pythonfinder/pythonfinder.py @@ -1,12 +1,8 @@ # -*- coding=utf-8 -*- -from __future__ import absolute_import, print_function - import importlib import operator import os -import six - from . import environment from .compat import lru_cache from .exceptions import InvalidPythonVersion @@ -97,7 +93,7 @@ def reload_system_path(self): self._system_path = self._system_path.clear_caches() self._system_path = None pyfinder_path = importlib.import_module("pythonfinder.models.path") - six.moves.reload_module(pyfinder_path) + importlib.reload(pyfinder_path) self._system_path = self.create_system_path() def rehash(self): @@ -145,7 +141,7 @@ def parse_major( # type: (...) -> Dict[str, Union[int, str, bool, None]] from .models import PythonVersion - major_is_str = major and isinstance(major, six.string_types) + major_is_str = major and isinstance(major, str) is_num = ( major and major_is_str @@ -252,7 +248,7 @@ def find_python_version( } # type: Dict[str, Union[str, int, Any]] if ( - isinstance(major, six.string_types) + isinstance(major, str) and pre is None and minor is None and dev is None @@ -269,7 +265,7 @@ def find_python_version( _dev = version_dict.get("is_devrelease", dev) dev = bool(_dev) if _dev is not None else dev if "architecture" in version_dict and isinstance( - version_dict["architecture"], six.string_types + version_dict["architecture"], str ): arch = version_dict["architecture"] # type: ignore if os.name == "nt" and self.windows_finder is not None: diff --git a/src/pythonfinder/utils.py b/src/pythonfinder/utils.py index 091c125..4330e17 100644 --- a/src/pythonfinder/utils.py +++ b/src/pythonfinder/utils.py @@ -1,6 +1,4 @@ # -*- coding=utf-8 -*- -from __future__ import absolute_import, print_function - import io import itertools import os @@ -11,23 +9,13 @@ from threading import Timer import attr -import six from packaging.version import LegacyVersion, Version from .compat import Path, TimeoutError, lru_cache # noqa from .environment import MYPY_RUNNING, PYENV_ROOT, SUBPROCESS_TIMEOUT from .exceptions import InvalidPythonVersion -six.add_move( - six.MovedAttribute("Iterable", "collections", "collections.abc") -) # type: ignore # noqa -six.add_move( - six.MovedAttribute("Sequence", "collections", "collections.abc") -) # type: ignore # noqa -# fmt: off -from six.moves import Iterable # type: ignore # noqa # isort:skip -from six.moves import Sequence # type: ignore # noqa # isort:skip -# fmt: on +from collections.abc import Iterable, Sequence if MYPY_RUNNING: from typing import Any, Callable, Dict, Iterator, List, Optional, Set, Tuple, Union @@ -332,13 +320,13 @@ def filter_pythons(path): def unnest(item): # type: (Any) -> Iterable[Any] target = None # type: Optional[Iterable] - if isinstance(item, Iterable) and not isinstance(item, six.string_types): + if isinstance(item, Iterable) and not isinstance(item, str): item, target = itertools.tee(item, 2) else: target = item if getattr(target, "__iter__", None): for el in target: - if isinstance(el, Iterable) and not isinstance(el, six.string_types): + if isinstance(el, Iterable) and not isinstance(el, str): el, el_copy = itertools.tee(el, 2) for sub in unnest(el_copy): yield sub @@ -384,7 +372,7 @@ def split_version_and_name( name=None, # type: Optional[str] ): # type: (...) -> Tuple[Optional[Union[str, int]], Optional[Union[str, int]], Optional[Union[str, int]], Optional[str]] # noqa - if isinstance(major, six.string_types) and not minor and not patch: + if isinstance(major, str) and not minor and not patch: # Only proceed if this is in the format "x.y.z" or similar if major.isdigit() or (major.count(".") > 0 and major[0].isdigit()): version = major.split(".", 2) diff --git a/tests/conftest.py b/tests/conftest.py index 0859b27..8d650b3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,7 @@ # -*- coding=utf-8 -*- from __future__ import absolute_import, print_function +import importlib import os import shutil import subprocess @@ -10,7 +11,6 @@ import click import click.testing import pytest -import six import pythonfinder @@ -96,8 +96,8 @@ def no_pyenv_root_envvar(monkeypatch): m.delenv("PYENV_ROOT") if "ASDF_DATA_DIR" in os.environ: m.delenv("ASDF_DATA_DIR") - six.moves.reload_module(pythonfinder.environment) - six.moves.reload_module(pythonfinder.models.path) + importlib.reload(pythonfinder.environment) + importlib.reload(pythonfinder.models.path) m.setattr(pythonfinder.environment, "PYENV_INSTALLED", False) m.setattr(pythonfinder.environment, "ASDF_INSTALLED", False) m.setattr(pythonfinder.environment, "PYENV_ROOT", normalize_path("~/.pyenv")) diff --git a/tests/test_python.py b/tests/test_python.py index bbefedc..0442c67 100644 --- a/tests/test_python.py +++ b/tests/test_python.py @@ -2,11 +2,11 @@ from __future__ import absolute_import, print_function import functools +import importlib import os import sys import pytest -import six from packaging.version import Version import pythonfinder @@ -155,8 +155,8 @@ def test_shims_are_removed(monkeypatch, no_virtual_env, setup_pythons): with monkeypatch.context() as m: pyenv_dir = pythonfinder.utils.normalize_path("~/.pyenv") asdf_dir = pythonfinder.utils.normalize_path("~/.asdf") - six.moves.reload_module(pythonfinder.environment) - six.moves.reload_module(pythonfinder.models.path) + importlib.reload(pythonfinder.environment) + importlib.reload(pythonfinder.models.path) m.setattr( pythonfinder.environment, "SHIM_PATHS", diff --git a/tests/test_utils.py b/tests/test_utils.py index e020e4a..399b4d3 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -9,10 +9,7 @@ import pythonfinder.utils from pythonfinder import Finder -if sys.version_info[:2] < (3, 5): - from pathlib2 import Path -else: - from pathlib import Path +from pathlib import Path os.environ["ANSI_COLORS_DISABLED"] = "1" diff --git a/tests/testutils.py b/tests/testutils.py index b042596..a861244 100644 --- a/tests/testutils.py +++ b/tests/testutils.py @@ -12,12 +12,8 @@ from contextlib import contextmanager import click -import six -if sys.version_info[:2] < (3, 5): - from pathlib2 import Path -else: - from pathlib import Path +from pathlib import Path TRACKED_TEMPORARY_DIRECTORIES = [] @@ -64,8 +60,7 @@ def create_tracked_tempdir(*args, **kwargs): tempdir = tempfile.mkdtemp(*args, **kwargs) TRACKED_TEMPORARY_DIRECTORIES.append(tempdir) atexit.register(shutil.rmtree, tempdir) - if six.PY3: - warnings.simplefilter("ignore", ResourceWarning) + warnings.simplefilter("ignore", ResourceWarning) return tempdir @@ -114,7 +109,7 @@ def normalize_path(path): BUFSIZE = 500 buffer = create_unicode_buffer(BUFSIZE) get_long_path_name = windll.kernel32.GetLongPathNameW - get_long_path_name(six.ensure_text(path), buffer, BUFSIZE) + get_long_path_name(path.decode(), buffer, BUFSIZE) path = buffer.value return path