dapla-toolbelt-metadata 0.9.7__py3-none-any.whl → 0.9.8__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.

Potentially problematic release.


This version of dapla-toolbelt-metadata might be problematic. Click here for more details.

@@ -13,9 +13,6 @@ from dotenv import load_dotenv
13
13
  from dapla_metadata._shared.enums import DaplaEnvironment
14
14
  from dapla_metadata._shared.enums import DaplaRegion
15
15
  from dapla_metadata._shared.enums import DaplaService
16
- from dapla_metadata.datasets.utility.constants import (
17
- DATADOC_STATISTICAL_SUBJECT_SOURCE_URL,
18
- )
19
16
 
20
17
  logger = logging.getLogger(__name__)
21
18
 
@@ -28,6 +25,12 @@ DAPLA_SERVICE = "DAPLA_SERVICE"
28
25
  DAPLA_GROUP_CONTEXT = "DAPLA_GROUP_CONTEXT"
29
26
  OIDC_TOKEN = "OIDC_TOKEN" # noqa: S105
30
27
 
28
+
29
+ DATADOC_STATISTICAL_SUBJECT_SOURCE_URL_DEFAULT = (
30
+ "https://www.ssb.no/xp/_/service/mimir/subjectStructurStatistics"
31
+ )
32
+
33
+
31
34
  env_loaded = False
32
35
 
33
36
 
@@ -73,7 +76,7 @@ def get_statistical_subject_source_url() -> str | None:
73
76
  """Get the URL to the statistical subject source."""
74
77
  return (
75
78
  get_config_item("DATADOC_STATISTICAL_SUBJECT_SOURCE_URL")
76
- or DATADOC_STATISTICAL_SUBJECT_SOURCE_URL
79
+ or DATADOC_STATISTICAL_SUBJECT_SOURCE_URL_DEFAULT
77
80
  )
78
81
 
79
82
 
