pytrilogy 0.0.3.61__tar.gz → 0.0.3.63__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.

Potentially problematic release.


This version of pytrilogy might be problematic. Click here for more details.

Files changed (149) hide show
  1. {pytrilogy-0.0.3.61/pytrilogy.egg-info → pytrilogy-0.0.3.63}/PKG-INFO +1 -1
  2. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63/pytrilogy.egg-info}/PKG-INFO +1 -1
  3. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/__init__.py +1 -1
  4. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/node_generators/basic_node.py +7 -1
  5. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/node_generators/synonym_node.py +31 -2
  6. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/LICENSE.md +0 -0
  7. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/README.md +0 -0
  8. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/pyproject.toml +0 -0
  9. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/pytrilogy.egg-info/SOURCES.txt +0 -0
  10. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/pytrilogy.egg-info/dependency_links.txt +0 -0
  11. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/pytrilogy.egg-info/entry_points.txt +0 -0
  12. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/pytrilogy.egg-info/requires.txt +0 -0
  13. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/pytrilogy.egg-info/top_level.txt +0 -0
  14. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/setup.cfg +0 -0
  15. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/setup.py +0 -0
  16. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_datatypes.py +0 -0
  17. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_declarations.py +0 -0
  18. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_derived_concepts.py +0 -0
  19. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_discovery_nodes.py +0 -0
  20. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_enums.py +0 -0
  21. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_environment.py +0 -0
  22. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_executor.py +0 -0
  23. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_failure.py +0 -0
  24. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_functions.py +0 -0
  25. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_imports.py +0 -0
  26. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_metadata.py +0 -0
  27. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_models.py +0 -0
  28. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_multi_join_assignments.py +0 -0
  29. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_parse_engine.py +0 -0
  30. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_parsing.py +0 -0
  31. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_parsing_failures.py +0 -0
  32. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_partial_handling.py +0 -0
  33. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_query_processing.py +0 -0
  34. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_query_render.py +0 -0
  35. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_select.py +0 -0
  36. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_show.py +0 -0
  37. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_statements.py +0 -0
  38. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_typing.py +0 -0
  39. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_undefined_concept.py +0 -0
  40. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_user_functions.py +0 -0
  41. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/tests/test_where_clause.py +0 -0
  42. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/authoring/__init__.py +0 -0
  43. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/compiler.py +0 -0
  44. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/constants.py +0 -0
  45. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/__init__.py +0 -0
  46. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/constants.py +0 -0
  47. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/enums.py +0 -0
  48. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/env_processor.py +0 -0
  49. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/environment_helpers.py +0 -0
  50. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/ergonomics.py +0 -0
  51. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/exceptions.py +0 -0
  52. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/functions.py +0 -0
  53. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/graph_models.py +0 -0
  54. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/internal.py +0 -0
  55. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/models/__init__.py +0 -0
  56. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/models/author.py +0 -0
  57. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/models/build.py +0 -0
  58. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/models/build_environment.py +0 -0
  59. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/models/core.py +0 -0
  60. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/models/datasource.py +0 -0
  61. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/models/environment.py +0 -0
  62. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/models/execute.py +0 -0
  63. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/optimization.py +0 -0
  64. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/optimizations/__init__.py +0 -0
  65. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/optimizations/base_optimization.py +0 -0
  66. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/optimizations/inline_datasource.py +0 -0
  67. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/optimizations/predicate_pushdown.py +0 -0
  68. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/__init__.py +0 -0
  69. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/concept_strategies_v3.py +0 -0
  70. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/discovery_loop.py +0 -0
  71. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/discovery_node_factory.py +0 -0
  72. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/discovery_utility.py +0 -0
  73. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/discovery_validation.py +0 -0
  74. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/graph_utils.py +0 -0
  75. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/node_generators/__init__.py +0 -0
  76. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/node_generators/common.py +0 -0
  77. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/node_generators/filter_node.py +0 -0
  78. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/node_generators/group_node.py +0 -0
  79. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/node_generators/group_to_node.py +0 -0
  80. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/node_generators/multiselect_node.py +0 -0
  81. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/node_generators/node_merge_node.py +0 -0
  82. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/node_generators/recursive_node.py +0 -0
  83. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/node_generators/rowset_node.py +0 -0
  84. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/node_generators/select_helpers/__init__.py +0 -0
  85. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/node_generators/select_helpers/datasource_injection.py +0 -0
  86. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/node_generators/select_merge_node.py +0 -0
  87. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/node_generators/select_node.py +0 -0
  88. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/node_generators/union_node.py +0 -0
  89. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/node_generators/unnest_node.py +0 -0
  90. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/node_generators/window_node.py +0 -0
  91. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/nodes/__init__.py +0 -0
  92. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/nodes/base_node.py +0 -0
  93. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/nodes/filter_node.py +0 -0
  94. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/nodes/group_node.py +0 -0
  95. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/nodes/merge_node.py +0 -0
  96. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/nodes/recursive_node.py +0 -0
  97. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/nodes/select_node_v2.py +0 -0
  98. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/nodes/union_node.py +0 -0
  99. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/nodes/unnest_node.py +0 -0
  100. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/nodes/window_node.py +0 -0
  101. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/processing/utility.py +0 -0
  102. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/query_processor.py +0 -0
  103. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/statements/__init__.py +0 -0
  104. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/statements/author.py +0 -0
  105. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/statements/build.py +0 -0
  106. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/statements/common.py +0 -0
  107. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/statements/execute.py +0 -0
  108. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/core/utility.py +0 -0
  109. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/dialect/__init__.py +0 -0
  110. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/dialect/base.py +0 -0
  111. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/dialect/bigquery.py +0 -0
  112. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/dialect/common.py +0 -0
  113. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/dialect/config.py +0 -0
  114. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/dialect/dataframe.py +0 -0
  115. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/dialect/duckdb.py +0 -0
  116. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/dialect/enums.py +0 -0
  117. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/dialect/postgres.py +0 -0
  118. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/dialect/presto.py +0 -0
  119. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/dialect/snowflake.py +0 -0
  120. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/dialect/sql_server.py +0 -0
  121. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/engine.py +0 -0
  122. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/executor.py +0 -0
  123. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/hooks/__init__.py +0 -0
  124. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/hooks/base_hook.py +0 -0
  125. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/hooks/graph_hook.py +0 -0
  126. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/hooks/query_debugger.py +0 -0
  127. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/metadata/__init__.py +0 -0
  128. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/parser.py +0 -0
  129. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/parsing/__init__.py +0 -0
  130. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/parsing/common.py +0 -0
  131. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/parsing/config.py +0 -0
  132. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/parsing/exceptions.py +0 -0
  133. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/parsing/helpers.py +0 -0
  134. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/parsing/parse_engine.py +0 -0
  135. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/parsing/render.py +0 -0
  136. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/parsing/trilogy.lark +0 -0
  137. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/py.typed +0 -0
  138. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/render.py +0 -0
  139. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/scripts/__init__.py +0 -0
  140. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/scripts/trilogy.py +0 -0
  141. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/std/__init__.py +0 -0
  142. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/std/date.preql +0 -0
  143. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/std/display.preql +0 -0
  144. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/std/geography.preql +0 -0
  145. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/std/money.preql +0 -0
  146. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/std/net.preql +0 -0
  147. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/std/ranking.preql +0 -0
  148. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/std/report.preql +0 -0
  149. {pytrilogy-0.0.3.61 → pytrilogy-0.0.3.63}/trilogy/utility.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytrilogy
