crate 0.34.0__tar.gz → 0.35.1__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {crate-0.34.0 → crate-0.35.1}/PKG-INFO +2 -3
- {crate-0.34.0 → crate-0.35.1}/setup.py +7 -3
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/__init__.py +1 -1
- crate-0.35.1/src/crate/client/_pep440.py +1 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/connection.py +1 -1
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/http.py +4 -2
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/sa_version.py +1 -1
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/test_connection.py +24 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/testing/test_layer.py +1 -1
- {crate-0.34.0 → crate-0.35.1}/src/crate.egg-info/PKG-INFO +2 -3
- {crate-0.34.0 → crate-0.35.1}/src/crate.egg-info/entry_points.txt +0 -1
- {crate-0.34.0 → crate-0.35.1}/src/crate.egg-info/requires.txt +4 -3
- crate-0.34.0/src/crate/client/_pep440.py +0 -501
- {crate-0.34.0 → crate-0.35.1}/CONTRIBUTING.rst +0 -0
- {crate-0.34.0 → crate-0.35.1}/DEVELOP.rst +0 -0
- {crate-0.34.0 → crate-0.35.1}/LICENSE +0 -0
- {crate-0.34.0 → crate-0.35.1}/MANIFEST.in +0 -0
- {crate-0.34.0 → crate-0.35.1}/NOTICE +0 -0
- {crate-0.34.0 → crate-0.35.1}/README.rst +0 -0
- {crate-0.34.0 → crate-0.35.1}/docs/_extra/robots.txt +0 -0
- {crate-0.34.0 → crate-0.35.1}/docs/requirements.txt +0 -0
- {crate-0.34.0 → crate-0.35.1}/pyproject.toml +0 -0
- {crate-0.34.0 → crate-0.35.1}/setup.cfg +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/__init__.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/blob.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/converter.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/cursor.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/exceptions.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/pki/readme.rst +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/__init__.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/compat/__init__.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/compat/api13.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/compat/core10.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/compat/core14.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/compat/core20.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/compiler.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/dialect.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/predicates/__init__.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/support.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/tests/__init__.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/tests/array_test.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/tests/bulk_test.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/tests/compiler_test.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/tests/connection_test.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/tests/create_table_test.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/tests/datetime_test.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/tests/dialect_test.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/tests/dict_test.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/tests/function_test.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/tests/insert_from_select_test.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/tests/match_test.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/tests/query_caching.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/tests/update_test.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/tests/warnings_test.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/sqlalchemy/types.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/test_cursor.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/test_http.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/client/test_util.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/testing/__init__.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/testing/layer.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/testing/settings.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate/testing/util.py +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate.egg-info/SOURCES.txt +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate.egg-info/dependency_links.txt +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate.egg-info/namespace_packages.txt +0 -0
- {crate-0.34.0 → crate-0.35.1}/src/crate.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: crate
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.35.1
|
4
4
|
Summary: CrateDB Python Client
|
5
5
|
Home-page: https://github.com/crate/crate-python
|
6
6
|
Author: Crate.io
|
@@ -20,6 +20,7 @@ Classifier: Programming Language :: Python :: 3.8
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.9
|
21
21
|
Classifier: Programming Language :: Python :: 3.10
|
22
22
|
Classifier: Programming Language :: Python :: 3.11
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
23
24
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
24
25
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
25
26
|
Classifier: Topic :: Database
|
@@ -124,5 +125,3 @@ GitHub`_. We appreciate contributions of any kind.
|
|
124
125
|
.. _SQLAlchemy dialect: https://docs.sqlalchemy.org/dialects/
|
125
126
|
.. _StackOverflow: https://stackoverflow.com/tags/cratedb
|
126
127
|
.. _support channels: https://crate.io/support/
|
127
|
-
|
128
|
-
|
@@ -58,7 +58,10 @@ setup(
|
|
58
58
|
'crate = crate.client.sqlalchemy:CrateDialect'
|
59
59
|
]
|
60
60
|
},
|
61
|
-
install_requires=[
|
61
|
+
install_requires=[
|
62
|
+
'urllib3<2.2',
|
63
|
+
'verlib2==0.2.0',
|
64
|
+
],
|
62
65
|
extras_require=dict(
|
63
66
|
sqlalchemy=['sqlalchemy>=1.0,<2.1',
|
64
67
|
'geojson>=2.5.0,<4',
|
@@ -71,8 +74,8 @@ setup(
|
|
71
74
|
'createcoverage>=1,<2',
|
72
75
|
'dask',
|
73
76
|
'stopit>=1.1.2,<2',
|
74
|
-
'flake8>=4,<
|
75
|
-
'pandas',
|
77
|
+
'flake8>=4,<8',
|
78
|
+
'pandas<2.1',
|
76
79
|
'pytz',
|
77
80
|
],
|
78
81
|
doc=['sphinx>=3.5,<8',
|
@@ -93,6 +96,7 @@ setup(
|
|
93
96
|
'Programming Language :: Python :: 3.9',
|
94
97
|
'Programming Language :: Python :: 3.10',
|
95
98
|
'Programming Language :: Python :: 3.11',
|
99
|
+
'Programming Language :: Python :: 3.12',
|
96
100
|
'Programming Language :: Python :: Implementation :: CPython',
|
97
101
|
'Programming Language :: Python :: Implementation :: PyPy',
|
98
102
|
'Topic :: Database'
|
@@ -0,0 +1 @@
|
|
1
|
+
from verlib2 import Version # noqa: F401
|
@@ -49,8 +49,8 @@ from urllib3.exceptions import (
|
|
49
49
|
SSLError,
|
50
50
|
)
|
51
51
|
from urllib3.util.retry import Retry
|
52
|
+
from verlib2 import Version
|
52
53
|
|
53
|
-
from crate.client._pep440 import Version
|
54
54
|
from crate.client.exceptions import (
|
55
55
|
ConnectionError,
|
56
56
|
BlobLocationNotFoundException,
|
@@ -273,7 +273,9 @@ def _pool_kw_args(verify_ssl_cert, ca_cert, client_cert, client_key,
|
|
273
273
|
'key_file': client_key,
|
274
274
|
}
|
275
275
|
if timeout is not None:
|
276
|
-
|
276
|
+
if isinstance(timeout, str):
|
277
|
+
timeout = float(timeout)
|
278
|
+
kw['timeout'] = timeout
|
277
279
|
if pool_size is not None:
|
278
280
|
kw['maxsize'] = int(pool_size)
|
279
281
|
return kw
|
@@ -1,5 +1,7 @@
|
|
1
1
|
import datetime
|
2
2
|
|
3
|
+
from urllib3 import Timeout
|
4
|
+
|
3
5
|
from .connection import Connection
|
4
6
|
from .http import Client
|
5
7
|
from crate.client import connect
|
@@ -72,3 +74,25 @@ class ConnectionTest(TestCase):
|
|
72
74
|
cursor = connection.cursor()
|
73
75
|
self.assertEqual(cursor.time_zone.tzname(None), "UTC")
|
74
76
|
self.assertEqual(cursor.time_zone.utcoffset(None), datetime.timedelta(0))
|
77
|
+
|
78
|
+
def test_timeout_float(self):
|
79
|
+
"""
|
80
|
+
Verify setting the timeout value as a scalar (float) works.
|
81
|
+
"""
|
82
|
+
with connect('localhost:4200', timeout=2.42) as conn:
|
83
|
+
self.assertEqual(conn.client._pool_kw["timeout"], 2.42)
|
84
|
+
|
85
|
+
def test_timeout_string(self):
|
86
|
+
"""
|
87
|
+
Verify setting the timeout value as a scalar (string) works.
|
88
|
+
"""
|
89
|
+
with connect('localhost:4200', timeout="2.42") as conn:
|
90
|
+
self.assertEqual(conn.client._pool_kw["timeout"], 2.42)
|
91
|
+
|
92
|
+
def test_timeout_object(self):
|
93
|
+
"""
|
94
|
+
Verify setting the timeout value as a Timeout object works.
|
95
|
+
"""
|
96
|
+
timeout = Timeout(connect=2.42, read=0.01)
|
97
|
+
with connect('localhost:4200', timeout=timeout) as conn:
|
98
|
+
self.assertEqual(conn.client._pool_kw["timeout"], timeout)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: crate
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.35.1
|
4
4
|
Summary: CrateDB Python Client
|
5
5
|
Home-page: https://github.com/crate/crate-python
|
6
6
|
Author: Crate.io
|
@@ -20,6 +20,7 @@ Classifier: Programming Language :: Python :: 3.8
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.9
|
21
21
|
Classifier: Programming Language :: Python :: 3.10
|
22
22
|
Classifier: Programming Language :: Python :: 3.11
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
23
24
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
24
25
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
25
26
|
Classifier: Topic :: Database
|
@@ -124,5 +125,3 @@ GitHub`_. We appreciate contributions of any kind.
|
|
124
125
|
.. _SQLAlchemy dialect: https://docs.sqlalchemy.org/dialects/
|
125
126
|
.. _StackOverflow: https://stackoverflow.com/tags/cratedb
|
126
127
|
.. _support channels: https://crate.io/support/
|
127
|
-
|
128
|
-
|
@@ -1,501 +0,0 @@
|
|
1
|
-
"""Utility to compare pep440 compatible version strings.
|
2
|
-
|
3
|
-
The LooseVersion and StrictVersion classes that distutils provides don't
|
4
|
-
work; they don't recognize anything like alpha/beta/rc/dev versions.
|
5
|
-
|
6
|
-
This specific file has been vendored from NumPy on 2023-02-10 [1].
|
7
|
-
Its reference location is in `packaging` [2,3].
|
8
|
-
|
9
|
-
[1] https://github.com/numpy/numpy/blob/v1.25.0.dev0/numpy/compat/_pep440.py
|
10
|
-
[2] https://github.com/pypa/packaging/blob/23.0/src/packaging/_structures.py
|
11
|
-
[3] https://github.com/pypa/packaging/blob/23.0/src/packaging/version.py
|
12
|
-
"""
|
13
|
-
|
14
|
-
# Copyright (c) Donald Stufft and individual contributors.
|
15
|
-
# All rights reserved.
|
16
|
-
|
17
|
-
# Redistribution and use in source and binary forms, with or without
|
18
|
-
# modification, are permitted provided that the following conditions are met:
|
19
|
-
|
20
|
-
# 1. Redistributions of source code must retain the above copyright notice,
|
21
|
-
# this list of conditions and the following disclaimer.
|
22
|
-
|
23
|
-
# 2. Redistributions in binary form must reproduce the above copyright
|
24
|
-
# notice, this list of conditions and the following disclaimer in the
|
25
|
-
# documentation and/or other materials provided with the distribution.
|
26
|
-
|
27
|
-
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
28
|
-
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
29
|
-
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
30
|
-
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
31
|
-
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
32
|
-
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
33
|
-
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
34
|
-
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
35
|
-
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
36
|
-
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
37
|
-
# POSSIBILITY OF SUCH DAMAGE.
|
38
|
-
|
39
|
-
import collections
|
40
|
-
import itertools
|
41
|
-
import re
|
42
|
-
|
43
|
-
|
44
|
-
__all__ = [
|
45
|
-
"parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN",
|
46
|
-
]
|
47
|
-
|
48
|
-
|
49
|
-
# BEGIN packaging/_structures.py
|
50
|
-
|
51
|
-
|
52
|
-
class Infinity:
|
53
|
-
def __repr__(self):
|
54
|
-
return "Infinity"
|
55
|
-
|
56
|
-
def __hash__(self):
|
57
|
-
return hash(repr(self))
|
58
|
-
|
59
|
-
def __lt__(self, other):
|
60
|
-
return False
|
61
|
-
|
62
|
-
def __le__(self, other):
|
63
|
-
return False
|
64
|
-
|
65
|
-
def __eq__(self, other):
|
66
|
-
return isinstance(other, self.__class__)
|
67
|
-
|
68
|
-
def __ne__(self, other):
|
69
|
-
return not isinstance(other, self.__class__)
|
70
|
-
|
71
|
-
def __gt__(self, other):
|
72
|
-
return True
|
73
|
-
|
74
|
-
def __ge__(self, other):
|
75
|
-
return True
|
76
|
-
|
77
|
-
def __neg__(self):
|
78
|
-
return NegativeInfinity
|
79
|
-
|
80
|
-
|
81
|
-
Infinity = Infinity()
|
82
|
-
|
83
|
-
|
84
|
-
class NegativeInfinity:
|
85
|
-
def __repr__(self):
|
86
|
-
return "-Infinity"
|
87
|
-
|
88
|
-
def __hash__(self):
|
89
|
-
return hash(repr(self))
|
90
|
-
|
91
|
-
def __lt__(self, other):
|
92
|
-
return True
|
93
|
-
|
94
|
-
def __le__(self, other):
|
95
|
-
return True
|
96
|
-
|
97
|
-
def __eq__(self, other):
|
98
|
-
return isinstance(other, self.__class__)
|
99
|
-
|
100
|
-
def __ne__(self, other):
|
101
|
-
return not isinstance(other, self.__class__)
|
102
|
-
|
103
|
-
def __gt__(self, other):
|
104
|
-
return False
|
105
|
-
|
106
|
-
def __ge__(self, other):
|
107
|
-
return False
|
108
|
-
|
109
|
-
def __neg__(self):
|
110
|
-
return Infinity
|
111
|
-
|
112
|
-
|
113
|
-
# BEGIN packaging/version.py
|
114
|
-
|
115
|
-
|
116
|
-
NegativeInfinity = NegativeInfinity()
|
117
|
-
|
118
|
-
_Version = collections.namedtuple(
|
119
|
-
"_Version",
|
120
|
-
["epoch", "release", "dev", "pre", "post", "local"],
|
121
|
-
)
|
122
|
-
|
123
|
-
|
124
|
-
def parse(version):
|
125
|
-
"""
|
126
|
-
Parse the given version string and return either a :class:`Version` object
|
127
|
-
or a :class:`LegacyVersion` object depending on if the given version is
|
128
|
-
a valid PEP 440 version or a legacy version.
|
129
|
-
"""
|
130
|
-
try:
|
131
|
-
return Version(version)
|
132
|
-
except InvalidVersion:
|
133
|
-
return LegacyVersion(version)
|
134
|
-
|
135
|
-
|
136
|
-
class InvalidVersion(ValueError):
|
137
|
-
"""
|
138
|
-
An invalid version was found, users should refer to PEP 440.
|
139
|
-
"""
|
140
|
-
|
141
|
-
|
142
|
-
class _BaseVersion:
|
143
|
-
|
144
|
-
def __hash__(self):
|
145
|
-
return hash(self._key)
|
146
|
-
|
147
|
-
def __lt__(self, other):
|
148
|
-
return self._compare(other, lambda s, o: s < o)
|
149
|
-
|
150
|
-
def __le__(self, other):
|
151
|
-
return self._compare(other, lambda s, o: s <= o)
|
152
|
-
|
153
|
-
def __eq__(self, other):
|
154
|
-
return self._compare(other, lambda s, o: s == o)
|
155
|
-
|
156
|
-
def __ge__(self, other):
|
157
|
-
return self._compare(other, lambda s, o: s >= o)
|
158
|
-
|
159
|
-
def __gt__(self, other):
|
160
|
-
return self._compare(other, lambda s, o: s > o)
|
161
|
-
|
162
|
-
def __ne__(self, other):
|
163
|
-
return self._compare(other, lambda s, o: s != o)
|
164
|
-
|
165
|
-
def _compare(self, other, method):
|
166
|
-
if not isinstance(other, _BaseVersion):
|
167
|
-
return NotImplemented
|
168
|
-
|
169
|
-
return method(self._key, other._key)
|
170
|
-
|
171
|
-
|
172
|
-
class LegacyVersion(_BaseVersion):
|
173
|
-
|
174
|
-
def __init__(self, version):
|
175
|
-
self._version = str(version)
|
176
|
-
self._key = _legacy_cmpkey(self._version)
|
177
|
-
|
178
|
-
def __str__(self):
|
179
|
-
return self._version
|
180
|
-
|
181
|
-
def __repr__(self):
|
182
|
-
return "<LegacyVersion({0})>".format(repr(str(self)))
|
183
|
-
|
184
|
-
@property
|
185
|
-
def public(self):
|
186
|
-
return self._version
|
187
|
-
|
188
|
-
@property
|
189
|
-
def base_version(self):
|
190
|
-
return self._version
|
191
|
-
|
192
|
-
@property
|
193
|
-
def local(self):
|
194
|
-
return None
|
195
|
-
|
196
|
-
@property
|
197
|
-
def is_prerelease(self):
|
198
|
-
return False
|
199
|
-
|
200
|
-
@property
|
201
|
-
def is_postrelease(self):
|
202
|
-
return False
|
203
|
-
|
204
|
-
|
205
|
-
_legacy_version_component_re = re.compile(
|
206
|
-
r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE,
|
207
|
-
)
|
208
|
-
|
209
|
-
_legacy_version_replacement_map = {
|
210
|
-
"pre": "c", "preview": "c", "-": "final-", "rc": "c", "dev": "@",
|
211
|
-
}
|
212
|
-
|
213
|
-
|
214
|
-
def _parse_version_parts(s):
|
215
|
-
for part in _legacy_version_component_re.split(s):
|
216
|
-
part = _legacy_version_replacement_map.get(part, part)
|
217
|
-
|
218
|
-
if not part or part == ".":
|
219
|
-
continue
|
220
|
-
|
221
|
-
if part[:1] in "0123456789":
|
222
|
-
# pad for numeric comparison
|
223
|
-
yield part.zfill(8)
|
224
|
-
else:
|
225
|
-
yield "*" + part
|
226
|
-
|
227
|
-
# ensure that alpha/beta/candidate are before final
|
228
|
-
yield "*final"
|
229
|
-
|
230
|
-
|
231
|
-
def _legacy_cmpkey(version):
|
232
|
-
# We hardcode an epoch of -1 here. A PEP 440 version can only have an epoch
|
233
|
-
# greater than or equal to 0. This will effectively put the LegacyVersion,
|
234
|
-
# which uses the defacto standard originally implemented by setuptools,
|
235
|
-
# as before all PEP 440 versions.
|
236
|
-
epoch = -1
|
237
|
-
|
238
|
-
# This scheme is taken from pkg_resources.parse_version setuptools prior to
|
239
|
-
# its adoption of the packaging library.
|
240
|
-
parts = []
|
241
|
-
for part in _parse_version_parts(version.lower()):
|
242
|
-
if part.startswith("*"):
|
243
|
-
# remove "-" before a prerelease tag
|
244
|
-
if part < "*final":
|
245
|
-
while parts and parts[-1] == "*final-":
|
246
|
-
parts.pop()
|
247
|
-
|
248
|
-
# remove trailing zeros from each series of numeric parts
|
249
|
-
while parts and parts[-1] == "00000000":
|
250
|
-
parts.pop()
|
251
|
-
|
252
|
-
parts.append(part)
|
253
|
-
parts = tuple(parts)
|
254
|
-
|
255
|
-
return epoch, parts
|
256
|
-
|
257
|
-
|
258
|
-
# Deliberately not anchored to the start and end of the string, to make it
|
259
|
-
# easier for 3rd party code to reuse
|
260
|
-
VERSION_PATTERN = r"""
|
261
|
-
v?
|
262
|
-
(?:
|
263
|
-
(?:(?P<epoch>[0-9]+)!)? # epoch
|
264
|
-
(?P<release>[0-9]+(?:\.[0-9]+)*) # release segment
|
265
|
-
(?P<pre> # pre-release
|
266
|
-
[-_\.]?
|
267
|
-
(?P<pre_l>(a|b|c|rc|alpha|beta|pre|preview))
|
268
|
-
[-_\.]?
|
269
|
-
(?P<pre_n>[0-9]+)?
|
270
|
-
)?
|
271
|
-
(?P<post> # post release
|
272
|
-
(?:-(?P<post_n1>[0-9]+))
|
273
|
-
|
|
274
|
-
(?:
|
275
|
-
[-_\.]?
|
276
|
-
(?P<post_l>post|rev|r)
|
277
|
-
[-_\.]?
|
278
|
-
(?P<post_n2>[0-9]+)?
|
279
|
-
)
|
280
|
-
)?
|
281
|
-
(?P<dev> # dev release
|
282
|
-
[-_\.]?
|
283
|
-
(?P<dev_l>dev)
|
284
|
-
[-_\.]?
|
285
|
-
(?P<dev_n>[0-9]+)?
|
286
|
-
)?
|
287
|
-
)
|
288
|
-
(?:\+(?P<local>[a-z0-9]+(?:[-_\.][a-z0-9]+)*))? # local version
|
289
|
-
"""
|
290
|
-
|
291
|
-
|
292
|
-
class Version(_BaseVersion):
|
293
|
-
|
294
|
-
_regex = re.compile(
|
295
|
-
r"^\s*" + VERSION_PATTERN + r"\s*$",
|
296
|
-
re.VERBOSE | re.IGNORECASE,
|
297
|
-
)
|
298
|
-
|
299
|
-
def __init__(self, version):
|
300
|
-
# Validate the version and parse it into pieces
|
301
|
-
match = self._regex.search(version)
|
302
|
-
if not match:
|
303
|
-
raise InvalidVersion("Invalid version: '{0}'".format(version))
|
304
|
-
|
305
|
-
# Store the parsed out pieces of the version
|
306
|
-
self._version = _Version(
|
307
|
-
epoch=int(match.group("epoch")) if match.group("epoch") else 0,
|
308
|
-
release=tuple(int(i) for i in match.group("release").split(".")),
|
309
|
-
pre=_parse_letter_version(
|
310
|
-
match.group("pre_l"),
|
311
|
-
match.group("pre_n"),
|
312
|
-
),
|
313
|
-
post=_parse_letter_version(
|
314
|
-
match.group("post_l"),
|
315
|
-
match.group("post_n1") or match.group("post_n2"),
|
316
|
-
),
|
317
|
-
dev=_parse_letter_version(
|
318
|
-
match.group("dev_l"),
|
319
|
-
match.group("dev_n"),
|
320
|
-
),
|
321
|
-
local=_parse_local_version(match.group("local")),
|
322
|
-
)
|
323
|
-
|
324
|
-
# Generate a key which will be used for sorting
|
325
|
-
self._key = _cmpkey(
|
326
|
-
self._version.epoch,
|
327
|
-
self._version.release,
|
328
|
-
self._version.pre,
|
329
|
-
self._version.post,
|
330
|
-
self._version.dev,
|
331
|
-
self._version.local,
|
332
|
-
)
|
333
|
-
|
334
|
-
def __repr__(self):
|
335
|
-
return "<Version({0})>".format(repr(str(self)))
|
336
|
-
|
337
|
-
def __str__(self):
|
338
|
-
parts = []
|
339
|
-
|
340
|
-
# Epoch
|
341
|
-
if self._version.epoch != 0:
|
342
|
-
parts.append("{0}!".format(self._version.epoch))
|
343
|
-
|
344
|
-
# Release segment
|
345
|
-
parts.append(".".join(str(x) for x in self._version.release))
|
346
|
-
|
347
|
-
# Pre-release
|
348
|
-
if self._version.pre is not None:
|
349
|
-
parts.append("".join(str(x) for x in self._version.pre))
|
350
|
-
|
351
|
-
# Post-release
|
352
|
-
if self._version.post is not None:
|
353
|
-
parts.append(".post{0}".format(self._version.post[1]))
|
354
|
-
|
355
|
-
# Development release
|
356
|
-
if self._version.dev is not None:
|
357
|
-
parts.append(".dev{0}".format(self._version.dev[1]))
|
358
|
-
|
359
|
-
# Local version segment
|
360
|
-
if self._version.local is not None:
|
361
|
-
parts.append(
|
362
|
-
"+{0}".format(".".join(str(x) for x in self._version.local))
|
363
|
-
)
|
364
|
-
|
365
|
-
return "".join(parts)
|
366
|
-
|
367
|
-
@property
|
368
|
-
def public(self):
|
369
|
-
return str(self).split("+", 1)[0]
|
370
|
-
|
371
|
-
@property
|
372
|
-
def base_version(self):
|
373
|
-
parts = []
|
374
|
-
|
375
|
-
# Epoch
|
376
|
-
if self._version.epoch != 0:
|
377
|
-
parts.append("{0}!".format(self._version.epoch))
|
378
|
-
|
379
|
-
# Release segment
|
380
|
-
parts.append(".".join(str(x) for x in self._version.release))
|
381
|
-
|
382
|
-
return "".join(parts)
|
383
|
-
|
384
|
-
@property
|
385
|
-
def local(self):
|
386
|
-
version_string = str(self)
|
387
|
-
if "+" in version_string:
|
388
|
-
return version_string.split("+", 1)[1]
|
389
|
-
|
390
|
-
@property
|
391
|
-
def is_prerelease(self):
|
392
|
-
return bool(self._version.dev or self._version.pre)
|
393
|
-
|
394
|
-
@property
|
395
|
-
def is_postrelease(self):
|
396
|
-
return bool(self._version.post)
|
397
|
-
|
398
|
-
@property
|
399
|
-
def version(self) -> tuple:
|
400
|
-
"""
|
401
|
-
PATCH: Return version tuple for backward-compatibility.
|
402
|
-
"""
|
403
|
-
return self._version.release
|
404
|
-
|
405
|
-
|
406
|
-
def _parse_letter_version(letter, number):
|
407
|
-
if letter:
|
408
|
-
# We assume there is an implicit 0 in a pre-release if there is
|
409
|
-
# no numeral associated with it.
|
410
|
-
if number is None:
|
411
|
-
number = 0
|
412
|
-
|
413
|
-
# We normalize any letters to their lower-case form
|
414
|
-
letter = letter.lower()
|
415
|
-
|
416
|
-
# We consider some words to be alternate spellings of other words and
|
417
|
-
# in those cases we want to normalize the spellings to our preferred
|
418
|
-
# spelling.
|
419
|
-
if letter == "alpha":
|
420
|
-
letter = "a"
|
421
|
-
elif letter == "beta":
|
422
|
-
letter = "b"
|
423
|
-
elif letter in ["c", "pre", "preview"]:
|
424
|
-
letter = "rc"
|
425
|
-
elif letter in ["rev", "r"]:
|
426
|
-
letter = "post"
|
427
|
-
|
428
|
-
return letter, int(number)
|
429
|
-
if not letter and number:
|
430
|
-
# We assume that if we are given a number but not given a letter,
|
431
|
-
# then this is using the implicit post release syntax (e.g., 1.0-1)
|
432
|
-
letter = "post"
|
433
|
-
|
434
|
-
return letter, int(number)
|
435
|
-
|
436
|
-
|
437
|
-
_local_version_seperators = re.compile(r"[\._-]")
|
438
|
-
|
439
|
-
|
440
|
-
def _parse_local_version(local):
|
441
|
-
"""
|
442
|
-
Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
|
443
|
-
"""
|
444
|
-
if local is not None:
|
445
|
-
return tuple(
|
446
|
-
part.lower() if not part.isdigit() else int(part)
|
447
|
-
for part in _local_version_seperators.split(local)
|
448
|
-
)
|
449
|
-
|
450
|
-
|
451
|
-
def _cmpkey(epoch, release, pre, post, dev, local):
|
452
|
-
# When we compare a release version, we want to compare it with all of the
|
453
|
-
# trailing zeros removed. So we'll use a reverse the list, drop all the now
|
454
|
-
# leading zeros until we come to something non-zero, then take the rest,
|
455
|
-
# re-reverse it back into the correct order, and make it a tuple and use
|
456
|
-
# that for our sorting key.
|
457
|
-
release = tuple(
|
458
|
-
reversed(list(
|
459
|
-
itertools.dropwhile(
|
460
|
-
lambda x: x == 0,
|
461
|
-
reversed(release),
|
462
|
-
)
|
463
|
-
))
|
464
|
-
)
|
465
|
-
|
466
|
-
# We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
|
467
|
-
# We'll do this by abusing the pre-segment, but we _only_ want to do this
|
468
|
-
# if there is no pre- or a post-segment. If we have one of those, then
|
469
|
-
# the normal sorting rules will handle this case correctly.
|
470
|
-
if pre is None and post is None and dev is not None:
|
471
|
-
pre = -Infinity
|
472
|
-
# Versions without a pre-release (except as noted above) should sort after
|
473
|
-
# those with one.
|
474
|
-
elif pre is None:
|
475
|
-
pre = Infinity
|
476
|
-
|
477
|
-
# Versions without a post-segment should sort before those with one.
|
478
|
-
if post is None:
|
479
|
-
post = -Infinity
|
480
|
-
|
481
|
-
# Versions without a development segment should sort after those with one.
|
482
|
-
if dev is None:
|
483
|
-
dev = Infinity
|
484
|
-
|
485
|
-
if local is None:
|
486
|
-
# Versions without a local segment should sort before those with one.
|
487
|
-
local = -Infinity
|
488
|
-
else:
|
489
|
-
# Versions with a local segment need that segment parsed to implement
|
490
|
-
# the sorting rules in PEP440.
|
491
|
-
# - Alphanumeric segments sort before numeric segments
|
492
|
-
# - Alphanumeric segments sort lexicographically
|
493
|
-
# - Numeric segments sort numerically
|
494
|
-
# - Shorter versions sort before longer versions when the prefixes
|
495
|
-
# match exactly
|
496
|
-
local = tuple(
|
497
|
-
(i, "") if isinstance(i, int) else (-Infinity, i)
|
498
|
-
for i in local
|
499
|
-
)
|
500
|
-
|
501
|
-
return epoch, release, pre, post, dev, local
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|