cloe-nessy 0.3.10__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.
@@ -1,3 +1,4 @@
1
+ # type: ignore
1
2
  from pathlib import Path
2
3
  from typing import Any, Self
3
4
 
@@ -12,6 +13,14 @@ from pydantic import (
12
13
  model_validator,
13
14
  )
14
15
 
16
+ try:
17
+ from importlib.resources import files # type: ignore[attr-defined]
18
+ except ImportError:
19
+ try:
20
+ from importlib_resources import files # type: ignore[import-untyped]
21
+ except ImportError:
22
+ files = None # type: ignore[assignment]
23
+
15
24
  from ..logging import LoggerMixin
16
25
  from ..utils.file_and_directory_handler import process_path
17
26
  from .column import Column
@@ -247,14 +256,62 @@ class Table(TemplateLoaderMixin, ReadInstancesMixin, LoggerMixin):
247
256
  Raises:
248
257
  TemplateNotFound: If the template file is not found.
249
258
  """
250
- templates = Path(__file__).parent / "templates"
251
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
269
+
270
+ env = Environment(loader=BaseLoader(), keep_trailing_newline=True)
271
+ template = env.from_string(template_content)
272
+
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
283
+
284
+ # Approach 3: Try relative to module location
285
+ if template is None:
286
+ try:
287
+ import cloe_nessy.models
288
+
289
+ module_path = Path(cloe_nessy.models.__file__).parent
290
+ templates = module_path / "templates"
291
+ template = self.get_template(templates, template_name)
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)
252
314
 
253
- try:
254
- template = self.get_template(templates, template_name)
255
- except TemplateNotFound as err:
256
- self._console_logger.error("Template [ {template_name} ] not found.")
257
- raise err
258
315
  render = template.render(table=self, replace=replace)
259
316
  return render
260
317
 
@@ -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 -%};
@@ -4,6 +4,16 @@ from typing import Any
4
4
  from jinja2 import TemplateNotFound
5
5
  from pydantic import BaseModel, field_validator
6
6
 
7
+ try:
8
+ from importlib.resources import files # type: ignore[attr-defined]
9
+ except ImportError:
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]
16
+
7
17
  from ..logging import LoggerMixin
8
18
  from .mixins.template_loader_mixin import TemplateLoaderMixin
9
19
 
@@ -64,13 +74,61 @@ class Volume(TemplateLoaderMixin, LoggerMixin, BaseModel):
64
74
  Returns:
65
75
  The rendered create statement as a string.
66
76
  """
67
- template_name: str = "create_volume.sql.j2"
68
- templates = Path(__file__).parent / "templates"
69
-
70
- try:
71
- template = self.get_template(templates, template_name)
72
- except TemplateNotFound as err:
73
- self._console_logger.error(f"Template [ {template_name} ] not found.")
74
- raise err
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
87
+
88
+ env = Environment(loader=BaseLoader(), keep_trailing_newline=True)
89
+ template = env.from_string(template_content)
90
+
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
101
+
102
+ # Approach 3: Try relative to module location
103
+ if template is None:
104
+ try:
105
+ import cloe_nessy.models
106
+
107
+ module_path = Path(cloe_nessy.models.__file__).parent
108
+ templates = module_path / "templates"
109
+ template = self.get_template(templates, template_name)
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)
132
+
75
133
  render = template.render(volume=self, if_not_exists=if_not_exists)
76
134
  return render
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloe-nessy
3
- Version: 0.3.10
3
+ Version: 0.3.11.2b0
4
4
  Summary: Your friendly datalake monster.
5
5
  Author-email: initions <ICSMC_EXT_PYPIORG@accenture.com>
6
6
  License: MIT
@@ -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=1N79hc79uJbNw5tHuoQAhLLS6y-9TFx5LIQT-C1X-wU,12075
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=51BE06FrL1Wv6zblFwJ_HTiR6WQqH7pSmrdH90rqwLg,2444
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.10.dist-info/METADATA,sha256=NBGGYODGPrVIhK3HBYkRSCUkd3tvBnU0AsYqB2j90Js,3162
96
- cloe_nessy-0.3.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
97
- cloe_nessy-0.3.10.dist-info/top_level.txt,sha256=Z7izn8HmQpg2wBUb-0jzaKlYKMU7Ypzuc9__9vPtW_I,11
98
- cloe_nessy-0.3.10.dist-info/RECORD,,
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,,