sql-glider 0.1.6__tar.gz → 0.1.8__tar.gz

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.
Files changed (137) hide show
  1. {sql_glider-0.1.6 → sql_glider-0.1.8}/PKG-INFO +1 -1
  2. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/_version.py +2 -2
  3. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/graph/builder.py +8 -7
  4. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/graph/serialization.py +5 -5
  5. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/graph/test_builder.py +53 -0
  6. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/graph/test_query.py +2 -2
  7. {sql_glider-0.1.6 → sql_glider-0.1.8}/.github/workflows/ci.yml +0 -0
  8. {sql_glider-0.1.6 → sql_glider-0.1.8}/.github/workflows/publish.yml +0 -0
  9. {sql_glider-0.1.6 → sql_glider-0.1.8}/.gitignore +0 -0
  10. {sql_glider-0.1.6 → sql_glider-0.1.8}/.python-version +0 -0
  11. {sql_glider-0.1.6 → sql_glider-0.1.8}/ARCHITECTURE.md +0 -0
  12. {sql_glider-0.1.6 → sql_glider-0.1.8}/CLAUDE.md +0 -0
  13. {sql_glider-0.1.6 → sql_glider-0.1.8}/LICENSE +0 -0
  14. {sql_glider-0.1.6 → sql_glider-0.1.8}/README.md +0 -0
  15. {sql_glider-0.1.6 → sql_glider-0.1.8}/plans/2025-12-05-column-level-lineage.md +0 -0
  16. {sql_glider-0.1.6 → sql_glider-0.1.8}/plans/2025-12-05-reverse-lineage.md +0 -0
  17. {sql_glider-0.1.6 → sql_glider-0.1.8}/plans/2025-12-06-config-file-support.md +0 -0
  18. {sql_glider-0.1.6 → sql_glider-0.1.8}/plans/2025-12-06-graph-lineage.md +0 -0
  19. {sql_glider-0.1.6 → sql_glider-0.1.8}/plans/2025-12-06-unify-single-multi-query.md +0 -0
  20. {sql_glider-0.1.6 → sql_glider-0.1.8}/plans/2025-12-07-sample-data-model.md +0 -0
  21. {sql_glider-0.1.6 → sql_glider-0.1.8}/plans/2025-12-07-sql-templating.md +0 -0
  22. {sql_glider-0.1.6 → sql_glider-0.1.8}/plans/2025-12-08-tables-command.md +0 -0
  23. {sql_glider-0.1.6 → sql_glider-0.1.8}/plans/2025-12-09-graph-query-paths.md +0 -0
  24. {sql_glider-0.1.6 → sql_glider-0.1.8}/plans/2025-12-13-dissect-command.md +0 -0
  25. {sql_glider-0.1.6 → sql_glider-0.1.8}/plans/2025-12-14-tables-pull-command.md +0 -0
  26. {sql_glider-0.1.6 → sql_glider-0.1.8}/plans/2026-01-25-fix-union-lineage-chain.md +0 -0
  27. {sql_glider-0.1.6 → sql_glider-0.1.8}/plans/2026-01-26-file-scoped-schema-context.md +0 -0
  28. {sql_glider-0.1.6 → sql_glider-0.1.8}/pyproject.toml +0 -0
  29. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/README.md +0 -0
  30. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/business/expire_dim_customer.sql +0 -0
  31. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/business/load_fact_orders.sql +0 -0
  32. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/business/load_fact_payments.sql +0 -0
  33. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/business/merge_dim_customer.sql +0 -0
  34. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/business/merge_dim_product.sql +0 -0
  35. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/business/update_dim_customer_metrics.sql +0 -0
  36. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/complex/conditional_merge.sql +0 -0
  37. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/complex/cte_insert.sql +0 -0
  38. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/complex/multi_table_transform.sql +0 -0
  39. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/ddl/dim_customer.sql +0 -0
  40. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/ddl/dim_product.sql +0 -0
  41. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/ddl/fact_orders.sql +0 -0
  42. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/ddl/fact_payments.sql +0 -0
  43. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/ddl/raw_addresses.sql +0 -0
  44. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/ddl/raw_customers.sql +0 -0
  45. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/ddl/raw_order_items.sql +0 -0
  46. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/ddl/raw_orders.sql +0 -0
  47. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/ddl/raw_payments.sql +0 -0
  48. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/ddl/raw_products.sql +0 -0
  49. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/ddl/stg_customers.sql +0 -0
  50. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/ddl/stg_orders.sql +0 -0
  51. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/ddl/stg_payments.sql +0 -0
  52. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/ddl/stg_products.sql +0 -0
  53. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/incremental/incr_fact_orders.sql +0 -0
  54. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/incremental/incr_fact_payments.sql +0 -0
  55. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/incremental/incr_pres_sales_summary.sql +0 -0
  56. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/maintenance/delete_expired_customers.sql +0 -0
  57. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/maintenance/update_product_status.sql +0 -0
  58. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/presentation/load_pres_customer_360.sql +0 -0
  59. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/presentation/load_pres_customer_cohort.sql +0 -0
  60. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/presentation/load_pres_product_performance.sql +0 -0
  61. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/presentation/load_pres_sales_summary.sql +0 -0
  62. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/staging/load_stg_customers.sql +0 -0
  63. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/staging/load_stg_orders.sql +0 -0
  64. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/staging/load_stg_payments.sql +0 -0
  65. {sql_glider-0.1.6 → sql_glider-0.1.8}/sample_data_model/staging/load_stg_products.sql +0 -0
  66. {sql_glider-0.1.6 → sql_glider-0.1.8}/sqlglider.toml.example +0 -0
  67. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/__init__.py +0 -0
  68. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/catalog/__init__.py +0 -0
  69. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/catalog/base.py +0 -0
  70. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/catalog/databricks.py +0 -0
  71. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/catalog/registry.py +0 -0
  72. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/cli.py +0 -0
  73. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/dissection/__init__.py +0 -0
  74. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/dissection/analyzer.py +0 -0
  75. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/dissection/formatters.py +0 -0
  76. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/dissection/models.py +0 -0
  77. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/global_models.py +0 -0
  78. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/graph/__init__.py +0 -0
  79. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/graph/merge.py +0 -0
  80. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/graph/models.py +0 -0
  81. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/graph/query.py +0 -0
  82. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/lineage/__init__.py +0 -0
  83. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/lineage/analyzer.py +0 -0
  84. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/lineage/formatters.py +0 -0
  85. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/templating/__init__.py +0 -0
  86. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/templating/base.py +0 -0
  87. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/templating/jinja.py +0 -0
  88. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/templating/registry.py +0 -0
  89. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/templating/variables.py +0 -0
  90. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/utils/__init__.py +0 -0
  91. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/utils/config.py +0 -0
  92. {sql_glider-0.1.6 → sql_glider-0.1.8}/src/sqlglider/utils/file_utils.py +0 -0
  93. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/__init__.py +0 -0
  94. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/fixtures/multi_file_queries/analytics_pipeline.sql +0 -0
  95. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/fixtures/multi_file_queries/analytics_pipeline_union_merge.sql +0 -0
  96. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/fixtures/multi_file_queries/customers.sql +0 -0
  97. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/fixtures/multi_file_queries/orders.sql +0 -0
  98. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/fixtures/multi_file_queries/reports.sql +0 -0
  99. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/fixtures/multi_file_queries/view_based_merge.sql +0 -0
  100. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/fixtures/original_queries/test_cte.sql +0 -0
  101. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/fixtures/original_queries/test_cte_query.sql +0 -0
  102. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/fixtures/original_queries/test_cte_view_star.sql +0 -0
  103. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/fixtures/original_queries/test_generated_column_query.sql +0 -0
  104. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/fixtures/original_queries/test_multi.sql +0 -0
  105. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/fixtures/original_queries/test_multi_query.sql +0 -0
  106. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/fixtures/original_queries/test_single_query.sql +0 -0
  107. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/fixtures/original_queries/test_subquery.sql +0 -0
  108. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/fixtures/original_queries/test_tables.sql +0 -0
  109. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/fixtures/original_queries/test_view.sql +0 -0
  110. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/fixtures/original_queries/test_view_window_cte.sql +0 -0
  111. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/fixtures/sample_manifest.csv +0 -0
  112. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/__init__.py +0 -0
  113. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/catalog/__init__.py +0 -0
  114. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/catalog/test_base.py +0 -0
  115. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/catalog/test_databricks.py +0 -0
  116. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/catalog/test_registry.py +0 -0
  117. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/dissection/__init__.py +0 -0
  118. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/dissection/test_analyzer.py +0 -0
  119. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/dissection/test_formatters.py +0 -0
  120. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/dissection/test_models.py +0 -0
  121. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/graph/__init__.py +0 -0
  122. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/graph/test_merge.py +0 -0
  123. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/graph/test_models.py +0 -0
  124. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/graph/test_serialization.py +0 -0
  125. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/lineage/__init__.py +0 -0
  126. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/lineage/test_analyzer.py +0 -0
  127. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/lineage/test_formatters.py +0 -0
  128. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/templating/__init__.py +0 -0
  129. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/templating/test_base.py +0 -0
  130. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/templating/test_jinja.py +0 -0
  131. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/templating/test_registry.py +0 -0
  132. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/templating/test_variables.py +0 -0
  133. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/test_cli.py +0 -0
  134. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/utils/__init__.py +0 -0
  135. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/utils/test_config.py +0 -0
  136. {sql_glider-0.1.6 → sql_glider-0.1.8}/tests/sqlglider/utils/test_file_utils.py +0 -0
  137. {sql_glider-0.1.6 → sql_glider-0.1.8}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sql-glider
