pytecode 0.0.1__py3-none-any.whl

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.
@@ -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,27 @@
1
+ pytecode/__init__.py,sha256=0WijlZ3llZ5PBPC9yFTLCi17uprAZa5HBjQPrk8OBIE,930
2
+ pytecode/analysis.py,sha256=H8f2uElVeY_6jVUvcb9BW7pDtmiMKpKdvrT3ej4V1Vg,77641
3
+ pytecode/attributes.py,sha256=M2p_Ni7fOx7XnYQXinOIfFItnbRHHC8Dded0tt1WxZ0,20592
4
+ pytecode/bytes_utils.py,sha256=rmVczsgq-TI3EGPO2N1Go93eO04_G3RIPWxFiEsqoO0,5465
5
+ pytecode/class_reader.py,sha256=7GFldG94gaszgjQ1NEh9UwbVW8qKQ-l438TRNBxCOVs,38670
6
+ pytecode/class_writer.py,sha256=RvOtmUJRciKaJu4QJ_WvfEb3LE6ZCMMryvhPrCAA6Y0,24317
7
+ pytecode/constant_pool.py,sha256=mSww_ZznLTe-PeADLfxFoIuphTLAbuNAr9OB8RPsPDc,4005
8
+ pytecode/constant_pool_builder.py,sha256=zKebqffE8qObqsjK6FXtjCCEbhit-iIxPC40HecZxPU,31450
9
+ pytecode/constants.py,sha256=b_1p13jtCbFixmBNytfX3pzHj7en9rMFnXu-33WTvhk,5409
10
+ pytecode/debug_info.py,sha256=Yst0MNh39r4Z92PZ6foZXnv9NP2Ymyg76zFjb6jwZWs,9903
11
+ pytecode/descriptors.py,sha256=0q6z5GbijYZOf8xMPTPjtCWIGAZK8C7f-F8r2xmFYD0,23556
12
+ pytecode/hierarchy.py,sha256=SseaGtZnN1XKY68iEgrcJsgYLpjLCWVkRll-FyiDR9I,18380
13
+ pytecode/info.py,sha256=CX_JAVcFX3Ps7j1kabPT1RERFpFwETe4vel39r8kU2w,4824
14
+ pytecode/instructions.py,sha256=oK0yrNu60otwc98GifXgUO64fhhKEDvrWTPeUOIAJ4o,12538
15
+ pytecode/jar.py,sha256=lERB0D60WSQIM7aepLtRQt1-Eaj51EXL6jUpnUYz04c,9923
16
+ pytecode/labels.py,sha256=aFXz9s3uwK5UScLZAi3RLG4md1Wf5i_JN2U-Eh065HU,36235
17
+ pytecode/model.py,sha256=OkSHCOhm4z0x1uFS7dfd0-pIiLL0jqUSUAuKOhFpbiU,34583
18
+ pytecode/modified_utf8.py,sha256=bJ_xeJMurV70NmayMrO4ILeyimUGXrot6AsmVf87CVs,4801
19
+ pytecode/operands.py,sha256=k_aTMgwVxRGBdVjY0Tv7JYRIIf_VwKwJh92U3AD_cd8,21320
20
+ pytecode/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
+ pytecode/transforms.py,sha256=FSxRjQHizHRdfRL06WUF-k_JZ8DX7I_ohno9EpXR0C4,27274
22
+ pytecode/verify.py,sha256=Rt-GBoMlX9U4ei6NylVbbFZ15nKptCkgTbOqlwGZkM8,53086
23
+ pytecode-0.0.1.dist-info/licenses/LICENSE,sha256=xcOCdQxGtsJL7y8NYaYJZnoZNcnvMejSkpBKAhvlUe4,1070
24
+ pytecode-0.0.1.dist-info/METADATA,sha256=hl7hQjs3pCETvNiHwuAS7ALw88uI1WcDKa1nhztpC8Q,7382
25
+ pytecode-0.0.1.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
26
+ pytecode-0.0.1.dist-info/top_level.txt,sha256=L1TzD0q2abDDznp3W8eWNoHtZK_pH3oXoEHWf7Su1Sg,9
27
+ pytecode-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -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
+ pytecode