py2dag 0.2.2__tar.gz → 0.2.3__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.
- {py2dag-0.2.2 → py2dag-0.2.3}/PKG-INFO +1 -1
- {py2dag-0.2.2 → py2dag-0.2.3}/py2dag/parser.py +79 -2
- {py2dag-0.2.2 → py2dag-0.2.3}/pyproject.toml +1 -1
- {py2dag-0.2.2 → py2dag-0.2.3}/LICENSE +0 -0
- {py2dag-0.2.2 → py2dag-0.2.3}/README.md +0 -0
- {py2dag-0.2.2 → py2dag-0.2.3}/py2dag/__init__.py +0 -0
- {py2dag-0.2.2 → py2dag-0.2.3}/py2dag/cli.py +0 -0
- {py2dag-0.2.2 → py2dag-0.2.3}/py2dag/export_dagre.py +0 -0
- {py2dag-0.2.2 → py2dag-0.2.3}/py2dag/export_svg.py +0 -0
- {py2dag-0.2.2 → py2dag-0.2.3}/py2dag/pseudo.py +0 -0
@@ -173,6 +173,10 @@ def parse(source: str, function_name: Optional[str] = None) -> Dict[str, Any]:
|
|
173
173
|
ops.append({"id": ssa, "op": op_name, "deps": deps, "args": kwargs})
|
174
174
|
return ssa
|
175
175
|
|
176
|
+
def _emit_expr_call(call: ast.Call) -> str:
|
177
|
+
"""Emit a node for a bare expression call (no assignment)."""
|
178
|
+
return _emit_assign_from_call("call", call)
|
179
|
+
|
176
180
|
def _emit_assign_from_fstring(var_name: str, fstr: ast.JoinedStr) -> str:
|
177
181
|
deps: List[str] = []
|
178
182
|
parts: List[str] = []
|
@@ -222,6 +226,45 @@ def parse(source: str, function_name: Optional[str] = None) -> Dict[str, Any]:
|
|
222
226
|
"args": {},
|
223
227
|
})
|
224
228
|
return ssa
|
229
|
+
if isinstance(value, ast.Dict):
|
230
|
+
# Support dict with values from names/calls or literals by synthesizing nodes
|
231
|
+
keys: List[str] = []
|
232
|
+
deps: List[str] = []
|
233
|
+
for k_node, v_node in zip(value.keys, value.values):
|
234
|
+
k_str = _literal(k_node)
|
235
|
+
if not isinstance(k_str, (str, int, float, bool)):
|
236
|
+
k_str = str(k_str)
|
237
|
+
keys.append(str(k_str))
|
238
|
+
if isinstance(v_node, ast.Name):
|
239
|
+
deps.append(_ssa_get(v_node.id))
|
240
|
+
elif isinstance(v_node, ast.Await):
|
241
|
+
inner = v_node.value
|
242
|
+
if not isinstance(inner, ast.Call):
|
243
|
+
raise DSLParseError("await must wrap a call in dict value")
|
244
|
+
tmp_id = _emit_assign_from_call(f"{var_name}_field", inner)
|
245
|
+
deps.append(tmp_id)
|
246
|
+
elif isinstance(v_node, ast.Call):
|
247
|
+
tmp_id = _emit_assign_from_call(f"{var_name}_field", v_node)
|
248
|
+
deps.append(tmp_id)
|
249
|
+
else:
|
250
|
+
# Synthesize const for literal value
|
251
|
+
lit_val = _literal(v_node)
|
252
|
+
tmp = _ssa_new(f"{var_name}_lit")
|
253
|
+
ops.append({
|
254
|
+
"id": tmp,
|
255
|
+
"op": "CONST.value",
|
256
|
+
"deps": [],
|
257
|
+
"args": {"value": lit_val},
|
258
|
+
})
|
259
|
+
deps.append(tmp)
|
260
|
+
ssa = _ssa_new(var_name)
|
261
|
+
ops.append({
|
262
|
+
"id": ssa,
|
263
|
+
"op": "PACK.dict",
|
264
|
+
"deps": deps,
|
265
|
+
"args": {"keys": keys},
|
266
|
+
})
|
267
|
+
return ssa
|
225
268
|
raise
|
226
269
|
|
227
270
|
def _emit_assign_from_comp(var_name: str, node: ast.AST) -> str:
|
@@ -310,7 +353,8 @@ def parse(source: str, function_name: Optional[str] = None) -> Dict[str, Any]:
|
|
310
353
|
raise DSLParseError("output requires as=\"filename\"")
|
311
354
|
outputs.append({"from": ssa_from, "as": filename})
|
312
355
|
else:
|
313
|
-
|
356
|
+
# General expression call: represent as an op node too
|
357
|
+
_emit_expr_call(call)
|
314
358
|
return None
|
315
359
|
elif isinstance(stmt, ast.Return):
|
316
360
|
if isinstance(stmt.value, ast.Name):
|
@@ -411,6 +455,29 @@ def parse(source: str, function_name: Optional[str] = None) -> Dict[str, Any]:
|
|
411
455
|
ctx_counts["loop"] += 1
|
412
456
|
context_suffix = f"loop{ctx_counts['loop']}"
|
413
457
|
versions, latest = versions_body, latest_body
|
458
|
+
# Predefine loop target variables as items from iterator for dependency resolution
|
459
|
+
def _bind_loop_target(target: ast.AST):
|
460
|
+
if isinstance(target, ast.Name):
|
461
|
+
ssa_item = _ssa_new(target.id)
|
462
|
+
ops.append({
|
463
|
+
"id": ssa_item,
|
464
|
+
"op": "ITER.item",
|
465
|
+
"deps": [iter_id],
|
466
|
+
"args": {"target": target.id},
|
467
|
+
})
|
468
|
+
elif isinstance(target, ast.Tuple):
|
469
|
+
for elt in target.elts:
|
470
|
+
if isinstance(elt, ast.Name):
|
471
|
+
ssa_item = _ssa_new(elt.id)
|
472
|
+
ops.append({
|
473
|
+
"id": ssa_item,
|
474
|
+
"op": "ITER.item",
|
475
|
+
"deps": [iter_id],
|
476
|
+
"args": {"target": elt.id},
|
477
|
+
})
|
478
|
+
# Other patterns are ignored for now
|
479
|
+
|
480
|
+
_bind_loop_target(stmt.target)
|
414
481
|
for inner in stmt.body:
|
415
482
|
_parse_stmt(inner)
|
416
483
|
versions_body, latest_body = versions, latest
|
@@ -419,6 +486,16 @@ def parse(source: str, function_name: Optional[str] = None) -> Dict[str, Any]:
|
|
419
486
|
# Add iter dep to first op in body
|
420
487
|
if len(ops) > body_ops_start:
|
421
488
|
ops[body_ops_start]["deps"] = [*ops[body_ops_start].get("deps", []), iter_id]
|
489
|
+
# Emit a summary foreach comp node depending on iterable value deps
|
490
|
+
iter_name_deps = _collect_value_deps(stmt.iter)
|
491
|
+
foreach_deps = [_ssa_get(n) for n in iter_name_deps]
|
492
|
+
ssa_foreach = _ssa_new("foreach")
|
493
|
+
ops.append({
|
494
|
+
"id": ssa_foreach,
|
495
|
+
"op": "COMP.foreach",
|
496
|
+
"deps": foreach_deps,
|
497
|
+
"args": {"target": t_label or ""},
|
498
|
+
})
|
422
499
|
# Loop-carried vars: only those existing pre-loop and reassigned in body
|
423
500
|
changed = {k for k in latest_body if pre_latest.get(k) != latest_body.get(k)}
|
424
501
|
carried = [k for k in changed if k in pre_latest]
|
@@ -461,7 +538,7 @@ def parse(source: str, function_name: Optional[str] = None) -> Dict[str, Any]:
|
|
461
538
|
"args": {"var": var},
|
462
539
|
})
|
463
540
|
return None
|
464
|
-
elif isinstance(stmt, (ast.Pass,)):
|
541
|
+
elif isinstance(stmt, (ast.Pass, ast.Continue, ast.Break)):
|
465
542
|
return None
|
466
543
|
else:
|
467
544
|
raise DSLParseError("Only assignments, control flow, settings/output calls, and return are allowed in function body")
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|