3
- Version: 0.0.3.61
3
+ Version: 0.0.3.63
4
4
  Summary: Declarative, typed query language that compiles to SQL.
5
5
  Home-page:
6
6
  Author:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytrilogy
3
- Version: 0.0.3.61
3
+ Version: 0.0.3.63
4
4
  Summary: Declarative, typed query language that compiles to SQL.
5
5
  Home-page:
6
6
  Author:
@@ -4,6 +4,6 @@ from trilogy.dialect.enums import Dialects
4
4
  from trilogy.executor import Executor
5
5
  from trilogy.parser import parse
6
6
 
7
- __version__ = "0.0.3.61"
7
+ __version__ = "0.0.3.63"
8
8
 
9
9
  __all__ = ["parse", "Executor", "Dialects", "Environment", "CONFIG"]
@@ -52,6 +52,9 @@ def gen_basic_node(
52
52
  synonyms: list[BuildConcept] = []
53
53
  ignored_optional: set[str] = set()
54
54
  assert isinstance(concept.lineage, BuildFunction)
55
+ # when we are getting an attribute, if there is anything else
56
+ # that is an attribute of the same struct in local optional
57
+ # select that value for discovery as well
55
58
  if concept.lineage.operator == FunctionType.ATTR_ACCESS:
56
59
  logger.info(
57
60
  f"{depth_prefix}{LOGGER_PREFIX} checking for synonyms for attribute access"
@@ -62,7 +65,10 @@ def gen_basic_node(
62
65
  # gate to ensure we don't match to multiple synonyms
63
66
  if found:
64
67
  continue
65
- s_concept = environment.alias_origin_lookup[z]
68
+ if z in environment.concepts:
69
+ s_concept = environment.concepts[z]
70
+ else:
71
+ s_concept = environment.alias_origin_lookup[z]
66
72
  if is_equivalent_basic_function_lineage(concept, s_concept):
67
73
  found = True
68
74
  synonyms.append(s_concept)
@@ -43,16 +43,45 @@ def gen_synonym_node(
43
43
  elif y in environment.concepts:
44
44
  synonyms[x.address].append(environment.concepts[y])
45
45
  synonym_count += 1
46
+ for address in synonyms:
47
+ synonyms[address].sort(key=lambda obj: obj.address)
46
48
  if synonym_count == 0:
47
49
  return None
48
50
 
49
51
  logger.info(f"{local_prefix} Generating Synonym Node with {len(synonyms)} synonyms")
52
+ sorted_keys = sorted(synonyms.keys())
53
+ combinations_list = list(itertools.product(*(synonyms[obj] for obj in sorted_keys)))
50
54
 
51
- combinations = itertools.product(*(synonyms[obj] for obj in synonyms.keys()))
52
- for combo in combinations:
55
+ def similarity_sort_key(combo):
56
+ addresses = [x.address for x in combo]
57
+
58
+ # Calculate similarity score - count how many pairs share prefixes
59
+ similarity_score = 0
60
+ for i in range(len(addresses)):
61
+ for j in range(i + 1, len(addresses)):
62
+ # Find common prefix length
63
+ addr1_parts = addresses[i].split(".")
64
+ addr2_parts = addresses[j].split(".")
65
+ common_prefix_len = 0
66
+ for k in range(min(len(addr1_parts), len(addr2_parts))):
67
+ if addr1_parts[k] == addr2_parts[k]:
68
+ common_prefix_len += 1
69
+ else:
70
+ break
71
+ similarity_score += common_prefix_len
72
+
73
+ # Sort by similarity (descending), then by addresses (ascending) for ties
74
+ return (-similarity_score, addresses)
75
+
76
+ combinations_list.sort(key=similarity_sort_key)
77
+ logger.info(combinations_list)
78
+ for combo in combinations_list:
53
79
  fingerprint = tuple([x.address for x in combo])
54
80
  if fingerprint == base_fingerprint:
55
81
  continue
82
+ logger.info(
83
+ f"{local_prefix} checking combination {fingerprint} with {len(combo)} concepts"
84
+ )
56
85
  attempt: StrategyNode | None = source_concepts(
57
86
  combo,
58
87
  history=history,
File without changes
File without changes
File without changes
File without changes