pytecode 0.0.1__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.
Files changed (57) hide show
  1. pytecode-0.0.1/LICENSE +21 -0
  2. pytecode-0.0.1/MANIFEST.in +1 -0
  3. pytecode-0.0.1/PKG-INFO +218 -0
  4. pytecode-0.0.1/README.md +192 -0
  5. pytecode-0.0.1/pyproject.toml +75 -0
  6. pytecode-0.0.1/pytecode/__init__.py +22 -0
  7. pytecode-0.0.1/pytecode/analysis.py +2402 -0
  8. pytecode-0.0.1/pytecode/attributes.py +868 -0
  9. pytecode-0.0.1/pytecode/bytes_utils.py +208 -0
  10. pytecode-0.0.1/pytecode/class_reader.py +810 -0
  11. pytecode-0.0.1/pytecode/class_writer.py +630 -0
  12. pytecode-0.0.1/pytecode/constant_pool.py +196 -0
  13. pytecode-0.0.1/pytecode/constant_pool_builder.py +844 -0
  14. pytecode-0.0.1/pytecode/constants.py +208 -0
  15. pytecode-0.0.1/pytecode/debug_info.py +319 -0
  16. pytecode-0.0.1/pytecode/descriptors.py +791 -0
  17. pytecode-0.0.1/pytecode/hierarchy.py +561 -0
  18. pytecode-0.0.1/pytecode/info.py +123 -0
  19. pytecode-0.0.1/pytecode/instructions.py +495 -0
  20. pytecode-0.0.1/pytecode/jar.py +271 -0
  21. pytecode-0.0.1/pytecode/labels.py +1041 -0
  22. pytecode-0.0.1/pytecode/model.py +929 -0
  23. pytecode-0.0.1/pytecode/modified_utf8.py +145 -0
  24. pytecode-0.0.1/pytecode/operands.py +683 -0
  25. pytecode-0.0.1/pytecode/py.typed +0 -0
  26. pytecode-0.0.1/pytecode/transforms.py +954 -0
  27. pytecode-0.0.1/pytecode/verify.py +1386 -0
  28. pytecode-0.0.1/pytecode.egg-info/PKG-INFO +218 -0
  29. pytecode-0.0.1/pytecode.egg-info/SOURCES.txt +55 -0
  30. pytecode-0.0.1/pytecode.egg-info/dependency_links.txt +1 -0
  31. pytecode-0.0.1/pytecode.egg-info/requires.txt +6 -0
  32. pytecode-0.0.1/pytecode.egg-info/top_level.txt +1 -0
  33. pytecode-0.0.1/setup.cfg +4 -0
  34. pytecode-0.0.1/tests/test_analysis.py +2974 -0
  35. pytecode-0.0.1/tests/test_api_docs.py +115 -0
  36. pytecode-0.0.1/tests/test_attributes.py +1115 -0
  37. pytecode-0.0.1/tests/test_bytes_utils.py +610 -0
  38. pytecode-0.0.1/tests/test_cfg_oracle.py +245 -0
  39. pytecode-0.0.1/tests/test_class_reader.py +438 -0
  40. pytecode-0.0.1/tests/test_class_writer.py +132 -0
  41. pytecode-0.0.1/tests/test_constant_pool.py +411 -0
  42. pytecode-0.0.1/tests/test_constant_pool_builder.py +995 -0
  43. pytecode-0.0.1/tests/test_debug_info.py +465 -0
  44. pytecode-0.0.1/tests/test_descriptors.py +586 -0
  45. pytecode-0.0.1/tests/test_helpers.py +196 -0
  46. pytecode-0.0.1/tests/test_hierarchy.py +290 -0
  47. pytecode-0.0.1/tests/test_instructions.py +724 -0
  48. pytecode-0.0.1/tests/test_jar.py +472 -0
  49. pytecode-0.0.1/tests/test_javap_parser.py +426 -0
  50. pytecode-0.0.1/tests/test_labels.py +807 -0
  51. pytecode-0.0.1/tests/test_model.py +1075 -0
  52. pytecode-0.0.1/tests/test_modified_utf8.py +33 -0
  53. pytecode-0.0.1/tests/test_operands.py +864 -0
  54. pytecode-0.0.1/tests/test_transforms.py +1064 -0
  55. pytecode-0.0.1/tests/test_validate_release_tag.py +66 -0
  56. pytecode-0.0.1/tests/test_validation.py +146 -0
  57. pytecode-0.0.1/tests/test_verify.py +2111 -0
