datamasque-python 1.2.5__tar.gz → 1.3.1__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.
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/.github/workflows/release.yml +24 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/HISTORY.rst +26 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/PKG-INFO +1 -1
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/RELEASING.rst +4 -25
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/__init__.py +4 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/connection.py +36 -2
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/discovery.py +9 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/pyproject.toml +1 -1
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/tests/test_connections.py +75 -6
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/tests/test_discovery.py +17 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/uv.lock +1 -1
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/.editorconfig +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/.github/workflows/ci.yml +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/.github/workflows/release-testpypi.yml +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/.gitignore +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/.readthedocs.yaml +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/CONTRIBUTING.rst +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/LICENSE +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/MANIFEST.in +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/Makefile +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/NOTICE +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/README.rst +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/base.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/connections.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/discovery.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/discovery_config_libraries.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/discovery_configs.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/dmclient.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/exceptions.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/files.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/ifm.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/license.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/__init__.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/data_selection.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/discovery_config.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/discovery_config_library.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/dm_instance.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/files.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/git.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/ifm.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/license.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/pagination.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/rg_config.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/ruleset.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/ruleset_library.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/runs.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/safe_data_preview.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/status.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/table_reference.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/user.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/py.typed +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/rg_configs.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/ruleset_libraries.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/rulesets.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/runs.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/settings.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/spcs.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/table_references.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/users.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/docs/Makefile +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/docs/client.models.rst +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/docs/client.rst +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/docs/conf.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/docs/contributing.rst +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/docs/history.rst +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/docs/index.rst +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/docs/installation.rst +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/docs/make.bat +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/docs/modules.rst +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/docs/readme.rst +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/docs/usage.rst +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/tests/__init__.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/tests/conftest.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/tests/helpers.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/tests/test_base.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/tests/test_discovery_config_libraries.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/tests/test_discovery_configs.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/tests/test_files.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/tests/test_ifm.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/tests/test_license.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/tests/test_pagination.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/tests/test_rg_configs.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/tests/test_ruleset_library.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/tests/test_rulesets.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/tests/test_runs.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/tests/test_safe_data_preview.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/tests/test_settings.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/tests/test_spcs.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/tests/test_table_references.py +0 -0
- {datamasque_python-1.2.5 → datamasque_python-1.3.1}/tests/test_users.py +0 -0
|
@@ -60,3 +60,27 @@ jobs:
|
|
|
60
60
|
|
|
61
61
|
- name: Publish to PyPI
|
|
62
62
|
uses: pypa/gh-action-pypi-publish@release/v1
|
|
63
|
+
|
|
64
|
+
github-release:
|
|
65
|
+
name: Publish GitHub Release
|
|
66
|
+
needs: publish
|
|
67
|
+
runs-on: ubuntu-latest
|
|
68
|
+
permissions:
|
|
69
|
+
contents: write
|
|
70
|
+
steps:
|
|
71
|
+
- name: Download distributions
|
|
72
|
+
uses: actions/download-artifact@v4
|
|
73
|
+
with:
|
|
74
|
+
name: dist
|
|
75
|
+
path: dist/
|
|
76
|
+
|
|
77
|
+
- name: Create GitHub Release
|
|
78
|
+
env:
|
|
79
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
80
|
+
run: |
|
|
81
|
+
gh release create "${GITHUB_REF_NAME}" \
|
|
82
|
+
--repo "${GITHUB_REPOSITORY}" \
|
|
83
|
+
--title "${GITHUB_REF_NAME}" \
|
|
84
|
+
--verify-tag \
|
|
85
|
+
--notes "See [HISTORY.rst](https://github.com/${GITHUB_REPOSITORY}/blob/${GITHUB_REF_NAME}/HISTORY.rst) for changelog." \
|
|
86
|
+
dist/*
|
|
@@ -2,6 +2,32 @@
|
|
|
2
2
|
History
|
|
3
3
|
=======
|
|
4
4
|
|
|
5
|
+
1.3.1 (2026-09-09)
|
|
6
|
+
------------------
|
|
7
|
+
|
|
8
|
+
* Added ``max_length_unit`` to ``SchemaDiscoveryColumn``, typed by the new ``LengthUnit`` enum
|
|
9
|
+
(``chars`` or ``bytes``), reporting the unit a column's ``max_length`` is counted in.
|
|
10
|
+
It is ``None`` for results from older servers that do not report a unit.
|
|
11
|
+
|
|
12
|
+
Requires server version 3.26.17
|
|
13
|
+
|
|
14
|
+
1.3.0 (2026-09-04)
|
|
15
|
+
------------------
|
|
16
|
+
|
|
17
|
+
* Added ``CosmosDbConnectionConfig`` and the ``cosmosdb`` ``DatabaseType``, for Azure Cosmos DB.
|
|
18
|
+
It differs from ``MongoConnectionConfig`` by ``db_type`` and three defaults: ``port`` 10255,
|
|
19
|
+
``tls`` on, because Cosmos DB only accepts TLS connections, and ``retry_writes`` off, because
|
|
20
|
+
Cosmos DB rejects retryable inserts.
|
|
21
|
+
|
|
22
|
+
* ``DatabaseConnectionConfig`` now rejects the ``documentdb`` and ``cosmosdb`` database types with a
|
|
23
|
+
message naming the class to use, as it already did for MongoDB, DynamoDB, Snowflake and Databricks.
|
|
24
|
+
|
|
25
|
+
* The MongoDB serializer prunes ``tls`` and ``retry_writes`` against the concrete class's default
|
|
26
|
+
rather than MongoDB's, so a Cosmos DB config that sets either the other way now sends it instead
|
|
27
|
+
of leaving the server to apply its own default.
|
|
28
|
+
|
|
29
|
+
Requires server version 3.26.17
|
|
30
|
+
|
|
5
31
|
1.2.5 (2026-08-17)
|
|
6
32
|
------------------
|
|
7
33
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: datamasque-python
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.1
|
|
4
4
|
Summary: Official Python client for the DataMasque data-masking API.
|
|
5
5
|
Project-URL: Homepage, https://datamasque.com/
|
|
6
6
|
Project-URL: Documentation, https://datamasque-python.readthedocs.io/
|
|
@@ -68,31 +68,10 @@ Releasing to PyPI
|
|
|
68
68
|
You can verify that the release appears at https://pypi.org/project/datamasque-python/,
|
|
69
69
|
and Read the Docs has built the new tag
|
|
70
70
|
at https://datamasque-python.readthedocs.io/.
|
|
71
|
-
5.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
Do this after the PyPI publish has succeeded,
|
|
77
|
-
so the release never points at a version nobody can install.
|
|
78
|
-
|
|
79
|
-
1. On the repository home page,
|
|
80
|
-
find **Releases** in the right-hand sidebar under the *About* box,
|
|
81
|
-
and click it,
|
|
82
|
-
then **Draft a new release**.
|
|
83
|
-
2. **Choose a tag** — pick the existing tag you pushed as part of releasing to PyPI.
|
|
84
|
-
Don't let GitHub create a new one; the tag should already exist from the release flow.
|
|
85
|
-
3. Set the target to ``main``.
|
|
86
|
-
4. Title it the same as the tag, e.g. ``v1.2.2``.
|
|
87
|
-
5. Paste the ``HISTORY.rst`` entry for this version into the body, converted to Markdown.
|
|
88
|
-
**Generate release notes** is a reasonable starting point for the commit list,
|
|
89
|
-
but the hand-written changelog is what users read.
|
|
90
|
-
6. Leave *Set as a pre-release* unticked for a normal release.
|
|
91
|
-
7. Click **Publish release**.
|
|
92
|
-
|
|
93
|
-
Creating releases can also be done from the ``gh`` CLI::
|
|
94
|
-
|
|
95
|
-
gh release create v1.2.2 --title v1.2.2 --notes-file notes.md
|
|
71
|
+
5. The GitHub Release is created automatically once the PyPI publish succeeds.
|
|
72
|
+
``release.yml`` runs a ``github-release`` job that creates the release for the pushed tag,
|
|
73
|
+
attaches the built distributions, and links to ``HISTORY.rst`` at that tag for the changelog.
|
|
74
|
+
Nothing to do by hand; just confirm it appears under **Releases** on the repository home page.
|
|
96
75
|
|
|
97
76
|
Releasing a dev build to TestPyPI
|
|
98
77
|
=================================
|
|
@@ -31,6 +31,7 @@ from datamasque.client.models.connection import (
|
|
|
31
31
|
AzureConnectionConfig,
|
|
32
32
|
ConnectionConfig,
|
|
33
33
|
ConnectionId,
|
|
34
|
+
CosmosDbConnectionConfig,
|
|
34
35
|
DatabaseConnectionConfig,
|
|
35
36
|
DatabaseType,
|
|
36
37
|
DatabricksConnectionConfig,
|
|
@@ -72,6 +73,7 @@ from datamasque.client.models.discovery import (
|
|
|
72
73
|
ForeignKeyRef,
|
|
73
74
|
InDataDiscoveryConfig,
|
|
74
75
|
InDataDiscoveryRule,
|
|
76
|
+
LengthUnit,
|
|
75
77
|
ReferencingForeignKey,
|
|
76
78
|
RulesetGenerationRequest,
|
|
77
79
|
RulesetGenerationWithRGConfigRequest,
|
|
@@ -203,6 +205,7 @@ __all__ = [
|
|
|
203
205
|
"DiscoveryConfigNotFoundError",
|
|
204
206
|
"DiscoveryConfigType",
|
|
205
207
|
"DiscoveryMatch",
|
|
208
|
+
"CosmosDbConnectionConfig",
|
|
206
209
|
"DocumentDbConnectionConfig",
|
|
207
210
|
"DynamoConnectionConfig",
|
|
208
211
|
"FailedToStartError",
|
|
@@ -237,6 +240,7 @@ __all__ = [
|
|
|
237
240
|
"InvalidRulesetError",
|
|
238
241
|
"JsonPath",
|
|
239
242
|
"LengthEntry",
|
|
243
|
+
"LengthUnit",
|
|
240
244
|
"LengthsStatistics",
|
|
241
245
|
"LicenseInfo",
|
|
242
246
|
"Locator",
|
|
@@ -45,6 +45,7 @@ class DatabaseType(Enum):
|
|
|
45
45
|
snowflake = "snowflake"
|
|
46
46
|
mongodb = "mongodb"
|
|
47
47
|
documentdb = "documentdb"
|
|
48
|
+
cosmosdb = "cosmosdb"
|
|
48
49
|
databricks_lakebase = "databricks_lakebase"
|
|
49
50
|
databricks = "databricks"
|
|
50
51
|
informix = "informix"
|
|
@@ -184,8 +185,11 @@ class MongoConnectionConfig(ConnectionConfig):
|
|
|
184
185
|
password = d.pop("password", None)
|
|
185
186
|
if password:
|
|
186
187
|
d["dbpassword"] = password
|
|
188
|
+
# `tls` and `retry_writes` are pruned against this class's own default, not MongoDB's:
|
|
189
|
+
# the subclasses invert them, so a hardcoded comparison would drop the very value the
|
|
190
|
+
# caller set and let the server apply its default instead.
|
|
191
|
+
defaults = type(self).model_fields
|
|
187
192
|
if not d.get("tls"):
|
|
188
|
-
d.pop("tls", None)
|
|
189
193
|
d.pop("tls_ca_file", None)
|
|
190
194
|
d.pop("tls_allow_invalid_certificates", None)
|
|
191
195
|
else:
|
|
@@ -193,9 +197,11 @@ class MongoConnectionConfig(ConnectionConfig):
|
|
|
193
197
|
d.pop("tls_ca_file", None)
|
|
194
198
|
if not d.get("tls_allow_invalid_certificates"):
|
|
195
199
|
d.pop("tls_allow_invalid_certificates", None)
|
|
200
|
+
if d.get("tls") == defaults["tls"].default:
|
|
201
|
+
d.pop("tls", None)
|
|
196
202
|
if not d.get("direct_connection"):
|
|
197
203
|
d.pop("direct_connection", None)
|
|
198
|
-
if d.get("retry_writes"
|
|
204
|
+
if d.get("retry_writes") == defaults["retry_writes"].default:
|
|
199
205
|
d.pop("retry_writes", None)
|
|
200
206
|
if not d.get("replica_set"):
|
|
201
207
|
d.pop("replica_set", None)
|
|
@@ -229,6 +235,29 @@ class DocumentDbConnectionConfig(MongoConnectionConfig):
|
|
|
229
235
|
return DatabaseType.documentdb
|
|
230
236
|
|
|
231
237
|
|
|
238
|
+
class CosmosDbConnectionConfig(MongoConnectionConfig):
|
|
239
|
+
"""
|
|
240
|
+
Connection configuration for an Azure Cosmos DB account.
|
|
241
|
+
|
|
242
|
+
Cosmos DB listens on 10255, only accepts TLS connections and rejects retryable inserts, so it
|
|
243
|
+
differs from `MongoConnectionConfig` by `db_type`/`database_type` and those three defaults.
|
|
244
|
+
|
|
245
|
+
They are defaults, not constraints. Setting one the other way sends it to the server: with
|
|
246
|
+
retryable writes on, masking still runs (it only updates) but the run-history insert is
|
|
247
|
+
rejected, so the run is not recorded.
|
|
248
|
+
"""
|
|
249
|
+
|
|
250
|
+
# Narrowing the inherited Literal is a deliberate Pydantic discriminator override.
|
|
251
|
+
db_type: Literal["cosmosdb"] = "cosmosdb" # type: ignore[assignment]
|
|
252
|
+
port: int = 10255
|
|
253
|
+
tls: bool = True
|
|
254
|
+
retry_writes: bool = False
|
|
255
|
+
|
|
256
|
+
@property
|
|
257
|
+
def database_type(self) -> DatabaseType:
|
|
258
|
+
return DatabaseType.cosmosdb
|
|
259
|
+
|
|
260
|
+
|
|
232
261
|
class SnowflakeConnectionConfig(ConnectionConfig):
|
|
233
262
|
"""
|
|
234
263
|
Connection configuration for a Snowflake database.
|
|
@@ -339,6 +368,10 @@ class DatabaseConnectionConfig(ConnectionConfig):
|
|
|
339
368
|
raise ValueError("For Snowflake, use the SnowflakeConnectionConfig class instead")
|
|
340
369
|
if self.database_type is DatabaseType.mongodb:
|
|
341
370
|
raise ValueError("For MongoDB, use the MongoConnectionConfig class instead")
|
|
371
|
+
if self.database_type is DatabaseType.documentdb:
|
|
372
|
+
raise ValueError("For AWS DocumentDB, use the DocumentDbConnectionConfig class instead")
|
|
373
|
+
if self.database_type is DatabaseType.cosmosdb:
|
|
374
|
+
raise ValueError("For Azure Cosmos DB, use the CosmosDbConnectionConfig class instead")
|
|
342
375
|
if self.database_type is DatabaseType.databricks:
|
|
343
376
|
raise ValueError("For Databricks SQL Warehouse, use the DatabricksConnectionConfig class instead")
|
|
344
377
|
return self
|
|
@@ -490,6 +523,7 @@ DB_TYPE_MAP: dict[str, type[ConnectionConfig]] = {
|
|
|
490
523
|
DatabaseType.dynamodb.value: DynamoConnectionConfig,
|
|
491
524
|
DatabaseType.mongodb.value: MongoConnectionConfig,
|
|
492
525
|
DatabaseType.documentdb.value: DocumentDbConnectionConfig,
|
|
526
|
+
DatabaseType.cosmosdb.value: CosmosDbConnectionConfig,
|
|
493
527
|
DatabaseType.snowflake.value: SnowflakeConnectionConfig,
|
|
494
528
|
DatabaseType.mssql_linked.value: MssqlLinkedServerConnectionConfig,
|
|
495
529
|
DatabaseType.databricks.value: DatabricksConnectionConfig,
|
|
@@ -367,6 +367,13 @@ class ReferencingForeignKey(BaseModel):
|
|
|
367
367
|
referencing_column: str # Dotted path: "schema.table.column".
|
|
368
368
|
|
|
369
369
|
|
|
370
|
+
class LengthUnit(Enum):
|
|
371
|
+
"""The unit a column's declared width (`max_length`) is counted in."""
|
|
372
|
+
|
|
373
|
+
chars = "chars"
|
|
374
|
+
bytes = "bytes"
|
|
375
|
+
|
|
376
|
+
|
|
370
377
|
class SchemaDiscoveryColumn(BaseModel):
|
|
371
378
|
"""Column-level data in a schema discovery result."""
|
|
372
379
|
|
|
@@ -374,6 +381,8 @@ class SchemaDiscoveryColumn(BaseModel):
|
|
|
374
381
|
|
|
375
382
|
data_type: Optional[str] = None
|
|
376
383
|
max_length: Optional[int] = None
|
|
384
|
+
# None when the server does not report a unit (older runs count chars).
|
|
385
|
+
max_length_unit: Optional[LengthUnit] = None
|
|
377
386
|
foreign_keys: list[ForeignKeyRef]
|
|
378
387
|
discovery_matches: list[DiscoveryMatch]
|
|
379
388
|
numeric_precision: Optional[int] = None
|
|
@@ -7,6 +7,7 @@ from datamasque.client.exceptions import DataMasqueApiError, DataMasqueException
|
|
|
7
7
|
from datamasque.client.models.connection import (
|
|
8
8
|
AzureConnectionConfig,
|
|
9
9
|
ConnectionId,
|
|
10
|
+
CosmosDbConnectionConfig,
|
|
10
11
|
DatabaseConnectionConfig,
|
|
11
12
|
DatabaseType,
|
|
12
13
|
DatabricksConnectionConfig,
|
|
@@ -1360,17 +1361,85 @@ def test_connection_config_dispatch_picks_documentdb_subclass():
|
|
|
1360
1361
|
assert conn.database_type is DatabaseType.documentdb
|
|
1361
1362
|
|
|
1362
1363
|
|
|
1363
|
-
def
|
|
1364
|
-
"""
|
|
1365
|
-
|
|
1364
|
+
def _cosmosdb_connection(**overrides) -> CosmosDbConnectionConfig:
|
|
1365
|
+
"""Build a Cosmos DB config, leaving the port to the connection type's own default."""
|
|
1366
|
+
return CosmosDbConnectionConfig(
|
|
1367
|
+
name="cosmos",
|
|
1368
|
+
host="dtq-cosmos.mongo.cosmos.azure.com",
|
|
1369
|
+
database="people",
|
|
1370
|
+
user="dtq-cosmos",
|
|
1371
|
+
password="hunter2",
|
|
1372
|
+
**overrides,
|
|
1373
|
+
)
|
|
1374
|
+
|
|
1375
|
+
|
|
1376
|
+
def test_cosmosdb_connection_defaults_port_tls_and_retry_writes():
|
|
1377
|
+
"""
|
|
1378
|
+
Cosmos DB listens on 10255, only accepts TLS connections and rejects retryable writes.
|
|
1379
|
+
|
|
1380
|
+
The config carries all three as defaults. `tls` and `retry_writes` are omitted from the payload
|
|
1381
|
+
because the server defaults the same way for this connection type; the port is always sent.
|
|
1382
|
+
"""
|
|
1383
|
+
conn = _cosmosdb_connection()
|
|
1384
|
+
d = conn.model_dump(exclude_none=True, by_alias=True, mode="json")
|
|
1385
|
+
assert d["db_type"] == "cosmosdb"
|
|
1386
|
+
assert d["mask_type"] == "database"
|
|
1387
|
+
assert conn.port == 10255
|
|
1388
|
+
assert d["port"] == 10255
|
|
1389
|
+
assert conn.tls is True
|
|
1390
|
+
assert conn.retry_writes is False
|
|
1391
|
+
assert "tls" not in d
|
|
1392
|
+
assert "retry_writes" not in d
|
|
1393
|
+
assert conn.database_type is DatabaseType.cosmosdb
|
|
1394
|
+
|
|
1395
|
+
|
|
1396
|
+
def test_cosmosdb_connection_sends_values_that_differ_from_its_own_defaults():
|
|
1397
|
+
"""
|
|
1398
|
+
The Mongo serializer prunes a field whose value matches the default the server would apply.
|
|
1399
|
+
|
|
1400
|
+
Cosmos DB inverts two of MongoDB's defaults, so pruning against MongoDB's would drop exactly
|
|
1401
|
+
the value the caller set and leave the server applying the opposite.
|
|
1402
|
+
"""
|
|
1403
|
+
d = _cosmosdb_connection(tls=False, retry_writes=True).model_dump(exclude_none=True, by_alias=True, mode="json")
|
|
1404
|
+
assert d["tls"] is False
|
|
1405
|
+
assert d["retry_writes"] is True
|
|
1406
|
+
|
|
1407
|
+
|
|
1408
|
+
def test_connection_config_dispatch_picks_cosmosdb_subclass():
|
|
1409
|
+
payload = {
|
|
1410
|
+
"id": "cosmos-id-1",
|
|
1411
|
+
"name": "cosmos",
|
|
1412
|
+
"mask_type": "database",
|
|
1413
|
+
"db_type": "cosmosdb",
|
|
1414
|
+
"host": "dtq-cosmos.mongo.cosmos.azure.com",
|
|
1415
|
+
"database": "people",
|
|
1416
|
+
}
|
|
1417
|
+
conn = validate_connection(payload)
|
|
1418
|
+
assert isinstance(conn, CosmosDbConnectionConfig)
|
|
1419
|
+
assert conn.database_type is DatabaseType.cosmosdb
|
|
1420
|
+
|
|
1421
|
+
|
|
1422
|
+
@pytest.mark.parametrize(
|
|
1423
|
+
("database_type", "message"),
|
|
1424
|
+
[
|
|
1425
|
+
(DatabaseType.mongodb, "For MongoDB"),
|
|
1426
|
+
(DatabaseType.documentdb, "For AWS DocumentDB"),
|
|
1427
|
+
(DatabaseType.cosmosdb, "For Azure Cosmos DB"),
|
|
1428
|
+
],
|
|
1429
|
+
)
|
|
1430
|
+
def test_database_connection_config_rejects_document_store_database_types(
|
|
1431
|
+
database_type: DatabaseType, message: str
|
|
1432
|
+
) -> None:
|
|
1433
|
+
"""`DatabaseConnectionConfig` is for SQL engines; each document store has its own class."""
|
|
1434
|
+
with pytest.raises(ValueError, match=message):
|
|
1366
1435
|
DatabaseConnectionConfig(
|
|
1367
|
-
name="
|
|
1368
|
-
host="
|
|
1436
|
+
name="doc-store",
|
|
1437
|
+
host="doc-store.example",
|
|
1369
1438
|
port=27017,
|
|
1370
1439
|
database="people",
|
|
1371
1440
|
user="alice",
|
|
1372
1441
|
password="hunter2",
|
|
1373
|
-
database_type=
|
|
1442
|
+
database_type=database_type,
|
|
1374
1443
|
)
|
|
1375
1444
|
|
|
1376
1445
|
|
|
@@ -21,6 +21,7 @@ from datamasque.client import (
|
|
|
21
21
|
FileRulesetGenerationRequest,
|
|
22
22
|
FileRulesetGenerationWithRGConfigRequest,
|
|
23
23
|
InDataDiscoveryConfig,
|
|
24
|
+
LengthUnit,
|
|
24
25
|
RGConfig,
|
|
25
26
|
RGConfigId,
|
|
26
27
|
RulesetGenerationRequest,
|
|
@@ -795,6 +796,22 @@ def test_schema_discovery_result_parses_safe_data_preview():
|
|
|
795
796
|
assert preview.statistics_common.count_distinct == 988
|
|
796
797
|
|
|
797
798
|
|
|
799
|
+
def test_schema_discovery_result_parses_max_length_unit() -> None:
|
|
800
|
+
row = _schema_discovery_row(1, "name")
|
|
801
|
+
row["data"]["max_length"] = 10
|
|
802
|
+
row["data"]["max_length_unit"] = "bytes"
|
|
803
|
+
result = SchemaDiscoveryResult.model_validate(row)
|
|
804
|
+
assert result.data.max_length == 10
|
|
805
|
+
assert result.data.max_length_unit is LengthUnit.bytes
|
|
806
|
+
|
|
807
|
+
|
|
808
|
+
def test_schema_discovery_result_without_max_length_unit_is_none() -> None:
|
|
809
|
+
row = _schema_discovery_row(1, "name")
|
|
810
|
+
assert "max_length_unit" not in row["data"]
|
|
811
|
+
result = SchemaDiscoveryResult.model_validate(row)
|
|
812
|
+
assert result.data.max_length_unit is None
|
|
813
|
+
|
|
814
|
+
|
|
798
815
|
def test_list_schema_discovery_results_follows_pagination(client):
|
|
799
816
|
run_id = RunId(42)
|
|
800
817
|
page1 = {
|
|
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
|
{datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/discovery_config_libraries.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/data_selection.py
RENAMED
|
File without changes
|
{datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/discovery_config.py
RENAMED
|
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
|
{datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/ruleset_library.py
RENAMED
|
File without changes
|
|
File without changes
|
{datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/safe_data_preview.py
RENAMED
|
File without changes
|
|
File without changes
|
{datamasque_python-1.2.5 → datamasque_python-1.3.1}/datamasque/client/models/table_reference.py
RENAMED
|
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
|
{datamasque_python-1.2.5 → datamasque_python-1.3.1}/tests/test_discovery_config_libraries.py
RENAMED
|
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
|