mirror of https://github.com/pypa/pip
Vendoring Updates for Jan 2020 (#7618)
This commit is contained in:
commit
bd02564af2
|
@ -0,0 +1 @@
|
|||
Upgrade CacheControl to 0.12.5
|
|
@ -0,0 +1 @@
|
|||
Upgrade certifi to 2019.9.11
|
|
@ -0,0 +1 @@
|
|||
Upgrade colorama to 0.4.1
|
|
@ -0,0 +1 @@
|
|||
Upgrade distlib to 0.2.9.post0
|
|
@ -0,0 +1 @@
|
|||
Upgrade ipaddress to 1.0.22
|
|
@ -0,0 +1 @@
|
|||
Upgrade pkg_resources (via setuptools) to 44.0.0
|
|
@ -0,0 +1 @@
|
|||
Upgrade pyparsing to 2.4.2
|
|
@ -0,0 +1 @@
|
|||
Upgrade six to 1.12.0
|
|
@ -0,0 +1 @@
|
|||
Upgrade urllib3 to 1.25.6
|
|
@ -4,7 +4,7 @@ Make it easy to import from cachecontrol without long namespaces.
|
|||
"""
|
||||
__author__ = "Eric Larson"
|
||||
__email__ = "eric@ionrock.org"
|
||||
__version__ = "0.12.5"
|
||||
__version__ = "0.12.6"
|
||||
|
||||
from .wrapper import CacheControl
|
||||
from .adapter import CacheControlAdapter
|
||||
|
|
|
@ -24,7 +24,7 @@ class CacheControlAdapter(HTTPAdapter):
|
|||
**kw
|
||||
):
|
||||
super(CacheControlAdapter, self).__init__(*args, **kw)
|
||||
self.cache = cache or DictCache()
|
||||
self.cache = DictCache() if cache is None else cache
|
||||
self.heuristic = heuristic
|
||||
self.cacheable_methods = cacheable_methods or ("GET",)
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ class CacheController(object):
|
|||
def __init__(
|
||||
self, cache=None, cache_etags=True, serializer=None, status_codes=None
|
||||
):
|
||||
self.cache = cache or DictCache()
|
||||
self.cache = DictCache() if cache is None else cache
|
||||
self.cache_etags = cache_etags
|
||||
self.serializer = serializer or Serializer()
|
||||
self.cacheable_status_codes = status_codes or (200, 203, 300, 301)
|
||||
|
@ -293,6 +293,15 @@ class CacheController(object):
|
|||
if no_store:
|
||||
return
|
||||
|
||||
# https://tools.ietf.org/html/rfc7234#section-4.1:
|
||||
# A Vary header field-value of "*" always fails to match.
|
||||
# Storing such a response leads to a deserialization warning
|
||||
# during cache lookup and is not allowed to ever be served,
|
||||
# so storing it can be avoided.
|
||||
if "*" in response_headers.get("vary", ""):
|
||||
logger.debug('Response header has "Vary: *"')
|
||||
return
|
||||
|
||||
# If we've been given an etag, then keep the response
|
||||
if self.cache_etags and "etag" in response_headers:
|
||||
logger.debug("Caching due to etag")
|
||||
|
|
|
@ -107,6 +107,8 @@ class Serializer(object):
|
|||
"""
|
||||
# Special case the '*' Vary value as it means we cannot actually
|
||||
# determine if the cached response is suitable for this request.
|
||||
# This case is also handled in the controller code when creating
|
||||
# a cache entry, but is left here for backwards compatibility.
|
||||
if "*" in cached.get("vary", {}):
|
||||
return
|
||||
|
||||
|
@ -179,7 +181,7 @@ class Serializer(object):
|
|||
|
||||
def _loads_v4(self, request, data):
|
||||
try:
|
||||
cached = msgpack.loads(data, encoding="utf-8")
|
||||
cached = msgpack.loads(data, raw=False)
|
||||
except ValueError:
|
||||
return
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ def CacheControl(
|
|||
cacheable_methods=None,
|
||||
):
|
||||
|
||||
cache = cache or DictCache()
|
||||
cache = DictCache() if cache is None else cache
|
||||
adapter_class = adapter_class or CacheControlAdapter
|
||||
adapter = adapter_class(
|
||||
cache,
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
from .core import where
|
||||
|
||||
__version__ = "2019.09.11"
|
||||
__version__ = "2019.11.28"
|
||||
|
|
|
@ -4556,3 +4556,47 @@ L5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB60PZ2Pierc+xYw5F9KBa
|
|||
LJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fqdBb9HxEG
|
||||
mpv0
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
# Issuer: CN=Entrust Root Certification Authority - G4 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2015 Entrust, Inc. - for authorized use only
|
||||
# Subject: CN=Entrust Root Certification Authority - G4 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2015 Entrust, Inc. - for authorized use only
|
||||
# Label: "Entrust Root Certification Authority - G4"
|
||||
# Serial: 289383649854506086828220374796556676440
|
||||
# MD5 Fingerprint: 89:53:f1:83:23:b7:7c:8e:05:f1:8c:71:38:4e:1f:88
|
||||
# SHA1 Fingerprint: 14:88:4e:86:26:37:b0:26:af:59:62:5c:40:77:ec:35:29:ba:96:01
|
||||
# SHA256 Fingerprint: db:35:17:d1:f6:73:2a:2d:5a:b9:7c:53:3e:c7:07:79:ee:32:70:a6:2f:b4:ac:42:38:37:24:60:e6:f0:1e:88
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAw
|
||||
gb4xCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQL
|
||||
Ex9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykg
|
||||
MjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAw
|
||||
BgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0
|
||||
MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYTAlVT
|
||||
MRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1
|
||||
c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJ
|
||||
bmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3Qg
|
||||
Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0MIICIjANBgkqhkiG9w0B
|
||||
AQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3DumSXbcr3DbVZwbPLqGgZ
|
||||
2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV3imz/f3E
|
||||
T+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j
|
||||
5pds8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAM
|
||||
C1rlLAHGVK/XqsEQe9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73T
|
||||
DtTUXm6Hnmo9RR3RXRv06QqsYJn7ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNX
|
||||
wbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5XxNMhIWNlUpEbsZmOeX7m640A
|
||||
2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV7rtNOzK+mndm
|
||||
nqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8
|
||||
dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwl
|
||||
N4y6mACXi0mWHv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNj
|
||||
c0kCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
|
||||
VR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9nMA0GCSqGSIb3DQEBCwUAA4ICAQAS
|
||||
5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4QjbRaZIxowLByQzTS
|
||||
Gwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht7LGr
|
||||
hFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/
|
||||
B7NTeLUKYvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uI
|
||||
AeV8KEsD+UmDfLJ/fOPtjqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbw
|
||||
H5Lk6rWS02FREAutp9lfx1/cH6NcjKF+m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+
|
||||
b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKWRGhXxNUzzxkvFMSUHHuk
|
||||
2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjAJOgc47Ol
|
||||
IQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk
|
||||
5F6G+TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuY
|
||||
n/PIjhs4ViFqUZPTkcpG2om3PVODLAgfi49T3f+sHw==
|
||||
-----END CERTIFICATE-----
|
||||
|
|
|
@ -3,4 +3,4 @@ from .initialise import init, deinit, reinit, colorama_text
|
|||
from .ansi import Fore, Back, Style, Cursor
|
||||
from .ansitowin32 import AnsiToWin32
|
||||
|
||||
__version__ = '0.4.1'
|
||||
__version__ = '0.4.3'
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#
|
||||
import logging
|
||||
|
||||
__version__ = '0.2.9.post0'
|
||||
__version__ = '0.3.0'
|
||||
|
||||
class DistlibException(Exception):
|
||||
pass
|
||||
|
|
|
@ -119,11 +119,9 @@ def _expand_globals(config):
|
|||
|
||||
#_expand_globals(_SCHEMES)
|
||||
|
||||
# FIXME don't rely on sys.version here, its format is an implementation detail
|
||||
# of CPython, use sys.version_info or sys.hexversion
|
||||
_PY_VERSION = sys.version.split()[0]
|
||||
_PY_VERSION_SHORT = sys.version[:3]
|
||||
_PY_VERSION_SHORT_NO_DOT = _PY_VERSION[0] + _PY_VERSION[2]
|
||||
_PY_VERSION = '%s.%s.%s' % sys.version_info[:3]
|
||||
_PY_VERSION_SHORT = '%s.%s' % sys.version_info[:2]
|
||||
_PY_VERSION_SHORT_NO_DOT = '%s%s' % sys.version_info[:2]
|
||||
_PREFIX = os.path.normpath(sys.prefix)
|
||||
_EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
|
||||
_CONFIG_VARS = None
|
||||
|
|
|
@ -567,7 +567,7 @@ class InstalledDistribution(BaseInstalledDistribution):
|
|||
p = os.path.join(path, 'top_level.txt')
|
||||
if os.path.exists(p):
|
||||
with open(p, 'rb') as f:
|
||||
data = f.read()
|
||||
data = f.read().decode('utf-8')
|
||||
self.modules = data.splitlines()
|
||||
|
||||
def __repr__(self):
|
||||
|
|
|
@ -304,18 +304,25 @@ class Locator(object):
|
|||
|
||||
def _get_digest(self, info):
|
||||
"""
|
||||
Get a digest from a dictionary by looking at keys of the form
|
||||
'algo_digest'.
|
||||
Get a digest from a dictionary by looking at a "digests" dictionary
|
||||
or keys of the form 'algo_digest'.
|
||||
|
||||
Returns a 2-tuple (algo, digest) if found, else None. Currently
|
||||
looks only for SHA256, then MD5.
|
||||
"""
|
||||
result = None
|
||||
for algo in ('sha256', 'md5'):
|
||||
key = '%s_digest' % algo
|
||||
if key in info:
|
||||
result = (algo, info[key])
|
||||
break
|
||||
if 'digests' in info:
|
||||
digests = info['digests']
|
||||
for algo in ('sha256', 'md5'):
|
||||
if algo in digests:
|
||||
result = (algo, digests[algo])
|
||||
break
|
||||
if not result:
|
||||
for algo in ('sha256', 'md5'):
|
||||
key = '%s_digest' % algo
|
||||
if key in info:
|
||||
result = (algo, info[key])
|
||||
break
|
||||
return result
|
||||
|
||||
def _update_version_data(self, result, info):
|
||||
|
|
|
@ -172,8 +172,16 @@ class ScriptMaker(object):
|
|||
|
||||
if sys.platform.startswith('java'): # pragma: no cover
|
||||
executable = self._fix_jython_executable(executable)
|
||||
# Normalise case for Windows
|
||||
executable = os.path.normcase(executable)
|
||||
|
||||
# Normalise case for Windows - COMMENTED OUT
|
||||
# executable = os.path.normcase(executable)
|
||||
# N.B. The normalising operation above has been commented out: See
|
||||
# issue #124. Although paths in Windows are generally case-insensitive,
|
||||
# they aren't always. For example, a path containing a ẞ (which is a
|
||||
# LATIN CAPITAL LETTER SHARP S - U+1E9E) is normcased to ß (which is a
|
||||
# LATIN SMALL LETTER SHARP S' - U+00DF). The two are not considered by
|
||||
# Windows as equivalent in path names.
|
||||
|
||||
# If the user didn't specify an executable, it may be necessary to
|
||||
# cater for executable paths with spaces (not uncommon on Windows)
|
||||
if enquote:
|
||||
|
@ -285,9 +293,10 @@ class ScriptMaker(object):
|
|||
if '' in self.variants:
|
||||
scriptnames.add(name)
|
||||
if 'X' in self.variants:
|
||||
scriptnames.add('%s%s' % (name, sys.version[0]))
|
||||
scriptnames.add('%s%s' % (name, sys.version_info[0]))
|
||||
if 'X.Y' in self.variants:
|
||||
scriptnames.add('%s-%s' % (name, sys.version[:3]))
|
||||
scriptnames.add('%s-%s.%s' % (name, sys.version_info[0],
|
||||
sys.version_info[1]))
|
||||
if options and options.get('gui', False):
|
||||
ext = 'pyw'
|
||||
else:
|
||||
|
@ -367,8 +376,12 @@ class ScriptMaker(object):
|
|||
# Issue 31: don't hardcode an absolute package name, but
|
||||
# determine it relative to the current package
|
||||
distlib_package = __name__.rsplit('.', 1)[0]
|
||||
result = finder(distlib_package).find(name).bytes
|
||||
return result
|
||||
resource = finder(distlib_package).find(name)
|
||||
if not resource:
|
||||
msg = ('Unable to find resource %s in package %s' % (name,
|
||||
distlib_package))
|
||||
raise ValueError(msg)
|
||||
return resource.bytes
|
||||
|
||||
# Public API follows
|
||||
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -703,7 +703,7 @@ class ExportEntry(object):
|
|||
|
||||
ENTRY_RE = re.compile(r'''(?P<name>(\w|[-.+])+)
|
||||
\s*=\s*(?P<callable>(\w+)([:\.]\w+)*)
|
||||
\s*(\[\s*(?P<flags>\w+(=\w+)?(,\s*\w+(=\w+)?)*)\s*\])?
|
||||
\s*(\[\s*(?P<flags>[\w-]+(=\w+)?(,\s*\w+(=\w+)?)*)\s*\])?
|
||||
''', re.VERBOSE)
|
||||
|
||||
def get_export_entry(specification):
|
||||
|
@ -1438,7 +1438,8 @@ if ssl:
|
|||
ca_certs=self.ca_certs)
|
||||
else: # pragma: no cover
|
||||
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
|
||||
context.options |= ssl.OP_NO_SSLv2
|
||||
if hasattr(ssl, 'OP_NO_SSLv2'):
|
||||
context.options |= ssl.OP_NO_SSLv2
|
||||
if self.cert_file:
|
||||
context.load_cert_chain(self.cert_file, self.key_file)
|
||||
kwargs = {}
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -684,7 +684,7 @@ class Wheel(object):
|
|||
if cache is None:
|
||||
# Use native string to avoid issues on 2.x: see Python #20140.
|
||||
base = os.path.join(get_cache_base(), str('dylib-cache'),
|
||||
sys.version[:3])
|
||||
'%s.%s' % sys.version_info[:2])
|
||||
cache = Cache(base)
|
||||
return cache
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ from __future__ import unicode_literals
|
|||
import itertools
|
||||
import struct
|
||||
|
||||
__version__ = '1.0.22'
|
||||
__version__ = '1.0.23'
|
||||
|
||||
# Compatibility functions
|
||||
_compat_int_types = (int,)
|
||||
|
@ -1103,7 +1103,8 @@ class _BaseNetwork(_IPAddressBase):
|
|||
try:
|
||||
# Always false if one is v4 and the other is v6.
|
||||
if a._version != b._version:
|
||||
raise TypeError("%s and %s are not of the same version" (a, b))
|
||||
raise TypeError(
|
||||
"%s and %s are not of the same version" % (a, b))
|
||||
return (b.network_address <= a.network_address and
|
||||
b.broadcast_address >= a.broadcast_address)
|
||||
except AttributeError:
|
||||
|
|
|
@ -88,8 +88,8 @@ __import__('pip._vendor.packaging.markers')
|
|||
__metaclass__ = type
|
||||
|
||||
|
||||
if (3, 0) < sys.version_info < (3, 4):
|
||||
raise RuntimeError("Python 3.4 or later is required")
|
||||
if (3, 0) < sys.version_info < (3, 5):
|
||||
raise RuntimeError("Python 3.5 or later is required")
|
||||
|
||||
if six.PY2:
|
||||
# Those builtin exceptions are only defined in Python 3
|
||||
|
@ -333,7 +333,7 @@ class UnknownExtra(ResolutionError):
|
|||
|
||||
_provider_factories = {}
|
||||
|
||||
PY_MAJOR = sys.version[:3]
|
||||
PY_MAJOR = '{}.{}'.format(*sys.version_info)
|
||||
EGG_DIST = 3
|
||||
BINARY_DIST = 2
|
||||
SOURCE_DIST = 1
|
||||
|
@ -3109,6 +3109,7 @@ class Requirement(packaging.requirements.Requirement):
|
|||
self.extras = tuple(map(safe_extra, self.extras))
|
||||
self.hashCmp = (
|
||||
self.key,
|
||||
self.url,
|
||||
self.specifier,
|
||||
frozenset(self.extras),
|
||||
str(self.marker) if self.marker else None,
|
||||
|
|
|
@ -95,8 +95,8 @@ classes inherit from. Use the docstrings for examples of how to:
|
|||
namespace class
|
||||
"""
|
||||
|
||||
__version__ = "2.4.2"
|
||||
__versionTime__ = "29 Jul 2019 02:58 UTC"
|
||||
__version__ = "2.4.6"
|
||||
__versionTime__ = "24 Dec 2019 04:27 UTC"
|
||||
__author__ = "Paul McGuire <ptmcg@users.sourceforge.net>"
|
||||
|
||||
import string
|
||||
|
@ -114,6 +114,7 @@ from datetime import datetime
|
|||
from operator import itemgetter
|
||||
import itertools
|
||||
from functools import wraps
|
||||
from contextlib import contextmanager
|
||||
|
||||
try:
|
||||
# Python 3
|
||||
|
@ -184,8 +185,15 @@ __diag__.warn_ungrouped_named_tokens_in_collection = False
|
|||
__diag__.warn_name_set_on_empty_Forward = False
|
||||
__diag__.warn_on_multiple_string_args_to_oneof = False
|
||||
__diag__.enable_debug_on_named_expressions = False
|
||||
__diag__._all_names = [nm for nm in vars(__diag__) if nm.startswith("enable_") or nm.startswith("warn_")]
|
||||
|
||||
def _enable_all_warnings():
|
||||
__diag__.warn_multiple_tokens_in_named_alternation = True
|
||||
__diag__.warn_ungrouped_named_tokens_in_collection = True
|
||||
__diag__.warn_name_set_on_empty_Forward = True
|
||||
__diag__.warn_on_multiple_string_args_to_oneof = True
|
||||
__diag__.enable_all_warnings = _enable_all_warnings
|
||||
|
||||
# ~ sys.stderr.write("testing pyparsing module, version %s, %s\n" % (__version__, __versionTime__))
|
||||
|
||||
__all__ = ['__version__', '__versionTime__', '__author__', '__compat__', '__diag__',
|
||||
'And', 'CaselessKeyword', 'CaselessLiteral', 'CharsNotIn', 'Combine', 'Dict', 'Each', 'Empty',
|
||||
|
@ -206,7 +214,7 @@ __all__ = ['__version__', '__versionTime__', '__author__', '__compat__', '__diag
|
|||
'stringStart', 'traceParseAction', 'unicodeString', 'upcaseTokens', 'withAttribute',
|
||||
'indentedBlock', 'originalTextFor', 'ungroup', 'infixNotation', 'locatedExpr', 'withClass',
|
||||
'CloseMatch', 'tokenMap', 'pyparsing_common', 'pyparsing_unicode', 'unicode_set',
|
||||
'conditionAsParseAction',
|
||||
'conditionAsParseAction', 're',
|
||||
]
|
||||
|
||||
system_version = tuple(sys.version_info)[:3]
|
||||
|
@ -2561,15 +2569,13 @@ class ParserElement(object):
|
|||
raise exc
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, ParserElement):
|
||||
if PY_3:
|
||||
self is other or super(ParserElement, self).__eq__(other)
|
||||
else:
|
||||
return self is other or vars(self) == vars(other)
|
||||
if self is other:
|
||||
return True
|
||||
elif isinstance(other, basestring):
|
||||
return self.matches(other)
|
||||
else:
|
||||
return super(ParserElement, self) == other
|
||||
elif isinstance(other, ParserElement):
|
||||
return vars(self) == vars(other)
|
||||
return False
|
||||
|
||||
def __ne__(self, other):
|
||||
return not (self == other)
|
||||
|
@ -3252,14 +3258,23 @@ class Regex(Token):
|
|||
If the given regex contains named groups (defined using ``(?P<name>...)``),
|
||||
these will be preserved as named parse results.
|
||||
|
||||
If instead of the Python stdlib re module you wish to use a different RE module
|
||||
(such as the `regex` module), you can replace it by either building your
|
||||
Regex object with a compiled RE that was compiled using regex:
|
||||
|
||||
Example::
|
||||
|
||||
realnum = Regex(r"[+-]?\d+\.\d*")
|
||||
date = Regex(r'(?P<year>\d{4})-(?P<month>\d\d?)-(?P<day>\d\d?)')
|
||||
# ref: https://stackoverflow.com/questions/267399/how-do-you-match-only-valid-roman-numerals-with-a-regular-expression
|
||||
roman = Regex(r"M{0,4}(CM|CD|D?{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})")
|
||||
|
||||
# use regex module instead of stdlib re module to construct a Regex using
|
||||
# a compiled regular expression
|
||||
import regex
|
||||
parser = pp.Regex(regex.compile(r'[0-9]'))
|
||||
|
||||
"""
|
||||
compiledREtype = type(re.compile("[A-Z]"))
|
||||
def __init__(self, pattern, flags=0, asGroupList=False, asMatch=False):
|
||||
"""The parameters ``pattern`` and ``flags`` are passed
|
||||
to the ``re.compile()`` function as-is. See the Python
|
||||
|
@ -3284,13 +3299,13 @@ class Regex(Token):
|
|||
SyntaxWarning, stacklevel=2)
|
||||
raise
|
||||
|
||||
elif isinstance(pattern, Regex.compiledREtype):
|
||||
elif hasattr(pattern, 'pattern') and hasattr(pattern, 'match'):
|
||||
self.re = pattern
|
||||
self.pattern = self.reString = str(pattern)
|
||||
self.pattern = self.reString = pattern.pattern
|
||||
self.flags = flags
|
||||
|
||||
else:
|
||||
raise ValueError("Regex may only be constructed with a string or a compiled RE object")
|
||||
raise TypeError("Regex may only be constructed with a string or a compiled RE object")
|
||||
|
||||
self.re_match = self.re.match
|
||||
|
||||
|
@ -3617,24 +3632,24 @@ class White(Token):
|
|||
'\n': '<LF>',
|
||||
'\r': '<CR>',
|
||||
'\f': '<FF>',
|
||||
'u\00A0': '<NBSP>',
|
||||
'u\1680': '<OGHAM_SPACE_MARK>',
|
||||
'u\180E': '<MONGOLIAN_VOWEL_SEPARATOR>',
|
||||
'u\2000': '<EN_QUAD>',
|
||||
'u\2001': '<EM_QUAD>',
|
||||
'u\2002': '<EN_SPACE>',
|
||||
'u\2003': '<EM_SPACE>',
|
||||
'u\2004': '<THREE-PER-EM_SPACE>',
|
||||
'u\2005': '<FOUR-PER-EM_SPACE>',
|
||||
'u\2006': '<SIX-PER-EM_SPACE>',
|
||||
'u\2007': '<FIGURE_SPACE>',
|
||||
'u\2008': '<PUNCTUATION_SPACE>',
|
||||
'u\2009': '<THIN_SPACE>',
|
||||
'u\200A': '<HAIR_SPACE>',
|
||||
'u\200B': '<ZERO_WIDTH_SPACE>',
|
||||
'u\202F': '<NNBSP>',
|
||||
'u\205F': '<MMSP>',
|
||||
'u\3000': '<IDEOGRAPHIC_SPACE>',
|
||||
u'\u00A0': '<NBSP>',
|
||||
u'\u1680': '<OGHAM_SPACE_MARK>',
|
||||
u'\u180E': '<MONGOLIAN_VOWEL_SEPARATOR>',
|
||||
u'\u2000': '<EN_QUAD>',
|
||||
u'\u2001': '<EM_QUAD>',
|
||||
u'\u2002': '<EN_SPACE>',
|
||||
u'\u2003': '<EM_SPACE>',
|
||||
u'\u2004': '<THREE-PER-EM_SPACE>',
|
||||
u'\u2005': '<FOUR-PER-EM_SPACE>',
|
||||
u'\u2006': '<SIX-PER-EM_SPACE>',
|
||||
u'\u2007': '<FIGURE_SPACE>',
|
||||
u'\u2008': '<PUNCTUATION_SPACE>',
|
||||
u'\u2009': '<THIN_SPACE>',
|
||||
u'\u200A': '<HAIR_SPACE>',
|
||||
u'\u200B': '<ZERO_WIDTH_SPACE>',
|
||||
u'\u202F': '<NNBSP>',
|
||||
u'\u205F': '<MMSP>',
|
||||
u'\u3000': '<IDEOGRAPHIC_SPACE>',
|
||||
}
|
||||
def __init__(self, ws=" \t\r\n", min=1, max=0, exact=0):
|
||||
super(White, self).__init__()
|
||||
|
@ -4566,6 +4581,7 @@ class PrecededBy(ParseElementEnhance):
|
|||
self.retreat = retreat
|
||||
self.errmsg = "not preceded by " + str(expr)
|
||||
self.skipWhitespace = False
|
||||
self.parseAction.append(lambda s, l, t: t.__delitem__(slice(None, None)))
|
||||
|
||||
def parseImpl(self, instring, loc=0, doActions=True):
|
||||
if self.exact:
|
||||
|
@ -4576,19 +4592,18 @@ class PrecededBy(ParseElementEnhance):
|
|||
else:
|
||||
# retreat specified a maximum lookbehind window, iterate
|
||||
test_expr = self.expr + StringEnd()
|
||||
instring_slice = instring[:loc]
|
||||
instring_slice = instring[max(0, loc - self.retreat):loc]
|
||||
last_expr = ParseException(instring, loc, self.errmsg)
|
||||
for offset in range(1, min(loc, self.retreat + 1)):
|
||||
for offset in range(1, min(loc, self.retreat + 1)+1):
|
||||
try:
|
||||
_, ret = test_expr._parse(instring_slice, loc - offset)
|
||||
# print('trying', offset, instring_slice, repr(instring_slice[loc - offset:]))
|
||||
_, ret = test_expr._parse(instring_slice, len(instring_slice) - offset)
|
||||
except ParseBaseException as pbe:
|
||||
last_expr = pbe
|
||||
else:
|
||||
break
|
||||
else:
|
||||
raise last_expr
|
||||
# return empty list of tokens, but preserve any defined results names
|
||||
del ret[:]
|
||||
return loc, ret
|
||||
|
||||
|
||||
|
@ -6051,7 +6066,7 @@ def infixNotation(baseExpr, opList, lpar=Suppress('('), rpar=Suppress(')')):
|
|||
matchExpr = _FB(lastExpr + lastExpr) + Group(lastExpr + OneOrMore(lastExpr))
|
||||
elif arity == 3:
|
||||
matchExpr = (_FB(lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr)
|
||||
+ Group(lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr))
|
||||
+ Group(lastExpr + OneOrMore(opExpr1 + lastExpr + opExpr2 + lastExpr)))
|
||||
else:
|
||||
raise ValueError("operator must be unary (1), binary (2), or ternary (3)")
|
||||
elif rightLeftAssoc == opAssoc.RIGHT:
|
||||
|
@ -6305,18 +6320,18 @@ def indentedBlock(blockStatementExpr, indentStack, indent=True):
|
|||
if curCol < indentStack[-1]:
|
||||
indentStack.pop()
|
||||
|
||||
NL = OneOrMore(LineEnd().setWhitespaceChars("\t ").suppress())
|
||||
NL = OneOrMore(LineEnd().setWhitespaceChars("\t ").suppress(), stopOn=StringEnd())
|
||||
INDENT = (Empty() + Empty().setParseAction(checkSubIndent)).setName('INDENT')
|
||||
PEER = Empty().setParseAction(checkPeerIndent).setName('')
|
||||
UNDENT = Empty().setParseAction(checkUnindent).setName('UNINDENT')
|
||||
if indent:
|
||||
smExpr = Group(Optional(NL)
|
||||
+ INDENT
|
||||
+ OneOrMore(PEER + Group(blockStatementExpr) + Optional(NL))
|
||||
+ OneOrMore(PEER + Group(blockStatementExpr) + Optional(NL), stopOn=StringEnd())
|
||||
+ UNDENT)
|
||||
else:
|
||||
smExpr = Group(Optional(NL)
|
||||
+ OneOrMore(PEER + Group(blockStatementExpr) + Optional(NL))
|
||||
+ OneOrMore(PEER + Group(blockStatementExpr) + Optional(NL), stopOn=StringEnd())
|
||||
+ UNDENT)
|
||||
smExpr.setFailAction(lambda a, b, c, d: reset_stack())
|
||||
blockStatementExpr.ignore(_bslash + LineEnd())
|
||||
|
@ -6822,6 +6837,187 @@ if PY_3:
|
|||
setattr(pyparsing_unicode, u"देवनागरी", pyparsing_unicode.Devanagari)
|
||||
|
||||
|
||||
class pyparsing_test:
|
||||
"""
|
||||
namespace class for classes useful in writing unit tests
|
||||
"""
|
||||
|
||||
class reset_pyparsing_context:
|
||||
"""
|
||||
Context manager to be used when writing unit tests that modify pyparsing config values:
|
||||
- packrat parsing
|
||||
- default whitespace characters.
|
||||
- default keyword characters
|
||||
- literal string auto-conversion class
|
||||
- __diag__ settings
|
||||
|
||||
Example:
|
||||
with reset_pyparsing_context():
|
||||
# test that literals used to construct a grammar are automatically suppressed
|
||||
ParserElement.inlineLiteralsUsing(Suppress)
|
||||
|
||||
term = Word(alphas) | Word(nums)
|
||||
group = Group('(' + term[...] + ')')
|
||||
|
||||
# assert that the '()' characters are not included in the parsed tokens
|
||||
self.assertParseAndCheckLisst(group, "(abc 123 def)", ['abc', '123', 'def'])
|
||||
|
||||
# after exiting context manager, literals are converted to Literal expressions again
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._save_context = {}
|
||||
|
||||
def save(self):
|
||||
self._save_context["default_whitespace"] = ParserElement.DEFAULT_WHITE_CHARS
|
||||
self._save_context["default_keyword_chars"] = Keyword.DEFAULT_KEYWORD_CHARS
|
||||
self._save_context[
|
||||
"literal_string_class"
|
||||
] = ParserElement._literalStringClass
|
||||
self._save_context["packrat_enabled"] = ParserElement._packratEnabled
|
||||
self._save_context["packrat_parse"] = ParserElement._parse
|
||||
self._save_context["__diag__"] = {
|
||||
name: getattr(__diag__, name) for name in __diag__._all_names
|
||||
}
|
||||
self._save_context["__compat__"] = {
|
||||
"collect_all_And_tokens": __compat__.collect_all_And_tokens
|
||||
}
|
||||
return self
|
||||
|
||||
def restore(self):
|
||||
# reset pyparsing global state
|
||||
if (
|
||||
ParserElement.DEFAULT_WHITE_CHARS
|
||||
!= self._save_context["default_whitespace"]
|
||||
):
|
||||
ParserElement.setDefaultWhitespaceChars(
|
||||
self._save_context["default_whitespace"]
|
||||
)
|
||||
Keyword.DEFAULT_KEYWORD_CHARS = self._save_context["default_keyword_chars"]
|
||||
ParserElement.inlineLiteralsUsing(
|
||||
self._save_context["literal_string_class"]
|
||||
)
|
||||
for name, value in self._save_context["__diag__"].items():
|
||||
setattr(__diag__, name, value)
|
||||
ParserElement._packratEnabled = self._save_context["packrat_enabled"]
|
||||
ParserElement._parse = self._save_context["packrat_parse"]
|
||||
__compat__.collect_all_And_tokens = self._save_context["__compat__"]
|
||||
|
||||
def __enter__(self):
|
||||
return self.save()
|
||||
|
||||
def __exit__(self, *args):
|
||||
return self.restore()
|
||||
|
||||
class TestParseResultsAsserts:
|
||||
"""
|
||||
A mixin class to add parse results assertion methods to normal unittest.TestCase classes.
|
||||
"""
|
||||
def assertParseResultsEquals(
|
||||
self, result, expected_list=None, expected_dict=None, msg=None
|
||||
):
|
||||
"""
|
||||
Unit test assertion to compare a ParseResults object with an optional expected_list,
|
||||
and compare any defined results names with an optional expected_dict.
|
||||
"""
|
||||
if expected_list is not None:
|
||||
self.assertEqual(expected_list, result.asList(), msg=msg)
|
||||
if expected_dict is not None:
|
||||
self.assertEqual(expected_dict, result.asDict(), msg=msg)
|
||||
|
||||
def assertParseAndCheckList(
|
||||
self, expr, test_string, expected_list, msg=None, verbose=True
|
||||
):
|
||||
"""
|
||||
Convenience wrapper assert to test a parser element and input string, and assert that
|
||||
the resulting ParseResults.asList() is equal to the expected_list.
|
||||
"""
|
||||
result = expr.parseString(test_string, parseAll=True)
|
||||
if verbose:
|
||||
print(result.dump())
|
||||
self.assertParseResultsEquals(result, expected_list=expected_list, msg=msg)
|
||||
|
||||
def assertParseAndCheckDict(
|
||||
self, expr, test_string, expected_dict, msg=None, verbose=True
|
||||
):
|
||||
"""
|
||||
Convenience wrapper assert to test a parser element and input string, and assert that
|
||||
the resulting ParseResults.asDict() is equal to the expected_dict.
|
||||
"""
|
||||
result = expr.parseString(test_string, parseAll=True)
|
||||
if verbose:
|
||||
print(result.dump())
|
||||
self.assertParseResultsEquals(result, expected_dict=expected_dict, msg=msg)
|
||||
|
||||
def assertRunTestResults(
|
||||
self, run_tests_report, expected_parse_results=None, msg=None
|
||||
):
|
||||
"""
|
||||
Unit test assertion to evaluate output of ParserElement.runTests(). If a list of
|
||||
list-dict tuples is given as the expected_parse_results argument, then these are zipped
|
||||
with the report tuples returned by runTests and evaluated using assertParseResultsEquals.
|
||||
Finally, asserts that the overall runTests() success value is True.
|
||||
|
||||
:param run_tests_report: tuple(bool, [tuple(str, ParseResults or Exception)]) returned from runTests
|
||||
:param expected_parse_results (optional): [tuple(str, list, dict, Exception)]
|
||||
"""
|
||||
run_test_success, run_test_results = run_tests_report
|
||||
|
||||
if expected_parse_results is not None:
|
||||
merged = [
|
||||
(rpt[0], rpt[1], expected)
|
||||
for rpt, expected in zip(run_test_results, expected_parse_results)
|
||||
]
|
||||
for test_string, result, expected in merged:
|
||||
# expected should be a tuple containing a list and/or a dict or an exception,
|
||||
# and optional failure message string
|
||||
# an empty tuple will skip any result validation
|
||||
fail_msg = next(
|
||||
(exp for exp in expected if isinstance(exp, str)), None
|
||||
)
|
||||
expected_exception = next(
|
||||
(
|
||||
exp
|
||||
for exp in expected
|
||||
if isinstance(exp, type) and issubclass(exp, Exception)
|
||||
),
|
||||
None,
|
||||
)
|
||||
if expected_exception is not None:
|
||||
with self.assertRaises(
|
||||
expected_exception=expected_exception, msg=fail_msg or msg
|
||||
):
|
||||
if isinstance(result, Exception):
|
||||
raise result
|
||||
else:
|
||||
expected_list = next(
|
||||
(exp for exp in expected if isinstance(exp, list)), None
|
||||
)
|
||||
expected_dict = next(
|
||||
(exp for exp in expected if isinstance(exp, dict)), None
|
||||
)
|
||||
if (expected_list, expected_dict) != (None, None):
|
||||
self.assertParseResultsEquals(
|
||||
result,
|
||||
expected_list=expected_list,
|
||||
expected_dict=expected_dict,
|
||||
msg=fail_msg or msg,
|
||||
)
|
||||
else:
|
||||
# warning here maybe?
|
||||
print("no validation for {!r}".format(test_string))
|
||||
|
||||
# do this last, in case some specific test results can be reported instead
|
||||
self.assertTrue(
|
||||
run_test_success, msg=msg if msg is not None else "failed runTests"
|
||||
)
|
||||
|
||||
@contextmanager
|
||||
def assertRaisesParseException(self, exc_type=ParseException, msg=None):
|
||||
with self.assertRaises(exc_type, msg=msg):
|
||||
yield
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
selectToken = CaselessLiteral("select")
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2010-2018 Benjamin Peterson
|
||||
Copyright (c) 2010-2020 Benjamin Peterson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) 2010-2018 Benjamin Peterson
|
||||
# Copyright (c) 2010-2020 Benjamin Peterson
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -29,7 +29,7 @@ import sys
|
|||
import types
|
||||
|
||||
__author__ = "Benjamin Peterson <benjamin@python.org>"
|
||||
__version__ = "1.12.0"
|
||||
__version__ = "1.14.0"
|
||||
|
||||
|
||||
# Useful for very coarse version differentiation.
|
||||
|
@ -255,9 +255,11 @@ _moved_attributes = [
|
|||
MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"),
|
||||
MovedModule("builtins", "__builtin__"),
|
||||
MovedModule("configparser", "ConfigParser"),
|
||||
MovedModule("collections_abc", "collections", "collections.abc" if sys.version_info >= (3, 3) else "collections"),
|
||||
MovedModule("copyreg", "copy_reg"),
|
||||
MovedModule("dbm_gnu", "gdbm", "dbm.gnu"),
|
||||
MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"),
|
||||
MovedModule("dbm_ndbm", "dbm", "dbm.ndbm"),
|
||||
MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread" if sys.version_info < (3, 9) else "_thread"),
|
||||
MovedModule("http_cookiejar", "cookielib", "http.cookiejar"),
|
||||
MovedModule("http_cookies", "Cookie", "http.cookies"),
|
||||
MovedModule("html_entities", "htmlentitydefs", "html.entities"),
|
||||
|
@ -637,13 +639,16 @@ if PY3:
|
|||
import io
|
||||
StringIO = io.StringIO
|
||||
BytesIO = io.BytesIO
|
||||
del io
|
||||
_assertCountEqual = "assertCountEqual"
|
||||
if sys.version_info[1] <= 1:
|
||||
_assertRaisesRegex = "assertRaisesRegexp"
|
||||
_assertRegex = "assertRegexpMatches"
|
||||
_assertNotRegex = "assertNotRegexpMatches"
|
||||
else:
|
||||
_assertRaisesRegex = "assertRaisesRegex"
|
||||
_assertRegex = "assertRegex"
|
||||
_assertNotRegex = "assertNotRegex"
|
||||
else:
|
||||
def b(s):
|
||||
return s
|
||||
|
@ -665,6 +670,7 @@ else:
|
|||
_assertCountEqual = "assertItemsEqual"
|
||||
_assertRaisesRegex = "assertRaisesRegexp"
|
||||
_assertRegex = "assertRegexpMatches"
|
||||
_assertNotRegex = "assertNotRegexpMatches"
|
||||
_add_doc(b, """Byte literal""")
|
||||
_add_doc(u, """Text literal""")
|
||||
|
||||
|
@ -681,6 +687,10 @@ def assertRegex(self, *args, **kwargs):
|
|||
return getattr(self, _assertRegex)(*args, **kwargs)
|
||||
|
||||
|
||||
def assertNotRegex(self, *args, **kwargs):
|
||||
return getattr(self, _assertNotRegex)(*args, **kwargs)
|
||||
|
||||
|
||||
if PY3:
|
||||
exec_ = getattr(moves.builtins, "exec")
|
||||
|
||||
|
@ -716,16 +726,7 @@ else:
|
|||
""")
|
||||
|
||||
|
||||
if sys.version_info[:2] == (3, 2):
|
||||
exec_("""def raise_from(value, from_value):
|
||||
try:
|
||||
if from_value is None:
|
||||
raise value
|
||||
raise value from from_value
|
||||
finally:
|
||||
value = None
|
||||
""")
|
||||
elif sys.version_info[:2] > (3, 2):
|
||||
if sys.version_info[:2] > (3,):
|
||||
exec_("""def raise_from(value, from_value):
|
||||
try:
|
||||
raise value from from_value
|
||||
|
@ -805,13 +806,33 @@ if sys.version_info[:2] < (3, 3):
|
|||
_add_doc(reraise, """Reraise an exception.""")
|
||||
|
||||
if sys.version_info[0:2] < (3, 4):
|
||||
# This does exactly the same what the :func:`py3:functools.update_wrapper`
|
||||
# function does on Python versions after 3.2. It sets the ``__wrapped__``
|
||||
# attribute on ``wrapper`` object and it doesn't raise an error if any of
|
||||
# the attributes mentioned in ``assigned`` and ``updated`` are missing on
|
||||
# ``wrapped`` object.
|
||||
def _update_wrapper(wrapper, wrapped,
|
||||
assigned=functools.WRAPPER_ASSIGNMENTS,
|
||||
updated=functools.WRAPPER_UPDATES):
|
||||
for attr in assigned:
|
||||
try:
|
||||
value = getattr(wrapped, attr)
|
||||
except AttributeError:
|
||||
continue
|
||||
else:
|
||||
setattr(wrapper, attr, value)
|
||||
for attr in updated:
|
||||
getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
|
||||
wrapper.__wrapped__ = wrapped
|
||||
return wrapper
|
||||
_update_wrapper.__doc__ = functools.update_wrapper.__doc__
|
||||
|
||||
def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS,
|
||||
updated=functools.WRAPPER_UPDATES):
|
||||
def wrapper(f):
|
||||
f = functools.wraps(wrapped, assigned, updated)(f)
|
||||
f.__wrapped__ = wrapped
|
||||
return f
|
||||
return wrapper
|
||||
return functools.partial(_update_wrapper, wrapped=wrapped,
|
||||
assigned=assigned, updated=updated)
|
||||
wraps.__doc__ = functools.wraps.__doc__
|
||||
|
||||
else:
|
||||
wraps = functools.wraps
|
||||
|
||||
|
@ -824,7 +845,15 @@ def with_metaclass(meta, *bases):
|
|||
class metaclass(type):
|
||||
|
||||
def __new__(cls, name, this_bases, d):
|
||||
return meta(name, bases, d)
|
||||
if sys.version_info[:2] >= (3, 7):
|
||||
# This version introduced PEP 560 that requires a bit
|
||||
# of extra care (we mimic what is done by __build_class__).
|
||||
resolved_bases = types.resolve_bases(bases)
|
||||
if resolved_bases is not bases:
|
||||
d['__orig_bases__'] = bases
|
||||
else:
|
||||
resolved_bases = bases
|
||||
return meta(name, resolved_bases, d)
|
||||
|
||||
@classmethod
|
||||
def __prepare__(cls, name, this_bases):
|
||||
|
@ -908,10 +937,9 @@ def ensure_text(s, encoding='utf-8', errors='strict'):
|
|||
raise TypeError("not expecting type '%s'" % type(s))
|
||||
|
||||
|
||||
|
||||
def python_2_unicode_compatible(klass):
|
||||
"""
|
||||
A decorator that defines __unicode__ and __str__ methods under Python 2.
|
||||
A class decorator that defines __unicode__ and __str__ methods under Python 2.
|
||||
Under Python 3 it does nothing.
|
||||
|
||||
To support Python 2 and 3 with a single code base, define a __str__ method
|
||||
|
|
|
@ -22,7 +22,7 @@ from logging import NullHandler
|
|||
|
||||
__author__ = "Andrey Petrov (andrey.petrov@shazow.net)"
|
||||
__license__ = "MIT"
|
||||
__version__ = "1.25.6"
|
||||
__version__ = "1.25.7"
|
||||
|
||||
__all__ = (
|
||||
"HTTPConnectionPool",
|
||||
|
|
|
@ -412,7 +412,7 @@ class VerifiedHTTPSConnection(HTTPSConnection):
|
|||
(
|
||||
"Certificate for {0} has no `subjectAltName`, falling back to check for a "
|
||||
"`commonName` for now. This feature is being removed by major browsers and "
|
||||
"deprecated by RFC 2818. (See https://github.com/shazow/urllib3/issues/497 "
|
||||
"deprecated by RFC 2818. (See https://github.com/urllib3/urllib3/issues/497 "
|
||||
"for details.)".format(hostname)
|
||||
),
|
||||
SubjectAltNameWarning,
|
||||
|
@ -430,7 +430,7 @@ def _match_hostname(cert, asserted_hostname):
|
|||
match_hostname(cert, asserted_hostname)
|
||||
except CertificateError as e:
|
||||
log.warning(
|
||||
"Certificate did not match expected hostname: %s. " "Certificate: %s",
|
||||
"Certificate did not match expected hostname: %s. Certificate: %s",
|
||||
asserted_hostname,
|
||||
cert,
|
||||
)
|
||||
|
|
|
@ -257,7 +257,7 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods):
|
|||
if self.block:
|
||||
raise EmptyPoolError(
|
||||
self,
|
||||
"Pool reached maximum size and no more " "connections are allowed.",
|
||||
"Pool reached maximum size and no more connections are allowed.",
|
||||
)
|
||||
pass # Oh well, we'll create a new connection then
|
||||
|
||||
|
@ -626,7 +626,7 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods):
|
|||
#
|
||||
# See issue #651 [1] for details.
|
||||
#
|
||||
# [1] <https://github.com/shazow/urllib3/issues/651>
|
||||
# [1] <https://github.com/urllib3/urllib3/issues/651>
|
||||
release_this_conn = release_conn
|
||||
|
||||
# Merge the proxy headers. Only do this in HTTP. We have to copy the
|
||||
|
@ -742,10 +742,7 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods):
|
|||
if not conn:
|
||||
# Try again
|
||||
log.warning(
|
||||
"Retrying (%r) after connection " "broken by '%r': %s",
|
||||
retries,
|
||||
err,
|
||||
url,
|
||||
"Retrying (%r) after connection broken by '%r': %s", retries, err, url
|
||||
)
|
||||
return self.urlopen(
|
||||
method,
|
||||
|
@ -758,6 +755,7 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods):
|
|||
timeout=timeout,
|
||||
pool_timeout=pool_timeout,
|
||||
release_conn=release_conn,
|
||||
chunked=chunked,
|
||||
body_pos=body_pos,
|
||||
**response_kw
|
||||
)
|
||||
|
@ -809,6 +807,7 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods):
|
|||
timeout=timeout,
|
||||
pool_timeout=pool_timeout,
|
||||
release_conn=release_conn,
|
||||
chunked=chunked,
|
||||
body_pos=body_pos,
|
||||
**response_kw
|
||||
)
|
||||
|
@ -842,6 +841,7 @@ class HTTPConnectionPool(ConnectionPool, RequestMethods):
|
|||
timeout=timeout,
|
||||
pool_timeout=pool_timeout,
|
||||
release_conn=release_conn,
|
||||
chunked=chunked,
|
||||
body_pos=body_pos,
|
||||
**response_kw
|
||||
)
|
||||
|
@ -961,7 +961,7 @@ class HTTPSConnectionPool(HTTPConnectionPool):
|
|||
|
||||
if not self.ConnectionCls or self.ConnectionCls is DummyConnection:
|
||||
raise SSLError(
|
||||
"Can't connect to HTTPS URL because the SSL " "module is not available."
|
||||
"Can't connect to HTTPS URL because the SSL module is not available."
|
||||
)
|
||||
|
||||
actual_host = self.host
|
||||
|
|
|
@ -6,27 +6,31 @@ import os
|
|||
|
||||
|
||||
def is_appengine():
|
||||
return is_local_appengine() or is_prod_appengine() or is_prod_appengine_mvms()
|
||||
return "APPENGINE_RUNTIME" in os.environ
|
||||
|
||||
|
||||
def is_appengine_sandbox():
|
||||
return is_appengine() and not is_prod_appengine_mvms()
|
||||
"""Reports if the app is running in the first generation sandbox.
|
||||
|
||||
The second generation runtimes are technically still in a sandbox, but it
|
||||
is much less restrictive, so generally you shouldn't need to check for it.
|
||||
see https://cloud.google.com/appengine/docs/standard/runtimes
|
||||
"""
|
||||
return is_appengine() and os.environ["APPENGINE_RUNTIME"] == "python27"
|
||||
|
||||
|
||||
def is_local_appengine():
|
||||
return (
|
||||
"APPENGINE_RUNTIME" in os.environ
|
||||
and "Development/" in os.environ["SERVER_SOFTWARE"]
|
||||
return is_appengine() and os.environ.get("SERVER_SOFTWARE", "").startswith(
|
||||
"Development/"
|
||||
)
|
||||
|
||||
|
||||
def is_prod_appengine():
|
||||
return (
|
||||
"APPENGINE_RUNTIME" in os.environ
|
||||
and "Google App Engine/" in os.environ["SERVER_SOFTWARE"]
|
||||
and not is_prod_appengine_mvms()
|
||||
return is_appengine() and os.environ.get("SERVER_SOFTWARE", "").startswith(
|
||||
"Google App Engine/"
|
||||
)
|
||||
|
||||
|
||||
def is_prod_appengine_mvms():
|
||||
return os.environ.get("GAE_VM", False) == "true"
|
||||
"""Deprecated."""
|
||||
return False
|
||||
|
|
|
@ -415,6 +415,7 @@ class SecurityConst(object):
|
|||
kTLSProtocol1 = 4
|
||||
kTLSProtocol11 = 7
|
||||
kTLSProtocol12 = 8
|
||||
# SecureTransport does not support TLS 1.3 even if there's a constant for it
|
||||
kTLSProtocol13 = 10
|
||||
kTLSProtocolMaxSupported = 999
|
||||
|
||||
|
|
|
@ -108,13 +108,6 @@ class AppEngineManager(RequestMethods):
|
|||
"URLFetch is not available in this environment."
|
||||
)
|
||||
|
||||
if is_prod_appengine_mvms():
|
||||
raise AppEnginePlatformError(
|
||||
"Use normal urllib3.PoolManager instead of AppEngineManager"
|
||||
"on Managed VMs, as using URLFetch is not necessary in "
|
||||
"this environment."
|
||||
)
|
||||
|
||||
warnings.warn(
|
||||
"urllib3 is using URLFetch on Google App Engine sandbox instead "
|
||||
"of sockets. To use sockets directly instead of URLFetch see "
|
||||
|
|
|
@ -96,9 +96,7 @@ class NTLMConnectionPool(HTTPSConnectionPool):
|
|||
log.debug("Response data: %s [...]", res.read()[:100])
|
||||
if res.status != 200:
|
||||
if res.status == 401:
|
||||
raise Exception(
|
||||
"Server rejected request: wrong " "username or password"
|
||||
)
|
||||
raise Exception("Server rejected request: wrong username or password")
|
||||
raise Exception("Wrong server response: %s %s" % (res.status, res.reason))
|
||||
|
||||
res.fp = None
|
||||
|
|
|
@ -144,13 +144,10 @@ CIPHER_SUITES = [
|
|||
]
|
||||
|
||||
# Basically this is simple: for PROTOCOL_SSLv23 we turn it into a low of
|
||||
# TLSv1 and a high of TLSv1.3. For everything else, we pin to that version.
|
||||
# TLSv1 to 1.2 are supported on macOS 10.8+ and TLSv1.3 is macOS 10.13+
|
||||
# TLSv1 and a high of TLSv1.2. For everything else, we pin to that version.
|
||||
# TLSv1 to 1.2 are supported on macOS 10.8+
|
||||
_protocol_to_min_max = {
|
||||
util.PROTOCOL_TLS: (
|
||||
SecurityConst.kTLSProtocol1,
|
||||
SecurityConst.kTLSProtocolMaxSupported,
|
||||
)
|
||||
util.PROTOCOL_TLS: (SecurityConst.kTLSProtocol1, SecurityConst.kTLSProtocol12)
|
||||
}
|
||||
|
||||
if hasattr(ssl, "PROTOCOL_SSLv2"):
|
||||
|
@ -488,15 +485,7 @@ class WrappedSocket(object):
|
|||
result = Security.SSLSetProtocolVersionMin(self.context, min_version)
|
||||
_assert_no_error(result)
|
||||
|
||||
# TLS 1.3 isn't necessarily enabled by the OS
|
||||
# so we have to detect when we error out and try
|
||||
# setting TLS 1.3 if it's allowed. kTLSProtocolMaxSupported
|
||||
# was added in macOS 10.13 along with kTLSProtocol13.
|
||||
result = Security.SSLSetProtocolVersionMax(self.context, max_version)
|
||||
if result != 0 and max_version == SecurityConst.kTLSProtocolMaxSupported:
|
||||
result = Security.SSLSetProtocolVersionMax(
|
||||
self.context, SecurityConst.kTLSProtocol12
|
||||
)
|
||||
_assert_no_error(result)
|
||||
|
||||
# If there's a trust DB, we need to use it. We do that by telling
|
||||
|
@ -707,7 +696,7 @@ class WrappedSocket(object):
|
|||
)
|
||||
_assert_no_error(result)
|
||||
if protocol.value == SecurityConst.kTLSProtocol13:
|
||||
return "TLSv1.3"
|
||||
raise ssl.SSLError("SecureTransport does not support TLS 1.3")
|
||||
elif protocol.value == SecurityConst.kTLSProtocol12:
|
||||
return "TLSv1.2"
|
||||
elif protocol.value == SecurityConst.kTLSProtocol11:
|
||||
|
|
|
@ -222,7 +222,7 @@ class IncompleteRead(HTTPError, httplib_IncompleteRead):
|
|||
super(IncompleteRead, self).__init__(partial, expected)
|
||||
|
||||
def __repr__(self):
|
||||
return "IncompleteRead(%i bytes read, " "%i more expected)" % (
|
||||
return "IncompleteRead(%i bytes read, %i more expected)" % (
|
||||
self.partial,
|
||||
self.expected,
|
||||
)
|
||||
|
|
|
@ -153,10 +153,8 @@ def match_hostname(cert, hostname):
|
|||
"doesn't match either of %s" % (hostname, ", ".join(map(repr, dnsnames)))
|
||||
)
|
||||
elif len(dnsnames) == 1:
|
||||
raise CertificateError(
|
||||
"hostname %r " "doesn't match %r" % (hostname, dnsnames[0])
|
||||
)
|
||||
raise CertificateError("hostname %r doesn't match %r" % (hostname, dnsnames[0]))
|
||||
else:
|
||||
raise CertificateError(
|
||||
"no appropriate commonName or " "subjectAltName fields were found"
|
||||
"no appropriate commonName or subjectAltName fields were found"
|
||||
)
|
||||
|
|
|
@ -121,7 +121,7 @@ def _has_ipv6(host):
|
|||
# has_ipv6 returns true if cPython was compiled with IPv6 support.
|
||||
# It does not tell us if the system has IPv6 support enabled. To
|
||||
# determine that we must bind to an IPv6 address.
|
||||
# https://github.com/shazow/urllib3/pull/611
|
||||
# https://github.com/urllib3/urllib3/pull/611
|
||||
# https://bugs.python.org/issue658327
|
||||
try:
|
||||
sock = socket.socket(socket.AF_INET6)
|
||||
|
|
|
@ -122,7 +122,7 @@ def rewind_body(body, body_pos):
|
|||
body_seek(body_pos)
|
||||
except (IOError, OSError):
|
||||
raise UnrewindableBodyError(
|
||||
"An error occurred when rewinding request " "body for redirect/retry."
|
||||
"An error occurred when rewinding request body for redirect/retry."
|
||||
)
|
||||
elif body_pos is _FAILEDTELL:
|
||||
raise UnrewindableBodyError(
|
||||
|
@ -131,5 +131,5 @@ def rewind_body(body, body_pos):
|
|||
)
|
||||
else:
|
||||
raise ValueError(
|
||||
"body_pos must be of type integer, " "instead it was %s." % type(body_pos)
|
||||
"body_pos must be of type integer, instead it was %s." % type(body_pos)
|
||||
)
|
||||
|
|
|
@ -203,7 +203,7 @@ class Timeout(object):
|
|||
"""
|
||||
if self._start_connect is None:
|
||||
raise TimeoutStateError(
|
||||
"Can't get connect duration for timer " "that has not started."
|
||||
"Can't get connect duration for timer that has not started."
|
||||
)
|
||||
return current_time() - self._start_connect
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ IPV6_PAT = "(?:" + "|".join([x % _subs for x in _variations]) + ")"
|
|||
ZONE_ID_PAT = "(?:%25|%)(?:[" + UNRESERVED_PAT + "]|%[a-fA-F0-9]{2})+"
|
||||
IPV6_ADDRZ_PAT = r"\[" + IPV6_PAT + r"(?:" + ZONE_ID_PAT + r")?\]"
|
||||
REG_NAME_PAT = r"(?:[^\[\]%:/?#]|%[a-fA-F0-9]{2})*"
|
||||
TARGET_RE = re.compile(r"^(/[^?]*)(?:\?([^#]+))?(?:#(.*))?$")
|
||||
TARGET_RE = re.compile(r"^(/[^?#]*)(?:\?([^#]*))?(?:#.*)?$")
|
||||
|
||||
IPV4_RE = re.compile("^" + IPV4_PAT + "$")
|
||||
IPV6_RE = re.compile("^" + IPV6_PAT + "$")
|
||||
|
@ -325,14 +325,11 @@ def _encode_target(target):
|
|||
if not target.startswith("/"):
|
||||
return target
|
||||
|
||||
path, query, fragment = TARGET_RE.match(target).groups()
|
||||
path, query = TARGET_RE.match(target).groups()
|
||||
target = _encode_invalid_chars(path, PATH_CHARS)
|
||||
query = _encode_invalid_chars(query, QUERY_CHARS)
|
||||
fragment = _encode_invalid_chars(fragment, FRAGMENT_CHARS)
|
||||
if query is not None:
|
||||
target += "?" + query
|
||||
if fragment is not None:
|
||||
target += "#" + target
|
||||
return target
|
||||
|
||||
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
appdirs==1.4.3
|
||||
CacheControl==0.12.5
|
||||
colorama==0.4.1
|
||||
CacheControl==0.12.6
|
||||
colorama==0.4.3
|
||||
contextlib2==0.6.0
|
||||
distlib==0.2.9.post0
|
||||
distlib==0.3.0
|
||||
distro==1.4.0
|
||||
html5lib==1.0.1
|
||||
ipaddress==1.0.22 # Only needed on 2.6 and 2.7
|
||||
ipaddress==1.0.23 # Only needed on 2.6 and 2.7
|
||||
msgpack==0.6.2
|
||||
packaging==20.0
|
||||
pep517==0.7.0
|
||||
progress==1.5
|
||||
pyparsing==2.4.2
|
||||
pyparsing==2.4.6
|
||||
pytoml==0.1.21
|
||||
requests==2.22.0
|
||||
certifi==2019.9.11
|
||||
certifi==2019.11.28
|
||||
chardet==3.0.4
|
||||
idna==2.8
|
||||
urllib3==1.25.6
|
||||
urllib3==1.25.7
|
||||
retrying==1.3.3
|
||||
setuptools==41.4.0
|
||||
six==1.12.0
|
||||
setuptools==44.0.0
|
||||
six==1.14.0
|
||||
webencodings==0.5.1
|
||||
|
|
Loading…
Reference in New Issue