cloe-nessy 0.3.11.1b0__py3-none-any.whl → 0.3.11.2b0__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.
- cloe_nessy/models/table.py +56 -17
- cloe_nessy/models/templates/create_table.sql.j2 +36 -0
- cloe_nessy/models/templates/create_volume.sql.j2 +3 -0
- cloe_nessy/models/volume.py +57 -17
- {cloe_nessy-0.3.11.1b0.dist-info → cloe_nessy-0.3.11.2b0.dist-info}/METADATA +1 -1
- {cloe_nessy-0.3.11.1b0.dist-info → cloe_nessy-0.3.11.2b0.dist-info}/RECORD +8 -6
- {cloe_nessy-0.3.11.1b0.dist-info → cloe_nessy-0.3.11.2b0.dist-info}/WHEEL +0 -0
- {cloe_nessy-0.3.11.1b0.dist-info → cloe_nessy-0.3.11.2b0.dist-info}/top_level.txt +0 -0
cloe_nessy/models/table.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# type: ignore
|
|
1
2
|
from pathlib import Path
|
|
2
3
|
from typing import Any, Self
|
|
3
4
|
|
|
@@ -13,9 +14,12 @@ from pydantic import (
|
|
|
13
14
|
)
|
|
14
15
|
|
|
15
16
|
try:
|
|
16
|
-
from importlib.resources import files
|
|
17
|
+
from importlib.resources import files # type: ignore[attr-defined]
|
|
17
18
|
except ImportError:
|
|
18
|
-
|
|
19
|
+
try:
|
|
20
|
+
from importlib_resources import files # type: ignore[import-untyped]
|
|
21
|
+
except ImportError:
|
|
22
|
+
files = None # type: ignore[assignment]
|
|
19
23
|
|
|
20
24
|
from ..logging import LoggerMixin
|
|
21
25
|
from ..utils.file_and_directory_handler import process_path
|
|
@@ -252,26 +256,61 @@ class Table(TemplateLoaderMixin, ReadInstancesMixin, LoggerMixin):
|
|
|
252
256
|
Raises:
|
|
253
257
|
TemplateNotFound: If the template file is not found.
|
|
254
258
|
"""
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
+
template_name = "create_table.sql.j2"
|
|
260
|
+
template = None
|
|
261
|
+
|
|
262
|
+
# Approach 1: Try importlib.resources (recommended for Python 3.9+)
|
|
263
|
+
if files is not None:
|
|
264
|
+
try:
|
|
265
|
+
template_files = files("cloe_nessy.models") / "templates"
|
|
266
|
+
template_content = (template_files / template_name).read_text()
|
|
267
|
+
|
|
268
|
+
from jinja2 import BaseLoader, Environment
|
|
259
269
|
|
|
260
|
-
|
|
261
|
-
|
|
270
|
+
env = Environment(loader=BaseLoader(), keep_trailing_newline=True)
|
|
271
|
+
template = env.from_string(template_content)
|
|
262
272
|
|
|
263
|
-
|
|
264
|
-
|
|
273
|
+
except (FileNotFoundError, AttributeError, ImportError):
|
|
274
|
+
pass # Try next approach
|
|
275
|
+
|
|
276
|
+
# Approach 2: Try relative to __file__ (development/editable install)
|
|
277
|
+
if template is None:
|
|
278
|
+
try:
|
|
279
|
+
templates = Path(__file__).parent / "templates"
|
|
280
|
+
template = self.get_template(templates, template_name)
|
|
281
|
+
except TemplateNotFound:
|
|
282
|
+
pass # Try next approach
|
|
265
283
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
templates = Path(__file__).parent / "templates"
|
|
269
|
-
template_name = "create_table.sql.j2"
|
|
284
|
+
# Approach 3: Try relative to module location
|
|
285
|
+
if template is None:
|
|
270
286
|
try:
|
|
287
|
+
import cloe_nessy.models
|
|
288
|
+
|
|
289
|
+
module_path = Path(cloe_nessy.models.__file__).parent
|
|
290
|
+
templates = module_path / "templates"
|
|
271
291
|
template = self.get_template(templates, template_name)
|
|
272
|
-
except TemplateNotFound
|
|
273
|
-
|
|
274
|
-
|
|
292
|
+
except (TemplateNotFound, AttributeError):
|
|
293
|
+
pass # Try next approach
|
|
294
|
+
|
|
295
|
+
# Approach 4: Last resort - search in package data
|
|
296
|
+
if template is None:
|
|
297
|
+
try:
|
|
298
|
+
import pkg_resources
|
|
299
|
+
|
|
300
|
+
template_content = pkg_resources.resource_string(
|
|
301
|
+
"cloe_nessy.models", f"templates/{template_name}"
|
|
302
|
+
).decode("utf-8")
|
|
303
|
+
|
|
304
|
+
from jinja2 import BaseLoader, Environment
|
|
305
|
+
|
|
306
|
+
env = Environment(loader=BaseLoader(), keep_trailing_newline=True)
|
|
307
|
+
template = env.from_string(template_content)
|
|
308
|
+
except (ImportError, FileNotFoundError):
|
|
309
|
+
pass # All approaches failed
|
|
310
|
+
|
|
311
|
+
if template is None:
|
|
312
|
+
self._console_logger.error(f"Template [ {template_name} ] not found in any location.")
|
|
313
|
+
raise TemplateNotFound(template_name)
|
|
275
314
|
|
|
276
315
|
render = template.render(table=self, replace=replace)
|
|
277
316
|
return render
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
CREATE {% if replace %}OR REPLACE {% endif %}{% if table.is_external %}EXTERNAL {% endif -%}
|
|
2
|
+
TABLE {%- if not replace %} IF NOT EXISTS{% endif %} {{ table.escaped_identifier }} {% if table.columns %}( {% endif %}
|
|
3
|
+
{%- for column in table.columns %}
|
|
4
|
+
{% if not loop.first %}, {% endif -%}
|
|
5
|
+
{{column.name}} {{column.data_type|upper}}
|
|
6
|
+
{%- if not column.nullable %} NOT NULL{% endif -%}
|
|
7
|
+
{%- if column.default_value %} DEFAULT {{column.default_value}}{% endif -%}
|
|
8
|
+
{%- if column.comment %} COMMENT '{{column.comment}}'{% endif -%}
|
|
9
|
+
{%- if column.generated %} GENERATED {{column.generated}}{% endif -%}
|
|
10
|
+
{% endfor %}
|
|
11
|
+
{% if table.columns %}) {% endif %}
|
|
12
|
+
USING delta
|
|
13
|
+
{% if table.storage_path %}
|
|
14
|
+
LOCATION '{{ table.storage_path }}'
|
|
15
|
+
{% endif %}
|
|
16
|
+
{% if table.partition_by -%}
|
|
17
|
+
{%- if table.liquid_clustering -%} CLUSTER {%- else -%} PARTITIONED {%- endif %} BY (
|
|
18
|
+
{%- for column in table.partition_by -%}
|
|
19
|
+
{%- if not loop.first %}, {% endif -%}
|
|
20
|
+
{{column}}
|
|
21
|
+
{%- endfor -%}
|
|
22
|
+
)
|
|
23
|
+
{%- endif -%}
|
|
24
|
+
;
|
|
25
|
+
{%- for constraint in table.constraints %}
|
|
26
|
+
ALTER TABLE {{ table.escaped_identifier }} ADD CONSTRAINT {{constraint.name}} CHECK ({{constraint.expression}});
|
|
27
|
+
{%- endfor -%}
|
|
28
|
+
|
|
29
|
+
{%- for fk in table.foreign_keys %}
|
|
30
|
+
ALTER TABLE {{ table.escaped_identifier }} ADD CONSTRAINT {{table.name}}__{{fk.parent_table|replace(".","_")}}__{{fk.foreign_key_columns|join("_")}} FOREIGN KEY ({{fk.foreign_key_columns|join(", ")}}) REFERENCES {{fk.parent_table}}({{fk.parent_columns|join(", ")}})
|
|
31
|
+
NOT ENFORCED NORELY;
|
|
32
|
+
{%- endfor %}
|
|
33
|
+
|
|
34
|
+
{%- if table.comment %}
|
|
35
|
+
COMMENT ON TABLE {{ table.escaped_identifier }} IS '{{ table.comment }}';
|
|
36
|
+
{%- endif %}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
CREATE{% if volume.storage_path %} EXTERNAL{% endif %} VOLUME{% if if_not_exists %} IF NOT EXISTS{% endif %} {{ volume.escaped_identifier }}
|
|
2
|
+
{%- if volume.storage_path %} LOCATION '{{ volume.storage_path }}'{% endif -%}
|
|
3
|
+
{%- if volume.comment %} COMMENT '{{ volume.comment }}'{% endif -%};
|
cloe_nessy/models/volume.py
CHANGED
|
@@ -5,9 +5,14 @@ from jinja2 import TemplateNotFound
|
|
|
5
5
|
from pydantic import BaseModel, field_validator
|
|
6
6
|
|
|
7
7
|
try:
|
|
8
|
-
from importlib.resources import files
|
|
8
|
+
from importlib.resources import files # type: ignore[attr-defined]
|
|
9
9
|
except ImportError:
|
|
10
|
-
|
|
10
|
+
try:
|
|
11
|
+
from importlib_resources import files as importlib_resources_files # type: ignore[import-untyped]
|
|
12
|
+
|
|
13
|
+
files = importlib_resources_files
|
|
14
|
+
except ImportError:
|
|
15
|
+
files = None # type: ignore[assignment]
|
|
11
16
|
|
|
12
17
|
from ..logging import LoggerMixin
|
|
13
18
|
from .mixins.template_loader_mixin import TemplateLoaderMixin
|
|
@@ -69,26 +74,61 @@ class Volume(TemplateLoaderMixin, LoggerMixin, BaseModel):
|
|
|
69
74
|
Returns:
|
|
70
75
|
The rendered create statement as a string.
|
|
71
76
|
"""
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
77
|
+
template_name = "create_volume.sql.j2"
|
|
78
|
+
template = None
|
|
79
|
+
|
|
80
|
+
# Approach 1: Try importlib.resources (recommended for Python 3.9+)
|
|
81
|
+
if files is not None:
|
|
82
|
+
try:
|
|
83
|
+
template_files = files("cloe_nessy.models") / "templates"
|
|
84
|
+
template_content = (template_files / template_name).read_text()
|
|
85
|
+
|
|
86
|
+
from jinja2 import BaseLoader, Environment
|
|
76
87
|
|
|
77
|
-
|
|
78
|
-
|
|
88
|
+
env = Environment(loader=BaseLoader(), keep_trailing_newline=True)
|
|
89
|
+
template = env.from_string(template_content)
|
|
79
90
|
|
|
80
|
-
|
|
81
|
-
|
|
91
|
+
except (FileNotFoundError, AttributeError, ImportError):
|
|
92
|
+
pass # Try next approach
|
|
93
|
+
|
|
94
|
+
# Approach 2: Try relative to __file__ (development/editable install)
|
|
95
|
+
if template is None:
|
|
96
|
+
try:
|
|
97
|
+
templates = Path(__file__).parent / "templates"
|
|
98
|
+
template = self.get_template(templates, template_name)
|
|
99
|
+
except TemplateNotFound:
|
|
100
|
+
pass # Try next approach
|
|
82
101
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
template_name = "create_volume.sql.j2"
|
|
86
|
-
templates = Path(__file__).parent / "templates"
|
|
102
|
+
# Approach 3: Try relative to module location
|
|
103
|
+
if template is None:
|
|
87
104
|
try:
|
|
105
|
+
import cloe_nessy.models
|
|
106
|
+
|
|
107
|
+
module_path = Path(cloe_nessy.models.__file__).parent
|
|
108
|
+
templates = module_path / "templates"
|
|
88
109
|
template = self.get_template(templates, template_name)
|
|
89
|
-
except TemplateNotFound
|
|
90
|
-
|
|
91
|
-
|
|
110
|
+
except (TemplateNotFound, AttributeError):
|
|
111
|
+
pass # Try next approach
|
|
112
|
+
|
|
113
|
+
# Approach 4: Last resort - search in package data
|
|
114
|
+
if template is None:
|
|
115
|
+
try:
|
|
116
|
+
import pkg_resources
|
|
117
|
+
|
|
118
|
+
template_content = pkg_resources.resource_string(
|
|
119
|
+
"cloe_nessy.models", f"templates/{template_name}"
|
|
120
|
+
).decode("utf-8")
|
|
121
|
+
|
|
122
|
+
from jinja2 import BaseLoader, Environment
|
|
123
|
+
|
|
124
|
+
env = Environment(loader=BaseLoader(), keep_trailing_newline=True)
|
|
125
|
+
template = env.from_string(template_content)
|
|
126
|
+
except (ImportError, FileNotFoundError):
|
|
127
|
+
pass # All approaches failed
|
|
128
|
+
|
|
129
|
+
if template is None:
|
|
130
|
+
self._console_logger.error(f"Template [ {template_name} ] not found in any location.")
|
|
131
|
+
raise TemplateNotFound(template_name)
|
|
92
132
|
|
|
93
133
|
render = template.render(volume=self, if_not_exists=if_not_exists)
|
|
94
134
|
return render
|
|
@@ -42,14 +42,16 @@ cloe_nessy/models/column.py,sha256=53fBwRnino72XKACsHZpN9QfCBqqSXyKLHZlM0huumg,1
|
|
|
42
42
|
cloe_nessy/models/constraint.py,sha256=hsFlhn4n928z81O3dl3v5bMetewPWzMjkJK3_4kASSM,178
|
|
43
43
|
cloe_nessy/models/foreign_key.py,sha256=DwRVHs9sShqqPV-NL7ow_3AmPPWX0Od26yZn_I565pU,1001
|
|
44
44
|
cloe_nessy/models/schema.py,sha256=yUrjjEhAH5zbCymE67Az_jPnVB8hGO-_UNfqzeZCD_Y,3376
|
|
45
|
-
cloe_nessy/models/table.py,sha256=
|
|
45
|
+
cloe_nessy/models/table.py,sha256=D3kkPG_iqOcCuOKSCcgj34Xf9fLMTspNK28hPn07Xtc,14258
|
|
46
46
|
cloe_nessy/models/types.py,sha256=XRbuJGdTNa6aXyE3IAzs_J9gVjbfkzMDLfGl-k6jI_4,223
|
|
47
|
-
cloe_nessy/models/volume.py,sha256=
|
|
47
|
+
cloe_nessy/models/volume.py,sha256=OnpwVej2o_JTHG3R09EJRFQcCUBNo3VPLR6GgKoCsYc,4678
|
|
48
48
|
cloe_nessy/models/adapter/__init__.py,sha256=m36W_mqwB3dCYnCIt0fLOSHS4E1VU8FRGoaum4Gf95o,90
|
|
49
49
|
cloe_nessy/models/adapter/unity_catalog_adapter.py,sha256=a-14Ys-AevVYQd0xeJU1syLxjT5Wzo4uog1hFSEs76M,12651
|
|
50
50
|
cloe_nessy/models/mixins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
51
51
|
cloe_nessy/models/mixins/read_instance_mixin.py,sha256=j5Y4aNWOh1jlskEaxNooZFJgPyxRmik00gAVLJnAaRs,4507
|
|
52
52
|
cloe_nessy/models/mixins/template_loader_mixin.py,sha256=5MXhEGBFlq3dwZvINEyBowSlipNnVun2H_TmhI_fsS4,549
|
|
53
|
+
cloe_nessy/models/templates/create_table.sql.j2,sha256=QWbiTXwmGaIlZUAIGL4pAlHkDbP9mq1vGAkdKCPOqm4,1669
|
|
54
|
+
cloe_nessy/models/templates/create_volume.sql.j2,sha256=XIUf1cHcvAxcGTyhzUiv4xpQ1cfDw_ra3_FKmOuLoBs,289
|
|
53
55
|
cloe_nessy/object_manager/__init__.py,sha256=3sle0vNpPwBOkycxA3XVS9m4XZf5LD3Qd4NGxdqcHno,186
|
|
54
56
|
cloe_nessy/object_manager/table_manager.py,sha256=oYcYiZR0-JyoadcCcDelxfFb-ATeKDIZerYaZc-moiI,12634
|
|
55
57
|
cloe_nessy/object_manager/volume_manager.py,sha256=6epd3KXzcNH04EvaKubAfLsaUm9qBMeT3KNvMK04gGs,2727
|
|
@@ -92,7 +94,7 @@ cloe_nessy/settings/__init__.py,sha256=ZbkneO3WaKOxon7qHFHnou7EnBOSnBFyKMDZblIEv
|
|
|
92
94
|
cloe_nessy/settings/settings.py,sha256=I4n129lrujriW-d8q4as2Kb4_kI932ModfZ5Ow_UpVM,3653
|
|
93
95
|
cloe_nessy/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
94
96
|
cloe_nessy/utils/file_and_directory_handler.py,sha256=r2EVt9xG81p6ScaJCwETC5an6pMT6WseB0jMOR-JlpU,602
|
|
95
|
-
cloe_nessy-0.3.11.
|
|
96
|
-
cloe_nessy-0.3.11.
|
|
97
|
-
cloe_nessy-0.3.11.
|
|
98
|
-
cloe_nessy-0.3.11.
|
|
97
|
+
cloe_nessy-0.3.11.2b0.dist-info/METADATA,sha256=pjkK299KMeCos76S2Vj_3k8E7sFY6narDkE8472nfQY,3166
|
|
98
|
+
cloe_nessy-0.3.11.2b0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
99
|
+
cloe_nessy-0.3.11.2b0.dist-info/top_level.txt,sha256=Z7izn8HmQpg2wBUb-0jzaKlYKMU7Ypzuc9__9vPtW_I,11
|
|
100
|
+
cloe_nessy-0.3.11.2b0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|