dg-kit 0.1.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.
- dg_kit-0.1.0/PKG-INFO +99 -0
- dg_kit-0.1.0/README.md +85 -0
- dg_kit-0.1.0/pyproject.toml +31 -0
- dg_kit-0.1.0/src/dg_kit/__init__.py +0 -0
- dg_kit-0.1.0/src/dg_kit/base/__init__.py +0 -0
- dg_kit-0.1.0/src/dg_kit/base/business_information.py +60 -0
- dg_kit-0.1.0/src/dg_kit/base/convention.py +57 -0
- dg_kit-0.1.0/src/dg_kit/base/data_catalog.py +7 -0
- dg_kit-0.1.0/src/dg_kit/base/dataclasses/__init__.py +7 -0
- dg_kit-0.1.0/src/dg_kit/base/dataclasses/business_information.py +77 -0
- dg_kit-0.1.0/src/dg_kit/base/dataclasses/convention.py +30 -0
- dg_kit-0.1.0/src/dg_kit/base/dataclasses/data_catalog.py +64 -0
- dg_kit-0.1.0/src/dg_kit/base/dataclasses/logical_model.py +86 -0
- dg_kit-0.1.0/src/dg_kit/base/dataclasses/physical_model.py +38 -0
- dg_kit-0.1.0/src/dg_kit/base/enums.py +13 -0
- dg_kit-0.1.0/src/dg_kit/base/logical_model.py +66 -0
- dg_kit-0.1.0/src/dg_kit/base/physical_model.py +41 -0
- dg_kit-0.1.0/src/dg_kit/integrations/__init__.py +0 -0
- dg_kit-0.1.0/src/dg_kit/integrations/dbt/README.md +27 -0
- dg_kit-0.1.0/src/dg_kit/integrations/dbt/__init__.py +0 -0
- dg_kit-0.1.0/src/dg_kit/integrations/dbt/parser.py +202 -0
- dg_kit-0.1.0/src/dg_kit/integrations/notion/README.md +38 -0
- dg_kit-0.1.0/src/dg_kit/integrations/notion/__init__.py +0 -0
- dg_kit-0.1.0/src/dg_kit/integrations/notion/api.py +495 -0
- dg_kit-0.1.0/src/dg_kit/integrations/notion/formater.py +65 -0
- dg_kit-0.1.0/src/dg_kit/integrations/odm/README.md +46 -0
- dg_kit-0.1.0/src/dg_kit/integrations/odm/__init__.py +0 -0
- dg_kit-0.1.0/src/dg_kit/integrations/odm/attr_types.py +6 -0
- dg_kit-0.1.0/src/dg_kit/integrations/odm/parser.py +490 -0
dg_kit-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: dg_kit
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Data Governance Kit provides programmatic access to data governance metadata with integrations for different Logical and Physical Modeling tools.
|
|
5
|
+
Author: Chelidze Georgii
|
|
6
|
+
Author-email: Chelidze Georgii <chelidze.georgii.d@gmail.com>
|
|
7
|
+
License: MIT
|
|
8
|
+
Requires-Dist: pyyaml>=6.0.3 ; extra == 'dbt'
|
|
9
|
+
Requires-Dist: notion-client>=2.7.0 ; extra == 'notion'
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Provides-Extra: dbt
|
|
12
|
+
Provides-Extra: notion
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
15
|
+
## Data Governance Kit (dg_kit)
|
|
16
|
+
|
|
17
|
+
Data Governance Kit helps you access Data Governance information programmatically.
|
|
18
|
+
It provides core objects that model Physical Model, Logical Model, Business Information,
|
|
19
|
+
and related governance metadata. Integrations let you pull this data from tools like
|
|
20
|
+
dbt, Oracle Data Modeler, and Notion, with more connectors planned in upcoming releases.
|
|
21
|
+
|
|
22
|
+
This toolkit is handy for building Data Governance CI gates, strengthening Data Ops
|
|
23
|
+
practices, and keeping governance checks close to your delivery workflows.
|
|
24
|
+
|
|
25
|
+
## Requirements
|
|
26
|
+
- Python >= 3.10
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
```bash
|
|
30
|
+
pip install -e .
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Optional extras:
|
|
34
|
+
```bash
|
|
35
|
+
pip install -e ".[dbt]"
|
|
36
|
+
pip install -e ".[notion]"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Quick Start
|
|
40
|
+
|
|
41
|
+
### Parse an Oracle Data Modeler project
|
|
42
|
+
```python
|
|
43
|
+
from dg_kit.integrations.odm.parser import ODMParser
|
|
44
|
+
|
|
45
|
+
parser = ODMParser("path/to/model.dmd")
|
|
46
|
+
bi = parser.parse_bi()
|
|
47
|
+
lm = parser.parse_lm()
|
|
48
|
+
|
|
49
|
+
print(lm.version, len(lm.entities))
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Parse a dbt project into a physical model
|
|
53
|
+
```python
|
|
54
|
+
from dg_kit.integrations.dbt.parser import DBTParser
|
|
55
|
+
|
|
56
|
+
pm = DBTParser("path/to/dbt_project").parse_pm()
|
|
57
|
+
print(pm.version, len(pm.tables))
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Validate with conventions
|
|
61
|
+
```python
|
|
62
|
+
from dg_kit.base.convention import Convention, ConventionValidator
|
|
63
|
+
from dg_kit.base.enums import ConventionRuleSeverity
|
|
64
|
+
|
|
65
|
+
convention = Convention("example")
|
|
66
|
+
|
|
67
|
+
@convention.rule(
|
|
68
|
+
name="has-entities",
|
|
69
|
+
severity=ConventionRuleSeverity.ERROR,
|
|
70
|
+
description="Logical model must contain at least one entity",
|
|
71
|
+
)
|
|
72
|
+
def has_entities(lm, pm):
|
|
73
|
+
return set() if lm.entities else {("no entities")}
|
|
74
|
+
|
|
75
|
+
issues = ConventionValidator(lm, pm, convention).validate()
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Sync to Notion data catalog
|
|
79
|
+
```python
|
|
80
|
+
from dg_kit.integrations.notion.api import NotionDataCatalog
|
|
81
|
+
|
|
82
|
+
catalog = NotionDataCatalog(
|
|
83
|
+
notion_token="secret",
|
|
84
|
+
dc_table_id="data_source_id",
|
|
85
|
+
)
|
|
86
|
+
rows = catalog.pull()
|
|
87
|
+
print(len(rows))
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Development
|
|
91
|
+
Run tests:
|
|
92
|
+
```bash
|
|
93
|
+
pytest
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Export requirements with uv:
|
|
97
|
+
```bash
|
|
98
|
+
uv export --extra dbt --extra notion --group test -o requirements.txt
|
|
99
|
+
```
|
dg_kit-0.1.0/README.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
## Data Governance Kit (dg_kit)
|
|
2
|
+
|
|
3
|
+
Data Governance Kit helps you access Data Governance information programmatically.
|
|
4
|
+
It provides core objects that model Physical Model, Logical Model, Business Information,
|
|
5
|
+
and related governance metadata. Integrations let you pull this data from tools like
|
|
6
|
+
dbt, Oracle Data Modeler, and Notion, with more connectors planned in upcoming releases.
|
|
7
|
+
|
|
8
|
+
This toolkit is handy for building Data Governance CI gates, strengthening Data Ops
|
|
9
|
+
practices, and keeping governance checks close to your delivery workflows.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
- Python >= 3.10
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
```bash
|
|
16
|
+
pip install -e .
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Optional extras:
|
|
20
|
+
```bash
|
|
21
|
+
pip install -e ".[dbt]"
|
|
22
|
+
pip install -e ".[notion]"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
### Parse an Oracle Data Modeler project
|
|
28
|
+
```python
|
|
29
|
+
from dg_kit.integrations.odm.parser import ODMParser
|
|
30
|
+
|
|
31
|
+
parser = ODMParser("path/to/model.dmd")
|
|
32
|
+
bi = parser.parse_bi()
|
|
33
|
+
lm = parser.parse_lm()
|
|
34
|
+
|
|
35
|
+
print(lm.version, len(lm.entities))
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Parse a dbt project into a physical model
|
|
39
|
+
```python
|
|
40
|
+
from dg_kit.integrations.dbt.parser import DBTParser
|
|
41
|
+
|
|
42
|
+
pm = DBTParser("path/to/dbt_project").parse_pm()
|
|
43
|
+
print(pm.version, len(pm.tables))
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Validate with conventions
|
|
47
|
+
```python
|
|
48
|
+
from dg_kit.base.convention import Convention, ConventionValidator
|
|
49
|
+
from dg_kit.base.enums import ConventionRuleSeverity
|
|
50
|
+
|
|
51
|
+
convention = Convention("example")
|
|
52
|
+
|
|
53
|
+
@convention.rule(
|
|
54
|
+
name="has-entities",
|
|
55
|
+
severity=ConventionRuleSeverity.ERROR,
|
|
56
|
+
description="Logical model must contain at least one entity",
|
|
57
|
+
)
|
|
58
|
+
def has_entities(lm, pm):
|
|
59
|
+
return set() if lm.entities else {("no entities")}
|
|
60
|
+
|
|
61
|
+
issues = ConventionValidator(lm, pm, convention).validate()
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Sync to Notion data catalog
|
|
65
|
+
```python
|
|
66
|
+
from dg_kit.integrations.notion.api import NotionDataCatalog
|
|
67
|
+
|
|
68
|
+
catalog = NotionDataCatalog(
|
|
69
|
+
notion_token="secret",
|
|
70
|
+
dc_table_id="data_source_id",
|
|
71
|
+
)
|
|
72
|
+
rows = catalog.pull()
|
|
73
|
+
print(len(rows))
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Development
|
|
77
|
+
Run tests:
|
|
78
|
+
```bash
|
|
79
|
+
pytest
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Export requirements with uv:
|
|
83
|
+
```bash
|
|
84
|
+
uv export --extra dbt --extra notion --group test -o requirements.txt
|
|
85
|
+
```
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["uv_build>=0.9.26,<0.10.0"]
|
|
3
|
+
build-backend = "uv_build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "dg_kit"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Data Governance Kit provides programmatic access to data governance metadata with integrations for different Logical and Physical Modeling tools."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Chelidze Georgii", email = "chelidze.georgii.d@gmail.com" }]
|
|
13
|
+
|
|
14
|
+
[project.optional-dependencies]
|
|
15
|
+
notion = [
|
|
16
|
+
"notion-client>=2.7.0",
|
|
17
|
+
]
|
|
18
|
+
dbt = [
|
|
19
|
+
"pyyaml>=6.0.3",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
[dependency-groups]
|
|
23
|
+
dev = [
|
|
24
|
+
"pre-commit>=4.5.1",
|
|
25
|
+
"pyright>=1.1.408",
|
|
26
|
+
"pytest>=9.0.2",
|
|
27
|
+
"ruff>=0.15.0",
|
|
28
|
+
]
|
|
29
|
+
test = [
|
|
30
|
+
"pytest>=9.0.2",
|
|
31
|
+
]
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from typing import Dict
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
from dg_kit.base.dataclasses.business_information import (
|
|
6
|
+
Team,
|
|
7
|
+
Contact,
|
|
8
|
+
Document,
|
|
9
|
+
Email,
|
|
10
|
+
Url,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class BusinessInformation:
|
|
15
|
+
def __init__(self, version: str):
|
|
16
|
+
self.version = version
|
|
17
|
+
self.teams: Dict[str, Team] = {}
|
|
18
|
+
self.contacts: Dict[str, Contact] = {}
|
|
19
|
+
self.documents: Dict[str, Document] = {}
|
|
20
|
+
self.emails: Dict[str, Email] = {}
|
|
21
|
+
self.urls: Dict[str, Url] = {}
|
|
22
|
+
self.all_units_by_id: Dict[str, Team | Contact | Document | Email | Url] = {}
|
|
23
|
+
self.all_units_by_natural_key: Dict[
|
|
24
|
+
str, Team | Contact | Document | Email | Url
|
|
25
|
+
] = {}
|
|
26
|
+
|
|
27
|
+
def register_team(self, team: Team) -> None:
|
|
28
|
+
self.teams[team.id] = team
|
|
29
|
+
self.all_units_by_id[team.id] = team
|
|
30
|
+
self.all_units_by_natural_key[team.natural_key] = team
|
|
31
|
+
|
|
32
|
+
def register_contact(self, contact: Contact) -> None:
|
|
33
|
+
self.contacts[contact.id] = contact
|
|
34
|
+
self.all_units_by_id[contact.id] = contact
|
|
35
|
+
self.all_units_by_natural_key[contact.natural_key] = contact
|
|
36
|
+
|
|
37
|
+
def register_document(self, document: Document) -> None:
|
|
38
|
+
self.documents[document.id] = document
|
|
39
|
+
self.all_units_by_id[document.id] = document
|
|
40
|
+
self.all_units_by_natural_key[document.natural_key] = document
|
|
41
|
+
|
|
42
|
+
def register_email(self, email: Email) -> None:
|
|
43
|
+
self.emails[email.id] = email
|
|
44
|
+
self.all_units_by_id[email.id] = email
|
|
45
|
+
self.all_units_by_natural_key[email.natural_key] = email
|
|
46
|
+
|
|
47
|
+
def register_url(self, url: Url) -> None:
|
|
48
|
+
self.urls[url.id] = url
|
|
49
|
+
self.all_units_by_id[url.id] = url
|
|
50
|
+
self.all_units_by_natural_key[url.natural_key] = url
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class BusinessInformationDatabase:
|
|
54
|
+
def __init__(self):
|
|
55
|
+
self.business_information: Dict[str, BusinessInformation] = {}
|
|
56
|
+
|
|
57
|
+
def register_business_information(
|
|
58
|
+
self, business_information: BusinessInformation
|
|
59
|
+
) -> None:
|
|
60
|
+
self.business_information[business_information.version] = business_information
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import List
|
|
4
|
+
|
|
5
|
+
from dg_kit.base.physical_model import PhysicalModel
|
|
6
|
+
from dg_kit.base.logical_model import LogicalModel
|
|
7
|
+
from dg_kit.base.enums import ConventionRuleSeverity
|
|
8
|
+
from dg_kit.base.dataclasses.convention import (
|
|
9
|
+
ConventionRule,
|
|
10
|
+
ConventionRuleFn,
|
|
11
|
+
ConventionBreach,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Convention:
|
|
16
|
+
def __init__(self, name: str):
|
|
17
|
+
self.name = name
|
|
18
|
+
self._rules: List[ConventionRule] = []
|
|
19
|
+
|
|
20
|
+
def rule(
|
|
21
|
+
self,
|
|
22
|
+
name: str,
|
|
23
|
+
severity: ConventionRuleSeverity,
|
|
24
|
+
description: str,
|
|
25
|
+
):
|
|
26
|
+
def decorator(fn: ConventionRuleFn) -> ConventionRuleFn:
|
|
27
|
+
self._rules.append(ConventionRule(name, severity, description, fn))
|
|
28
|
+
return fn
|
|
29
|
+
|
|
30
|
+
return decorator
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def rules(self) -> List[ConventionRule]:
|
|
34
|
+
return list(self._rules)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class ConventionValidator:
|
|
38
|
+
def __init__(self, lm: LogicalModel, pm: PhysicalModel, convention: Convention):
|
|
39
|
+
self.lm = lm
|
|
40
|
+
self.pm = pm
|
|
41
|
+
self.convention = convention
|
|
42
|
+
|
|
43
|
+
def validate(self) -> List[ConventionBreach]:
|
|
44
|
+
issues: List[ConventionBreach] = []
|
|
45
|
+
|
|
46
|
+
for rule in self.convention.rules:
|
|
47
|
+
res = rule.fn(self.lm, self.pm)
|
|
48
|
+
for issue in res:
|
|
49
|
+
issue = ConventionBreach(
|
|
50
|
+
severity=rule.severity,
|
|
51
|
+
message=issue.message,
|
|
52
|
+
unit_id=issue.unit_id,
|
|
53
|
+
unit_natural_key=issue.unit_natural_key,
|
|
54
|
+
)
|
|
55
|
+
issues.append(issue)
|
|
56
|
+
|
|
57
|
+
return issues
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Docstring for dg_kit.base.dataclasses.business_information
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from dataclasses import dataclass, field
|
|
8
|
+
from typing import Optional, Tuple
|
|
9
|
+
|
|
10
|
+
from dg_kit.base.dataclasses import id_generator
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True, slots=True)
|
|
14
|
+
class SlackChannelUrl:
|
|
15
|
+
id: str = field(init=False)
|
|
16
|
+
natural_key: str
|
|
17
|
+
name: str
|
|
18
|
+
url: Optional[str]
|
|
19
|
+
|
|
20
|
+
def __post_init__(self) -> None:
|
|
21
|
+
object.__setattr__(self, "id", id_generator(self.natural_key))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True, slots=True)
|
|
25
|
+
class Email:
|
|
26
|
+
id: str = field(init=False)
|
|
27
|
+
natural_key: str
|
|
28
|
+
name: str
|
|
29
|
+
email_address: Optional[str]
|
|
30
|
+
|
|
31
|
+
def __post_init__(self) -> None:
|
|
32
|
+
object.__setattr__(self, "id", id_generator(self.natural_key))
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclass(frozen=True, slots=True)
|
|
36
|
+
class Url:
|
|
37
|
+
id: str = field(init=False)
|
|
38
|
+
natural_key: str
|
|
39
|
+
name: str
|
|
40
|
+
url: Optional[str]
|
|
41
|
+
|
|
42
|
+
def __post_init__(self) -> None:
|
|
43
|
+
object.__setattr__(self, "id", id_generator(self.natural_key))
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass(frozen=True, slots=True)
|
|
47
|
+
class Contact:
|
|
48
|
+
id: str = field(init=False)
|
|
49
|
+
natural_key: str
|
|
50
|
+
name: str
|
|
51
|
+
emails: Tuple[Email, ...]
|
|
52
|
+
urls: Tuple[Url, ...]
|
|
53
|
+
|
|
54
|
+
def __post_init__(self) -> None:
|
|
55
|
+
object.__setattr__(self, "id", id_generator(self.natural_key))
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass(frozen=True, slots=True)
|
|
59
|
+
class Team:
|
|
60
|
+
id: str = field(init=False)
|
|
61
|
+
natural_key: str
|
|
62
|
+
name: str
|
|
63
|
+
contacts: Tuple[Contact, ...]
|
|
64
|
+
|
|
65
|
+
def __post_init__(self) -> None:
|
|
66
|
+
object.__setattr__(self, "id", id_generator(self.natural_key))
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@dataclass(frozen=True, slots=True)
|
|
70
|
+
class Document:
|
|
71
|
+
id: str = field(init=False)
|
|
72
|
+
natural_key: str
|
|
73
|
+
name: str
|
|
74
|
+
reference: Optional[str]
|
|
75
|
+
|
|
76
|
+
def __post_init__(self) -> None:
|
|
77
|
+
object.__setattr__(self, "id", id_generator(self.natural_key))
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Optional, Protocol, Set
|
|
5
|
+
|
|
6
|
+
from dg_kit.base.enums import ConventionRuleSeverity
|
|
7
|
+
from dg_kit.base.logical_model import LogicalModel
|
|
8
|
+
from dg_kit.base.physical_model import PhysicalModel
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(frozen=True, slots=True)
|
|
12
|
+
class ConventionBreach:
|
|
13
|
+
severity: ConventionRuleSeverity
|
|
14
|
+
message: str
|
|
15
|
+
unit_id: Optional[str] = None
|
|
16
|
+
unit_natural_key: Optional[str] = None
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ConventionRuleFn(Protocol):
|
|
20
|
+
def __call__(
|
|
21
|
+
self, lm: LogicalModel, pm: PhysicalModel
|
|
22
|
+
) -> Set[ConventionBreach]: ...
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass(frozen=True, slots=True)
|
|
26
|
+
class ConventionRule:
|
|
27
|
+
name: str
|
|
28
|
+
severity: ConventionRuleSeverity
|
|
29
|
+
description: str
|
|
30
|
+
fn: ConventionRuleFn
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Optional, Tuple
|
|
4
|
+
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
|
|
9
|
+
from dg_kit.base.enums import DataUnitType
|
|
10
|
+
from dg_kit.base.dataclasses.business_information import Document, Team
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True, slots=True)
|
|
14
|
+
class DataCatalogRow:
|
|
15
|
+
data_unit_name: str
|
|
16
|
+
data_unit_type: DataUnitType
|
|
17
|
+
domain: str
|
|
18
|
+
data_unit_uuid: str
|
|
19
|
+
last_edited_time: Optional[datetime] = None
|
|
20
|
+
created_time: Optional[datetime] = None
|
|
21
|
+
|
|
22
|
+
def __post_init__(self) -> None: ...
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass(frozen=True, slots=True)
|
|
26
|
+
class EntityTypeDataUnitPageInfo:
|
|
27
|
+
data_unit_type: DataUnitType
|
|
28
|
+
description: str
|
|
29
|
+
linked_documents: Tuple[Document, ...]
|
|
30
|
+
responsible_parties: Tuple[Team, ...]
|
|
31
|
+
master_source_systems: Tuple[str, ...]
|
|
32
|
+
core_layer_mapping: Tuple[str, ...]
|
|
33
|
+
pk_attributes_page_ids: Tuple[str, ...]
|
|
34
|
+
attributes_page_ids: Tuple[str, ...]
|
|
35
|
+
relationes_page_ids: Tuple[str, ...]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass(frozen=True, slots=True)
|
|
39
|
+
class AttributeTypeDataUnitPageInfo:
|
|
40
|
+
parent_entity_page_id: str
|
|
41
|
+
data_unit_type: DataUnitType
|
|
42
|
+
description: str
|
|
43
|
+
data_type: str
|
|
44
|
+
sensitivity_type: str
|
|
45
|
+
linked_documents: Tuple[Document, ...]
|
|
46
|
+
responsible_parties: Tuple[Team, ...]
|
|
47
|
+
core_layer_mapping: Tuple[str, ...]
|
|
48
|
+
master_source_systems: Tuple[str, ...]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@dataclass(frozen=True, slots=True)
|
|
52
|
+
class RelationTypeDataUnitPageInfo:
|
|
53
|
+
data_unit_type: DataUnitType
|
|
54
|
+
description: str
|
|
55
|
+
linked_documents: Tuple[Document, ...]
|
|
56
|
+
responsible_parties: Tuple[Team, ...]
|
|
57
|
+
core_layer_mapping: Tuple[str, ...]
|
|
58
|
+
master_source_systems: Tuple[str, ...]
|
|
59
|
+
source_entity_page_id: str
|
|
60
|
+
target_entity_page_id: str
|
|
61
|
+
optional_source: bool
|
|
62
|
+
optional_target: bool
|
|
63
|
+
source_cardinality: str
|
|
64
|
+
target_cardinality: str
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from typing import Optional, Tuple
|
|
6
|
+
|
|
7
|
+
from dg_kit.base.dataclasses import id_generator
|
|
8
|
+
from dg_kit.base.dataclasses.business_information import Team, Document
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(frozen=True, slots=True)
|
|
12
|
+
class EntityIdentifier:
|
|
13
|
+
id: str = field(init=False)
|
|
14
|
+
natural_key: str
|
|
15
|
+
name: Optional[str]
|
|
16
|
+
is_pk: bool
|
|
17
|
+
entity_id: str
|
|
18
|
+
used_attributes_ids: Tuple[str, ...]
|
|
19
|
+
|
|
20
|
+
def __post_init__(self) -> None:
|
|
21
|
+
object.__setattr__(self, "id", id_generator(self.natural_key))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True, slots=True)
|
|
25
|
+
class Relation:
|
|
26
|
+
id: str = field(init=False)
|
|
27
|
+
natural_key: str
|
|
28
|
+
name: str
|
|
29
|
+
domain: Optional[str]
|
|
30
|
+
description: str
|
|
31
|
+
pm_map: Tuple[str, ...]
|
|
32
|
+
master_source_systems: Tuple[str, ...]
|
|
33
|
+
responsible_parties: Tuple[Team, ...]
|
|
34
|
+
documents: Tuple[Document, ...]
|
|
35
|
+
source_entity_id: str
|
|
36
|
+
target_entity_id: str
|
|
37
|
+
optional_source: Optional[bool]
|
|
38
|
+
optional_target: Optional[bool]
|
|
39
|
+
source_cardinality: Optional[str]
|
|
40
|
+
target_cardinality: Optional[str]
|
|
41
|
+
created_by: Optional[str] = None
|
|
42
|
+
created_time: Optional[datetime] = None
|
|
43
|
+
|
|
44
|
+
def __post_init__(self) -> None:
|
|
45
|
+
object.__setattr__(self, "id", id_generator(self.natural_key))
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass(frozen=True, slots=True)
|
|
49
|
+
class Attribute:
|
|
50
|
+
id: str = field(init=False)
|
|
51
|
+
natural_key: str
|
|
52
|
+
name: str
|
|
53
|
+
domain: Optional[str]
|
|
54
|
+
description: str
|
|
55
|
+
sensitivity_type: str
|
|
56
|
+
data_type: str
|
|
57
|
+
pm_map: Tuple[str, ...]
|
|
58
|
+
master_source_systems: Tuple[str, ...]
|
|
59
|
+
responsible_parties: Tuple[Team, ...]
|
|
60
|
+
documents: Tuple[Document, ...]
|
|
61
|
+
entity_id: str
|
|
62
|
+
created_by: Optional[str] = None
|
|
63
|
+
created_time: Optional[datetime] = None
|
|
64
|
+
|
|
65
|
+
def __post_init__(self) -> None:
|
|
66
|
+
object.__setattr__(self, "id", id_generator(self.natural_key))
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@dataclass(frozen=True, slots=True)
|
|
70
|
+
class Entity:
|
|
71
|
+
id: str = field(init=False)
|
|
72
|
+
natural_key: str
|
|
73
|
+
name: str
|
|
74
|
+
domain: Optional[str]
|
|
75
|
+
description: str
|
|
76
|
+
identifiers: Tuple[EntityIdentifier, ...]
|
|
77
|
+
attributes: Tuple[str, ...]
|
|
78
|
+
pm_map: Tuple[str, ...]
|
|
79
|
+
master_source_systems: Tuple[str, ...]
|
|
80
|
+
responsible_parties: Tuple[Team, ...]
|
|
81
|
+
documents: Tuple[Document, ...]
|
|
82
|
+
created_by: Optional[str] = None
|
|
83
|
+
created_time: Optional[datetime] = None
|
|
84
|
+
|
|
85
|
+
def __post_init__(self) -> None:
|
|
86
|
+
object.__setattr__(self, "id", id_generator(self.natural_key))
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from dg_kit.base.dataclasses import id_generator
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@dataclass(frozen=True, slots=True)
|
|
6
|
+
class Layer:
|
|
7
|
+
id: str = field(init=False)
|
|
8
|
+
natural_key: str
|
|
9
|
+
name: str
|
|
10
|
+
is_landing: bool
|
|
11
|
+
|
|
12
|
+
def __post_init__(self) -> None:
|
|
13
|
+
object.__setattr__(self, "id", id_generator(self.natural_key))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass(frozen=True, slots=True)
|
|
17
|
+
class Table:
|
|
18
|
+
id: str = field(init=False)
|
|
19
|
+
natural_key: str
|
|
20
|
+
layer_id: str
|
|
21
|
+
name: str
|
|
22
|
+
|
|
23
|
+
def __post_init__(self) -> None:
|
|
24
|
+
object.__setattr__(self, "id", id_generator(self.natural_key))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass(frozen=True, slots=True)
|
|
28
|
+
class Column:
|
|
29
|
+
id: str = field(init=False)
|
|
30
|
+
natural_key: str
|
|
31
|
+
layer_id: str
|
|
32
|
+
table_id: str
|
|
33
|
+
name: str
|
|
34
|
+
data_type: str
|
|
35
|
+
description: str = ""
|
|
36
|
+
|
|
37
|
+
def __post_init__(self) -> None:
|
|
38
|
+
object.__setattr__(self, "id", id_generator(self.natural_key))
|