sqlmesh 0.181.1.dev6__py3-none-any.whl → 0.181.2.dev2__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/__init__.py CHANGED
@@ -172,6 +172,7 @@ def configure_logging(
172
172
  write_to_file: bool = True,
173
173
  log_limit: int = c.DEFAULT_LOG_LIMIT,
174
174
  log_file_dir: t.Optional[t.Union[str, Path]] = None,
175
+ ignore_warnings: bool = False,
175
176
  ) -> None:
176
177
  # Remove noisy grpc logs that are not useful for users
177
178
  os.environ["GRPC_VERBOSITY"] = os.environ.get("GRPC_VERBOSITY", "NONE")
@@ -186,7 +187,7 @@ def configure_logging(
186
187
  if write_to_stdout:
187
188
  stdout_handler = logging.StreamHandler(sys.stdout)
188
189
  stdout_handler.setFormatter(CustomFormatter())
189
- stdout_handler.setLevel(level)
190
+ stdout_handler.setLevel(logging.ERROR if ignore_warnings else level)
190
191
  logger.addHandler(stdout_handler)
191
192
 
192
193
  log_file_dir = log_file_dir or c.DEFAULT_LOG_FILE_DIR
sqlmesh/_version.py CHANGED
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.181.1.dev6'
21
- __version_tuple__ = version_tuple = (0, 181, 1, 'dev6')
20
+ __version__ = version = '0.181.2.dev2'
21
+ __version_tuple__ = version_tuple = (0, 181, 2, 'dev2')
sqlmesh/cli/main.py CHANGED
@@ -102,7 +102,13 @@ def cli(
102
102
 
103
103
  configs = load_configs(config, Context.CONFIG_TYPE, paths)
104
104
  log_limit = list(configs.values())[0].log_limit
105
- configure_logging(debug, log_to_stdout, log_limit=log_limit, log_file_dir=log_file_dir)
105
+ configure_logging(
106
+ debug,
107
+ log_to_stdout,
108
+ log_limit=log_limit,
109
+ log_file_dir=log_file_dir,
110
+ ignore_warnings=ignore_warnings,
111
+ )
106
112
  configure_console(ignore_warnings=ignore_warnings)
107
113
 
108
114
  try:
@@ -546,6 +552,19 @@ def janitor(ctx: click.Context, ignore_ttl: bool, **kwargs: t.Any) -> None:
546
552
  ctx.obj.run_janitor(ignore_ttl, **kwargs)
547
553
 
548
554
 
555
+ @cli.command("destroy")
556
+ @click.pass_context
557
+ @error_handler
558
+ @cli_analytics
559
+ def destroy(ctx: click.Context, **kwargs: t.Any) -> None:
560
+ """
561
+ The destroy command removes all project resources.
562
+
563
+ This includes engine-managed objects, state tables, the SQLMesh cache and any build artifacts.
564
+ """
565
+ ctx.obj.destroy(**kwargs)
566
+
567
+
549
568
  @cli.command("dag")
550
569
  @click.argument("file", required=True)
551
570
  @click.option(
sqlmesh/core/console.py CHANGED
@@ -181,6 +181,26 @@ class JanitorConsole(abc.ABC):
181
181
  """
182
182
 
183
183
 
184
+ class DestroyConsole(abc.ABC):
185
+ """Console for describing a destroy operation"""
186
+
187
+ @abc.abstractmethod
188
+ def start_destroy(self) -> bool:
189
+ """Start a destroy operation.
190
+
191
+ Returns:
192
+ Whether or not the destroy operation should proceed
193
+ """
194
+
195
+ @abc.abstractmethod
196
+ def stop_destroy(self, success: bool = True) -> None:
197
+ """Indicates the destroy operation has ended
198
+
199
+ Args:
200
+ success: Whether or not the cleanup completed successfully
201
+ """
202
+
203
+
184
204
  class EnvironmentsConsole(abc.ABC):
185
205
  """Console for displaying environments"""
186
206
 
@@ -304,6 +324,7 @@ class Console(
304
324
  StateExporterConsole,
305
325
  StateImporterConsole,
306
326
  JanitorConsole,
327
+ DestroyConsole,
307
328
  EnvironmentsConsole,
308
329
  DifferenceConsole,
309
330
  TableDiffConsole,
@@ -744,6 +765,12 @@ class NoopConsole(Console):
744
765
  ) -> None:
745
766
  pass
746
767
 
768
+ def start_destroy(self) -> bool:
769
+ return True
770
+
771
+ def stop_destroy(self, success: bool = True) -> None:
772
+ pass
773
+
747
774
 
748
775
  def make_progress_bar(
749
776
  message: str,
@@ -1092,6 +1119,25 @@ class TerminalConsole(Console):
1092
1119
  else:
1093
1120
  self.log_error("Cleanup failed!")
1094
1121
 
1122
+ def start_destroy(self) -> bool:
1123
+ self.log_warning(
1124
+ (
1125
+ "This will permanently delete all engine-managed objects, state tables and SQLMesh cache.\n"
1126
+ "The operation is irreversible and may disrupt any currently running or scheduled plans.\n"
1127
+ "Use this command only when you intend to fully reset the project."
1128
+ )
1129
+ )
1130
+ if not self._confirm("Proceed?"):
1131
+ self.log_error("Destroy aborted!")
1132
+ return False
1133
+ return True
1134
+
1135
+ def stop_destroy(self, success: bool = False) -> None:
1136
+ if success:
1137
+ self.log_success("Destroy completed successfully.")
1138
+ else:
1139
+ self.log_error("Destroy failed!")
1140
+
1095
1141
  def start_promotion_progress(
1096
1142
  self,
1097
1143
  snapshots: t.List[SnapshotTableInfo],
sqlmesh/core/context.py CHANGED
@@ -832,6 +832,19 @@ class GenericContext(BaseContext, t.Generic[C]):
832
832
 
833
833
  return success
834
834
 
835
+ @python_api_analytics
836
+ def destroy(self) -> bool:
837
+ success = False
838
+
839
+ if self.console.start_destroy():
840
+ try:
841
+ self._destroy()
842
+ success = True
843
+ finally:
844
+ self.console.stop_destroy(success=success)
845
+
846
+ return success
847
+
835
848
  @t.overload
836
849
  def get_model(
837
850
  self, model_or_snapshot: ModelOrSnapshot, raise_if_missing: Literal[True] = True
@@ -2537,6 +2550,22 @@ class GenericContext(BaseContext, t.Generic[C]):
2537
2550
  gateway_managed_virtual_layer=self.gateway_managed_virtual_layer,
2538
2551
  )
2539
2552
 
2553
+ def _destroy(self) -> None:
2554
+ # Invalidate all environments, including prod
2555
+ for environment in self.state_reader.get_environments():
2556
+ self.state_sync.invalidate_environment(name=environment.name, protect_prod=False)
2557
+ self.console.log_success(f"Environment '{environment.name}' invalidated.")
2558
+
2559
+ # Run janitor to clean up all objects
2560
+ self._run_janitor(ignore_ttl=True)
2561
+
2562
+ # Remove state tables, including backup tables
2563
+ self.state_sync.remove_state(including_backup=True)
2564
+ self.console.log_status_update("State tables removed.")
2565
+
2566
+ # Finally clear caches
2567
+ self.clear_caches()
2568
+
2540
2569
  def _run_janitor(self, ignore_ttl: bool = False) -> None:
2541
2570
  current_ts = now_timestamp()
2542
2571
 
@@ -347,13 +347,18 @@ class StateSync(StateReader, abc.ABC):
347
347
  """
348
348
 
349
349
  @abc.abstractmethod
350
- def invalidate_environment(self, name: str) -> None:
350
+ def invalidate_environment(self, name: str, protect_prod: bool = True) -> None:
351
351
  """Invalidates the target environment by setting its expiration timestamp to now.
352
352
 
353
353
  Args:
354
354
  name: The name of the environment to invalidate.
355
+ protect_prod: If True, prevents invalidation of the production environment.
355
356
  """
356
357
 
358
+ @abc.abstractmethod
359
+ def remove_state(self, including_backup: bool = False) -> None:
360
+ """Removes the state store objects."""
361
+
357
362
  @abc.abstractmethod
358
363
  def remove_intervals(
359
364
  self,
@@ -108,14 +108,15 @@ class EnvironmentState:
108
108
  columns_to_types=self._environment_statements_columns_to_types,
109
109
  )
110
110
 
111
- def invalidate_environment(self, name: str) -> None:
111
+ def invalidate_environment(self, name: str, protect_prod: bool = True) -> None:
112
112
  """Invalidates the environment.
113
113
 
114
114
  Args:
115
115
  name: The name of the environment
116
+ protect_prod: If True, prevents invalidation of the production environment.
116
117
  """
117
118
  name = name.lower()
118
- if name == c.PROD:
119
+ if protect_prod and name == c.PROD:
119
120
  raise SQLMeshError("Cannot invalidate the production environment.")
120
121
 
121
122
  filter_expr = exp.column("name").eq(name)
@@ -59,7 +59,7 @@ from sqlmesh.core.state_sync.db.interval import IntervalState
59
59
  from sqlmesh.core.state_sync.db.environment import EnvironmentState
60
60
  from sqlmesh.core.state_sync.db.snapshot import SnapshotState
61
61
  from sqlmesh.core.state_sync.db.version import VersionState
62
- from sqlmesh.core.state_sync.db.migrator import StateMigrator
62
+ from sqlmesh.core.state_sync.db.migrator import StateMigrator, _backup_table_name
63
63
  from sqlmesh.utils.date import TimeLike, to_timestamp, time_like_to_str, now_timestamp
64
64
  from sqlmesh.utils.errors import ConflictingPlanError, SQLMeshError
65
65
 
@@ -270,8 +270,8 @@ class EngineAdapterStateSync(StateSync):
270
270
  ) -> None:
271
271
  self.snapshot_state.unpause_snapshots(snapshots, unpaused_dt, self.interval_state)
272
272
 
273
- def invalidate_environment(self, name: str) -> None:
274
- self.environment_state.invalidate_environment(name)
273
+ def invalidate_environment(self, name: str, protect_prod: bool = True) -> None:
274
+ self.environment_state.invalidate_environment(name, protect_prod)
275
275
 
276
276
  def get_expired_snapshots(
277
277
  self, current_ts: int, ignore_ttl: bool = False
@@ -313,18 +313,26 @@ class EngineAdapterStateSync(StateSync):
313
313
  def nodes_exist(self, names: t.Iterable[str], exclude_external: bool = False) -> t.Set[str]:
314
314
  return self.snapshot_state.nodes_exist(names, exclude_external)
315
315
 
316
- def reset(self, default_catalog: t.Optional[str]) -> None:
317
- """Resets the state store to the state when it was first initialized."""
316
+ def remove_state(self, including_backup: bool = False) -> None:
317
+ """Removes the state store objects."""
318
318
  for table in (
319
319
  self.snapshot_state.snapshots_table,
320
320
  self.snapshot_state.auto_restatements_table,
321
321
  self.environment_state.environments_table,
322
+ self.environment_state.environment_statements_table,
322
323
  self.interval_state.intervals_table,
323
324
  self.plan_dags_table,
324
325
  self.version_state.versions_table,
325
326
  ):
326
327
  self.engine_adapter.drop_table(table)
328
+ if including_backup:
329
+ self.engine_adapter.drop_table(_backup_table_name(table))
330
+
327
331
  self.snapshot_state.clear_cache()
332
+
333
+ def reset(self, default_catalog: t.Optional[str]) -> None:
334
+ """Resets the state store to the state when it was first initialized."""
335
+ self.remove_state()
328
336
  self.migrate(default_catalog)
329
337
 
330
338
  @transactional()
sqlmesh/magics.py CHANGED
@@ -134,7 +134,12 @@ class SQLMeshMagics(Magics):
134
134
  args = parse_argstring(self.context, line)
135
135
  configs = load_configs(args.config, Context.CONFIG_TYPE, args.paths)
136
136
  log_limit = list(configs.values())[0].log_limit
137
- configure_logging(args.debug, log_limit=log_limit, log_file_dir=args.log_file_dir)
137
+ configure_logging(
138
+ args.debug,
139
+ log_limit=log_limit,
140
+ log_file_dir=args.log_file_dir,
141
+ ignore_warnings=args.ignore_warnings,
142
+ )
138
143
  configure_console(ignore_warnings=args.ignore_warnings)
139
144
  try:
140
145
  context = Context(paths=args.paths, config=configs, gateway=args.gateway)
@@ -1111,6 +1116,13 @@ class SQLMeshMagics(Magics):
1111
1116
  args = parse_argstring(self.lint, line)
1112
1117
  context.lint_models(args.models)
1113
1118
 
1119
+ @magic_arguments()
1120
+ @line_magic
1121
+ @pass_sqlmesh_context
1122
+ def destroy(self, context: Context, line: str) -> None:
1123
+ """Removes all project resources, engine-managed objects, state tables and clears the SQLMesh cache."""
1124
+ context.destroy()
1125
+
1114
1126
 
1115
1127
  def register_magics() -> None:
1116
1128
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlmesh
3
- Version: 0.181.1.dev6
3
+ Version: 0.181.2.dev2
4
4
  Summary: Next-generation data transformation framework
5
5
  Author-email: "TobikoData Inc." <engineering@tobikodata.com>
6
6
  License: Apache License
@@ -1,19 +1,19 @@
1
- sqlmesh/__init__.py,sha256=uPXld_xTZ2NTruSfVJ_vR_w-uAxR3T-gMXAb-EphTe8,7167
2
- sqlmesh/_version.py,sha256=zmY3aLooNCgnDxJu644T70Z5_ZM5X7cu7fBIpp1Ppzw,528
3
- sqlmesh/magics.py,sha256=7BU9ec9zE4tjvZ3hdEqwFX2VVV-CI0h06TGZo_Ssi8M,39070
1
+ sqlmesh/__init__.py,sha256=DRovDXI-9D9xeYDP7t8Fq7mI31S2btlN-LHPOK3y7PA,7240
2
+ sqlmesh/_version.py,sha256=UTbksF6FJCdg25HnFVlHkCpBV5LKcoc82FJhyR3Jh4E,528
3
+ sqlmesh/magics.py,sha256=9oY1Uz8uwsuTtPRg9HTYDxnGiJ7-OVRCpmCgAhbKHUU,39431
4
4
  sqlmesh/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  sqlmesh/cicd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  sqlmesh/cicd/bot.py,sha256=2zlbn-DXkqQzr3lA0__IGU4XaIfXBXBKLWXNI2DRJX8,759
7
7
  sqlmesh/cicd/config.py,sha256=mpgkisSBBovlNrNZir2unT8Wes6b38RW2UsU_o4e8vY,109
8
8
  sqlmesh/cli/__init__.py,sha256=MAXAyO7isbyM-PaSdFjkJNcjn32WjOl0XzxT5gvp_vo,1690
9
9
  sqlmesh/cli/example_project.py,sha256=QAFQbw_kzqn30GLTthqsuWXbFDBpX8W6RsCgQ-jx65M,9308
10
- sqlmesh/cli/main.py,sha256=foSIAx3hyhCWLIG7XQuBE-zH7lNqSvazkgpydtJados,31564
10
+ sqlmesh/cli/main.py,sha256=z1Af0bwqtnYHzkY0_9REpaJe-onxvXN4rLw6upyxKec,31979
11
11
  sqlmesh/cli/options.py,sha256=aC_L5WnMScKzMU55BD1Y-8R-QzqCkPSYrlCI-payHRA,1333
12
12
  sqlmesh/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  sqlmesh/core/_typing.py,sha256=e1f7xO2aZCy38M_3VoDy-XI3shyd99-IFctgIFSgXWM,497
14
- sqlmesh/core/console.py,sha256=4uwhySxa3n5mkydmslt2Os3s06W4TnRbRk8IJYbQ4yU,148010
14
+ sqlmesh/core/console.py,sha256=qPMcYwr4ktv8BJe7-2vYI3N5534mdviihK4p9YipuMQ,149415
15
15
  sqlmesh/core/constants.py,sha256=oqt6zjepUhQoWlgapKn_HpG7Pu9mrFwepdX5caNfJUI,2499
16
- sqlmesh/core/context.py,sha256=CPrmMHceymyDjjgKfkszwWxAkjTUqO90TbGfozkZJWw,113720
16
+ sqlmesh/core/context.py,sha256=kLKXwOLc_5Orv-SxvI0zbpL9ZJ0XkB9HZgd9R6uh-9Y,114691
17
17
  sqlmesh/core/context_diff.py,sha256=s9toP17d4tJfOpFH91LcjGK2CM64PVuB0MPkeFgF4hQ,20415
18
18
  sqlmesh/core/dialect.py,sha256=fPTV517IOS0nWMxYznNNQnXkQkFFrPOSKe8ghsQ0o8A,49759
19
19
  sqlmesh/core/environment.py,sha256=0TTQf4C4LXwf37fm-dfYv1qyG7vtZfQI5rizgm5g0j0,11442
@@ -102,13 +102,13 @@ sqlmesh/core/snapshot/categorizer.py,sha256=qGG5870mu1jR2whKisSBH_GFbsyh96RnzJDg
102
102
  sqlmesh/core/snapshot/definition.py,sha256=PKzBLiQ1yIycGbmslEoQyJEwtfnJHsQuY_sl1xkBcvk,84081
103
103
  sqlmesh/core/snapshot/evaluator.py,sha256=NZVgQoaSH-D7Q7PAHTRzQ5O2pdra3MUToLi9p8qAyVg,89265
104
104
  sqlmesh/core/state_sync/__init__.py,sha256=B60xj-_Xk-4jas3UphLvwkuf04G-9AyGckcblXE0aRg,869
105
- sqlmesh/core/state_sync/base.py,sha256=1gQzl8GCf0yYVfAtGYnNF86lU6rW1MAXB6Lcctd2mBs,18186
105
+ sqlmesh/core/state_sync/base.py,sha256=M3EsZ_HyV_6aCKucwdmZPWV9QFNvHm5mCCgSaQ-mE7c,18441
106
106
  sqlmesh/core/state_sync/cache.py,sha256=xKLPOrPiQeRDPMkUtSlZaMMVlUnnK2ytxGE2rilHRBY,5446
107
107
  sqlmesh/core/state_sync/common.py,sha256=THK-6AGHFBAuLXydD8QhzmzCdyl0BMrz2rB2xpmC99Y,6532
108
108
  sqlmesh/core/state_sync/export_import.py,sha256=WJ7sFX2b_RPAFE4yspJRi_4JQnaO23xpJgRxwXD0agA,8709
109
109
  sqlmesh/core/state_sync/db/__init__.py,sha256=jGCqKYB7npq4eh6H2LyfBAJWdOP-IFu0DC4CMiQgYvw,107
110
- sqlmesh/core/state_sync/db/environment.py,sha256=7HVRkRugHsGgyHZuSMil6NyTtx7B02QQN-AE18GSJWM,13382
111
- sqlmesh/core/state_sync/db/facade.py,sha256=2HcuQt8PrHXHbv3VqvzHhXHDW6_aRwTfY8oX_ntGsAs,25045
110
+ sqlmesh/core/state_sync/db/environment.py,sha256=pwc2eRxZnIiTM8ZTHSfiOslO4FqFz9ch91J3VK6U1b8,13514
111
+ sqlmesh/core/state_sync/db/facade.py,sha256=F3B6M1x3rM9XNq6L4UvpXKOf-uZUGgRPlJdIp_-mrWo,25423
112
112
  sqlmesh/core/state_sync/db/interval.py,sha256=QgdqoVyLYw15SnX8O6icHUF3ZHnI6a9rX0505-FgFNg,17964
113
113
  sqlmesh/core/state_sync/db/migrator.py,sha256=2LNUwOBNFkA1ntp-Z93S_OWxFQhOBj3ZD_ZqPCyPEAE,18139
114
114
  sqlmesh/core/state_sync/db/snapshot.py,sha256=04b2lan3KamXuX3bdnhOiaoQpXgwRFMjW08tgWIL0Qk,29596
@@ -265,7 +265,7 @@ sqlmesh/utils/pandas.py,sha256=j_tYhuPcWpzuPceZZ6IhdTVbmxYyGJW7l4FHr4bQqjM,1824
265
265
  sqlmesh/utils/pydantic.py,sha256=ioaAzYF42PutEJRyAS11-AHguiCG3yWI6VRcTVa2G-g,10470
266
266
  sqlmesh/utils/rich.py,sha256=xNZyPCqEc4TAlJlsEthg-5eYUWpaizz0QjBzO7a1Yv4,1509
267
267
  sqlmesh/utils/yaml.py,sha256=np-WVcwmwsKghCgAj1OBBMsK1SXSRn4wR-H37cGiFr8,2282
268
- sqlmesh-0.181.1.dev6.dist-info/licenses/LICENSE,sha256=OlMefUjgWJdULtf84BLW0AZZcY8DwdgQqb_1j2862j8,11346
268
+ sqlmesh-0.181.2.dev2.dist-info/licenses/LICENSE,sha256=OlMefUjgWJdULtf84BLW0AZZcY8DwdgQqb_1j2862j8,11346
269
269
  web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
270
270
  web/client/dist/index.html,sha256=cQRIlDgkl6OgeWuHI9hM8bJhKUE9-Ji2NpQa2hlgNM8,5472
271
271
  web/client/dist/assets/Audits-4U9LnWyN.js,sha256=reXu-sKJ76kiaAZIGkCPvgO68Km9tj1PN_9mx6X6WAY,997
@@ -382,8 +382,8 @@ web/server/api/endpoints/models.py,sha256=SzS5bshzdXyM6hb948sZ_3k-xhpGCHkxkb7pHz
382
382
  web/server/api/endpoints/modules.py,sha256=8hqqgonGay_mJmpCw0IdbjsPhWlQH2VLdKAqha-myac,468
383
383
  web/server/api/endpoints/plan.py,sha256=OYuQ_4dgbhG9ibTcX1a8mvYgH3ANxw9Fhbb4wg6QWqc,9222
384
384
  web/server/api/endpoints/table_diff.py,sha256=Wd5YxeKbZB7AkrDvqFgvV9ZQlnKYOF1n5W_w2EHE_Zw,2085
385
- sqlmesh-0.181.1.dev6.dist-info/METADATA,sha256=SrOE2G6P-ZgEf-Ak05RGlhzM4GLRUJRt3CWqnt87wuE,25307
386
- sqlmesh-0.181.1.dev6.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
387
- sqlmesh-0.181.1.dev6.dist-info/entry_points.txt,sha256=pIYKtg-u-uO7BK_Y0qrdmfyj0bYrcMc3Xiqr5WE3VFk,121
388
- sqlmesh-0.181.1.dev6.dist-info/top_level.txt,sha256=bspjo5vjELQkuN0qKuTFIbsrUt3Zeo8D2mlKeHG1LdE,12
389
- sqlmesh-0.181.1.dev6.dist-info/RECORD,,
385
+ sqlmesh-0.181.2.dev2.dist-info/METADATA,sha256=Bn9XxP3OdiKwnsN8Vz7gSJc2oSTWiyYU9hVKWm0c5Cs,25307
386
+ sqlmesh-0.181.2.dev2.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
387
+ sqlmesh-0.181.2.dev2.dist-info/entry_points.txt,sha256=pIYKtg-u-uO7BK_Y0qrdmfyj0bYrcMc3Xiqr5WE3VFk,121
388
+ sqlmesh-0.181.2.dev2.dist-info/top_level.txt,sha256=bspjo5vjELQkuN0qKuTFIbsrUt3Zeo8D2mlKeHG1LdE,12
389
+ sqlmesh-0.181.2.dev2.dist-info/RECORD,,