sqlmesh 0.206.2.dev7__py3-none-any.whl → 0.206.2.dev8__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
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.206.2.dev7'
21
- __version_tuple__ = version_tuple = (0, 206, 2, 'dev7')
20
+ __version__ = version = '0.206.2.dev8'
21
+ __version_tuple__ = version_tuple = (0, 206, 2, 'dev8')
sqlmesh/core/console.py CHANGED
@@ -2163,13 +2163,12 @@ class TerminalConsole(Console):
2163
2163
  self._print("-" * divider_length)
2164
2164
  self._print("Test Failure Summary", style="red")
2165
2165
  self._print("=" * divider_length)
2166
- failures = len(result.failures) + len(result.errors)
2166
+ fail_and_error_tests = result.get_fail_and_error_tests()
2167
2167
  self._print(f"{message} \n")
2168
2168
 
2169
- self._print(f"Failed tests ({failures}):")
2170
- for test, _ in result.failures + result.errors:
2171
- if isinstance(test, ModelTest):
2172
- self._print(f" • {test.path}::{test.test_name}")
2169
+ self._print(f"Failed tests ({len(fail_and_error_tests)}):")
2170
+ for test in fail_and_error_tests:
2171
+ self._print(f" • {test.path}::{test.test_name}")
2173
2172
  self._print("=" * divider_length, end="\n\n")
2174
2173
 
2175
2174
  def _captured_unit_test_results(self, result: ModelTextTestResult) -> str:
@@ -2721,28 +2720,15 @@ class TerminalConsole(Console):
2721
2720
  Args:
2722
2721
  result: The unittest test result that contains metrics like num success, fails, ect.
