# pm3py Refactor Progress **Design:** [2026-03-18-refactor-design.md](2026-03-18-refactor-design.md) **Branch:** merged to `master` **Started:** 2026-03-18 ## Phase 1 — Create `core/`, normalize names, fix imports **Status: Complete** ### What was done - Created `pm3py/core/` sub-package - Moved all source modules into `core/`: - `protocol.py`, `transport.py`, `client.py`, `hw.py`, `hf.py`, `lf.py` — moved as-is - `hf_14a.py` → `hf_iso14a.py` (renamed) - `hf_15.py` → `hf_iso15.py` (renamed) - `hf_mf.py` → `hf_mfc.py` (renamed) - Normalized client attributes: - `hf.a14` → `hf.iso14a` - `hf.mf` → `hf.mfc` - `hf.iso15` — unchanged - Created `core/__init__.py` re-exporting: `Proxmark3`, `FirmwareInfo`, `PM3Transport`, `PM3Error`, `PM3Response`, `PM3Status`, `Cmd` - Updated `pm3py/__init__.py` to import from `.core.*` - Updated all 10 test files (imports + attribute references) - **30/30 tests passing** ### Backward compatibility - `from pm3py import Proxmark3` still works (re-exported) - **Breaking:** `hf.a14` → `hf.iso14a`, `hf.mf` → `hf.mfc` - **Breaking:** Direct imports like `from pm3py.hf_14a import ...` → `from pm3py.core.hf_iso14a import ...` ## Phase 2 — Extract `sniff/` **Status: Complete** Extracted sniff infrastructure from `core/hf_iso15.py` (615→130 lines) into two packages: **`pm3py/trace/`** — shared trace infrastructure (used by sniff, sim, reader): - `trace.py` — `parse_tracelog()`, `TRACELOG_HDR_SIZE` (protocol-agnostic) - `ndef.py` — NDEF TLV/record decode (`decode_ndef_annotation()`) - `decode_iso15.py` — ISO 15693 command/response decoders, command tables - `format.py` — ANSI color formatting, `format_sniff_line()` **`pm3py/sniff/`** — sniff orchestration (consumes trace/): - `session.py` — `SniffSession` with `iso15()` method (replaces `sniff_decoded()`) - `__init__.py` — re-exports trace symbols for convenience `core/hf_iso15.py` retains `HF15Commands` (scan/rdbl/wrbl/sniff) and re-exports trace symbols for backward compat. `download_trace()` and `sniff_decoded()` delegate to `SniffSession`. **65/65 tests passing** (35 sniff/trace tests work through re-exports, no test changes needed). ## Phase 3 — Transponder models in `transponders/` **Status: Complete** Moved 23 IC-specific files from `sim/` into `transponders/` organized by standard/manufacturer: ``` transponders/ hf/ iso14443a/ base.py # Tag14443A, Tag14443A_3/4, Reader14443A ndef.py # NfcType2Tag, NfcType4Tag nxp/ crypto1.py # Crypto1 mifare_classic.py # MifareClassicTag, MifareClassicReader desfire.py # DesfireTag, DesfireReader iso15693/ base.py # Tag15693, Reader15693 type5.py # NfcType5Tag, ndef_text/uri/mime nxp/ auth_password.py # NxpPasswordAuth auth_aes.py # NxpAesAuth nxp_icode.py → icode_slix → icode_slix2 → icode3, icode_dna ntag5_platform → ntag5_switch, ntag5_link → ntag5_boost st/ # future ST25TV lf/ base.py # TagLF, ReaderLF, Modulation em/em4100.py # EM4100Tag, EM4100Reader hid/hid.py # HIDProxTag, HIDReader atmel/t5577.py # T5577Tag, T5577Reader implants.py # xEM, xNT, xM1, FlexDF, NExT ``` Backward-compat shims left in `sim/` — `from pm3py.sim import IcodeSlix2Tag` still works. `sim/__init__.py` imports from canonical `transponders/` locations. **751 tests passing, zero test changes.** ## Phase 4 — sim/ infrastructure + reader/ scaffold **Status: Complete** ### sim/ (migrated + cleaned) Sim framework migrated from `.worktrees/sim-framework/`, then transponder models extracted to `transponders/`. sim/ now contains only simulation infrastructure: - Core: `frame.py`, `memory.py`, `transponder.py` (ABC), `reader.py` (ABC), `medium.py` - Sessions: `sim_session.py`, `dual_session.py` - Tools: `table_compiler.py`, `trace_fmt.py`, `fuzzer.py`, `relay.py`, `replay.py`, `pm3medium.py` - MCU: `mcu_bridge.py`, `mcu_protocol.py` - Access control: `access_control/` - Backward-compat shims for all moved transponder files ### reader/ (scaffolded) - `reader/hf/nxp/` — NXP reader ICs (CLRC663, PN5xx) - `reader/hf/st/` — ST reader ICs - `reader/lf/` - `reader/modes/` — inventory, programming, access control workflows ## DX improvements - `source activate` — core imports (Proxmark3, Cmd) - `source activate sim` — + SimSession, all transponder models - `source activate sniff` — + SniffSession, trace decoders - `source activate all` — everything ## Next Steps - Reader modes: implement inventory, programming, access workflows in `reader/modes/` - Unify `sim/trace_fmt.py` with `trace/` package (dedup 15693 decoders, move 14443-A decoders) - Sniff: add `decode_iso14a.py` using decoders from `sim/trace_fmt.py` - Sim worktree cleanup: verify parity with master, then remove `.worktrees/sim-framework/`