[pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci
This commit is contained in:
pre-commit-ci[bot] 2024-04-13 00:00:18 +00:00
parent 72ad6dc953
commit f4cd1ba0d6
813 changed files with 66015 additions and 58839 deletions

View file

@ -1,8 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (c) 2005-2010 ActiveState Software Inc.
# Copyright (c) 2013 Eddy Petrișor
"""Utilities for determining application-specific dirs.
See <http://github.com/ActiveState/appdirs> for details and usage.
@ -12,6 +10,7 @@ See <http://github.com/ActiveState/appdirs> for details and usage.
# http://support.microsoft.com/default.aspx?scid=kb;en-us;310294#XSLTH3194121123120121120120
# - Mac OS X: http://developer.apple.com/documentation/MacOSX/Conceptual/BPFileSystem/index.html
# - XDG spec for Un*x: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
from __future__ import annotations
__version_info__ = (1, 4, 3)
__version__ = '.'.join(map(str, __version_info__))
@ -28,11 +27,11 @@ if PY3:
if sys.platform.startswith('java'):
import platform
os_name = platform.java_ver()[3][0]
if os_name.startswith('Windows'): # "Windows XP", "Windows 7", etc.
if os_name.startswith('Windows'): # "Windows XP", "Windows 7", etc.
system = 'win32'
elif os_name.startswith('Mac'): # "Mac OS X", etc.
elif os_name.startswith('Mac'): # "Mac OS X", etc.
system = 'darwin'
else: # "Linux", "SunOS", "FreeBSD", etc.
else: # "Linux", "SunOS", "FreeBSD", etc.
# Setting this to "linux2" is not ideal, but only Windows or Mac
# are actually checked for and the rest of the module expects
# *sys.platform* style strings.
@ -41,7 +40,6 @@ else:
system = sys.platform
def user_data_dir(appname=None, appauthor=None, version=None, roaming=False):
r"""Return full path to the user-specific data dir for this application.
@ -74,10 +72,10 @@ def user_data_dir(appname=None, appauthor=None, version=None, roaming=False):
For Unix, we follow the XDG spec and support $XDG_DATA_HOME.
That means, by default "~/.local/share/<AppName>".
"""
if system == "win32":
if system == 'win32':
if appauthor is None:
appauthor = appname
const = roaming and "CSIDL_APPDATA" or "CSIDL_LOCAL_APPDATA"
const = roaming and 'CSIDL_APPDATA' or 'CSIDL_LOCAL_APPDATA'
path = os.path.normpath(_get_win_folder(const))
if appname:
if appauthor is not False:
@ -89,7 +87,7 @@ def user_data_dir(appname=None, appauthor=None, version=None, roaming=False):
if appname:
path = os.path.join(path, appname)
else:
path = os.getenv('XDG_DATA_HOME', os.path.expanduser("~/.local/share"))
path = os.getenv('XDG_DATA_HOME', os.path.expanduser('~/.local/share'))
if appname:
path = os.path.join(path, appname)
if appname and version:
@ -128,10 +126,10 @@ def site_data_dir(appname=None, appauthor=None, version=None, multipath=False):
WARNING: Do not use this on Windows. See the Vista-Fail note above for why.
"""
if system == "win32":
if system == 'win32':
if appauthor is None:
appauthor = appname
path = os.path.normpath(_get_win_folder("CSIDL_COMMON_APPDATA"))
path = os.path.normpath(_get_win_folder('CSIDL_COMMON_APPDATA'))
if appname:
if appauthor is not False:
path = os.path.join(path, appauthor, appname)
@ -144,8 +142,10 @@ def site_data_dir(appname=None, appauthor=None, version=None, multipath=False):
else:
# XDG default for $XDG_DATA_DIRS
# only first, if multipath is False
path = os.getenv('XDG_DATA_DIRS',
os.pathsep.join(['/usr/local/share', '/usr/share']))
path = os.getenv(
'XDG_DATA_DIRS',
os.pathsep.join(['/usr/local/share', '/usr/share']),
)
pathlist = [os.path.expanduser(x.rstrip(os.sep)) for x in path.split(os.pathsep)]
if appname:
if version:
@ -192,10 +192,10 @@ def user_config_dir(appname=None, appauthor=None, version=None, roaming=False):
For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME.
That means, by default "~/.config/<AppName>".
"""
if system in ["win32", "darwin"]:
if system in ['win32', 'darwin']:
path = user_data_dir(appname, appauthor, None, roaming)
else:
path = os.getenv('XDG_CONFIG_HOME', os.path.expanduser("~/.config"))
path = os.getenv('XDG_CONFIG_HOME', os.path.expanduser('~/.config'))
if appname:
path = os.path.join(path, appname)
if appname and version:
@ -233,7 +233,7 @@ def site_config_dir(appname=None, appauthor=None, version=None, multipath=False)
WARNING: Do not use this on Windows. See the Vista-Fail note above for why.
"""
if system in ["win32", "darwin"]:
if system in ['win32', 'darwin']:
path = site_data_dir(appname, appauthor)
if appname and version:
path = os.path.join(path, version)
@ -287,17 +287,17 @@ def user_cache_dir(appname=None, appauthor=None, version=None, opinion=True):
OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value.
This can be disabled with the `opinion=False` option.
"""
if system == "win32":
if system == 'win32':
if appauthor is None:
appauthor = appname
path = os.path.normpath(_get_win_folder("CSIDL_LOCAL_APPDATA"))
path = os.path.normpath(_get_win_folder('CSIDL_LOCAL_APPDATA'))
if appname:
if appauthor is not False:
path = os.path.join(path, appauthor, appname)
else:
path = os.path.join(path, appname)
if opinion:
path = os.path.join(path, "Cache")
path = os.path.join(path, 'Cache')
elif system == 'darwin':
path = os.path.expanduser('~/Library/Caches')
if appname:
@ -342,10 +342,10 @@ def user_state_dir(appname=None, appauthor=None, version=None, roaming=False):
That means, by default "~/.local/state/<AppName>".
"""
if system in ["win32", "darwin"]:
if system in ['win32', 'darwin']:
path = user_data_dir(appname, appauthor, None, roaming)
else:
path = os.getenv('XDG_STATE_HOME', os.path.expanduser("~/.local/state"))
path = os.getenv('XDG_STATE_HOME', os.path.expanduser('~/.local/state'))
if appname:
path = os.path.join(path, appname)
if appname and version:
@ -385,29 +385,33 @@ def user_log_dir(appname=None, appauthor=None, version=None, opinion=True):
value for Windows and appends "log" to the user cache dir for Unix.
This can be disabled with the `opinion=False` option.
"""
if system == "darwin":
if system == 'darwin':
path = os.path.join(
os.path.expanduser('~/Library/Logs'),
appname)
elif system == "win32":
appname,
)
elif system == 'win32':
path = user_data_dir(appname, appauthor, version)
version = False
if opinion:
path = os.path.join(path, "Logs")
path = os.path.join(path, 'Logs')
else:
path = user_cache_dir(appname, appauthor, version)
version = False
if opinion:
path = os.path.join(path, "log")
path = os.path.join(path, 'log')
if appname and version:
path = os.path.join(path, version)
return path
class AppDirs(object):
class AppDirs:
"""Convenience wrapper for getting application dirs."""
def __init__(self, appname=None, appauthor=None, version=None,
roaming=False, multipath=False):
def __init__(
self, appname=None, appauthor=None, version=None,
roaming=False, multipath=False,
):
self.appname = appname
self.appauthor = appauthor
self.version = version
@ -416,38 +420,52 @@ class AppDirs(object):
@property
def user_data_dir(self):
return user_data_dir(self.appname, self.appauthor,
version=self.version, roaming=self.roaming)
return user_data_dir(
self.appname, self.appauthor,
version=self.version, roaming=self.roaming,
)
@property
def site_data_dir(self):
return site_data_dir(self.appname, self.appauthor,
version=self.version, multipath=self.multipath)
return site_data_dir(
self.appname, self.appauthor,
version=self.version, multipath=self.multipath,
)
@property
def user_config_dir(self):
return user_config_dir(self.appname, self.appauthor,
version=self.version, roaming=self.roaming)
return user_config_dir(
self.appname, self.appauthor,
version=self.version, roaming=self.roaming,
)
@property
def site_config_dir(self):
return site_config_dir(self.appname, self.appauthor,
version=self.version, multipath=self.multipath)
return site_config_dir(
self.appname, self.appauthor,
version=self.version, multipath=self.multipath,
)
@property
def user_cache_dir(self):
return user_cache_dir(self.appname, self.appauthor,
version=self.version)
return user_cache_dir(
self.appname, self.appauthor,
version=self.version,
)
@property
def user_state_dir(self):
return user_state_dir(self.appname, self.appauthor,
version=self.version)
return user_state_dir(
self.appname, self.appauthor,
version=self.version,
)
@property
def user_log_dir(self):
return user_log_dir(self.appname, self.appauthor,
version=self.version)
return user_log_dir(
self.appname, self.appauthor,
version=self.version,
)
#---- internal support stuff
@ -458,19 +476,19 @@ def _get_win_folder_from_registry(csidl_name):
names.
"""
if PY3:
import winreg as _winreg
import winreg as _winreg
else:
import _winreg
import _winreg
shell_folder_name = {
"CSIDL_APPDATA": "AppData",
"CSIDL_COMMON_APPDATA": "Common AppData",
"CSIDL_LOCAL_APPDATA": "Local AppData",
'CSIDL_APPDATA': 'AppData',
'CSIDL_COMMON_APPDATA': 'Common AppData',
'CSIDL_LOCAL_APPDATA': 'Local AppData',
}[csidl_name]
key = _winreg.OpenKey(
_winreg.HKEY_CURRENT_USER,
r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
r'Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders',
)
dir, type = _winreg.QueryValueEx(key, shell_folder_name)
return dir
@ -507,9 +525,9 @@ def _get_win_folder_with_ctypes(csidl_name):
import ctypes
csidl_const = {
"CSIDL_APPDATA": 26,
"CSIDL_COMMON_APPDATA": 35,
"CSIDL_LOCAL_APPDATA": 28,
'CSIDL_APPDATA': 26,
'CSIDL_COMMON_APPDATA': 35,
'CSIDL_LOCAL_APPDATA': 28,
}[csidl_name]
buf = ctypes.create_unicode_buffer(1024)
@ -529,6 +547,7 @@ def _get_win_folder_with_ctypes(csidl_name):
return buf.value
def _get_win_folder_with_jna(csidl_name):
import array
from com.sun import jna
@ -538,7 +557,7 @@ def _get_win_folder_with_jna(csidl_name):
buf = array.zeros('c', buf_size)
shell = win32.Shell32.INSTANCE
shell.SHGetFolderPath(None, getattr(win32.ShlObj, csidl_name), None, win32.ShlObj.SHGFP_TYPE_CURRENT, buf)
dir = jna.Native.toString(buf.tostring()).rstrip("\0")
dir = jna.Native.toString(buf.tostring()).rstrip('\0')
# Downgrade to short path name if have highbit chars. See
# <http://bugs.activestate.com/show_bug.cgi?id=85099>.
@ -551,11 +570,12 @@ def _get_win_folder_with_jna(csidl_name):
buf = array.zeros('c', buf_size)
kernel = win32.Kernel32.INSTANCE
if kernel.GetShortPathName(dir, buf, buf_size):
dir = jna.Native.toString(buf.tostring()).rstrip("\0")
dir = jna.Native.toString(buf.tostring()).rstrip('\0')
return dir
if system == "win32":
if system == 'win32':
try:
import win32com.shell
_get_win_folder = _get_win_folder_with_pywin32
@ -573,36 +593,38 @@ if system == "win32":
#---- self test code
if __name__ == "__main__":
appname = "MyApp"
appauthor = "MyCompany"
if __name__ == '__main__':
appname = 'MyApp'
appauthor = 'MyCompany'
props = ("user_data_dir",
"user_config_dir",
"user_cache_dir",
"user_state_dir",
"user_log_dir",
"site_data_dir",
"site_config_dir")
props = (
'user_data_dir',
'user_config_dir',
'user_cache_dir',
'user_state_dir',
'user_log_dir',
'site_data_dir',
'site_config_dir',
)
print("-- app dirs %s --" % __version__)
print('-- app dirs %s --' % __version__)
print("-- app dirs (with optional 'version')")
dirs = AppDirs(appname, appauthor, version="1.0")
dirs = AppDirs(appname, appauthor, version='1.0')
for prop in props:
print("%s: %s" % (prop, getattr(dirs, prop)))
print('{}: {}'.format(prop, getattr(dirs, prop)))
print("\n-- app dirs (without optional 'version')")
dirs = AppDirs(appname, appauthor)
for prop in props:
print("%s: %s" % (prop, getattr(dirs, prop)))
print('{}: {}'.format(prop, getattr(dirs, prop)))
print("\n-- app dirs (without optional 'appauthor')")
dirs = AppDirs(appname)
for prop in props:
print("%s: %s" % (prop, getattr(dirs, prop)))
print('{}: {}'.format(prop, getattr(dirs, prop)))
print("\n-- app dirs (with disabled 'appauthor')")
dirs = AppDirs(appname, appauthor=False)
for prop in props:
print("%s: %s" % (prop, getattr(dirs, prop)))
print('{}: {}'.format(prop, getattr(dirs, prop)))

View file

@ -1,27 +1,27 @@
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function
from __future__ import annotations
__all__ = [
"__title__",
"__summary__",
"__uri__",
"__version__",
"__author__",
"__email__",
"__license__",
"__copyright__",
'__title__',
'__summary__',
'__uri__',
'__version__',
'__author__',
'__email__',
'__license__',
'__copyright__',
]
__title__ = "packaging"
__summary__ = "Core utilities for Python packages"
__uri__ = "https://github.com/pypa/packaging"
__title__ = 'packaging'
__summary__ = 'Core utilities for Python packages'
__uri__ = 'https://github.com/pypa/packaging'
__version__ = "20.4"
__version__ = '20.4'
__author__ = "Donald Stufft and individual contributors"
__email__ = "donald@stufft.io"
__author__ = 'Donald Stufft and individual contributors'
__email__ = 'donald@stufft.io'
__license__ = "BSD-2-Clause or Apache-2.0"
__copyright__ = "Copyright 2014-2019 %s" % __author__
__license__ = 'BSD-2-Clause or Apache-2.0'
__copyright__ = 'Copyright 2014-2019 %s' % __author__

View file

@ -1,26 +1,24 @@
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function
from __future__ import annotations
from .__about__ import (
__author__,
__copyright__,
__email__,
__license__,
__summary__,
__title__,
__uri__,
__version__,
)
from .__about__ import __author__
from .__about__ import __copyright__
from .__about__ import __email__
from .__about__ import __license__
from .__about__ import __summary__
from .__about__ import __title__
from .__about__ import __uri__
from .__about__ import __version__
__all__ = [
"__title__",
"__summary__",
"__uri__",
"__version__",
"__author__",
"__email__",
"__license__",
"__copyright__",
'__title__',
'__summary__',
'__uri__',
'__version__',
'__author__',
'__email__',
'__license__',
'__copyright__',
]

View file

@ -1,7 +1,7 @@
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function
from __future__ import annotations
import sys
@ -35,4 +35,4 @@ def with_metaclass(meta, *bases):
# type: (Type[Any], str, Tuple[Any], Dict[Any, Any]) -> Any
return meta(name, bases, d)
return type.__new__(metaclass, "temporary_class", (), {})
return type.__new__(metaclass, 'temporary_class', (), {})

View file

@ -1,13 +1,13 @@
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function
from __future__ import annotations
class InfinityType(object):
class InfinityType:
def __repr__(self):
# type: () -> str
return "Infinity"
return 'Infinity'
def __hash__(self):
# type: () -> int
@ -45,10 +45,10 @@ class InfinityType(object):
Infinity = InfinityType()
class NegativeInfinityType(object):
class NegativeInfinityType:
def __repr__(self):
# type: () -> str
return "-Infinity"
return '-Infinity'
def __hash__(self):
# type: () -> int

View file

@ -25,8 +25,9 @@ In packaging, all static-typing related imports should be guarded as follows:
Ref: https://github.com/python/mypy/issues/3216
"""
from __future__ import annotations
__all__ = ["TYPE_CHECKING", "cast"]
__all__ = ['TYPE_CHECKING', 'cast']
# The TYPE_CHECKING constant defined by the typing module is False at runtime
# but True while type checking.

View file

@ -1,20 +1,27 @@
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function
from __future__ import annotations
import operator
import os
import platform
import sys
from pkg_resources.extern.pyparsing import ParseException, ParseResults, stringStart, stringEnd
from pkg_resources.extern.pyparsing import ZeroOrMore, Group, Forward, QuotedString
from pkg_resources.extern.pyparsing import Forward
from pkg_resources.extern.pyparsing import Group
from pkg_resources.extern.pyparsing import Literal as L # noqa
from pkg_resources.extern.pyparsing import ParseException
from pkg_resources.extern.pyparsing import ParseResults
from pkg_resources.extern.pyparsing import QuotedString
from pkg_resources.extern.pyparsing import stringEnd
from pkg_resources.extern.pyparsing import stringStart
from pkg_resources.extern.pyparsing import ZeroOrMore
from ._compat import string_types
from ._typing import TYPE_CHECKING
from .specifiers import Specifier, InvalidSpecifier
from .specifiers import InvalidSpecifier
from .specifiers import Specifier
if TYPE_CHECKING: # pragma: no cover
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
@ -23,11 +30,11 @@ if TYPE_CHECKING: # pragma: no cover
__all__ = [
"InvalidMarker",
"UndefinedComparison",
"UndefinedEnvironmentName",
"Marker",
"default_environment",
'InvalidMarker',
'UndefinedComparison',
'UndefinedEnvironmentName',
'Marker',
'default_environment',
]
@ -50,7 +57,7 @@ class UndefinedEnvironmentName(ValueError):
"""
class Node(object):
class Node:
def __init__(self, value):
# type: (Any) -> None
self.value = value
@ -61,7 +68,7 @@ class Node(object):
def __repr__(self):
# type: () -> str
return "<{0}({1!r})>".format(self.__class__.__name__, str(self))
return f'<{self.__class__.__name__}({str(self)!r})>'
def serialize(self):
# type: () -> str
@ -77,7 +84,7 @@ class Variable(Node):
class Value(Node):
def serialize(self):
# type: () -> str
return '"{0}"'.format(self)
return f'"{self}"'
class Op(Node):
@ -87,54 +94,54 @@ class Op(Node):
VARIABLE = (
L("implementation_version")
| L("platform_python_implementation")
| L("implementation_name")
| L("python_full_version")
| L("platform_release")
| L("platform_version")
| L("platform_machine")
| L("platform_system")
| L("python_version")
| L("sys_platform")
| L("os_name")
| L("os.name") # PEP-345
| L("sys.platform") # PEP-345
| L("platform.version") # PEP-345
| L("platform.machine") # PEP-345
| L("platform.python_implementation") # PEP-345
| L("python_implementation") # undocumented setuptools legacy
| L("extra") # PEP-508
L('implementation_version') |
L('platform_python_implementation') |
L('implementation_name') |
L('python_full_version') |
L('platform_release') |
L('platform_version') |
L('platform_machine') |
L('platform_system') |
L('python_version') |
L('sys_platform') |
L('os_name') |
L('os.name') | # PEP-345
L('sys.platform') | # PEP-345
L('platform.version') | # PEP-345
L('platform.machine') | # PEP-345
L('platform.python_implementation') | # PEP-345
L('python_implementation') | # undocumented setuptools legacy
L('extra') # PEP-508
)
ALIASES = {
"os.name": "os_name",
"sys.platform": "sys_platform",
"platform.version": "platform_version",
"platform.machine": "platform_machine",
"platform.python_implementation": "platform_python_implementation",
"python_implementation": "platform_python_implementation",
'os.name': 'os_name',
'sys.platform': 'sys_platform',
'platform.version': 'platform_version',
'platform.machine': 'platform_machine',
'platform.python_implementation': 'platform_python_implementation',
'python_implementation': 'platform_python_implementation',
}
VARIABLE.setParseAction(lambda s, l, t: Variable(ALIASES.get(t[0], t[0])))
VERSION_CMP = (
L("===") | L("==") | L(">=") | L("<=") | L("!=") | L("~=") | L(">") | L("<")
L('===') | L('==') | L('>=') | L('<=') | L('!=') | L('~=') | L('>') | L('<')
)
MARKER_OP = VERSION_CMP | L("not in") | L("in")
MARKER_OP = VERSION_CMP | L('not in') | L('in')
MARKER_OP.setParseAction(lambda s, l, t: Op(t[0]))
MARKER_VALUE = QuotedString("'") | QuotedString('"')
MARKER_VALUE.setParseAction(lambda s, l, t: Value(t[0]))
BOOLOP = L("and") | L("or")
BOOLOP = L('and') | L('or')
MARKER_VAR = VARIABLE | MARKER_VALUE
MARKER_ITEM = Group(MARKER_VAR + MARKER_OP + MARKER_VAR)
MARKER_ITEM.setParseAction(lambda s, l, t: tuple(t[0]))
LPAREN = L("(").suppress()
RPAREN = L(")").suppress()
LPAREN = L('(').suppress()
RPAREN = L(')').suppress()
MARKER_EXPR = Forward()
MARKER_ATOM = MARKER_ITEM | Group(LPAREN + MARKER_EXPR + RPAREN)
@ -161,40 +168,40 @@ def _format_marker(marker, first=True):
# the rest of this function so that we don't get extraneous () on the
# outside.
if (
isinstance(marker, list)
and len(marker) == 1
and isinstance(marker[0], (list, tuple))
isinstance(marker, list) and
len(marker) == 1 and
isinstance(marker[0], (list, tuple))
):
return _format_marker(marker[0])
if isinstance(marker, list):
inner = (_format_marker(m, first=False) for m in marker)
if first:
return " ".join(inner)
return ' '.join(inner)
else:
return "(" + " ".join(inner) + ")"
return '(' + ' '.join(inner) + ')'
elif isinstance(marker, tuple):
return " ".join([m.serialize() for m in marker])
return ' '.join([m.serialize() for m in marker])
else:
return marker
_operators = {
"in": lambda lhs, rhs: lhs in rhs,
"not in": lambda lhs, rhs: lhs not in rhs,
"<": operator.lt,
"<=": operator.le,
"==": operator.eq,
"!=": operator.ne,
">=": operator.ge,
">": operator.gt,
'in': lambda lhs, rhs: lhs in rhs,
'not in': lambda lhs, rhs: lhs not in rhs,
'<': operator.lt,
'<=': operator.le,
'==': operator.eq,
'!=': operator.ne,
'>=': operator.ge,
'>': operator.gt,
} # type: Dict[str, Operator]
def _eval_op(lhs, op, rhs):
# type: (str, Op, str) -> bool
try:
spec = Specifier("".join([op.serialize(), rhs]))
spec = Specifier(''.join([op.serialize(), rhs]))
except InvalidSpecifier:
pass
else:
@ -203,13 +210,13 @@ def _eval_op(lhs, op, rhs):
oper = _operators.get(op.serialize()) # type: Optional[Operator]
if oper is None:
raise UndefinedComparison(
"Undefined {0!r} on {1!r} and {2!r}.".format(op, lhs, rhs)
f'Undefined {op!r} on {lhs!r} and {rhs!r}.',
)
return oper(lhs, rhs)
class Undefined(object):
class Undefined:
pass
@ -222,7 +229,7 @@ def _get_env(environment, name):
if isinstance(value, Undefined):
raise UndefinedEnvironmentName(
"{0!r} does not exist in evaluation environment.".format(name)
f'{name!r} does not exist in evaluation environment.',
)
return value
@ -249,8 +256,8 @@ def _evaluate_markers(markers, environment):
groups[-1].append(_eval_op(lhs_value, op, rhs_value))
else:
assert marker in ["and", "or"]
if marker == "or":
assert marker in ['and', 'or']
if marker == 'or':
groups.append([])
return any(all(item) for item in groups)
@ -258,48 +265,48 @@ def _evaluate_markers(markers, environment):
def format_full_version(info):
# type: (sys._version_info) -> str
version = "{0.major}.{0.minor}.{0.micro}".format(info)
version = '{0.major}.{0.minor}.{0.micro}'.format(info)
kind = info.releaselevel
if kind != "final":
if kind != 'final':
version += kind[0] + str(info.serial)
return version
def default_environment():
# type: () -> Dict[str, str]
if hasattr(sys, "implementation"):
if hasattr(sys, 'implementation'):
# Ignoring the `sys.implementation` reference for type checking due to
# mypy not liking that the attribute doesn't exist in Python 2.7 when
# run with the `--py27` flag.
iver = format_full_version(sys.implementation.version) # type: ignore
implementation_name = sys.implementation.name # type: ignore
else:
iver = "0"
implementation_name = ""
iver = '0'
implementation_name = ''
return {
"implementation_name": implementation_name,
"implementation_version": iver,
"os_name": os.name,
"platform_machine": platform.machine(),
"platform_release": platform.release(),
"platform_system": platform.system(),
"platform_version": platform.version(),
"python_full_version": platform.python_version(),
"platform_python_implementation": platform.python_implementation(),
"python_version": ".".join(platform.python_version_tuple()[:2]),
"sys_platform": sys.platform,
'implementation_name': implementation_name,
'implementation_version': iver,
'os_name': os.name,
'platform_machine': platform.machine(),
'platform_release': platform.release(),
'platform_system': platform.system(),
'platform_version': platform.version(),
'python_full_version': platform.python_version(),
'platform_python_implementation': platform.python_implementation(),
'python_version': '.'.join(platform.python_version_tuple()[:2]),
'sys_platform': sys.platform,
}
class Marker(object):
class Marker:
def __init__(self, marker):
# type: (str) -> None
try:
self._markers = _coerce_parse_result(MARKER.parseString(marker))
except ParseException as e:
err_str = "Invalid marker: {0!r}, parse error at {1!r}".format(
marker, marker[e.loc : e.loc + 8]
err_str = 'Invalid marker: {!r}, parse error at {!r}'.format(
marker, marker[e.loc: e.loc + 8],
)
raise InvalidMarker(err_str)
@ -309,7 +316,7 @@ class Marker(object):
def __repr__(self):
# type: () -> str
return "<Marker({0!r})>".format(str(self))
return f'<Marker({str(self)!r})>'
def evaluate(self, environment=None):
# type: (Optional[Dict[str, str]]) -> bool

View file

@ -1,19 +1,29 @@
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function
from __future__ import annotations
import string
import re
from pkg_resources.extern.pyparsing import stringStart, stringEnd, originalTextFor, ParseException
from pkg_resources.extern.pyparsing import ZeroOrMore, Word, Optional, Regex, Combine
from pkg_resources.extern.pyparsing import Literal as L # noqa
import string
from urllib import parse as urlparse
from pkg_resources.extern.pyparsing import Combine
from pkg_resources.extern.pyparsing import Literal as L # noqa
from pkg_resources.extern.pyparsing import Optional
from pkg_resources.extern.pyparsing import originalTextFor
from pkg_resources.extern.pyparsing import ParseException
from pkg_resources.extern.pyparsing import Regex
from pkg_resources.extern.pyparsing import stringEnd
from pkg_resources.extern.pyparsing import stringStart
from pkg_resources.extern.pyparsing import Word
from pkg_resources.extern.pyparsing import ZeroOrMore
from ._typing import TYPE_CHECKING
from .markers import MARKER_EXPR, Marker
from .specifiers import LegacySpecifier, Specifier, SpecifierSet
from .markers import Marker
from .markers import MARKER_EXPR
from .specifiers import LegacySpecifier
from .specifiers import Specifier
from .specifiers import SpecifierSet
if TYPE_CHECKING: # pragma: no cover
from typing import List
@ -27,43 +37,43 @@ class InvalidRequirement(ValueError):
ALPHANUM = Word(string.ascii_letters + string.digits)
LBRACKET = L("[").suppress()
RBRACKET = L("]").suppress()
LPAREN = L("(").suppress()
RPAREN = L(")").suppress()
COMMA = L(",").suppress()
SEMICOLON = L(";").suppress()
AT = L("@").suppress()
LBRACKET = L('[').suppress()
RBRACKET = L(']').suppress()
LPAREN = L('(').suppress()
RPAREN = L(')').suppress()
COMMA = L(',').suppress()
SEMICOLON = L(';').suppress()
AT = L('@').suppress()
PUNCTUATION = Word("-_.")
PUNCTUATION = Word('-_.')
IDENTIFIER_END = ALPHANUM | (ZeroOrMore(PUNCTUATION) + ALPHANUM)
IDENTIFIER = Combine(ALPHANUM + ZeroOrMore(IDENTIFIER_END))
NAME = IDENTIFIER("name")
NAME = IDENTIFIER('name')
EXTRA = IDENTIFIER
URI = Regex(r"[^ ]+")("url")
URI = Regex(r'[^ ]+')('url')
URL = AT + URI
EXTRAS_LIST = EXTRA + ZeroOrMore(COMMA + EXTRA)
EXTRAS = (LBRACKET + Optional(EXTRAS_LIST) + RBRACKET)("extras")
EXTRAS = (LBRACKET + Optional(EXTRAS_LIST) + RBRACKET)('extras')
VERSION_PEP440 = Regex(Specifier._regex_str, re.VERBOSE | re.IGNORECASE)
VERSION_LEGACY = Regex(LegacySpecifier._regex_str, re.VERBOSE | re.IGNORECASE)
VERSION_ONE = VERSION_PEP440 ^ VERSION_LEGACY
VERSION_MANY = Combine(
VERSION_ONE + ZeroOrMore(COMMA + VERSION_ONE), joinString=",", adjacent=False
)("_raw_spec")
_VERSION_SPEC = Optional(((LPAREN + VERSION_MANY + RPAREN) | VERSION_MANY))
_VERSION_SPEC.setParseAction(lambda s, l, t: t._raw_spec or "")
VERSION_ONE + ZeroOrMore(COMMA + VERSION_ONE), joinString=',', adjacent=False,
)('_raw_spec')
_VERSION_SPEC = Optional((LPAREN + VERSION_MANY + RPAREN) | VERSION_MANY)
_VERSION_SPEC.setParseAction(lambda s, l, t: t._raw_spec or '')
VERSION_SPEC = originalTextFor(_VERSION_SPEC)("specifier")
VERSION_SPEC = originalTextFor(_VERSION_SPEC)('specifier')
VERSION_SPEC.setParseAction(lambda s, l, t: t[1])
MARKER_EXPR = originalTextFor(MARKER_EXPR())("marker")
MARKER_EXPR = originalTextFor(MARKER_EXPR())('marker')
MARKER_EXPR.setParseAction(
lambda s, l, t: Marker(s[t._original_start : t._original_end])
lambda s, l, t: Marker(s[t._original_start: t._original_end]),
)
MARKER_SEPARATOR = SEMICOLON
MARKER = MARKER_SEPARATOR + MARKER_EXPR
@ -76,10 +86,10 @@ NAMED_REQUIREMENT = NAME + Optional(EXTRAS) + (URL_AND_MARKER | VERSION_AND_MARK
REQUIREMENT = stringStart + NAMED_REQUIREMENT + stringEnd
# pkg_resources.extern.pyparsing isn't thread safe during initialization, so we do it eagerly, see
# issue #104
REQUIREMENT.parseString("x[]")
REQUIREMENT.parseString('x[]')
class Requirement(object):
class Requirement:
"""Parse a requirement.
Parse a given requirement string into its parts, such as name, specifier,
@ -98,21 +108,21 @@ class Requirement(object):
req = REQUIREMENT.parseString(requirement_string)
except ParseException as e:
raise InvalidRequirement(
'Parse error at "{0!r}": {1}'.format(
requirement_string[e.loc : e.loc + 8], e.msg
)
'Parse error at "{!r}": {}'.format(
requirement_string[e.loc: e.loc + 8], e.msg,
),
)
self.name = req.name
if req.url:
parsed_url = urlparse.urlparse(req.url)
if parsed_url.scheme == "file":
if parsed_url.scheme == 'file':
if urlparse.urlunparse(parsed_url) != req.url:
raise InvalidRequirement("Invalid URL given")
raise InvalidRequirement('Invalid URL given')
elif not (parsed_url.scheme and parsed_url.netloc) or (
not parsed_url.scheme and not parsed_url.netloc
):
raise InvalidRequirement("Invalid URL: {0}".format(req.url))
raise InvalidRequirement(f'Invalid URL: {req.url}')
self.url = req.url
else:
self.url = None
@ -125,21 +135,21 @@ class Requirement(object):
parts = [self.name] # type: List[str]
if self.extras:
parts.append("[{0}]".format(",".join(sorted(self.extras))))
parts.append('[{}]'.format(','.join(sorted(self.extras))))
if self.specifier:
parts.append(str(self.specifier))
if self.url:
parts.append("@ {0}".format(self.url))
parts.append(f'@ {self.url}')
if self.marker:
parts.append(" ")
parts.append(' ')
if self.marker:
parts.append("; {0}".format(self.marker))
parts.append(f'; {self.marker}')
return "".join(parts)
return ''.join(parts)
def __repr__(self):
# type: () -> str
return "<Requirement({0!r})>".format(str(self))
return f'<Requirement({str(self)!r})>'

View file

@ -1,17 +1,20 @@
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function
from __future__ import annotations
import abc
import functools
import itertools
import re
from ._compat import string_types, with_metaclass
from ._compat import string_types
from ._compat import with_metaclass
from ._typing import TYPE_CHECKING
from .utils import canonicalize_version
from .version import Version, LegacyVersion, parse
from .version import LegacyVersion
from .version import parse
from .version import Version
if TYPE_CHECKING: # pragma: no cover
from typing import (
@ -105,15 +108,15 @@ class _IndividualSpecifier(BaseSpecifier):
_operators = {} # type: Dict[str, str]
def __init__(self, spec="", prereleases=None):
def __init__(self, spec='', prereleases=None):
# type: (str, Optional[bool]) -> None
match = self._regex.search(spec)
if not match:
raise InvalidSpecifier("Invalid specifier: '{0}'".format(spec))
raise InvalidSpecifier(f"Invalid specifier: '{spec}'")
self._spec = (
match.group("operator").strip(),
match.group("version").strip(),
match.group('operator').strip(),
match.group('version').strip(),
) # type: Tuple[str, str]
# Store whether or not this Specifier should accept prereleases
@ -122,16 +125,16 @@ class _IndividualSpecifier(BaseSpecifier):
def __repr__(self):
# type: () -> str
pre = (
", prereleases={0!r}".format(self.prereleases)
f', prereleases={self.prereleases!r}'
if self._prereleases is not None
else ""
else ''
)
return "<{0}({1!r}{2})>".format(self.__class__.__name__, str(self), pre)
return f'<{self.__class__.__name__}({str(self)!r}{pre})>'
def __str__(self):
# type: () -> str
return "{0}{1}".format(*self._spec)
return '{}{}'.format(*self._spec)
@property
def _canonical_spec(self):
@ -169,7 +172,7 @@ class _IndividualSpecifier(BaseSpecifier):
def _get_operator(self, op):
# type: (str) -> CallableOperator
operator_callable = getattr(
self, "_compare_{0}".format(self._operators[op])
self, f'_compare_{self._operators[op]}',
) # type: CallableOperator
return operator_callable
@ -231,7 +234,7 @@ class _IndividualSpecifier(BaseSpecifier):
yielded = False
found_prereleases = []
kw = {"prereleases": prereleases if prereleases is not None else True}
kw = {'prereleases': prereleases if prereleases is not None else True}
# Attempt to iterate over all the values in the iterable and if any of
# them match, yield them.
@ -274,15 +277,15 @@ class LegacySpecifier(_IndividualSpecifier):
)
"""
_regex = re.compile(r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE)
_regex = re.compile(r'^\s*' + _regex_str + r'\s*$', re.VERBOSE | re.IGNORECASE)
_operators = {
"==": "equal",
"!=": "not_equal",
"<=": "less_than_equal",
">=": "greater_than_equal",
"<": "less_than",
">": "greater_than",
'==': 'equal',
'!=': 'not_equal',
'<=': 'less_than_equal',
'>=': 'greater_than_equal',
'<': 'less_than',
'>': 'greater_than',
}
def _coerce_version(self, version):
@ -317,7 +320,7 @@ class LegacySpecifier(_IndividualSpecifier):
def _require_version_compare(
fn # type: (Callable[[Specifier, ParsedVersion, str], bool])
fn, # type: (Callable[[Specifier, ParsedVersion, str], bool])
):
# type: (...) -> Callable[[Specifier, ParsedVersion, str], bool]
@functools.wraps(fn)
@ -425,17 +428,17 @@ class Specifier(_IndividualSpecifier):
)
"""
_regex = re.compile(r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE)
_regex = re.compile(r'^\s*' + _regex_str + r'\s*$', re.VERBOSE | re.IGNORECASE)
_operators = {
"~=": "compatible",
"==": "equal",
"!=": "not_equal",
"<=": "less_than_equal",
">=": "greater_than_equal",
"<": "less_than",
">": "greater_than",
"===": "arbitrary",
'~=': 'compatible',
'==': 'equal',
'!=': 'not_equal',
'<=': 'less_than_equal',
'>=': 'greater_than_equal',
'<': 'less_than',
'>': 'greater_than',
'===': 'arbitrary',
}
@_require_version_compare
@ -451,20 +454,20 @@ class Specifier(_IndividualSpecifier):
# We want everything but the last item in the version, but we want to
# ignore post and dev releases and we want to treat the pre-release as
# it's own separate segment.
prefix = ".".join(
prefix = '.'.join(
list(
itertools.takewhile(
lambda x: (not x.startswith("post") and not x.startswith("dev")),
lambda x: (not x.startswith('post') and not x.startswith('dev')),
_version_split(spec),
)
)[:-1]
),
)[:-1],
)
# Add the prefix notation to the end of our string
prefix += ".*"
prefix += '.*'
return self._get_operator(">=")(prospective, spec) and self._get_operator("==")(
prospective, prefix
return self._get_operator('>=')(prospective, spec) and self._get_operator('==')(
prospective, prefix,
)
@_require_version_compare
@ -472,7 +475,7 @@ class Specifier(_IndividualSpecifier):
# type: (ParsedVersion, str) -> bool
# We need special logic to handle prefix matching
if spec.endswith(".*"):
if spec.endswith('.*'):
# In the case of prefix matching we want to ignore local segment.
prospective = Version(prospective.public)
# Split the spec out by dots, and pretend that there is an implicit
@ -492,7 +495,7 @@ class Specifier(_IndividualSpecifier):
# Pad out our two sides with zeros so that they both equal the same
# length.
padded_spec, padded_prospective = _pad_version(
split_spec, shortened_prospective
split_spec, shortened_prospective,
)
return padded_prospective == padded_spec
@ -608,10 +611,10 @@ class Specifier(_IndividualSpecifier):
# operators, and if they are if they are including an explicit
# prerelease.
operator, version = self._spec
if operator in ["==", ">=", "<=", "~=", "==="]:
if operator in ['==', '>=', '<=', '~=', '===']:
# The == specifier can include a trailing .*, if it does we
# want to remove before parsing.
if operator == "==" and version.endswith(".*"):
if operator == '==' and version.endswith('.*'):
version = version[:-2]
# Parse the version, and if it is a pre-release than this
@ -627,13 +630,13 @@ class Specifier(_IndividualSpecifier):
self._prereleases = value
_prefix_regex = re.compile(r"^([0-9]+)((?:a|b|c|rc)[0-9]+)$")
_prefix_regex = re.compile(r'^([0-9]+)((?:a|b|c|rc)[0-9]+)$')
def _version_split(version):
# type: (str) -> List[str]
result = [] # type: List[str]
for item in version.split("."):
for item in version.split('.'):
match = _prefix_regex.search(item)
if match:
result.extend(match.groups())
@ -651,23 +654,23 @@ def _pad_version(left, right):
right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right)))
# Get the rest of our versions
left_split.append(left[len(left_split[0]) :])
right_split.append(right[len(right_split[0]) :])
left_split.append(left[len(left_split[0]):])
right_split.append(right[len(right_split[0]):])
# Insert our padding
left_split.insert(1, ["0"] * max(0, len(right_split[0]) - len(left_split[0])))
right_split.insert(1, ["0"] * max(0, len(left_split[0]) - len(right_split[0])))
left_split.insert(1, ['0'] * max(0, len(right_split[0]) - len(left_split[0])))
right_split.insert(1, ['0'] * max(0, len(left_split[0]) - len(right_split[0])))
return (list(itertools.chain(*left_split)), list(itertools.chain(*right_split)))
class SpecifierSet(BaseSpecifier):
def __init__(self, specifiers="", prereleases=None):
def __init__(self, specifiers='', prereleases=None):
# type: (str, Optional[bool]) -> None
# Split on , to break each individual specifier into it's own item, and
# strip each item to remove leading/trailing whitespace.
split_specifiers = [s.strip() for s in specifiers.split(",") if s.strip()]
split_specifiers = [s.strip() for s in specifiers.split(',') if s.strip()]
# Parsed each individual specifier, attempting first to make it a
# Specifier and falling back to a LegacySpecifier.
@ -688,16 +691,16 @@ class SpecifierSet(BaseSpecifier):
def __repr__(self):
# type: () -> str
pre = (
", prereleases={0!r}".format(self.prereleases)
f', prereleases={self.prereleases!r}'
if self._prereleases is not None
else ""
else ''
)
return "<SpecifierSet({0!r}{1})>".format(str(self), pre)
return f'<SpecifierSet({str(self)!r}{pre})>'
def __str__(self):
# type: () -> str
return ",".join(sorted(str(s) for s in self._specs))
return ','.join(sorted(str(s) for s in self._specs))
def __hash__(self):
# type: () -> int
@ -721,8 +724,8 @@ class SpecifierSet(BaseSpecifier):
specifier._prereleases = self._prereleases
else:
raise ValueError(
"Cannot combine SpecifierSets with True and False prerelease "
"overrides."
'Cannot combine SpecifierSets with True and False prerelease '
'overrides.',
)
return specifier

View file

@ -1,8 +1,7 @@
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import
from __future__ import annotations
import distutils.util
@ -46,18 +45,18 @@ if TYPE_CHECKING: # pragma: no cover
logger = logging.getLogger(__name__)
INTERPRETER_SHORT_NAMES = {
"python": "py", # Generic.
"cpython": "cp",
"pypy": "pp",
"ironpython": "ip",
"jython": "jy",
'python': 'py', # Generic.
'cpython': 'cp',
'pypy': 'pp',
'ironpython': 'ip',
'jython': 'jy',
} # type: Dict[str, str]
_32_BIT_INTERPRETER = sys.maxsize <= 2 ** 32
class Tag(object):
class Tag:
"""
A representation of the tag triple for a wheel.
@ -65,7 +64,7 @@ class Tag(object):
is also supported.
"""
__slots__ = ["_interpreter", "_abi", "_platform"]
__slots__ = ['_interpreter', '_abi', '_platform']
def __init__(self, interpreter, abi, platform):
# type: (str, str, str) -> None
@ -94,9 +93,9 @@ class Tag(object):
return NotImplemented
return (
(self.platform == other.platform)
and (self.abi == other.abi)
and (self.interpreter == other.interpreter)
(self.platform == other.platform) and
(self.abi == other.abi) and
(self.interpreter == other.interpreter)
)
def __hash__(self):
@ -105,11 +104,11 @@ class Tag(object):
def __str__(self):
# type: () -> str
return "{}-{}-{}".format(self._interpreter, self._abi, self._platform)
return f'{self._interpreter}-{self._abi}-{self._platform}'
def __repr__(self):
# type: () -> str
return "<{self} @ {self_id}>".format(self=self, self_id=id(self))
return f'<{self} @ {id(self)}>'
def parse_tag(tag):
@ -121,10 +120,10 @@ def parse_tag(tag):
compressed tag set.
"""
tags = set()
interpreters, abis, platforms = tag.split("-")
for interpreter in interpreters.split("."):
for abi in abis.split("."):
for platform_ in platforms.split("."):
interpreters, abis, platforms = tag.split('-')
for interpreter in interpreters.split('.'):
for abi in abis.split('.'):
for platform_ in platforms.split('.'):
tags.add(Tag(interpreter, abi, platform_))
return frozenset(tags)
@ -136,13 +135,13 @@ def _warn_keyword_parameter(func_name, kwargs):
"""
if not kwargs:
return False
elif len(kwargs) > 1 or "warn" not in kwargs:
kwargs.pop("warn", None)
elif len(kwargs) > 1 or 'warn' not in kwargs:
kwargs.pop('warn', None)
arg = next(iter(kwargs.keys()))
raise TypeError(
"{}() got an unexpected keyword argument {!r}".format(func_name, arg)
f'{func_name}() got an unexpected keyword argument {arg!r}',
)
return kwargs["warn"]
return kwargs['warn']
def _get_config_var(name, warn=False):
@ -150,14 +149,14 @@ def _get_config_var(name, warn=False):
value = sysconfig.get_config_var(name)
if value is None and warn:
logger.debug(
"Config variable '%s' is unset, Python ABI tag may be incorrect", name
"Config variable '%s' is unset, Python ABI tag may be incorrect", name,
)
return value
def _normalize_string(string):
# type: (str) -> str
return string.replace(".", "_").replace("-", "_")
return string.replace('.', '_').replace('-', '_')
def _abi3_applies(python_version):
@ -175,33 +174,33 @@ def _cpython_abis(py_version, warn=False):
py_version = tuple(py_version) # To allow for version comparison.
abis = []
version = _version_nodot(py_version[:2])
debug = pymalloc = ucs4 = ""
with_debug = _get_config_var("Py_DEBUG", warn)
has_refcount = hasattr(sys, "gettotalrefcount")
debug = pymalloc = ucs4 = ''
with_debug = _get_config_var('Py_DEBUG', warn)
has_refcount = hasattr(sys, 'gettotalrefcount')
# Windows doesn't set Py_DEBUG, so checking for support of debug-compiled
# extension modules is the best option.
# https://github.com/pypa/pip/issues/3383#issuecomment-173267692
has_ext = "_d.pyd" in EXTENSION_SUFFIXES
has_ext = '_d.pyd' in EXTENSION_SUFFIXES
if with_debug or (with_debug is None and (has_refcount or has_ext)):
debug = "d"
debug = 'd'
if py_version < (3, 8):
with_pymalloc = _get_config_var("WITH_PYMALLOC", warn)
with_pymalloc = _get_config_var('WITH_PYMALLOC', warn)
if with_pymalloc or with_pymalloc is None:
pymalloc = "m"
pymalloc = 'm'
if py_version < (3, 3):
unicode_size = _get_config_var("Py_UNICODE_SIZE", warn)
unicode_size = _get_config_var('Py_UNICODE_SIZE', warn)
if unicode_size == 4 or (
unicode_size is None and sys.maxunicode == 0x10FFFF
):
ucs4 = "u"
ucs4 = 'u'
elif debug:
# Debug builds can also load "normal" extension modules.
# We can also assume no UCS-4 or pymalloc requirement.
abis.append("cp{version}".format(version=version))
abis.append(f'cp{version}')
abis.insert(
0,
"cp{version}{debug}{pymalloc}{ucs4}".format(
version=version, debug=debug, pymalloc=pymalloc, ucs4=ucs4
'cp{version}{debug}{pymalloc}{ucs4}'.format(
version=version, debug=debug, pymalloc=pymalloc, ucs4=ucs4,
),
)
return abis
@ -211,7 +210,7 @@ def cpython_tags(
python_version=None, # type: Optional[PythonVersion]
abis=None, # type: Optional[Iterable[str]]
platforms=None, # type: Optional[Iterable[str]]
**kwargs # type: bool
**kwargs, # type: bool
):
# type: (...) -> Iterator[Tag]
"""
@ -229,11 +228,11 @@ def cpython_tags(
If 'abi3' or 'none' are specified in 'abis' then they will be yielded at
their normal position and not at the beginning.
"""
warn = _warn_keyword_parameter("cpython_tags", kwargs)
warn = _warn_keyword_parameter('cpython_tags', kwargs)
if not python_version:
python_version = sys.version_info[:2]
interpreter = "cp{}".format(_version_nodot(python_version[:2]))
interpreter = f'cp{_version_nodot(python_version[:2])}'
if abis is None:
if len(python_version) > 1:
@ -242,7 +241,7 @@ def cpython_tags(
abis = []
abis = list(abis)
# 'abi3' and 'none' are explicitly handled later.
for explicit_abi in ("abi3", "none"):
for explicit_abi in ('abi3', 'none'):
try:
abis.remove(explicit_abi)
except ValueError:
@ -253,23 +252,21 @@ def cpython_tags(
for platform_ in platforms:
yield Tag(interpreter, abi, platform_)
if _abi3_applies(python_version):
for tag in (Tag(interpreter, "abi3", platform_) for platform_ in platforms):
yield tag
for tag in (Tag(interpreter, "none", platform_) for platform_ in platforms):
yield tag
yield from (Tag(interpreter, 'abi3', platform_) for platform_ in platforms)
yield from (Tag(interpreter, 'none', platform_) for platform_ in platforms)
if _abi3_applies(python_version):
for minor_version in range(python_version[1] - 1, 1, -1):
for platform_ in platforms:
interpreter = "cp{version}".format(
version=_version_nodot((python_version[0], minor_version))
interpreter = 'cp{version}'.format(
version=_version_nodot((python_version[0], minor_version)),
)
yield Tag(interpreter, "abi3", platform_)
yield Tag(interpreter, 'abi3', platform_)
def _generic_abi():
# type: () -> Iterator[str]
abi = sysconfig.get_config_var("SOABI")
abi = sysconfig.get_config_var('SOABI')
if abi:
yield _normalize_string(abi)
@ -278,7 +275,7 @@ def generic_tags(
interpreter=None, # type: Optional[str]
abis=None, # type: Optional[Iterable[str]]
platforms=None, # type: Optional[Iterable[str]]
**kwargs # type: bool
**kwargs, # type: bool
):
# type: (...) -> Iterator[Tag]
"""
@ -289,17 +286,17 @@ def generic_tags(
The "none" ABI will be added if it was not explicitly provided.
"""
warn = _warn_keyword_parameter("generic_tags", kwargs)
warn = _warn_keyword_parameter('generic_tags', kwargs)
if not interpreter:
interp_name = interpreter_name()
interp_version = interpreter_version(warn=warn)
interpreter = "".join([interp_name, interp_version])
interpreter = ''.join([interp_name, interp_version])
if abis is None:
abis = _generic_abi()
platforms = list(platforms or _platform_tags())
abis = list(abis)
if "none" not in abis:
abis.append("none")
if 'none' not in abis:
abis.append('none')
for abi in abis:
for platform_ in platforms:
yield Tag(interpreter, abi, platform_)
@ -314,11 +311,11 @@ def _py_interpreter_range(py_version):
all previous versions of that major version.
"""
if len(py_version) > 1:
yield "py{version}".format(version=_version_nodot(py_version[:2]))
yield "py{major}".format(major=py_version[0])
yield f'py{_version_nodot(py_version[:2])}'
yield f'py{py_version[0]}'
if len(py_version) > 1:
for minor in range(py_version[1] - 1, -1, -1):
yield "py{version}".format(version=_version_nodot((py_version[0], minor)))
yield f'py{_version_nodot((py_version[0], minor))}'
def compatible_tags(
@ -340,11 +337,11 @@ def compatible_tags(
platforms = list(platforms or _platform_tags())
for version in _py_interpreter_range(python_version):
for platform_ in platforms:
yield Tag(version, "none", platform_)
yield Tag(version, 'none', platform_)
if interpreter:
yield Tag(interpreter, "none", "any")
yield Tag(interpreter, 'none', 'any')
for version in _py_interpreter_range(python_version):
yield Tag(version, "none", "any")
yield Tag(version, 'none', 'any')
def _mac_arch(arch, is_32bit=_32_BIT_INTERPRETER):
@ -352,37 +349,37 @@ def _mac_arch(arch, is_32bit=_32_BIT_INTERPRETER):
if not is_32bit:
return arch
if arch.startswith("ppc"):
return "ppc"
if arch.startswith('ppc'):
return 'ppc'
return "i386"
return 'i386'
def _mac_binary_formats(version, cpu_arch):
# type: (MacVersion, str) -> List[str]
formats = [cpu_arch]
if cpu_arch == "x86_64":
if cpu_arch == 'x86_64':
if version < (10, 4):
return []
formats.extend(["intel", "fat64", "fat32"])
formats.extend(['intel', 'fat64', 'fat32'])
elif cpu_arch == "i386":
elif cpu_arch == 'i386':
if version < (10, 4):
return []
formats.extend(["intel", "fat32", "fat"])
formats.extend(['intel', 'fat32', 'fat'])
elif cpu_arch == "ppc64":
elif cpu_arch == 'ppc64':
# TODO: Need to care about 32-bit PPC for ppc64 through 10.2?
if version > (10, 5) or version < (10, 4):
return []
formats.append("fat64")
formats.append('fat64')
elif cpu_arch == "ppc":
elif cpu_arch == 'ppc':
if version > (10, 6):
return []
formats.extend(["fat32", "fat"])
formats.extend(['fat32', 'fat'])
formats.append("universal")
formats.append('universal')
return formats
@ -398,7 +395,7 @@ def mac_platforms(version=None, arch=None):
"""
version_str, _, cpu_arch = platform.mac_ver() # type: ignore
if version is None:
version = cast("MacVersion", tuple(map(int, version_str.split(".")[:2])))
version = cast('MacVersion', tuple(map(int, version_str.split('.')[:2])))
else:
version = version
if arch is None:
@ -409,7 +406,7 @@ def mac_platforms(version=None, arch=None):
compat_version = version[0], minor_version
binary_formats = _mac_binary_formats(compat_version, arch)
for binary_format in binary_formats:
yield "macosx_{major}_{minor}_{binary_format}".format(
yield 'macosx_{major}_{minor}_{binary_format}'.format(
major=compat_version[0],
minor=compat_version[1],
binary_format=binary_format,
@ -423,7 +420,7 @@ def _is_manylinux_compatible(name, glibc_version):
try:
import _manylinux # noqa
return bool(getattr(_manylinux, name + "_compatible"))
return bool(getattr(_manylinux, name + '_compatible'))
except (ImportError, AttributeError):
# Fall through to heuristic check below.
pass
@ -449,7 +446,7 @@ def _glibc_version_string_confstr():
try:
# os.confstr("CS_GNU_LIBC_VERSION") returns a string like "glibc 2.17".
version_string = os.confstr( # type: ignore[attr-defined] # noqa: F821
"CS_GNU_LIBC_VERSION"
'CS_GNU_LIBC_VERSION',
)
assert version_string is not None
_, version = version_string.split() # type: Tuple[str, str]
@ -488,7 +485,7 @@ def _glibc_version_string_ctypes():
version_str = gnu_get_libc_version() # type: str
# py2 / py3 compatibility:
if not isinstance(version_str, str):
version_str = version_str.decode("ascii")
version_str = version_str.decode('ascii')
return version_str
@ -502,17 +499,17 @@ def _check_glibc_version(version_str, required_major, minimum_minor):
# random junk that might come after the minor version -- this might happen
# in patched/forked versions of glibc (e.g. Linaro's version of glibc
# uses version strings like "2.20-2014.11"). See gh-3588.
m = re.match(r"(?P<major>[0-9]+)\.(?P<minor>[0-9]+)", version_str)
m = re.match(r'(?P<major>[0-9]+)\.(?P<minor>[0-9]+)', version_str)
if not m:
warnings.warn(
"Expected glibc version with 2 components major.minor,"
" got: %s" % version_str,
'Expected glibc version with 2 components major.minor,'
' got: %s' % version_str,
RuntimeWarning,
)
return False
return (
int(m.group("major")) == required_major
and int(m.group("minor")) >= minimum_minor
int(m.group('major')) == required_major and
int(m.group('minor')) >= minimum_minor
)
@ -528,7 +525,7 @@ def _have_compatible_glibc(required_major, minimum_minor):
# identify the architecture of the running executable in some cases, so we
# determine it dynamically by reading the information from the running
# process. This only applies on Linux, which uses the ELF format.
class _ELFFileHeader(object):
class _ELFFileHeader:
# https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#File_header
class _InvalidELFFileHeader(ValueError):
"""
@ -554,28 +551,28 @@ class _ELFFileHeader(object):
# type: (str) -> int
try:
(result,) = struct.unpack(
fmt, file.read(struct.calcsize(fmt))
fmt, file.read(struct.calcsize(fmt)),
) # type: (int, )
except struct.error:
raise _ELFFileHeader._InvalidELFFileHeader()
return result
self.e_ident_magic = unpack(">I")
self.e_ident_magic = unpack('>I')
if self.e_ident_magic != self.ELF_MAGIC_NUMBER:
raise _ELFFileHeader._InvalidELFFileHeader()
self.e_ident_class = unpack("B")
self.e_ident_class = unpack('B')
if self.e_ident_class not in {self.ELFCLASS32, self.ELFCLASS64}:
raise _ELFFileHeader._InvalidELFFileHeader()
self.e_ident_data = unpack("B")
self.e_ident_data = unpack('B')
if self.e_ident_data not in {self.ELFDATA2LSB, self.ELFDATA2MSB}:
raise _ELFFileHeader._InvalidELFFileHeader()
self.e_ident_version = unpack("B")
self.e_ident_osabi = unpack("B")
self.e_ident_abiversion = unpack("B")
self.e_ident_version = unpack('B')
self.e_ident_osabi = unpack('B')
self.e_ident_abiversion = unpack('B')
self.e_ident_pad = file.read(7)
format_h = "<H" if self.e_ident_data == self.ELFDATA2LSB else ">H"
format_i = "<I" if self.e_ident_data == self.ELFDATA2LSB else ">I"
format_q = "<Q" if self.e_ident_data == self.ELFDATA2LSB else ">Q"
format_h = '<H' if self.e_ident_data == self.ELFDATA2LSB else '>H'
format_i = '<I' if self.e_ident_data == self.ELFDATA2LSB else '>I'
format_q = '<Q' if self.e_ident_data == self.ELFDATA2LSB else '>Q'
format_p = format_i if self.e_ident_class == self.ELFCLASS32 else format_q
self.e_type = unpack(format_h)
self.e_machine = unpack(format_h)
@ -595,9 +592,9 @@ class _ELFFileHeader(object):
def _get_elf_header():
# type: () -> Optional[_ELFFileHeader]
try:
with open(sys.executable, "rb") as f:
with open(sys.executable, 'rb') as f:
elf_header = _ELFFileHeader(f)
except (IOError, OSError, TypeError, _ELFFileHeader._InvalidELFFileHeader):
except (OSError, TypeError, _ELFFileHeader._InvalidELFFileHeader):
return None
return elf_header
@ -635,9 +632,9 @@ def _is_linux_i686():
def _have_compatible_manylinux_abi(arch):
# type: (str) -> bool
if arch == "armv7l":
if arch == 'armv7l':
return _is_linux_armhf()
if arch == "i686":
if arch == 'i686':
return _is_linux_i686()
return True
@ -646,32 +643,32 @@ def _linux_platforms(is_32bit=_32_BIT_INTERPRETER):
# type: (bool) -> Iterator[str]
linux = _normalize_string(distutils.util.get_platform())
if is_32bit:
if linux == "linux_x86_64":
linux = "linux_i686"
elif linux == "linux_aarch64":
linux = "linux_armv7l"
if linux == 'linux_x86_64':
linux = 'linux_i686'
elif linux == 'linux_aarch64':
linux = 'linux_armv7l'
manylinux_support = []
_, arch = linux.split("_", 1)
_, arch = linux.split('_', 1)
if _have_compatible_manylinux_abi(arch):
if arch in {"x86_64", "i686", "aarch64", "armv7l", "ppc64", "ppc64le", "s390x"}:
if arch in {'x86_64', 'i686', 'aarch64', 'armv7l', 'ppc64', 'ppc64le', 's390x'}:
manylinux_support.append(
("manylinux2014", (2, 17))
('manylinux2014', (2, 17)),
) # CentOS 7 w/ glibc 2.17 (PEP 599)
if arch in {"x86_64", "i686"}:
if arch in {'x86_64', 'i686'}:
manylinux_support.append(
("manylinux2010", (2, 12))
('manylinux2010', (2, 12)),
) # CentOS 6 w/ glibc 2.12 (PEP 571)
manylinux_support.append(
("manylinux1", (2, 5))
('manylinux1', (2, 5)),
) # CentOS 5 w/ glibc 2.5 (PEP 513)
manylinux_support_iter = iter(manylinux_support)
for name, glibc_version in manylinux_support_iter:
if _is_manylinux_compatible(name, glibc_version):
yield linux.replace("linux", name)
yield linux.replace('linux', name)
break
# Support for a later manylinux implies support for an earlier version.
for name, _ in manylinux_support_iter:
yield linux.replace("linux", name)
yield linux.replace('linux', name)
yield linux
@ -685,9 +682,9 @@ def _platform_tags():
"""
Provides the platform tags for this installation.
"""
if platform.system() == "Darwin":
if platform.system() == 'Darwin':
return mac_platforms()
elif platform.system() == "Linux":
elif platform.system() == 'Linux':
return _linux_platforms()
else:
return _generic_platforms()
@ -711,8 +708,8 @@ def interpreter_version(**kwargs):
"""
Returns the version of the running interpreter.
"""
warn = _warn_keyword_parameter("interpreter_version", kwargs)
version = _get_config_var("py_version_nodot", warn=warn)
warn = _warn_keyword_parameter('interpreter_version', kwargs)
version = _get_config_var('py_version_nodot', warn=warn)
if version:
version = str(version)
else:
@ -723,9 +720,9 @@ def interpreter_version(**kwargs):
def _version_nodot(version):
# type: (PythonVersion) -> str
if any(v >= 10 for v in version):
sep = "_"
sep = '_'
else:
sep = ""
sep = ''
return sep.join(map(str, version))
@ -737,15 +734,12 @@ def sys_tags(**kwargs):
The order of the sequence corresponds to priority order for the
interpreter, from most to least important.
"""
warn = _warn_keyword_parameter("sys_tags", kwargs)
warn = _warn_keyword_parameter('sys_tags', kwargs)
interp_name = interpreter_name()
if interp_name == "cp":
for tag in cpython_tags(warn=warn):
yield tag
if interp_name == 'cp':
yield from cpython_tags(warn=warn)
else:
for tag in generic_tags():
yield tag
yield from generic_tags()
for tag in compatible_tags():
yield tag
yield from compatible_tags()

View file

@ -1,26 +1,28 @@
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function
from __future__ import annotations
import re
from ._typing import TYPE_CHECKING, cast
from .version import InvalidVersion, Version
from ._typing import cast
from ._typing import TYPE_CHECKING
from .version import InvalidVersion
from .version import Version
if TYPE_CHECKING: # pragma: no cover
from typing import NewType, Union
NormalizedName = NewType("NormalizedName", str)
NormalizedName = NewType('NormalizedName', str)
_canonicalize_regex = re.compile(r"[-_.]+")
_canonicalize_regex = re.compile(r'[-_.]+')
def canonicalize_name(name):
# type: (str) -> NormalizedName
# This is taken from PEP 503.
value = _canonicalize_regex.sub("-", name).lower()
return cast("NormalizedName", value)
value = _canonicalize_regex.sub('-', name).lower()
return cast('NormalizedName', value)
def canonicalize_version(_version):
@ -40,26 +42,26 @@ def canonicalize_version(_version):
# Epoch
if version.epoch != 0:
parts.append("{0}!".format(version.epoch))
parts.append(f'{version.epoch}!')
# Release segment
# NB: This strips trailing '.0's to normalize
parts.append(re.sub(r"(\.0)+$", "", ".".join(str(x) for x in version.release)))
parts.append(re.sub(r'(\.0)+$', '', '.'.join(str(x) for x in version.release)))
# Pre-release
if version.pre is not None:
parts.append("".join(str(x) for x in version.pre))
parts.append(''.join(str(x) for x in version.pre))
# Post-release
if version.post is not None:
parts.append(".post{0}".format(version.post))
parts.append(f'.post{version.post}')
# Development release
if version.dev is not None:
parts.append(".dev{0}".format(version.dev))
parts.append(f'.dev{version.dev}')
# Local version segment
if version.local is not None:
parts.append("+{0}".format(version.local))
parts.append(f'+{version.local}')
return "".join(parts)
return ''.join(parts)

View file

@ -1,13 +1,14 @@
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
from __future__ import absolute_import, division, print_function
from __future__ import annotations
import collections
import itertools
import re
from ._structures import Infinity, NegativeInfinity
from ._structures import Infinity
from ._structures import NegativeInfinity
from ._typing import TYPE_CHECKING
if TYPE_CHECKING: # pragma: no cover
@ -30,18 +31,18 @@ if TYPE_CHECKING: # pragma: no cover
],
]
CmpKey = Tuple[
int, Tuple[int, ...], PrePostDevType, PrePostDevType, PrePostDevType, LocalType
int, Tuple[int, ...], PrePostDevType, PrePostDevType, PrePostDevType, LocalType,
]
LegacyCmpKey = Tuple[int, Tuple[str, ...]]
VersionComparisonMethod = Callable[
[Union[CmpKey, LegacyCmpKey], Union[CmpKey, LegacyCmpKey]], bool
[Union[CmpKey, LegacyCmpKey], Union[CmpKey, LegacyCmpKey]], bool,
]
__all__ = ["parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN"]
__all__ = ['parse', 'Version', 'LegacyVersion', 'InvalidVersion', 'VERSION_PATTERN']
_Version = collections.namedtuple(
"_Version", ["epoch", "release", "dev", "pre", "post", "local"]
'_Version', ['epoch', 'release', 'dev', 'pre', 'post', 'local'],
)
@ -64,7 +65,7 @@ class InvalidVersion(ValueError):
"""
class _BaseVersion(object):
class _BaseVersion:
_key = None # type: Union[CmpKey, LegacyCmpKey]
def __hash__(self):
@ -115,7 +116,7 @@ class LegacyVersion(_BaseVersion):
def __repr__(self):
# type: () -> str
return "<LegacyVersion({0})>".format(repr(str(self)))
return f'<LegacyVersion({repr(str(self))})>'
@property
def public(self):
@ -173,14 +174,14 @@ class LegacyVersion(_BaseVersion):
return False
_legacy_version_component_re = re.compile(r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE)
_legacy_version_component_re = re.compile(r'(\d+ | [a-z]+ | \.| -)', re.VERBOSE)
_legacy_version_replacement_map = {
"pre": "c",
"preview": "c",
"-": "final-",
"rc": "c",
"dev": "@",
'pre': 'c',
'preview': 'c',
'-': 'final-',
'rc': 'c',
'dev': '@',
}
@ -189,17 +190,17 @@ def _parse_version_parts(s):
for part in _legacy_version_component_re.split(s):
part = _legacy_version_replacement_map.get(part, part)
if not part or part == ".":
if not part or part == '.':
continue
if part[:1] in "0123456789":
if part[:1] in '0123456789':
# pad for numeric comparison
yield part.zfill(8)
else:
yield "*" + part
yield '*' + part
# ensure that alpha/beta/candidate are before final
yield "*final"
yield '*final'
def _legacy_cmpkey(version):
@ -215,14 +216,14 @@ def _legacy_cmpkey(version):
# it's adoption of the packaging library.
parts = [] # type: List[str]
for part in _parse_version_parts(version.lower()):
if part.startswith("*"):
if part.startswith('*'):
# remove "-" before a prerelease tag
if part < "*final":
while parts and parts[-1] == "*final-":
if part < '*final':
while parts and parts[-1] == '*final-':
parts.pop()
# remove trailing zeros from each series of numeric parts
while parts and parts[-1] == "00000000":
while parts and parts[-1] == '00000000':
parts.pop()
parts.append(part)
@ -266,7 +267,7 @@ VERSION_PATTERN = r"""
class Version(_BaseVersion):
_regex = re.compile(r"^\s*" + VERSION_PATTERN + r"\s*$", re.VERBOSE | re.IGNORECASE)
_regex = re.compile(r'^\s*' + VERSION_PATTERN + r'\s*$', re.VERBOSE | re.IGNORECASE)
def __init__(self, version):
# type: (str) -> None
@ -274,18 +275,18 @@ class Version(_BaseVersion):
# Validate the version and parse it into pieces
match = self._regex.search(version)
if not match:
raise InvalidVersion("Invalid version: '{0}'".format(version))
raise InvalidVersion(f"Invalid version: '{version}'")
# Store the parsed out pieces of the version
self._version = _Version(
epoch=int(match.group("epoch")) if match.group("epoch") else 0,
release=tuple(int(i) for i in match.group("release").split(".")),
pre=_parse_letter_version(match.group("pre_l"), match.group("pre_n")),
epoch=int(match.group('epoch')) if match.group('epoch') else 0,
release=tuple(int(i) for i in match.group('release').split('.')),
pre=_parse_letter_version(match.group('pre_l'), match.group('pre_n')),
post=_parse_letter_version(
match.group("post_l"), match.group("post_n1") or match.group("post_n2")
match.group('post_l'), match.group('post_n1') or match.group('post_n2'),
),
dev=_parse_letter_version(match.group("dev_l"), match.group("dev_n")),
local=_parse_local_version(match.group("local")),
dev=_parse_letter_version(match.group('dev_l'), match.group('dev_n')),
local=_parse_local_version(match.group('local')),
)
# Generate a key which will be used for sorting
@ -300,7 +301,7 @@ class Version(_BaseVersion):
def __repr__(self):
# type: () -> str
return "<Version({0})>".format(repr(str(self)))
return f'<Version({repr(str(self))})>'
def __str__(self):
# type: () -> str
@ -308,28 +309,28 @@ class Version(_BaseVersion):
# Epoch
if self.epoch != 0:
parts.append("{0}!".format(self.epoch))
parts.append(f'{self.epoch}!')
# Release segment
parts.append(".".join(str(x) for x in self.release))
parts.append('.'.join(str(x) for x in self.release))
# Pre-release
if self.pre is not None:
parts.append("".join(str(x) for x in self.pre))
parts.append(''.join(str(x) for x in self.pre))
# Post-release
if self.post is not None:
parts.append(".post{0}".format(self.post))
parts.append(f'.post{self.post}')
# Development release
if self.dev is not None:
parts.append(".dev{0}".format(self.dev))
parts.append(f'.dev{self.dev}')
# Local version segment
if self.local is not None:
parts.append("+{0}".format(self.local))
parts.append(f'+{self.local}')
return "".join(parts)
return ''.join(parts)
@property
def epoch(self):
@ -363,14 +364,14 @@ class Version(_BaseVersion):
def local(self):
# type: () -> Optional[str]
if self._version.local:
return ".".join(str(x) for x in self._version.local)
return '.'.join(str(x) for x in self._version.local)
else:
return None
@property
def public(self):
# type: () -> str
return str(self).split("+", 1)[0]
return str(self).split('+', 1)[0]
@property
def base_version(self):
@ -379,12 +380,12 @@ class Version(_BaseVersion):
# Epoch
if self.epoch != 0:
parts.append("{0}!".format(self.epoch))
parts.append(f'{self.epoch}!')
# Release segment
parts.append(".".join(str(x) for x in self.release))
parts.append('.'.join(str(x) for x in self.release))
return "".join(parts)
return ''.join(parts)
@property
def is_prerelease(self):
@ -435,27 +436,27 @@ def _parse_letter_version(
# We consider some words to be alternate spellings of other words and
# in those cases we want to normalize the spellings to our preferred
# spelling.
if letter == "alpha":
letter = "a"
elif letter == "beta":
letter = "b"
elif letter in ["c", "pre", "preview"]:
letter = "rc"
elif letter in ["rev", "r"]:
letter = "post"
if letter == 'alpha':
letter = 'a'
elif letter == 'beta':
letter = 'b'
elif letter in ['c', 'pre', 'preview']:
letter = 'rc'
elif letter in ['rev', 'r']:
letter = 'post'
return letter, int(number)
if not letter and number:
# We assume if we are given a number, but we are not given a letter
# then this is using the implicit post release syntax (e.g. 1.0-1)
letter = "post"
letter = 'post'
return letter, int(number)
return None
_local_version_separators = re.compile(r"[\._-]")
_local_version_separators = re.compile(r'[\._-]')
def _parse_local_version(local):
@ -487,7 +488,7 @@ def _cmpkey(
# re-reverse it back into the correct order and make it a tuple and use
# that for our sorting key.
_release = tuple(
reversed(list(itertools.dropwhile(lambda x: x == 0, reversed(release))))
reversed(list(itertools.dropwhile(lambda x: x == 0, reversed(release)))),
)
# We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
@ -529,7 +530,7 @@ def _cmpkey(
# - Shorter versions sort before longer versions when the prefixes
# match exactly
_local = tuple(
(i, "") if isinstance(i, int) else (NegativeInfinity, i) for i in local
(i, '') if isinstance(i, int) else (NegativeInfinity, i) for i in local
)
return epoch, _release, _pre, _post, _dev, _local