PyAthena 3.32.0__tar.gz → 3.33.0__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.
- {pyathena-3.32.0 → pyathena-3.33.0}/PKG-INFO +2 -2
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/_version.py +2 -2
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/sqlalchemy/base.py +7 -2
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/sqlalchemy/compiler.py +95 -13
- {pyathena-3.32.0 → pyathena-3.33.0}/pyproject.toml +5 -5
- {pyathena-3.32.0 → pyathena-3.33.0}/.gitignore +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/LICENSE +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/README.md +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/__init__.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/aio/__init__.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/aio/arrow/__init__.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/aio/arrow/cursor.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/aio/common.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/aio/connection.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/aio/cursor.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/aio/pandas/__init__.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/aio/pandas/cursor.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/aio/polars/__init__.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/aio/polars/cursor.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/aio/result_set.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/aio/s3fs/__init__.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/aio/s3fs/cursor.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/aio/spark/__init__.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/aio/spark/cursor.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/aio/sqlalchemy/__init__.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/aio/sqlalchemy/arrow.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/aio/sqlalchemy/base.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/aio/sqlalchemy/pandas.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/aio/sqlalchemy/polars.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/aio/sqlalchemy/rest.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/aio/sqlalchemy/s3fs.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/aio/util.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/arrow/__init__.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/arrow/async_cursor.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/arrow/converter.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/arrow/cursor.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/arrow/result_set.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/arrow/util.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/async_cursor.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/common.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/connection.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/converter.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/cursor.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/error.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/filesystem/__init__.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/filesystem/s3.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/filesystem/s3_async.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/filesystem/s3_executor.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/filesystem/s3_object.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/formatter.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/model.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/pandas/__init__.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/pandas/async_cursor.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/pandas/converter.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/pandas/cursor.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/pandas/result_set.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/pandas/util.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/parser.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/polars/__init__.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/polars/async_cursor.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/polars/converter.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/polars/cursor.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/polars/result_set.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/polars/util.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/py.typed +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/result_set.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/s3fs/__init__.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/s3fs/async_cursor.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/s3fs/converter.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/s3fs/cursor.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/s3fs/reader.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/s3fs/result_set.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/spark/__init__.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/spark/async_cursor.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/spark/common.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/spark/cursor.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/sqlalchemy/__init__.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/sqlalchemy/arrow.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/sqlalchemy/constants.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/sqlalchemy/pandas.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/sqlalchemy/polars.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/sqlalchemy/preparer.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/sqlalchemy/requirements.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/sqlalchemy/rest.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/sqlalchemy/s3fs.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/sqlalchemy/types.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/sqlalchemy/util.py +0 -0
- {pyathena-3.32.0 → pyathena-3.33.0}/pyathena/util.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyAthena
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.33.0
|
|
4
4
|
Summary: Python DB API 2.0 (PEP 249) client for Amazon Athena
|
|
5
5
|
Project-URL: homepage, https://github.com/pyathena-dev/PyAthena/
|
|
6
6
|
Project-URL: repository, https://github.com/pyathena-dev/PyAthena/
|
|
@@ -38,7 +38,7 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
38
38
|
Classifier: Programming Language :: Python :: 3.14
|
|
39
39
|
Classifier: Topic :: Database :: Front-Ends
|
|
40
40
|
Requires-Python: >=3.10
|
|
41
|
-
Requires-Dist: boto3>=1.
|
|
41
|
+
Requires-Dist: boto3>=1.41.2
|
|
42
42
|
Requires-Dist: botocore>=1.41.2
|
|
43
43
|
Requires-Dist: fsspec
|
|
44
44
|
Requires-Dist: python-dateutil
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '3.
|
|
22
|
-
__version_tuple__ = version_tuple = (3,
|
|
21
|
+
__version__ = version = '3.33.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (3, 33, 0)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -207,8 +207,7 @@ class AthenaDialect(DefaultDialect):
|
|
|
207
207
|
# awsathena+rest://
|
|
208
208
|
# {aws_access_key_id}:{aws_secret_access_key}@athena.{region_name}.amazonaws.com:443/
|
|
209
209
|
# {schema_name}?s3_staging_dir={s3_staging_dir}&...
|
|
210
|
-
|
|
211
|
-
return cast(tuple[str], ()), self._connect_options
|
|
210
|
+
return cast(tuple[str], ()), self._create_connect_args(url)
|
|
212
211
|
|
|
213
212
|
def _create_connect_args(self, url: URL) -> dict[str, Any]:
|
|
214
213
|
opts: dict[str, Any] = {
|
|
@@ -238,6 +237,12 @@ class AthenaDialect(DefaultDialect):
|
|
|
238
237
|
opts.update({"result_reuse_enable": bool(strtobool(opts["result_reuse_enable"]))})
|
|
239
238
|
if "result_reuse_minutes" in opts:
|
|
240
239
|
opts.update({"result_reuse_minutes": int(opts["result_reuse_minutes"])})
|
|
240
|
+
# Store on the dialect so compilers can consult connection options
|
|
241
|
+
# (e.g. catalog_name for S3 Tables detection). Assigned here rather than
|
|
242
|
+
# in create_connect_args because subclass dialects call this method
|
|
243
|
+
# directly and mutate the returned dict afterwards; sharing the same
|
|
244
|
+
# object keeps _connect_options in sync with their updates.
|
|
245
|
+
self._connect_options = opts
|
|
241
246
|
return opts
|
|
242
247
|
|
|
243
248
|
@reflection.cache
|
|
@@ -39,6 +39,13 @@ if TYPE_CHECKING:
|
|
|
39
39
|
_DialectArgDict = Mapping[str, Any]
|
|
40
40
|
CreateColumn = Any
|
|
41
41
|
|
|
42
|
+
# Prefix of the Athena data catalog name registered for an Amazon S3 Tables
|
|
43
|
+
# table bucket (e.g. ``s3tablescatalog/my-bucket``). It is selected via the
|
|
44
|
+
# connection ``catalog_name``. S3 Tables are Iceberg-backed and use managed
|
|
45
|
+
# storage, so their CREATE TABLE statements must not include a LOCATION clause.
|
|
46
|
+
# https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-integrations-query-athena.html
|
|
47
|
+
S3_TABLES_CATALOG_PREFIX = "s3tablescatalog/"
|
|
48
|
+
|
|
42
49
|
|
|
43
50
|
class AthenaTypeCompiler(GenericTypeCompiler):
|
|
44
51
|
"""Type compiler for Amazon Athena SQL types.
|
|
@@ -305,6 +312,10 @@ class AthenaDDLCompiler(DDLCompiler):
|
|
|
305
312
|
|
|
306
313
|
- External table creation (EXTERNAL keyword for Hive-style tables)
|
|
307
314
|
- Iceberg table creation (managed tables with ACID support)
|
|
315
|
+
- Amazon S3 Tables (Iceberg-backed, managed storage): set the connection
|
|
316
|
+
``catalog_name`` to ``s3tablescatalog/<table-bucket>`` and use the
|
|
317
|
+
namespace as the table ``schema``. The LOCATION clause is omitted since
|
|
318
|
+
storage is managed.
|
|
308
319
|
- File formats: PARQUET, ORC, TEXTFILE, JSON, AVRO, etc.
|
|
309
320
|
- Row formats with SerDe specifications
|
|
310
321
|
- Compression settings for various file formats
|
|
@@ -445,6 +456,74 @@ class AthenaDDLCompiler(DDLCompiler):
|
|
|
445
456
|
text.append(")")
|
|
446
457
|
return "\n".join(text)
|
|
447
458
|
|
|
459
|
+
@staticmethod
|
|
460
|
+
def _is_s3_tables_catalog(connect_opts: Mapping[str, Any]) -> bool:
|
|
461
|
+
"""Return whether the connection targets an Amazon S3 Tables catalog.
|
|
462
|
+
|
|
463
|
+
S3 Tables are queried by setting the connection ``catalog_name`` to
|
|
464
|
+
``s3tablescatalog/<table-bucket>`` and using the namespace as the table
|
|
465
|
+
``schema`` (a two-part ``namespace.table`` identifier). Athena rejects a
|
|
466
|
+
three-part ``catalog.namespace.table`` identifier in DDL, so the catalog
|
|
467
|
+
must be selected at the connection level. Such tables use managed
|
|
468
|
+
storage, so their CREATE TABLE statement must omit the LOCATION clause.
|
|
469
|
+
|
|
470
|
+
Args:
|
|
471
|
+
connect_opts: The dialect connection options.
|
|
472
|
+
|
|
473
|
+
Returns:
|
|
474
|
+
True if ``catalog_name`` names an S3 Tables catalog.
|
|
475
|
+
"""
|
|
476
|
+
if not connect_opts:
|
|
477
|
+
return False
|
|
478
|
+
catalog = connect_opts.get("catalog_name") or ""
|
|
479
|
+
# Athena resolves catalog names case-insensitively.
|
|
480
|
+
return catalog.lower().startswith(S3_TABLES_CATALOG_PREFIX)
|
|
481
|
+
|
|
482
|
+
def _is_iceberg_table(
|
|
483
|
+
self, dialect_opts: _DialectArgDict, connect_opts: Mapping[str, Any]
|
|
484
|
+
) -> bool:
|
|
485
|
+
"""Return whether the table properties declare an Iceberg table.
|
|
486
|
+
|
|
487
|
+
Args:
|
|
488
|
+
dialect_opts: The table's ``awsathena_*`` dialect options.
|
|
489
|
+
connect_opts: The dialect connection options.
|
|
490
|
+
|
|
491
|
+
Returns:
|
|
492
|
+
True if the rendered TBLPROPERTIES set ``table_type`` to Iceberg.
|
|
493
|
+
"""
|
|
494
|
+
table_properties = self._get_table_properties_specification(
|
|
495
|
+
dialect_opts, connect_opts
|
|
496
|
+
).lower()
|
|
497
|
+
return ("table_type" in table_properties) and ("iceberg" in table_properties)
|
|
498
|
+
|
|
499
|
+
def _validate_s3_tables_create_table(
|
|
500
|
+
self, dialect_opts: _DialectArgDict, connect_opts: Mapping[str, Any]
|
|
501
|
+
) -> None:
|
|
502
|
+
"""Validate a CREATE TABLE compiled against an S3 Tables catalog.
|
|
503
|
+
|
|
504
|
+
S3 Tables support only Iceberg tables on managed storage, so the table
|
|
505
|
+
must declare ``table_type`` ICEBERG and must not specify a location.
|
|
506
|
+
Raising here surfaces a clear client-side error instead of emitting DDL
|
|
507
|
+
that Athena would reject.
|
|
508
|
+
|
|
509
|
+
Args:
|
|
510
|
+
dialect_opts: The table's ``awsathena_*`` dialect options.
|
|
511
|
+
connect_opts: The dialect connection options.
|
|
512
|
+
|
|
513
|
+
Raises:
|
|
514
|
+
exc.CompileError: If the table is not Iceberg or specifies a location.
|
|
515
|
+
"""
|
|
516
|
+
if not self._is_iceberg_table(dialect_opts, connect_opts):
|
|
517
|
+
raise exc.CompileError(
|
|
518
|
+
"S3 Tables support only Iceberg tables; specify the dialect keyword "
|
|
519
|
+
"argument `awsathena_tblproperties={'table_type': 'ICEBERG'}`"
|
|
520
|
+
)
|
|
521
|
+
if dialect_opts["location"]:
|
|
522
|
+
raise exc.CompileError(
|
|
523
|
+
"S3 Tables use managed storage and do not accept a table location; "
|
|
524
|
+
"remove the dialect keyword argument `awsathena_location`"
|
|
525
|
+
)
|
|
526
|
+
|
|
448
527
|
def _get_table_location(
|
|
449
528
|
self, table: Table, dialect_opts: _DialectArgDict, connect_opts: Mapping[str, Any]
|
|
450
529
|
) -> str | None:
|
|
@@ -662,12 +741,7 @@ class AthenaDDLCompiler(DDLCompiler):
|
|
|
662
741
|
dialect = cast("AthenaDialect", self.dialect)
|
|
663
742
|
connect_opts = dialect._connect_options
|
|
664
743
|
|
|
665
|
-
|
|
666
|
-
dialect_opts, connect_opts
|
|
667
|
-
).lower()
|
|
668
|
-
is_iceberg = False
|
|
669
|
-
if ("table_type" in table_properties) and ("iceberg" in table_properties):
|
|
670
|
-
is_iceberg = True
|
|
744
|
+
is_iceberg = self._is_iceberg_table(dialect_opts, connect_opts)
|
|
671
745
|
|
|
672
746
|
# https://docs.aws.amazon.com/athena/latest/ug/querying-iceberg-creating-tables.html
|
|
673
747
|
text = ["\nCREATE TABLE"] if is_iceberg else ["\nCREATE EXTERNAL TABLE"]
|
|
@@ -705,11 +779,19 @@ class AthenaDDLCompiler(DDLCompiler):
|
|
|
705
779
|
dialect_opts: _DialectArgDict = table.dialect_options["awsathena"]
|
|
706
780
|
dialect = cast("AthenaDialect", self.dialect)
|
|
707
781
|
connect_opts = dialect._connect_options
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
self.
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
782
|
+
if self._is_s3_tables_catalog(connect_opts):
|
|
783
|
+
# S3 Tables are managed Iceberg tables: ROW FORMAT, SERDEPROPERTIES,
|
|
784
|
+
# STORED AS, and LOCATION are not accepted, so emit only TBLPROPERTIES.
|
|
785
|
+
self._validate_s3_tables_create_table(dialect_opts, connect_opts)
|
|
786
|
+
text = [
|
|
787
|
+
self._get_table_properties_specification(dialect_opts, connect_opts),
|
|
788
|
+
]
|
|
789
|
+
else:
|
|
790
|
+
text = [
|
|
791
|
+
self._get_row_format_specification(dialect_opts, connect_opts),
|
|
792
|
+
self._get_serde_properties_specification(dialect_opts, connect_opts),
|
|
793
|
+
self._get_file_format_specification(dialect_opts, connect_opts),
|
|
794
|
+
self._get_table_location_specification(table, dialect_opts, connect_opts),
|
|
795
|
+
self._get_table_properties_specification(dialect_opts, connect_opts),
|
|
796
|
+
]
|
|
715
797
|
return "\n".join([t for t in text if t])
|
|
@@ -5,7 +5,7 @@ authors = [
|
|
|
5
5
|
{name = "laughingman7743", email = "laughingman7743@gmail.com"},
|
|
6
6
|
]
|
|
7
7
|
dependencies = [
|
|
8
|
-
"boto3>=1.
|
|
8
|
+
"boto3>=1.41.2",
|
|
9
9
|
"botocore>=1.41.2",
|
|
10
10
|
"tenacity>=4.1.0",
|
|
11
11
|
"fsspec",
|
|
@@ -223,12 +223,12 @@ TEST_TYPE =
|
|
|
223
223
|
allowlist_externals =
|
|
224
224
|
uv
|
|
225
225
|
uvx
|
|
226
|
-
|
|
226
|
+
just
|
|
227
227
|
commands =
|
|
228
228
|
uv sync --group dev
|
|
229
|
-
pyathena:
|
|
230
|
-
sqla:
|
|
231
|
-
sqla_async:
|
|
229
|
+
pyathena: just test pyathena
|
|
230
|
+
sqla: just test sqla
|
|
231
|
+
sqla_async: just test sqla-async
|
|
232
232
|
passenv =
|
|
233
233
|
TOXENV
|
|
234
234
|
AWS_*
|
|
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
|
|
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
|