3
- Version: 0.1.6
3
+ Version: 0.1.8
4
4
  Summary: SQL Utility Toolkit for better understanding, use, and governance of your queries in a native environment.
5
5
  Project-URL: Homepage, https://github.com/rycowhi/sql-glider/
6
6
  Project-URL: Repository, https://github.com/rycowhi/sql-glider/
@@ -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.1.6'
32
- __version_tuple__ = version_tuple = (0, 1, 6)
31
+ __version__ = version = '0.1.8'
32
+ __version_tuple__ = version_tuple = (0, 1, 8)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -114,11 +114,11 @@ class GraphBuilder:
114
114
  )
115
115
 
116
116
  # Add edge (source contributes_to target) - deduplicate
117
- edge_key = (item.source_name, item.output_name)
117
+ edge_key = (item.source_name.lower(), item.output_name.lower())
118
118
  if edge_key not in self._edge_set:
119
119
  edge = GraphEdge(
120
- source_node=item.source_name,
121
- target_node=item.output_name,
120
+ source_node=item.source_name.lower(),
121
+ target_node=item.output_name.lower(),
122
122
  file_path=file_path_str,
123
123
  query_index=query_index,
124
124
  )
@@ -280,17 +280,18 @@ class GraphBuilder:
280
280
  Returns:
