deltacat 2.0__py3-none-any.whl → 2.0.0__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.
- deltacat/__init__.py +117 -18
- deltacat/api.py +536 -126
- deltacat/aws/constants.py +0 -23
- deltacat/aws/s3u.py +4 -631
- deltacat/benchmarking/benchmark_engine.py +4 -2
- deltacat/benchmarking/conftest.py +1 -19
- deltacat/benchmarking/test_benchmark_pipeline.py +6 -4
- deltacat/catalog/__init__.py +64 -5
- deltacat/catalog/delegate.py +445 -63
- deltacat/catalog/interface.py +188 -62
- deltacat/catalog/main/impl.py +2444 -282
- deltacat/catalog/model/catalog.py +208 -113
- deltacat/catalog/model/properties.py +63 -24
- deltacat/compute/__init__.py +14 -0
- deltacat/compute/compactor/compaction_session.py +97 -75
- deltacat/compute/compactor/model/compact_partition_params.py +75 -30
- deltacat/compute/compactor/model/compaction_session_audit_info.py +17 -0
- deltacat/compute/compactor/model/round_completion_info.py +16 -6
- deltacat/compute/compactor/repartition_session.py +8 -21
- deltacat/compute/compactor/steps/hash_bucket.py +5 -5
- deltacat/compute/compactor/steps/materialize.py +9 -7
- deltacat/compute/compactor/steps/repartition.py +12 -11
- deltacat/compute/compactor/utils/io.py +6 -5
- deltacat/compute/compactor/utils/round_completion_reader.py +117 -0
- deltacat/compute/compactor/utils/system_columns.py +3 -1
- deltacat/compute/compactor_v2/compaction_session.py +17 -14
- deltacat/compute/compactor_v2/constants.py +30 -1
- deltacat/compute/compactor_v2/model/evaluate_compaction_result.py +0 -1
- deltacat/compute/compactor_v2/model/hash_bucket_input.py +9 -3
- deltacat/compute/compactor_v2/model/merge_file_group.py +5 -2
- deltacat/compute/compactor_v2/model/merge_input.py +33 -8
- deltacat/compute/compactor_v2/private/compaction_utils.py +167 -68
- deltacat/compute/compactor_v2/steps/hash_bucket.py +5 -2
- deltacat/compute/compactor_v2/steps/merge.py +267 -55
- deltacat/compute/compactor_v2/utils/content_type_params.py +34 -6
- deltacat/compute/compactor_v2/utils/dedupe.py +1 -1
- deltacat/compute/compactor_v2/utils/delta.py +5 -3
- deltacat/compute/compactor_v2/utils/io.py +11 -4
- deltacat/compute/compactor_v2/utils/merge.py +15 -2
- deltacat/compute/compactor_v2/utils/primary_key_index.py +28 -4
- deltacat/compute/compactor_v2/utils/task_options.py +45 -33
- deltacat/compute/converter/constants.py +5 -0
- deltacat/compute/converter/converter_session.py +207 -52
- deltacat/compute/converter/model/convert_input.py +43 -16
- deltacat/compute/converter/model/convert_input_files.py +33 -16
- deltacat/compute/converter/model/convert_result.py +80 -0
- deltacat/compute/converter/model/converter_session_params.py +64 -19
- deltacat/compute/converter/pyiceberg/catalog.py +21 -18
- deltacat/compute/converter/pyiceberg/overrides.py +193 -65
- deltacat/compute/converter/pyiceberg/update_snapshot_overrides.py +148 -100
- deltacat/compute/converter/steps/convert.py +230 -75
- deltacat/compute/converter/steps/dedupe.py +46 -12
- deltacat/compute/converter/utils/convert_task_options.py +66 -22
- deltacat/compute/converter/utils/converter_session_utils.py +126 -60
- deltacat/compute/converter/utils/iceberg_columns.py +13 -8
- deltacat/compute/converter/utils/io.py +173 -13
- deltacat/compute/converter/utils/s3u.py +42 -27
- deltacat/compute/janitor.py +205 -0
- deltacat/compute/jobs/client.py +417 -0
- deltacat/compute/resource_estimation/delta.py +38 -6
- deltacat/compute/resource_estimation/model.py +8 -0
- deltacat/constants.py +49 -6
- deltacat/docs/autogen/schema/inference/generate_type_mappings.py +687 -0
- deltacat/docs/autogen/schema/inference/parse_json_type_mappings.py +673 -0
- deltacat/env.py +10 -0
- deltacat/examples/basic_logging.py +6 -6
- deltacat/examples/compactor/aws/__init__.py +1 -0
- deltacat/examples/compactor/bootstrap.py +863 -0
- deltacat/examples/compactor/compactor.py +373 -0
- deltacat/examples/compactor/explorer.py +473 -0
- deltacat/examples/compactor/gcp/__init__.py +1 -0
- deltacat/examples/compactor/job_runner.py +439 -0
- deltacat/examples/compactor/utils/__init__.py +1 -0
- deltacat/examples/compactor/utils/common.py +261 -0
- deltacat/examples/experimental/iceberg/converter/beam/app.py +226 -0
- deltacat/examples/experimental/iceberg/converter/beam/main.py +133 -0
- deltacat/examples/experimental/iceberg/converter/beam/test_workflow.py +113 -0
- deltacat/examples/experimental/iceberg/converter/beam/utils/__init__.py +3 -0
- deltacat/examples/experimental/iceberg/converter/beam/utils/common.py +174 -0
- deltacat/examples/experimental/iceberg/converter/beam/utils/spark.py +263 -0
- deltacat/examples/{iceberg → experimental/iceberg}/iceberg_bucket_writer.py +66 -21
- deltacat/examples/{iceberg → experimental/iceberg}/iceberg_reader.py +2 -4
- deltacat/examples/hello_world.py +4 -2
- deltacat/examples/indexer/indexer.py +163 -0
- deltacat/examples/indexer/job_runner.py +198 -0
- deltacat/exceptions.py +66 -4
- deltacat/experimental/catalog/iceberg/__init__.py +6 -0
- deltacat/{catalog → experimental/catalog}/iceberg/iceberg_catalog_config.py +1 -1
- deltacat/{catalog → experimental/catalog}/iceberg/impl.py +43 -12
- deltacat/{catalog → experimental/catalog}/iceberg/overrides.py +12 -14
- deltacat/experimental/compatibility/backfill_locator_to_id_mappings.py +201 -0
- deltacat/experimental/converter_agent/__init__.py +0 -0
- deltacat/experimental/converter_agent/beam/__init__.py +0 -0
- deltacat/experimental/converter_agent/beam/managed.py +173 -0
- deltacat/experimental/converter_agent/table_monitor.py +479 -0
- deltacat/experimental/daft/__init__.py +4 -0
- deltacat/experimental/daft/daft_catalog.py +229 -0
- deltacat/experimental/storage/__init__.py +0 -0
- deltacat/experimental/storage/iceberg/__init__.py +0 -0
- deltacat/experimental/storage/iceberg/iceberg_scan_planner.py +129 -0
- deltacat/{storage → experimental/storage}/iceberg/impl.py +6 -4
- deltacat/{storage → experimental/storage}/iceberg/model.py +7 -3
- deltacat/experimental/storage/iceberg/visitor.py +119 -0
- deltacat/experimental/storage/rivulet/__init__.py +11 -0
- deltacat/experimental/storage/rivulet/arrow/__init__.py +0 -0
- deltacat/{storage → experimental/storage}/rivulet/arrow/serializer.py +7 -4
- deltacat/{storage → experimental/storage}/rivulet/dataset.py +13 -12
- deltacat/{storage → experimental/storage}/rivulet/dataset_executor.py +12 -20
- deltacat/experimental/storage/rivulet/feather/__init__.py +7 -0
- deltacat/{storage → experimental/storage}/rivulet/feather/file_reader.py +7 -5
- deltacat/{storage → experimental/storage}/rivulet/feather/serializer.py +4 -4
- deltacat/experimental/storage/rivulet/fs/__init__.py +0 -0
- deltacat/{storage → experimental/storage}/rivulet/fs/file_provider.py +3 -3
- deltacat/{storage → experimental/storage}/rivulet/fs/file_store.py +2 -2
- deltacat/{storage → experimental/storage}/rivulet/fs/output_file.py +1 -1
- deltacat/{storage → experimental/storage}/rivulet/logical_plan.py +4 -4
- deltacat/experimental/storage/rivulet/metastore/__init__.py +0 -0
- deltacat/{storage → experimental/storage}/rivulet/metastore/delta.py +1 -3
- deltacat/{storage → experimental/storage}/rivulet/metastore/json_sst.py +3 -3
- deltacat/{storage → experimental/storage}/rivulet/metastore/sst.py +2 -2
- deltacat/{storage → experimental/storage}/rivulet/metastore/sst_interval_tree.py +3 -3
- deltacat/experimental/storage/rivulet/parquet/__init__.py +7 -0
- deltacat/experimental/storage/rivulet/parquet/data_reader.py +0 -0
- deltacat/{storage → experimental/storage}/rivulet/parquet/file_reader.py +7 -5
- deltacat/{storage → experimental/storage}/rivulet/parquet/serializer.py +4 -4
- deltacat/experimental/storage/rivulet/reader/__init__.py +0 -0
- deltacat/{storage → experimental/storage}/rivulet/reader/block_scanner.py +20 -9
- deltacat/{storage → experimental/storage}/rivulet/reader/data_reader.py +3 -3
- deltacat/{storage → experimental/storage}/rivulet/reader/data_scan.py +5 -3
- deltacat/{storage → experimental/storage}/rivulet/reader/dataset_metastore.py +7 -6
- deltacat/{storage → experimental/storage}/rivulet/reader/dataset_reader.py +8 -6
- deltacat/{storage → experimental/storage}/rivulet/reader/pyarrow_data_reader.py +4 -1
- deltacat/{storage → experimental/storage}/rivulet/reader/reader_type_registrar.py +4 -4
- deltacat/experimental/storage/rivulet/schema/__init__.py +0 -0
- deltacat/{storage → experimental/storage}/rivulet/schema/schema.py +1 -1
- deltacat/{storage → experimental/storage}/rivulet/serializer.py +1 -1
- deltacat/{storage → experimental/storage}/rivulet/serializer_factory.py +9 -5
- deltacat/experimental/storage/rivulet/shard/__init__.py +0 -0
- deltacat/experimental/storage/rivulet/shard/range_shard.py +129 -0
- deltacat/experimental/storage/rivulet/writer/__init__.py +0 -0
- deltacat/{storage → experimental/storage}/rivulet/writer/memtable_dataset_writer.py +20 -9
- deltacat/io/__init__.py +13 -0
- deltacat/io/dataset/__init__.py +0 -0
- deltacat/io/dataset/deltacat_dataset.py +91 -0
- deltacat/io/datasink/__init__.py +0 -0
- deltacat/io/datasink/deltacat_datasink.py +207 -0
- deltacat/io/datasource/__init__.py +0 -0
- deltacat/io/datasource/deltacat_datasource.py +579 -0
- deltacat/io/reader/__init__.py +0 -0
- deltacat/io/reader/deltacat_read_api.py +172 -0
- deltacat/storage/__init__.py +22 -2
- deltacat/storage/interface.py +54 -32
- deltacat/storage/main/impl.py +1494 -541
- deltacat/storage/model/delta.py +27 -3
- deltacat/storage/model/expression/__init__.py +47 -0
- deltacat/storage/model/expression/expression.py +656 -0
- deltacat/storage/model/expression/visitor.py +248 -0
- deltacat/storage/model/locator.py +6 -12
- deltacat/storage/model/manifest.py +231 -6
- deltacat/storage/model/metafile.py +224 -119
- deltacat/storage/model/namespace.py +8 -1
- deltacat/storage/model/partition.py +117 -42
- deltacat/storage/model/scan/push_down.py +32 -5
- deltacat/storage/model/schema.py +2427 -159
- deltacat/storage/model/shard.py +6 -2
- deltacat/storage/model/sort_key.py +40 -0
- deltacat/storage/model/stream.py +9 -2
- deltacat/storage/model/table.py +12 -1
- deltacat/storage/model/table_version.py +11 -0
- deltacat/storage/model/transaction.py +1184 -208
- deltacat/storage/model/transform.py +81 -2
- deltacat/storage/model/types.py +53 -29
- deltacat/storage/util/__init__.py +0 -0
- deltacat/storage/util/scan_planner.py +26 -0
- deltacat/tests/_io/reader/__init__.py +0 -0
- deltacat/tests/_io/reader/test_deltacat_read_api.py +0 -0
- deltacat/tests/_io/test_cloudpickle_bug_fix.py +8 -4
- deltacat/tests/aws/test_s3u.py +2 -31
- deltacat/tests/catalog/data/__init__.py +0 -0
- deltacat/tests/catalog/main/__init__.py +0 -0
- deltacat/tests/catalog/main/test_catalog_impl_namespace_operations.py +130 -0
- deltacat/tests/catalog/main/test_catalog_impl_table_operations.py +1972 -0
- deltacat/tests/catalog/model/__init__.py +0 -0
- deltacat/tests/catalog/model/test_table_definition.py +16 -0
- deltacat/tests/catalog/test_catalogs.py +103 -106
- deltacat/tests/catalog/test_default_catalog_impl.py +12152 -72
- deltacat/tests/compute/compact_partition_test_cases.py +35 -8
- deltacat/tests/compute/compactor/steps/test_repartition.py +12 -12
- deltacat/tests/compute/compactor/utils/test_io.py +124 -120
- deltacat/tests/compute/compactor/utils/test_round_completion_reader.py +254 -0
- deltacat/tests/compute/compactor_v2/test_compaction_session.py +423 -312
- deltacat/tests/compute/compactor_v2/utils/test_content_type_params.py +266 -0
- deltacat/tests/compute/compactor_v2/utils/test_primary_key_index.py +45 -0
- deltacat/tests/compute/compactor_v2/utils/test_task_options.py +270 -1
- deltacat/tests/compute/conftest.py +8 -44
- deltacat/tests/compute/converter/test_convert_session.py +697 -349
- deltacat/tests/compute/converter/utils.py +15 -6
- deltacat/tests/compute/resource_estimation/test_delta.py +145 -79
- deltacat/tests/compute/test_compact_partition_incremental.py +103 -70
- deltacat/tests/compute/test_compact_partition_multiple_rounds.py +89 -66
- deltacat/tests/compute/test_compact_partition_params.py +13 -8
- deltacat/tests/compute/test_compact_partition_rebase.py +77 -62
- deltacat/tests/compute/test_compact_partition_rebase_then_incremental.py +263 -193
- deltacat/tests/compute/test_janitor.py +236 -0
- deltacat/tests/compute/test_util_common.py +716 -43
- deltacat/tests/compute/test_util_constant.py +0 -1
- deltacat/tests/{storage/conftest.py → conftest.py} +1 -1
- deltacat/tests/daft/__init__.py +0 -0
- deltacat/tests/daft/test_model.py +97 -0
- deltacat/tests/experimental/__init__.py +1 -0
- deltacat/tests/experimental/catalog/__init__.py +0 -0
- deltacat/tests/experimental/catalog/iceberg/__init__.py +0 -0
- deltacat/tests/experimental/catalog/iceberg/test_iceberg_catalog.py +71 -0
- deltacat/tests/experimental/compatibility/__init__.py +1 -0
- deltacat/tests/experimental/compatibility/test_backfill_locator_to_id_mappings.py +582 -0
- deltacat/tests/experimental/daft/__init__.py +0 -0
- deltacat/tests/experimental/daft/test_deltacat_daft_integration.py +136 -0
- deltacat/tests/experimental/storage/__init__.py +0 -0
- deltacat/tests/experimental/storage/rivulet/__init__.py +0 -0
- deltacat/tests/{storage → experimental/storage}/rivulet/conftest.py +3 -3
- deltacat/tests/experimental/storage/rivulet/fs/__init__.py +0 -0
- deltacat/tests/{storage → experimental/storage}/rivulet/fs/test_file_location_provider.py +3 -2
- deltacat/tests/experimental/storage/rivulet/reader/__init__.py +0 -0
- deltacat/tests/experimental/storage/rivulet/reader/query_expression.py +80 -0
- deltacat/tests/experimental/storage/rivulet/reader/test_data_scan.py +119 -0
- deltacat/tests/experimental/storage/rivulet/reader/test_dataset_metastore.py +71 -0
- deltacat/tests/experimental/storage/rivulet/schema/__init__.py +0 -0
- deltacat/tests/{storage → experimental/storage}/rivulet/schema/test_schema.py +1 -1
- deltacat/tests/experimental/storage/rivulet/shard/__init__.py +0 -0
- deltacat/tests/experimental/storage/rivulet/shard/test_range_shard.py +162 -0
- deltacat/tests/{storage → experimental/storage}/rivulet/test_dataset.py +6 -4
- deltacat/tests/{storage → experimental/storage}/rivulet/test_manifest.py +5 -5
- deltacat/tests/{storage → experimental/storage}/rivulet/test_sst_interval_tree.py +5 -5
- deltacat/tests/{storage → experimental/storage}/rivulet/test_utils.py +8 -6
- deltacat/tests/experimental/storage/rivulet/writer/__init__.py +0 -0
- deltacat/tests/{storage → experimental/storage}/rivulet/writer/test_dataset_write_then_read.py +11 -9
- deltacat/tests/{storage → experimental/storage}/rivulet/writer/test_dataset_writer.py +2 -2
- deltacat/tests/{storage → experimental/storage}/rivulet/writer/test_memtable_dataset_writer.py +7 -7
- deltacat/tests/storage/main/test_main_storage.py +6900 -95
- deltacat/tests/storage/model/test_expression.py +327 -0
- deltacat/tests/storage/model/test_manifest.py +129 -0
- deltacat/tests/storage/model/test_metafile_io.py +78 -173
- deltacat/tests/storage/model/test_partition_scheme.py +85 -0
- deltacat/tests/storage/model/test_schema.py +171 -0
- deltacat/tests/storage/model/test_schema_update.py +1925 -0
- deltacat/tests/storage/model/test_shard.py +3 -1
- deltacat/tests/storage/model/test_sort_scheme.py +90 -0
- deltacat/tests/storage/model/test_transaction.py +393 -48
- deltacat/tests/storage/model/test_transaction_history.py +886 -0
- deltacat/tests/test_deltacat_api.py +1036 -11
- deltacat/tests/test_exceptions.py +9 -5
- deltacat/tests/test_utils/pyarrow.py +52 -21
- deltacat/tests/test_utils/storage.py +23 -34
- deltacat/tests/types/__init__.py +0 -0
- deltacat/tests/types/test_tables.py +104 -0
- deltacat/tests/utils/exceptions.py +22 -0
- deltacat/tests/utils/main_deltacat_storage_mock.py +31 -0
- deltacat/tests/utils/ray_utils/test_dataset.py +123 -5
- deltacat/tests/utils/test_daft.py +121 -31
- deltacat/tests/utils/test_numpy.py +1193 -0
- deltacat/tests/utils/test_pandas.py +1106 -0
- deltacat/tests/utils/test_polars.py +1040 -0
- deltacat/tests/utils/test_pyarrow.py +1370 -89
- deltacat/types/media.py +345 -37
- deltacat/types/tables.py +2344 -46
- deltacat/utils/arguments.py +33 -1
- deltacat/utils/daft.py +824 -40
- deltacat/utils/export.py +3 -1
- deltacat/utils/filesystem.py +139 -9
- deltacat/utils/metafile_locator.py +2 -1
- deltacat/utils/numpy.py +118 -26
- deltacat/utils/pandas.py +577 -48
- deltacat/utils/polars.py +759 -0
- deltacat/utils/pyarrow.py +1373 -192
- deltacat/utils/ray_utils/concurrency.py +1 -1
- deltacat/utils/ray_utils/dataset.py +101 -10
- deltacat/utils/ray_utils/runtime.py +56 -4
- deltacat/utils/reader_compatibility_mapping.py +3083 -0
- deltacat/utils/url.py +1325 -0
- deltacat-2.0.0.dist-info/METADATA +1163 -0
- deltacat-2.0.0.dist-info/RECORD +439 -0
- {deltacat-2.0.dist-info → deltacat-2.0.0.dist-info}/WHEEL +1 -1
- deltacat/catalog/iceberg/__init__.py +0 -4
- deltacat/compute/compactor/utils/round_completion_file.py +0 -97
- deltacat/compute/merge_on_read/__init__.py +0 -4
- deltacat/compute/merge_on_read/daft.py +0 -40
- deltacat/compute/merge_on_read/model/merge_on_read_params.py +0 -66
- deltacat/compute/merge_on_read/utils/delta.py +0 -42
- deltacat/examples/common/fixtures.py +0 -15
- deltacat/storage/iceberg/iceberg_scan_planner.py +0 -28
- deltacat/storage/rivulet/__init__.py +0 -11
- deltacat/storage/rivulet/feather/__init__.py +0 -5
- deltacat/storage/rivulet/parquet/__init__.py +0 -5
- deltacat/tests/compute/compactor/utils/test_round_completion_file.py +0 -231
- deltacat/tests/compute/test_util_create_table_deltas_repo.py +0 -388
- deltacat/tests/local_deltacat_storage/__init__.py +0 -1235
- deltacat/tests/local_deltacat_storage/exceptions.py +0 -10
- deltacat/utils/s3fs.py +0 -21
- deltacat-2.0.dist-info/METADATA +0 -65
- deltacat-2.0.dist-info/RECORD +0 -347
- /deltacat/compute/{merge_on_read/model → jobs}/__init__.py +0 -0
- /deltacat/{compute/merge_on_read/utils → docs}/__init__.py +0 -0
- /deltacat/{examples/common → docs/autogen}/__init__.py +0 -0
- /deltacat/{examples/iceberg → docs/autogen/schema}/__init__.py +0 -0
- /deltacat/{storage/iceberg → docs/autogen/schema/inference}/__init__.py +0 -0
- /deltacat/{storage/rivulet/arrow → examples/compactor}/__init__.py +0 -0
- /deltacat/{storage/rivulet/fs → examples/experimental}/__init__.py +0 -0
- /deltacat/{storage/rivulet/metastore → examples/experimental/iceberg}/__init__.py +0 -0
- /deltacat/{storage/rivulet/reader → examples/experimental/iceberg/converter}/__init__.py +0 -0
- /deltacat/{storage/rivulet/schema → examples/experimental/iceberg/converter/beam}/__init__.py +0 -0
- /deltacat/{storage/rivulet/writer → examples/indexer}/__init__.py +0 -0
- /deltacat/{tests/storage/rivulet → examples/indexer/aws}/__init__.py +0 -0
- /deltacat/{tests/storage/rivulet/fs → examples/indexer/gcp}/__init__.py +0 -0
- /deltacat/{tests/storage/rivulet/schema → experimental}/__init__.py +0 -0
- /deltacat/{tests/storage/rivulet/writer → experimental/catalog}/__init__.py +0 -0
- /deltacat/{storage/rivulet/parquet/data_reader.py → experimental/compatibility/__init__.py} +0 -0
- /deltacat/{storage → experimental/storage}/rivulet/fs/input_file.py +0 -0
- /deltacat/{storage → experimental/storage}/rivulet/mvp/Table.py +0 -0
- /deltacat/{storage → experimental/storage}/rivulet/mvp/__init__.py +0 -0
- /deltacat/{storage → experimental/storage}/rivulet/reader/query_expression.py +0 -0
- /deltacat/{storage → experimental/storage}/rivulet/schema/datatype.py +0 -0
- /deltacat/{storage → experimental/storage}/rivulet/writer/dataset_writer.py +0 -0
- {deltacat-2.0.dist-info → deltacat-2.0.0.dist-info/licenses}/LICENSE +0 -0
- {deltacat-2.0.dist-info → deltacat-2.0.0.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,11 @@
|
|
1
1
|
from __future__ import annotations
|
2
|
+
|
3
|
+
import base64
|
2
4
|
from enum import Enum
|
3
5
|
from typing import Dict, Any, Optional
|
6
|
+
import pyarrow as pa
|
7
|
+
|
8
|
+
from deltacat.constants import METAFILE_FORMAT, METAFILE_FORMAT_JSON
|
4
9
|
|
5
10
|
|
6
11
|
class TransformName(str, Enum):
|
@@ -36,6 +41,18 @@ class BucketingStrategy(str, Enum):
|
|
36
41
|
ICEBERG = "iceberg"
|
37
42
|
|
38
43
|
|
44
|
+
class TruncateStrategy(str, Enum):
|
45
|
+
"""
|
46
|
+
A truncation strategy for the transform
|
47
|
+
"""
|
48
|
+
|
49
|
+
# Default DeltaCAT truncate strategy.
|
50
|
+
DEFAULT = "default"
|
51
|
+
|
52
|
+
# Iceberg-compliant truncate strategy.
|
53
|
+
ICEBERG = "iceberg"
|
54
|
+
|
55
|
+
|
39
56
|
class BucketTransformParameters(TransformParameters):
|
40
57
|
"""
|
41
58
|
Parameters for the bucket transform.
|
@@ -44,7 +61,7 @@ class BucketTransformParameters(TransformParameters):
|
|
44
61
|
@staticmethod
|
45
62
|
def of(
|
46
63
|
num_buckets: int,
|
47
|
-
bucketing_strategy: BucketingStrategy,
|
64
|
+
bucketing_strategy: BucketingStrategy = BucketingStrategy.DEFAULT,
|
48
65
|
) -> BucketTransformParameters:
|
49
66
|
bucket_transform_parameters = BucketTransformParameters()
|
50
67
|
bucket_transform_parameters["numBuckets"] = num_buckets
|
@@ -73,9 +90,13 @@ class TruncateTransformParameters(TransformParameters):
|
|
73
90
|
"""
|
74
91
|
|
75
92
|
@staticmethod
|
76
|
-
def of(
|
93
|
+
def of(
|
94
|
+
width: int,
|
95
|
+
truncate_strategy: TruncateStrategy = TruncateStrategy.DEFAULT,
|
96
|
+
) -> TruncateTransformParameters:
|
77
97
|
truncate_transform_parameters = TruncateTransformParameters()
|
78
98
|
truncate_transform_parameters["width"] = width
|
99
|
+
truncate_transform_parameters["truncateStrategy"] = truncate_strategy
|
79
100
|
return truncate_transform_parameters
|
80
101
|
|
81
102
|
@property
|
@@ -85,6 +106,13 @@ class TruncateTransformParameters(TransformParameters):
|
|
85
106
|
"""
|
86
107
|
return self["width"]
|
87
108
|
|
109
|
+
@property
|
110
|
+
def truncate_strategy(self) -> TruncateStrategy:
|
111
|
+
"""
|
112
|
+
The truncate strategy to use.
|
113
|
+
"""
|
114
|
+
return TruncateStrategy(self["truncateStrategy"])
|
115
|
+
|
88
116
|
|
89
117
|
class Transform(dict):
|
90
118
|
"""
|
@@ -112,10 +140,44 @@ class Transform(dict):
|
|
112
140
|
) -> None:
|
113
141
|
NAME_TO_TRANSFORM[self.name].parameters = parameters
|
114
142
|
|
143
|
+
@property
|
144
|
+
def return_type(self) -> Optional[pa.DataType]:
|
145
|
+
"""
|
146
|
+
The PyArrow data type that this transform returns.
|
147
|
+
A return value of "None" indicates that the return type is the same
|
148
|
+
as the source type. Transforms that always return null return pa.null().
|
149
|
+
"""
|
150
|
+
return_type = self.get("return_type")
|
151
|
+
if return_type is not None:
|
152
|
+
schema_bytes = (
|
153
|
+
base64.b64decode(return_type)
|
154
|
+
if METAFILE_FORMAT == METAFILE_FORMAT_JSON
|
155
|
+
else return_type
|
156
|
+
)
|
157
|
+
return_type = pa.ipc.read_schema(
|
158
|
+
pa.py_buffer(schema_bytes),
|
159
|
+
)[0].type
|
160
|
+
return return_type
|
161
|
+
|
162
|
+
@return_type.setter
|
163
|
+
def return_type(self, return_type: pa.Schema) -> None:
|
164
|
+
"""
|
165
|
+
Set the PyArrow data type that this transform returns.
|
166
|
+
"""
|
167
|
+
self["return_type"] = return_type.serialize().to_pybytes()
|
168
|
+
|
169
|
+
@property
|
170
|
+
def is_multi_field_transform(self) -> bool:
|
171
|
+
"""
|
172
|
+
Whether this transform is a multi-field transform.
|
173
|
+
"""
|
174
|
+
return False
|
175
|
+
|
115
176
|
|
116
177
|
class BucketTransform(Transform):
|
117
178
|
"""
|
118
179
|
A transform that hashes field values into a fixed number of buckets.
|
180
|
+
Returns a PyArrow int32() type.
|
119
181
|
"""
|
120
182
|
|
121
183
|
@staticmethod
|
@@ -123,6 +185,7 @@ class BucketTransform(Transform):
|
|
123
185
|
transform = BucketTransform()
|
124
186
|
transform.name = TransformName.BUCKET
|
125
187
|
transform.parameters = parameters
|
188
|
+
transform.return_type = pa.schema([("return_type", pa.int32())])
|
126
189
|
return transform
|
127
190
|
|
128
191
|
@property
|
@@ -139,10 +202,15 @@ class BucketTransform(Transform):
|
|
139
202
|
) -> None:
|
140
203
|
self["parameters"] = parameters
|
141
204
|
|
205
|
+
@property
|
206
|
+
def is_multi_field_transform(self) -> bool:
|
207
|
+
return True
|
208
|
+
|
142
209
|
|
143
210
|
class TruncateTransform(Transform):
|
144
211
|
"""
|
145
212
|
A transform that truncates field values to a fixed width.
|
213
|
+
Returns the same type as the input field.
|
146
214
|
"""
|
147
215
|
|
148
216
|
@staticmethod
|
@@ -170,6 +238,7 @@ class TruncateTransform(Transform):
|
|
170
238
|
class IdentityTransform(Transform):
|
171
239
|
"""
|
172
240
|
A no-op transform that returns unmodified field values.
|
241
|
+
Returns the same PyArrow type as the input.
|
173
242
|
"""
|
174
243
|
|
175
244
|
@staticmethod
|
@@ -182,60 +251,70 @@ class IdentityTransform(Transform):
|
|
182
251
|
class HourTransform(Transform):
|
183
252
|
"""
|
184
253
|
A transform that returns the hour of a datetime value.
|
254
|
+
Returns a PyArrow int32 type representing the hour (0-23).
|
185
255
|
"""
|
186
256
|
|
187
257
|
@staticmethod
|
188
258
|
def of() -> HourTransform:
|
189
259
|
transform = HourTransform()
|
190
260
|
transform.name = TransformName.HOUR
|
261
|
+
transform.return_type = pa.schema([("return_type", pa.int32())])
|
191
262
|
return transform
|
192
263
|
|
193
264
|
|
194
265
|
class DayTransform(Transform):
|
195
266
|
"""
|
196
267
|
A transform that returns the day of a datetime value.
|
268
|
+
Returns a PyArrow int32 type representing the day (1-31).
|
197
269
|
"""
|
198
270
|
|
199
271
|
@staticmethod
|
200
272
|
def of() -> DayTransform:
|
201
273
|
transform = DayTransform()
|
202
274
|
transform.name = TransformName.DAY
|
275
|
+
transform.return_type = pa.schema([("return_type", pa.int32())])
|
203
276
|
return transform
|
204
277
|
|
205
278
|
|
206
279
|
class MonthTransform(Transform):
|
207
280
|
"""
|
208
281
|
A transform that returns the month of a datetime value.
|
282
|
+
Returns a PyArrow int32 type representing the month (1-12).
|
209
283
|
"""
|
210
284
|
|
211
285
|
@staticmethod
|
212
286
|
def of() -> MonthTransform:
|
213
287
|
transform = MonthTransform()
|
214
288
|
transform.name = TransformName.MONTH
|
289
|
+
transform.return_type = pa.schema([("return_type", pa.int32())])
|
215
290
|
return transform
|
216
291
|
|
217
292
|
|
218
293
|
class YearTransform(Transform):
|
219
294
|
"""
|
220
295
|
A transform that returns the year of a datetime value.
|
296
|
+
Returns a PyArrow int32 type representing the year.
|
221
297
|
"""
|
222
298
|
|
223
299
|
@staticmethod
|
224
300
|
def of() -> YearTransform:
|
225
301
|
transform = YearTransform()
|
226
302
|
transform.name = TransformName.YEAR
|
303
|
+
transform.return_type = pa.schema([("return_type", pa.int32())])
|
227
304
|
return transform
|
228
305
|
|
229
306
|
|
230
307
|
class VoidTransform(Transform):
|
231
308
|
"""
|
232
309
|
A transform that coerces all field values to None.
|
310
|
+
Returns a PyArrow null type.
|
233
311
|
"""
|
234
312
|
|
235
313
|
@staticmethod
|
236
314
|
def of() -> VoidTransform:
|
237
315
|
transform = VoidTransform()
|
238
316
|
transform.name = TransformName.VOID
|
317
|
+
transform.return_type = pa.schema([("return_type", pa.null())])
|
239
318
|
return transform
|
240
319
|
|
241
320
|
|
deltacat/storage/model/types.py
CHANGED
@@ -6,23 +6,33 @@ from typing import List, Union
|
|
6
6
|
import numpy as np
|
7
7
|
import pandas as pd
|
8
8
|
import pyarrow as pa
|
9
|
-
|
9
|
+
import polars as pl
|
10
|
+
from ray.data.dataset import Dataset as RayDataset
|
10
11
|
from daft import DataFrame as DaftDataFrame
|
11
12
|
|
13
|
+
from deltacat.constants import (
|
14
|
+
RUNNING_TXN_DIR_NAME,
|
15
|
+
PAUSED_TXN_DIR_NAME,
|
16
|
+
FAILED_TXN_DIR_NAME,
|
17
|
+
SUCCESS_TXN_DIR_NAME,
|
18
|
+
)
|
12
19
|
|
13
20
|
LocalTable = Union[
|
14
21
|
pa.Table,
|
15
22
|
pd.DataFrame,
|
23
|
+
pl.DataFrame,
|
16
24
|
np.ndarray,
|
17
25
|
pa.parquet.ParquetFile,
|
18
26
|
]
|
19
|
-
LocalDataset = List[LocalTable]
|
20
|
-
DistributedDataset = Union[
|
27
|
+
LocalDataset = Union[LocalTable, List[LocalTable]]
|
28
|
+
DistributedDataset = Union[RayDataset, DaftDataFrame]
|
29
|
+
Dataset = Union[LocalDataset, DistributedDataset]
|
21
30
|
|
22
31
|
|
23
32
|
class StreamFormat(str, Enum):
|
24
33
|
DELTACAT = "deltacat"
|
25
34
|
ICEBERG = "iceberg"
|
35
|
+
HIVE = "hive"
|
26
36
|
HUDI = "hudi"
|
27
37
|
DELTA_LAKE = "delta_lake"
|
28
38
|
SQLITE3 = "SQLITE3" # used by tests
|
@@ -34,34 +44,10 @@ class DeltaType(str, Enum):
|
|
34
44
|
DELETE = "delete"
|
35
45
|
|
36
46
|
|
37
|
-
class TransactionType(str, Enum):
|
38
|
-
# the transaction reads existing data
|
39
|
-
# does not conflict with any other transaction types
|
40
|
-
READ = "read"
|
41
|
-
# the transaction only appends new data
|
42
|
-
# conflicts with other transaction types can be auto-resolved
|
43
|
-
APPEND = "append"
|
44
|
-
# the transaction alters existing data
|
45
|
-
# (even if it also appends data)
|
46
|
-
# conflicts with other alters/overwrites/restates/deletes fail
|
47
|
-
ALTER = "alter"
|
48
|
-
# the transaction overwrites existing data
|
49
|
-
# (even if it also appends or alters data)
|
50
|
-
# conflicts with other alters/overwrites/restates/deletes fail
|
51
|
-
OVERWRITE = "overwrite"
|
52
|
-
# the transaction restates existing data with a new layout
|
53
|
-
# (even if it appends, alters, or overwrites data to do so)
|
54
|
-
# conflicts with other alters/overwrites/restates/deletes fail
|
55
|
-
RESTATE = "restate"
|
56
|
-
# the transaction deletes existing data
|
57
|
-
# (even if it also appends, alters, overwrites, or restates data)
|
58
|
-
# conflicts with other alters/overwrites/restates/deletes fail
|
59
|
-
DELETE = "delete"
|
60
|
-
|
61
|
-
|
62
47
|
class TransactionOperationType(str, Enum):
|
63
48
|
CREATE = "create"
|
64
49
|
UPDATE = "update"
|
50
|
+
REPLACE = "replace"
|
65
51
|
DELETE = "delete"
|
66
52
|
|
67
53
|
READ_SIBLINGS = "read_siblings"
|
@@ -74,6 +60,7 @@ class TransactionOperationType(str, Enum):
|
|
74
60
|
return {
|
75
61
|
TransactionOperationType.CREATE,
|
76
62
|
TransactionOperationType.UPDATE,
|
63
|
+
TransactionOperationType.REPLACE,
|
77
64
|
TransactionOperationType.DELETE,
|
78
65
|
}
|
79
66
|
|
@@ -90,7 +77,44 @@ class TransactionOperationType(str, Enum):
|
|
90
77
|
return self in TransactionOperationType.write_operations()
|
91
78
|
|
92
79
|
def is_read_operation(self) -> bool:
|
93
|
-
return self in TransactionOperationType.
|
80
|
+
return self in TransactionOperationType.read_operations()
|
81
|
+
|
82
|
+
|
83
|
+
class TransactionStatus(str, Enum):
|
84
|
+
"""
|
85
|
+
Transaction user status types. Every transaction status maps to a distinct
|
86
|
+
transaction log directory.
|
87
|
+
"""
|
88
|
+
|
89
|
+
SUCCESS = "SUCCESS"
|
90
|
+
RUNNING = "RUNNING"
|
91
|
+
PAUSED = "PAUSED"
|
92
|
+
FAILED = "FAILED"
|
93
|
+
|
94
|
+
def dir_name(self) -> str:
|
95
|
+
if self == TransactionStatus.RUNNING:
|
96
|
+
return RUNNING_TXN_DIR_NAME
|
97
|
+
elif self == TransactionStatus.PAUSED:
|
98
|
+
return PAUSED_TXN_DIR_NAME
|
99
|
+
elif self == TransactionStatus.FAILED:
|
100
|
+
return FAILED_TXN_DIR_NAME
|
101
|
+
elif self == TransactionStatus.SUCCESS:
|
102
|
+
return SUCCESS_TXN_DIR_NAME
|
103
|
+
|
104
|
+
|
105
|
+
class TransactionState(str, Enum):
|
106
|
+
"""
|
107
|
+
Transaction system state types. Transaction states do not map to distinct transaction log directories,
|
108
|
+
but can be inferred by its presence in one or more directories. These states are used to infer whether
|
109
|
+
to run system activities like transaction cleanup jobs.
|
110
|
+
"""
|
111
|
+
|
112
|
+
FAILED = "FAILED"
|
113
|
+
PURGED = "PURGED"
|
114
|
+
TIMEOUT = "TIMEOUT"
|
115
|
+
RUNNING = "RUNNING"
|
116
|
+
SUCCESS = "SUCCESS"
|
117
|
+
PAUSED = "PAUSED"
|
94
118
|
|
95
119
|
|
96
120
|
class LifecycleState(str, Enum):
|
File without changes
|
@@ -0,0 +1,26 @@
|
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
from typing import Optional
|
3
|
+
|
4
|
+
from deltacat.storage.model.scan.push_down import Pushdown
|
5
|
+
from deltacat.storage.model.scan.scan_plan import ScanPlan
|
6
|
+
|
7
|
+
|
8
|
+
class ScanPlanner(ABC):
|
9
|
+
@abstractmethod
|
10
|
+
def create_scan_plan(
|
11
|
+
self,
|
12
|
+
table_name: str,
|
13
|
+
namespace: Optional[str] = None,
|
14
|
+
pushdown: Optional[Pushdown] = None,
|
15
|
+
) -> ScanPlan:
|
16
|
+
"""Return a ScanPlan for a given DeltaCAT Table after applying pushdown predicates
|
17
|
+
|
18
|
+
Args:
|
19
|
+
table: Name of the table
|
20
|
+
namespace: Optional namespace of the table. Uses default namespace if not specified.
|
21
|
+
pushdown: Pushdown predicates used to filter partitions/data files
|
22
|
+
|
23
|
+
Returns:
|
24
|
+
a ScanPlan object containing list of ScanTasks
|
25
|
+
"""
|
26
|
+
pass
|
File without changes
|
File without changes
|
@@ -45,7 +45,11 @@ class TestCloudpickleBugFix(unittest.TestCase):
|
|
45
45
|
def test_sanity(self):
|
46
46
|
ray.init(local_mode=True, ignore_reinit_error=True)
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
48
|
+
try:
|
49
|
+
result = ray.get(calculate_pickled_length.remote(AnyObject()))
|
50
|
+
|
51
|
+
self.assertTrue(result[0] < 1000)
|
52
|
+
self.assertTrue(result[1] >= 5000000)
|
53
|
+
finally:
|
54
|
+
if ray.is_initialized():
|
55
|
+
ray.shutdown()
|
deltacat/tests/aws/test_s3u.py
CHANGED
@@ -2,9 +2,8 @@ import unittest
|
|
2
2
|
|
3
3
|
import botocore
|
4
4
|
|
5
|
-
from deltacat.
|
6
|
-
from deltacat.
|
7
|
-
|
5
|
+
from deltacat.constants import RETRYABLE_TRANSIENT_ERRORS
|
6
|
+
from deltacat.types.tables import CapturedBlockWritePaths, UuidBlockWritePathProvider
|
8
7
|
|
9
8
|
import os
|
10
9
|
from unittest import mock
|
@@ -99,34 +98,6 @@ class TestDownloadUpload(unittest.TestCase):
|
|
99
98
|
|
100
99
|
assert mock_s3.put_object.call_count > 3
|
101
100
|
|
102
|
-
@patch("deltacat.aws.s3u.UPLOAD_SLICED_TABLE_RETRY_STOP_AFTER_DELAY", 1)
|
103
|
-
@patch("deltacat.aws.s3u.ManifestEntry")
|
104
|
-
@patch("deltacat.aws.s3u._get_metadata")
|
105
|
-
@patch("deltacat.aws.s3u.CapturedBlockWritePaths")
|
106
|
-
def test_upload_sliced_table_retry(
|
107
|
-
self,
|
108
|
-
mock_captured_block_write_paths,
|
109
|
-
mock_get_metadata,
|
110
|
-
mock_manifest_entry,
|
111
|
-
):
|
112
|
-
mock_manifest_entry.from_s3_obj_url.side_effect = OSError(
|
113
|
-
"Please reduce your request rate.."
|
114
|
-
)
|
115
|
-
mock_get_metadata.return_value = [mock.MagicMock()]
|
116
|
-
cbwp = CapturedBlockWritePaths()
|
117
|
-
cbwp._write_paths = ["s3_write_path"]
|
118
|
-
cbwp._block_refs = [mock.MagicMock()]
|
119
|
-
mock_captured_block_write_paths.return_value = cbwp
|
120
|
-
with pytest.raises(RetryError):
|
121
|
-
s3u.upload_sliced_table(
|
122
|
-
mock.MagicMock(),
|
123
|
-
"s3-prefix",
|
124
|
-
mock.MagicMock(),
|
125
|
-
mock.MagicMock(),
|
126
|
-
mock.MagicMock(),
|
127
|
-
mock.MagicMock(),
|
128
|
-
)
|
129
|
-
|
130
101
|
@patch("deltacat.aws.s3u.UPLOAD_DOWNLOAD_RETRY_STOP_AFTER_DELAY", 1)
|
131
102
|
@patch("deltacat.aws.s3u.s3_client_cache")
|
132
103
|
def test_upload_transient_error_retry(self, mock_s3_client_cache):
|
File without changes
|
File without changes
|
@@ -0,0 +1,130 @@
|
|
1
|
+
import shutil
|
2
|
+
|
3
|
+
from deltacat.catalog import get_catalog_properties
|
4
|
+
from deltacat.exceptions import NamespaceAlreadyExistsError
|
5
|
+
import pytest
|
6
|
+
import tempfile
|
7
|
+
import deltacat.catalog.main.impl as catalog
|
8
|
+
|
9
|
+
|
10
|
+
class TestCatalogNamespaceOperations:
|
11
|
+
temp_dir = None
|
12
|
+
property_catalog = None
|
13
|
+
catalog = None
|
14
|
+
|
15
|
+
@classmethod
|
16
|
+
def setup_class(cls):
|
17
|
+
cls.temp_dir = tempfile.mkdtemp()
|
18
|
+
cls.catalog_properties = get_catalog_properties(root=cls.temp_dir)
|
19
|
+
|
20
|
+
@classmethod
|
21
|
+
def teardown_class(cls):
|
22
|
+
shutil.rmtree(cls.temp_dir)
|
23
|
+
|
24
|
+
def test_create_namespace(self):
|
25
|
+
"""Test creating a namespace with properties"""
|
26
|
+
namespace = "test_create_namespace"
|
27
|
+
properties = {"description": "Test Namespace", "owner": "test-user"}
|
28
|
+
|
29
|
+
# Create namespace
|
30
|
+
catalog.create_namespace(
|
31
|
+
namespace=namespace, properties=properties, inner=self.catalog_properties
|
32
|
+
)
|
33
|
+
|
34
|
+
# Verify namespace exists
|
35
|
+
assert catalog.namespace_exists(namespace, inner=self.catalog_properties)
|
36
|
+
|
37
|
+
# Get namespace and verify properties
|
38
|
+
namespace = catalog.get_namespace(namespace, inner=self.catalog_properties)
|
39
|
+
assert namespace.namespace == "test_create_namespace"
|
40
|
+
assert namespace.properties["description"] == "Test Namespace"
|
41
|
+
|
42
|
+
def test_get_namespace(self):
|
43
|
+
"""Test getting namespace properties"""
|
44
|
+
namespace = "test_get_namespace"
|
45
|
+
properties = {"description": "foo", "created_by": "bar"}
|
46
|
+
|
47
|
+
# Create namespace
|
48
|
+
catalog.create_namespace(
|
49
|
+
namespace=namespace, properties=properties, inner=self.catalog_properties
|
50
|
+
)
|
51
|
+
|
52
|
+
# Get namespace properties
|
53
|
+
namespace = catalog.get_namespace(namespace, inner=self.catalog_properties)
|
54
|
+
|
55
|
+
# Verify properties
|
56
|
+
assert namespace.namespace == "test_get_namespace"
|
57
|
+
assert namespace.properties["created_by"] == "bar"
|
58
|
+
|
59
|
+
def test_namespace_exists(self):
|
60
|
+
"""Test checking if a namespace exists"""
|
61
|
+
existing_namespace = "test_namespace_exists"
|
62
|
+
non_existing_namespace = "non_existing_namespace"
|
63
|
+
|
64
|
+
# Create namespace
|
65
|
+
catalog.create_namespace(
|
66
|
+
namespace=existing_namespace, properties={}, inner=self.catalog_properties
|
67
|
+
)
|
68
|
+
|
69
|
+
# Check existing namespace
|
70
|
+
assert catalog.namespace_exists(
|
71
|
+
existing_namespace, inner=self.catalog_properties
|
72
|
+
)
|
73
|
+
|
74
|
+
# Check non-existing namespace
|
75
|
+
assert not catalog.namespace_exists(
|
76
|
+
non_existing_namespace, inner=self.catalog_properties
|
77
|
+
)
|
78
|
+
|
79
|
+
def test_create_namespace_already_exists(self):
|
80
|
+
"""Test creating a namespace that already exists should fail"""
|
81
|
+
namespace = "test_create_namespace_already_exists"
|
82
|
+
properties = {"description": "Test namespace", "owner": "test-user"}
|
83
|
+
|
84
|
+
# Create namespace first time
|
85
|
+
catalog.create_namespace(
|
86
|
+
namespace=namespace,
|
87
|
+
properties=properties,
|
88
|
+
inner=self.catalog_properties,
|
89
|
+
)
|
90
|
+
|
91
|
+
# Verify namespace exists
|
92
|
+
assert catalog.namespace_exists(namespace, inner=self.catalog_properties)
|
93
|
+
|
94
|
+
# Try to create the same namespace again, should raise ValueError
|
95
|
+
with pytest.raises(NamespaceAlreadyExistsError, match=namespace):
|
96
|
+
catalog.create_namespace(
|
97
|
+
namespace=namespace,
|
98
|
+
properties=properties,
|
99
|
+
inner=self.catalog_properties,
|
100
|
+
)
|
101
|
+
|
102
|
+
def test_drop_namespace(self):
|
103
|
+
"""Test dropping a namespace"""
|
104
|
+
namespace = "test_drop_namespace"
|
105
|
+
properties = {"description": "Test Namespace", "owner": "test-user"}
|
106
|
+
|
107
|
+
# Create namespace
|
108
|
+
catalog.create_namespace(
|
109
|
+
namespace=namespace,
|
110
|
+
properties=properties,
|
111
|
+
inner=self.catalog_properties,
|
112
|
+
)
|
113
|
+
|
114
|
+
# Verify namespace exists
|
115
|
+
assert catalog.namespace_exists(
|
116
|
+
namespace,
|
117
|
+
inner=self.catalog_properties,
|
118
|
+
)
|
119
|
+
|
120
|
+
# Drop namespace
|
121
|
+
catalog.drop_namespace(
|
122
|
+
namespace,
|
123
|
+
inner=self.catalog_properties,
|
124
|
+
)
|
125
|
+
|
126
|
+
# Verify namespace does not exist
|
127
|
+
assert not catalog.namespace_exists(
|
128
|
+
namespace,
|
129
|
+
inner=self.catalog_properties,
|
130
|
+
)
|