Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@
History
=======

1.2.0 (2026-07-22)
------------------

* Made discovery config libraries untyped, matching the DataMasque 3.26.14 server. A single
library is now identified by ``(namespace, name)`` and may be imported by both database and
file discovery configs. **Breaking:** removed the ``config_type`` field from
``DiscoveryConfigLibrary`` and the ``config_type`` argument from
``get_discovery_config_library_by_name``, ``create_or_update_discovery_config_library``, and
``delete_discovery_config_library_by_name_if_exists``. Requires a 3.26.14 or later server.

1.1.7 (2026-07-14)
------------------

Expand Down
40 changes: 14 additions & 26 deletions datamasque/client/discovery_config_libraries.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

from datamasque.client.base import BaseClient
from datamasque.client.exceptions import DataMasqueApiError
from datamasque.client.models.discovery_config import DiscoveryConfigType
from datamasque.client.models.discovery_config_library import DiscoveryConfigLibrary, DiscoveryConfigLibraryId

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -31,14 +30,12 @@ def get_discovery_config_library(self, library_id: DiscoveryConfigLibraryId) ->
response = self.make_request("GET", f"/api/discovery/config-libraries/{library_id}/")
return DiscoveryConfigLibrary.model_validate(response.json())

def _get_discovery_config_library_id_by_name(
self, name: str, config_type: DiscoveryConfigType, namespace: str
) -> Optional[DiscoveryConfigLibraryId]:
def _get_discovery_config_library_id_by_name(self, name: str, namespace: str) -> Optional[DiscoveryConfigLibraryId]:
"""
Returns the ID of the library with the given name, type, and namespace, or `None` if there is none.
Returns the ID of the library with the given name and namespace, or `None` if there is none.

The listing is filtered by name to keep the response small;
type and namespace are matched client-side,
the namespace is matched client-side,
since the API's namespace filter cannot select the default (empty) namespace.
"""

Expand All @@ -48,11 +45,7 @@ def _get_discovery_config_library_id_by_name(
params={"name_exact": name},
)
entries = [DiscoveryConfigLibrary.model_validate(item) for item in response.json()]
matches = [
entry
for entry in entries
if entry.name == name and entry.namespace == namespace and entry.config_type is config_type
]
matches = [entry for entry in entries if entry.name == name and entry.namespace == namespace]
if not matches:
return None

Expand All @@ -64,18 +57,15 @@ def _get_discovery_config_library_id_by_name(

return matches[0].id

def get_discovery_config_library_by_name(
self, name: str, config_type: DiscoveryConfigType, namespace: str = ""
) -> Optional[DiscoveryConfigLibrary]:
def get_discovery_config_library_by_name(self, name: str, namespace: str = "") -> Optional[DiscoveryConfigLibrary]:
"""
Looks for a discovery config library matching the given name, type, and namespace (case-sensitive, exact match).
Looks for a discovery config library matching the given name and namespace (case-sensitive, exact match).

Library names are unique per type within a namespace,
so a type is required to identify a single library.
Library names are unique within a namespace.
Returns it (with full YAML content) if found, otherwise `None`.
"""

library_id = self._get_discovery_config_library_id_by_name(name, config_type, namespace)
library_id = self._get_discovery_config_library_id_by_name(name, namespace)
if library_id is None:
return None

Expand Down Expand Up @@ -106,7 +96,6 @@ def update_discovery_config_library(self, library: DiscoveryConfigLibrary) -> Di

The library must have its `id` set (i.e., it must have been previously created or retrieved from the server)
and its `yaml` content present.
A library's `config_type` is fixed at creation and cannot be changed by an update.
"""

if library.id is None:
Expand All @@ -129,12 +118,12 @@ def update_discovery_config_library(self, library: DiscoveryConfigLibrary) -> Di

def create_or_update_discovery_config_library(self, library: DiscoveryConfigLibrary) -> DiscoveryConfigLibrary:
"""
Creates the library, or updates the existing one with the same name, namespace, and config type.
Creates the library, or updates the existing one with the same name and namespace.

Sets the library's `id` property.
"""

library_id = self._get_discovery_config_library_id_by_name(library.name, library.config_type, library.namespace)
library_id = self._get_discovery_config_library_id_by_name(library.name, library.namespace)
if library_id is not None:
library.id = library_id
return self.update_discovery_config_library(library)
Expand All @@ -157,16 +146,15 @@ def delete_discovery_config_library_by_id_if_exists(
self._delete_if_exists(f"/api/discovery/config-libraries/{library_id}/", params=params)

def delete_discovery_config_library_by_name_if_exists(
self, name: str, config_type: DiscoveryConfigType, namespace: str = "", *, force: bool = False
self, name: str, namespace: str = "", *, force: bool = False
) -> None:
"""
Deletes the discovery config library with the given name, type, and namespace.
Deletes the discovery config library with the given name and namespace.

Library names are unique per type within a namespace,
so a type is required to identify a single library.
Library names are unique within a namespace.
No-op if no such library exists.
"""

library_id = self._get_discovery_config_library_id_by_name(name, config_type, namespace)
library_id = self._get_discovery_config_library_id_by_name(name, namespace)
if library_id is not None:
self.delete_discovery_config_library_by_id_if_exists(library_id, force=force)
6 changes: 2 additions & 4 deletions datamasque/client/models/discovery_config_library.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

from pydantic import BaseModel, ConfigDict, Field

from datamasque.client.models.discovery_config import DiscoveryConfigType
from datamasque.client.models.status import ValidationStatus

DiscoveryConfigLibraryId = NewType("DiscoveryConfigLibraryId", str)
Expand All @@ -13,14 +12,13 @@ class DiscoveryConfigLibrary(BaseModel):
"""
Represents a named, namespaced, persisted YAML discovery config library.

Library names are unique per config type within a namespace,
so a database and a file library may share a name.
A library is untyped: the same library may be imported by both database and
file discovery configs, and its name is unique within a namespace.
"""

model_config = ConfigDict(extra="allow", populate_by_name=True)

name: str
config_type: DiscoveryConfigType
namespace: str = ""
yaml: Optional[str] = Field(default=None, alias="config_yaml")
# Server-populated read-only fields, excluded from request bodies.
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "datamasque-python"
version = "1.1.7"
version = "1.2.0"
description = "Official Python client for the DataMasque data-masking API."
authors = [
{ name = "DataMasque Ltd" },
Expand Down
Loading
Loading