datamasque-python 1.2.4__py3-none-any.whl → 1.3.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.
@@ -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,
@@ -203,6 +204,7 @@ __all__ = [
203
204
  "DiscoveryConfigNotFoundError",
204
205
  "DiscoveryConfigType",
205
206
  "DiscoveryMatch",
207
+ "CosmosDbConnectionConfig",
206
208
  "DocumentDbConnectionConfig",
207
209
  "DynamoConnectionConfig",
208
210
  "FailedToStartError",
@@ -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", True):
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.
@@ -289,6 +318,22 @@ class SnowflakeConnectionConfig(ConnectionConfig):
289
318
  return data
290
319
 
291
320
 
321
+ # Engines that can sit behind an Amazon RDS, Aurora or Redshift endpoint, and so can carry a role
322
+ # for DataMasque to assume when tagging the resource. Aurora needs no entry of its own: it uses
323
+ # these same engines with a cluster endpoint.
324
+ _AWS_TAGGABLE_DATABASE_TYPES = frozenset(
325
+ {
326
+ DatabaseType.postgres,
327
+ DatabaseType.mysql,
328
+ DatabaseType.mariadb,
329
+ DatabaseType.oracle,
330
+ DatabaseType.mssql,
331
+ DatabaseType.db2_luw,
332
+ DatabaseType.redshift,
333
+ }
334
+ )
335
+
336
+
292
337
  class DatabaseConnectionConfig(ConnectionConfig):
293
338
  """
294
339
  Connection configuration for a SQL database.
@@ -309,6 +354,11 @@ class DatabaseConnectionConfig(ConnectionConfig):
309
354
  is_read_only: bool = False
310
355
  s3_bucket_name: Optional[str] = None
311
356
  s3_redshift_iam_role: Optional[str] = None
357
+ # An IAM role for DataMasque to assume when tagging this database's AWS resource after a run.
358
+ # Only the engines in `_AWS_TAGGABLE_DATABASE_TYPES` can be an RDS instance, Aurora cluster or
359
+ # Redshift cluster, so it is pruned for the rest. Distinct from `s3_redshift_iam_role`, which is
360
+ # the role the Redshift cluster itself uses to reach S3.
361
+ iam_role_arn: Optional[str] = None
312
362
 
313
363
  @model_validator(mode="after")
314
364
  def _reject_special_engines(self) -> "DatabaseConnectionConfig":
@@ -318,6 +368,10 @@ class DatabaseConnectionConfig(ConnectionConfig):
318
368
  raise ValueError("For Snowflake, use the SnowflakeConnectionConfig class instead")
319
369
  if self.database_type is DatabaseType.mongodb:
320
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")
321
375
  if self.database_type is DatabaseType.databricks:
322
376
  raise ValueError("For Databricks SQL Warehouse, use the DatabricksConnectionConfig class instead")
323
377
  return self
@@ -348,6 +402,8 @@ class DatabaseConnectionConfig(ConnectionConfig):
348
402
  if db_type is not DatabaseType.redshift:
349
403
  d.pop("s3_bucket_name", None)
350
404
  d.pop("s3_redshift_iam_role", None)
405
+ if db_type not in _AWS_TAGGABLE_DATABASE_TYPES:
406
+ d.pop("iam_role_arn", None)
351
407
  if not d.get("engine_options"):
352
408
  d.pop("engine_options", None)
353
409
  return d
@@ -467,6 +523,7 @@ DB_TYPE_MAP: dict[str, type[ConnectionConfig]] = {
467
523
  DatabaseType.dynamodb.value: DynamoConnectionConfig,
468
524
  DatabaseType.mongodb.value: MongoConnectionConfig,
469
525
  DatabaseType.documentdb.value: DocumentDbConnectionConfig,
526
+ DatabaseType.cosmosdb.value: CosmosDbConnectionConfig,
470
527
  DatabaseType.snowflake.value: SnowflakeConnectionConfig,
471
528
  DatabaseType.mssql_linked.value: MssqlLinkedServerConnectionConfig,
472
529
  DatabaseType.databricks.value: DatabricksConnectionConfig,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: datamasque-python
3
- Version: 1.2.4
3
+ Version: 1.3.0
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/
@@ -1,4 +1,4 @@
1
- datamasque/client/__init__.py,sha256=bw_5NEF3vLuOLKrT-z7UCkWaR_nFVkhE_RmY3Q9Y7sw,8707
1
+ datamasque/client/__init__.py,sha256=A_S4sw3m9hNFpW5RvAvK-qpIlLHIuUtH241Dip2VgBk,8769
2
2
  datamasque/client/base.py,sha256=cXU4dluL9e1N1F2pV48iIvebv6OHt7Kh4Ka2y9vkOPo,14296
3
3
  datamasque/client/connections.py,sha256=EFinx8fJRme0mTxuWY3d29UnmUFbsQhMaUQT0Ma2PK4,2885
4
4
  datamasque/client/discovery.py,sha256=xidiAj5LdVSGQy6pjta_2Z_aJmuPPohblyNDfua_Mxk,28859
@@ -19,7 +19,7 @@ datamasque/client/spcs.py,sha256=geHrBQ6WLWsMGpSMV8hmK5SFAwftrOU0DXkrR2orOmo,753
19
19
  datamasque/client/table_references.py,sha256=dPyB59Sz4iLuF1lc7xffgf9qeNTFA5srT55E8TnFLvk,6092
20
20
  datamasque/client/users.py,sha256=VCUo2CJyOw4-aO_3mp_w_0BcSoa6-h1HcReMcAMyumw,3701
21
21
  datamasque/client/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
- datamasque/client/models/connection.py,sha256=loLy4RCiIfY9kvBFspSqJSRhHqhcJxm_mQzXwMRS4VU,17529
22
+ datamasque/client/models/connection.py,sha256=W5WtzrrEfrZi7rUBMGcIZ7P6HRQ8PAC3btlD-07n4cY,20201
23
23
  datamasque/client/models/data_selection.py,sha256=9hRpkQQIQlKGFYDYQCrreggsv96dh6DelppCpCE4S2U,2725
24
24
  datamasque/client/models/discovery.py,sha256=J_cAXuIpoQTzHh_-1zvBwXsFnbKI2hRywALb5Yfc5vI,17955
25
25
  datamasque/client/models/discovery_config.py,sha256=8sqs9x_X0H_hR1fJDEFmOdJyGRDwgbdb3eddEAe98WE,2420
@@ -38,7 +38,7 @@ datamasque/client/models/safe_data_preview.py,sha256=BiI9d13KdQrTin2JfbjiRiODjns
38
38
  datamasque/client/models/status.py,sha256=DXcucL_jRsOQ0vaV0t8CJt6crvCIOLBn07KuwpwW-4A,3247
39
39
  datamasque/client/models/table_reference.py,sha256=55fKdHjC2TQnUmbp0XiWqfeFGXqcq4wXjbWgMaN3p3c,3835
40
40
  datamasque/client/models/user.py,sha256=UGAUzgJkf78m24_zFXXoA99zdut48BXkX_ivV8yq1Vc,2043
41
- datamasque_python-1.2.4.dist-info/METADATA,sha256=JfLuGmshJx1zHMoPocIbxfuO3H3jMKAJEa5hPTnKPNM,4497
42
- datamasque_python-1.2.4.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
43
- datamasque_python-1.2.4.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
44
- datamasque_python-1.2.4.dist-info/RECORD,,
41
+ datamasque_python-1.3.0.dist-info/METADATA,sha256=cDwoJ6gG2rHLCOv4zhi0OaNIG3VFpfOQkUVgCen5eaE,4497
42
+ datamasque_python-1.3.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
43
+ datamasque_python-1.3.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
44
+ datamasque_python-1.3.0.dist-info/RECORD,,