281
281
  rustworkx node index
282
282
  """
283
- if identifier in self._node_index_map:
284
- return self._node_index_map[identifier]
283
+ key = identifier.lower()
284
+ if key in self._node_index_map:
285
+ return self._node_index_map[key]
285
286
 
286
287
  node = GraphNode.from_identifier(
287
- identifier=identifier,
288
+ identifier=key,
288
289
  file_path=file_path,
289
290
  query_index=query_index,
290
291
  )
291
292
 
292
293
  node_idx = self.graph.add_node(node.model_dump())
293
- self._node_index_map[identifier] = node_idx
294
+ self._node_index_map[key] = node_idx
294
295
  return node_idx
295
296
 
296
297
  def build(self) -> LineageGraph:
@@ -61,15 +61,15 @@ def to_rustworkx(graph: LineageGraph) -> Tuple[rx.PyDiGraph, Dict[str, int]]:
61
61
  rx_graph: rx.PyDiGraph = rx.PyDiGraph()
62
62
  node_map: Dict[str, int] = {}
63
63
 
64
- # Add nodes
64
+ # Add nodes (use lowercase keys for case-insensitive lookup)
65
65
  for node in graph.nodes:
66
66
  idx = rx_graph.add_node(node.model_dump())
67
- node_map[node.identifier] = idx
67
+ node_map[node.identifier.lower()] = idx
68
68
 
69
- # Add edges
69
+ # Add edges (use lowercase for lookup to match node keys)
70
70
  for edge in graph.edges:
71
- source_idx = node_map.get(edge.source_node)
72
- target_idx = node_map.get(edge.target_node)
71
+ source_idx = node_map.get(edge.source_node.lower())
72
+ target_idx = node_map.get(edge.target_node.lower())
73
73
  if source_idx is not None and target_idx is not None:
74
74
  rx_graph.add_edge(source_idx, target_idx, edge.model_dump())
75
75
 
@@ -578,3 +578,56 @@ class TestGraphBuilderCreateViewWithCTEAndWindowFunction:
578
578
  assert "raw_sales.customer_id" in node_ids
579
579
  assert "raw_sales.product_id" in node_ids
580
580
  assert "raw_sales.quantity" in node_ids
581
+
582
+
583
+ class TestGraphBuilderCaseInsensitive:
584
+ """Tests for case-insensitive node deduplication during graph build."""
585
+
586
+ def test_nodes_deduplicated_across_files_different_case(self, tmp_path):
587
+ """Nodes with different casing should be deduplicated into one node."""
588
+ file1 = tmp_path / "query1.sql"
589
+ file1.write_text("SELECT Customer_ID FROM Orders;")
590
+
591
+ file2 = tmp_path / "query2.sql"
592
+ file2.write_text("SELECT customer_id FROM orders;")
593
+
594
+ builder = GraphBuilder()
595
+ builder.add_file(file1)
596
+ builder.add_file(file2)
597
+ graph = builder.build()
598
+
599
+ # Should have deduplicated nodes regardless of case
600
+ identifiers_lower = [n.identifier.lower() for n in graph.nodes]
601
+ assert identifiers_lower.count("orders.customer_id") == 1
602
+
603
+ def test_edges_deduplicated_across_files_different_case(self, tmp_path):
604
+ """Edges with different casing should be deduplicated."""
605
+ file1 = tmp_path / "query1.sql"
606
+ file1.write_text("SELECT Customer_Name FROM Customers;")
607
+
608
+ file2 = tmp_path / "query2.sql"
609
+ file2.write_text("SELECT customer_name FROM customers;")
610
+
611
+ builder = GraphBuilder()
612
+ builder.add_file(file1)
613
+ builder.add_file(file2)
614
+ graph = builder.build()
615
+
616
+ # Edges should be deduplicated
617
+ edge_pairs = [
618
+ (e.source_node.lower(), e.target_node.lower()) for e in graph.edges
619
+ ]
620
+ for pair in edge_pairs:
621
+ assert edge_pairs.count(pair) == 1
622
+
623
+ def test_node_index_map_uses_lowercase_keys(self, tmp_path):
624
+ """The internal node index map should use lowercase keys."""
625
+ sql_file = tmp_path / "query.sql"
626
+ sql_file.write_text("SELECT Customer_ID FROM Orders;")
627
+
628
+ builder = GraphBuilder()
629
+ builder.add_file(sql_file)
630
+
631
+ # All keys in the node index map should be lowercase
632
+ for key in builder.node_index_map:
633
+ assert key == key.lower(), f"Node index map key '{key}' is not lowercase"
@@ -196,7 +196,7 @@ class TestGraphQuerierUpstream:
196
196
  # Query with different case
197
197
  result = querier.find_upstream("TARGET.COLUMN")
198
198
 
199
- assert result.query_column == "Target.Column" # Original case preserved
199
+ assert result.query_column == "target.column" # Normalized to lowercase
200
200
  assert len(result) == 1
201
201
 
202
202
 
@@ -302,7 +302,7 @@ class TestGraphQuerierDownstream:
302
302
  # Query with different case
303
303
  result = querier.find_downstream("source.column")
304
304
 
305
- assert result.query_column == "Source.Column" # Original case preserved
305
+ assert result.query_column == "source.column" # Normalized to lowercase
306
306
  assert len(result) == 1
307
307
 
308
308
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes