sqlmesh 0.225.1.dev15__py3-none-any.whl → 0.225.1.dev17__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.
sqlmesh/_version.py CHANGED
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '0.225.1.dev15'
32
- __version_tuple__ = version_tuple = (0, 225, 1, 'dev15')
31
+ __version__ = version = '0.225.1.dev17'
32
+ __version_tuple__ = version_tuple = (0, 225, 1, 'dev17')
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -178,6 +178,7 @@ def load_config_from_paths(
178
178
 
179
179
  dbt_python_config = sqlmesh_config(
180
180
  project_root=dbt_project_file.parent,
181
+ profiles_dir=kwargs.pop("profiles_dir", None),
181
182
  dbt_profile_name=kwargs.pop("profile", None),
182
183
  dbt_target_name=kwargs.pop("target", None),
183
184
  variables=variables,
sqlmesh/dbt/column.py CHANGED
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import typing as t
4
+ import logging
4
5
 
5
6
  from sqlglot import exp, parse_one
6
7
  from sqlglot.helper import ensure_list
@@ -9,6 +10,8 @@ from sqlmesh.dbt.common import GeneralConfig
9
10
  from sqlmesh.utils.conversions import ensure_bool
10
11
  from sqlmesh.utils.pydantic import field_validator
11
12
 
13
+ logger = logging.getLogger(__name__)
14
+
12
15
 
13
16
  def yaml_to_columns(
14
17
  yaml: t.Dict[str, ColumnConfig] | t.List[t.Dict[str, ColumnConfig]],
@@ -31,11 +34,20 @@ def column_types_to_sqlmesh(
31
34
  Returns:
32
35
  A dict of column name to exp.DataType
33
36
  """
34
- return {
35
- name: parse_one(column.data_type, into=exp.DataType, dialect=dialect or "")
36
- for name, column in columns.items()
37
- if column.enabled and column.data_type
38
- }
37
+ col_types_to_sqlmesh: t.Dict[str, exp.DataType] = {}
38
+ for name, column in columns.items():
39
+ if column.enabled and column.data_type:
40
+ column_def = parse_one(
41
+ f"{name} {column.data_type}", into=exp.ColumnDef, dialect=dialect or ""
42
+ )
43
+ if column_def.args.get("constraints"):
44
+ logger.warning(
45
+ f"Ignoring unsupported constraints for column '{name}' with definition '{column.data_type}'. Please refer to github.com/TobikoData/sqlmesh/issues/4717 for more information."
46
+ )
47
+ kind = column_def.kind
48
+ if kind:
49
+ col_types_to_sqlmesh[name] = kind
50
+ return col_types_to_sqlmesh
39
51
 
40
52
 
41
53
  def column_descriptions_to_sqlmesh(columns: t.Dict[str, ColumnConfig]) -> t.Dict[str, str]:
sqlmesh/dbt/context.py CHANGED
@@ -37,6 +37,8 @@ class DbtContext:
37
37
  """Context for DBT environment"""
38
38
 
39
39
  project_root: Path = Path()
40
+ profiles_dir: t.Optional[Path] = None
41
+ """Optional override to specify the directory where profiles.yml is located, if not at the :project_root"""
40
42
  target_name: t.Optional[str] = None
41
43
  profile_name: t.Optional[str] = None
42
44
  project_schema: t.Optional[str] = None
sqlmesh/dbt/loader.py CHANGED
@@ -53,10 +53,18 @@ def sqlmesh_config(
53
53
  threads: t.Optional[int] = None,
54
54
  register_comments: t.Optional[bool] = None,
55
55
  infer_state_schema_name: bool = False,
56
+ profiles_dir: t.Optional[Path] = None,
56
57
  **kwargs: t.Any,
57
58
  ) -> Config:
58
59
  project_root = project_root or Path()
59
- context = DbtContext(project_root=project_root, profile_name=dbt_profile_name)
60
+ context = DbtContext(
61
+ project_root=project_root, profiles_dir=profiles_dir, profile_name=dbt_profile_name
62
+ )
63
+
64
+ # note: Profile.load() is called twice with different DbtContext's:
65
+ # - once here with the above DbtContext (to determine connnection / gateway config which has to be set up before everything else)
66
+ # - again on the SQLMesh side via GenericContext.load() -> DbtLoader._load_projects() -> Project.load() which constructs a fresh DbtContext and ignores the above one
67
+ # it's important to ensure that the DbtContext created within the DbtLoader uses the same project root / profiles dir that we use here
60
68
  profile = Profile.load(context, target_name=dbt_target_name)
61
69
  model_defaults = kwargs.pop("model_defaults", ModelDefaultsConfig())
62
70
  if model_defaults.dialect is None:
@@ -98,6 +106,7 @@ def sqlmesh_config(
98
106
 
99
107
  return Config(
100
108
  loader=loader,
109
+ loader_kwargs=dict(profiles_dir=profiles_dir),
101
110
  model_defaults=model_defaults,
102
111
  variables=variables or {},
103
112
  dbt=RootDbtConfig(infer_state_schema_name=infer_state_schema_name),
@@ -116,9 +125,12 @@ def sqlmesh_config(
116
125
 
117
126
 
118
127
  class DbtLoader(Loader):
119
- def __init__(self, context: GenericContext, path: Path) -> None:
128
+ def __init__(
129
+ self, context: GenericContext, path: Path, profiles_dir: t.Optional[Path] = None
130
+ ) -> None:
120
131
  self._projects: t.List[Project] = []
121
132
  self._macros_max_mtime: t.Optional[float] = None
133
+ self._profiles_dir = profiles_dir
122
134
  super().__init__(context, path)
123
135
 
124
136
  def load(self) -> LoadedProject:
@@ -225,6 +237,7 @@ class DbtLoader(Loader):
225
237
  project = Project.load(
226
238
  DbtContext(
227
239
  project_root=self.config_path,
240
+ profiles_dir=self._profiles_dir,
228
241
  target_name=target_name,
229
242
  sqlmesh_config=self.config,
230
243
  ),
sqlmesh/dbt/profile.py CHANGED
@@ -60,7 +60,7 @@ class Profile:
60
60
  if not context.profile_name:
61
61
  raise ConfigError(f"{project_file.stem} must include project name.")
62
62
 
63
- profile_filepath = cls._find_profile(context.project_root)
63
+ profile_filepath = cls._find_profile(context.project_root, context.profiles_dir)
64
64
  if not profile_filepath:
65
65
  raise ConfigError(f"{cls.PROFILE_FILE} not found.")
66
66
 
@@ -68,8 +68,8 @@ class Profile:
68
68
  return Profile(profile_filepath, target_name, target)
69
69
 
70
70
  @classmethod
71
- def _find_profile(cls, project_root: Path) -> t.Optional[Path]:
72
- dir = os.environ.get("DBT_PROFILES_DIR", "")
71
+ def _find_profile(cls, project_root: Path, profiles_dir: t.Optional[Path]) -> t.Optional[Path]:
72
+ dir = os.environ.get("DBT_PROFILES_DIR", profiles_dir or "")
73
73
  path = Path(project_root, dir, cls.PROFILE_FILE)
74
74
  if path.exists():
75
75
  return path
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlmesh
3
- Version: 0.225.1.dev15
3
+ Version: 0.225.1.dev17
4
4
  Summary: Next-generation data transformation framework
5
5
  Author-email: "TobikoData Inc." <engineering@tobikodata.com>
6
6
  License: Apache License
@@ -235,7 +235,7 @@ Requires-Dist: python-dotenv
235
235
  Requires-Dist: requests
236
236
  Requires-Dist: rich[jupyter]
237
237
  Requires-Dist: ruamel.yaml
238
- Requires-Dist: sqlglot[rs]~=27.24.2
238
+ Requires-Dist: sqlglot[rs]~=27.27.0
239
239
  Requires-Dist: tenacity
240
240
  Requires-Dist: time-machine
241
241
  Requires-Dist: json-stream
@@ -1,5 +1,5 @@
1
1
  sqlmesh/__init__.py,sha256=v_spqQEhcnGaahp1yPvMqUIa6mhH3cs3Bc1CznxvCEA,7965
2
- sqlmesh/_version.py,sha256=XJ_E-an9zSgcdG4frk9FvpyPMKbjrN_5k6vGmWAkTng,723
2
+ sqlmesh/_version.py,sha256=0vDUvywH_ZkmJlZuCZc7Q299r7zD869DTT8Mio64uNY,723
3
3
  sqlmesh/magics.py,sha256=xLh3u4eqpVrKRVN5KF3X84RPRqjygAB9AJP1TXwH8hg,42086
4
4
  sqlmesh/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  sqlmesh/cicd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -48,7 +48,7 @@ sqlmesh/core/config/format.py,sha256=6CXFbvnor56xbldKE-Vrm9k_ABRoY4v6vgIb3mCihiQ
48
48
  sqlmesh/core/config/gateway.py,sha256=tYngyqwd_4Qr9lhcv2hlvLvb_2pgYYtKu6hdGsTr-4I,1931
49
49
  sqlmesh/core/config/janitor.py,sha256=jxZWSNZMhNjJR9lWI00rDe2nr_5AOxkKE52Fo5nbq_U,901
50
50
  sqlmesh/core/config/linter.py,sha256=4Fh6UgY5FrRD9tk_R41Y-M_r91Wh7EQW3Pc1IdRN9Cg,1287
51
- sqlmesh/core/config/loader.py,sha256=h8yfsq0YAmamAW-YGysVuluvLL-YAFvmJ5VcIceFq3U,10104
51
+ sqlmesh/core/config/loader.py,sha256=p26Ux_-ekgXtOHuqSMObDGfnAfb8Ou3Rug95mZ_uiOg,10167
52
52
  sqlmesh/core/config/migration.py,sha256=3lZIlmIcQH3_hIEm3Y3jFtvpw0YXzRzAnk4OdiklO6M,408
53
53
  sqlmesh/core/config/model.py,sha256=NgqyIq7J5DCGhIo9I_htiWjTycydVRlchG5McZuHSd0,4627
54
54
  sqlmesh/core/config/naming.py,sha256=KVGaxUgswoQajXR_cHFJvgkmEFcU1V182GkOH1SJxuE,326
@@ -131,14 +131,14 @@ sqlmesh/dbt/__init__.py,sha256=KUv-lW5sG9D2ceXAIzA4MLcjyhzq3E-7qJP4P_PH2EU,144
131
131
  sqlmesh/dbt/adapter.py,sha256=z-tFIj3rpVvdBr3y8l40FU531-TQ5H2ctLmjwzMBxwk,21321
132
132
  sqlmesh/dbt/basemodel.py,sha256=oUr_Em-TjQbpYZS5gtvMA65JRTdnZM46NO9MWvLBLzQ,14860
133
133
  sqlmesh/dbt/builtin.py,sha256=c7spvtMFMR6hfLkuZj9uqBQ093R_hYRv9b4jd9k26QI,19792
134
- sqlmesh/dbt/column.py,sha256=Kvj_N3D_QegcoNQG7VqRiqy-FRfupud-6ilhlykBOgE,1873
134
+ sqlmesh/dbt/column.py,sha256=T5xEWNf0n1sZ3REWnc5D9RsXt5VrrZ1YlMWZUUuAUxo,2449
135
135
  sqlmesh/dbt/common.py,sha256=AezWUEoGDISQj9eOo1Z5kLsXz3oRFb0LikTMEaAX3J8,8593
136
- sqlmesh/dbt/context.py,sha256=Ofhto7_TFvbRfUnRNJpeZBy8ELDi7LX5hPQko7SdlN0,10920
137
- sqlmesh/dbt/loader.py,sha256=XpPCoHJkcAuXfeIhKmTrJsaGQSHbrk4twCptPQGbsWI,18466
136
+ sqlmesh/dbt/context.py,sha256=JDfSkVBBV2Xi4nDOwWipVHJRll3ioEmvh7gBglPVvqM,11074
137
+ sqlmesh/dbt/loader.py,sha256=ZTpPFnXuf4hQ8Z7Z6oMzxqN2wMMxsQqhm2x-8a5R1AA,19269
138
138
  sqlmesh/dbt/manifest.py,sha256=aea8FaSnMbnjF1JfJx0hDRvg-cEwLCkS207dlf_NCvg,34613
139
139
  sqlmesh/dbt/model.py,sha256=uFeNj-bL68fQjj6L2fRAv00UQMZTJSTlrJNRrfvETKk,35117
140
140
  sqlmesh/dbt/package.py,sha256=8MOq_kHP2qjj24bpoC3GPnHlOVLYO4V9oVb9krk1Mdk,4759
141
- sqlmesh/dbt/profile.py,sha256=hAqL8lfT98pSBY-wCInPg2WhFEjCNUGF2bx5UcWFx-4,3939
141
+ sqlmesh/dbt/profile.py,sha256=ilDiSqBqw6lsJLUu4MfJSrIkvtC3fbxlvawKn44lHjc,4009
142
142
  sqlmesh/dbt/project.py,sha256=Dxf9JakvvQofhcRa2bSi5tFCU4eHMlyRt_Dd7vwOWQM,4712
143
143
  sqlmesh/dbt/relation.py,sha256=8QhnW_mQ6bjhKNZwTI1p9SLdMBCcAxvHfo0Qs97Mw6w,228
144
144
  sqlmesh/dbt/seed.py,sha256=4X2SDKNaJv4r91S2kpwgJKhOL6GoEpb8d0gRchrCKo0,4494
@@ -238,12 +238,12 @@ sqlmesh/utils/pydantic.py,sha256=o_NsXbIpDqNpUA1Uc5xF0ZzoXQYYB0DfHwdRxBwXPNk,120
238
238
  sqlmesh/utils/rich.py,sha256=cwQ5nJ6sgz64xHtoh6_ec7ReV5YpsOGhMtUJnwoRfEI,3549
239
239
  sqlmesh/utils/windows.py,sha256=0F9RdpuuCoG5NiEDXvWlAGCiJ-59OjSAmgFF5wW05aY,1133
240
240
  sqlmesh/utils/yaml.py,sha256=KFBd7hsKNRTtRudGR7d410qUYffQv0EWRcDM8hVNNZg,3025
241
- sqlmesh-0.225.1.dev15.dist-info/licenses/LICENSE,sha256=OlMefUjgWJdULtf84BLW0AZZcY8DwdgQqb_1j2862j8,11346
241
+ sqlmesh-0.225.1.dev17.dist-info/licenses/LICENSE,sha256=OlMefUjgWJdULtf84BLW0AZZcY8DwdgQqb_1j2862j8,11346
242
242
  sqlmesh_dbt/__init__.py,sha256=awYS5y5mz-1NUmx6i5h5NSTJ7tidRl9NC0FAnFWSF6U,350
243
- sqlmesh_dbt/cli.py,sha256=eAeOZtHOikSDEZNI6hnZYJ-pja6ijFldRV4PeSzwYwU,5744
243
+ sqlmesh_dbt/cli.py,sha256=p9foHjAW9ni7BTOJ2loynk47M0Sf43QIJZRggOzF5tc,6351
244
244
  sqlmesh_dbt/console.py,sha256=RwWLYnEZHzn9Xp-e2gbZvkdKbWbBLN146geI84mJitg,1132
245
245
  sqlmesh_dbt/error.py,sha256=1sPNU6Dik30DR9WTCvGp3ED-pzNmAA3LhP95BXb3ndI,1146
246
- sqlmesh_dbt/operations.py,sha256=QiCsz5NtD9XScc3t2ASjtnkyVg0tjiyWkIjp21d5MG4,14196
246
+ sqlmesh_dbt/operations.py,sha256=-9yM-czQpaA-U42kad5a5OJXIAh63FiIBtuP_672AF0,14331
247
247
  sqlmesh_dbt/options.py,sha256=noB_qK4uGGi7Erqk1XkkMaFz5aUc6lp44wwn1Nv_LI4,737
248
248
  sqlmesh_dbt/selectors.py,sha256=nmVrFsC7CR2A24FdGTp5Wz7MuWreI-xLQTpOTy0H9K4,6543
249
249
  web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -363,8 +363,8 @@ web/server/api/endpoints/models.py,sha256=kwj0s7uve3iZSMfmjkoPVMFMeY1sD0peTeyrWf
363
363
  web/server/api/endpoints/modules.py,sha256=8hqqgonGay_mJmpCw0IdbjsPhWlQH2VLdKAqha-myac,468
364
364
  web/server/api/endpoints/plan.py,sha256=bbbY50W_2MsZSTxOHWMKz0tbIm75nsRSlPy8GI2fg9Q,9306
365
365
  web/server/api/endpoints/table_diff.py,sha256=8XTwgOh6QBbNy_hTM1JuHgRjbnie-pGPrphiW-FNLjQ,6058
366
- sqlmesh-0.225.1.dev15.dist-info/METADATA,sha256=2bhN5fdwuRPD3RyRmeqx11wNE-FtRYripkZfJeKoRdI,26686
367
- sqlmesh-0.225.1.dev15.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
368
- sqlmesh-0.225.1.dev15.dist-info/entry_points.txt,sha256=sHAf6tQczIM8xZoduN4qaUjV7QEPVUUW_LCT8EDUMv4,155
369
- sqlmesh-0.225.1.dev15.dist-info/top_level.txt,sha256=RQ-33FPe2IgL0rgossAfJkCRtqslz9b7wFARqiWLC5Q,24
370
- sqlmesh-0.225.1.dev15.dist-info/RECORD,,
366
+ sqlmesh-0.225.1.dev17.dist-info/METADATA,sha256=3Z-gHxpytLz_svwdo2EkWmyBvt1IhiXS6GYcVleOS74,26686
367
+ sqlmesh-0.225.1.dev17.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
368
+ sqlmesh-0.225.1.dev17.dist-info/entry_points.txt,sha256=sHAf6tQczIM8xZoduN4qaUjV7QEPVUUW_LCT8EDUMv4,155
369
+ sqlmesh-0.225.1.dev17.dist-info/top_level.txt,sha256=RQ-33FPe2IgL0rgossAfJkCRtqslz9b7wFARqiWLC5Q,24
370
+ sqlmesh-0.225.1.dev17.dist-info/RECORD,,
sqlmesh_dbt/cli.py CHANGED
@@ -84,6 +84,16 @@ resource_type_option = click.option(
84
84
  type=click.Choice(["debug", "info", "warn", "error", "none"]),
85
85
  help="Specify the minimum severity of events that are logged to the console and the log file.",
86
86
  )
87
+ @click.option(
88
+ "--profiles-dir",
89
+ type=click.Path(exists=True, file_okay=False, path_type=Path),
90
+ help="Which directory to look in for the profiles.yml file. If not set, dbt will look in the current working directory first, then HOME/.dbt/",
91
+ )
92
+ @click.option(
93
+ "--project-dir",
94
+ type=click.Path(exists=True, file_okay=False, path_type=Path),
95
+ help="Which directory to look in for the dbt_project.yml file. Default is the current working directory and its parents.",
96
+ )
87
97
  @click.pass_context
88
98
  @cli_global_error_handler
89
99
  def dbt(
@@ -92,6 +102,8 @@ def dbt(
92
102
  target: t.Optional[str] = None,
93
103
  debug: bool = False,
94
104
  log_level: t.Optional[str] = None,
105
+ profiles_dir: t.Optional[Path] = None,
106
+ project_dir: t.Optional[Path] = None,
95
107
  ) -> None:
96
108
  """
97
109
  An ELT tool for managing your SQL transformations and data models, powered by the SQLMesh engine.
@@ -105,7 +117,8 @@ def dbt(
105
117
  # that need to be known before we attempt to load the project
106
118
  ctx.obj = functools.partial(
107
119
  create,
108
- project_dir=Path.cwd(),
120
+ project_dir=project_dir,
121
+ profiles_dir=profiles_dir,
109
122
  profile=profile,
110
123
  target=target,
111
124
  debug=debug,
sqlmesh_dbt/operations.py CHANGED
@@ -232,6 +232,7 @@ class DbtOperations:
232
232
 
233
233
  def create(
234
234
  project_dir: t.Optional[Path] = None,
235
+ profiles_dir: t.Optional[Path] = None,
235
236
  profile: t.Optional[str] = None,
236
237
  target: t.Optional[str] = None,
237
238
  vars: t.Optional[t.Dict[str, t.Any]] = None,
@@ -268,7 +269,11 @@ def create(
268
269
  sqlmesh_context = Context(
269
270
  paths=[project_dir],
270
271
  config_loader_kwargs=dict(
271
- profile=profile, target=target, variables=vars, threads=threads
272
+ profile=profile,
273
+ target=target,
274
+ variables=vars,
275
+ threads=threads,
276
+ profiles_dir=profiles_dir,
272
277
  ),
273
278
  load=True,
274
279
  # DbtSelector selects based on dbt model fqn's rather than SQLMesh model names