j2py-converter 0.1.0a1__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.
- j2py_converter-0.1.0a1/.gitignore +17 -0
- j2py_converter-0.1.0a1/CHANGELOG.md +132 -0
- j2py_converter-0.1.0a1/CONTRIBUTING.md +121 -0
- j2py_converter-0.1.0a1/LICENSE +21 -0
- j2py_converter-0.1.0a1/Makefile +81 -0
- j2py_converter-0.1.0a1/PKG-INFO +199 -0
- j2py_converter-0.1.0a1/README.md +158 -0
- j2py_converter-0.1.0a1/SECURITY.md +21 -0
- j2py_converter-0.1.0a1/docs/ARCHITECTURE.md +150 -0
- j2py_converter-0.1.0a1/docs/CORPUS_SCOREBOARD.md +147 -0
- j2py_converter-0.1.0a1/docs/PRD.md +81 -0
- j2py_converter-0.1.0a1/docs/RELEASING.md +42 -0
- j2py_converter-0.1.0a1/docs/TRANSLATION_TARGETS.md +68 -0
- j2py_converter-0.1.0a1/docs/decisions/0001-record-architecture-decisions.md +58 -0
- j2py_converter-0.1.0a1/docs/decisions/0002-tree-sitter-for-java-parsing.md +47 -0
- j2py_converter-0.1.0a1/docs/decisions/0003-layered-translation-pipeline.md +69 -0
- j2py_converter-0.1.0a1/docs/decisions/0004-claude-as-llm-backend.md +49 -0
- j2py_converter-0.1.0a1/docs/decisions/0005-python-311-target-with-type-hints.md +52 -0
- j2py_converter-0.1.0a1/docs/decisions/0006-overload-translation-policy.md +52 -0
- j2py_converter-0.1.0a1/docs/decisions/0007-type-declaration-translation.md +42 -0
- j2py_converter-0.1.0a1/docs/decisions/0008-expression-narrowing-and-bitwise-translation.md +66 -0
- j2py_converter-0.1.0a1/docs/decisions/0009-two-tier-overload-translation.md +107 -0
- j2py_converter-0.1.0a1/docs/decisions/0010-post-llm-structural-verification.md +47 -0
- j2py_converter-0.1.0a1/docs/decisions/0010-synchronized-this-translation.md +37 -0
- j2py_converter-0.1.0a1/j2py/__init__.py +3 -0
- j2py_converter-0.1.0a1/j2py/analyze/__init__.py +1 -0
- j2py_converter-0.1.0a1/j2py/analyze/graph.py +130 -0
- j2py_converter-0.1.0a1/j2py/analyze/symbols.py +264 -0
- j2py_converter-0.1.0a1/j2py/cli/__init__.py +1 -0
- j2py_converter-0.1.0a1/j2py/cli/main.py +437 -0
- j2py_converter-0.1.0a1/j2py/config/__init__.py +1 -0
- j2py_converter-0.1.0a1/j2py/config/default.py +159 -0
- j2py_converter-0.1.0a1/j2py/config/loader.py +88 -0
- j2py_converter-0.1.0a1/j2py/llm/__init__.py +1 -0
- j2py_converter-0.1.0a1/j2py/llm/client.py +141 -0
- j2py_converter-0.1.0a1/j2py/llm/prompts.py +84 -0
- j2py_converter-0.1.0a1/j2py/parse/__init__.py +1 -0
- j2py_converter-0.1.0a1/j2py/parse/java_ast.py +111 -0
- j2py_converter-0.1.0a1/j2py/pipeline.py +255 -0
- j2py_converter-0.1.0a1/j2py/translate/__init__.py +1 -0
- j2py_converter-0.1.0a1/j2py/translate/classes.py +1645 -0
- j2py_converter-0.1.0a1/j2py/translate/comments.py +41 -0
- j2py_converter-0.1.0a1/j2py/translate/diagnostics.py +127 -0
- j2py_converter-0.1.0a1/j2py/translate/expressions.py +1753 -0
- j2py_converter-0.1.0a1/j2py/translate/node_utils.py +23 -0
- j2py_converter-0.1.0a1/j2py/translate/rules/__init__.py +1 -0
- j2py_converter-0.1.0a1/j2py/translate/rules/literals.py +151 -0
- j2py_converter-0.1.0a1/j2py/translate/rules/naming.py +71 -0
- j2py_converter-0.1.0a1/j2py/translate/rules/types.py +138 -0
- j2py_converter-0.1.0a1/j2py/translate/runtime/__init__.py +21 -0
- j2py_converter-0.1.0a1/j2py/translate/runtime/j2py_runtime.py +221 -0
- j2py_converter-0.1.0a1/j2py/translate/skeleton.py +114 -0
- j2py_converter-0.1.0a1/j2py/translate/statements.py +920 -0
- j2py_converter-0.1.0a1/j2py/validate/__init__.py +1 -0
- j2py_converter-0.1.0a1/j2py/validate/checks.py +84 -0
- j2py_converter-0.1.0a1/j2py/verify/__init__.py +2 -0
- j2py_converter-0.1.0a1/j2py/verify/structure.py +114 -0
- j2py_converter-0.1.0a1/pyproject.toml +97 -0
- j2py_converter-0.1.0a1/tests/__init__.py +0 -0
- j2py_converter-0.1.0a1/tests/analyze/__init__.py +0 -0
- j2py_converter-0.1.0a1/tests/analyze/test_graph.py +128 -0
- j2py_converter-0.1.0a1/tests/analyze/test_symbols.py +116 -0
- j2py_converter-0.1.0a1/tests/behavior/__init__.py +1 -0
- j2py_converter-0.1.0a1/tests/behavior/test_equivalence.py +196 -0
- j2py_converter-0.1.0a1/tests/cli/test_main.py +539 -0
- j2py_converter-0.1.0a1/tests/config/test_loader.py +27 -0
- j2py_converter-0.1.0a1/tests/conftest.py +20 -0
- j2py_converter-0.1.0a1/tests/corpus/test_translate_spring_sample.py +236 -0
- j2py_converter-0.1.0a1/tests/fixtures/behavior/enhanced_for_list/Main.java +13 -0
- j2py_converter-0.1.0a1/tests/fixtures/behavior/fields_methods/Main.java +29 -0
- j2py_converter-0.1.0a1/tests/fixtures/behavior/hello_print/Main.java +5 -0
- j2py_converter-0.1.0a1/tests/fixtures/behavior/if_else_arithmetic/Main.java +15 -0
- j2py_converter-0.1.0a1/tests/fixtures/behavior/loops_sum/Main.java +14 -0
- j2py_converter-0.1.0a1/tests/fixtures/corpus/constructs/AdvancedEnum.java +42 -0
- j2py_converter-0.1.0a1/tests/fixtures/corpus/constructs/AdvancedStreams.java +47 -0
- j2py_converter-0.1.0a1/tests/fixtures/corpus/constructs/AnonymousAndInner.java +61 -0
- j2py_converter-0.1.0a1/tests/fixtures/corpus/constructs/ComplexRecords.java +35 -0
- j2py_converter-0.1.0a1/tests/fixtures/corpus/constructs/InterfaceDefaults.java +40 -0
- j2py_converter-0.1.0a1/tests/fixtures/corpus/constructs/README.md +50 -0
- j2py_converter-0.1.0a1/tests/fixtures/corpus/constructs/SealedClasses.java +36 -0
- j2py_converter-0.1.0a1/tests/fixtures/corpus/constructs/SuperMethodCalls.java +33 -0
- j2py_converter-0.1.0a1/tests/fixtures/corpus/constructs/SwitchFallthrough.java +43 -0
- j2py_converter-0.1.0a1/tests/fixtures/corpus/constructs/TextBlocks.java +40 -0
- j2py_converter-0.1.0a1/tests/fixtures/corpus/constructs/VarKeyword.java +34 -0
- j2py_converter-0.1.0a1/tests/fixtures/corpus/spring-dense-baseline.json +1362 -0
- j2py_converter-0.1.0a1/tests/fixtures/corpus/spring-sample-baseline.json +1442 -0
- j2py_converter-0.1.0a1/tests/fixtures/java/Fields.java +17 -0
- j2py_converter-0.1.0a1/tests/fixtures/java/HelloWorld.java +36 -0
- j2py_converter-0.1.0a1/tests/fixtures/java/PartialUnsupported.java +8 -0
- j2py_converter-0.1.0a1/tests/fixtures/java/targets/ArrayCreation.java +8 -0
- j2py_converter-0.1.0a1/tests/fixtures/java/targets/BitwiseOperators.java +16 -0
- j2py_converter-0.1.0a1/tests/fixtures/java/targets/CastExpression.java +8 -0
- j2py_converter-0.1.0a1/tests/fixtures/java/targets/CommentsAnnotations.java +13 -0
- j2py_converter-0.1.0a1/tests/fixtures/java/targets/CompoundAssignment.java +10 -0
- j2py_converter-0.1.0a1/tests/fixtures/java/targets/ControlFlow.java +32 -0
- j2py_converter-0.1.0a1/tests/fixtures/java/targets/Exceptions.java +18 -0
- j2py_converter-0.1.0a1/tests/fixtures/java/targets/Expressions.java +13 -0
- j2py_converter-0.1.0a1/tests/fixtures/java/targets/Functional.java +14 -0
- j2py_converter-0.1.0a1/tests/fixtures/java/targets/InstanceofExpression.java +11 -0
- j2py_converter-0.1.0a1/tests/fixtures/java/targets/NestedTypes.java +61 -0
- j2py_converter-0.1.0a1/tests/fixtures/java/targets/OverloadChains.java +36 -0
- j2py_converter-0.1.0a1/tests/fixtures/java/targets/OverloadDispatch.java +41 -0
- j2py_converter-0.1.0a1/tests/fixtures/java/targets/Overloads.java +22 -0
- j2py_converter-0.1.0a1/tests/fixtures/java/targets/StaticAndSynchronized.java +14 -0
- j2py_converter-0.1.0a1/tests/fixtures/java/targets/TryWithResources.java +12 -0
- j2py_converter-0.1.0a1/tests/fixtures/python/Fields.py +13 -0
- j2py_converter-0.1.0a1/tests/fixtures/python/HelloWorld.py +25 -0
- j2py_converter-0.1.0a1/tests/llm/__init__.py +0 -0
- j2py_converter-0.1.0a1/tests/llm/test_client.py +194 -0
- j2py_converter-0.1.0a1/tests/llm/test_e2e_llm.py +136 -0
- j2py_converter-0.1.0a1/tests/llm/test_prompts.py +41 -0
- j2py_converter-0.1.0a1/tests/parse/__init__.py +0 -0
- j2py_converter-0.1.0a1/tests/parse/test_java_ast.py +36 -0
- j2py_converter-0.1.0a1/tests/targets/test_translation_targets.py +143 -0
- j2py_converter-0.1.0a1/tests/test_pipeline.py +460 -0
- j2py_converter-0.1.0a1/tests/translate/__init__.py +0 -0
- j2py_converter-0.1.0a1/tests/translate/skeleton/__init__.py +1 -0
- j2py_converter-0.1.0a1/tests/translate/skeleton/helpers.py +26 -0
- j2py_converter-0.1.0a1/tests/translate/skeleton/test_config.py +67 -0
- j2py_converter-0.1.0a1/tests/translate/skeleton/test_control_flow.py +577 -0
- j2py_converter-0.1.0a1/tests/translate/skeleton/test_expressions.py +843 -0
- j2py_converter-0.1.0a1/tests/translate/skeleton/test_fields_enums.py +319 -0
- j2py_converter-0.1.0a1/tests/translate/skeleton/test_fixtures.py +340 -0
- j2py_converter-0.1.0a1/tests/translate/skeleton/test_misc.py +98 -0
- j2py_converter-0.1.0a1/tests/translate/skeleton/test_overloads.py +150 -0
- j2py_converter-0.1.0a1/tests/translate/skeleton/test_streams.py +421 -0
- j2py_converter-0.1.0a1/tests/translate/test_diagnostics.py +18 -0
- j2py_converter-0.1.0a1/tests/translate/test_literals.py +34 -0
- j2py_converter-0.1.0a1/tests/translate/test_naming.py +38 -0
- j2py_converter-0.1.0a1/tests/translate/test_runtime_dispatch.py +175 -0
- j2py_converter-0.1.0a1/tests/translate/test_types.py +54 -0
- j2py_converter-0.1.0a1/tests/validate/__init__.py +0 -0
- j2py_converter-0.1.0a1/tests/validate/test_checks.py +43 -0
- j2py_converter-0.1.0a1/tests/verify/test_structure.py +87 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to j2py will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format follows the repository commit types: `feat`, `fix`, `refactor`, `test`,
|
|
6
|
+
`docs`, `chore`, and `adr`.
|
|
7
|
+
|
|
8
|
+
## Unreleased
|
|
9
|
+
|
|
10
|
+
No changes yet.
|
|
11
|
+
|
|
12
|
+
## 0.1.0a1 - 2026-06-11
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- GitHub Actions corpus workflow (`.github/workflows/corpus.yml`) comparing the pinned
|
|
16
|
+
Spring sample against the committed baseline on translation/corpus path changes.
|
|
17
|
+
- `j2py analyze` dependency graph and translation-order output for file and directory modes.
|
|
18
|
+
- Skeleton translator tests split under `tests/translate/skeleton/` by concern (#69).
|
|
19
|
+
- ADR 0010: `synchronized(this)` translates to `self._j2py_lock` with `threading.Lock()`
|
|
20
|
+
initialization in constructors or synthetic `__init__`.
|
|
21
|
+
- Preferred dense Spring + curated-construct corpus baseline workflow:
|
|
22
|
+
`corpus-spring-dense-check`, `corpus-spring-dense-update-baseline`, and
|
|
23
|
+
`tests/fixtures/corpus/spring-dense-baseline.json`.
|
|
24
|
+
- Future corpus target for `super.method(...)` receiver calls identified by the dense
|
|
25
|
+
Spring corpus.
|
|
26
|
+
- Shared `tests/conftest.py` with session `cfg` fixture and fixture path constants.
|
|
27
|
+
- `TranslationDiagnostics.semantic_warning_count` and `rule_coverage` alias documenting
|
|
28
|
+
that warnings do not reduce node coverage.
|
|
29
|
+
- Strict xfail `FUTURE_TARGETS` for two corpus constructs still below full rule coverage
|
|
30
|
+
(`AdvancedStreams`, `SuperMethodCalls`).
|
|
31
|
+
- Graduated corpus construct regression tests in `make check` for eight constructs that
|
|
32
|
+
reach full skeleton coverage (`AdvancedEnum`, `ComplexRecords`, `InterfaceDefaults`,
|
|
33
|
+
`SealedClasses`, `TextBlocks`, `VarKeyword`, `SwitchFallthrough`, `AnonymousAndInner`).
|
|
34
|
+
- Record declarations (`record_declaration`) in the symbol table: component fields,
|
|
35
|
+
body methods, inner records, and `is_record` on `ClassSymbol`.
|
|
36
|
+
- `TranslationResult.parse_ok` and `PARSE_ERROR_LLM_SKIP_MSG`: malformed Java with
|
|
37
|
+
tree-sitter `ERROR`/`MISSING` nodes skips LLM completion and reports `confidence=0.0`.
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
- Anonymous class instance fields translate to helper-class `__init__` assignments with
|
|
41
|
+
`self.` field access in methods (#74).
|
|
42
|
+
- Switch fall-through translates to reviewable prefix `elif`/`if` chains with explicit
|
|
43
|
+
default guards (`elif subject not in (...)` after fall-through blocks) (#73).
|
|
44
|
+
- Local `var` declarations infer Python types from initializers; enhanced-for `var` binds
|
|
45
|
+
element types from iterable annotations (#72).
|
|
46
|
+
- Prepared the first MIT-licensed PyPI alpha release as distribution `j2py-converter`
|
|
47
|
+
with import package and CLI name `j2py`.
|
|
48
|
+
- README known gaps refreshed to match graduated targets/corpus constructs and remaining
|
|
49
|
+
`FUTURE_TARGETS` xfail items (#69).
|
|
50
|
+
- Non-`this` synchronized blocks keep `with <expr>:` but warn that lock semantics need review.
|
|
51
|
+
- LLM system prompt aligned with the `_j2py_lock` instance-monitor pattern.
|
|
52
|
+
- Dependency graph resolves simple type names only when unambiguous; ambiguous `User`-style
|
|
53
|
+
collisions no longer pick an arbitrary file.
|
|
54
|
+
- `j2py analyze` prints class inventory plus dependency graph and translation order (#69).
|
|
55
|
+
- `TranslationResult.confidence` documented as rule-layer coverage (unchanged after LLM).
|
|
56
|
+
- Agent docs (`AGENTS.md`, `CLAUDE.md`) updated for graduated vs xfail test tiers.
|
|
57
|
+
- Graduated target fixtures (`tests/fixtures/java/targets/`) now run in `make check` and
|
|
58
|
+
CI; `make test-targets` is reserved for strict `xfail` entries in `FUTURE_TARGETS`.
|
|
59
|
+
- CLI `analyze` reports record types, nested declarations, and parse-error status.
|
|
60
|
+
- CLI translate summaries surface `parse_ok=False` and parse-error warnings.
|
|
61
|
+
- Directory translation aggregates per-file parse-error warnings in `batch.warnings`.
|
|
62
|
+
|
|
63
|
+
### Added
|
|
64
|
+
- Two-tier overload translation (ADR 0009, issue #44): chained `this(...)`
|
|
65
|
+
constructor delegation and builder-style forwarding method overloads now merge
|
|
66
|
+
into default parameters (immutable literals inline; constructed values become
|
|
67
|
+
`None` sentinels with normalization lines). Overload groups that genuinely
|
|
68
|
+
dispatch on parameter types emit each Java overload as a same-named def behind
|
|
69
|
+
a vendored `@overloaded` runtime dispatcher (`j2py_runtime.py`, stdlib-only,
|
|
70
|
+
written next to translated output by the CLI). The manual-dispatch
|
|
71
|
+
`NotImplementedError` fallback now only remains for static overload groups and
|
|
72
|
+
erased-signature collisions (e.g. `int` vs `long`).
|
|
73
|
+
- Java varargs parameters (`Type... name`) now translate to `*name: Type` in
|
|
74
|
+
method signatures instead of being dropped.
|
|
75
|
+
- Deterministic translation for `instanceof` expressions, `instanceof` pattern
|
|
76
|
+
variable bindings, cast expressions with review warnings, and bitwise/shift
|
|
77
|
+
operators including compound bitwise assignment.
|
|
78
|
+
- Block lambdas (`x -> { statements; return v; }`) are now supported deterministically. They are turned into a local nested helper (`_j2py_lambda_N`) emitted near the top of the enclosing method; the helper name is used at the call site. The block body structure is preserved for reviewability.
|
|
79
|
+
- Complex stream pipelines/collectors: extended deterministic support for toSet, basic joining, .distinct(), .sorted() (simple or with key via method ref), and basic groupingBy (via emitted accumulation helpers using defaultdict). Builds on prior block lambda work; many cases now rewrite to clean comps or stdlib helpers (per review feedback favoring itertools/functools where used).
|
|
80
|
+
|
|
81
|
+
### Fixed
|
|
82
|
+
- Constructor overload merging no longer emits invalid self-referential defaults
|
|
83
|
+
(`name: str = name`) or raw Java generic types in annotations when a delegating
|
|
84
|
+
constructor passes its own parameters through alongside constructed values; the
|
|
85
|
+
pass-through prefix rule in ADR 0009 rejects or correctly composes these.
|
|
86
|
+
- `_stream_item_name`: improved plural stripping with explicit map for common cases ("statuses"→"status", "types"→"type", "classes"→"class" etc.) to avoid "statu"/"addres"/"typ" etc. in stream listcomps.
|
|
87
|
+
- Integer division (`int / int`): now uses `diagnostics.warn()` (visible for review) instead of `record(supported=False)`. Correct `//` output no longer forces LLM or lowers coverage.
|
|
88
|
+
- Lambda/alias context in expressions: added `try/finally` around mutable `TranslationContext` updates (`local_names`, `variable_types`, `expression_aliases`) so exceptions during body translation cannot leak state to callers.
|
|
89
|
+
- Overload merge paths: no longer downgrade `class_field_types` to all `"object"`. Real field types (including collections) are now preserved in the shared implementation body, enabling correct specializations (e.g. list `get`).
|
|
90
|
+
- Removed misleading claim that the `switch_expression` dispatch in `translate_statement` was dead; kept it (with expanded comment) because tree-sitter-java uses the same node type for traditional colon switch *statements*. Added clarifying comments + tests.
|
|
91
|
+
|
|
92
|
+
### Added (historical)
|
|
93
|
+
|
|
94
|
+
- Initial deterministic skeleton translator for simple Java classes.
|
|
95
|
+
- Structured rule-layer diagnostics and coverage reporting.
|
|
96
|
+
- Spring corpus scoreboard with a pinned baseline.
|
|
97
|
+
- Roadmap target tests for unsupported Java-to-Python constructs.
|
|
98
|
+
- Dependency-ordered directory translation with package-relative output paths.
|
|
99
|
+
- Config-driven import emission, type maps, collection maps, exception maps, and
|
|
100
|
+
translation flags.
|
|
101
|
+
- Deterministic translation for common control flow, exception handling, comments,
|
|
102
|
+
nested type declarations, overload stubs, constructor delegation, and common
|
|
103
|
+
expression shapes.
|
|
104
|
+
- Deterministic translation for standalone expression lambdas and basic method
|
|
105
|
+
references, with block lambdas kept as explicit unresolved regions.
|
|
106
|
+
- Deterministic translation for safe traditional switch cases and switch expressions,
|
|
107
|
+
with fall-through and complex switch blocks left as diagnostics.
|
|
108
|
+
- Deterministic translation for simple stream `map`/`filter`/`toList` pipelines when
|
|
109
|
+
mapper and predicate expressions are supported.
|
|
110
|
+
- LLM prompt context for project symbols, rule diagnostics, config fingerprints, and
|
|
111
|
+
validation feedback.
|
|
112
|
+
- On-demand LLM exploration helper for manually inspecting the tree-sitter skeleton,
|
|
113
|
+
diagnostics, final LLM output, and validation results outside the normal test suite.
|
|
114
|
+
|
|
115
|
+
### Changed
|
|
116
|
+
|
|
117
|
+
- Clarified the target-test workflow: current roadmap fixtures now run as graduated
|
|
118
|
+
deterministic regression checks, while future unsupported targets remain strict xfails.
|
|
119
|
+
- Split skeleton translation into class, statement, expression, diagnostic, and node helper
|
|
120
|
+
modules.
|
|
121
|
+
- Updated contributor and architecture docs to describe the implemented deterministic
|
|
122
|
+
visitor layer and the remaining unsupported constructs.
|
|
123
|
+
- Generalized CLI help text for configured LLM usage without changing the Anthropic
|
|
124
|
+
backend contract.
|
|
125
|
+
|
|
126
|
+
### Fixed
|
|
127
|
+
|
|
128
|
+
- Preserved Java `Map.get` missing-key semantics, translated `.equals(...)`, and made
|
|
129
|
+
integer division and ambiguous `get` calls honest through diagnostics.
|
|
130
|
+
- Preserved Java left-to-right evaluation for string concatenation with leading numeric
|
|
131
|
+
operands.
|
|
132
|
+
- Removed tracked `.pyc` and `__pycache__` files from version control.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Contributing to j2py
|
|
2
|
+
|
|
3
|
+
## Setup
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
git clone git@github.com:tomanizer/j2py.git
|
|
7
|
+
cd j2py
|
|
8
|
+
uv sync --locked
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Python 3.11 required. `uv` manages the virtualenv automatically.
|
|
12
|
+
|
|
13
|
+
## Workflow
|
|
14
|
+
|
|
15
|
+
1. **Branch from `main`**: `git checkout -b feat/my-feature`
|
|
16
|
+
2. **Run checks before committing**: `make check` (lint + typecheck + test)
|
|
17
|
+
3. **Run `make ci-local-pr`** before pushing — this is what CI runs
|
|
18
|
+
4. **Open a PR** using the template — fill every section
|
|
19
|
+
|
|
20
|
+
### Commit style
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
<type>: <short imperative summary>
|
|
24
|
+
|
|
25
|
+
<optional body — why, not what>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Types: `feat` · `fix` · `refactor` · `test` · `docs` · `chore` · `adr`
|
|
29
|
+
|
|
30
|
+
Examples:
|
|
31
|
+
```
|
|
32
|
+
feat: translate enhanced for-loops to Python for comprehensions
|
|
33
|
+
fix: preserve Optional<T> in nested generic types
|
|
34
|
+
adr: document choice of tree-sitter over javalang (ADR 0002)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Adding a translation rule
|
|
38
|
+
|
|
39
|
+
Every new Java construct translation needs:
|
|
40
|
+
|
|
41
|
+
1. **Java fixture** — `tests/fixtures/java/<Feature>.java`
|
|
42
|
+
2. **Expected Python fixture** — `tests/fixtures/python/<Feature>.py`
|
|
43
|
+
3. **Test** — parametrised entry in `tests/translate/` (or a new test file)
|
|
44
|
+
4. **Implementation** — rule in `j2py/translate/rules/` or `skeleton.py`
|
|
45
|
+
|
|
46
|
+
The fixture pair is the contract. CI runs exact fixture equality tests in `make check`.
|
|
47
|
+
|
|
48
|
+
For unsupported but planned Java constructs, add or update a roadmap target test first.
|
|
49
|
+
Graduated target tests live under `tests/targets/` and run in `make check`. Future
|
|
50
|
+
`xfail` roadmap contracts use the `target_translation` marker and run with:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
make test-targets
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Once a target is supported, remove it from `FUTURE_TARGETS` so it runs in the graduated
|
|
57
|
+
target check, or move the behavior into the normal fixture suite. See
|
|
58
|
+
[Translation Target Tests](docs/TRANSLATION_TARGETS.md) for the target-test workflow and
|
|
59
|
+
graduation rules.
|
|
60
|
+
|
|
61
|
+
For real-corpus progress checks, run the preferred dense Spring + curated-construct
|
|
62
|
+
scoreboard:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
make corpus-spring-dense-check
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
See [Spring Corpus Scoreboard](docs/CORPUS_SCOREBOARD.md) for the preferred dense
|
|
69
|
+
baseline, historical lexical baseline, comparison mode, and intentional baseline refresh
|
|
70
|
+
workflow.
|
|
71
|
+
|
|
72
|
+
## Material changes
|
|
73
|
+
|
|
74
|
+
A **material change** is any of:
|
|
75
|
+
- Changing how a Java construct is translated (different Python idiom)
|
|
76
|
+
- Adding a new pipeline stage
|
|
77
|
+
- Changing the LLM model or prompt structure
|
|
78
|
+
- Changing the Python output version target
|
|
79
|
+
- Breaking the `translate_file()` public API
|
|
80
|
+
|
|
81
|
+
Material changes require:
|
|
82
|
+
1. A new ADR in `docs/decisions/` ([template](docs/decisions/0001-record-architecture-decisions.md))
|
|
83
|
+
2. Updated `docs/ARCHITECTURE.md` if the pipeline shape changes
|
|
84
|
+
3. Explicit note in the PR body linking the ADR
|
|
85
|
+
4. A `CHANGELOG.md` entry when the change affects user-visible behavior or project
|
|
86
|
+
workflow
|
|
87
|
+
|
|
88
|
+
## PR rules
|
|
89
|
+
|
|
90
|
+
- One concern per PR — translation rules, refactor, or docs; not all three
|
|
91
|
+
- `Closes #N` in the PR body to auto-close issues (checkboxes in the issue do **not** close it)
|
|
92
|
+
- `make ci-local-pr` must pass before requesting review
|
|
93
|
+
- No version bumps on feature PRs — version is bumped in a dedicated release PR
|
|
94
|
+
|
|
95
|
+
## Release
|
|
96
|
+
|
|
97
|
+
Alpha releases are published to PyPI as the `j2py-converter` distribution. The import
|
|
98
|
+
package and console script remain `j2py`; the `j2py` PyPI project name is already owned
|
|
99
|
+
by an unrelated project.
|
|
100
|
+
|
|
101
|
+
Releases are tagged `vX.Y.Z` on `main`; pre-releases use PEP 440 suffixes such as
|
|
102
|
+
`v0.1.0a1`. Versioning follows [SemVer](https://semver.org/) for stable releases:
|
|
103
|
+
|
|
104
|
+
- `MAJOR` — breaking change to `translate_file()` API or output format
|
|
105
|
+
- `MINOR` — new Java construct support, new CLI flag
|
|
106
|
+
- `PATCH` — bug fix, doc fix, test improvement
|
|
107
|
+
|
|
108
|
+
Update `CHANGELOG.md`, `pyproject.toml`, and `j2py/__init__.py` in the release PR.
|
|
109
|
+
Feature and fix PRs should add notes under `## Unreleased`; the release PR moves those
|
|
110
|
+
notes under the tagged version.
|
|
111
|
+
|
|
112
|
+
Before publishing:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
make release-check
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The release workflow builds the wheel/sdist and publishes through PyPI trusted
|
|
119
|
+
publishing when a GitHub release is published. PyPI trusted publishing is configured for
|
|
120
|
+
repository `tomanizer/j2py`, workflow `.github/workflows/publish.yml`, environment
|
|
121
|
+
`pypi`, and project `j2py-converter`.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Thomas Haederle
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
.PHONY: check lint format typecheck test test-behavior test-targets test-llm-e2e test-cov corpus-spring corpus-spring-smoke corpus-spring-update-baseline corpus-spring-dense corpus-spring-dense-check corpus-spring-dense-update-baseline corpus-spring-broad clean ci-local-pr ci-local-governance build dist-check release-check
|
|
2
|
+
|
|
3
|
+
SPRING_DENSE_BASELINE := tests/fixtures/corpus/spring-dense-baseline.json
|
|
4
|
+
SPRING_DENSE_ARGS := --strategy density --max-loc 250 --min-constructs 5 --include-constructs --baseline $(SPRING_DENSE_BASELINE)
|
|
5
|
+
|
|
6
|
+
# ── Primary targets ──────────────────────────────────────────────────────────
|
|
7
|
+
|
|
8
|
+
check: lint typecheck test ## Run all checks (alias for ci-local-pr)
|
|
9
|
+
|
|
10
|
+
lint: ## Lint with ruff
|
|
11
|
+
uv run --extra dev ruff check j2py/ tests/
|
|
12
|
+
|
|
13
|
+
format: ## Format with ruff
|
|
14
|
+
uv run --extra dev ruff format j2py/ tests/
|
|
15
|
+
|
|
16
|
+
typecheck: ## Type-check with mypy (strict)
|
|
17
|
+
uv run --extra dev mypy j2py/
|
|
18
|
+
|
|
19
|
+
test: ## Run test suite
|
|
20
|
+
uv run --extra dev pytest -m "not behavior and not live_llm"
|
|
21
|
+
|
|
22
|
+
test-behavior: ## Run Java/Python behavior-equivalence tests (requires a local JDK)
|
|
23
|
+
uv run --extra dev pytest tests/behavior -m behavior
|
|
24
|
+
|
|
25
|
+
test-targets: ## Run future Java-to-Python roadmap xfail targets only
|
|
26
|
+
uv run --extra dev pytest tests/targets -m target_translation -rxXs
|
|
27
|
+
|
|
28
|
+
test-llm-e2e: ## Run the on-demand live-LLM exploratory test (requires ANTHROPIC_API_KEY)
|
|
29
|
+
@echo "Running live LLM exploratory test. This is excluded from normal make check."
|
|
30
|
+
uv run --extra dev pytest -m live_llm tests/llm/test_e2e_llm.py -v -s
|
|
31
|
+
|
|
32
|
+
test-cov: ## Run tests with coverage report
|
|
33
|
+
uv run --extra dev pytest --cov=j2py --cov-report=term-missing --cov-report=xml
|
|
34
|
+
|
|
35
|
+
corpus-spring: ## Compare the Spring corpus sample against the committed baseline
|
|
36
|
+
uv run python scripts/corpus/translate_spring_sample.py --compare-baseline
|
|
37
|
+
|
|
38
|
+
corpus-spring-smoke: ## Run a quick 25-file Spring corpus smoke sample without baseline comparison
|
|
39
|
+
uv run python scripts/corpus/translate_spring_sample.py --limit 25
|
|
40
|
+
|
|
41
|
+
corpus-spring-update-baseline: ## Regenerate the committed Spring corpus baseline intentionally
|
|
42
|
+
uv run python scripts/corpus/translate_spring_sample.py --update-baseline --compare-baseline
|
|
43
|
+
|
|
44
|
+
corpus-spring-dense: ## Run the preferred dense Spring + curated-construct corpus without comparing the baseline
|
|
45
|
+
uv run python scripts/corpus/translate_spring_sample.py $(SPRING_DENSE_ARGS)
|
|
46
|
+
|
|
47
|
+
corpus-spring-dense-check: ## Compare the preferred dense Spring + curated-construct corpus against its baseline
|
|
48
|
+
uv run python scripts/corpus/translate_spring_sample.py $(SPRING_DENSE_ARGS) --compare-baseline --fail-on-regression
|
|
49
|
+
|
|
50
|
+
corpus-spring-dense-update-baseline: ## Regenerate the preferred dense Spring + curated-construct corpus baseline intentionally
|
|
51
|
+
uv run python scripts/corpus/translate_spring_sample.py $(SPRING_DENSE_ARGS) --update-baseline
|
|
52
|
+
|
|
53
|
+
corpus-spring-broad: ## Broader + more extensive sample (more modules + curated construct files for the new roadmap items)
|
|
54
|
+
# Note: does not compare to the default baseline (different sampling parameters)
|
|
55
|
+
uv run python scripts/corpus/translate_spring_sample.py \
|
|
56
|
+
--module spring-context/src/main/java \
|
|
57
|
+
--include-constructs \
|
|
58
|
+
--limit 150 \
|
|
59
|
+
--strategy density
|
|
60
|
+
|
|
61
|
+
# ── CI local presets ─────────────────────────────────────────────────────────
|
|
62
|
+
# These mirror exactly what GitHub Actions runs. If make ci-local-pr passes,
|
|
63
|
+
# CI will pass.
|
|
64
|
+
|
|
65
|
+
ci-local-pr: check ## For code/test/docs PRs — lint + typecheck + test
|
|
66
|
+
|
|
67
|
+
ci-local-governance: check ## For CI/tooling/dependency PRs — same gates, explicit label
|
|
68
|
+
|
|
69
|
+
# ── Utility ──────────────────────────────────────────────────────────────────
|
|
70
|
+
|
|
71
|
+
clean: ## Remove build artifacts and caches
|
|
72
|
+
rm -rf dist/ .mypy_cache/ .ruff_cache/ .pytest_cache/ htmlcov/ .coverage coverage.xml corpus-reports/
|
|
73
|
+
find . -type d -name __pycache__ -not -path './.venv/*' -exec rm -rf {} +
|
|
74
|
+
|
|
75
|
+
build: ## Build wheel and sdist
|
|
76
|
+
uv build
|
|
77
|
+
|
|
78
|
+
dist-check: build ## Validate built distributions with twine
|
|
79
|
+
uv run --extra dev twine check dist/*
|
|
80
|
+
|
|
81
|
+
release-check: check test-targets test-behavior dist-check ## Run alpha release readiness checks
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: j2py-converter
|
|
3
|
+
Version: 0.1.0a1
|
|
4
|
+
Summary: Java to Python source converter with line-level semantic equivalence
|
|
5
|
+
Project-URL: Homepage, https://github.com/tomanizer/j2py
|
|
6
|
+
Project-URL: Repository, https://github.com/tomanizer/j2py
|
|
7
|
+
Project-URL: Issues, https://github.com/tomanizer/j2py/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/tomanizer/j2py/blob/main/CHANGELOG.md
|
|
9
|
+
Author-email: Thomas Haederle <thomas.haederle@gmail.com>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: java,python,source-conversion,translation,tree-sitter
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Java
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
+
Requires-Python: >=3.11
|
|
24
|
+
Requires-Dist: anthropic>=0.30
|
|
25
|
+
Requires-Dist: diskcache>=5.6
|
|
26
|
+
Requires-Dist: networkx>=3.3
|
|
27
|
+
Requires-Dist: pydantic>=2.7
|
|
28
|
+
Requires-Dist: rich>=13.7
|
|
29
|
+
Requires-Dist: tenacity>=8.3
|
|
30
|
+
Requires-Dist: tree-sitter-java>=0.23
|
|
31
|
+
Requires-Dist: tree-sitter>=0.23
|
|
32
|
+
Requires-Dist: typer>=0.12
|
|
33
|
+
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
35
|
+
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
|
|
36
|
+
Requires-Dist: pytest-snapshot>=0.9; extra == 'dev'
|
|
37
|
+
Requires-Dist: pytest>=8.2; extra == 'dev'
|
|
38
|
+
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
39
|
+
Requires-Dist: twine>=5.0; extra == 'dev'
|
|
40
|
+
Description-Content-Type: text/markdown
|
|
41
|
+
|
|
42
|
+
# j2py
|
|
43
|
+
|
|
44
|
+
j2py converts Java source to reviewable Python with line-level structural
|
|
45
|
+
correspondence. The goal is not a fully idiomatic rewrite; the goal is Python that a
|
|
46
|
+
reviewer can compare against the original Java side by side.
|
|
47
|
+
|
|
48
|
+
## Current Status
|
|
49
|
+
|
|
50
|
+
j2py is a rule-development and measurement harness for Java-to-Python translation. It is
|
|
51
|
+
not yet a production Spring porting tool.
|
|
52
|
+
|
|
53
|
+
Current deterministic rule support includes:
|
|
54
|
+
|
|
55
|
+
- tree-sitter Java parsing and symbol extraction
|
|
56
|
+
- class, nested class, basic local/anonymous class helpers, interface,
|
|
57
|
+
basic and constructor-backed enum, and record skeletons
|
|
58
|
+
- interface abstract methods, default methods, and static methods
|
|
59
|
+
- fields, constructors, methods, and overloads: chained constructor delegation and
|
|
60
|
+
builder-style forwarding merge into default parameters; type-dispatch overload
|
|
61
|
+
groups emit same-named defs behind a vendored `@overloaded` runtime dispatcher
|
|
62
|
+
(ADR 0009)
|
|
63
|
+
- common expressions: literals, identifiers, field access, arrays, class literals,
|
|
64
|
+
assignments, updates, ternaries, null checks, common collection calls, and string concat
|
|
65
|
+
- common stream pipelines: `map`, `filter`, `distinct`, `sorted`, simple collectors
|
|
66
|
+
such as `toList`, `toSet`, `joining`, basic `groupingBy`/`toMap`, and supported
|
|
67
|
+
block lambdas
|
|
68
|
+
- control flow: `if`/`else`, enhanced and classic `for`, `while`, `do while`,
|
|
69
|
+
safe `switch` forms, `try`/`catch`/`finally`, `throw`, `break`, and `continue`
|
|
70
|
+
- configured import emission, naming policy, type maps, exception maps, and comment flags
|
|
71
|
+
- dependency-ordered directory translation
|
|
72
|
+
- structured diagnostics, confidence, default validation, post-LLM structural
|
|
73
|
+
verification, and optional Anthropic completion for partial translations
|
|
74
|
+
- side-by-side Java/Python review through the `j2py compare` CLI command
|
|
75
|
+
|
|
76
|
+
Known gaps include:
|
|
77
|
+
|
|
78
|
+
- two corpus constructs still tracked as strict xfail targets: advanced stream collectors
|
|
79
|
+
and long chains (`AdvancedStreams`), and `super.method(...)` receiver calls
|
|
80
|
+
(`SuperMethodCalls`)
|
|
81
|
+
- overload groups whose erased Python signatures collide (e.g. `int` vs `long`)
|
|
82
|
+
and static-method overload groups still fall back to manual-dispatch TODOs
|
|
83
|
+
- enum constant class bodies, complex enum static initialization, and annotation semantics
|
|
84
|
+
- behavioral equivalence testing between Java and Python
|
|
85
|
+
- framework semantics such as Spring dependency injection or Hibernate mappings
|
|
86
|
+
|
|
87
|
+
Graduated in `make check` (no longer listed as gaps): common switch forms, interface
|
|
88
|
+
defaults/statics, text blocks, sealed classes, records, instance `synchronized(this)`,
|
|
89
|
+
local `var` inference, switch fall-through, and anonymous class instance fields.
|
|
90
|
+
|
|
91
|
+
## Quick Start
|
|
92
|
+
|
|
93
|
+
Install the alpha from PyPI:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
pip install --pre j2py-converter
|
|
97
|
+
j2py --help
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The PyPI distribution is `j2py-converter`; the import package and console command remain
|
|
101
|
+
`j2py`.
|
|
102
|
+
|
|
103
|
+
For local development:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
uv sync --locked
|
|
107
|
+
make check
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Translate a fixture without LLM completion:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
uv run j2py translate tests/fixtures/java/HelloWorld.java --no-llm --no-validate --dry-run
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Translate a directory in dependency order:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
uv run j2py translate path/to/java/root --output translated_py --no-llm
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Open a side-by-side Java/Python diff in VS Code, generating the Python file first if
|
|
123
|
+
needed:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
uv run j2py compare tests/fixtures/java/HelloWorld.java --no-llm
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Print the compare paths without opening an editor:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
uv run j2py compare tests/fixtures/java/HelloWorld.java --no-open --no-llm
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Use LLM completion only when `ANTHROPIC_API_KEY` is set:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
ANTHROPIC_API_KEY=... uv run j2py translate SomeClass.java
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Quality Gates
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
make check # ruff + mypy strict + normal pytest suite (excludes behavior, live_llm)
|
|
145
|
+
make test-behavior # Java/Python stdout/stderr/exit-code equivalence tests (requires a JDK)
|
|
146
|
+
make test-targets # future xfail roadmap targets only (graduated targets run in make check)
|
|
147
|
+
make release-check # alpha release gate: check + targets + behavior + distribution check
|
|
148
|
+
make corpus-spring-dense-check # preferred Spring + curated-construct corpus comparison
|
|
149
|
+
make corpus-spring # historical lexical Spring-only corpus comparison
|
|
150
|
+
|
|
151
|
+
# Corpus modes:
|
|
152
|
+
make corpus-spring-dense # preferred density-based Spring + curated-construct sample
|
|
153
|
+
make corpus-spring-broad # extra modules + curated constructs/ mini-corpus
|
|
154
|
+
|
|
155
|
+
# On-demand only (requires ANTHROPIC_API_KEY):
|
|
156
|
+
make test-llm-e2e # exploratory live-LLM test of current skeleton quality
|
|
157
|
+
# or: ANTHROPIC_API_KEY=... uv run pytest -m live_llm tests/llm/test_e2e_llm.py -v -s
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
The preferred dense corpus baseline includes Spring files plus curated non-Spring
|
|
161
|
+
construct fixtures and is stored at `tests/fixtures/corpus/spring-dense-baseline.json`.
|
|
162
|
+
|
|
163
|
+
The historical lexical Spring-only baseline is:
|
|
164
|
+
|
|
165
|
+
- parse success: 100.00%
|
|
166
|
+
- generated Python syntax success: 93.00%
|
|
167
|
+
- average skeleton coverage: 94.71% across 92 coverage-bearing files
|
|
168
|
+
- full-coverage files: 65 of 92 coverage-bearing files
|
|
169
|
+
- files with unhandled constructs: 27 of 100
|
|
170
|
+
- files below 80% coverage: 4 of 92 coverage-bearing files
|
|
171
|
+
- sample size: 100 files with committed per-file failure metrics
|
|
172
|
+
|
|
173
|
+
See [docs/CORPUS_SCOREBOARD.md](docs/CORPUS_SCOREBOARD.md) and
|
|
174
|
+
[docs/TRANSLATION_TARGETS.md](docs/TRANSLATION_TARGETS.md) for the implementation
|
|
175
|
+
workflow.
|
|
176
|
+
|
|
177
|
+
## Adding Translation Support
|
|
178
|
+
|
|
179
|
+
1. Add or update a target fixture if the construct is not yet supported.
|
|
180
|
+
2. Implement the smallest deterministic rule in `j2py/translate/`.
|
|
181
|
+
3. Graduate the behavior into normal tests once it passes.
|
|
182
|
+
4. Run `make check`, `make test-targets`, and `make corpus-spring-dense-check`.
|
|
183
|
+
5. Update the dense corpus baseline only when the comparison has no regressions.
|
|
184
|
+
|
|
185
|
+
Material translation policy changes should get an ADR under `docs/decisions/`.
|
|
186
|
+
|
|
187
|
+
## Alpha Release Notes
|
|
188
|
+
|
|
189
|
+
`j2py-converter` is published as an alpha package. Expect incomplete Java construct
|
|
190
|
+
coverage, diagnostics for unsupported regions, and non-production behavior on large
|
|
191
|
+
framework-heavy codebases. The existing `j2py` PyPI name is owned by an unrelated
|
|
192
|
+
Jupyter notebook converter, so this project uses the distinct distribution name
|
|
193
|
+
`j2py-converter`.
|
|
194
|
+
|
|
195
|
+
See [docs/RELEASING.md](docs/RELEASING.md) for the alpha release checklist.
|
|
196
|
+
|
|
197
|
+
## License
|
|
198
|
+
|
|
199
|
+
MIT. See [LICENSE](LICENSE).
|