Mugshot produces code diffs for targeted classes in two jar files.
Purpose built to support Myelin so includes a parser to automatically idenitfy classes from jpype wrappers in a python codebase.
- CFR to decompile class files
- go-difflib for source diffs
- treesitter for Python code parsing
go build -o bin/mugshot ./cmd/mugshot- Java runtime available on PATH (
java -version) - CFR decompiler jar (
--cfr-path=/abs/path/to/cfr-<version>.jar)
--jar1and--jar2(required): absolute paths to the JARs to compare- One of:
--scan=/abs/path/to/python/rootto discover JPypeJClass("...")usages--classnames=a.b.C1,a.b.C2for explicit FQCNs
- Output:
--out=stdout(default) or--out=/abs/path/diff.txt(atomic write)--format=unified|context|raw(default: unified)
- Behavior:
--summary=true|falseemit a summary header (default: true)--fail-on-missing=true|falsefail if a class is missing or decompilation fails (default: false)--include-inner=true|falsealso diff inner classes (default: true)
- Performance:
--concurrency=N(default: CPU count)--cache-dir=~/.cache/mugshotoverride cache location--cfr-path=/abs/path/cfr.jarCFR jar to execute
- A summary header is always printed first (unless
--summary=false), indicating whether differences were found, and listing:- each processed FQCN
- class file entries considered (including inner classes when enabled)
- any entries that failed decompilation
- Diff hunks follow the summary when there are differences, using the selected format.
If your Jpype class wrapper is uses dynamic string composition like f-strings it will not be included.
jpype.JClass(f"com.example.v{version}")
- Scan a Python project and write to stdout:
mugshot --jar1=/path/a.jar --jar2=/path/b.jar --scan=/path/python --cfr-path=/path/to/cfr.jar --out=stdout- Scan a single Python file and write to stdout (stdout is default):
mugshot --jar1=/path/a.jar --jar2=/path/b.jar --scan=/path/python_file.py --cfr-path=/path/to/cfr.jar- Explicit classes and write to a file:
mugshot --jar1=/path/a.jar --jar2=/path/b.jar --classnames=a.b.C1,a.b.C2 --cfr-path=/path/to/cfr.jar --out=/tmp/diff.txt- Include inner classes and show context diff:
mugshot --jar1=/path/a.jar --jar2=/path/b.jar --classnames=a.b.Outer --include-inner=true --format=context --cfr-path=/path/to/cfr.jar- Simple scan for classes:
mugshot --scan=/path/python