Compile Python scripts and notebooks into Texera workflows
- 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
Assessment
This issue has not been assessed yet.