2723
2722
  """
2724
-
2725
2723
  if result.wasSuccessful():
2726
2724
  self._print("\n", end="")
2727
2725
  return
2728
2726
 
2729
- errors = result.errors
2730
- failures = result.failures
2731
- skipped = result.skipped
2732
-
2733
- infos = []
2734
- if failures:
2735
- infos.append(f"failures={len(failures)}")
2736
- if errors:
2737
- infos.append(f"errors={len(errors)}")
2738
- if skipped:
2739
- infos.append(f"skipped={skipped}")
2740
-
2741
2727
  if unittest_char_separator:
2742
2728
  self._print(f"\n{unittest.TextTestResult.separator1}\n\n", end="")
2743
2729
 
2744
2730
  for (test_case, failure), test_failure_tables in zip_longest( # type: ignore
2745
- failures, result.failure_tables
2731
+ result.failures, result.failure_tables
2746
2732
  ):
2747
2733
  self._print(unittest.TextTestResult.separator2)
2748
2734
  self._print(f"FAIL: {test_case}")
@@ -2758,7 +2744,7 @@ class TerminalConsole(Console):
2758
2744
  self._print(failure_table)
2759
2745
  self._print("\n", end="")
2760
2746
 
2761
- for test_case, error in errors:
2747
+ for test_case, error in result.errors:
2762
2748
  self._print(unittest.TextTestResult.separator2)
2763
2749
  self._print(f"ERROR: {test_case}")
2764
2750
  self._print(f"{unittest.TextTestResult.separator2}")
@@ -3080,27 +3066,27 @@ class NotebookMagicConsole(TerminalConsole):
3080
3066
  fail_shared_style = {**shared_style, **fail_color}
3081
3067
  header = str(h("span", {"style": fail_shared_style}, "-" * divider_length))
3082
3068
  message = str(h("span", {"style": fail_shared_style}, "Test Failure Summary"))
3069
+ fail_and_error_tests = result.get_fail_and_error_tests()
3083
3070
  failed_tests = [
3084
3071
  str(
3085
3072
  h(
3086
3073
  "span",
3087
3074
  {"style": fail_shared_style},
3088
- f"Failed tests ({len(result.failures) + len(result.errors)}):",
3075
+ f"Failed tests ({len(fail_and_error_tests)}):",
3089
3076
  )
3090
3077
  )
3091
3078
  ]
3092
3079
 
3093
- for test, _ in result.failures + result.errors:
3094
- if isinstance(test, ModelTest):
3095
- failed_tests.append(
3096
- str(
3097
- h(
3098
- "span",
3099
- {"style": fail_shared_style},
3100
- f" • {test.model.name}::{test.test_name}",
3101
- )
3080
+ for test in fail_and_error_tests:
3081
+ failed_tests.append(
3082
+ str(
3083
+ h(
3084
+ "span",
3085
+ {"style": fail_shared_style},
3086
+ f" • {test.model.name}::{test.test_name}",
3102
3087
  )
3103
3088
  )
3089
+ )
3104
3090
  failures = "<br>".join(failed_tests)
3105
3091
  footer = str(h("span", {"style": fail_shared_style}, "=" * divider_length))
3106
3092
  error_output = widgets.Textarea(output, layout={"height": "300px", "width": "100%"})
@@ -3508,10 +3494,10 @@ class MarkdownConsole(CaptureTerminalConsole):
3508
3494
  self._log_test_details(result, unittest_char_separator=False)
3509
3495
  self._print("```\n\n")
3510
3496
 
3511
- failures = len(result.failures) + len(result.errors)
3497
+ fail_and_error_tests = result.get_fail_and_error_tests()
3512
3498
  self._print(f"**{message}**\n")
3513
- self._print(f"**Failed tests ({failures}):**")
3514
- for test, _ in result.failures + result.errors:
3499
+ self._print(f"**Failed tests ({len(fail_and_error_tests)}):**")
3500
+ for test in fail_and_error_tests:
3515
3501
  if isinstance(test, ModelTest):
3516
3502
  self._print(f" • `{test.model.name}`::`{test.test_name}`\n\n")
3517
3503
 
@@ -317,6 +317,13 @@ class ModelTest(unittest.TestCase):
317
317
  #
318
318
  # This is a bit of a hack, but it's a way to get the best of both worlds.
319
319
  args: t.List[t.Any] = []
320
+
321
+ failed_subtest = ""
322
+
323
+ if subtest := getattr(self, "_subtest", None):
324
+ if cte := subtest.params.get("cte"):
325
+ failed_subtest = f" (CTE {cte})"
326
+
320
327
  if expected.shape != actual.shape:
321
328
  _raise_if_unexpected_columns(expected.columns, actual.columns)
322
329
 
@@ -325,13 +332,13 @@ class ModelTest(unittest.TestCase):
325
332
  missing_rows = _row_difference(expected, actual)
326
333
  if not missing_rows.empty:
327
334
  args[0] += f"\n\nMissing rows:\n\n{missing_rows}"
328
- args.append(df_to_table("Missing rows", missing_rows))
335
+ args.append(df_to_table(f"Missing rows{failed_subtest}", missing_rows))
329
336
 
330
337
  unexpected_rows = _row_difference(actual, expected)
331
338
 
332
339
  if not unexpected_rows.empty:
333
340
  args[0] += f"\n\nUnexpected rows:\n\n{unexpected_rows}"
334
- args.append(df_to_table("Unexpected rows", unexpected_rows))
341
+ args.append(df_to_table(f"Unexpected rows{failed_subtest}", unexpected_rows))
335
342
 
336
343
  else:
337
344
  diff = expected.compare(actual).rename(columns={"self": "exp", "other": "act"})
@@ -341,7 +348,8 @@ class ModelTest(unittest.TestCase):
341
348
  diff.rename(columns={"exp": "Expected", "act": "Actual"}, inplace=True)
342
349
  if self.verbosity == Verbosity.DEFAULT:
343
350
  args.extend(
344
- df_to_table("Data mismatch", df) for df in _split_df_by_column_pairs(diff)
351
+ df_to_table(f"Data mismatch{failed_subtest}", df)
352
+ for df in _split_df_by_column_pairs(diff)
345
353
  )
346
354
  else:
347
355
  from pandas import MultiIndex
@@ -351,7 +359,8 @@ class ModelTest(unittest.TestCase):
351
359
  col_diff = diff[col]
352
360
  if not col_diff.empty:
353
361
  table = df_to_table(
354
- f"[bold red]Column '{col}' mismatch[/bold red]", col_diff
362
+ f"[bold red]Column '{col}' mismatch{failed_subtest}[/bold red]",
363
+ col_diff,
355
364
  )
356
365
  args.append(table)
357
366
 
@@ -4,6 +4,8 @@ import types
4
4
  import typing as t
5
5
  import unittest
6
6
 
7
+ from sqlmesh.core.test.definition import ModelTest
8
+
7
9
  if t.TYPE_CHECKING:
8
10
  ErrorType = t.Union[
9
11
  t.Tuple[type[BaseException], BaseException, types.TracebackType],
@@ -42,7 +44,10 @@ class ModelTextTestResult(unittest.TextTestResult):
42
44
  exctype, value, tb = err
43
45
  err = (exctype, value, None) # type: ignore
44
46
 
45
- super().addSubTest(test, subtest, err)
47
+ if err[0] and issubclass(err[0], test.failureException):
48
+ self.addFailure(test, err)
49
+ else:
50
+ self.addError(test, err)
46
51
 
47
52
  def _print_char(self, char: str) -> None:
48
53
  from sqlmesh.core.console import TerminalConsole
@@ -117,4 +122,14 @@ class ModelTextTestResult(unittest.TextTestResult):
117
122
  skipped_args = other.skipped[0]
118
123
  self.addSkip(skipped_args[0], skipped_args[1])
119
124
 
120
- self.testsRun += 1
125
+ self.testsRun += other.testsRun
126
+
127
+ def get_fail_and_error_tests(self) -> t.List[ModelTest]:
128
+ # If tests contain failed subtests (e.g testing CTE outputs) we don't want
129
+ # to report it as different test failures
130
+ test_name_to_test = {
131
+ test.test_name: test
132
+ for test, _ in self.failures + self.errors
133
+ if isinstance(test, ModelTest)
134
+ }
135
+ return list(test_name_to_test.values())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlmesh
3
- Version: 0.206.2.dev7
3
+ Version: 0.206.2.dev8
4
4
  Summary: Next-generation data transformation framework
5
5
  Author-email: "TobikoData Inc." <engineering@tobikodata.com>
6
6
  License: Apache License
@@ -1,5 +1,5 @@
1
1
  sqlmesh/__init__.py,sha256=QjwaamJIdW7voXoS880yAx7tHm-Im4_mqGA-XJgafos,7631
2
- sqlmesh/_version.py,sha256=VDX-JTy68y-G9zQ4XHshhimsqwRSwbiwG68vlnYzYfk,528
2
+ sqlmesh/_version.py,sha256=xjRXn5bPwiZFKZ9lkp60TXLTlVjewwJGYmGlX053TQo,528
3
3
  sqlmesh/magics.py,sha256=bEzYqXHcM0P3CjyUZ1O9arlmXAdLAhoglKbQ29fD9AE,41842
4
4
  sqlmesh/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  sqlmesh/cicd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -11,7 +11,7 @@ sqlmesh/cli/options.py,sha256=8qEGWivk4urGikpEmaU9T8WsyaZtjCpmW4Ed25iQ73I,2543
11
11
  sqlmesh/cli/project_init.py,sha256=5JmDmUK0WJs39hM-p76uzHYdo1Hnx6fKuJg_pR3Hn5A,16419
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=ovjM75l1A2rAi-ud3ovsIKSGwF9TsGYTK8NvokbCdL4,166111
14
+ sqlmesh/core/console.py,sha256=KbIXoxt5hpDENEolY-DpBlPmcWtJ9vzEgF52mjG2jPE,165710
15
15
  sqlmesh/core/constants.py,sha256=gUABXWYgH_XOSbaZAJsR5o1dmA61JDCvBDyxqqXX3LM,2630
16
16
  sqlmesh/core/context.py,sha256=SkTNrp9TUNx469_mWkemhMk4leGDtmblBIWE7S64sk8,127598
17
17
  sqlmesh/core/context_diff.py,sha256=_Ur55fGLJ58Icsp44I4pVhdi7_JHiHq45mWIco9oFzk,21792
@@ -119,9 +119,9 @@ sqlmesh/core/state_sync/db/utils.py,sha256=204OpT3ISFPCwWP9Aqq8nr6ETl24sbG5uOyo8
119
119
  sqlmesh/core/state_sync/db/version.py,sha256=fl5g1tNMYu8O6WTN4J3bciwjGq0c5nZlRDlxxRKGU78,2210
120
120
  sqlmesh/core/test/__init__.py,sha256=e83TJPwPRR_rAG29Y0OVbZb-5oWVBzz-_wrcd22Qk10,418
121
121
  sqlmesh/core/test/context.py,sha256=9mmskKXpzsIkW_I31uN1n3Ioj8ngvyGAqyL_AZvVHpc,2253
122
- sqlmesh/core/test/definition.py,sha256=38jIDb0H2oNg_h9-PXdXPSPDLxZwuXi6tF9SI0j6S4w,41544
122
+ sqlmesh/core/test/definition.py,sha256=VvjwvBoyd-y6Ucepf_vLuDm2DxqDLJh0X--D8BzFUng,41868
123
123
  sqlmesh/core/test/discovery.py,sha256=WXIwPidLoacAGHoT_3TVFFEKamG89nHNtaMsZ01uGjs,1188
124
- sqlmesh/core/test/result.py,sha256=IIyR4uMDDFJ9Hf57iwrHgZ_W_tLwnr0KSWKeBJ0Pc6k,3961
124
+ sqlmesh/core/test/result.py,sha256=6gOKEsERciHhcrw9TedtNr7g1ynTO7UwA5-PPrzvYuM,4564
125
125
  sqlmesh/core/test/runner.py,sha256=8I-cL7Q9CggLvET_GPkrXB2YjlyCIHrvbFbbRDnSHRE,6169
126
126
  sqlmesh/dbt/__init__.py,sha256=KUv-lW5sG9D2ceXAIzA4MLcjyhzq3E-7qJP4P_PH2EU,144
127
127
  sqlmesh/dbt/adapter.py,sha256=pV8b8m_wqK3YJo_6D5b6cZBwgewFAPvAlvLO51UCBl4,16948
@@ -288,7 +288,7 @@ sqlmesh/utils/pydantic.py,sha256=o_NsXbIpDqNpUA1Uc5xF0ZzoXQYYB0DfHwdRxBwXPNk,120
288
288
  sqlmesh/utils/rich.py,sha256=cwQ5nJ6sgz64xHtoh6_ec7ReV5YpsOGhMtUJnwoRfEI,3549
289
289
  sqlmesh/utils/windows.py,sha256=r7Yin4WEwbvH7sKA3hOJtRsclmscNuBeCklCfVPvtQs,611
290
290
  sqlmesh/utils/yaml.py,sha256=hvo5lmybYLcIx4p6CQwufS8X4MbwS60lEBnCmYJCXmU,2336
291
- sqlmesh-0.206.2.dev7.dist-info/licenses/LICENSE,sha256=OlMefUjgWJdULtf84BLW0AZZcY8DwdgQqb_1j2862j8,11346
291
+ sqlmesh-0.206.2.dev8.dist-info/licenses/LICENSE,sha256=OlMefUjgWJdULtf84BLW0AZZcY8DwdgQqb_1j2862j8,11346
292
292
  web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
293
293
  web/client/dist/index.html,sha256=SXykdSRNgrT1k6I2dPZPEfpxPjIsi8-yVFijt-naSA4,5472
294
294
  web/client/dist/assets/Audits-Jm353fhk.js,sha256=ry6b5IKT3hLAfD5C3T2BqxulfauEV0n0YZ2vsP4eQ_U,1041
@@ -406,8 +406,8 @@ web/server/api/endpoints/models.py,sha256=kwj0s7uve3iZSMfmjkoPVMFMeY1sD0peTeyrWf
406
406
  web/server/api/endpoints/modules.py,sha256=8hqqgonGay_mJmpCw0IdbjsPhWlQH2VLdKAqha-myac,468
407
407
  web/server/api/endpoints/plan.py,sha256=bbbY50W_2MsZSTxOHWMKz0tbIm75nsRSlPy8GI2fg9Q,9306
408
408
  web/server/api/endpoints/table_diff.py,sha256=SCy3-pr5x6bEEiOaZGCDbiHQhpgxwmnz3Acqa2Ie6jI,2090
409
- sqlmesh-0.206.2.dev7.dist-info/METADATA,sha256=5bnu6iA2itOFDLlLk9SJ1DJ3nbMrnAYOIBNbphHnoP0,26685
410
- sqlmesh-0.206.2.dev7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
411
- sqlmesh-0.206.2.dev7.dist-info/entry_points.txt,sha256=pIYKtg-u-uO7BK_Y0qrdmfyj0bYrcMc3Xiqr5WE3VFk,121
412
- sqlmesh-0.206.2.dev7.dist-info/top_level.txt,sha256=bspjo5vjELQkuN0qKuTFIbsrUt3Zeo8D2mlKeHG1LdE,12
413
- sqlmesh-0.206.2.dev7.dist-info/RECORD,,
409
+ sqlmesh-0.206.2.dev8.dist-info/METADATA,sha256=6yXTgCs4ubiok83fzzYObV7Fs7VF8WbOa5DvfwqolCU,26685
410
+ sqlmesh-0.206.2.dev8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
411
+ sqlmesh-0.206.2.dev8.dist-info/entry_points.txt,sha256=pIYKtg-u-uO7BK_Y0qrdmfyj0bYrcMc3Xiqr5WE3VFk,121
412
+ sqlmesh-0.206.2.dev8.dist-info/top_level.txt,sha256=bspjo5vjELQkuN0qKuTFIbsrUt3Zeo8D2mlKeHG1LdE,12
413
+ sqlmesh-0.206.2.dev8.dist-info/RECORD,,