@@ -94,10 +94,6 @@ DATASET_FIELDS_FROM_EXISTING_METADATA = [
94
94
 
95
95
  METADATA_DOCUMENT_FILE_SUFFIX = "__DOC.json"
96
96
 
97
- DATADOC_STATISTICAL_SUBJECT_SOURCE_URL = (
98
- "https://www.ssb.no/xp/_/service/mimir/subjectStructurStatistics"
99
- )
100
-
101
97
  PAPIS_STABLE_IDENTIFIER_TYPE = "FREG_SNR"
102
98
  PAPIS_ENCRYPTION_KEY_REFERENCE = "papis-common-key-1"
103
99
  DAEAD_ENCRYPTION_KEY_REFERENCE = "ssb-common-key-1"
@@ -6,9 +6,12 @@ from collections.abc import Iterable
6
6
  from dataclasses import dataclass
7
7
  from enum import Enum
8
8
  from enum import auto
9
+ from typing import Literal
9
10
 
10
11
  from pydantic import AnyUrl
11
12
 
13
+ from dapla_metadata._shared.config import get_dapla_environment
14
+ from dapla_metadata._shared.enums import DaplaEnvironment
12
15
  from dapla_metadata.datasets.utility.utils import VariableListType
13
16
 
14
17
  logger = logging.getLogger(__name__)
@@ -44,6 +47,9 @@ class ReferenceUrlTypes(Enum):
44
47
  FRONTEND = auto()
45
48
 
46
49
 
50
+ UrlVisibility = Literal["public", "internal"]
51
+
52
+
47
53
  @dataclass
48
54
  class UrnConverter:
49
55
  """Converts URLs to URNs and vice versa.
@@ -70,11 +76,81 @@ class UrnConverter:
70
76
  def _build_pattern(self, url_base: str) -> re.Pattern[str]:
71
77
  return re.compile(f"^{url_base}/{self.id_pattern}")
72
78
 
73
- def build_urn(self, identifier: str) -> str:
79
+ def get_urn(self, identifier: str) -> str:
74
80
  """Build a URN for the given identifier."""
75
81
  return f"{self.urn_base}:{identifier}"
76
82
 
77
- def convert_to_urn(self, url: str | AnyUrl) -> AnyUrl | None:
83
+ def get_url(
84
+ self,
85
+ identifier: str,
86
+ url_type: ReferenceUrlTypes,
87
+ visibility: Literal["public", "internal"] = "public",
88
+ ) -> str | None:
89
+ """Build concrete URL to reference a resource.
90
+
91
+ There are typically multiple URLs used to refer to one resource, this method attempts to support known variations.
92
+
93
+ Args:
94
+ identifier (str): The identifier of the resource the URL refers to.
95
+ url_type (ReferenceUrlTypes): The representation type of the URL
96
+ visibility (UrlVisibility, optional): Whether the URL should be that which is publicly available or not. Defaults to "public".
97
+
98
+ Returns:
99
+ str | None: The concrete URL. None if we cannot satisfy the supplied requirements.
100
+ """
101
+ candidates = [base[-1] for base in self.url_bases if base[0] == url_type]
102
+
103
+ def matches_visibility(url: str, visibility: UrlVisibility):
104
+ return (".intern." in url) is (visibility == "internal")
105
+
106
+ def matches_environment(url: str):
107
+ current_environment = get_dapla_environment()
108
+ if current_environment == DaplaEnvironment.TEST:
109
+ return ".test." in url
110
+ return ".test." not in url
111
+
112
+ if url := next(
113
+ (
114
+ url
115
+ for url in candidates
116
+ if matches_visibility(url, visibility) and matches_environment(url)
117
+ ),
118
+ None,
119
+ ):
120
+ return url + "/" + identifier
121
+ return None
122
+
123
+ def get_id(self, urn_or_url: str | AnyUrl) -> str | None:
124
+ """Get an identifier from a URN or URL.
125
+
126
+ Args:
127
+ urn_or_url (str | AnyUrl): The URN or URL refering to a particular resource
128
+
129
+ Returns:
130
+ str | None: The identifier for the resource, or None if it cannot be extracted.
131
+ """
132
+ if str(urn_or_url).startswith(self.urn_base):
133
+ return str(urn_or_url).removeprefix(self.urn_base + ":")
134
+ return self._extract_id_from_url(urn_or_url)
135
+
136
+ def is_id(self, value: str) -> bool:
137
+ """Check if the value is an identifier for this URN type.
138
+
139
+ Args:
140
+ value (str): The value to check.
141
+ """
142
+ if not isinstance(value, str):
143
+ # Mypy thinks it's impossible to reach this branch, but there are no guarantees in Python.
144
+ return False # type: ignore [unreachable]
145
+ pattern = re.compile(f"^{self.id_pattern}$")
146
+ return bool(pattern.match(value))
147
+
148
+ def _extract_id_from_url(self, url: str | AnyUrl) -> str | None:
149
+ patterns = (self._build_pattern(url[-1]) for url in self.url_bases)
150
+ matches = (self._extract_id(str(url), p) for p in patterns)
151
+ return next((m for m in matches if m), None)
152
+
153
+ def convert_url_to_urn(self, url: str | AnyUrl) -> AnyUrl | None:
78
154
  """Convert a URL to a generalized URN for that same resource.
79
155
 
80
156
  Args:
@@ -86,11 +162,8 @@ class UrnConverter:
86
162
  if str(url).startswith(self.urn_base):
87
163
  # In this case the value is already in the expected format and nothing needs to be done.
88
164
  return AnyUrl(url)
89
- patterns = (self._build_pattern(url[-1]) for url in self.url_bases)
90
- matches = (self._extract_id(str(url), p) for p in patterns)
91
- identifier = next((m for m in matches if m), None)
92
- if identifier:
93
- return AnyUrl(self.build_urn(identifier))
165
+ if identifier := self._extract_id_from_url(url):
166
+ return AnyUrl(self.get_urn(identifier))
94
167
 
95
168
  return None
96
169
 
@@ -149,7 +222,7 @@ def convert_uris_to_urns(
149
222
  for v in variables:
150
223
  field = getattr(v, field_name, None)
151
224
  if field:
152
- if urn := next((c.convert_to_urn(field) for c in converters), None):
225
+ if urn := next((c.convert_url_to_urn(field) for c in converters), None):
153
226
  setattr(v, field_name, urn)
154
227
  else:
155
228
  logger.error(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dapla-toolbelt-metadata
3
- Version: 0.9.7
3
+ Version: 0.9.8
4
4
  Summary: Dapla Toolbelt Metadata
5
5
  Project-URL: homepage, https://github.com/statisticsnorway/dapla-toolbelt-metadata
6
6
  Project-URL: repository, https://github.com/statisticsnorway/dapla-toolbelt-metadata
@@ -1,6 +1,6 @@
1
1
  dapla_metadata/__init__.py,sha256=37yh9XWYQoLIVIS_fDdwNN8OXzbYY-6kMYwvjQrLMJQ,428
2
2
  dapla_metadata/_shared/__init__.py,sha256=qUFgnVhBVlPRQP0ePmY76c8FvWRrJ-9c5GvzibwERnQ,103
3
- dapla_metadata/_shared/config.py,sha256=QqXcmP66AfXF8wi6FMsa7et7kH2k4EJPOF4IELKuQig,3213
3
+ dapla_metadata/_shared/config.py,sha256=xRAXDULS85lAi5XyAirh1acDbf7_0xPhElssXvQQk3Y,3245
4
4
  dapla_metadata/_shared/enums.py,sha256=WHkH1d8xw41gOly6au_izZB1_-6XTcKu5rhBWUImjp8,509
5
5
  dapla_metadata/_shared/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  dapla_metadata/dapla/__init__.py,sha256=tkapF-YwmruPPrKvN3pEoCZqb7xvJx_ogBM8XyGMuJI,130
@@ -21,9 +21,9 @@ dapla_metadata/datasets/compatibility/model_backwards_compatibility.py,sha256=W5
21
21
  dapla_metadata/datasets/external_sources/__init__.py,sha256=qvIdXwqyEmXNUCB94ZtZXRzifdW4hiXASFFPtC70f6E,83
22
22
  dapla_metadata/datasets/external_sources/external_sources.py,sha256=9eIcOIUbaodNX1w9Tj2wl4U4wUmr5kF1R0i01fKUzGs,2974
23
23
  dapla_metadata/datasets/utility/__init__.py,sha256=pp6tUcgUbo8iq9OPtFKQrTbLuI3uY7NHptwWSTpasOU,33
24
- dapla_metadata/datasets/utility/constants.py,sha256=YKsn6GfNIkwLoBp0yq209o0TbsEhsA_jGaZLVR984JU,2933
24
+ dapla_metadata/datasets/utility/constants.py,sha256=4ixDvz5nErQwXa3BEtaGZb2AFUUUldJtNZV46SKwUBc,2817
25
25
  dapla_metadata/datasets/utility/enums.py,sha256=i6dcxWya5k4LjLdGGIM_H37rRndizug3peaAgoE5UdM,652
26
- dapla_metadata/datasets/utility/urn.py,sha256=Y_4wYwWWaFDffIN3uXjCodi-uUUQ7zkX1qEFSwGlVqs,5317
26
+ dapla_metadata/datasets/utility/urn.py,sha256=1NtM9OkTUe4_T5Iy8cR-ofwuR0gUlrtA7oQqEmgWKOc,8141
27
27
  dapla_metadata/datasets/utility/utils.py,sha256=q76UJI8W4j2aHSq1jz_AfYnJmLfygEflgUrQpqQEPnY,20157
28
28
  dapla_metadata/standards/__init__.py,sha256=n8jnMrudLuScSdfQ4UMJorc-Ptg3Y1-ilT8zAaQnM70,179
29
29
  dapla_metadata/standards/name_validator.py,sha256=6-DQE_EKVd6UjL--EXpFcZDQtusVbSFaWaUY-CfOV2c,9184
@@ -91,7 +91,7 @@ dapla_metadata/variable_definitions/_utils/constants.py,sha256=zr5FNVCEz6TM9PVEr
91
91
  dapla_metadata/variable_definitions/_utils/files.py,sha256=JbPgPNQ7iA38juMqGEdcg5OjZZUwCb6NQtPL0AEspD0,10933
92
92
  dapla_metadata/variable_definitions/_utils/template_files.py,sha256=7fcc7yEHOl5JUZ698kqj4IiikXPHBi3SrAVOk4wqQtw,3308
93
93
  dapla_metadata/variable_definitions/_utils/variable_definition_files.py,sha256=sGhcSpckR9NtYGNh2oVkiCd5SI3bbJEBhc1PA2uShs0,4701
94
- dapla_toolbelt_metadata-0.9.7.dist-info/METADATA,sha256=yb6SMXPh6nMfUPfOMyicbrcConcCoWgEtcgsUsl2jJ0,4854
95
- dapla_toolbelt_metadata-0.9.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
96
- dapla_toolbelt_metadata-0.9.7.dist-info/licenses/LICENSE,sha256=np3IfD5m0ZUofn_kVzDZqliozuiO6wrktw3LRPjyEiI,1073
97
- dapla_toolbelt_metadata-0.9.7.dist-info/RECORD,,
94
+ dapla_toolbelt_metadata-0.9.8.dist-info/METADATA,sha256=jBwnT3Vs5w-JIXTjzcMDmzhDr8XPlkkdU24zxTNaz4w,4854
95
+ dapla_toolbelt_metadata-0.9.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
96
+ dapla_toolbelt_metadata-0.9.8.dist-info/licenses/LICENSE,sha256=np3IfD5m0ZUofn_kVzDZqliozuiO6wrktw3LRPjyEiI,1073
97
+ dapla_toolbelt_metadata-0.9.8.dist-info/RECORD,,