dapla-toolbelt-metadata 0.6.3__tar.gz → 0.6.5__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.
Potentially problematic release.
This version of dapla-toolbelt-metadata might be problematic. Click here for more details.
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/PKG-INFO +3 -3
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/pyproject.toml +38 -51
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/datasets/core.py +87 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_utils/constants.py +21 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_utils/files.py +72 -56
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_utils/template_files.py +3 -14
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_utils/variable_definition_files.py +32 -5
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/resources/vardef_model_descriptions_nb.yaml +60 -32
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/LICENSE +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/README.md +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/__init__.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/_shared/__init__.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/_shared/config.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/_shared/enums.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/_shared/py.typed +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/dapla/__init__.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/dapla/user_info.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/datasets/__init__.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/datasets/code_list.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/datasets/dapla_dataset_path_info.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/datasets/dataset_parser.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/datasets/external_sources/__init__.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/datasets/external_sources/external_sources.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/datasets/model_backwards_compatibility.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/datasets/model_validation.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/datasets/py.typed +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/datasets/statistic_subject_mapping.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/datasets/utility/__init__.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/datasets/utility/constants.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/datasets/utility/enums.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/datasets/utility/utils.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/standards/__init__.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/standards/name_validator.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/standards/standard_validators.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/standards/utils/__init__.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/standards/utils/constants.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/__init__.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/.openapi-generator/FILES +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/.openapi-generator/VERSION +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/.openapi-generator-ignore +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/README.md +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/__init__.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/__init__.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/api/__init__.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/api/data_migration_api.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/api/draft_variable_definitions_api.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/api/patches_api.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/api/validity_periods_api.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/api/variable_definitions_api.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/api_client.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/api_response.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/configuration.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/docs/CompleteResponse.md +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/docs/Contact.md +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/docs/DataMigrationApi.md +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/docs/Draft.md +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/docs/DraftVariableDefinitionsApi.md +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/docs/LanguageStringType.md +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/docs/Owner.md +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/docs/Patch.md +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/docs/PatchesApi.md +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/docs/PublicApi.md +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/docs/SupportedLanguages.md +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/docs/UpdateDraft.md +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/docs/ValidityPeriod.md +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/docs/ValidityPeriodsApi.md +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/docs/VariableDefinitionsApi.md +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/docs/VariableStatus.md +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/exceptions.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/models/__init__.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/models/complete_response.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/models/contact.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/models/draft.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/models/language_string_type.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/models/owner.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/models/patch.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/models/problem.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/models/update_draft.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/models/validity_period.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/models/variable_status.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/py.typed +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_generated/vardef_client/rest.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_utils/__init__.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_utils/_client.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_utils/config.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/_utils/descriptions.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/exceptions.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/vardef.py +0 -0
- {dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/variable_definitions/variable_definition.py +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: dapla-toolbelt-metadata
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.5
|
|
4
4
|
Summary: Dapla Toolbelt Metadata
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: Team Metadata
|
|
7
7
|
Author-email: metadata@ssb.no
|
|
8
|
-
Requires-Python: >=3.10
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
9
|
Classifier: Development Status :: 4 - Beta
|
|
10
10
|
Classifier: License :: OSI Approved :: MIT License
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -24,7 +24,7 @@ Requires-Dist: pyjwt (>=2.8.0)
|
|
|
24
24
|
Requires-Dist: python-dotenv (>=1.0.1)
|
|
25
25
|
Requires-Dist: requests (>=2.31.0)
|
|
26
26
|
Requires-Dist: ruamel-yaml (>=0.18.10)
|
|
27
|
-
Requires-Dist: ssb-datadoc-model (
|
|
27
|
+
Requires-Dist: ssb-datadoc-model (==6.0.0)
|
|
28
28
|
Requires-Dist: ssb-klass-python (>=1.0.1)
|
|
29
29
|
Requires-Dist: typing-extensions (>=4.12.2)
|
|
30
30
|
Project-URL: Changelog, https://github.com/statisticsnorway/dapla-toolbelt-metadata/releases
|
|
@@ -1,36 +1,45 @@
|
|
|
1
|
-
[
|
|
1
|
+
[project]
|
|
2
2
|
name = "dapla-toolbelt-metadata"
|
|
3
|
-
version = "0.6.3"
|
|
4
3
|
description = "Dapla Toolbelt Metadata"
|
|
5
|
-
authors = ["Team Metadata <metadata@ssb.no>"]
|
|
6
4
|
license = "MIT"
|
|
5
|
+
version = "0.6.5"
|
|
6
|
+
dynamic = ["classifiers"]
|
|
7
7
|
readme = "README.md"
|
|
8
|
+
authors = [{ name = "Team Metadata", email = "metadata@ssb.no" }]
|
|
9
|
+
requires-python = '>=3.10'
|
|
10
|
+
dependencies = [
|
|
11
|
+
'pyarrow >=8.0.0',
|
|
12
|
+
'pydantic >=2.5.2',
|
|
13
|
+
'arrow >=1.3.0',
|
|
14
|
+
'python-dotenv >=1.0.1',
|
|
15
|
+
'requests >=2.31.0',
|
|
16
|
+
'beautifulsoup4 >=4.12.3',
|
|
17
|
+
'cloudpathlib[gs] >=0.17.0',
|
|
18
|
+
'pyjwt >=2.8.0',
|
|
19
|
+
'ssb-klass-python >=1.0.1',
|
|
20
|
+
'ssb-datadoc-model ==6.0.0',
|
|
21
|
+
'typing-extensions >=4.12.2',
|
|
22
|
+
'ruamel-yaml >=0.18.10',
|
|
23
|
+
'google-auth >=2.38.0',
|
|
24
|
+
'lxml >=5.3.1',
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[project.urls]
|
|
8
28
|
homepage = "https://github.com/statisticsnorway/dapla-toolbelt-metadata"
|
|
9
29
|
repository = "https://github.com/statisticsnorway/dapla-toolbelt-metadata"
|
|
10
30
|
documentation = "https://statisticsnorway.github.io/dapla-toolbelt-metadata"
|
|
11
|
-
|
|
31
|
+
Changelog = "https://github.com/statisticsnorway/dapla-toolbelt-metadata/releases"
|
|
12
32
|
|
|
33
|
+
[tool.poetry]
|
|
34
|
+
requires-poetry = '>=2.0,<3.0'
|
|
13
35
|
packages = [{ include = "dapla_metadata", from = "src" }]
|
|
36
|
+
classifiers = ["Development Status :: 4 - Beta"]
|
|
14
37
|
|
|
15
|
-
[tool.poetry.
|
|
16
|
-
|
|
38
|
+
[tool.poetry.requires-plugins]
|
|
39
|
+
poetry-plugin-export = ">=1.9.0" # Used with nox
|
|
17
40
|
|
|
18
41
|
[tool.poetry.dependencies]
|
|
19
|
-
python = ">=3.10,<4.0"
|
|
20
|
-
pyarrow = ">=8.0.0"
|
|
21
|
-
pydantic = ">=2.5.2"
|
|
22
|
-
arrow = ">=1.3.0"
|
|
23
|
-
python-dotenv = ">=1.0.1"
|
|
24
|
-
requests = ">=2.31.0"
|
|
25
|
-
beautifulsoup4 = ">=4.12.3"
|
|
26
|
-
cloudpathlib = { extras = ["gs"], version = ">=0.17.0" }
|
|
27
|
-
pyjwt = ">=2.8.0"
|
|
28
|
-
ssb-klass-python = ">=1.0.1"
|
|
29
|
-
ssb-datadoc-model = "^6.0.0"
|
|
30
|
-
typing-extensions = ">=4.12.2"
|
|
31
|
-
ruamel-yaml = ">=0.18.10"
|
|
32
|
-
google-auth = ">=2.38.0"
|
|
33
|
-
lxml = ">=5.3.1"
|
|
42
|
+
python = ">=3.10,<4.0" # This is currently needed for compatibility with ssb-klass-python
|
|
34
43
|
|
|
35
44
|
[tool.poetry.group.dev.dependencies]
|
|
36
45
|
pygments = ">=2.18.0"
|
|
@@ -64,7 +73,7 @@ types-beautifulsoup4 = ">=4.12.0.20240511"
|
|
|
64
73
|
ipykernel = "^6.29.5"
|
|
65
74
|
rich = "^13.9.4"
|
|
66
75
|
bpython = "^0.24"
|
|
67
|
-
testcontainers = { version = "
|
|
76
|
+
testcontainers = { version = ">=4.8.2", extras = ["generic"] }
|
|
68
77
|
pytest-asyncio = "^0.26.0"
|
|
69
78
|
|
|
70
79
|
[tool.pytest.ini_options]
|
|
@@ -77,11 +86,7 @@ tests = ["tests", "*/tests", "*/test"]
|
|
|
77
86
|
[tool.coverage.run]
|
|
78
87
|
branch = true
|
|
79
88
|
source = ["dapla_metadata"]
|
|
80
|
-
omit = [
|
|
81
|
-
"tests/*",
|
|
82
|
-
"__init__.py",
|
|
83
|
-
"*/dapla_metadata/variable_definitions/_generated/*",
|
|
84
|
-
]
|
|
89
|
+
omit = ["tests/*", "__init__.py", "*/dapla_metadata/variable_definitions/_generated/*"]
|
|
85
90
|
relative_files = true
|
|
86
91
|
|
|
87
92
|
[tool.coverage.report]
|
|
@@ -105,7 +110,6 @@ warn_unreachable = false
|
|
|
105
110
|
ignore_errors = true
|
|
106
111
|
disable_error_code = ["unreachable"]
|
|
107
112
|
|
|
108
|
-
|
|
109
113
|
[[tool.mypy.overrides]]
|
|
110
114
|
# Allow missing type hints in third-party libraries without type information.
|
|
111
115
|
module = [
|
|
@@ -127,27 +131,15 @@ ignore_missing_imports = true
|
|
|
127
131
|
# Also don't require type annotations
|
|
128
132
|
[[tool.mypy.overrides]]
|
|
129
133
|
module = ["tests.*"]
|
|
130
|
-
disable_error_code = [
|
|
131
|
-
"var-annotated",
|
|
132
|
-
"has-type",
|
|
133
|
-
"no-any-return",
|
|
134
|
-
"no-untyped-def",
|
|
135
|
-
]
|
|
134
|
+
disable_error_code = ["var-annotated", "has-type", "no-any-return", "no-untyped-def"]
|
|
136
135
|
|
|
137
136
|
[tool.ruff]
|
|
138
|
-
force-exclude = true
|
|
137
|
+
force-exclude = true # Apply excludes to pre-commit
|
|
139
138
|
show-fixes = true
|
|
140
139
|
src = ["src", "tests"]
|
|
141
|
-
target-version = "py310"
|
|
140
|
+
target-version = "py310" # Minimum Python version supported
|
|
142
141
|
include = ["*.py", "*.pyi", "**/pyproject.toml", "*.ipynb"]
|
|
143
|
-
extend-exclude = [
|
|
144
|
-
"__pycache__",
|
|
145
|
-
"old",
|
|
146
|
-
".ipynb_checkpoints",
|
|
147
|
-
"noxfile.py",
|
|
148
|
-
"docs/conf.py",
|
|
149
|
-
"_generated/",
|
|
150
|
-
]
|
|
142
|
+
extend-exclude = ["__pycache__", "old", ".ipynb_checkpoints", "noxfile.py", "docs/conf.py", "_generated/"]
|
|
151
143
|
|
|
152
144
|
# Ruff rules may be customized as desired: https://docs.astral.sh/ruff/rules/
|
|
153
145
|
[tool.ruff.lint]
|
|
@@ -181,12 +173,7 @@ fixture-parentheses = false
|
|
|
181
173
|
max-args = 8
|
|
182
174
|
|
|
183
175
|
[tool.ruff.lint.pep8-naming]
|
|
184
|
-
classmethod-decorators = [
|
|
185
|
-
"classmethod",
|
|
186
|
-
"validator",
|
|
187
|
-
"root_validator",
|
|
188
|
-
"pydantic.validator",
|
|
189
|
-
]
|
|
176
|
+
classmethod-decorators = ["classmethod", "validator", "root_validator", "pydantic.validator"]
|
|
190
177
|
|
|
191
178
|
[tool.ruff.lint.per-file-ignores]
|
|
192
179
|
"*/__init__.py" = ["F401"]
|
|
@@ -206,5 +193,5 @@ classmethod-decorators = [
|
|
|
206
193
|
]
|
|
207
194
|
|
|
208
195
|
[build-system]
|
|
209
|
-
requires = ["poetry-core>=
|
|
196
|
+
requires = ["poetry-core>=2.0"]
|
|
210
197
|
build-backend = "poetry.core.masonry.api"
|
{dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/datasets/core.py
RENAMED
|
@@ -109,7 +109,9 @@ class Datadoc:
|
|
|
109
109
|
self.dataset_path: pathlib.Path | CloudPath | None = None
|
|
110
110
|
self.dataset = model.Dataset()
|
|
111
111
|
self.variables: list = []
|
|
112
|
+
self.pseudo_variables: list[model.PseudoVariable] = []
|
|
112
113
|
self.variables_lookup: dict[str, model.Variable] = {}
|
|
114
|
+
self.pseudo_variables_lookup: dict[str, model.PseudoVariable] = {}
|
|
113
115
|
self.explicitly_defined_metadata_document = False
|
|
114
116
|
self.dataset_consistency_status: list = []
|
|
115
117
|
if metadata_document_path:
|
|
@@ -149,11 +151,19 @@ class Datadoc:
|
|
|
149
151
|
"""
|
|
150
152
|
extracted_metadata: model.DatadocMetadata | None = None
|
|
151
153
|
existing_metadata: model.DatadocMetadata | None = None
|
|
154
|
+
existing_pseudonymization: model.PseudonymizationMetadata | None = None
|
|
155
|
+
|
|
152
156
|
if self.metadata_document and self.metadata_document.exists():
|
|
153
157
|
existing_metadata = self._extract_metadata_from_existing_document(
|
|
154
158
|
self.metadata_document,
|
|
155
159
|
)
|
|
156
160
|
|
|
161
|
+
existing_pseudonymization = (
|
|
162
|
+
self._extract_pseudonymization_from_existing_document(
|
|
163
|
+
self.metadata_document,
|
|
164
|
+
)
|
|
165
|
+
)
|
|
166
|
+
|
|
157
167
|
if (
|
|
158
168
|
self.dataset_path is not None
|
|
159
169
|
and self.dataset == model.Dataset()
|
|
@@ -192,10 +202,15 @@ class Datadoc:
|
|
|
192
202
|
self._set_metadata(merged_metadata)
|
|
193
203
|
else:
|
|
194
204
|
self._set_metadata(existing_metadata or extracted_metadata)
|
|
205
|
+
|
|
206
|
+
if existing_pseudonymization:
|
|
207
|
+
self._set_pseudonymization_metadata(existing_pseudonymization)
|
|
208
|
+
|
|
195
209
|
set_default_values_variables(self.variables)
|
|
196
210
|
set_default_values_dataset(self.dataset)
|
|
197
211
|
set_dataset_owner(self.dataset)
|
|
198
212
|
self._create_variables_lookup()
|
|
213
|
+
self._create_pseudo_variables_lookup()
|
|
199
214
|
|
|
200
215
|
def _get_existing_file_path(
|
|
201
216
|
self,
|
|
@@ -222,11 +237,29 @@ class Datadoc:
|
|
|
222
237
|
self.dataset = merged_metadata.dataset
|
|
223
238
|
self.variables = merged_metadata.variables
|
|
224
239
|
|
|
240
|
+
def _set_pseudonymization_metadata(
|
|
241
|
+
self,
|
|
242
|
+
existing_pseudonymization: model.PseudonymizationMetadata | None,
|
|
243
|
+
) -> None:
|
|
244
|
+
if not existing_pseudonymization or not (
|
|
245
|
+
existing_pseudonymization.pseudo_variables is not None
|
|
246
|
+
):
|
|
247
|
+
msg = "Error reading pseudonymization metadata"
|
|
248
|
+
logger.error(msg)
|
|
249
|
+
return
|
|
250
|
+
self.pseudo_variables = existing_pseudonymization.pseudo_variables
|
|
251
|
+
|
|
225
252
|
def _create_variables_lookup(self) -> None:
|
|
226
253
|
self.variables_lookup = {
|
|
227
254
|
v.short_name: v for v in self.variables if v.short_name
|
|
228
255
|
}
|
|
229
256
|
|
|
257
|
+
def _create_pseudo_variables_lookup(self) -> None:
|
|
258
|
+
if self.pseudo_variables:
|
|
259
|
+
self.pseudo_variables_lookup = {
|
|
260
|
+
v.short_name: v for v in self.pseudo_variables if v.short_name
|
|
261
|
+
}
|
|
262
|
+
|
|
230
263
|
@staticmethod
|
|
231
264
|
def _check_dataset_consistency(
|
|
232
265
|
new_dataset_path: Path | CloudPath,
|
|
@@ -399,6 +432,42 @@ class Datadoc:
|
|
|
399
432
|
)
|
|
400
433
|
return None
|
|
401
434
|
|
|
435
|
+
def _extract_pseudonymization_from_existing_document(
|
|
436
|
+
self,
|
|
437
|
+
document: pathlib.Path | CloudPath,
|
|
438
|
+
) -> model.PseudonymizationMetadata | None:
|
|
439
|
+
"""Read pseudo metadata from an existing metadata document.
|
|
440
|
+
|
|
441
|
+
If there is pseudo metadata in the document supplied, the method validates and returns the pseudonymization structure.
|
|
442
|
+
|
|
443
|
+
Args:
|
|
444
|
+
document: A path to the existing metadata document.
|
|
445
|
+
|
|
446
|
+
Raises:
|
|
447
|
+
json.JSONDecodeError: If the metadata document cannot be parsed.
|
|
448
|
+
"""
|
|
449
|
+
try:
|
|
450
|
+
with document.open(mode="r", encoding="utf-8") as file:
|
|
451
|
+
fresh_metadata = json.load(file)
|
|
452
|
+
except json.JSONDecodeError:
|
|
453
|
+
logger.warning(
|
|
454
|
+
"Could not open existing metadata file %s.",
|
|
455
|
+
document,
|
|
456
|
+
exc_info=True,
|
|
457
|
+
)
|
|
458
|
+
return None
|
|
459
|
+
|
|
460
|
+
if not is_metadata_in_container_structure(fresh_metadata):
|
|
461
|
+
return None
|
|
462
|
+
|
|
463
|
+
pseudonymization_metadata = fresh_metadata.get("pseudonymization")
|
|
464
|
+
if pseudonymization_metadata is None:
|
|
465
|
+
return None
|
|
466
|
+
|
|
467
|
+
return model.PseudonymizationMetadata.model_validate_json(
|
|
468
|
+
json.dumps(pseudonymization_metadata),
|
|
469
|
+
)
|
|
470
|
+
|
|
402
471
|
def _extract_subject_field_from_path(
|
|
403
472
|
self,
|
|
404
473
|
dapla_dataset_path_info: DaplaDatasetPathInfo,
|
|
@@ -516,6 +585,11 @@ class Datadoc:
|
|
|
516
585
|
)
|
|
517
586
|
if self.container:
|
|
518
587
|
self.container.datadoc = datadoc
|
|
588
|
+
if not self.container.pseudonymization:
|
|
589
|
+
self.container.pseudonymization = model.PseudonymizationMetadata(
|
|
590
|
+
pseudo_dataset=model.PseudoDataset()
|
|
591
|
+
)
|
|
592
|
+
self.container.pseudonymization.pseudo_variables = self.pseudo_variables
|
|
519
593
|
else:
|
|
520
594
|
self.container = model.MetadataContainer(datadoc=datadoc)
|
|
521
595
|
if self.metadata_document:
|
|
@@ -545,3 +619,16 @@ class Datadoc:
|
|
|
545
619
|
self.dataset,
|
|
546
620
|
) + num_obligatory_variables_fields_completed(self.variables)
|
|
547
621
|
return calculate_percentage(num_set_fields, num_all_fields)
|
|
622
|
+
|
|
623
|
+
def add_pseudo_variable(self, variable_short_name: str) -> None:
|
|
624
|
+
"""Adds a new pseudo variable to the list of pseudonymized variables."""
|
|
625
|
+
if self.variables_lookup[variable_short_name] is not None:
|
|
626
|
+
pseudo_variable = model.PseudoVariable(short_name=variable_short_name)
|
|
627
|
+
self.pseudo_variables.append(pseudo_variable)
|
|
628
|
+
self.pseudo_variables_lookup[variable_short_name] = pseudo_variable
|
|
629
|
+
|
|
630
|
+
def get_pseudo_variable(
|
|
631
|
+
self, variable_short_name: str
|
|
632
|
+
) -> model.PseudoVariable | None:
|
|
633
|
+
"""Finds a pseudo variable by shortname."""
|
|
634
|
+
return self.pseudo_variables_lookup.get(variable_short_name)
|
|
@@ -41,3 +41,24 @@ OPTIONAL_FIELD = "~ Valgfritt felt ~"
|
|
|
41
41
|
REQUIRED_FIELD = "! Obligatorisk felt !"
|
|
42
42
|
|
|
43
43
|
YAML_STR_TAG = "tag:yaml.org,2002:str"
|
|
44
|
+
|
|
45
|
+
BLOCK_FIELDS = [
|
|
46
|
+
"definition",
|
|
47
|
+
"name",
|
|
48
|
+
"contact.title",
|
|
49
|
+
"comment",
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
DOUBLE_QUOTE_FIELDS = [
|
|
53
|
+
"unit_types",
|
|
54
|
+
"subject_fields",
|
|
55
|
+
"related_variable_definition_uris",
|
|
56
|
+
"owner",
|
|
57
|
+
"short_name",
|
|
58
|
+
"classification_reference",
|
|
59
|
+
"measurement_type",
|
|
60
|
+
"external_reference_uri",
|
|
61
|
+
"created_by",
|
|
62
|
+
"id",
|
|
63
|
+
"last_updated_by",
|
|
64
|
+
]
|
|
@@ -4,6 +4,7 @@ import logging
|
|
|
4
4
|
from datetime import datetime
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from typing import TYPE_CHECKING
|
|
7
|
+
from typing import Any
|
|
7
8
|
from typing import cast
|
|
8
9
|
|
|
9
10
|
import pytz
|
|
@@ -12,7 +13,7 @@ from ruamel.yaml import YAML
|
|
|
12
13
|
from ruamel.yaml import CommentedMap
|
|
13
14
|
from ruamel.yaml import RoundTripRepresenter
|
|
14
15
|
from ruamel.yaml.scalarstring import DoubleQuotedScalarString
|
|
15
|
-
from ruamel.yaml.scalarstring import
|
|
16
|
+
from ruamel.yaml.scalarstring import LiteralScalarString
|
|
16
17
|
|
|
17
18
|
from dapla_metadata.variable_definitions._generated.vardef_client.models.complete_response import (
|
|
18
19
|
CompleteResponse,
|
|
@@ -21,6 +22,8 @@ from dapla_metadata.variable_definitions._generated.vardef_client.models.variabl
|
|
|
21
22
|
VariableStatus,
|
|
22
23
|
)
|
|
23
24
|
from dapla_metadata.variable_definitions._utils import config
|
|
25
|
+
from dapla_metadata.variable_definitions._utils.constants import BLOCK_FIELDS
|
|
26
|
+
from dapla_metadata.variable_definitions._utils.constants import DOUBLE_QUOTE_FIELDS
|
|
24
27
|
from dapla_metadata.variable_definitions._utils.constants import (
|
|
25
28
|
MACHINE_GENERATED_FIELDS,
|
|
26
29
|
)
|
|
@@ -116,6 +119,15 @@ def _get_variable_definitions_dir():
|
|
|
116
119
|
return folder_path
|
|
117
120
|
|
|
118
121
|
|
|
122
|
+
def _set_field_requirement(field_name: str, field: Any) -> str | None:
|
|
123
|
+
"""Determine the field requirement status."""
|
|
124
|
+
if field_name not in MACHINE_GENERATED_FIELDS:
|
|
125
|
+
if field.is_required() or field_name == VARIABLE_STATUS_FIELD_NAME:
|
|
126
|
+
return REQUIRED_FIELD
|
|
127
|
+
return OPTIONAL_FIELD
|
|
128
|
+
return None
|
|
129
|
+
|
|
130
|
+
|
|
119
131
|
def _populate_commented_map(
|
|
120
132
|
field_name: str,
|
|
121
133
|
value: str,
|
|
@@ -129,12 +141,12 @@ def _populate_commented_map(
|
|
|
129
141
|
JsonDict,
|
|
130
142
|
field.json_schema_extra,
|
|
131
143
|
)[NORWEGIAN_DESCRIPTIONS]
|
|
144
|
+
field_requirement: str | None = _set_field_requirement(field_name, field)
|
|
132
145
|
if description is not None:
|
|
133
146
|
new_description = (
|
|
134
|
-
"\n"
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
+ str(description)
|
|
147
|
+
("\n" + field_requirement + "\n" + str(description))
|
|
148
|
+
if field_requirement
|
|
149
|
+
else ("\n" + str(description))
|
|
138
150
|
)
|
|
139
151
|
commented_map.yaml_set_comment_before_after_key(
|
|
140
152
|
field_name,
|
|
@@ -185,9 +197,11 @@ def configure_yaml(yaml: YAML) -> YAML:
|
|
|
185
197
|
yaml.default_flow_style = False # Ensures pretty YAML formatting block style
|
|
186
198
|
yaml.allow_unicode = True # Support special characters
|
|
187
199
|
yaml.preserve_quotes = True
|
|
188
|
-
yaml.width =
|
|
200
|
+
yaml.width = 4096 # prevent wrapping lines
|
|
189
201
|
yaml.indent(
|
|
190
|
-
mapping=4,
|
|
202
|
+
mapping=4,
|
|
203
|
+
sequence=6,
|
|
204
|
+
offset=4,
|
|
191
205
|
) # Ensure indentation for nested keys and lists
|
|
192
206
|
yaml.representer.add_representer(
|
|
193
207
|
VariableStatus,
|
|
@@ -209,59 +223,63 @@ def _safe_get(data: dict, keys: list):
|
|
|
209
223
|
return data
|
|
210
224
|
|
|
211
225
|
|
|
212
|
-
def
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
226
|
+
def _apply_literal_scalars(field: dict):
|
|
227
|
+
"""Helper function to wrap `LanguageStringType` values in `LiteralScalarString`.
|
|
228
|
+
|
|
229
|
+
This function wraps each non-`None` language value in a `LanguageStringType` field
|
|
230
|
+
in the `LiteralScalarString` YAML type, ensuring proper YAML formatting with block style.
|
|
231
|
+
"""
|
|
232
|
+
for lang, value in field.items():
|
|
233
|
+
if value is not None:
|
|
234
|
+
field[lang] = LiteralScalarString(value)
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def _apply_double_quotes_to_dict_values(field: dict):
|
|
238
|
+
"""Helper function to wrap dictionary values in `DoubleQuotedScalarString`.
|
|
239
|
+
|
|
240
|
+
This function wraps each non-`None` value in a dictionary, including values inside lists,
|
|
241
|
+
in the `DoubleQuotedScalarString` YAML type, ensuring proper YAML formatting with double quotes.
|
|
242
|
+
"""
|
|
243
|
+
for sub_key, sub_value in field.items():
|
|
244
|
+
if isinstance(sub_value, list):
|
|
245
|
+
field[sub_key] = [
|
|
246
|
+
DoubleQuotedScalarString(item) for item in sub_value if item is not None
|
|
247
|
+
]
|
|
248
|
+
elif sub_value is not None:
|
|
249
|
+
field[sub_key] = DoubleQuotedScalarString(sub_value)
|
|
217
250
|
|
|
218
251
|
|
|
219
252
|
def pre_process_data(data: dict) -> dict:
|
|
220
|
-
"""Format
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
"
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
253
|
+
"""Format variable definition model fields with ruamel YAML scalar string types.
|
|
254
|
+
|
|
255
|
+
This method sets the appropriate scalar string type (either `LiteralScalarString` or `DoubleQuotedScalarString`)
|
|
256
|
+
for fields of the variable definition model, based on predefined lists of fields.
|
|
257
|
+
|
|
258
|
+
It processes both nested dictionaries and lists, ensuring each element is formatted with the correct YAML string type.
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
data (dict): A dictionary containing the variable definition data.
|
|
262
|
+
|
|
263
|
+
Returns:
|
|
264
|
+
dict: The updated dictionary with model fields formatted as ruamel.yaml scalar string types.
|
|
265
|
+
"""
|
|
266
|
+
for key in BLOCK_FIELDS:
|
|
267
|
+
keys = key.split(".")
|
|
268
|
+
field = _safe_get(data, keys)
|
|
269
|
+
if isinstance(field, dict):
|
|
270
|
+
_apply_literal_scalars(field)
|
|
271
|
+
|
|
272
|
+
for key in DOUBLE_QUOTE_FIELDS:
|
|
273
|
+
keys = key.split(".")
|
|
274
|
+
field = _safe_get(data, keys)
|
|
275
|
+
if isinstance(field, list):
|
|
238
276
|
data[key] = [
|
|
239
|
-
DoubleQuotedScalarString(item) for item in
|
|
277
|
+
DoubleQuotedScalarString(item) for item in field if item is not None
|
|
240
278
|
]
|
|
241
|
-
|
|
242
|
-
single_line_fields = [
|
|
243
|
-
"short_name",
|
|
244
|
-
"classification_reference",
|
|
245
|
-
"measurement_type",
|
|
246
|
-
"external_reference_uri",
|
|
247
|
-
"created_by",
|
|
248
|
-
"id",
|
|
249
|
-
"last_updated_by",
|
|
250
|
-
]
|
|
251
|
-
for key in single_line_fields:
|
|
252
|
-
if data.get(key) is not None:
|
|
279
|
+
elif isinstance(field, str):
|
|
253
280
|
data[key] = DoubleQuotedScalarString(data[key])
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
if isinstance(owner, dict):
|
|
257
|
-
if owner.get("team") is not None:
|
|
258
|
-
owner["team"] = DoubleQuotedScalarString(owner["team"])
|
|
259
|
-
if isinstance(owner.get("groups"), list):
|
|
260
|
-
owner["groups"] = [
|
|
261
|
-
DoubleQuotedScalarString(item)
|
|
262
|
-
for item in owner["groups"]
|
|
263
|
-
if item is not None
|
|
264
|
-
]
|
|
281
|
+
elif isinstance(field, dict):
|
|
282
|
+
_apply_double_quotes_to_dict_values(field)
|
|
265
283
|
|
|
266
284
|
return data
|
|
267
285
|
|
|
@@ -322,8 +340,6 @@ def _model_to_yaml_with_comments(
|
|
|
322
340
|
model_instance,
|
|
323
341
|
)
|
|
324
342
|
elif field_name not in {VARIABLE_STATUS_FIELD_NAME, OWNER_FIELD_NAME}:
|
|
325
|
-
if isinstance(value, str):
|
|
326
|
-
value.strip()
|
|
327
343
|
_populate_commented_map(field_name, value, commented_map, model_instance)
|
|
328
344
|
|
|
329
345
|
base_path = (
|
|
@@ -41,35 +41,24 @@ def _get_default_template() -> "VariableDefinition":
|
|
|
41
41
|
|
|
42
42
|
return VariableDefinition(
|
|
43
43
|
name=LanguageStringType(
|
|
44
|
-
nb="
|
|
45
|
-
nn="namn",
|
|
46
|
-
en="name",
|
|
44
|
+
nb="Navn",
|
|
47
45
|
),
|
|
48
46
|
short_name="generert_kortnavn",
|
|
49
47
|
definition=LanguageStringType(
|
|
50
|
-
nb="
|
|
51
|
-
nn="definisjonstekst",
|
|
52
|
-
en="definition text",
|
|
48
|
+
nb="Definisjonstekst",
|
|
53
49
|
),
|
|
54
50
|
valid_from=DEFAULT_DATE,
|
|
55
51
|
unit_types=[""],
|
|
56
52
|
subject_fields=[""],
|
|
57
53
|
contains_special_categories_of_personal_data=False,
|
|
58
|
-
variable_status=VariableStatus.DRAFT.value,
|
|
59
54
|
owner=Owner(team="default team", groups=["default group"]),
|
|
60
55
|
contact=Contact(
|
|
61
56
|
title=LanguageStringType(
|
|
62
57
|
nb="generert tittel",
|
|
63
|
-
nn="generert tittel",
|
|
64
|
-
en="generert title",
|
|
65
58
|
),
|
|
66
59
|
email="generert@ssb.no",
|
|
67
60
|
),
|
|
68
|
-
|
|
69
|
-
nb="",
|
|
70
|
-
nn="",
|
|
71
|
-
en="",
|
|
72
|
-
),
|
|
61
|
+
variable_status=VariableStatus.DRAFT.value,
|
|
73
62
|
id="",
|
|
74
63
|
patch_id=0,
|
|
75
64
|
created_at=DEFAULT_DATE,
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import logging
|
|
4
4
|
from os import PathLike
|
|
5
5
|
from pathlib import Path
|
|
6
|
+
from typing import Any
|
|
6
7
|
from typing import TypeVar
|
|
7
8
|
|
|
8
9
|
from pydantic import BaseModel
|
|
@@ -17,6 +18,7 @@ from dapla_metadata.variable_definitions._utils.files import _get_current_time
|
|
|
17
18
|
from dapla_metadata.variable_definitions._utils.files import (
|
|
18
19
|
_model_to_yaml_with_comments,
|
|
19
20
|
)
|
|
21
|
+
from dapla_metadata.variable_definitions._utils.files import configure_yaml
|
|
20
22
|
|
|
21
23
|
logger = logging.getLogger(__name__)
|
|
22
24
|
|
|
@@ -46,13 +48,38 @@ def create_variable_yaml(
|
|
|
46
48
|
|
|
47
49
|
def _read_variable_definition_file(file_path: Path) -> dict:
|
|
48
50
|
yaml = YAML()
|
|
49
|
-
|
|
51
|
+
configure_yaml(yaml)
|
|
50
52
|
logger.debug("Full path to variable definition file %s", file_path)
|
|
51
53
|
logger.info("Reading from '%s'", file_path.name)
|
|
52
54
|
with file_path.open(encoding="utf-8") as f:
|
|
53
55
|
return yaml.load(f)
|
|
54
56
|
|
|
55
57
|
|
|
58
|
+
def _strip_strings_recursively(data: Any) -> Any:
|
|
59
|
+
"""Recursively strip leading and trailing whitespace from string values in nested dicts/lists.
|
|
60
|
+
|
|
61
|
+
This function traverses the provided data, which may be a dictionary, list, or other types,
|
|
62
|
+
and applies the following logic:
|
|
63
|
+
- If the data is a dictionary, it recursively strips string values in all key-value pairs.
|
|
64
|
+
- If the data is a list, it recursively strips string values in all list elements.
|
|
65
|
+
- If the data is a string, it strips leading and trailing whitespace.
|
|
66
|
+
- Any other data types are returned unchanged.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
data: The input data, which may include nested dictionaries, lists, or other types.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
Any: The processed data, with strings stripped of whitespace or unchanged if not a string.
|
|
73
|
+
"""
|
|
74
|
+
if isinstance(data, dict):
|
|
75
|
+
return {k: _strip_strings_recursively(v) for k, v in data.items()}
|
|
76
|
+
if isinstance(data, list):
|
|
77
|
+
return [_strip_strings_recursively(item) for item in data]
|
|
78
|
+
if isinstance(data, str):
|
|
79
|
+
return data.strip()
|
|
80
|
+
return data
|
|
81
|
+
|
|
82
|
+
|
|
56
83
|
def _read_file_to_model(
|
|
57
84
|
file_path: PathLike[str] | None,
|
|
58
85
|
model_class: type[T],
|
|
@@ -80,14 +107,14 @@ def _read_file_to_model(
|
|
|
80
107
|
raise FileNotFoundError(
|
|
81
108
|
msg,
|
|
82
109
|
) from e
|
|
110
|
+
raw_data = _read_variable_definition_file(file_path)
|
|
111
|
+
cleaned_data = _strip_strings_recursively(raw_data)
|
|
112
|
+
|
|
83
113
|
model = model_class.from_dict( # type:ignore [attr-defined]
|
|
84
|
-
|
|
85
|
-
file_path,
|
|
86
|
-
),
|
|
114
|
+
cleaned_data
|
|
87
115
|
)
|
|
88
116
|
|
|
89
117
|
if model is None:
|
|
90
118
|
msg = f"Could not read data from {file_path}"
|
|
91
119
|
raise FileNotFoundError(msg)
|
|
92
|
-
|
|
93
120
|
return model
|
|
@@ -1,66 +1,94 @@
|
|
|
1
1
|
# --- Variabel definisjoner ---
|
|
2
2
|
# ref: https://statistics-norway.atlassian.net/wiki/spaces/MPD/pages/3009839199/VarDef+-+Krav+til+dokumentasjon+av+variabler
|
|
3
3
|
name: |
|
|
4
|
-
Variabelens navn. Dette skal ikke være en mer “teknisk” forkortelse, men et navn som er forståelig for mennesker
|
|
4
|
+
Variabelens navn. Dette skal ikke være en mer “teknisk” forkortelse, men et navn som er forståelig for mennesker.
|
|
5
|
+
-------------------------
|
|
6
|
+
>>> EKSEMPEL:
|
|
7
|
+
name:
|
|
8
|
+
nb: |-
|
|
9
|
+
Lønnsinntekter
|
|
5
10
|
short_name: |
|
|
6
11
|
Dette er variabelens kortnavn, som kan være en mer “teknisk” forkortelse, f.eks. wlonn (kortnavnet til Lønnsinntekter). Kortnavnet til en variabel i Vardef skal være unikt.
|
|
7
|
-
Kravet til kortnavnet er at det kan inneholde a-z (kun små bokstaver), 0-9 og _ (understrek). Minimumslengden på kortnavnet er 2 tegn.
|
|
12
|
+
Kravet til kortnavnet er at det kan inneholde a-z (kun små bokstaver), 0-9 og _ (understrek). Minimumslengden på kortnavnet er 2 tegn.
|
|
13
|
+
Bokstavene “æ”, “ø” og “å” kan ikke brukes. Disse anbefales erstattet med hhv. “ae”, “oe” og “aa"
|
|
8
14
|
definition: |
|
|
9
15
|
En definisjon skal beskrive hva variabelen betyr og være så kort og presis som mulig. Mer utfyllende opplysninger kan legges i Merknad-feltet.
|
|
16
|
+
-------------------------
|
|
17
|
+
>>> EKSEMPEL:
|
|
18
|
+
definition:
|
|
19
|
+
nb: |-
|
|
20
|
+
Yrkesinntekter, kapitalinntekter, skattepliktige og skattefrie overføringer, i løpet av kalenderåret.
|
|
10
21
|
classification_reference: |
|
|
11
22
|
ID av en klassifikasjon eller kodeliste fra KLASS som beskriver verdiene variabelen kan anta.
|
|
12
23
|
For eksempel vil variabelen 'Sivilstand' ha klassifikasjon 'Standard for sivilstand' (kan vises på https://www.ssb.no/klass/klassifikasjoner/19 ) som har ID 19.
|
|
13
|
-
|
|
24
|
+
-------------------------
|
|
25
|
+
>>> EKSEMPEL:
|
|
26
|
+
classification_reference: "19"
|
|
14
27
|
unit_types: |
|
|
15
|
-
Enhetstyper - enhetene som beskrives av denne variabelen. Variabelen “sivilstand” vil f.eks. ha enhetstypen person,
|
|
28
|
+
Enhetstyper - enhetene som beskrives av denne variabelen. Variabelen “sivilstand” vil f.eks. ha enhetstypen person,
|
|
29
|
+
mens f.eks. “Produsentpris for tjenester” vil ha både foretak og bedrift som enhetstyper siden variabelen kan beskrive begge.
|
|
16
30
|
Verdier skal være koder fra: https://www.ssb.no/klass/klassifikasjoner/702.
|
|
17
|
-
|
|
18
|
-
|
|
31
|
+
-------------------------
|
|
32
|
+
>>> EKSEMPEL:
|
|
33
|
+
unit_types:
|
|
34
|
+
- "20"
|
|
19
35
|
subject_fields: |
|
|
20
36
|
Statistikkområder som variabelen brukes innenfor. For eksempel tilhører variabelen “Sivilstand” statistikkområdet “Befolkning”.
|
|
21
37
|
Verdier skal være koder fra https://www.ssb.no/klass/klassifikasjoner/618.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
38
|
+
-------------------------
|
|
39
|
+
>>> EKSEMPEL:
|
|
40
|
+
subject_fields:
|
|
41
|
+
- "bf"
|
|
42
|
+
- "be"
|
|
25
43
|
contains_special_categories_of_personal_data: |
|
|
26
44
|
Viser om variabelen inneholder spesielt sensitive personopplysninger.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
- opplysninger om religion
|
|
31
|
-
- opplysninger om filosofisk overbevisning
|
|
32
|
-
- opplysninger om fagforeningsmedlemskap
|
|
33
|
-
- genetiske opplysninger
|
|
34
|
-
- biometriske opplysninger med det formål å entydig identifisere noen
|
|
35
|
-
- helseopplysninger
|
|
36
|
-
- opplysninger om seksuelle forhold
|
|
37
|
-
- opplysninger om seksuell legning
|
|
38
|
-
ref: https://lovdata.no/dokument/NL/lov/2018-06-15-38/KAPITTEL_gdpr-2#gdpr/a9
|
|
39
|
-
Eksempel: true
|
|
45
|
+
-------------------------
|
|
46
|
+
>>> EKSEMPEL:
|
|
47
|
+
contains_special_categories_of_personal_data: true
|
|
40
48
|
measurement_type: |
|
|
41
49
|
Måletype som en kvantitativ variabelen tilhører, f.eks. valuta, areal osv.
|
|
42
50
|
Verdien skal være en kode fra: https://www.ssb.no/klass/klassifikasjoner/303
|
|
43
|
-
|
|
51
|
+
-------------------------
|
|
52
|
+
>>> EKSEMPEL:
|
|
53
|
+
measurement_type: "03"
|
|
44
54
|
valid_from: |
|
|
45
55
|
Datoen variabeldefinisjonen er gyldig f.o.m.
|
|
46
|
-
|
|
56
|
+
-------------------------
|
|
57
|
+
>>> EKSEMPEL:
|
|
58
|
+
valid_from: 1999-01-30
|
|
47
59
|
valid_until: |
|
|
48
60
|
Datoen variabeldefinisjonens var gyldig t.o.m. Settes hvis definisjonen skal erstattet av en ny definisjon (med en ny gyldighetsperiode), eller variabelen ikke lenger skal brukes.
|
|
49
|
-
|
|
61
|
+
-------------------------
|
|
62
|
+
>>> EKSEMPEL:
|
|
63
|
+
valid_until: 2024-10-23
|
|
50
64
|
external_reference_uri: |
|
|
51
65
|
En peker (URI) til ekstern definisjon/dokumentasjon, f.eks. ei webside som er relevant for variabelen.
|
|
52
|
-
|
|
66
|
+
-----------------------------------------------------
|
|
67
|
+
>>> EKSEMPEL:
|
|
68
|
+
external_reference_uri: "https://www.landbruksdirektoratet.com"
|
|
53
69
|
comment: |
|
|
54
|
-
Her kan en sette inn eventuelle tilleggsopplysninger som ikke hører hjemme i selve definisjonen.
|
|
70
|
+
Her kan en sette inn eventuelle tilleggsopplysninger som ikke hører hjemme i selve definisjonen.
|
|
71
|
+
Variabelen “Landbakgrunn” har f.eks. merknaden “Fra og med 1.1.2003 ble definisjon endret til også å trekke inn besteforeldrenes fødeland”.
|
|
72
|
+
-----------------------------------------------------------------------------------------------
|
|
73
|
+
>>> EKSEMPEL:
|
|
74
|
+
comment:
|
|
75
|
+
nb: |-
|
|
76
|
+
Fra og med 1.1.2003 ble definisjon endret til også å trekke inn besteforeldrenes fødeland.
|
|
55
77
|
related_variable_definition_uris: |
|
|
56
|
-
Her kan en legge inn URIer til andre variabler som er relevante. Eksempelvis er variabelen “Inntekt etter skatt” en beregnet variabel der “Yrkesinntekter” og “Kapitalinntekter” inngår i beregningen.
|
|
57
|
-
|
|
78
|
+
Her kan en legge inn URIer til andre variabler som er relevante. Eksempelvis er variabelen “Inntekt etter skatt” en beregnet variabel der “Yrkesinntekter” og “Kapitalinntekter” inngår i beregningen.
|
|
79
|
+
En kan da legge inn deres URI-er i dette feltet.
|
|
80
|
+
-------------------------
|
|
81
|
+
>>> EKSEMPEL:
|
|
82
|
+
related_variable_definition_uris:
|
|
83
|
+
- "https://example.com/"
|
|
58
84
|
contact: |
|
|
59
85
|
Her dokumenterer en navn og epost for person eller gruppe som kan svare på spørsmål.
|
|
60
|
-
|
|
61
|
-
|
|
86
|
+
-------------------------
|
|
87
|
+
>>> EKSEMPEL:
|
|
88
|
+
contact:
|
|
62
89
|
title:
|
|
63
|
-
|
|
90
|
+
nb: |-
|
|
91
|
+
Seksjonsleder
|
|
64
92
|
email: leder@ssb.no
|
|
65
93
|
variable_status: |
|
|
66
94
|
Livssyklus for variabelen.
|
|
File without changes
|
|
File without changes
|
{dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/_shared/config.py
RENAMED
|
File without changes
|
{dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/_shared/enums.py
RENAMED
|
File without changes
|
{dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/_shared/py.typed
RENAMED
|
File without changes
|
{dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/dapla/__init__.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
|
{dapla_toolbelt_metadata-0.6.3 → dapla_toolbelt_metadata-0.6.5}/src/dapla_metadata/datasets/py.typed
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
|
|
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
|