apache / apache/texera

Compile Python scripts and notebooks into Texera workflows

Open
#8,319 3 comments 0 reactions 1 assignee Claimed by @carloea2 View on GitHub
Dominant language
Scala
Stars
314
Forks
187
Avg merge
1d 21h
Merged PRs (30d)
214

Description

## Feature Summary

Texera users currently need to rewrite Python programs manually as workflows. This feature adds a compiler that accepts a Python file or the code cells of a Jupyter notebook and produces an ordinary Texera workflow composed of Python UDF operators.

The initial delivery intentionally supports a restricted, statically analyzable subset of module-level Python. Compilation does not execute user code.

Each accepted top-level statement is an indivisible evaluation unit. The placement strategy may combine multiple contiguous statements into one operator, but it does not decompose expressions or compound statement bodies.

### Initial language scope

| Supported | Rejected with a source-located diagnostic |
| --- | --- |
| `.py` source files | `if`, `for`, `while`, `try`, `with`, and `match` |
| Nonempty code cells from `.ipynb` files | Function, asynchronous function, class, and lambda definitions |
| Absolute imports | Relative, wildcard, and `__future__` imports |
| Assignments, annotated assignments, and augmented assignments | `return`, `raise`, `yield`, `await`, `global`, and `nonlocal` |
| Top-level expression statements and ordinary calls | `assert`, `break`, `continue`, `delete`, and assignment expressions |
| Ordinary literals, indexing, attributes, arithmetic, and comparisons | Comprehensions, generators, conditional expressions, and `and`/`or` |
| Required downstream Python values | Reflective calls such as `eval`, `exec`, `globals`, and `locals` |

For notebooks, nonempty code cells are concatenated in notebook order and passed through the same compiler path as a Python module. Markdown cells and stored outputs are ignored. Notebook magics, shell commands, and `get_ipython` forms are outside the initial scope.

## Proposed Solution or Design

```text
.py source or normalized .ipynb code cells
|
v
ADMIT
|
v
ANALYZE -> GROUP -> VERIFY -> BUILD
|
v
ordinary Texera workflow JSON
|
v
standard Amber execution
```

| Phase | Responsibility |
| --- | --- |
| Admit | Parse the source and reject unsupported constructs with their source location |
| Analyze | Build the source representation and derive bindings, aliases, effects, liveness, and statement dependencies |
| Group | Propose contiguous groups of complete top-level statements |
| Verify | Confirm that every group is locally reconstructable and every boundary has a valid transport realization |
| Build | Generate Python UDF source, ports, links, positions, and ordinary Texera workflow JSON |
| Execute | Run the generated Python UDF operators through the standard Amber execution path |

The default placement strategy targets:

```text
min(statement count, ceil(sqrt(physical source LOC)))
```

groups. This is a target rather than a guarantee: the compiler may produce fewer groups when there are not enough legal dependency-preserving seams. Grouping is deterministic, contiguous, and must leave the physical workflow acyclic.

A one-statement-per-operator strategy is retained as a diagnostic baseline.

Values required by downstream operators are transported through a Cloudpickle envelope. The transport preserves object aliases and cycles within each boundary payload. The generated workflow does not serialize the complete Python namespace.

### Acceptance criteria

- A supported `.py` program produces importable Texera workflow JSON.
- Notebook code cells use the same compiler and verification pipeline as `.py` source.
- Unsupported syntax is rejected before workflow generation with the construct and source location.
- The default placement is deterministic and respects the `sqrt(LOC)` target when legal seams permit it.
- Every generated operator contains complete top-level statements.
- No expression or control-flow body is distributed across operators.
- Required downstream values are transported without duplicating their analysis in the renderer.
- Generated workflows execute through real Amber Python workers.
- Representative linear data-science programs produce the same observable output under Python and the generated workflow.
- Compiler rejections return HTTP 422 with a safe diagnostic.
- Invalid requests return HTTP 400.
- Operational compiler failures return a generic HTTP 500 response while detailed information remains in server logs.
- The frontend can upload `.py` and `.ipynb` files, create the generated workflow, and display compiler diagnostics.
- The deployed migration service contains the compiler and its required runtime packages.

Related discussion: #8160

### Delivery plan

Every PR includes its directly related positive, negative, and boundary tests. The estimates are review budgets, not permission to exceed the hard limit of 999 changed lines.

| # | PR scope | Budget | Depends on |
| ---: | --- | ---: | --- |
| 1 | [Preserve PyAmber channel-marker port provenance](https://github.com/apache/texera/pull/8432) | 300 | — |
| 2 | [Add the PyTexera Cloudpickle boundary envelope codec](https://github.com/apache/texera/pull/8433) | 300 | — |
| 3 | Add the PyTexera heap, ports, driver runtime, and tuple operator support | 900 | 2 |
| 4 | Add compiler packaging, source types, and core immutable models | 850 | — |
| 5 | Add linear-source admission and source-located diagnostics | 450 | 4 |
| 6 | Add source-forest structural types, indexes, and templates | 900 | 4 |
| 7 | Extract syntax occurrences and expression parameters | 900 | 6 |
| 8 | Extract top-level statements, names, reads, and writes | 850 | 7 |
| 9 | Build and validate the complete source forest and graph | 950 | 8 |
| 10 | Add binding identities, lexical scopes, and entry bindings | 900 | 9 |
| 11 | Add the alias domain and constraint collection | 950 | 10 |
| 12 | Add the points-to fixed-point solver | 850 | 11 |
| 13 | Add alias access paths and source-alias interpretation | 900 | 12 |
| 14 | Add statement states and binding-flow analysis | 850 | 13 |
| 15 | Add effects and transfer knowledge | 950 | 14 |
| 16 | Add import, call, and entry-graph resolution | 900 | 15 |
| 17 | Add liveness, linearization, and dependency analysis | 900 | 16 |
| 18 | Derive and validate statement-level evaluation atoms | 900 | 17 |
| 19 | Build the coloring problem and carrier availability model | 850 | 18 |
| 20 | Add the statement placement view and deterministic strategies | 750 | 19 |
| 21 | Add realization contracts, profiles, and selection records | 900 | 20, 3 |
| 22 | Add native internal realization of complete statements | 900 | 21 |
| 23 | Add the Cloudpickle Python-value boundary realization | 750 | 21, 2 |
| 24 | Add import, annotation, state, and ordering realizations | 900 | 23 |
| 25 | Add the checker, compiler configuration, and analysis session | 950 | 22, 24 |
| 26 | Construct the verified physical workflow plan | 650 | 25 |
| 27 | Compose and render generated Python UDF programs | 900 | 26, 3 |
| 28 | Add workflow JSON generation, public API, and CLI | 950 | 27 |
| 29 | Package the compiler wheel and sbt module | 800 | 28 |
| 30 | Add the isolated migration-service compiler endpoint | 900 | 29 |
| 31 | Include the compiler in the service image and local development path | 700 | 30 |
| 32 | Add the frontend compiler tab, uploads, and diagnostics | 900 | 30 |
| 33 | Wire and validate real Amber end-to-end execution | 800 | 1, 3, 28 |

If a prepared diff reaches 1,000 changed lines, that PR is split before publication.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.