pytecode-0.0.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 Trenton Smith
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 @@
1
+ include LICENSE README.md
@@ -0,0 +1,218 @@
1
+ Metadata-Version: 2.4
2
+ Name: pytecode
3
+ Version: 0.0.1
4
+ Summary: Python library for parsing, manipulating, and emitting JVM class files
5
+ Author: Trenton Smith
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/smithtrenton/pytecode
8
+ Project-URL: Documentation, https://smithtrenton.github.io/pytecode/
9
+ Project-URL: Repository, https://github.com/smithtrenton/pytecode
10
+ Project-URL: Issues, https://github.com/smithtrenton/pytecode/issues
11
+ Project-URL: Changelog, https://github.com/smithtrenton/pytecode/releases
12
+ Keywords: bytecode,classfile,java,jvm
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Classifier: Operating System :: OS Independent
17
+ Requires-Python: >=3.14
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Provides-Extra: dev
21
+ Requires-Dist: basedpyright<2.0.0,>=1.38.3; extra == "dev"
22
+ Requires-Dist: pdoc<17.0.0,>=16.0.0; extra == "dev"
23
+ Requires-Dist: pytest<10.0.0,>=9.0.2; extra == "dev"
24
+ Requires-Dist: ruff<0.16.0,>=0.15.7; extra == "dev"
25
+ Dynamic: license-file
26
+
27
+ # pytecode
28
+
29
+ `pytecode` is a Python 3.14+ library for parsing, inspecting, editing, validating, and emitting JVM class files and JAR archives.
30
+
31
+ It is built for Python tooling that needs direct access to Java bytecode: classfile readers and writers, archive rewriters, transformation pipelines, control-flow analysis, descriptor utilities, hierarchy-aware frame computation, and verification-oriented workflows.
32
+
33
+ ## Why pytecode?
34
+
35
+ - Parse `.class` files into typed Python dataclasses.
36
+ - Edit classes, fields, methods, and bytecode through a mutable symbolic model.
37
+ - Rewrite JAR files while preserving non-class resources and ZIP metadata.
38
+ - Recompute `max_stack`, `max_locals`, and `StackMapTable` when requested.
39
+ - Validate parsed classfiles and edited models before emission.
40
+ - Work with descriptors, signatures, labels, symbolic operands, constant pools, and debug-info policies.
41
+
42
+ ## Installation
43
+
44
+ Install from PyPI:
45
+
46
+ ```bash
47
+ pip install pytecode
48
+ ```
49
+
50
+ Or with `uv`:
51
+
52
+ ```bash
53
+ uv add pytecode
54
+ ```
55
+
56
+ `pytecode` requires Python `3.14+`.
57
+
58
+ ## Quick start
59
+
60
+ ### Parse and roundtrip a class file
61
+
62
+ ```python
63
+ from pathlib import Path
64
+
65
+ from pytecode import ClassReader, ClassWriter
66
+
67
+ reader = ClassReader.from_file("HelloWorld.class")
68
+ classfile = reader.class_info
69
+
70
+ print(classfile.major_version)
71
+ print(classfile.methods_count)
72
+
73
+ Path("HelloWorld-copy.class").write_bytes(ClassWriter.write(classfile))
74
+ ```
75
+
76
+ ### Lift to the editable model
77
+
78
+ ```python
79
+ from pathlib import Path
80
+
81
+ from pytecode import ClassModel
82
+
83
+ model = ClassModel.from_bytes(Path("HelloWorld.class").read_bytes())
84
+ print(model.name)
85
+
86
+ updated_bytes = model.to_bytes()
87
+ Path("HelloWorld-updated.class").write_bytes(updated_bytes)
88
+ ```
89
+
90
+ Use `recompute_frames=True` when an edit changes control flow or stack/local layout.
91
+
92
+ ## JAR rewriting example
93
+
94
+ `JarFile.rewrite()` can apply in-place transforms to matching classes and methods:
95
+
96
+ ```python
97
+ from pytecode import JarFile
98
+ from pytecode.constants import MethodAccessFlag
99
+ from pytecode.model import ClassModel, MethodModel
100
+ from pytecode.transforms import (
101
+ class_named,
102
+ method_is_public,
103
+ method_is_static,
104
+ method_name_matches,
105
+ on_methods,
106
+ pipeline,
107
+ )
108
+
109
+
110
+ def make_final(method: MethodModel, _owner: ClassModel) -> None:
111
+ method.access_flags |= MethodAccessFlag.FINAL
112
+
113
+
114
+ JarFile("input.jar").rewrite(
115
+ "output.jar",
116
+ transform=pipeline(
117
+ on_methods(
118
+ make_final,
119
+ where=method_name_matches(r"main") & method_is_public() & method_is_static(),
120
+ owner=class_named("HelloWorld"),
121
+ )
122
+ ),
123
+ )
124
+ ```
125
+
126
+ Transforms must mutate models in place and return `None`. For code-shape changes, pass `recompute_frames=True`. For an ASM-like lift path that omits debug metadata, pass `skip_debug=True`.
127
+
128
+ ## Public surface
129
+
130
+ Top-level exports:
131
+
132
+ - `pytecode.ClassReader` and `pytecode.ClassWriter` for raw classfile parsing and emission.
133
+ - `pytecode.JarFile` for archive reads, mutation, and safe rewrite-to-disk.
134
+ - `pytecode.ClassModel` for mutable editing with symbolic references.
135
+
136
+ Supported submodules:
137
+
138
+ - `pytecode.transforms` for composable class, field, method, and code transforms.
139
+ - `pytecode.labels` for label-aware bytecode editing helpers.
140
+ - `pytecode.operands` for symbolic operand wrappers.
141
+ - `pytecode.analysis` for CFG construction, frame simulation, and recomputation helpers.
142
+ - `pytecode.verify` for structural validation and diagnostics.
143
+ - `pytecode.hierarchy` for type and override resolution helpers.
144
+ - `pytecode.descriptors` for JVM descriptors and generic signatures.
145
+ - `pytecode.constant_pool_builder` for deterministic constant-pool construction.
146
+ - `pytecode.modified_utf8` for JVM Modified UTF-8 encoding and decoding.
147
+ - `pytecode.debug_info` for explicit debug-info preservation and stripping policies.
148
+
149
+ ## Documentation
150
+
151
+ - Development docs overview: [docs/OVERVIEW.md](https://github.com/smithtrenton/pytecode/blob/master/docs/OVERVIEW.md)
152
+ - Hosted API reference: <https://smithtrenton.github.io/pytecode/>
153
+
154
+ ## Development
155
+
156
+ Create a local environment with development tools:
157
+
158
+ ```powershell
159
+ uv sync --extra dev
160
+ ```
161
+
162
+ Common checks:
163
+
164
+ ```powershell
165
+ uv run ruff check .
166
+ uv run ruff format --check .
167
+ uv run basedpyright
168
+ uv run pytest -q
169
+ uv run python tools\generate_api_docs.py --check
170
+ ```
171
+
172
+ Generate local API reference HTML with:
173
+
174
+ ```powershell
175
+ uv run python tools\generate_api_docs.py
176
+ ```
177
+
178
+ Build source and wheel distributions locally:
179
+
180
+ ```powershell
181
+ uv build
182
+ ```
183
+
184
+ The `oracle`-marked CFG tests lazily cache ASM 9.7.1 test jars under `.pytest_cache\pytecode-oracle` and also honor manually seeded jars in `tests\resources\oracle\lib`. If `java`, `javac`, or the ASM jars are unavailable, that suite skips without failing the rest of the test run.
185
+
186
+ ## Release automation
187
+
188
+ PyPI releases are published from GitHub Actions by pushing an immutable `v<version>` tag that matches `project.version` in `pyproject.toml`. The release workflow reruns validation on the tagged commit, builds both `sdist` and `wheel` with `uv build`, and publishes from the protected `pypi` environment via PyPI Trusted Publishing.
189
+
190
+ Release procedure:
191
+
192
+ ```powershell
193
+ # 1) bump project.version in pyproject.toml
194
+ uv run ruff check .
195
+ uv run ruff format --check .
196
+ uv run basedpyright
197
+ uv run pytest -q
198
+ uv run python tools\generate_api_docs.py --check
199
+
200
+ git commit -am "Bump version to X.Y.Z"
201
+ git push origin master
202
+ git tag vX.Y.Z
203
+ git push origin vX.Y.Z
204
+ ```
205
+
206
+ The release workflow rejects tags that do not match `project.version`. Treat release tags as immutable: if a tag or published artifact is wrong, bump to a new version and publish a new tag instead of force-pushing the old one. If the workflow fails before the publish step because of environment approval or a transient PyPI issue, rerun the workflow for the same tag instead of moving the tag.
207
+
208
+ ## Repository utilities
209
+
210
+ `run.py` is a manual smoke-test helper that parses a JAR file, writes pretty-printed parsed class structures under `<jar parent>\output\<jar stem>\parsed\`, and writes class-model-derived rewritten `.class` files plus copied resources under `<jar parent>\output\<jar stem>\rewritten\`.
211
+
212
+ Example:
213
+
214
+ ```powershell
215
+ uv run python .\run.py .\path\to\input.jar
216
+ ```
217
+
218
+ The script prints read, parse, lift, write, and rewrite timings plus class and resource counts to stdout.
@@ -0,0 +1,192 @@
1
+ # pytecode
2
+
3
+ `pytecode` is a Python 3.14+ library for parsing, inspecting, editing, validating, and emitting JVM class files and JAR archives.
4
+
5
+ It is built for Python tooling that needs direct access to Java bytecode: classfile readers and writers, archive rewriters, transformation pipelines, control-flow analysis, descriptor utilities, hierarchy-aware frame computation, and verification-oriented workflows.
6
+
7
+ ## Why pytecode?
8
+
9
+ - Parse `.class` files into typed Python dataclasses.
10
+ - Edit classes, fields, methods, and bytecode through a mutable symbolic model.
11
+ - Rewrite JAR files while preserving non-class resources and ZIP metadata.
12
+ - Recompute `max_stack`, `max_locals`, and `StackMapTable` when requested.
13
+ - Validate parsed classfiles and edited models before emission.
14
+ - Work with descriptors, signatures, labels, symbolic operands, constant pools, and debug-info policies.
15
+
16
+ ## Installation
17
+
18
+ Install from PyPI:
19
+
20
+ ```bash
21
+ pip install pytecode
22
+ ```
23
+
24
+ Or with `uv`:
25
+
26
+ ```bash
27
+ uv add pytecode
28
+ ```
29
+
30
+ `pytecode` requires Python `3.14+`.
31
+
32
+ ## Quick start
33
+
34
+ ### Parse and roundtrip a class file
35
+
36
+ ```python
37
+ from pathlib import Path
38
+
39
+ from pytecode import ClassReader, ClassWriter
40
+
41
+ reader = ClassReader.from_file("HelloWorld.class")
42
+ classfile = reader.class_info
43
+
44
+ print(classfile.major_version)
45
+ print(classfile.methods_count)
46
+
47
+ Path("HelloWorld-copy.class").write_bytes(ClassWriter.write(classfile))
48
+ ```
49
+
50
+ ### Lift to the editable model
51
+
52
+ ```python
53
+ from pathlib import Path
54
+
55
+ from pytecode import ClassModel
56
+
57
+ model = ClassModel.from_bytes(Path("HelloWorld.class").read_bytes())
58
+ print(model.name)
59
+
60
+ updated_bytes = model.to_bytes()
61
+ Path("HelloWorld-updated.class").write_bytes(updated_bytes)
62
+ ```
63
+
64
+ Use `recompute_frames=True` when an edit changes control flow or stack/local layout.
65
+
66
+ ## JAR rewriting example
67
+
68
+ `JarFile.rewrite()` can apply in-place transforms to matching classes and methods:
69
+
70
+ ```python
71
+ from pytecode import JarFile
72
+ from pytecode.constants import MethodAccessFlag
73
+ from pytecode.model import ClassModel, MethodModel
74
+ from pytecode.transforms import (
75
+ class_named,
76
+ method_is_public,
77
+ method_is_static,
78
+ method_name_matches,
79
+ on_methods,
80
+ pipeline,
81
+ )
82
+
83
+
84
+ def make_final(method: MethodModel, _owner: ClassModel) -> None:
85
+ method.access_flags |= MethodAccessFlag.FINAL
86
+
87
+
88
+ JarFile("input.jar").rewrite(
89
+ "output.jar",
90
+ transform=pipeline(
91
+ on_methods(
92
+ make_final,
93
+ where=method_name_matches(r"main") & method_is_public() & method_is_static(),
94
+ owner=class_named("HelloWorld"),
95
+ )
96
+ ),
97
+ )
98
+ ```
99
+
100
+ Transforms must mutate models in place and return `None`. For code-shape changes, pass `recompute_frames=True`. For an ASM-like lift path that omits debug metadata, pass `skip_debug=True`.
101
+
102
+ ## Public surface
103
+
104
+ Top-level exports:
105
+
106
+ - `pytecode.ClassReader` and `pytecode.ClassWriter` for raw classfile parsing and emission.
107
+ - `pytecode.JarFile` for archive reads, mutation, and safe rewrite-to-disk.
108
+ - `pytecode.ClassModel` for mutable editing with symbolic references.
109
+
110
+ Supported submodules:
111
+
112
+ - `pytecode.transforms` for composable class, field, method, and code transforms.
113
+ - `pytecode.labels` for label-aware bytecode editing helpers.
114
+ - `pytecode.operands` for symbolic operand wrappers.
115
+ - `pytecode.analysis` for CFG construction, frame simulation, and recomputation helpers.
116
+ - `pytecode.verify` for structural validation and diagnostics.
117
+ - `pytecode.hierarchy` for type and override resolution helpers.
118
+ - `pytecode.descriptors` for JVM descriptors and generic signatures.
119
+ - `pytecode.constant_pool_builder` for deterministic constant-pool construction.
120
+ - `pytecode.modified_utf8` for JVM Modified UTF-8 encoding and decoding.
121
+ - `pytecode.debug_info` for explicit debug-info preservation and stripping policies.
122
+
123
+ ## Documentation
124
+
125
+ - Development docs overview: [docs/OVERVIEW.md](https://github.com/smithtrenton/pytecode/blob/master/docs/OVERVIEW.md)
126
+ - Hosted API reference: <https://smithtrenton.github.io/pytecode/>
127
+
128
+ ## Development
129
+
130
+ Create a local environment with development tools:
131
+
132
+ ```powershell
133
+ uv sync --extra dev
134
+ ```
135
+
136
+ Common checks:
137
+
138
+ ```powershell
139
+ uv run ruff check .
140
+ uv run ruff format --check .
141
+ uv run basedpyright
142
+ uv run pytest -q
143
+ uv run python tools\generate_api_docs.py --check
144
+ ```
145
+
146
+ Generate local API reference HTML with:
147
+
148
+ ```powershell
149
+ uv run python tools\generate_api_docs.py
150
+ ```
151
+
152
+ Build source and wheel distributions locally:
153
+
154
+ ```powershell
155
+ uv build
156
+ ```
157
+
158
+ The `oracle`-marked CFG tests lazily cache ASM 9.7.1 test jars under `.pytest_cache\pytecode-oracle` and also honor manually seeded jars in `tests\resources\oracle\lib`. If `java`, `javac`, or the ASM jars are unavailable, that suite skips without failing the rest of the test run.
159
+
160
+ ## Release automation
161
+
162
+ PyPI releases are published from GitHub Actions by pushing an immutable `v<version>` tag that matches `project.version` in `pyproject.toml`. The release workflow reruns validation on the tagged commit, builds both `sdist` and `wheel` with `uv build`, and publishes from the protected `pypi` environment via PyPI Trusted Publishing.
163
+
164
+ Release procedure:
165
+
166
+ ```powershell
167
+ # 1) bump project.version in pyproject.toml
168
+ uv run ruff check .
169
+ uv run ruff format --check .
170
+ uv run basedpyright
171
+ uv run pytest -q
172
+ uv run python tools\generate_api_docs.py --check
173
+
174
+ git commit -am "Bump version to X.Y.Z"
175
+ git push origin master
176
+ git tag vX.Y.Z
177
+ git push origin vX.Y.Z
178
+ ```
179
+
180
+ The release workflow rejects tags that do not match `project.version`. Treat release tags as immutable: if a tag or published artifact is wrong, bump to a new version and publish a new tag instead of force-pushing the old one. If the workflow fails before the publish step because of environment approval or a transient PyPI issue, rerun the workflow for the same tag instead of moving the tag.
181
+
182
+ ## Repository utilities
183
+
184
+ `run.py` is a manual smoke-test helper that parses a JAR file, writes pretty-printed parsed class structures under `<jar parent>\output\<jar stem>\parsed\`, and writes class-model-derived rewritten `.class` files plus copied resources under `<jar parent>\output\<jar stem>\rewritten\`.
185
+
186
+ Example:
187
+
188
+ ```powershell
189
+ uv run python .\run.py .\path\to\input.jar
190
+ ```
191
+
192
+ The script prints read, parse, lift, write, and rewrite timings plus class and resource counts to stdout.
@@ -0,0 +1,75 @@
1
+ [build-system]
2
+ requires = ["setuptools>=82.0.1,<83.0.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [tool.setuptools]
6
+ include-package-data = true
7
+
8
+ [tool.setuptools.packages.find]
9
+ include = ["pytecode"]
10
+
11
+ [tool.setuptools.package-data]
12
+ pytecode = ["py.typed"]
13
+
14
+ [project]
15
+ name = "pytecode"
16
+ version = "0.0.1"
17
+ description = "Python library for parsing, manipulating, and emitting JVM class files"
18
+ readme = "README.md"
19
+ authors = [{ name = "Trenton Smith" }]
20
+ license = "MIT"
21
+ license-files = ["LICENSE"]
22
+ requires-python = ">=3.14"
23
+ keywords = ["bytecode", "classfile", "java", "jvm"]
24
+ classifiers = [
25
+ "Programming Language :: Python :: 3",
26
+ "Programming Language :: Python :: 3 :: Only",
27
+ "Programming Language :: Python :: 3.14",
28
+ "Operating System :: OS Independent",
29
+ ]
30
+ dependencies = []
31
+
32
+ [project.urls]
33
+ Homepage = "https://github.com/smithtrenton/pytecode"
34
+ Documentation = "https://smithtrenton.github.io/pytecode/"
35
+ Repository = "https://github.com/smithtrenton/pytecode"
36
+ Issues = "https://github.com/smithtrenton/pytecode/issues"
37
+ Changelog = "https://github.com/smithtrenton/pytecode/releases"
38
+
39
+ [project.optional-dependencies]
40
+ dev = [
41
+ "basedpyright>=1.38.3,<2.0.0",
42
+ "pdoc>=16.0.0,<17.0.0",
43
+ "pytest>=9.0.2,<10.0.0",
44
+ "ruff>=0.15.7,<0.16.0",
45
+ ]
46
+
47
+ [tool.basedpyright]
48
+ pythonVersion = "3.14"
49
+ typeCheckingMode = "strict"
50
+ include = ["pytecode", "run.py", "tools", "tests"]
51
+ exclude = ["output", "venv", ".venv"]
52
+ reportMissingTypeStubs = false
53
+ reportAttributeAccessIssue = false
54
+ reportPrivateUsage = false
55
+
56
+ [tool.ruff]
57
+ target-version = "py314"
58
+ line-length = 120
59
+ extend-exclude = [
60
+ "output",
61
+ "venv",
62
+ ".venv",
63
+ ]
64
+
65
+ [tool.ruff.lint]
66
+ select = ["E", "F", "I", "UP"]
67
+
68
+ [tool.pytest.ini_options]
69
+ pythonpath = ["."]
70
+ markers = [
71
+ "oracle: JVM-backed differential CFG validation against the ASM oracle",
72
+ ]
73
+
74
+ [tool.uv]
75
+ required-version = ">=0.10.12"
@@ -0,0 +1,22 @@
1
+ """Python library for parsing, inspecting, manipulating, and emitting JVM class files.
2
+
3
+ Provides four top-level entry points:
4
+
5
+ - ``ClassReader`` — parse ``.class`` bytes into a ``ClassFile`` tree.
6
+ - ``ClassWriter`` — serialize a ``ClassFile`` tree back to ``.class`` bytes.
7
+ - ``ClassModel`` — mutable editing model with symbolic references and
8
+ label-aware code editing.
9
+ - ``JarFile`` — read, mutate, and rewrite JAR archives.
10
+
11
+ Additional submodules expose transforms, descriptors, analysis, hierarchy
12
+ resolution, validation, operands, labels, debug-info helpers, and the
13
+ underlying data types. See ``pytecode.transforms``, ``pytecode.analysis``,
14
+ ``pytecode.verify``, and the other documented submodules for details.
15
+ """
16
+
17
+ from .class_reader import ClassReader
18
+ from .class_writer import ClassWriter
19
+ from .jar import JarFile
20
+ from .model import ClassModel
21
+
22
+ __all__ = ["ClassModel", "ClassReader", "ClassWriter", "JarFile"]