Java to Python source converter with line-level semantic equivalence
Project description
j2py
j2py converts Java source to reviewable Python with line-level structural correspondence. The goal is not a fully idiomatic rewrite; the goal is Python that a reviewer can compare against the original Java side by side.
Current Status
j2py is a rule-development and measurement harness for Java-to-Python translation. It is not yet a production Spring porting tool.
Current deterministic rule support includes:
- tree-sitter Java parsing and symbol extraction
- class, nested class, basic local/anonymous class helpers, interface, basic and constructor-backed enum, and record skeletons
- interface abstract methods, default methods, and static methods
- fields, constructors, methods, and overloads: chained constructor delegation and
builder-style forwarding merge into default parameters; type-dispatch overload
groups emit same-named defs behind a vendored
@overloadedruntime dispatcher (ADR 0009) - common expressions: literals, identifiers, field access, arrays, class literals, assignments, updates, ternaries, null checks, common collection calls, and string concat
- common stream pipelines:
map,filter,distinct,sorted, simple collectors such astoList,toSet,joining, basicgroupingBy/toMap, and supported block lambdas - control flow:
if/else, enhanced and classicfor,while,do while, safeswitchforms,try/catch/finally,throw,break, andcontinue - configured import emission, naming policy, type maps, exception maps, and comment flags
- dependency-ordered directory translation
- structured diagnostics, confidence, default validation, post-LLM structural verification, and optional Anthropic completion for partial translations
- side-by-side Java/Python review through the
j2py compareCLI command
Known gaps include:
- two corpus constructs still tracked as strict xfail targets: advanced stream collectors
and long chains (
AdvancedStreams), andsuper.method(...)receiver calls (SuperMethodCalls) - overload groups whose erased Python signatures collide (e.g.
intvslong) and static-method overload groups still fall back to manual-dispatch TODOs - enum constant class bodies, complex enum static initialization, and annotation semantics
- behavioral equivalence testing between Java and Python
- framework semantics such as Spring dependency injection or Hibernate mappings
Graduated in make check (no longer listed as gaps): common switch forms, interface
defaults/statics, text blocks, sealed classes, records, instance synchronized(this),
local var inference, switch fall-through, and anonymous class instance fields.
Quick Start
Install the alpha from PyPI:
pip install --pre j2py-converter
j2py --help
The PyPI distribution is j2py-converter; the import package and console command remain
j2py.
For local development:
uv sync --locked
make check
Translate a fixture without LLM completion:
uv run j2py translate tests/fixtures/java/HelloWorld.java --no-llm --no-validate --dry-run
Translate a directory in dependency order:
uv run j2py translate path/to/java/root --output translated_py --no-llm
Open a side-by-side Java/Python diff in VS Code, generating the Python file first if needed:
uv run j2py compare tests/fixtures/java/HelloWorld.java --no-llm
Print the compare paths without opening an editor:
uv run j2py compare tests/fixtures/java/HelloWorld.java --no-open --no-llm
Use LLM completion only when ANTHROPIC_API_KEY is set:
ANTHROPIC_API_KEY=... uv run j2py translate SomeClass.java
Quality Gates
make check # ruff + mypy strict + normal pytest suite (excludes behavior, live_llm)
make test-behavior # Java/Python stdout/stderr/exit-code equivalence tests (requires a JDK)
make test-targets # future xfail roadmap targets only (graduated targets run in make check)
make release-check # alpha release gate: check + targets + behavior + distribution check
make corpus-spring-dense-check # preferred Spring + curated-construct corpus comparison
make corpus-spring # historical lexical Spring-only corpus comparison
# Corpus modes:
make corpus-spring-dense # preferred density-based Spring + curated-construct sample
make corpus-spring-broad # extra modules + curated constructs/ mini-corpus
# On-demand only (requires ANTHROPIC_API_KEY):
make test-llm-e2e # exploratory live-LLM test of current skeleton quality
# or: ANTHROPIC_API_KEY=... uv run pytest -m live_llm tests/llm/test_e2e_llm.py -v -s
The preferred dense corpus baseline includes Spring files plus curated non-Spring
construct fixtures and is stored at tests/fixtures/corpus/spring-dense-baseline.json.
The historical lexical Spring-only baseline is:
- parse success: 100.00%
- generated Python syntax success: 93.00%
- average skeleton coverage: 94.71% across 92 coverage-bearing files
- full-coverage files: 65 of 92 coverage-bearing files
- files with unhandled constructs: 27 of 100
- files below 80% coverage: 4 of 92 coverage-bearing files
- sample size: 100 files with committed per-file failure metrics
See docs/CORPUS_SCOREBOARD.md and docs/TRANSLATION_TARGETS.md for the implementation workflow.
Adding Translation Support
- Add or update a target fixture if the construct is not yet supported.
- Implement the smallest deterministic rule in
j2py/translate/. - Graduate the behavior into normal tests once it passes.
- Run
make check,make test-targets, andmake corpus-spring-dense-check. - Update the dense corpus baseline only when the comparison has no regressions.
Material translation policy changes should get an ADR under docs/decisions/.
Alpha Release Notes
j2py-converter is published as an alpha package. Expect incomplete Java construct
coverage, diagnostics for unsupported regions, and non-production behavior on large
framework-heavy codebases. The existing j2py PyPI name is owned by an unrelated
Jupyter notebook converter, so this project uses the distinct distribution name
j2py-converter.
See docs/RELEASING.md for the alpha release checklist.
License
MIT. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file j2py_converter-0.1.0a1.tar.gz.
File metadata
- Download URL: j2py_converter-0.1.0a1.tar.gz
- Upload date:
- Size: 126.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5ac582bedd06dd0aadf9c877511c54e57697c78f349545e48162538ed0826f0d
|
|
| MD5 |
eaa901da4df66bf5b3928c0f42b81c2d
|
|
| BLAKE2b-256 |
4306a47f4a0acb516d8987efec4de99e527913038f08472751f3ee2794fd7f87
|
Provenance
The following attestation bundles were made for j2py_converter-0.1.0a1.tar.gz:
Publisher:
publish.yml on tomanizer/j2py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
j2py_converter-0.1.0a1.tar.gz -
Subject digest:
5ac582bedd06dd0aadf9c877511c54e57697c78f349545e48162538ed0826f0d - Sigstore transparency entry: 1790316367
- Sigstore integration time:
-
Permalink:
tomanizer/j2py@8bb901d766df2d9fd7c70cd570f1244f7ee4fa28 -
Branch / Tag:
refs/tags/v0.1.0a1 - Owner: https://github.com/tomanizer
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8bb901d766df2d9fd7c70cd570f1244f7ee4fa28 -
Trigger Event:
release
-
Statement type:
File details
Details for the file j2py_converter-0.1.0a1-py3-none-any.whl.
File metadata
- Download URL: j2py_converter-0.1.0a1-py3-none-any.whl
- Upload date:
- Size: 69.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
07d540a1ca65ea6b9511b225ec5bcf4f27f3a7463392276ee6b5b09b1c7c8067
|
|
| MD5 |
f94b9e11c98ae639924b62d20d6f6b09
|
|
| BLAKE2b-256 |
6222c008abf864e18d9a6a2ec6a902c06d307e2c90a95f8c3bb9e9702cd986b5
|
Provenance
The following attestation bundles were made for j2py_converter-0.1.0a1-py3-none-any.whl:
Publisher:
publish.yml on tomanizer/j2py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
j2py_converter-0.1.0a1-py3-none-any.whl -
Subject digest:
07d540a1ca65ea6b9511b225ec5bcf4f27f3a7463392276ee6b5b09b1c7c8067 - Sigstore transparency entry: 1790316424
- Sigstore integration time:
-
Permalink:
tomanizer/j2py@8bb901d766df2d9fd7c70cd570f1244f7ee4fa28 -
Branch / Tag:
refs/tags/v0.1.0a1 - Owner: https://github.com/tomanizer
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8bb901d766df2d9fd7c70cd570f1244f7ee4fa28 -
Trigger Event:
release
-
Statement type: