From d6a240f37371279104fb44c2c83898cdf4afc7c2 Mon Sep 17 00:00:00 2001 From: Joshua Wink Date: Sat, 10 Oct 2026 15:21:22 -0500 Subject: [PATCH] refactor!: the Python module codeupipe.lower is now codeupipe.compile One name for one thing. The module was "lower", the documents said "export", and the config key was "compile". All three are now "compile", as in the TypeScript package. - python -m codeupipe.lower is python -m codeupipe.compile. - docs/static-export.md is docs/compile.md. - The documents say "compile", "compiled code", "fast mode" and "observable mode". - tests/lower is tests/compile. Not changed: the --lowering option and the lowering key of the config file (steps or inline), and the names inside the module, such as build_export_pipeline_v2. BREAKING CHANGE: an import of codeupipe.lower, and the command python -m codeupipe.lower, must use codeupipe.compile. Co-Authored-By: Claude Opus 5.5 --- README.md | 14 ++-- conformance/API.md | 4 +- conformance/BENCH.md | 8 +-- conformance/MATRIX.md | 10 +-- conformance/README.md | 8 +-- conformance/run.py | 4 +- .../runners/python/conformance_sink.py | 2 +- conformance/runners/python/runner.py | 8 +-- docs/{static-export.md => compile.md} | 64 +++++++++---------- docs/config.md | 2 +- examples/pricing/__init__.py | 2 +- packages/codeupipe-compile-ts/README.md | 6 +- packages/codeupipe-lint/README.md | 2 +- packages/codeupipe-ts/README.md | 2 +- packages/codeupipe/README.md | 4 +- packages/codeupipe/codeupipe/__init__.py | 2 +- .../codeupipe/{lower => compile}/__init__.py | 0 .../codeupipe/{lower => compile}/__main__.py | 8 +-- .../codeupipe/{lower => compile}/errors.py | 0 .../{lower => compile}/filters/__init__.py | 0 .../filters/emit_inline_module_filter.py | 0 .../filters/emit_orchestrator_filter.py | 0 .../filters/emit_plain_files_filter.py | 0 .../filters/load_pipeline_filter.py | 0 .../filters/lower_control_flow_filter.py | 0 .../filters/parse_filter_source_filter.py | 0 .../filters/rewrite_payload_ops_filter.py | 0 .../codeupipe/{lower => compile}/ir.py | 0 .../{lower => compile}/pipelines/__init__.py | 0 .../pipelines/export_pipeline.py | 2 +- .../pipelines/lowering_mode_predicate.py | 0 .../{lower => compile}/resolve_target.py | 0 .../{lower => compile}/taps/__init__.py | 0 .../taps/write_files_tap.py | 0 packages/codeupipe/codeupipe/core/README.md | 4 +- scorecard/README.md | 12 ++-- scorecard/vocab.py | 2 +- tests/{lower => compile}/__init__.py | 0 tests/{lower => compile}/fixtures/__init__.py | 0 .../fixtures/cli_targets.py | 6 +- .../fixtures/export_module_globals.py | 0 .../fixtures/inline_shapes.py | 0 .../fixtures/instance_config.py | 0 tests/{lower => compile}/fixtures/plane_b.py | 0 .../fixtures/typed_steps.py | 0 tests/{lower => compile}/test_cli.py | 10 +-- .../test_emit_inline_module_filter.py | 2 +- .../test_emit_orchestrator_filter.py | 4 +- .../test_emit_plain_files_filter.py | 4 +- tests/{lower => compile}/test_errors.py | 2 +- .../test_export_instance_config.py | 4 +- .../test_export_module_globals.py | 4 +- .../{lower => compile}/test_export_observe.py | 10 +-- .../test_export_pipeline.py | 2 +- .../test_export_refusals.py | 6 +- .../test_export_typed_steps.py | 8 +-- tests/{lower => compile}/test_ir.py | 2 +- .../test_load_pipeline_filter.py | 6 +- .../test_lower_control_flow_filter.py | 6 +- .../test_parse_filter_source_filter.py | 6 +- .../test_per_filter_imports.py | 2 +- .../test_rewrite_payload_ops_filter.py | 6 +- .../test_write_files_tap.py | 2 +- tests/config/test_config.py | 4 +- tests/examples/test_pricing.py | 2 +- .../anonymous_steps/test_repo_is_clean.py | 4 +- 66 files changed, 136 insertions(+), 136 deletions(-) rename docs/{static-export.md => compile.md} (76%) rename packages/codeupipe/codeupipe/{lower => compile}/__init__.py (100%) rename packages/codeupipe/codeupipe/{lower => compile}/__main__.py (93%) rename packages/codeupipe/codeupipe/{lower => compile}/errors.py (100%) rename packages/codeupipe/codeupipe/{lower => compile}/filters/__init__.py (100%) rename packages/codeupipe/codeupipe/{lower => compile}/filters/emit_inline_module_filter.py (100%) rename packages/codeupipe/codeupipe/{lower => compile}/filters/emit_orchestrator_filter.py (100%) rename packages/codeupipe/codeupipe/{lower => compile}/filters/emit_plain_files_filter.py (100%) rename packages/codeupipe/codeupipe/{lower => compile}/filters/load_pipeline_filter.py (100%) rename packages/codeupipe/codeupipe/{lower => compile}/filters/lower_control_flow_filter.py (100%) rename packages/codeupipe/codeupipe/{lower => compile}/filters/parse_filter_source_filter.py (100%) rename packages/codeupipe/codeupipe/{lower => compile}/filters/rewrite_payload_ops_filter.py (100%) rename packages/codeupipe/codeupipe/{lower => compile}/ir.py (100%) rename packages/codeupipe/codeupipe/{lower => compile}/pipelines/__init__.py (100%) rename packages/codeupipe/codeupipe/{lower => compile}/pipelines/export_pipeline.py (97%) rename packages/codeupipe/codeupipe/{lower => compile}/pipelines/lowering_mode_predicate.py (100%) rename packages/codeupipe/codeupipe/{lower => compile}/resolve_target.py (100%) rename packages/codeupipe/codeupipe/{lower => compile}/taps/__init__.py (100%) rename packages/codeupipe/codeupipe/{lower => compile}/taps/write_files_tap.py (100%) rename tests/{lower => compile}/__init__.py (100%) rename tests/{lower => compile}/fixtures/__init__.py (100%) rename tests/{lower => compile}/fixtures/cli_targets.py (73%) rename tests/{lower => compile}/fixtures/export_module_globals.py (100%) rename tests/{lower => compile}/fixtures/inline_shapes.py (100%) rename tests/{lower => compile}/fixtures/instance_config.py (100%) rename tests/{lower => compile}/fixtures/plane_b.py (100%) rename tests/{lower => compile}/fixtures/typed_steps.py (100%) rename tests/{lower => compile}/test_cli.py (93%) rename tests/{lower => compile}/test_emit_inline_module_filter.py (99%) rename tests/{lower => compile}/test_emit_orchestrator_filter.py (93%) rename tests/{lower => compile}/test_emit_plain_files_filter.py (95%) rename tests/{lower => compile}/test_errors.py (95%) rename tests/{lower => compile}/test_export_instance_config.py (96%) rename tests/{lower => compile}/test_export_module_globals.py (96%) rename tests/{lower => compile}/test_export_observe.py (97%) rename tests/{lower => compile}/test_export_pipeline.py (99%) rename tests/{lower => compile}/test_export_refusals.py (95%) rename tests/{lower => compile}/test_export_typed_steps.py (91%) rename tests/{lower => compile}/test_ir.py (98%) rename tests/{lower => compile}/test_load_pipeline_filter.py (89%) rename tests/{lower => compile}/test_lower_control_flow_filter.py (87%) rename tests/{lower => compile}/test_parse_filter_source_filter.py (92%) rename tests/{lower => compile}/test_per_filter_imports.py (97%) rename tests/{lower => compile}/test_rewrite_payload_ops_filter.py (98%) rename tests/{lower => compile}/test_write_files_tap.py (95%) diff --git a/README.md b/README.md index bc89b96..56f1834 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ This repository has five packages. | Package | Contents | Reference | |---|---|---| -| `codeupipe` | The eight primitives. An export command that writes a pipeline as plain Python with no import of codeupipe. A config file reader. No dependencies | [conformance/API.md](conformance/API.md), [docs/static-export.md](docs/static-export.md), [docs/config.md](docs/config.md) | +| `codeupipe` | The eight primitives. A compile command that writes a pipeline as plain Python with no import of codeupipe. A config file reader. No dependencies | [conformance/API.md](conformance/API.md), [docs/compile.md](docs/compile.md), [docs/config.md](docs/config.md) | | `codeupipe-lint` | Two linters for pipeline code. Depends on `codeupipe` only | [packages/codeupipe-lint/README.md](packages/codeupipe-lint/README.md) | | `codeupipe` for TypeScript | The eight primitives. No dependencies | [packages/codeupipe-ts/README.md](packages/codeupipe-ts/README.md) | | `codeupipe-lint` for TypeScript | A linter for pipeline code in TypeScript | [packages/codeupipe-lint-ts/README.md](packages/codeupipe-lint-ts/README.md) | @@ -154,18 +154,18 @@ An editable install needs pip 21.3 or later. | Command | What it does | |---|---| | `python -m pytest tests -q` | Runs the tests | -| `python conformance/run.py` | Runs the 27 conformance cases against the Python dynamic run and the three exports, and against the TypeScript targets that the machine can run | +| `python conformance/run.py` | Runs the 27 conformance cases against the Python dynamic run and the three compiled forms, and against the TypeScript targets that the machine can run | | `python -m codeupipe_lint.anonymous_steps` | Runs the anonymous-step linter. Paths come from `cup.config.json` | | `python -m codeupipe_lint.invariants` | Runs the invariant linter. Paths come from `cup.config.json` | -| `python -m codeupipe.lower examples.pricing.pricing_pipeline:PricingPipeline --out build/pricing` | Exports the example to `build/pricing/src/steps/` | +| `python -m codeupipe.compile examples.pricing.pricing_pipeline:PricingPipeline --out build/pricing` | Compiles the example to `build/pricing/src/steps/` | | `python conformance/bench.py --check` | Compares benchmark numbers with the recorded baseline. Fails outside 25% | -| `python -m scorecard.differential` | Compares the export with the dynamic run on random pipelines | +| `python -m scorecard.differential` | Compares the compiled code with the dynamic run on random pipelines | ## Layout | Path | Contents | |---|---| -| `packages/codeupipe/` | The `codeupipe` package: `core/`, `lower/` (the export), `config.py` | +| `packages/codeupipe/` | The `codeupipe` package: `core/`, `compile/` (the compiler), `config.py` | | `packages/codeupipe-lint/` | The `codeupipe-lint` package: `anonymous_steps/`, `invariants/` | | `packages/codeupipe-ts/` | The TypeScript runtime, with its tests and its example | | `packages/codeupipe-lint-ts/` | The TypeScript linter, with its tests | @@ -173,8 +173,8 @@ An editable install needs pip 21.3 or later. | `conformance/` | The contract ([API.md](conformance/API.md)), the cases, the runners, the benchmark | | `tests/` | The tests for the two Python packages | | `examples/pricing/` | The example, with its test in `tests/examples/` | -| `scorecard/` | The comparison of the export with the dynamic run on random pipelines | -| `docs/` | Reference for the export and the config file | +| `scorecard/` | The comparison of the compiled code with the dynamic run on random pipelines | +| `docs/` | Reference for the compiler and the config file | The root `pyproject.toml` is not a package. It holds the test settings. diff --git a/conformance/API.md b/conformance/API.md index 7d8778a..064b5db 100644 --- a/conformance/API.md +++ b/conformance/API.md @@ -190,7 +190,7 @@ and limits: **Conformance.** The shared cases name their steps; the runner builds every step, so it maps each reported label back to the case's step name. A label -that is wrong, or differs between the dynamic run and an export, does not +that is wrong, or differs between the dynamic run and compiled code, does not map and fails the comparison. ## Not in the contract yet @@ -213,7 +213,7 @@ map and fails the comparison. | Run | `run` is sync. `run_async` is opt-in | One `run`. It returns a Promise. A step can be sync or async | | Absent | `None` | `null` | | Label of a step | `type(step).__name__` | `step.constructor.name` | -| Export | `codeupipe.lower` | `packages/codeupipe-compile-ts` | +| Compile | `codeupipe.compile` | `packages/codeupipe-compile-ts` | | Linter | `packages/codeupipe-lint` | `packages/codeupipe-lint-ts` | Notes on TypeScript: diff --git a/conformance/BENCH.md b/conformance/BENCH.md index c1cdaad..a9c241e 100644 --- a/conformance/BENCH.md +++ b/conformance/BENCH.md @@ -10,8 +10,8 @@ compares are in `bench/baseline.json` (`python conformance/bench.py --check`, [README.md](README.md)). `python:run` is the dynamic run. The three `static-*` targets are the -exports: `static-observe` records State and calls Hooks as `run` does; the -two fast exports do neither, and refuse the `hook` scenario rather than +compiles: `static-observe` records State and calls Hooks as `run` does; the +two fast modes do neither, and refuse the `hook` scenario rather than silently dropping the Hook. µs per run (best of 5 × 20,000, after 20,000 warmup runs); lower is better. @@ -25,5 +25,5 @@ silently dropping the Hook. | `heavy-allocation` | 50 | 17.14 | 2.80 | 1.49 | 7.22 | Not measured (the target refuses the scenario): -- python:static-steps hook: UnsupportedFilterShape: .call at line 0:0 — cannot lower Hook. Hint: Hooks do not run in the fast static export. Export with observe=True (top-level Hooks only), or remove them. -- python:static-inline hook: UnsupportedFilterShape: .call at line 0:0 — cannot lower Hook. Hint: Hooks do not run in the fast static export. Export with observe=True (top-level Hooks only), or remove them. +- python:static-steps hook: UnsupportedFilterShape: .call at line 0:0 — cannot lower Hook. Hint: Hooks do not run in the fast mode. Compile with observe=True (top-level Hooks only), or remove them. +- python:static-inline hook: UnsupportedFilterShape: .call at line 0:0 — cannot lower Hook. Hint: Hooks do not run in the fast mode. Compile with observe=True (top-level Hooks only), or remove them. diff --git a/conformance/MATRIX.md b/conformance/MATRIX.md index 8db7cd3..b336629 100644 --- a/conformance/MATRIX.md +++ b/conformance/MATRIX.md @@ -5,14 +5,14 @@ live copy is `results/latest.md` (not committed). The command exits non-zero if any target has a ❌. **Every target passes every case, and nothing is unsupported.** The targets -are the Python dynamic run, async run and three static exports, and the +are the Python dynamic run, async run and three compiled forms, and the TypeScript run and its compiled form. -The fast exports (`python:static-steps`, `python:static-inline`, +The fast modes (`python:static-steps`, `python:static-inline`, `typescript:static`) expose no State or Hooks, so they pass those cases as -✅\*. `static-observe` (export with +✅\*. `static-observe` (compile with `observe=True`) records both and passes every case outright. See -[docs/static-export.md](../docs/static-export.md). +[docs/compile.md](../docs/compile.md). | case | python:run | python:run_async | python:static-steps | python:static-inline | python:static-observe | typescript:run | typescript:static | |---|---|---|---|---|---|---|---| @@ -52,4 +52,4 @@ The fast exports (`python:static-steps`, `python:static-inline`, - **typescript:run**: 27 pass, 0 pass*, 0 fail, 0 unsupported - **typescript:static**: 11 pass, 16 pass*, 0 fail, 0 unsupported -✅* passed everything the target can observe; it does not expose State or Hooks (the fast static export). ➖ the target cannot express the case. +✅* passed everything the target can observe; it does not expose State or Hooks (the fast mode). ➖ the target cannot express the case. diff --git a/conformance/README.md b/conformance/README.md index 9d1f338..a489f06 100644 --- a/conformance/README.md +++ b/conformance/README.md @@ -4,7 +4,7 @@ The rules are in **[API.md](API.md)**, the CUP API contract. This suite checks them. One set of language-neutral cases, a runner, and **one judge** (`run.py`). -The dynamic run and each static export are held to exactly the same +The dynamic run and each compiled form are held to exactly the same comparison. ```bash @@ -40,8 +40,8 @@ load a number can leave the band. | Target | How it runs (all offline) | |---|---| | `python:run`, `python:run_async` | `codeupipe.core` Pipeline, sync and async entry points | -| `python:static-steps`, `python:static-inline` | `codeupipe.lower` fast export, loaded from disk (no State or Hooks: ✅\*) | -| `python:static-observe` | `codeupipe.lower` export with `observe=True`: State and Hooks judged too | +| `python:static-steps`, `python:static-inline` | `codeupipe.compile` fast mode, loaded from disk (no State or Hooks: ✅\*) | +| `python:static-observe` | `codeupipe.compile` with `observe=True`: State and Hooks judged too | | `typescript:run` | `packages/codeupipe-ts` Pipeline. Node runs the `.ts` runner as it is (Node 22.18 or later). With no arguments, `run.py` leaves this target out when the machine has no such Node | | `typescript:static` | `packages/codeupipe-compile-ts`: the pipeline as plain code, written to a file and imported (no State or Hooks: ✅\*). Needs `npm ci` in that package and a built core package; `run.py` leaves it out when they are not there | @@ -52,7 +52,7 @@ load a number can leave the band. | ✅ | every expectation matched | | ✅* | everything the target *can observe* matched. Static code has no State or Hooks, so those checks cannot run | | ❌ | something observable differed | -| ➖ | the target cannot express the case (e.g. export refuses a nested pipeline). Never counted as a pass | +| ➖ | the target cannot express the case (e.g. the compiler refuses a nested pipeline). Never counted as a pass | ## Case format (`cases/*.json`) diff --git a/conformance/run.py b/conformance/run.py index a502af7..59da284 100644 --- a/conformance/run.py +++ b/conformance/run.py @@ -15,7 +15,7 @@ partial every expectation the target can observe matched, but some (State, Hooks) it does not expose at all (fast static code) FAIL something observable differed (details in the JSON report) - unsupported the target cannot express the case (e.g. static export of a + unsupported the target cannot express the case (e.g. compiled form of a nested pipeline); reported, never counted as a pass """ @@ -221,7 +221,7 @@ def _markdown(cases, names, matrix, report): f"{t['unsupported']} unsupported") lines.append("") lines.append("✅* passed everything the target can observe; it does not expose State or Hooks " - "(the fast static export). ➖ the target cannot express the case.") + "(the fast mode). ➖ the target cannot express the case.") return "\n".join(lines) + "\n" diff --git a/conformance/runners/python/conformance_sink.py b/conformance/runners/python/conformance_sink.py index e815e87..89b2a56 100644 --- a/conformance/runners/python/conformance_sink.py +++ b/conformance/runners/python/conformance_sink.py @@ -4,7 +4,7 @@ ``from conformance_sink import TAPS`` as an import, so every lowered step appends to this one list. A list defined next to the ops would be *copied* into each lowered step instead (see the known limitation in -packages/codeupipe/codeupipe/lower/filters/emit_inline_module_filter.py). +packages/codeupipe/codeupipe/compile/filters/emit_inline_module_filter.py). """ TAPS = [] diff --git a/conformance/runners/python/runner.py b/conformance/runners/python/runner.py index 323c2be..37b5859 100644 --- a/conformance/runners/python/runner.py +++ b/conformance/runners/python/runner.py @@ -5,9 +5,9 @@ Targets run codeupipe Pipeline.run (sync, the default) run_async codeupipe Pipeline.run_async (inside asyncio.run) - static-steps codeupipe.lower export, per-step layout, loaded from disk - static-inline codeupipe.lower export, lowering="inline", loaded from disk - static-observe codeupipe.lower export, observe=True: State and Hooks too + static-steps codeupipe.compile export, per-step layout, loaded from disk + static-inline codeupipe.compile export, lowering="inline", loaded from disk + static-observe codeupipe.compile export, observe=True: State and Hooks too The runner never judges; conformance/run.py compares every target's results against the same expectations. The fast static targets have no State or @@ -183,7 +183,7 @@ def _dynamic(case, predicates, run_async=False): def _load_export(p, lowering, observe, workdir): """Export ``p`` and import the package from disk, as a customer would.""" - from codeupipe.lower import build_export_pipeline_v2 + from codeupipe.compile import build_export_pipeline_v2 out = build_export_pipeline_v2(write=False).run( Payload({"pipeline": p, "pattern": "flat", "lowering": lowering, "observe": observe})) diff --git a/docs/static-export.md b/docs/compile.md similarity index 76% rename from docs/static-export.md rename to docs/compile.md index ca02191..e2b6dbf 100644 --- a/docs/static-export.md +++ b/docs/compile.md @@ -1,18 +1,18 @@ -# Static export: what it guarantees +# Compile: what it guarantees -`codeupipe.lower` turns a live `Pipeline` into plain Python with no framework -import. This page says what the export lowers, what it refuses, and what -the exported code does not have. +`codeupipe.compile` turns a live `Pipeline` into plain Python with no framework +import. This page says what the compiler lowers, what it refuses, and what +the compiled code does not have. -**The rule: anything that exports behaves the same as the dynamic `run`. -Anything that cannot is refused at export time, with the step named.** A -shape that exports "successfully" and then behaves differently is a bug. +**The rule: anything that compiles behaves the same as the dynamic `run`. +Anything that cannot is refused at compile time, with the step named.** A +shape that compiles "successfully" and then behaves differently is a bug. -There are two exports. Pick per pipeline: +There are two modes. Pick per pipeline: | | fast (default) | observable (`observe=True`) | |---|---|---| -| exported entry point | `run(data)` | `run(data, state=None, hooks=None, timing=False, trace_id=None)` | +| compiled entry point | `run(data)` | `run(data, state=None, hooks=None, timing=False, trace_id=None)` | | output | same as dynamic | same as dynamic | | State (executed, skipped, errors, timings) | no | yes, into the `state` dict | | Hooks | refused | yes, same order as dynamic | @@ -22,7 +22,7 @@ There are two exports. Pick per pipeline: | 10 filters + a Hook (dynamic: 5.96) | refused | 3.03 | ```python -from codeupipe.lower import build_export_pipeline_v2 +from codeupipe.compile import build_export_pipeline_v2 out = build_export_pipeline_v2(write=False).run(Payload({ "pipeline": pipeline, @@ -34,9 +34,9 @@ out.get("files") # [{"path": ..., "content": ...}], exposing run(di ## From the command line ```bash -python -m codeupipe.lower app.pipelines:checkout --out build/checkout -python -m codeupipe.lower app.pipelines:checkout --out build/checkout --lowering inline -python -m codeupipe.lower app.pipelines:checkout --out build/checkout --observe +python -m codeupipe.compile app.pipelines:checkout --out build/checkout +python -m codeupipe.compile app.pipelines:checkout --out build/checkout --lowering inline +python -m codeupipe.compile app.pipelines:checkout --out build/checkout --observe ``` `module:name` is a `Pipeline`, a function that builds one, or a named @@ -46,16 +46,16 @@ file written is printed. A directory that is not empty is refused unless steps deleted from the pipeline leave their old modules behind). With no `module:name`, every pipeline listed under `compile` in -`cup.config.json` is exported ([config.md](config.md)). +`cup.config.json` is compiled ([config.md](config.md)). -Exit code: **0** exported, **1** refused (the message names the step and the +Exit code: **0** compiled, **1** refused (the message names the step and the fix), **2** the command could not run. Nothing is written on 1 or 2. Tests: -[tests/lower/test_cli.py](../tests/lower/test_cli.py). +[tests/compile/test_cli.py](../tests/compile/test_cli.py). -## Step labels in exported code +## Step labels in compiled code A step has a label, the name of its class (`Validate`, `Validate#2` from the -second use; conformance/API.md). A label is not an identifier, so exported +second use; conformance/API.md). A label is not an identifier, so compiled code never uses it as a name: each step gets a generated module and function, `step_01_validate`, `step_02_validate`, and the label appears only as a string in State and in Hook calls. That also rules out @@ -71,7 +71,7 @@ generated `run()` (scorecard findings F3–F8). | Tap (`observe`) | the call wrapped in `try/except Exception` (Plane B: never halts) | conformance, `test_export_pipeline` | | Nested Pipeline (a named `Pipeline` type) | its steps flattened in place; reported as the one nesting step | conformance, `test_export_pipeline` | | Literal instance settings (`self.key` holding a str, number, ...) | compiled in as constants | `test_export_instance_config` | -| Type hints on a step (`Payload[Reads] -> Payload[Writes]`, hinted locals) | erased: exported code carries no hints and never imports their names | `test_export_typed_steps` | +| Type hints on a step (`Payload[Reads] -> Payload[Writes]`, hinted locals) | erased: compiled code carries no hints and never imports their names | `test_export_typed_steps` | | Payload ops `get insert remove merge has to_dict copy` | dict operations; a write is an in-place statement (`data[k] = v`) | `test_rewrite_payload_ops` | Evidence: all 27 conformance cases on both layouts (`python:static-steps`, @@ -79,23 +79,23 @@ Evidence: all 27 conformance cases on both layouts (`python:static-steps`, ## What is refused -`UnsupportedFilterShape` is raised at export, naming the step. Tests: -[tests/lower/test_export_refusals.py](../tests/lower/test_export_refusals.py) +`UnsupportedFilterShape` is raised at compile time, naming the step. Tests: +[tests/compile/test_export_refusals.py](../tests/compile/test_export_refusals.py) and the older shape tests beside it. | Shape | Why there is no static form | What to do | |---|---|---| -| **Hooks**, in the fast export | the fast code has no lifecycle to hook into | export with `observe=True`, or remove them | -| **Hooks on a nested pipeline**, in either export | they belong to the inner run, which is flattened away | move them to the top-level pipeline | +| **Hooks**, in the fast mode | the fast code has no lifecycle to hook into | compile with `observe=True`, or remove them | +| **Hooks on a nested pipeline**, in either mode | they belong to the inner run, which is flattened away | move them to the top-level pipeline | | `observe=True` with `lowering="inline"` (`ValueError`) | inline writes the payload in place, so a Hook holding it would see later steps' writes | use the default `steps` layout | | **Async steps** (async `call`/`observe`, Valve around one, async `test`) | static `run` is sync, as the dynamic `run` is: it raises `AsyncStepInSyncRun` on the same pipeline | make the step sync | | **`payload.trace_id`, `payload.lineage`, `payload.with_trace`** | a plain dict carries neither | keep the step dynamic | -| any other payload attribute (`payload._data`, ...) | same: only the operations above have a dict form | use an exportable operation | +| any other payload attribute (`payload._data`, ...) | same: only the operations above have a dict form | use an compilable operation | | callables or objects on `self` (filter or predicate), steps writing `self.x` | no source or literal to compile in | literal settings (predicates and filters are module-level classes anyway: the runtime refuses anything else) | -## What the fast export gives up +## What the fast mode gives up -The fast export produces the same **output**. It does not produce: +The fast mode produces the same **output**. It does not produce: - **State**: no executed / skipped / errors / timings. - **Hook calls** (refused, above). @@ -105,7 +105,7 @@ The fast export produces the same **output**. It does not produce: So conformance can judge the fast targets only on output, Taps and an unchanged caller input: they pass the State and Hook cases as ✅\* (partial). -## Observable export (`observe=True`) +## Observable mode (`observe=True`) ```python out = build_export_pipeline_v2(write=False).run(Payload({"pipeline": pipeline, "observe": True})) @@ -127,7 +127,7 @@ It reproduces the dynamic run's observable behaviour exactly, and the contract's order (conformance/API.md). They receive the **dict**, not a `Payload`: `.get` works, but treat it as read-only, and `trace_id` is on `state`, not on the data. -- **Hooks are passed at run time**, since the exported code imports no +- **Hooks are passed at run time**, since the compiled code imports no framework and cannot rebuild hook objects. If the source pipeline had Hooks, the module lists them in `SOURCE_HOOKS` and `run()` **raises `TypeError` if `hooks` is omitted**, so they cannot be lost silently. @@ -143,15 +143,15 @@ Cost: 10 filters run in 1.95 µs against 0.84 for the fast per-step layout and 4.92 for the dynamic run: about 2.5× faster than dynamic with the same State and Hooks. With a Hook attached, 3.03 µs against 5.96. -## Testing exported code +## Testing compiled code -- **Fast export:** the package is `run(dict) -> dict`, so test by output. +- **Fast mode:** the package is `run(dict) -> dict`, so test by output. The scorecard (`python -m scorecard.differential`) runs the dynamic and static forms on the same inputs and compares outputs, raised errors and input mutation. -- **Observable export:** assert on the `state` dict and on a recording Hook, +- **Observable mode:** assert on the `state` dict and on a recording Hook, exactly as you would on `pipeline.state` and a Hook in the dynamic - runtime. `tests/lower/test_export_observe.py` runs both forms side by side + runtime. `tests/compile/test_export_observe.py` runs both forms side by side and asserts they match. - `run_filter` and `assert_state` from `codeupipe.testing` target the dynamic runtime only. diff --git a/docs/config.md b/docs/config.md index a5ad3bb..286a0f7 100644 --- a/docs/config.md +++ b/docs/config.md @@ -22,7 +22,7 @@ every time. ```bash python -m codeupipe_lint.invariants # lint.paths, minus lint.exclude python -m codeupipe_lint.anonymous_steps # the same -python -m codeupipe.lower # every pipeline under compile +python -m codeupipe.compile # every pipeline under compile ``` ## Keys diff --git a/examples/pricing/__init__.py b/examples/pricing/__init__.py index 6a76565..b7a9828 100644 --- a/examples/pricing/__init__.py +++ b/examples/pricing/__init__.py @@ -14,5 +14,5 @@ used again in another pipeline. Run it: python -m examples.pricing -Export it: python -m codeupipe.lower examples.pricing.pricing_pipeline:PricingPipeline --out build/pricing +Compile it: python -m codeupipe.compile examples.pricing.pricing_pipeline:PricingPipeline --out build/pricing """ diff --git a/packages/codeupipe-compile-ts/README.md b/packages/codeupipe-compile-ts/README.md index b374175..6f2b426 100644 --- a/packages/codeupipe-compile-ts/README.md +++ b/packages/codeupipe-compile-ts/README.md @@ -99,11 +99,11 @@ also check State or Hooks pass on what the code can show. The compiled module is like one instance of the pipeline: a setting that is a list or an object is one value for every run. -## Differences from the Python export +## Differences from the Python compiler -Python has `python -m codeupipe.lower`. It reads a pipeline object that is +Python has `python -m codeupipe.compile`. It reads a pipeline object that is in memory. This compiler reads the source of a pipeline class. Python also -has an inline layout and an observable export (State and Hooks); this +has an inline layout and an observable mode (State and Hooks); this compiler has neither. ## Development diff --git a/packages/codeupipe-lint/README.md b/packages/codeupipe-lint/README.md index fb9237a..84d53f6 100644 --- a/packages/codeupipe-lint/README.md +++ b/packages/codeupipe-lint/README.md @@ -162,7 +162,7 @@ Suppress with `cup: allow-name`. **Why CUP-I003.** A Filter's result and a Valve's decision must depend only on the Payload. A step is never handed State, so the only way to read it is to hold a pipeline or a State, and that makes the step's behaviour depend on -what ran before it, which the static export cannot reproduce. Taps and Hooks +what ran before it, which the compiled form cannot reproduce. Taps and Hooks only watch, so `observe` and Hook methods are not checked. `self.state` is not flagged when it is the step's own attribute. `.state` diff --git a/packages/codeupipe-ts/README.md b/packages/codeupipe-ts/README.md index cd80dfc..d909842 100644 --- a/packages/codeupipe-ts/README.md +++ b/packages/codeupipe-ts/README.md @@ -123,7 +123,7 @@ override the methods that you need. State. `pipeline.state` is the State of the run that started last. - **The linter and the compiler are separate packages**, because they need a parser: [codeupipe-lint-ts](../codeupipe-lint-ts/) and - [codeupipe-compile-ts](../codeupipe-compile-ts/). In Python the export is + [codeupipe-compile-ts](../codeupipe-compile-ts/). In Python the compiler is in the core package. ## Labels and minified code diff --git a/packages/codeupipe/README.md b/packages/codeupipe/README.md index cef9763..7a8649f 100644 --- a/packages/codeupipe/README.md +++ b/packages/codeupipe/README.md @@ -79,7 +79,7 @@ have the method of a step. ## What is in the package - `codeupipe`: the eight primitives. -- `python -m codeupipe.lower`: writes a pipeline as plain Python with no +- `python -m codeupipe.compile`: writes a pipeline as plain Python with no import of codeupipe. - `codeupipe.config`: reads `cup.config.json`. @@ -89,7 +89,7 @@ in the repository README. ## Documentation - The contract: https://github.com/orchestrate-solutions/codeupipe/blob/main/conformance/API.md -- The export: https://github.com/orchestrate-solutions/codeupipe/blob/main/docs/static-export.md +- The compiler: https://github.com/orchestrate-solutions/codeupipe/blob/main/docs/compile.md - The config file: https://github.com/orchestrate-solutions/codeupipe/blob/main/docs/config.md - The repository: https://github.com/orchestrate-solutions/codeupipe diff --git a/packages/codeupipe/codeupipe/__init__.py b/packages/codeupipe/codeupipe/__init__.py index 02132a2..aca48bc 100644 --- a/packages/codeupipe/codeupipe/__init__.py +++ b/packages/codeupipe/codeupipe/__init__.py @@ -1,6 +1,6 @@ """codeupipe: the eight primitives, runnable two ways. -``codeupipe.core`` is the dynamic runtime. ``codeupipe.lower`` exports a +``codeupipe.core`` is the dynamic runtime. ``codeupipe.compile`` compiles a pipeline as plain code with no framework import. """ diff --git a/packages/codeupipe/codeupipe/lower/__init__.py b/packages/codeupipe/codeupipe/compile/__init__.py similarity index 100% rename from packages/codeupipe/codeupipe/lower/__init__.py rename to packages/codeupipe/codeupipe/compile/__init__.py diff --git a/packages/codeupipe/codeupipe/lower/__main__.py b/packages/codeupipe/codeupipe/compile/__main__.py similarity index 93% rename from packages/codeupipe/codeupipe/lower/__main__.py rename to packages/codeupipe/codeupipe/compile/__main__.py index f4189eb..eb23c53 100644 --- a/packages/codeupipe/codeupipe/lower/__main__.py +++ b/packages/codeupipe/codeupipe/compile/__main__.py @@ -1,6 +1,6 @@ -"""``python -m codeupipe.lower [module:name --out DIR] [--lowering steps|inline] [--observe] [--overwrite] [--config FILE]`` +"""``python -m codeupipe.compile [module:name --out DIR] [--lowering steps|inline] [--observe] [--overwrite] [--config FILE]`` -Export a Pipeline to plain Python with no framework import (docs/static-export.md). +Export a Pipeline to plain Python with no framework import (docs/compile.md). With no ``module:name``, every pipeline listed under ``compile`` in ``cup.config.json`` is exported (packages/codeupipe/codeupipe/config.py). @@ -59,8 +59,8 @@ def export(target: str, out_dir: str, lowering: str = "steps", observe: bool = F def main(argv=None) -> int: - parser = argparse.ArgumentParser(prog="python -m codeupipe.lower", - description="Export a Pipeline to plain Python (docs/static-export.md).") + parser = argparse.ArgumentParser(prog="python -m codeupipe.compile", + description="Export a Pipeline to plain Python (docs/compile.md).") parser.add_argument("target", nargs="?", help="the pipeline, as module:name (a Pipeline, a builder function, or a Pipeline type); " "omit it to export every pipeline in the config") diff --git a/packages/codeupipe/codeupipe/lower/errors.py b/packages/codeupipe/codeupipe/compile/errors.py similarity index 100% rename from packages/codeupipe/codeupipe/lower/errors.py rename to packages/codeupipe/codeupipe/compile/errors.py diff --git a/packages/codeupipe/codeupipe/lower/filters/__init__.py b/packages/codeupipe/codeupipe/compile/filters/__init__.py similarity index 100% rename from packages/codeupipe/codeupipe/lower/filters/__init__.py rename to packages/codeupipe/codeupipe/compile/filters/__init__.py diff --git a/packages/codeupipe/codeupipe/lower/filters/emit_inline_module_filter.py b/packages/codeupipe/codeupipe/compile/filters/emit_inline_module_filter.py similarity index 100% rename from packages/codeupipe/codeupipe/lower/filters/emit_inline_module_filter.py rename to packages/codeupipe/codeupipe/compile/filters/emit_inline_module_filter.py diff --git a/packages/codeupipe/codeupipe/lower/filters/emit_orchestrator_filter.py b/packages/codeupipe/codeupipe/compile/filters/emit_orchestrator_filter.py similarity index 100% rename from packages/codeupipe/codeupipe/lower/filters/emit_orchestrator_filter.py rename to packages/codeupipe/codeupipe/compile/filters/emit_orchestrator_filter.py diff --git a/packages/codeupipe/codeupipe/lower/filters/emit_plain_files_filter.py b/packages/codeupipe/codeupipe/compile/filters/emit_plain_files_filter.py similarity index 100% rename from packages/codeupipe/codeupipe/lower/filters/emit_plain_files_filter.py rename to packages/codeupipe/codeupipe/compile/filters/emit_plain_files_filter.py diff --git a/packages/codeupipe/codeupipe/lower/filters/load_pipeline_filter.py b/packages/codeupipe/codeupipe/compile/filters/load_pipeline_filter.py similarity index 100% rename from packages/codeupipe/codeupipe/lower/filters/load_pipeline_filter.py rename to packages/codeupipe/codeupipe/compile/filters/load_pipeline_filter.py diff --git a/packages/codeupipe/codeupipe/lower/filters/lower_control_flow_filter.py b/packages/codeupipe/codeupipe/compile/filters/lower_control_flow_filter.py similarity index 100% rename from packages/codeupipe/codeupipe/lower/filters/lower_control_flow_filter.py rename to packages/codeupipe/codeupipe/compile/filters/lower_control_flow_filter.py diff --git a/packages/codeupipe/codeupipe/lower/filters/parse_filter_source_filter.py b/packages/codeupipe/codeupipe/compile/filters/parse_filter_source_filter.py similarity index 100% rename from packages/codeupipe/codeupipe/lower/filters/parse_filter_source_filter.py rename to packages/codeupipe/codeupipe/compile/filters/parse_filter_source_filter.py diff --git a/packages/codeupipe/codeupipe/lower/filters/rewrite_payload_ops_filter.py b/packages/codeupipe/codeupipe/compile/filters/rewrite_payload_ops_filter.py similarity index 100% rename from packages/codeupipe/codeupipe/lower/filters/rewrite_payload_ops_filter.py rename to packages/codeupipe/codeupipe/compile/filters/rewrite_payload_ops_filter.py diff --git a/packages/codeupipe/codeupipe/lower/ir.py b/packages/codeupipe/codeupipe/compile/ir.py similarity index 100% rename from packages/codeupipe/codeupipe/lower/ir.py rename to packages/codeupipe/codeupipe/compile/ir.py diff --git a/packages/codeupipe/codeupipe/lower/pipelines/__init__.py b/packages/codeupipe/codeupipe/compile/pipelines/__init__.py similarity index 100% rename from packages/codeupipe/codeupipe/lower/pipelines/__init__.py rename to packages/codeupipe/codeupipe/compile/pipelines/__init__.py diff --git a/packages/codeupipe/codeupipe/lower/pipelines/export_pipeline.py b/packages/codeupipe/codeupipe/compile/pipelines/export_pipeline.py similarity index 97% rename from packages/codeupipe/codeupipe/lower/pipelines/export_pipeline.py rename to packages/codeupipe/codeupipe/compile/pipelines/export_pipeline.py index 17042d1..a4ca9f6 100644 --- a/packages/codeupipe/codeupipe/lower/pipelines/export_pipeline.py +++ b/packages/codeupipe/codeupipe/compile/pipelines/export_pipeline.py @@ -42,7 +42,7 @@ def build_export_pipeline_v2(*, write: bool = True) -> Pipeline: State or Hooks. True: run() also records State and calls Hooks as the dynamic run does; "steps" - layout only. docs/static-export.md + layout only. docs/compile.md Output payload keys: ``pipeline_ir`` (PipelineIR) — the canonical IR. diff --git a/packages/codeupipe/codeupipe/lower/pipelines/lowering_mode_predicate.py b/packages/codeupipe/codeupipe/compile/pipelines/lowering_mode_predicate.py similarity index 100% rename from packages/codeupipe/codeupipe/lower/pipelines/lowering_mode_predicate.py rename to packages/codeupipe/codeupipe/compile/pipelines/lowering_mode_predicate.py diff --git a/packages/codeupipe/codeupipe/lower/resolve_target.py b/packages/codeupipe/codeupipe/compile/resolve_target.py similarity index 100% rename from packages/codeupipe/codeupipe/lower/resolve_target.py rename to packages/codeupipe/codeupipe/compile/resolve_target.py diff --git a/packages/codeupipe/codeupipe/lower/taps/__init__.py b/packages/codeupipe/codeupipe/compile/taps/__init__.py similarity index 100% rename from packages/codeupipe/codeupipe/lower/taps/__init__.py rename to packages/codeupipe/codeupipe/compile/taps/__init__.py diff --git a/packages/codeupipe/codeupipe/lower/taps/write_files_tap.py b/packages/codeupipe/codeupipe/compile/taps/write_files_tap.py similarity index 100% rename from packages/codeupipe/codeupipe/lower/taps/write_files_tap.py rename to packages/codeupipe/codeupipe/compile/taps/write_files_tap.py diff --git a/packages/codeupipe/codeupipe/core/README.md b/packages/codeupipe/codeupipe/core/README.md index e4cecd4..aa22183 100644 --- a/packages/codeupipe/codeupipe/core/README.md +++ b/packages/codeupipe/codeupipe/core/README.md @@ -2,7 +2,7 @@ This package holds the eight primitives: `Payload`, `Filter`, `Predicate`, `Valve`, `Tap`, `Hook`, `State`, `Pipeline`. The contract is -[conformance/API.md](../../../../conformance/API.md). The export (`codeupipe.lower`) and the linter +[conformance/API.md](../../../../conformance/API.md). The compiler (`codeupipe.compile`) and the linter (`codeupipe-lint`) are built on this package. No dependencies: standard library only. @@ -42,7 +42,7 @@ library only. ## How it fits in -`core` imports nothing else from codeupipe. `codeupipe.lower` and +`core` imports nothing else from codeupipe. `codeupipe.compile` and `codeupipe-lint` import from it, never the reverse. The data flow the framework is built around is `Payload → Pipeline.run(payload) → Filter.call(payload) → Payload`. diff --git a/scorecard/README.md b/scorecard/README.md index 6a191af..92c98f1 100644 --- a/scorecard/README.md +++ b/scorecard/README.md @@ -1,6 +1,6 @@ # Scorecard -The scorecard compares the static export of a Pipeline (`codeupipe.lower`) +The scorecard compares the compiled form of a Pipeline (`codeupipe.compile`) with the dynamic `Pipeline.run` on random pipelines. Each number in this document comes from a command in this document. @@ -29,8 +29,8 @@ steps) that cross the Payload's overlay-flattening depth. `--hostile-rate` generation (builtins, the generated `run()`'s locals, duplicates, non-identifiers). -Each case runs in four modes: dynamic (reference), fast export `steps`, -fast export `inline`, observable export (`observe=True`). +Each case runs in four modes: dynamic (reference), fast mode `steps`, +fast mode `inline`, observable mode (`observe=True`). | check | steps | inline | observe | |---|---|---|---| @@ -43,16 +43,16 @@ fast export `inline`, observable export (`observe=True`). | Hook event sequence, with a deep snapshot of the payload at every event | | | ✓ | | `SOURCE_HOOKS` guard: `run()` without `hooks=` raises `TypeError` | | | ✓ | -**Verdicts.** *pass*: agrees on every check. *refused*: export raised +**Verdicts.** *pass*: agrees on every check. *refused*: the compiler raised `UnsupportedFilterShape`, counted separately, never as a pass. *fail*: any -divergence, or an export that crashed (a `SyntaxError` on load is not a +divergence, or compiled code that crashed (a `SyntaxError` on load is not a refusal). Every distinct failure signature is shrunk (`minimize.py`) to a minimal case and printed. **Isolation (item 4)** is measured inside the same runs: the caller's input is deep-compared after every run in every mode, and a second run on a fresh copy must give the same result. A `SnapshotHook` (`snapshot_hook.py`) is -attached to the dynamic run and passed to the observable export's `run()`; +attached to the dynamic run and passed to the observable mode's `run()`; at each event it deep-copies the payload, because a Payload is written in place and the object changes later by design. diff --git a/scorecard/vocab.py b/scorecard/vocab.py index 895d465..b775eba 100644 --- a/scorecard/vocab.py +++ b/scorecard/vocab.py @@ -28,7 +28,7 @@ import cup_ops as ops # noqa: E402 import runner # noqa: E402 from codeupipe import Payload, Pipeline # noqa: E402 -from codeupipe.lower.errors import UnsupportedFilterShape # noqa: E402 +from codeupipe.compile.errors import UnsupportedFilterShape # noqa: E402 __all__ = ["sink", "ops", "runner", "Payload", "Pipeline", "UnsupportedFilterShape", "make_predicates", "build_pipeline", "load_export", "new_workdir", "walk_steps"] diff --git a/tests/lower/__init__.py b/tests/compile/__init__.py similarity index 100% rename from tests/lower/__init__.py rename to tests/compile/__init__.py diff --git a/tests/lower/fixtures/__init__.py b/tests/compile/fixtures/__init__.py similarity index 100% rename from tests/lower/fixtures/__init__.py rename to tests/compile/fixtures/__init__.py diff --git a/tests/lower/fixtures/cli_targets.py b/tests/compile/fixtures/cli_targets.py similarity index 73% rename from tests/lower/fixtures/cli_targets.py rename to tests/compile/fixtures/cli_targets.py index 51c33d4..8c91143 100644 --- a/tests/lower/fixtures/cli_targets.py +++ b/tests/compile/fixtures/cli_targets.py @@ -1,9 +1,9 @@ -"""Fixture: things `python -m codeupipe.lower module:name` can be pointed at.""" +"""Fixture: things `python -m codeupipe.compile module:name` can be pointed at.""" from codeupipe.core import Pipeline -from tests.lower.fixtures.instance_config import AtLeast, Discount, HoldsAnObject, SetFlag -from tests.lower.fixtures.plane_b import ExplodingTap +from tests.compile.fixtures.instance_config import AtLeast, Discount, HoldsAnObject, SetFlag +from tests.compile.fixtures.plane_b import ExplodingTap PRICING = Pipeline() PRICING.add_filter(Discount(0.1)) diff --git a/tests/lower/fixtures/export_module_globals.py b/tests/compile/fixtures/export_module_globals.py similarity index 100% rename from tests/lower/fixtures/export_module_globals.py rename to tests/compile/fixtures/export_module_globals.py diff --git a/tests/lower/fixtures/inline_shapes.py b/tests/compile/fixtures/inline_shapes.py similarity index 100% rename from tests/lower/fixtures/inline_shapes.py rename to tests/compile/fixtures/inline_shapes.py diff --git a/tests/lower/fixtures/instance_config.py b/tests/compile/fixtures/instance_config.py similarity index 100% rename from tests/lower/fixtures/instance_config.py rename to tests/compile/fixtures/instance_config.py diff --git a/tests/lower/fixtures/plane_b.py b/tests/compile/fixtures/plane_b.py similarity index 100% rename from tests/lower/fixtures/plane_b.py rename to tests/compile/fixtures/plane_b.py diff --git a/tests/lower/fixtures/typed_steps.py b/tests/compile/fixtures/typed_steps.py similarity index 100% rename from tests/lower/fixtures/typed_steps.py rename to tests/compile/fixtures/typed_steps.py diff --git a/tests/lower/test_cli.py b/tests/compile/test_cli.py similarity index 93% rename from tests/lower/test_cli.py rename to tests/compile/test_cli.py index d772f83..b80095c 100644 --- a/tests/lower/test_cli.py +++ b/tests/compile/test_cli.py @@ -1,4 +1,4 @@ -"""`python -m codeupipe.lower module:name --out DIR`: the export as a command.""" +"""`python -m codeupipe.compile module:name --out DIR`: the export as a command.""" import importlib import sys @@ -6,10 +6,10 @@ import pytest from codeupipe.core import Payload -from codeupipe.lower.__main__ import main -from tests.lower.fixtures import cli_targets +from codeupipe.compile.__main__ import main +from tests.compile.fixtures import cli_targets -TARGETS = "tests.lower.fixtures.cli_targets" +TARGETS = "tests.compile.fixtures.cli_targets" INPUTS = [{"price": 100, "qty": 12}, {"price": 80, "qty": 2}, {}] @@ -147,7 +147,7 @@ def test_runs_as_a_module(tmp_path): out = tmp_path / "out" done = subprocess.run( - [sys.executable, "-m", "codeupipe.lower", f"{TARGETS}:build_pricing", "--out", str(out)], + [sys.executable, "-m", "codeupipe.compile", f"{TARGETS}:build_pricing", "--out", str(out)], capture_output=True, text=True, ) diff --git a/tests/lower/test_emit_inline_module_filter.py b/tests/compile/test_emit_inline_module_filter.py similarity index 99% rename from tests/lower/test_emit_inline_module_filter.py rename to tests/compile/test_emit_inline_module_filter.py index 55f7f6c..20c1568 100644 --- a/tests/lower/test_emit_inline_module_filter.py +++ b/tests/compile/test_emit_inline_module_filter.py @@ -13,7 +13,7 @@ import pytest from codeupipe import Payload, Pipeline -from codeupipe.lower import build_export_pipeline_v2 +from codeupipe.compile import build_export_pipeline_v2 from .fixtures import export_module_globals as g from .fixtures import inline_shapes as s diff --git a/tests/lower/test_emit_orchestrator_filter.py b/tests/compile/test_emit_orchestrator_filter.py similarity index 93% rename from tests/lower/test_emit_orchestrator_filter.py rename to tests/compile/test_emit_orchestrator_filter.py index f07353d..85b4aec 100644 --- a/tests/lower/test_emit_orchestrator_filter.py +++ b/tests/compile/test_emit_orchestrator_filter.py @@ -4,8 +4,8 @@ import textwrap from codeupipe import Payload -from codeupipe.lower.filters.emit_orchestrator_filter import EmitOrchestratorFilter -from codeupipe.lower.ir import PipelineIR, StepIR +from codeupipe.compile.filters.emit_orchestrator_filter import EmitOrchestratorFilter +from codeupipe.compile.ir import PipelineIR, StepIR def _plain_fn(name: str) -> ast.FunctionDef: diff --git a/tests/lower/test_emit_plain_files_filter.py b/tests/compile/test_emit_plain_files_filter.py similarity index 95% rename from tests/lower/test_emit_plain_files_filter.py rename to tests/compile/test_emit_plain_files_filter.py index 46df94e..98e895d 100644 --- a/tests/lower/test_emit_plain_files_filter.py +++ b/tests/compile/test_emit_plain_files_filter.py @@ -4,8 +4,8 @@ import textwrap from codeupipe import Payload -from codeupipe.lower.filters.emit_plain_files_filter import EmitPlainFilesFilter -from codeupipe.lower.ir import PipelineIR, StepIR +from codeupipe.compile.filters.emit_plain_files_filter import EmitPlainFilesFilter +from codeupipe.compile.ir import PipelineIR, StepIR def _plain_fn(name: str) -> ast.FunctionDef: diff --git a/tests/lower/test_errors.py b/tests/compile/test_errors.py similarity index 95% rename from tests/lower/test_errors.py rename to tests/compile/test_errors.py index 12444a9..12b3fd3 100644 --- a/tests/lower/test_errors.py +++ b/tests/compile/test_errors.py @@ -2,7 +2,7 @@ import pytest -from codeupipe.lower.errors import UnsupportedFilterShape +from codeupipe.compile.errors import UnsupportedFilterShape class TestUnsupportedFilterShape: diff --git a/tests/lower/test_export_instance_config.py b/tests/compile/test_export_instance_config.py similarity index 96% rename from tests/lower/test_export_instance_config.py rename to tests/compile/test_export_instance_config.py index 89606b6..97bebae 100644 --- a/tests/lower/test_export_instance_config.py +++ b/tests/compile/test_export_instance_config.py @@ -11,8 +11,8 @@ import pytest from codeupipe import Payload, Pipeline -from codeupipe.lower import build_export_pipeline_v2 -from codeupipe.lower.errors import UnsupportedFilterShape +from codeupipe.compile import build_export_pipeline_v2 +from codeupipe.compile.errors import UnsupportedFilterShape from .fixtures import instance_config as c from .test_export_pipeline import _write_and_import diff --git a/tests/lower/test_export_module_globals.py b/tests/compile/test_export_module_globals.py similarity index 96% rename from tests/lower/test_export_module_globals.py rename to tests/compile/test_export_module_globals.py index 2ee8fce..93412b6 100644 --- a/tests/lower/test_export_module_globals.py +++ b/tests/compile/test_export_module_globals.py @@ -9,8 +9,8 @@ import pytest from codeupipe import Payload, Pipeline -from codeupipe.lower import build_export_pipeline_v2 -from codeupipe.lower.errors import UnsupportedFilterShape +from codeupipe.compile import build_export_pipeline_v2 +from codeupipe.compile.errors import UnsupportedFilterShape from .fixtures import export_module_globals as g from .test_export_pipeline import _write_and_import diff --git a/tests/lower/test_export_observe.py b/tests/compile/test_export_observe.py similarity index 97% rename from tests/lower/test_export_observe.py rename to tests/compile/test_export_observe.py index f3f417e..50213c0 100644 --- a/tests/lower/test_export_observe.py +++ b/tests/compile/test_export_observe.py @@ -1,6 +1,6 @@ """Observable static export: ``observe=True``. -The fast export gives up State and Hooks (docs/static-export.md). With +The fast export gives up State and Hooks (docs/compile.md). With ``observe=True`` the exported ``run`` records the same State the dynamic ``run`` does and calls Hooks in the same order, so the two modes can be judged by the same conformance cases, State and Hooks included. @@ -12,7 +12,7 @@ import pytest from codeupipe import Hook, Payload, Pipeline -from codeupipe.lower import build_export_pipeline_v2 +from codeupipe.compile import build_export_pipeline_v2 ADD = "_Add" @@ -279,7 +279,7 @@ def test_no_framework_import(self, tmp_path): class TestFastExportIsUnchanged: def test_hooks_still_refused_without_observe(self, tmp_path): - from codeupipe.lower.errors import UnsupportedFilterShape + from codeupipe.compile.errors import UnsupportedFilterShape p = Pipeline() p.add_filter(_Add()) @@ -288,7 +288,7 @@ def test_hooks_still_refused_without_observe(self, tmp_path): _export(p, tmp_path, observe=False) def test_nested_pipeline_hooks_refused_even_when_observing(self, tmp_path): - from codeupipe.lower.errors import UnsupportedFilterShape + from codeupipe.compile.errors import UnsupportedFilterShape inner = SubPipeline() inner.add_filter(_Add()) @@ -301,7 +301,7 @@ def test_nested_pipeline_hooks_refused_even_when_observing(self, tmp_path): def test_empty_nested_pipeline_refused_when_observing(self, tmp_path): """Scorecard finding F1: it flattens to no steps, so the observable export could not report it in State and Hooks as the dynamic run does.""" - from codeupipe.lower.errors import UnsupportedFilterShape + from codeupipe.compile.errors import UnsupportedFilterShape outer = Pipeline() outer.add_filter(_Add()) diff --git a/tests/lower/test_export_pipeline.py b/tests/compile/test_export_pipeline.py similarity index 99% rename from tests/lower/test_export_pipeline.py rename to tests/compile/test_export_pipeline.py index d1e4cc0..89daed6 100644 --- a/tests/lower/test_export_pipeline.py +++ b/tests/compile/test_export_pipeline.py @@ -11,7 +11,7 @@ import pytest from codeupipe import Payload, Pipeline -from codeupipe.lower import build_export_pipeline_v2 +from codeupipe.compile import build_export_pipeline_v2 class SubPipeline(Pipeline): diff --git a/tests/lower/test_export_refusals.py b/tests/compile/test_export_refusals.py similarity index 95% rename from tests/lower/test_export_refusals.py rename to tests/compile/test_export_refusals.py index b1637f2..ff79b28 100644 --- a/tests/lower/test_export_refusals.py +++ b/tests/compile/test_export_refusals.py @@ -4,7 +4,7 @@ from the dynamic runtime: Hooks vanished, async steps became broken code, ``payload.trace_id`` became ``data.trace_id`` on a dict, and resilience wrappers died on an unrelated AttributeError. The contract is in -docs/static-export.md: anything that exports behaves the same, and anything +docs/compile.md: anything that exports behaves the same, and anything that cannot is refused at export time with the step named. """ @@ -13,8 +13,8 @@ import pytest from codeupipe import Hook, Payload, Pipeline -from codeupipe.lower import build_export_pipeline_v2 -from codeupipe.lower.errors import UnsupportedFilterShape +from codeupipe.compile import build_export_pipeline_v2 +from codeupipe.compile.errors import UnsupportedFilterShape LOWERINGS = ["steps", "inline"] diff --git a/tests/lower/test_export_typed_steps.py b/tests/compile/test_export_typed_steps.py similarity index 91% rename from tests/lower/test_export_typed_steps.py rename to tests/compile/test_export_typed_steps.py index 77d2d7f..51644b8 100644 --- a/tests/lower/test_export_typed_steps.py +++ b/tests/compile/test_export_typed_steps.py @@ -6,10 +6,10 @@ import pytest from codeupipe.core import Payload -from codeupipe.lower.__main__ import main -from tests.lower.fixtures import typed_steps +from codeupipe.compile.__main__ import main +from tests.compile.fixtures import typed_steps -TARGET = "tests.lower.fixtures.typed_steps:build" +TARGET = "tests.compile.fixtures.typed_steps:build" INPUTS = [{"price": 2.5, "qty": 2}, {"price": 1.0, "qty": 12}] MODES = [[], ["--lowering", "inline"], ["--observe"]] @@ -56,7 +56,7 @@ def test_an_annotated_local_keeps_its_value_and_loses_its_type(tmp_path): def test_erasing_hints_never_leaves_an_empty_block(): import ast - from codeupipe.lower.filters.parse_filter_source_filter import _erase_annotations + from codeupipe.compile.filters.parse_filter_source_filter import _erase_annotations source = ( "def call(self, payload: 'P', *rest: int, flag: bool = False, **more: str) -> 'P':\n" diff --git a/tests/lower/test_ir.py b/tests/compile/test_ir.py similarity index 98% rename from tests/lower/test_ir.py rename to tests/compile/test_ir.py index bbcd34a..1b78b0c 100644 --- a/tests/lower/test_ir.py +++ b/tests/compile/test_ir.py @@ -5,7 +5,7 @@ import pytest -from codeupipe.lower.ir import ( +from codeupipe.compile.ir import ( HookIR, PipelineIR, PipelineMeta, diff --git a/tests/lower/test_load_pipeline_filter.py b/tests/compile/test_load_pipeline_filter.py similarity index 89% rename from tests/lower/test_load_pipeline_filter.py rename to tests/compile/test_load_pipeline_filter.py index 84c6cfc..a1b6a77 100644 --- a/tests/lower/test_load_pipeline_filter.py +++ b/tests/compile/test_load_pipeline_filter.py @@ -3,9 +3,9 @@ import pytest from codeupipe import Payload, Pipeline -from codeupipe.lower.errors import UnsupportedFilterShape -from codeupipe.lower.filters.load_pipeline_filter import LoadPipelineFilter -from codeupipe.lower.ir import PipelineIR +from codeupipe.compile.errors import UnsupportedFilterShape +from codeupipe.compile.filters.load_pipeline_filter import LoadPipelineFilter +from codeupipe.compile.ir import PipelineIR class _ExFilter: diff --git a/tests/lower/test_lower_control_flow_filter.py b/tests/compile/test_lower_control_flow_filter.py similarity index 87% rename from tests/lower/test_lower_control_flow_filter.py rename to tests/compile/test_lower_control_flow_filter.py index c789f64..7a151d9 100644 --- a/tests/lower/test_lower_control_flow_filter.py +++ b/tests/compile/test_lower_control_flow_filter.py @@ -4,8 +4,8 @@ import textwrap from codeupipe import Payload -from codeupipe.lower.filters.lower_control_flow_filter import LowerControlFlowFilter -from codeupipe.lower.ir import PipelineIR, StepIR +from codeupipe.compile.filters.lower_control_flow_filter import LowerControlFlowFilter +from codeupipe.compile.ir import PipelineIR, StepIR def _fn(src: str) -> ast.FunctionDef: @@ -30,7 +30,7 @@ def test_valve_predicate_is_dict_rewritten(self): assert "data.get" in pred_src def test_hooks_produce_warning_but_do_not_fail(self): - from codeupipe.lower.ir import HookIR + from codeupipe.compile.ir import HookIR ir = PipelineIR( steps=[], hooks=[HookIR(name="metrics")], diff --git a/tests/lower/test_parse_filter_source_filter.py b/tests/compile/test_parse_filter_source_filter.py similarity index 92% rename from tests/lower/test_parse_filter_source_filter.py rename to tests/compile/test_parse_filter_source_filter.py index fabd3b4..28ff50b 100644 --- a/tests/lower/test_parse_filter_source_filter.py +++ b/tests/compile/test_parse_filter_source_filter.py @@ -5,9 +5,9 @@ import pytest from codeupipe import Payload -from codeupipe.lower.errors import UnsupportedFilterShape -from codeupipe.lower.filters.parse_filter_source_filter import ParseFilterSourceFilter -from codeupipe.lower.ir import HookIR, PipelineIR, StepIR +from codeupipe.compile.errors import UnsupportedFilterShape +from codeupipe.compile.filters.parse_filter_source_filter import ParseFilterSourceFilter +from codeupipe.compile.ir import HookIR, PipelineIR, StepIR class _ExampleFilter: diff --git a/tests/lower/test_per_filter_imports.py b/tests/compile/test_per_filter_imports.py similarity index 97% rename from tests/lower/test_per_filter_imports.py rename to tests/compile/test_per_filter_imports.py index db8c619..b3827e3 100644 --- a/tests/lower/test_per_filter_imports.py +++ b/tests/compile/test_per_filter_imports.py @@ -5,7 +5,7 @@ import json from codeupipe import Payload, Pipeline -from codeupipe.lower import build_export_pipeline_v2 +from codeupipe.compile import build_export_pipeline_v2 class _UsesMath: diff --git a/tests/lower/test_rewrite_payload_ops_filter.py b/tests/compile/test_rewrite_payload_ops_filter.py similarity index 98% rename from tests/lower/test_rewrite_payload_ops_filter.py rename to tests/compile/test_rewrite_payload_ops_filter.py index 675fa05..d764737 100644 --- a/tests/lower/test_rewrite_payload_ops_filter.py +++ b/tests/compile/test_rewrite_payload_ops_filter.py @@ -6,9 +6,9 @@ import pytest from codeupipe import Payload -from codeupipe.lower.errors import UnsupportedFilterShape -from codeupipe.lower.filters.rewrite_payload_ops_filter import RewritePayloadOpsFilter -from codeupipe.lower.ir import PipelineIR, StepIR, PipelineMeta +from codeupipe.compile.errors import UnsupportedFilterShape +from codeupipe.compile.filters.rewrite_payload_ops_filter import RewritePayloadOpsFilter +from codeupipe.compile.ir import PipelineIR, StepIR, PipelineMeta def _fn(src: str) -> ast.FunctionDef: diff --git a/tests/lower/test_write_files_tap.py b/tests/compile/test_write_files_tap.py similarity index 95% rename from tests/lower/test_write_files_tap.py rename to tests/compile/test_write_files_tap.py index fa60ba2..31e999a 100644 --- a/tests/lower/test_write_files_tap.py +++ b/tests/compile/test_write_files_tap.py @@ -3,7 +3,7 @@ from pathlib import Path from codeupipe import Payload -from codeupipe.lower.taps.write_files_tap import WriteFilesTap +from codeupipe.compile.taps.write_files_tap import WriteFilesTap class TestWriteFilesTap: diff --git a/tests/config/test_config.py b/tests/config/test_config.py index 6307807..f154969 100644 --- a/tests/config/test_config.py +++ b/tests/config/test_config.py @@ -5,11 +5,11 @@ import pytest from codeupipe.config import ConfigError, load_config -from codeupipe.lower.__main__ import main as compile_main +from codeupipe.compile.__main__ import main as compile_main from codeupipe_lint.anonymous_steps.__main__ import main as anonymous_main from codeupipe_lint.invariants.__main__ import main as invariants_main -TARGETS = "tests.lower.fixtures.cli_targets" +TARGETS = "tests.compile.fixtures.cli_targets" def write(directory, config, name="cup.config.json"): diff --git a/tests/examples/test_pricing.py b/tests/examples/test_pricing.py index f262714..94ede71 100644 --- a/tests/examples/test_pricing.py +++ b/tests/examples/test_pricing.py @@ -77,7 +77,7 @@ def test_the_example_runs_as_a_module(): def test_export_matches_and_has_no_framework_import(tmp_path): done = subprocess.run( - [sys.executable, "-m", "codeupipe.lower", "examples.pricing.pricing_pipeline:PricingPipeline", "--out", str(tmp_path)], + [sys.executable, "-m", "codeupipe.compile", "examples.pricing.pricing_pipeline:PricingPipeline", "--out", str(tmp_path)], capture_output=True, text=True, cwd=EXAMPLE.parents[1], ) assert done.returncode == 0, done.stderr diff --git a/tests/lint/anonymous_steps/test_repo_is_clean.py b/tests/lint/anonymous_steps/test_repo_is_clean.py index 02e2a3e..6eb2d6e 100644 --- a/tests/lint/anonymous_steps/test_repo_is_clean.py +++ b/tests/lint/anonymous_steps/test_repo_is_clean.py @@ -7,9 +7,9 @@ from ._support import REPO -CHECKED = ["packages/codeupipe/codeupipe", "conformance/runners/python", "scorecard", "tests/core", "tests/lower", +CHECKED = ["packages/codeupipe/codeupipe", "conformance/runners/python", "scorecard", "tests/core", "tests/compile", "tests/scorecard", "tests/conformance"] -INTENTIONAL = {"tests/lower/test_export_refusals.py", +INTENTIONAL = {"tests/compile/test_export_refusals.py", "tests/core/test_add_valve.py", "tests/core/test_step_labels.py"}