crate 1.0.0.dev1__py3-none-any.whl → 1.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- crate/client/__init__.py +4 -3
- crate/client/blob.py +9 -7
- crate/client/connection.py +58 -52
- crate/client/converter.py +15 -10
- crate/client/cursor.py +55 -51
- crate/client/exceptions.py +5 -3
- crate/client/http.py +192 -160
- crate/testing/__init__.py +0 -1
- crate/testing/layer.py +140 -102
- crate/testing/util.py +80 -5
- {crate-1.0.0.dev1.dist-info → crate-1.0.1.dist-info}/LICENSE +0 -70
- {crate-1.0.0.dev1.dist-info → crate-1.0.1.dist-info}/METADATA +14 -16
- {crate-1.0.0.dev1.dist-info → crate-1.0.1.dist-info}/NOTICE +1 -1
- crate-1.0.1.dist-info/RECORD +17 -0
- {crate-1.0.0.dev1.dist-info → crate-1.0.1.dist-info}/WHEEL +1 -1
- crate/client/test_connection.py +0 -98
- crate/client/test_cursor.py +0 -341
- crate/client/test_exceptions.py +0 -14
- crate/client/test_http.py +0 -678
- crate/client/test_util.py +0 -69
- crate/client/tests.py +0 -340
- crate/testing/settings.py +0 -51
- crate/testing/test_datetime_old.py +0 -90
- crate/testing/test_layer.py +0 -290
- crate/testing/tests.py +0 -34
- crate-1.0.0.dev1-py3.9-nspkg.pth +0 -1
- crate-1.0.0.dev1.dist-info/RECORD +0 -29
- crate-1.0.0.dev1.dist-info/namespace_packages.txt +0 -1
- {crate-1.0.0.dev1.dist-info → crate-1.0.1.dist-info}/top_level.txt +0 -0
crate/testing/__init__.py
CHANGED
@@ -1 +0,0 @@
|
|
1
|
-
# package
|
crate/testing/layer.py
CHANGED
@@ -19,38 +19,44 @@
|
|
19
19
|
# with Crate these terms will supersede the license and you may use the
|
20
20
|
# software solely pursuant to the terms of the relevant commercial agreement.
|
21
21
|
|
22
|
+
# ruff: noqa: S603 # `subprocess` call: check for execution of untrusted input
|
23
|
+
# ruff: noqa: S202 # Uses of `tarfile.extractall()`
|
24
|
+
|
25
|
+
import io
|
26
|
+
import json
|
27
|
+
import logging
|
22
28
|
import os
|
23
29
|
import re
|
24
|
-
import sys
|
25
|
-
import time
|
26
|
-
import json
|
27
|
-
import urllib3
|
28
|
-
import tempfile
|
29
30
|
import shutil
|
30
31
|
import subprocess
|
32
|
+
import sys
|
31
33
|
import tarfile
|
32
|
-
import
|
34
|
+
import tempfile
|
33
35
|
import threading
|
34
|
-
import
|
36
|
+
import time
|
37
|
+
|
38
|
+
import urllib3
|
35
39
|
|
36
40
|
try:
|
37
41
|
from urllib.request import urlopen
|
38
42
|
except ImportError:
|
39
|
-
from urllib import urlopen
|
43
|
+
from urllib import urlopen # type: ignore[attr-defined,no-redef]
|
40
44
|
|
41
45
|
|
42
46
|
log = logging.getLogger(__name__)
|
43
47
|
|
44
48
|
|
45
|
-
CRATE_CONFIG_ERROR =
|
49
|
+
CRATE_CONFIG_ERROR = (
|
50
|
+
'crate_config must point to a folder or to a file named "crate.yml"'
|
51
|
+
)
|
46
52
|
HTTP_ADDRESS_RE = re.compile(
|
47
|
-
r
|
48
|
-
|
49
|
-
r
|
50
|
-
r
|
51
|
-
r
|
52
|
-
r
|
53
|
-
|
53
|
+
r".*\[(http|.*HttpServer.*)\s*] \[.*\] .*"
|
54
|
+
"publish_address {"
|
55
|
+
r"(?:inet\[[\w\d\.-]*/|\[)?"
|
56
|
+
r"(?:[\w\d\.-]+/)?"
|
57
|
+
r"(?P<addr>[\d\.:]+)"
|
58
|
+
r"(?:\])?"
|
59
|
+
"}"
|
54
60
|
)
|
55
61
|
|
56
62
|
|
@@ -61,18 +67,22 @@ def http_url_from_host_port(host, port):
|
|
61
67
|
port = int(port)
|
62
68
|
except ValueError:
|
63
69
|
return None
|
64
|
-
return
|
70
|
+
return "{}:{}".format(prepend_http(host), port)
|
65
71
|
return None
|
66
72
|
|
67
73
|
|
68
74
|
def prepend_http(host):
|
69
|
-
if not re.match(r
|
70
|
-
return
|
75
|
+
if not re.match(r"^https?\:\/\/.*", host):
|
76
|
+
return "http://{}".format(host)
|
71
77
|
return host
|
72
78
|
|
73
79
|
|
74
80
|
def _download_and_extract(uri, directory):
|
75
|
-
sys.stderr.write(
|
81
|
+
sys.stderr.write(
|
82
|
+
"\nINFO: Downloading CrateDB archive from {} into {}".format(
|
83
|
+
uri, directory
|
84
|
+
)
|
85
|
+
)
|
76
86
|
sys.stderr.flush()
|
77
87
|
with io.BytesIO(urlopen(uri).read()) as tmpfile:
|
78
88
|
with tarfile.open(fileobj=tmpfile) as t:
|
@@ -82,19 +92,18 @@ def _download_and_extract(uri, directory):
|
|
82
92
|
def wait_for_http_url(log, timeout=30, verbose=False):
|
83
93
|
start = time.monotonic()
|
84
94
|
while True:
|
85
|
-
line = log.readline().decode(
|
95
|
+
line = log.readline().decode("utf-8").strip()
|
86
96
|
elapsed = time.monotonic() - start
|
87
97
|
if verbose:
|
88
|
-
sys.stderr.write(
|
98
|
+
sys.stderr.write("[{:>4.1f}s]{}\n".format(elapsed, line))
|
89
99
|
m = HTTP_ADDRESS_RE.match(line)
|
90
100
|
if m:
|
91
|
-
return prepend_http(m.group(
|
101
|
+
return prepend_http(m.group("addr"))
|
92
102
|
elif elapsed > timeout:
|
93
103
|
return None
|
94
104
|
|
95
105
|
|
96
106
|
class OutputMonitor:
|
97
|
-
|
98
107
|
def __init__(self):
|
99
108
|
self.consumers = []
|
100
109
|
|
@@ -105,7 +114,9 @@ class OutputMonitor:
|
|
105
114
|
|
106
115
|
def start(self, proc):
|
107
116
|
self._stop_out_thread = threading.Event()
|
108
|
-
self._out_thread = threading.Thread(
|
117
|
+
self._out_thread = threading.Thread(
|
118
|
+
target=self.consume, args=(proc.stdout,)
|
119
|
+
)
|
109
120
|
self._out_thread.daemon = True
|
110
121
|
self._out_thread.start()
|
111
122
|
|
@@ -116,7 +127,6 @@ class OutputMonitor:
|
|
116
127
|
|
117
128
|
|
118
129
|
class LineBuffer:
|
119
|
-
|
120
130
|
def __init__(self):
|
121
131
|
self.lines = []
|
122
132
|
|
@@ -124,7 +134,7 @@ class LineBuffer:
|
|
124
134
|
self.lines.append(line.strip())
|
125
135
|
|
126
136
|
|
127
|
-
class CrateLayer
|
137
|
+
class CrateLayer:
|
128
138
|
"""
|
129
139
|
This layer starts a Crate server.
|
130
140
|
"""
|
@@ -135,14 +145,16 @@ class CrateLayer(object):
|
|
135
145
|
wait_interval = 0.2
|
136
146
|
|
137
147
|
@staticmethod
|
138
|
-
def from_uri(
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
148
|
+
def from_uri(
|
149
|
+
uri,
|
150
|
+
name,
|
151
|
+
http_port="4200-4299",
|
152
|
+
transport_port="4300-4399",
|
153
|
+
settings=None,
|
154
|
+
directory=None,
|
155
|
+
cleanup=True,
|
156
|
+
verbose=False,
|
157
|
+
):
|
146
158
|
"""Download the Crate tarball from a URI and create a CrateLayer
|
147
159
|
|
148
160
|
:param uri: The uri that points to the Crate tarball
|
@@ -158,11 +170,14 @@ class CrateLayer(object):
|
|
158
170
|
"""
|
159
171
|
directory = directory or tempfile.mkdtemp()
|
160
172
|
filename = os.path.basename(uri)
|
161
|
-
crate_dir = re.sub(r
|
173
|
+
crate_dir = re.sub(r"\.tar(\.gz)?$", "", filename)
|
162
174
|
crate_home = os.path.join(directory, crate_dir)
|
163
175
|
|
164
176
|
if os.path.exists(crate_home):
|
165
|
-
sys.stderr.write(
|
177
|
+
sys.stderr.write(
|
178
|
+
"\nWARNING: Not extracting CrateDB tarball"
|
179
|
+
" because folder already exists"
|
180
|
+
)
|
166
181
|
sys.stderr.flush()
|
167
182
|
else:
|
168
183
|
_download_and_extract(uri, directory)
|
@@ -173,29 +188,33 @@ class CrateLayer(object):
|
|
173
188
|
port=http_port,
|
174
189
|
transport_port=transport_port,
|
175
190
|
settings=settings,
|
176
|
-
verbose=verbose
|
191
|
+
verbose=verbose,
|
192
|
+
)
|
177
193
|
if cleanup:
|
178
194
|
tearDown = layer.tearDown
|
179
195
|
|
180
196
|
def new_teardown(*args, **kws):
|
181
197
|
shutil.rmtree(directory)
|
182
198
|
tearDown(*args, **kws)
|
183
|
-
|
199
|
+
|
200
|
+
layer.tearDown = new_teardown # type: ignore[method-assign]
|
184
201
|
return layer
|
185
202
|
|
186
|
-
def __init__(
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
203
|
+
def __init__(
|
204
|
+
self,
|
205
|
+
name,
|
206
|
+
crate_home,
|
207
|
+
crate_config=None,
|
208
|
+
port=None,
|
209
|
+
keepRunning=False,
|
210
|
+
transport_port=None,
|
211
|
+
crate_exec=None,
|
212
|
+
cluster_name=None,
|
213
|
+
host="127.0.0.1",
|
214
|
+
settings=None,
|
215
|
+
verbose=False,
|
216
|
+
env=None,
|
217
|
+
):
|
199
218
|
"""
|
200
219
|
:param name: layer name, is also used as the cluser name
|
201
220
|
:param crate_home: path to home directory of the crate installation
|
@@ -216,52 +235,69 @@ class CrateLayer(object):
|
|
216
235
|
self.__name__ = name
|
217
236
|
if settings and isinstance(settings, dict):
|
218
237
|
# extra settings may override host/port specification!
|
219
|
-
self.http_url = http_url_from_host_port(
|
220
|
-
|
238
|
+
self.http_url = http_url_from_host_port(
|
239
|
+
settings.get("network.host", host),
|
240
|
+
settings.get("http.port", port),
|
241
|
+
)
|
221
242
|
else:
|
222
243
|
self.http_url = http_url_from_host_port(host, port)
|
223
244
|
|
224
245
|
self.process = None
|
225
246
|
self.verbose = verbose
|
226
247
|
self.env = env or {}
|
227
|
-
self.env.setdefault(
|
228
|
-
self.env.setdefault(
|
248
|
+
self.env.setdefault("CRATE_USE_IPV4", "true")
|
249
|
+
self.env.setdefault("JAVA_HOME", os.environ.get("JAVA_HOME", ""))
|
229
250
|
self._stdout_consumers = []
|
230
251
|
self.conn_pool = urllib3.PoolManager(num_pools=1)
|
231
252
|
|
232
253
|
crate_home = os.path.abspath(crate_home)
|
233
254
|
if crate_exec is None:
|
234
|
-
start_script =
|
235
|
-
crate_exec = os.path.join(crate_home,
|
255
|
+
start_script = "crate.bat" if sys.platform == "win32" else "crate"
|
256
|
+
crate_exec = os.path.join(crate_home, "bin", start_script)
|
236
257
|
if crate_config is None:
|
237
|
-
crate_config = os.path.join(crate_home,
|
238
|
-
elif (
|
239
|
-
|
258
|
+
crate_config = os.path.join(crate_home, "config", "crate.yml")
|
259
|
+
elif (
|
260
|
+
os.path.isfile(crate_config)
|
261
|
+
and os.path.basename(crate_config) != "crate.yml"
|
262
|
+
):
|
240
263
|
raise ValueError(CRATE_CONFIG_ERROR)
|
241
264
|
if cluster_name is None:
|
242
|
-
cluster_name = "Testing{0}".format(port or
|
243
|
-
settings = self.create_settings(
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
265
|
+
cluster_name = "Testing{0}".format(port or "Dynamic")
|
266
|
+
settings = self.create_settings(
|
267
|
+
crate_config,
|
268
|
+
cluster_name,
|
269
|
+
name,
|
270
|
+
host,
|
271
|
+
port or "4200-4299",
|
272
|
+
transport_port or "4300-4399",
|
273
|
+
settings,
|
274
|
+
)
|
250
275
|
# ES 5 cannot parse 'True'/'False' as booleans so convert to lowercase
|
251
|
-
start_cmd = (crate_exec,
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
276
|
+
start_cmd = (crate_exec,) + tuple(
|
277
|
+
[
|
278
|
+
"-C%s=%s"
|
279
|
+
% (
|
280
|
+
(key, str(value).lower())
|
281
|
+
if isinstance(value, bool)
|
282
|
+
else (key, value)
|
283
|
+
)
|
284
|
+
for key, value in settings.items()
|
285
|
+
]
|
286
|
+
)
|
287
|
+
|
288
|
+
self._wd = wd = os.path.join(CrateLayer.tmpdir, "crate_layer", name)
|
289
|
+
self.start_cmd = start_cmd + ("-Cpath.data=%s" % wd,)
|
290
|
+
|
291
|
+
def create_settings(
|
292
|
+
self,
|
293
|
+
crate_config,
|
294
|
+
cluster_name,
|
295
|
+
node_name,
|
296
|
+
host,
|
297
|
+
http_port,
|
298
|
+
transport_port,
|
299
|
+
further_settings=None,
|
300
|
+
):
|
265
301
|
settings = {
|
266
302
|
"discovery.type": "zen",
|
267
303
|
"discovery.initial_state_timeout": 0,
|
@@ -294,20 +330,23 @@ class CrateLayer(object):
|
|
294
330
|
|
295
331
|
def start(self):
|
296
332
|
self._clean()
|
297
|
-
self.process = subprocess.Popen(
|
298
|
-
|
299
|
-
|
333
|
+
self.process = subprocess.Popen(
|
334
|
+
self.start_cmd, env=self.env, stdout=subprocess.PIPE
|
335
|
+
)
|
300
336
|
returncode = self.process.poll()
|
301
337
|
if returncode is not None:
|
302
338
|
raise SystemError(
|
303
|
-
|
304
|
-
|
339
|
+
"Failed to start server rc={0} cmd={1}".format(
|
340
|
+
returncode, self.start_cmd
|
341
|
+
)
|
305
342
|
)
|
306
343
|
|
307
344
|
if not self.http_url:
|
308
345
|
# try to read http_url from startup logs
|
309
346
|
# this is necessary if no static port is assigned
|
310
|
-
self.http_url = wait_for_http_url(
|
347
|
+
self.http_url = wait_for_http_url(
|
348
|
+
self.process.stdout, verbose=self.verbose
|
349
|
+
)
|
311
350
|
|
312
351
|
self.monitor = OutputMonitor()
|
313
352
|
self.monitor.start(self.process)
|
@@ -315,10 +354,10 @@ class CrateLayer(object):
|
|
315
354
|
if not self.http_url:
|
316
355
|
self.stop()
|
317
356
|
else:
|
318
|
-
sys.stderr.write(
|
357
|
+
sys.stderr.write("HTTP: {}\n".format(self.http_url))
|
319
358
|
self._wait_for_start()
|
320
359
|
self._wait_for_master()
|
321
|
-
sys.stderr.write(
|
360
|
+
sys.stderr.write("\nCrate instance ready.\n")
|
322
361
|
|
323
362
|
def stop(self):
|
324
363
|
self.conn_pool.clear()
|
@@ -352,10 +391,9 @@ class CrateLayer(object):
|
|
352
391
|
for line in line_buf.lines:
|
353
392
|
log.error(line)
|
354
393
|
self.stop()
|
355
|
-
raise SystemError(
|
356
|
-
|
357
|
-
|
358
|
-
time.sleep(self.wait_interval)
|
394
|
+
raise SystemError("Failed to start Crate instance in time.")
|
395
|
+
sys.stderr.write(".")
|
396
|
+
time.sleep(self.wait_interval)
|
359
397
|
|
360
398
|
self.monitor.consumers.remove(line_buf)
|
361
399
|
|
@@ -367,7 +405,7 @@ class CrateLayer(object):
|
|
367
405
|
# after the layer starts don't result in 503
|
368
406
|
def validator():
|
369
407
|
try:
|
370
|
-
resp = self.conn_pool.request(
|
408
|
+
resp = self.conn_pool.request("HEAD", self.http_url)
|
371
409
|
return resp.status == 200
|
372
410
|
except Exception:
|
373
411
|
return False
|
@@ -379,12 +417,12 @@ class CrateLayer(object):
|
|
379
417
|
|
380
418
|
def validator():
|
381
419
|
resp = self.conn_pool.urlopen(
|
382
|
-
|
383
|
-
|
384
|
-
headers={
|
385
|
-
body='{"stmt": "select master_node from sys.cluster"}'
|
420
|
+
"POST",
|
421
|
+
"{server}/_sql".format(server=self.http_url),
|
422
|
+
headers={"Content-Type": "application/json"},
|
423
|
+
body='{"stmt": "select master_node from sys.cluster"}',
|
386
424
|
)
|
387
|
-
data = json.loads(resp.data.decode(
|
388
|
-
return resp.status == 200 and data[
|
425
|
+
data = json.loads(resp.data.decode("utf-8"))
|
426
|
+
return resp.status == 200 and data["rows"][0][0]
|
389
427
|
|
390
428
|
self._wait_for(validator)
|
crate/testing/util.py
CHANGED
@@ -1,4 +1,75 @@
|
|
1
|
-
|
1
|
+
# -*- coding: utf-8; -*-
|
2
|
+
#
|
3
|
+
# Licensed to CRATE Technology GmbH ("Crate") under one or more contributor
|
4
|
+
# license agreements. See the NOTICE file distributed with this work for
|
5
|
+
# additional information regarding copyright ownership. Crate licenses
|
6
|
+
# this file to you under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License. You may
|
8
|
+
# obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
14
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
15
|
+
# License for the specific language governing permissions and limitations
|
16
|
+
# under the License.
|
17
|
+
#
|
18
|
+
# However, if you have executed another commercial license agreement
|
19
|
+
# with Crate these terms will supersede the license and you may use the
|
20
|
+
# software solely pursuant to the terms of the relevant commercial agreement.
|
21
|
+
import unittest
|
22
|
+
|
23
|
+
|
24
|
+
class ClientMocked:
|
25
|
+
active_servers = ["http://localhost:4200"]
|
26
|
+
|
27
|
+
def __init__(self):
|
28
|
+
self.response = {}
|
29
|
+
self._server_infos = ("http://localhost:4200", "my server", "2.0.0")
|
30
|
+
|
31
|
+
def sql(self, stmt=None, parameters=None, bulk_parameters=None):
|
32
|
+
return self.response
|
33
|
+
|
34
|
+
def server_infos(self, server):
|
35
|
+
return self._server_infos
|
36
|
+
|
37
|
+
def set_next_response(self, response):
|
38
|
+
self.response = response
|
39
|
+
|
40
|
+
def set_next_server_infos(self, server, server_name, version):
|
41
|
+
self._server_infos = (server, server_name, version)
|
42
|
+
|
43
|
+
def close(self):
|
44
|
+
pass
|
45
|
+
|
46
|
+
|
47
|
+
class ParametrizedTestCase(unittest.TestCase):
|
48
|
+
"""
|
49
|
+
TestCase classes that want to be parametrized should
|
50
|
+
inherit from this class.
|
51
|
+
|
52
|
+
https://eli.thegreenplace.net/2011/08/02/python-unit-testing-parametrized-test-cases
|
53
|
+
"""
|
54
|
+
|
55
|
+
def __init__(self, methodName="runTest", param=None):
|
56
|
+
super(ParametrizedTestCase, self).__init__(methodName)
|
57
|
+
self.param = param
|
58
|
+
|
59
|
+
@staticmethod
|
60
|
+
def parametrize(testcase_klass, param=None):
|
61
|
+
"""Create a suite containing all tests taken from the given
|
62
|
+
subclass, passing them the parameter 'param'.
|
63
|
+
"""
|
64
|
+
testloader = unittest.TestLoader()
|
65
|
+
testnames = testloader.getTestCaseNames(testcase_klass)
|
66
|
+
suite = unittest.TestSuite()
|
67
|
+
for name in testnames:
|
68
|
+
suite.addTest(testcase_klass(name, param=param))
|
69
|
+
return suite
|
70
|
+
|
71
|
+
|
72
|
+
class ExtraAssertions(unittest.TestCase):
|
2
73
|
"""
|
3
74
|
Additional assert methods for unittest.
|
4
75
|
|
@@ -12,9 +83,13 @@ class ExtraAssertions:
|
|
12
83
|
r = issubclass(cls, superclass)
|
13
84
|
except TypeError:
|
14
85
|
if not isinstance(cls, type):
|
15
|
-
self.fail(
|
16
|
-
|
86
|
+
self.fail(
|
87
|
+
self._formatMessage(msg, "%r is not a class" % (cls,))
|
88
|
+
)
|
17
89
|
raise
|
18
90
|
if not r:
|
19
|
-
self.fail(
|
20
|
-
|
91
|
+
self.fail(
|
92
|
+
self._formatMessage(
|
93
|
+
msg, "%r is not a subclass of %r" % (cls, superclass)
|
94
|
+
)
|
95
|
+
)
|
@@ -176,73 +176,3 @@
|
|
176
176
|
of your accepting any such warranty or additional liability.
|
177
177
|
|
178
178
|
END OF TERMS AND CONDITIONS
|
179
|
-
|
180
|
-
APPENDIX: How to apply the Apache License to your work.
|
181
|
-
|
182
|
-
To apply the Apache License to your work, attach the following
|
183
|
-
boilerplate notice, with the fields enclosed by brackets "[]"
|
184
|
-
replaced with your own identifying information. (Don't include
|
185
|
-
the brackets!) The text should be enclosed in the appropriate
|
186
|
-
comment syntax for the file format. We also recommend that a
|
187
|
-
file or class name and description of purpose be included on the
|
188
|
-
same "printed page" as the copyright notice for easier
|
189
|
-
identification within third-party archives.
|
190
|
-
|
191
|
-
Copyright [yyyy] [name of copyright owner]
|
192
|
-
|
193
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
194
|
-
you may not use this file except in compliance with the License.
|
195
|
-
You may obtain a copy of the License at
|
196
|
-
|
197
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
198
|
-
|
199
|
-
Unless required by applicable law or agreed to in writing, software
|
200
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
201
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
202
|
-
See the License for the specific language governing permissions and
|
203
|
-
limitations under the License.
|
204
|
-
|
205
|
-
|
206
|
-
===============================================================================
|
207
|
-
|
208
|
-
For the `docs` directory:
|
209
|
-
|
210
|
-
The source files for the documentation are licensed under the Apache License
|
211
|
-
Version 2.0. These source files are used by the project maintainers to build
|
212
|
-
online documentation for end-users:
|
213
|
-
|
214
|
-
<https://crate.io/docs/clients/python/en/latest/>
|
215
|
-
|
216
|
-
If you want to make contributions to the documentation, it may be necessary for
|
217
|
-
you to build the documentation yourself by following the instructions in the
|
218
|
-
`DEVELOP.rst` file. If you do this, a number of third-party software components
|
219
|
-
are necessary.
|
220
|
-
|
221
|
-
We do not ship the source code for these optional third-party software
|
222
|
-
components or their dependencies, so we cannot make any guarantees about the
|
223
|
-
licensing status of these components.
|
224
|
-
|
225
|
-
However, for convenience, the documentation build system explicitly references
|
226
|
-
the following software components (grouped by license):
|
227
|
-
|
228
|
-
PSF License:
|
229
|
-
|
230
|
-
- Python 3 <https://docs.python.org/3/license.html>
|
231
|
-
|
232
|
-
MIT License:
|
233
|
-
|
234
|
-
- pip <https://pypi.org/project/pip/>
|
235
|
-
- setuptools <https://pypi.org/project/setuptools/>
|
236
|
-
- sphinx-autobuild <https://pypi.org/project/sphinx-autobuild/>
|
237
|
-
|
238
|
-
BSD License:
|
239
|
-
|
240
|
-
- alabaster <https://pypi.org/project/alabaster/>
|
241
|
-
- sphinx <https://pypi.org/project/Sphinx/>
|
242
|
-
|
243
|
-
Apache License 2.0:
|
244
|
-
|
245
|
-
- crate-docs-theme <https://pypi.org/project/crate-docs-theme/>
|
246
|
-
|
247
|
-
Please note that each of these components may specify its own dependencies and
|
248
|
-
those dependencies may be licensed differently.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: crate
|
3
|
-
Version: 1.0.
|
3
|
+
Version: 1.0.1
|
4
4
|
Summary: CrateDB Python Client
|
5
5
|
Home-page: https://github.com/crate/crate-python
|
6
6
|
Author: Crate.io
|
@@ -21,6 +21,7 @@ Classifier: Programming Language :: Python :: 3.9
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.10
|
22
22
|
Classifier: Programming Language :: Python :: 3.11
|
23
23
|
Classifier: Programming Language :: Python :: 3.12
|
24
|
+
Classifier: Programming Language :: Python :: 3.13
|
24
25
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
25
26
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
26
27
|
Classifier: Topic :: Database
|
@@ -28,25 +29,24 @@ Requires-Python: >=3.6
|
|
28
29
|
Description-Content-Type: text/x-rst
|
29
30
|
License-File: LICENSE
|
30
31
|
License-File: NOTICE
|
31
|
-
Requires-Dist: urllib3
|
32
|
-
Requires-Dist: verlib2
|
32
|
+
Requires-Dist: urllib3
|
33
|
+
Requires-Dist: verlib2
|
33
34
|
Provides-Extra: doc
|
34
|
-
Requires-Dist: sphinx<8,>=3.5; extra == "doc"
|
35
35
|
Requires-Dist: crate-docs-theme>=0.26.5; extra == "doc"
|
36
|
+
Requires-Dist: sphinx<9,>=3.5; extra == "doc"
|
36
37
|
Provides-Extra: test
|
37
|
-
Requires-Dist:
|
38
|
-
Requires-Dist: zope.testing<6,>=4; extra == "test"
|
39
|
-
Requires-Dist: zope.testrunner<7,>=5; extra == "test"
|
40
|
-
Requires-Dist: zc.customdoctests<2,>=1.0.1; extra == "test"
|
38
|
+
Requires-Dist: backports.zoneinfo<1; python_version < "3.9" and extra == "test"
|
41
39
|
Requires-Dist: certifi; extra == "test"
|
42
40
|
Requires-Dist: createcoverage<2,>=1; extra == "test"
|
43
|
-
Requires-Dist:
|
41
|
+
Requires-Dist: mypy<1.14; extra == "test"
|
42
|
+
Requires-Dist: poethepoet<0.31; extra == "test"
|
43
|
+
Requires-Dist: ruff<0.8; extra == "test"
|
44
44
|
Requires-Dist: stopit<2,>=1.1.2; extra == "test"
|
45
|
-
Requires-Dist:
|
46
|
-
Requires-Dist: pandas<2.3; extra == "test"
|
47
|
-
Requires-Dist: pueblo>=0.0.7; extra == "test"
|
45
|
+
Requires-Dist: tox<5,>=3; extra == "test"
|
48
46
|
Requires-Dist: pytz; extra == "test"
|
49
|
-
Requires-Dist:
|
47
|
+
Requires-Dist: zc.customdoctests<2,>=1.0.1; extra == "test"
|
48
|
+
Requires-Dist: zope.testing<6,>=4; extra == "test"
|
49
|
+
Requires-Dist: zope.testrunner<7,>=5; extra == "test"
|
50
50
|
|
51
51
|
=====================
|
52
52
|
CrateDB Python Client
|
@@ -56,7 +56,7 @@ CrateDB Python Client
|
|
56
56
|
:target: https://github.com/crate/crate-python/actions?workflow=Tests
|
57
57
|
:alt: Build status
|
58
58
|
|
59
|
-
.. image:: https://codecov.io/gh/crate/crate-python/branch/
|
59
|
+
.. image:: https://codecov.io/gh/crate/crate-python/branch/main/graph/badge.svg
|
60
60
|
:target: https://app.codecov.io/gh/crate/crate-python
|
61
61
|
:alt: Coverage
|
62
62
|
|
@@ -152,5 +152,3 @@ GitHub`_. We appreciate contributions of any kind.
|
|
152
152
|
.. _sqlalchemy-cratedb documentation: https://cratedb.com/docs/sqlalchemy-cratedb/
|
153
153
|
.. _StackOverflow: https://stackoverflow.com/tags/cratedb
|
154
154
|
.. _support channels: https://cratedb.com/support/
|
155
|
-
|
156
|
-
|