datamasque-python 1.1.8__tar.gz → 1.2.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.
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/HISTORY.rst +10 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/PKG-INFO +1 -1
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/discovery_config_libraries.py +14 -26
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/models/discovery_config_library.py +2 -4
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/pyproject.toml +1 -1
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/setup.cfg +1 -1
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/tests/test_discovery_config_libraries.py +12 -142
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/uv.lock +1 -1
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/.editorconfig +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/.github/workflows/ci.yml +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/.github/workflows/release-testpypi.yml +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/.github/workflows/release.yml +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/.gitignore +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/.readthedocs.yaml +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/CONTRIBUTING.rst +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/LICENSE +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/MANIFEST.in +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/Makefile +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/NOTICE +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/README.rst +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/__init__.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/base.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/connections.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/discovery.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/discovery_configs.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/dmclient.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/exceptions.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/files.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/ifm.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/license.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/models/__init__.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/models/connection.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/models/data_selection.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/models/discovery.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/models/discovery_config.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/models/dm_instance.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/models/files.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/models/git.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/models/ifm.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/models/license.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/models/pagination.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/models/ruleset.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/models/ruleset_library.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/models/runs.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/models/safe_data_preview.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/models/status.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/models/table_reference.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/models/user.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/py.typed +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/ruleset_libraries.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/rulesets.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/runs.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/settings.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/spcs.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/table_references.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/users.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/docs/Makefile +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/docs/client.models.rst +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/docs/client.rst +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/docs/conf.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/docs/contributing.rst +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/docs/history.rst +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/docs/index.rst +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/docs/installation.rst +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/docs/make.bat +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/docs/modules.rst +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/docs/readme.rst +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/docs/usage.rst +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/tests/__init__.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/tests/conftest.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/tests/helpers.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/tests/test_base.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/tests/test_connections.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/tests/test_discovery.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/tests/test_discovery_configs.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/tests/test_files.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/tests/test_ifm.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/tests/test_license.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/tests/test_pagination.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/tests/test_ruleset_library.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/tests/test_rulesets.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/tests/test_runs.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/tests/test_safe_data_preview.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/tests/test_settings.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/tests/test_spcs.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/tests/test_table_references.py +0 -0
- {datamasque_python-1.1.8 → datamasque_python-1.2.0}/tests/test_users.py +0 -0
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
History
|
|
3
3
|
=======
|
|
4
4
|
|
|
5
|
+
1.2.0 (2026-07-27)
|
|
6
|
+
------------------
|
|
7
|
+
|
|
8
|
+
* Made discovery config libraries untyped, matching the DataMasque 3.26.14 server. A single
|
|
9
|
+
library is now identified by ``(namespace, name)`` and may be imported by both database and
|
|
10
|
+
file discovery configs. **Breaking:** removed the ``config_type`` field from
|
|
11
|
+
``DiscoveryConfigLibrary`` and the ``config_type`` argument from
|
|
12
|
+
``get_discovery_config_library_by_name``, ``create_or_update_discovery_config_library``, and
|
|
13
|
+
``delete_discovery_config_library_by_name_if_exists``. Requires a 3.26.14 or later server.
|
|
14
|
+
|
|
5
15
|
1.1.8 (2026-07-27)
|
|
6
16
|
------------------
|
|
7
17
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: datamasque-python
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2.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/
|
{datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/discovery_config_libraries.py
RENAMED
|
@@ -3,7 +3,6 @@ from typing import Optional
|
|
|
3
3
|
|
|
4
4
|
from datamasque.client.base import BaseClient
|
|
5
5
|
from datamasque.client.exceptions import DataMasqueApiError
|
|
6
|
-
from datamasque.client.models.discovery_config import DiscoveryConfigType
|
|
7
6
|
from datamasque.client.models.discovery_config_library import DiscoveryConfigLibrary, DiscoveryConfigLibraryId
|
|
8
7
|
|
|
9
8
|
logger = logging.getLogger(__name__)
|
|
@@ -31,14 +30,12 @@ class DiscoveryConfigLibraryClient(BaseClient):
|
|
|
31
30
|
response = self.make_request("GET", f"/api/discovery/config-libraries/{library_id}/")
|
|
32
31
|
return DiscoveryConfigLibrary.model_validate(response.json())
|
|
33
32
|
|
|
34
|
-
def _get_discovery_config_library_id_by_name(
|
|
35
|
-
self, name: str, config_type: DiscoveryConfigType, namespace: str
|
|
36
|
-
) -> Optional[DiscoveryConfigLibraryId]:
|
|
33
|
+
def _get_discovery_config_library_id_by_name(self, name: str, namespace: str) -> Optional[DiscoveryConfigLibraryId]:
|
|
37
34
|
"""
|
|
38
|
-
Returns the ID of the library with the given name
|
|
35
|
+
Returns the ID of the library with the given name and namespace, or `None` if there is none.
|
|
39
36
|
|
|
40
37
|
The listing is filtered by name to keep the response small;
|
|
41
|
-
|
|
38
|
+
the namespace is matched client-side,
|
|
42
39
|
since the API's namespace filter cannot select the default (empty) namespace.
|
|
43
40
|
"""
|
|
44
41
|
|
|
@@ -48,11 +45,7 @@ class DiscoveryConfigLibraryClient(BaseClient):
|
|
|
48
45
|
params={"name_exact": name},
|
|
49
46
|
)
|
|
50
47
|
entries = [DiscoveryConfigLibrary.model_validate(item) for item in response.json()]
|
|
51
|
-
matches = [
|
|
52
|
-
entry
|
|
53
|
-
for entry in entries
|
|
54
|
-
if entry.name == name and entry.namespace == namespace and entry.config_type is config_type
|
|
55
|
-
]
|
|
48
|
+
matches = [entry for entry in entries if entry.name == name and entry.namespace == namespace]
|
|
56
49
|
if not matches:
|
|
57
50
|
return None
|
|
58
51
|
|
|
@@ -64,18 +57,15 @@ class DiscoveryConfigLibraryClient(BaseClient):
|
|
|
64
57
|
|
|
65
58
|
return matches[0].id
|
|
66
59
|
|
|
67
|
-
def get_discovery_config_library_by_name(
|
|
68
|
-
self, name: str, config_type: DiscoveryConfigType, namespace: str = ""
|
|
69
|
-
) -> Optional[DiscoveryConfigLibrary]:
|
|
60
|
+
def get_discovery_config_library_by_name(self, name: str, namespace: str = "") -> Optional[DiscoveryConfigLibrary]:
|
|
70
61
|
"""
|
|
71
|
-
Looks for a discovery config library matching the given name
|
|
62
|
+
Looks for a discovery config library matching the given name and namespace (case-sensitive, exact match).
|
|
72
63
|
|
|
73
|
-
Library names are unique
|
|
74
|
-
so a type is required to identify a single library.
|
|
64
|
+
Library names are unique within a namespace.
|
|
75
65
|
Returns it (with full YAML content) if found, otherwise `None`.
|
|
76
66
|
"""
|
|
77
67
|
|
|
78
|
-
library_id = self._get_discovery_config_library_id_by_name(name,
|
|
68
|
+
library_id = self._get_discovery_config_library_id_by_name(name, namespace)
|
|
79
69
|
if library_id is None:
|
|
80
70
|
return None
|
|
81
71
|
|
|
@@ -106,7 +96,6 @@ class DiscoveryConfigLibraryClient(BaseClient):
|
|
|
106
96
|
|
|
107
97
|
The library must have its `id` set (i.e., it must have been previously created or retrieved from the server)
|
|
108
98
|
and its `yaml` content present.
|
|
109
|
-
A library's `config_type` is fixed at creation and cannot be changed by an update.
|
|
110
99
|
"""
|
|
111
100
|
|
|
112
101
|
if library.id is None:
|
|
@@ -129,12 +118,12 @@ class DiscoveryConfigLibraryClient(BaseClient):
|
|
|
129
118
|
|
|
130
119
|
def create_or_update_discovery_config_library(self, library: DiscoveryConfigLibrary) -> DiscoveryConfigLibrary:
|
|
131
120
|
"""
|
|
132
|
-
Creates the library, or updates the existing one with the same name
|
|
121
|
+
Creates the library, or updates the existing one with the same name and namespace.
|
|
133
122
|
|
|
134
123
|
Sets the library's `id` property.
|
|
135
124
|
"""
|
|
136
125
|
|
|
137
|
-
library_id = self._get_discovery_config_library_id_by_name(library.name, library.
|
|
126
|
+
library_id = self._get_discovery_config_library_id_by_name(library.name, library.namespace)
|
|
138
127
|
if library_id is not None:
|
|
139
128
|
library.id = library_id
|
|
140
129
|
return self.update_discovery_config_library(library)
|
|
@@ -157,16 +146,15 @@ class DiscoveryConfigLibraryClient(BaseClient):
|
|
|
157
146
|
self._delete_if_exists(f"/api/discovery/config-libraries/{library_id}/", params=params)
|
|
158
147
|
|
|
159
148
|
def delete_discovery_config_library_by_name_if_exists(
|
|
160
|
-
self, name: str,
|
|
149
|
+
self, name: str, namespace: str = "", *, force: bool = False
|
|
161
150
|
) -> None:
|
|
162
151
|
"""
|
|
163
|
-
Deletes the discovery config library with the given name
|
|
152
|
+
Deletes the discovery config library with the given name and namespace.
|
|
164
153
|
|
|
165
|
-
Library names are unique
|
|
166
|
-
so a type is required to identify a single library.
|
|
154
|
+
Library names are unique within a namespace.
|
|
167
155
|
No-op if no such library exists.
|
|
168
156
|
"""
|
|
169
157
|
|
|
170
|
-
library_id = self._get_discovery_config_library_id_by_name(name,
|
|
158
|
+
library_id = self._get_discovery_config_library_id_by_name(name, namespace)
|
|
171
159
|
if library_id is not None:
|
|
172
160
|
self.delete_discovery_config_library_by_id_if_exists(library_id, force=force)
|
|
@@ -3,7 +3,6 @@ from typing import NewType, Optional
|
|
|
3
3
|
|
|
4
4
|
from pydantic import BaseModel, ConfigDict, Field
|
|
5
5
|
|
|
6
|
-
from datamasque.client.models.discovery_config import DiscoveryConfigType
|
|
7
6
|
from datamasque.client.models.status import ValidationStatus
|
|
8
7
|
|
|
9
8
|
DiscoveryConfigLibraryId = NewType("DiscoveryConfigLibraryId", str)
|
|
@@ -13,14 +12,13 @@ class DiscoveryConfigLibrary(BaseModel):
|
|
|
13
12
|
"""
|
|
14
13
|
Represents a named, namespaced, persisted YAML discovery config library.
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
A library is untyped: the same library may be imported by both database and
|
|
16
|
+
file discovery configs, and its name is unique within a namespace.
|
|
18
17
|
"""
|
|
19
18
|
|
|
20
19
|
model_config = ConfigDict(extra="allow", populate_by_name=True)
|
|
21
20
|
|
|
22
21
|
name: str
|
|
23
|
-
config_type: DiscoveryConfigType
|
|
24
22
|
namespace: str = ""
|
|
25
23
|
yaml: Optional[str] = Field(default=None, alias="config_yaml")
|
|
26
24
|
# Server-populated read-only fields, excluded from request bodies.
|
{datamasque_python-1.1.8 → datamasque_python-1.2.0}/tests/test_discovery_config_libraries.py
RENAMED
|
@@ -5,13 +5,11 @@ from typing import Any
|
|
|
5
5
|
|
|
6
6
|
import pytest
|
|
7
7
|
import requests_mock
|
|
8
|
-
from pydantic import ValidationError
|
|
9
8
|
|
|
10
9
|
from datamasque.client import (
|
|
11
10
|
DataMasqueClient,
|
|
12
11
|
DiscoveryConfigLibrary,
|
|
13
12
|
DiscoveryConfigLibraryId,
|
|
14
|
-
DiscoveryConfigType,
|
|
15
13
|
)
|
|
16
14
|
from datamasque.client.exceptions import DataMasqueApiError
|
|
17
15
|
from datamasque.client.models.status import ValidationStatus
|
|
@@ -28,7 +26,6 @@ def sample_library_list_response() -> list[dict[str, Any]]:
|
|
|
28
26
|
"id": LIBRARY_ID_1,
|
|
29
27
|
"name": "my_library",
|
|
30
28
|
"namespace": "org",
|
|
31
|
-
"config_type": "database",
|
|
32
29
|
"is_valid": "valid",
|
|
33
30
|
"validation_error": None,
|
|
34
31
|
"usage_count": 0,
|
|
@@ -39,7 +36,6 @@ def sample_library_list_response() -> list[dict[str, Any]]:
|
|
|
39
36
|
"id": LIBRARY_ID_2,
|
|
40
37
|
"name": "another_library",
|
|
41
38
|
"namespace": "",
|
|
42
|
-
"config_type": "file",
|
|
43
39
|
"is_valid": "invalid",
|
|
44
40
|
"validation_error": "bad yaml",
|
|
45
41
|
"usage_count": 2,
|
|
@@ -56,7 +52,6 @@ def sample_library_detail_response() -> dict[str, Any]:
|
|
|
56
52
|
"id": LIBRARY_ID_1,
|
|
57
53
|
"name": "my_library",
|
|
58
54
|
"namespace": "org",
|
|
59
|
-
"config_type": "database",
|
|
60
55
|
"config_yaml": "labels: []\nmetadata_rules: []\nidd_rules: []\n",
|
|
61
56
|
"is_valid": "valid",
|
|
62
57
|
"validation_error": None,
|
|
@@ -66,44 +61,19 @@ def sample_library_detail_response() -> dict[str, Any]:
|
|
|
66
61
|
}
|
|
67
62
|
|
|
68
63
|
|
|
69
|
-
@pytest.fixture
|
|
70
|
-
def same_name_both_config_types() -> list[dict[str, Any]]:
|
|
71
|
-
"""Two libraries sharing (name, namespace) but with different config types, as the server allows."""
|
|
72
|
-
return [
|
|
73
|
-
{
|
|
74
|
-
"id": LIBRARY_ID_1,
|
|
75
|
-
"name": "my_library",
|
|
76
|
-
"namespace": "",
|
|
77
|
-
"config_type": "database",
|
|
78
|
-
"is_valid": "valid",
|
|
79
|
-
"created": "2025-01-01T12:00:00Z",
|
|
80
|
-
"modified": "2025-01-02T12:00:00Z",
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
"id": LIBRARY_ID_2,
|
|
84
|
-
"name": "my_library",
|
|
85
|
-
"namespace": "",
|
|
86
|
-
"config_type": "file",
|
|
87
|
-
"is_valid": "valid",
|
|
88
|
-
"created": "2025-01-01T12:00:00Z",
|
|
89
|
-
"modified": "2025-01-02T12:00:00Z",
|
|
90
|
-
},
|
|
91
|
-
]
|
|
92
|
-
|
|
93
|
-
|
|
94
64
|
@pytest.fixture
|
|
95
65
|
def config_library() -> DiscoveryConfigLibrary:
|
|
96
66
|
return DiscoveryConfigLibrary(
|
|
97
67
|
name="test_library",
|
|
98
68
|
namespace="test_ns",
|
|
99
|
-
config_type=DiscoveryConfigType.database,
|
|
100
69
|
yaml="labels: []\nmetadata_rules: []\nidd_rules: []\n",
|
|
101
70
|
)
|
|
102
71
|
|
|
103
72
|
|
|
104
|
-
def
|
|
105
|
-
|
|
106
|
-
|
|
73
|
+
def test_library_is_untyped() -> None:
|
|
74
|
+
"""A library carries no `config_type`; the same library serves both config types."""
|
|
75
|
+
library = DiscoveryConfigLibrary(name="test_library", yaml="labels: []\n")
|
|
76
|
+
assert "config_type" not in library.model_dump(by_alias=True)
|
|
107
77
|
|
|
108
78
|
|
|
109
79
|
def test_list_discovery_config_libraries(
|
|
@@ -121,12 +91,10 @@ def test_list_discovery_config_libraries(
|
|
|
121
91
|
assert libraries[0].id == DiscoveryConfigLibraryId(LIBRARY_ID_1)
|
|
122
92
|
assert libraries[0].name == "my_library"
|
|
123
93
|
assert libraries[0].namespace == "org"
|
|
124
|
-
assert libraries[0].config_type is DiscoveryConfigType.database
|
|
125
94
|
assert libraries[0].yaml is None
|
|
126
95
|
assert libraries[0].is_valid is ValidationStatus.valid
|
|
127
96
|
assert libraries[1].id == DiscoveryConfigLibraryId(LIBRARY_ID_2)
|
|
128
97
|
assert libraries[1].name == "another_library"
|
|
129
|
-
assert libraries[1].config_type is DiscoveryConfigType.file
|
|
130
98
|
assert libraries[1].is_valid is ValidationStatus.invalid
|
|
131
99
|
assert libraries[1].validation_error == "bad yaml"
|
|
132
100
|
|
|
@@ -155,7 +123,6 @@ def test_get_discovery_config_library(client: DataMasqueClient, sample_library_d
|
|
|
155
123
|
assert library.id == DiscoveryConfigLibraryId(LIBRARY_ID_1)
|
|
156
124
|
assert library.name == "my_library"
|
|
157
125
|
assert library.namespace == "org"
|
|
158
|
-
assert library.config_type is DiscoveryConfigType.database
|
|
159
126
|
assert library.yaml == "labels: []\nmetadata_rules: []\nidd_rules: []\n"
|
|
160
127
|
assert library.is_valid is ValidationStatus.valid
|
|
161
128
|
|
|
@@ -176,7 +143,7 @@ def test_get_discovery_config_library_by_name_found(
|
|
|
176
143
|
json=sample_library_detail_response,
|
|
177
144
|
status_code=200,
|
|
178
145
|
)
|
|
179
|
-
library = client.get_discovery_config_library_by_name("my_library",
|
|
146
|
+
library = client.get_discovery_config_library_by_name("my_library", "org")
|
|
180
147
|
|
|
181
148
|
assert library is not None
|
|
182
149
|
assert library.name == "my_library"
|
|
@@ -193,7 +160,6 @@ def test_get_discovery_config_library_by_name_matches_namespace_client_side(
|
|
|
193
160
|
"id": LIBRARY_ID_1,
|
|
194
161
|
"name": "my_library",
|
|
195
162
|
"namespace": "org",
|
|
196
|
-
"config_type": "database",
|
|
197
163
|
"is_valid": "valid",
|
|
198
164
|
"created": "2025-01-01T12:00:00Z",
|
|
199
165
|
"modified": "2025-01-02T12:00:00Z",
|
|
@@ -202,7 +168,6 @@ def test_get_discovery_config_library_by_name_matches_namespace_client_side(
|
|
|
202
168
|
"id": LIBRARY_ID_2,
|
|
203
169
|
"name": "my_library",
|
|
204
170
|
"namespace": "",
|
|
205
|
-
"config_type": "database",
|
|
206
171
|
"is_valid": "valid",
|
|
207
172
|
"created": "2025-01-01T12:00:00Z",
|
|
208
173
|
"modified": "2025-01-02T12:00:00Z",
|
|
@@ -220,7 +185,7 @@ def test_get_discovery_config_library_by_name_matches_namespace_client_side(
|
|
|
220
185
|
json=sample_library_detail_response,
|
|
221
186
|
status_code=200,
|
|
222
187
|
)
|
|
223
|
-
library = client.get_discovery_config_library_by_name("my_library",
|
|
188
|
+
library = client.get_discovery_config_library_by_name("my_library", "org")
|
|
224
189
|
|
|
225
190
|
assert library is not None
|
|
226
191
|
assert library.id == DiscoveryConfigLibraryId(LIBRARY_ID_1)
|
|
@@ -235,7 +200,7 @@ def test_get_discovery_config_library_by_name_default_namespace_does_not_match_o
|
|
|
235
200
|
json=[sample_library_list_response[0]],
|
|
236
201
|
status_code=200,
|
|
237
202
|
)
|
|
238
|
-
library = client.get_discovery_config_library_by_name("my_library"
|
|
203
|
+
library = client.get_discovery_config_library_by_name("my_library")
|
|
239
204
|
|
|
240
205
|
assert library is None
|
|
241
206
|
assert m.call_count == 1
|
|
@@ -248,50 +213,17 @@ def test_get_discovery_config_library_by_name_not_found(client: DataMasqueClient
|
|
|
248
213
|
json=[],
|
|
249
214
|
status_code=200,
|
|
250
215
|
)
|
|
251
|
-
library = client.get_discovery_config_library_by_name("nonexistent"
|
|
216
|
+
library = client.get_discovery_config_library_by_name("nonexistent")
|
|
252
217
|
|
|
253
218
|
assert library is None
|
|
254
219
|
|
|
255
220
|
|
|
256
|
-
def test_get_discovery_config_library_by_name_selects_matching_config_type(
|
|
257
|
-
client: DataMasqueClient, same_name_both_config_types: list[dict[str, Any]]
|
|
258
|
-
) -> None:
|
|
259
|
-
detail_response = {
|
|
260
|
-
"id": LIBRARY_ID_2,
|
|
261
|
-
"name": "my_library",
|
|
262
|
-
"namespace": "",
|
|
263
|
-
"config_type": "file",
|
|
264
|
-
"config_yaml": "labels: []\n",
|
|
265
|
-
"is_valid": "valid",
|
|
266
|
-
"created": "2025-01-01T12:00:00Z",
|
|
267
|
-
"modified": "2025-01-02T12:00:00Z",
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
with requests_mock.Mocker() as m:
|
|
271
|
-
m.get(
|
|
272
|
-
"http://test-server/api/discovery/config-libraries/",
|
|
273
|
-
json=same_name_both_config_types,
|
|
274
|
-
status_code=200,
|
|
275
|
-
)
|
|
276
|
-
m.get(
|
|
277
|
-
f"http://test-server/api/discovery/config-libraries/{LIBRARY_ID_2}/",
|
|
278
|
-
json=detail_response,
|
|
279
|
-
status_code=200,
|
|
280
|
-
)
|
|
281
|
-
library = client.get_discovery_config_library_by_name("my_library", DiscoveryConfigType.file)
|
|
282
|
-
|
|
283
|
-
assert library is not None
|
|
284
|
-
assert library.id == DiscoveryConfigLibraryId(LIBRARY_ID_2)
|
|
285
|
-
assert library.config_type is DiscoveryConfigType.file
|
|
286
|
-
|
|
287
|
-
|
|
288
221
|
def test_get_discovery_config_library_by_name_raises_when_server_omits_id(client: DataMasqueClient) -> None:
|
|
289
222
|
"""If the server returns a list entry without `id`, the by-name lookup surfaces a typed API error."""
|
|
290
223
|
list_response_without_id = [
|
|
291
224
|
{
|
|
292
225
|
"name": "my_library",
|
|
293
226
|
"namespace": "org",
|
|
294
|
-
"config_type": "database",
|
|
295
227
|
"is_valid": "valid",
|
|
296
228
|
"created": "2025-01-01T12:00:00Z",
|
|
297
229
|
"modified": "2025-01-02T12:00:00Z",
|
|
@@ -305,7 +237,7 @@ def test_get_discovery_config_library_by_name_raises_when_server_omits_id(client
|
|
|
305
237
|
status_code=200,
|
|
306
238
|
)
|
|
307
239
|
with pytest.raises(DataMasqueApiError, match="without an `id`"):
|
|
308
|
-
client.get_discovery_config_library_by_name("my_library",
|
|
240
|
+
client.get_discovery_config_library_by_name("my_library", "org")
|
|
309
241
|
|
|
310
242
|
|
|
311
243
|
def test_create_discovery_config_library(client: DataMasqueClient, config_library: DiscoveryConfigLibrary) -> None:
|
|
@@ -313,7 +245,6 @@ def test_create_discovery_config_library(client: DataMasqueClient, config_librar
|
|
|
313
245
|
"id": LIBRARY_ID_1,
|
|
314
246
|
"name": "test_library",
|
|
315
247
|
"namespace": "test_ns",
|
|
316
|
-
"config_type": "database",
|
|
317
248
|
"config_yaml": "labels: []\nmetadata_rules: []\nidd_rules: []\n",
|
|
318
249
|
"is_valid": "valid",
|
|
319
250
|
"validation_error": None,
|
|
@@ -338,7 +269,7 @@ def test_create_discovery_config_library(client: DataMasqueClient, config_librar
|
|
|
338
269
|
request_body = m.last_request.json()
|
|
339
270
|
assert request_body["name"] == "test_library"
|
|
340
271
|
assert request_body["namespace"] == "test_ns"
|
|
341
|
-
assert
|
|
272
|
+
assert "config_type" not in request_body
|
|
342
273
|
assert request_body["config_yaml"] == "labels: []\nmetadata_rules: []\nidd_rules: []\n"
|
|
343
274
|
read_only_fields = {"id", "is_valid", "validation_error", "created", "modified"}
|
|
344
275
|
assert not read_only_fields & request_body.keys()
|
|
@@ -351,7 +282,6 @@ def test_create_discovery_config_library_reports_validation_error(
|
|
|
351
282
|
"id": LIBRARY_ID_1,
|
|
352
283
|
"name": "test_library",
|
|
353
284
|
"namespace": "test_ns",
|
|
354
|
-
"config_type": "database",
|
|
355
285
|
"config_yaml": "labels: []\nmetadata_rules: []\nidd_rules: []\n",
|
|
356
286
|
"is_valid": "invalid",
|
|
357
287
|
"validation_error": "metadata_rules is not a list",
|
|
@@ -379,7 +309,6 @@ def test_update_discovery_config_library(client: DataMasqueClient, config_librar
|
|
|
379
309
|
"id": LIBRARY_ID_1,
|
|
380
310
|
"name": "test_library",
|
|
381
311
|
"namespace": "test_ns",
|
|
382
|
-
"config_type": "database",
|
|
383
312
|
"config_yaml": "labels: []\nmetadata_rules: []\nidd_rules: []\n",
|
|
384
313
|
"is_valid": "valid",
|
|
385
314
|
"validation_error": None,
|
|
@@ -431,7 +360,6 @@ def test_create_or_update_discovery_config_library_create(
|
|
|
431
360
|
"id": LIBRARY_ID_1,
|
|
432
361
|
"name": "test_library",
|
|
433
362
|
"namespace": "test_ns",
|
|
434
|
-
"config_type": "database",
|
|
435
363
|
"config_yaml": "labels: []\nmetadata_rules: []\nidd_rules: []\n",
|
|
436
364
|
"is_valid": "valid",
|
|
437
365
|
"validation_error": None,
|
|
@@ -466,7 +394,6 @@ def test_create_or_update_discovery_config_library_update(
|
|
|
466
394
|
"id": LIBRARY_ID_1,
|
|
467
395
|
"name": "test_library",
|
|
468
396
|
"namespace": "test_ns",
|
|
469
|
-
"config_type": "database",
|
|
470
397
|
"is_valid": "valid",
|
|
471
398
|
"created": "2025-06-01T10:00:00Z",
|
|
472
399
|
"modified": "2025-06-01T10:00:00Z",
|
|
@@ -476,7 +403,6 @@ def test_create_or_update_discovery_config_library_update(
|
|
|
476
403
|
"id": LIBRARY_ID_1,
|
|
477
404
|
"name": "test_library",
|
|
478
405
|
"namespace": "test_ns",
|
|
479
|
-
"config_type": "database",
|
|
480
406
|
"config_yaml": "labels: []\nmetadata_rules: []\nidd_rules: []\n",
|
|
481
407
|
"is_valid": "valid",
|
|
482
408
|
"validation_error": None,
|
|
@@ -503,42 +429,6 @@ def test_create_or_update_discovery_config_library_update(
|
|
|
503
429
|
assert m.request_history[1].method == "PUT"
|
|
504
430
|
|
|
505
431
|
|
|
506
|
-
def test_create_or_update_discovery_config_library_matches_config_type(
|
|
507
|
-
client: DataMasqueClient, same_name_both_config_types: list[dict[str, Any]]
|
|
508
|
-
) -> None:
|
|
509
|
-
file_library = DiscoveryConfigLibrary(
|
|
510
|
-
name="my_library",
|
|
511
|
-
config_type=DiscoveryConfigType.file,
|
|
512
|
-
yaml="labels: []\n",
|
|
513
|
-
)
|
|
514
|
-
update_response = {
|
|
515
|
-
"id": LIBRARY_ID_2,
|
|
516
|
-
"name": "my_library",
|
|
517
|
-
"namespace": "",
|
|
518
|
-
"config_type": "file",
|
|
519
|
-
"config_yaml": "labels: []\n",
|
|
520
|
-
"is_valid": "valid",
|
|
521
|
-
"validation_error": None,
|
|
522
|
-
"created": "2025-01-01T12:00:00Z",
|
|
523
|
-
"modified": "2025-01-03T12:00:00Z",
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
with requests_mock.Mocker() as m:
|
|
527
|
-
m.get(
|
|
528
|
-
"http://test-server/api/discovery/config-libraries/",
|
|
529
|
-
json=same_name_both_config_types,
|
|
530
|
-
status_code=200,
|
|
531
|
-
)
|
|
532
|
-
m.put(
|
|
533
|
-
f"http://test-server/api/discovery/config-libraries/{LIBRARY_ID_2}/",
|
|
534
|
-
json=update_response,
|
|
535
|
-
status_code=200,
|
|
536
|
-
)
|
|
537
|
-
result = client.create_or_update_discovery_config_library(file_library)
|
|
538
|
-
|
|
539
|
-
assert result.id == DiscoveryConfigLibraryId(LIBRARY_ID_2)
|
|
540
|
-
|
|
541
|
-
|
|
542
432
|
def test_delete_discovery_config_library_by_id(client: DataMasqueClient) -> None:
|
|
543
433
|
with requests_mock.Mocker() as m:
|
|
544
434
|
m.delete(
|
|
@@ -583,33 +473,13 @@ def test_delete_discovery_config_library_by_name(
|
|
|
583
473
|
f"http://test-server/api/discovery/config-libraries/{LIBRARY_ID_1}/",
|
|
584
474
|
status_code=204,
|
|
585
475
|
)
|
|
586
|
-
client.delete_discovery_config_library_by_name_if_exists("my_library",
|
|
476
|
+
client.delete_discovery_config_library_by_name_if_exists("my_library", "org")
|
|
587
477
|
|
|
588
478
|
assert m.request_history[0].method == "GET"
|
|
589
479
|
assert "name_exact=my_library" in m.request_history[0].url
|
|
590
480
|
assert m.request_history[1].method == "DELETE"
|
|
591
481
|
|
|
592
482
|
|
|
593
|
-
def test_delete_discovery_config_library_by_name_deletes_only_matching_config_type(
|
|
594
|
-
client: DataMasqueClient, same_name_both_config_types: list[dict[str, Any]]
|
|
595
|
-
) -> None:
|
|
596
|
-
with requests_mock.Mocker() as m:
|
|
597
|
-
m.get(
|
|
598
|
-
"http://test-server/api/discovery/config-libraries/",
|
|
599
|
-
json=same_name_both_config_types,
|
|
600
|
-
status_code=200,
|
|
601
|
-
)
|
|
602
|
-
m.delete(
|
|
603
|
-
f"http://test-server/api/discovery/config-libraries/{LIBRARY_ID_2}/",
|
|
604
|
-
status_code=204,
|
|
605
|
-
)
|
|
606
|
-
client.delete_discovery_config_library_by_name_if_exists("my_library", DiscoveryConfigType.file)
|
|
607
|
-
|
|
608
|
-
assert m.call_count == 2
|
|
609
|
-
assert m.request_history[1].method == "DELETE"
|
|
610
|
-
assert LIBRARY_ID_2 in m.request_history[1].url
|
|
611
|
-
|
|
612
|
-
|
|
613
483
|
def test_delete_discovery_config_library_by_name_not_found(
|
|
614
484
|
client: DataMasqueClient, sample_library_list_response: list[dict[str, Any]]
|
|
615
485
|
) -> None:
|
|
@@ -619,7 +489,7 @@ def test_delete_discovery_config_library_by_name_not_found(
|
|
|
619
489
|
json=sample_library_list_response,
|
|
620
490
|
status_code=200,
|
|
621
491
|
)
|
|
622
|
-
client.delete_discovery_config_library_by_name_if_exists("nonexistent"
|
|
492
|
+
client.delete_discovery_config_library_by_name_if_exists("nonexistent")
|
|
623
493
|
|
|
624
494
|
assert m.call_count == 1
|
|
625
495
|
assert m.request_history[0].method == "GET"
|
|
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.1.8 → datamasque_python-1.2.0}/datamasque/client/models/data_selection.py
RENAMED
|
File without changes
|
|
File without changes
|
{datamasque_python-1.1.8 → datamasque_python-1.2.0}/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
|
{datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/models/ruleset_library.py
RENAMED
|
File without changes
|
|
File without changes
|
{datamasque_python-1.1.8 → datamasque_python-1.2.0}/datamasque/client/models/safe_data_preview.py
RENAMED
|
File without changes
|
|
File without changes
|
{datamasque_python-1.1.8 → datamasque_python-1.2.0}/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
|
|
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
|