pytrilogy 0.0.2.23__py3-none-any.whl → 0.0.2.26__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.

Potentially problematic release.


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

@@ -28,14 +28,18 @@ def extract_address(node: str):
28
28
  return node.split("~")[1].split("@")[0]
29
29
 
30
30
 
31
- def get_graph_partial_nodes(g: nx.DiGraph) -> dict[str, list[str]]:
31
+ def get_graph_partial_nodes(
32
+ g: nx.DiGraph, conditions: WhereClause | None
33
+ ) -> dict[str, list[str]]:
32
34
  datasources: dict[str, Datasource] = nx.get_node_attributes(g, "datasource")
33
35
  partial: dict[str, list[str]] = {}
34
36
  for node in g.nodes:
35
37
  if node in datasources:
36
- partial[node] = [
37
- concept_to_node(c) for c in datasources[node].partial_concepts
38
- ]
38
+ ds = datasources[node]
39
+ partial[node] = [concept_to_node(c) for c in ds.partial_concepts]
40
+ if ds.non_partial_for and conditions == ds.non_partial_for:
41
+ partial[node] = []
42
+
39
43
  return partial
40
44
 
41
45
 
@@ -49,7 +53,10 @@ def get_graph_grain_length(g: nx.DiGraph) -> dict[str, int]:
49
53
 
50
54
 
51
55
  def create_pruned_concept_graph(
52
- g: nx.DiGraph, all_concepts: List[Concept], accept_partial: bool = False
56
+ g: nx.DiGraph,
57
+ all_concepts: List[Concept],
58
+ accept_partial: bool = False,
59
+ conditions: WhereClause | None = None,
53
60
  ) -> nx.DiGraph:
54
61
  orig_g = g
55
62
  g = g.copy()
@@ -66,11 +73,7 @@ def create_pruned_concept_graph(
66
73
  relevent_datasets: list[str] = []
67
74
  if not accept_partial:
68
75
  partial = {}
69
- for node in g.nodes:
70
- if node in datasources:
71
- partial[node] = [
72
- concept_to_node(c) for c in datasources[node].partial_concepts
73
- ]
76
+ partial = get_graph_partial_nodes(g, conditions)
74
77
  to_remove = []
75
78
  for edge in g.edges:
76
79
  if (
@@ -133,31 +136,53 @@ def create_pruned_concept_graph(
133
136
  return g
134
137
 
135
138
 
136
- def resolve_subgraphs(g: nx.DiGraph) -> dict[str, list[str]]:
139
+ def resolve_subgraphs(
140
+ g: nx.DiGraph, conditions: WhereClause | None
141
+ ) -> dict[str, list[str]]:
137
142
  datasources = [n for n in g.nodes if n.startswith("ds~")]
138
- subgraphs = {ds: list(set(list(nx.all_neighbors(g, ds)))) for ds in datasources}
139
- partial_map = get_graph_partial_nodes(g)
143
+ subgraphs: dict[str, list[str]] = {
144
+ ds: list(set(list(nx.all_neighbors(g, ds)))) for ds in datasources
145
+ }
146
+ partial_map = get_graph_partial_nodes(g, conditions)
140
147
  grain_length = get_graph_grain_length(g)
141
- non_partial = {
142
- ds: [c for c in subgraphs[ds] if c not in partial_map[ds]] for ds in datasources
148
+ concepts: dict[str, Concept] = nx.get_node_attributes(g, "concept")
149
+ non_partial_map = {
150
+ ds: [concepts[c].address for c in subgraphs[ds] if c not in partial_map[ds]]
151
+ for ds in datasources
152
+ }
153
+ concept_map = {
154
+ ds: [concepts[c].address for c in subgraphs[ds]] for ds in datasources
143
155
  }
144
156
  pruned_subgraphs = {}
145
- for key, value in subgraphs.items():
157
+ for key, nodes in subgraphs.items():
158
+ value = non_partial_map[key]
159
+ all_concepts = concept_map[key]
146
160
  is_subset = False
147
161
  matches = set()
148
162
  # Compare current list with other lists
149
- for other_key, other_value in non_partial.items():
150
- if key != other_key and set(value).issubset(set(other_value)):
163
+ for other_key, other_all_concepts in concept_map.items():
164
+ other_value = non_partial_map[other_key]
165
+ # needs to be a subset of non partial and a subset of all
166
+ if (
167
+ key != other_key
168
+ and set(value).issubset(set(other_value))
169
+ and set(all_concepts).issubset(set(other_all_concepts))
170
+ ):
151
171
  if len(value) < len(other_value):
152
172
  is_subset = True
173
+ logger.debug(
174
+ f"Dropping subgraph {key} with {value} as it is a subset of {other_key} with {other_value}"
175
+ )
153
176
  break
154
- elif len(value) == len(other_value):
177
+ elif len(value) == len(other_value) and len(all_concepts) == len(
178
+ other_all_concepts
179
+ ):
155
180
  matches.add(other_key)
156
181
  matches.add(key)
157
182
  if matches:
158
183
  is_subset = key is not min(matches, key=lambda x: (grain_length[x], x))
159
184
  if not is_subset:
160
- pruned_subgraphs[key] = value
185
+ pruned_subgraphs[key] = nodes
161
186
  return pruned_subgraphs
162
187
 
163
188
 
@@ -261,7 +286,9 @@ def gen_select_merge_node(
261
286
  force_group=False,
262
287
  )
263
288
  for attempt in [False, True]:
264
- pruned_concept_graph = create_pruned_concept_graph(g, non_constant, attempt)
289
+ pruned_concept_graph = create_pruned_concept_graph(
290
+ g, non_constant, attempt, conditions
291
+ )
265
292
  if pruned_concept_graph:
266
293
  logger.info(
267
294
  f"{padding(depth)}{LOGGER_PREFIX} found covering graph w/ partial flag {attempt}"
@@ -274,7 +301,7 @@ def gen_select_merge_node(
274
301
  )
275
302
  return None
276
303
 
277
- sub_nodes = resolve_subgraphs(pruned_concept_graph)
304
+ sub_nodes = resolve_subgraphs(pruned_concept_graph, conditions)
278
305
 
279
306
  logger.info(f"{padding(depth)}{LOGGER_PREFIX} fetching subgraphs {sub_nodes}")
280
307
  parents = [
@@ -215,7 +215,7 @@ class MergeNode(StrategyNode):
215
215
  logger.info(
216
216
  f"{self.logging_prefix}{LOGGER_PREFIX} inferring node joins to target grain {str(grain)}"
217
217
  )
218
- joins = get_node_joins(dataset_list, grain.components, environment)
218
+ joins = get_node_joins(dataset_list, environment=environment)
219
219
  elif final_joins:
220
220
  logger.info(
221
221
  f"{self.logging_prefix}{LOGGER_PREFIX} translating provided node joins {len(final_joins)}"
@@ -314,7 +314,7 @@ class MergeNode(StrategyNode):
314
314
  full_join_concepts = []
315
315
  for join in joins:
316
316
  if isinstance(join, BaseJoin) and join.join_type == JoinType.FULL:
317
- full_join_concepts += join.concepts
317
+ full_join_concepts += join.input_concepts
318
318
  if self.whole_grain:
319
319
  force_group = False
320
320
  elif self.force_group is False: