crate 2.0.0.dev5__tar.gz → 2.1.0.dev0__tar.gz
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-2.0.0.dev5 → crate-2.1.0.dev0}/CHANGES.rst +17 -5
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/DEVELOP.rst +9 -12
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/PKG-INFO +7 -7
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/docs/by-example/client.rst +2 -6
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/docs/connect.rst +1 -1
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/docs/index-all.rst +0 -1
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/docs/index.rst +1 -1
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/docs/query.rst +1 -1
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/requirements.txt +2 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/setup.py +4 -5
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/src/crate/client/__init__.py +1 -1
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/src/crate/client/connection.py +10 -1
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/src/crate/client/http.py +29 -7
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/src/crate.egg-info/PKG-INFO +7 -7
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/src/crate.egg-info/SOURCES.txt +0 -1
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/src/crate.egg-info/requires.txt +4 -5
- crate-2.0.0.dev5/docs/sqlalchemy.rst +0 -17
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/CONTRIBUTING.rst +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/LICENSE +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/MANIFEST.in +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/NOTICE +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/README.rst +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/docs/_extra/robots.txt +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/docs/backlog.rst +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/docs/blobs.rst +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/docs/by-example/blob.rst +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/docs/by-example/connection.rst +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/docs/by-example/cursor.rst +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/docs/by-example/http.rst +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/docs/by-example/https.rst +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/docs/by-example/index.rst +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/docs/conf.py +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/docs/data-types.rst +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/docs/docutils.conf +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/docs/getting-started.rst +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/docs/other-options.rst +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/docs/requirements.txt +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/pyproject.toml +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/setup.cfg +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/src/crate/client/_pep440.py +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/src/crate/client/blob.py +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/src/crate/client/converter.py +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/src/crate/client/cursor.py +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/src/crate/client/exceptions.py +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/src/crate/testing/__init__.py +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/src/crate/testing/layer.py +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/src/crate/testing/util.py +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/src/crate.egg-info/dependency_links.txt +0 -0
- {crate-2.0.0.dev5 → crate-2.1.0.dev0}/src/crate.egg-info/top_level.txt +0 -0
@@ -5,17 +5,29 @@ Changes for crate
|
|
5
5
|
Unreleased
|
6
6
|
==========
|
7
7
|
|
8
|
+
- Changed connection behaviour to fail early if the database cluster
|
9
|
+
does not respond
|
10
|
+
|
11
|
+
2025/01/30 2.0.0
|
12
|
+
================
|
13
|
+
|
8
14
|
- Switched JSON encoder to use the `orjson`_ library, to improve JSON
|
9
15
|
marshalling performance. Thanks, @widmogrod.
|
16
|
+
|
10
17
|
orjson is fast and in some spots even more correct when compared against
|
11
18
|
Python's stdlib ``json`` module. Contrary to the stdlib variant, orjson
|
12
|
-
will serialize to ``bytes`` instead of ``str``.
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
19
|
+
will serialize to ``bytes`` instead of ``str``. When sending data to CrateDB,
|
20
|
+
``crate-python`` uses a custom encoder to add support for additional data
|
21
|
+
types.
|
22
|
+
|
23
|
+
- Python's ``Decimal`` type will be serialized to ``str``.
|
24
|
+
- Python's ``dt.datetime`` and ``dt.date`` types will be serialized to
|
25
|
+
``int`` (``LONG``) after converting to milliseconds since epoch, to
|
26
|
+
optimally accommodate CrateDB's `TIMESTAMP`_ representation.
|
27
|
+
- NumPy's data types will be handled by ``orjson`` without any ado.
|
17
28
|
|
18
29
|
.. _orjson: https://github.com/ijl/orjson
|
30
|
+
.. _TIMESTAMP: https://cratedb.com/docs/crate/reference/en/latest/general/ddl/data-types.html#type-timestamp
|
19
31
|
|
20
32
|
2024/11/23 1.0.1
|
21
33
|
================
|
@@ -5,7 +5,7 @@ CrateDB Python developer guide
|
|
5
5
|
Setup
|
6
6
|
=====
|
7
7
|
|
8
|
-
Optionally install Python package and project manager
|
8
|
+
Optionally install Python package and project manager `uv`_,
|
9
9
|
in order to significantly speed up the package installation::
|
10
10
|
|
11
11
|
{apt,brew,pip,zypper} install uv
|
@@ -67,16 +67,11 @@ To inspect the whole list of test cases, run::
|
|
67
67
|
|
68
68
|
bin/test --list-tests
|
69
69
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
on your ``$PATH``.
|
76
|
-
|
77
|
-
To run against a single interpreter, you can also invoke::
|
78
|
-
|
79
|
-
tox -e py37
|
70
|
+
The CI setup on GitHub Actions (GHA) provides a full test matrix covering
|
71
|
+
relevant Python versions. You can invoke the software tests against a specific
|
72
|
+
Python interpreter or multiple `Python versions`_ on your workstation using
|
73
|
+
`uv`_, by supplying the ``--python`` command-line option, or by defining the
|
74
|
+
`UV_PYTHON`_ environment variable prior to invoking ``source bootstrap.sh``.
|
80
75
|
|
81
76
|
*Note*: Before running the tests, make sure to stop all CrateDB instances which
|
82
77
|
are listening on the default CrateDB transport port to avoid side effects with
|
@@ -168,12 +163,14 @@ nothing special you need to do to get the live docs to update.
|
|
168
163
|
.. _@crate/docs: https://github.com/orgs/crate/teams/docs
|
169
164
|
.. _buildout: https://pypi.python.org/pypi/zc.buildout
|
170
165
|
.. _PyPI: https://pypi.python.org/pypi
|
166
|
+
.. _Python versions: https://docs.astral.sh/uv/concepts/python-versions/
|
171
167
|
.. _Read the Docs: http://readthedocs.org
|
172
168
|
.. _ReStructuredText: http://docutils.sourceforge.net/rst.html
|
173
169
|
.. _Sphinx: http://sphinx-doc.org/
|
174
170
|
.. _tests/assets/pki/*.pem: https://github.com/crate/crate-python/tree/main/tests/assets/pki
|
175
|
-
.. _tox: http://testrun.org/tox/latest/
|
176
171
|
.. _twine: https://pypi.python.org/pypi/twine
|
177
172
|
.. _useful command-line options for zope-testrunner: https://pypi.org/project/zope.testrunner/#some-useful-command-line-options-to-get-you-started
|
173
|
+
.. _uv: https://docs.astral.sh/uv/
|
174
|
+
.. _UV_PYTHON: https://docs.astral.sh/uv/configuration/environment/#uv_python
|
178
175
|
.. _versions hosted on ReadTheDocs: https://readthedocs.org/projects/crate-python/versions/
|
179
176
|
.. _zope.testrunner: https://pypi.org/project/zope.testrunner/
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: crate
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.1.0.dev0
|
4
4
|
Summary: CrateDB Python Client
|
5
5
|
Home-page: https://github.com/crate/crate-python
|
6
6
|
Author: Crate.io
|
@@ -39,15 +39,14 @@ Provides-Extra: test
|
|
39
39
|
Requires-Dist: backports.zoneinfo<1; python_version < "3.9" and extra == "test"
|
40
40
|
Requires-Dist: certifi; extra == "test"
|
41
41
|
Requires-Dist: createcoverage<2,>=1; extra == "test"
|
42
|
-
Requires-Dist: mypy<1.
|
43
|
-
Requires-Dist: poethepoet<
|
44
|
-
Requires-Dist: ruff<0.
|
42
|
+
Requires-Dist: mypy<1.16; extra == "test"
|
43
|
+
Requires-Dist: poethepoet<1; extra == "test"
|
44
|
+
Requires-Dist: ruff<0.12; extra == "test"
|
45
45
|
Requires-Dist: stopit<2,>=1.1.2; extra == "test"
|
46
|
-
Requires-Dist: tox<5,>=3; extra == "test"
|
47
46
|
Requires-Dist: pytz; extra == "test"
|
48
47
|
Requires-Dist: zc.customdoctests<2,>=1.0.1; extra == "test"
|
49
48
|
Requires-Dist: zope.testing<6,>=4; extra == "test"
|
50
|
-
Requires-Dist: zope.testrunner<
|
49
|
+
Requires-Dist: zope.testrunner<8,>=5; extra == "test"
|
51
50
|
Dynamic: author
|
52
51
|
Dynamic: author-email
|
53
52
|
Dynamic: classifier
|
@@ -56,6 +55,7 @@ Dynamic: description-content-type
|
|
56
55
|
Dynamic: home-page
|
57
56
|
Dynamic: keywords
|
58
57
|
Dynamic: license
|
58
|
+
Dynamic: license-file
|
59
59
|
Dynamic: platform
|
60
60
|
Dynamic: provides-extra
|
61
61
|
Dynamic: requires-dist
|
@@ -35,12 +35,8 @@ respond, the request is automatically routed to the next server:
|
|
35
35
|
>>> connection = client.connect([invalid_host, crate_host])
|
36
36
|
>>> connection.close()
|
37
37
|
|
38
|
-
If no ``servers`` are
|
39
|
-
|
40
|
-
>>> connection = client.connect()
|
41
|
-
>>> connection.client._active_servers
|
42
|
-
['http://127.0.0.1:4200']
|
43
|
-
>>> connection.close()
|
38
|
+
If no ``servers`` are supplied to the ``connect`` method, the default address
|
39
|
+
``http://127.0.0.1:4200`` is used.
|
44
40
|
|
45
41
|
If the option ``error_trace`` is set to ``True``, the client will print a whole
|
46
42
|
traceback if a server error occurs:
|
@@ -10,7 +10,7 @@ Connect to CrateDB
|
|
10
10
|
`Python Database API Specification v2.0`_ (PEP 249).
|
11
11
|
|
12
12
|
For help using the `SQLAlchemy`_ dialect, consult the
|
13
|
-
:ref:`SQLAlchemy dialect documentation <
|
13
|
+
:ref:`SQLAlchemy dialect documentation <sqlalchemy-cratedb:index>`.
|
14
14
|
|
15
15
|
.. SEEALSO::
|
16
16
|
|
@@ -99,7 +99,7 @@ please consult the :ref:`data-types` documentation page.
|
|
99
99
|
Migration Notes
|
100
100
|
===============
|
101
101
|
|
102
|
-
The :ref:`CrateDB dialect <
|
102
|
+
The :ref:`CrateDB dialect <sqlalchemy-cratedb:index>` for `SQLAlchemy`_ is provided
|
103
103
|
by the `sqlalchemy-cratedb`_ package.
|
104
104
|
|
105
105
|
If you are migrating from previous versions of ``crate[sqlalchemy]<1.0.0``, you
|
@@ -10,7 +10,7 @@ Query CrateDB
|
|
10
10
|
`Python Database API Specification v2.0`_ (PEP 249).
|
11
11
|
|
12
12
|
For help using the `SQLAlchemy`_ dialect, consult
|
13
|
-
:ref:`the SQLAlchemy dialect documentation <
|
13
|
+
:ref:`the SQLAlchemy dialect documentation <sqlalchemy-cratedb:index>`.
|
14
14
|
|
15
15
|
.. SEEALSO::
|
16
16
|
|
@@ -67,15 +67,14 @@ setup(
|
|
67
67
|
'backports.zoneinfo<1; python_version<"3.9"',
|
68
68
|
"certifi",
|
69
69
|
"createcoverage>=1,<2",
|
70
|
-
"mypy<1.
|
71
|
-
"poethepoet<
|
72
|
-
"ruff<0.
|
70
|
+
"mypy<1.16",
|
71
|
+
"poethepoet<1",
|
72
|
+
"ruff<0.12",
|
73
73
|
"stopit>=1.1.2,<2",
|
74
|
-
"tox>=3,<5",
|
75
74
|
"pytz",
|
76
75
|
"zc.customdoctests>=1.0.1,<2",
|
77
76
|
"zope.testing>=4,<6",
|
78
|
-
"zope.testrunner>=5,<
|
77
|
+
"zope.testrunner>=5,<8",
|
79
78
|
],
|
80
79
|
},
|
81
80
|
python_requires=">=3.6",
|
@@ -18,8 +18,10 @@
|
|
18
18
|
# However, if you have executed another commercial license agreement
|
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
|
+
import json
|
21
22
|
|
22
23
|
from verlib2 import Version
|
24
|
+
from verlib2.packaging.version import InvalidVersion
|
23
25
|
|
24
26
|
from .blob import BlobContainer
|
25
27
|
from .cursor import Cursor
|
@@ -197,14 +199,21 @@ class Connection:
|
|
197
199
|
|
198
200
|
def _lowest_server_version(self):
|
199
201
|
lowest = None
|
202
|
+
server_count = len(self.client.active_servers)
|
203
|
+
connection_errors = []
|
200
204
|
for server in self.client.active_servers:
|
201
205
|
try:
|
202
206
|
_, _, version = self.client.server_infos(server)
|
203
207
|
version = Version(version)
|
204
|
-
except
|
208
|
+
except ConnectionError as ex:
|
209
|
+
connection_errors.append(ex)
|
210
|
+
continue
|
211
|
+
except (ValueError, InvalidVersion):
|
205
212
|
continue
|
206
213
|
if not lowest or version < lowest:
|
207
214
|
lowest = version
|
215
|
+
if connection_errors and len(connection_errors) == server_count:
|
216
|
+
raise ConnectionError(json.dumps(list(map(str, connection_errors))))
|
208
217
|
return lowest or Version("0.0.0")
|
209
218
|
|
210
219
|
def __repr__(self):
|
@@ -20,6 +20,8 @@
|
|
20
20
|
# software solely pursuant to the terms of the relevant commercial agreement.
|
21
21
|
|
22
22
|
|
23
|
+
import calendar
|
24
|
+
import datetime as dt
|
23
25
|
import heapq
|
24
26
|
import io
|
25
27
|
import logging
|
@@ -84,19 +86,35 @@ def super_len(o):
|
|
84
86
|
return None
|
85
87
|
|
86
88
|
|
87
|
-
|
89
|
+
epoch_aware = dt.datetime(1970, 1, 1, tzinfo=dt.timezone.utc)
|
90
|
+
epoch_naive = dt.datetime(1970, 1, 1)
|
91
|
+
|
92
|
+
|
93
|
+
def json_encoder(obj: t.Any) -> t.Union[int, str]:
|
88
94
|
"""
|
89
95
|
Encoder function for orjson, with additional type support.
|
90
96
|
|
91
|
-
- Python's `Decimal` type
|
92
|
-
-
|
97
|
+
- Python's `Decimal` type will be serialized to `str`.
|
98
|
+
- Python's `dt.datetime` and `dt.date` types will be
|
99
|
+
serialized to `int` after converting to milliseconds
|
100
|
+
since epoch.
|
93
101
|
|
94
102
|
https://github.com/ijl/orjson#default
|
103
|
+
https://cratedb.com/docs/crate/reference/en/latest/general/ddl/data-types.html#type-timestamp
|
95
104
|
"""
|
96
105
|
if isinstance(obj, Decimal):
|
97
106
|
return str(obj)
|
98
|
-
|
99
|
-
|
107
|
+
if isinstance(obj, dt.datetime):
|
108
|
+
if obj.tzinfo is not None:
|
109
|
+
delta = obj - epoch_aware
|
110
|
+
else:
|
111
|
+
delta = obj - epoch_naive
|
112
|
+
return int(
|
113
|
+
delta.microseconds / 1000.0
|
114
|
+
+ (delta.seconds + delta.days * 24 * 3600) * 1000.0
|
115
|
+
)
|
116
|
+
if isinstance(obj, dt.date):
|
117
|
+
return calendar.timegm(obj.timetuple()) * 1000
|
100
118
|
raise TypeError
|
101
119
|
|
102
120
|
|
@@ -108,8 +126,12 @@ def json_dumps(obj: t.Any) -> bytes:
|
|
108
126
|
"""
|
109
127
|
return orjson.dumps(
|
110
128
|
obj,
|
111
|
-
default=
|
112
|
-
option=(
|
129
|
+
default=json_encoder,
|
130
|
+
option=(
|
131
|
+
orjson.OPT_PASSTHROUGH_DATETIME
|
132
|
+
| orjson.OPT_NON_STR_KEYS
|
133
|
+
| orjson.OPT_SERIALIZE_NUMPY
|
134
|
+
),
|
113
135
|
)
|
114
136
|
|
115
137
|
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: crate
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.1.0.dev0
|
4
4
|
Summary: CrateDB Python Client
|
5
5
|
Home-page: https://github.com/crate/crate-python
|
6
6
|
Author: Crate.io
|
@@ -39,15 +39,14 @@ Provides-Extra: test
|
|
39
39
|
Requires-Dist: backports.zoneinfo<1; python_version < "3.9" and extra == "test"
|
40
40
|
Requires-Dist: certifi; extra == "test"
|
41
41
|
Requires-Dist: createcoverage<2,>=1; extra == "test"
|
42
|
-
Requires-Dist: mypy<1.
|
43
|
-
Requires-Dist: poethepoet<
|
44
|
-
Requires-Dist: ruff<0.
|
42
|
+
Requires-Dist: mypy<1.16; extra == "test"
|
43
|
+
Requires-Dist: poethepoet<1; extra == "test"
|
44
|
+
Requires-Dist: ruff<0.12; extra == "test"
|
45
45
|
Requires-Dist: stopit<2,>=1.1.2; extra == "test"
|
46
|
-
Requires-Dist: tox<5,>=3; extra == "test"
|
47
46
|
Requires-Dist: pytz; extra == "test"
|
48
47
|
Requires-Dist: zc.customdoctests<2,>=1.0.1; extra == "test"
|
49
48
|
Requires-Dist: zope.testing<6,>=4; extra == "test"
|
50
|
-
Requires-Dist: zope.testrunner<
|
49
|
+
Requires-Dist: zope.testrunner<8,>=5; extra == "test"
|
51
50
|
Dynamic: author
|
52
51
|
Dynamic: author-email
|
53
52
|
Dynamic: classifier
|
@@ -56,6 +55,7 @@ Dynamic: description-content-type
|
|
56
55
|
Dynamic: home-page
|
57
56
|
Dynamic: keywords
|
58
57
|
Dynamic: license
|
58
|
+
Dynamic: license-file
|
59
59
|
Dynamic: platform
|
60
60
|
Dynamic: provides-extra
|
61
61
|
Dynamic: requires-dist
|
@@ -9,15 +9,14 @@ sphinx<9,>=3.5
|
|
9
9
|
[test]
|
10
10
|
certifi
|
11
11
|
createcoverage<2,>=1
|
12
|
-
mypy<1.
|
13
|
-
poethepoet<
|
14
|
-
ruff<0.
|
12
|
+
mypy<1.16
|
13
|
+
poethepoet<1
|
14
|
+
ruff<0.12
|
15
15
|
stopit<2,>=1.1.2
|
16
|
-
tox<5,>=3
|
17
16
|
pytz
|
18
17
|
zc.customdoctests<2,>=1.0.1
|
19
18
|
zope.testing<6,>=4
|
20
|
-
zope.testrunner<
|
19
|
+
zope.testrunner<8,>=5
|
21
20
|
|
22
21
|
[test:python_version < "3.9"]
|
23
22
|
backports.zoneinfo<1
|
@@ -1,17 +0,0 @@
|
|
1
|
-
.. _sqlalchemy-support:
|
2
|
-
.. _using-sqlalchemy:
|
3
|
-
|
4
|
-
==================
|
5
|
-
SQLAlchemy support
|
6
|
-
==================
|
7
|
-
|
8
|
-
`SQLAlchemy`_ is the most popular `Object-Relational Mapping`_ (ORM) library
|
9
|
-
for Python.
|
10
|
-
|
11
|
-
The `SQLAlchemy`_ CrateDB dialect is provided by the `sqlalchemy-cratedb`_
|
12
|
-
package.
|
13
|
-
|
14
|
-
|
15
|
-
.. _Object-Relational Mapping: https://en.wikipedia.org/wiki/Object-relational_mapping
|
16
|
-
.. _SQLAlchemy: https://www.sqlalchemy.org/
|
17
|
-
.. _sqlalchemy-cratedb: https://github.com/crate-workbench/sqlalchemy-cratedb
|
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
|