4.9 KiB
pm3py Refactor Progress
Design: 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-ishf_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.iso14ahf.mf→hf.mfchf.iso15— unchanged
- Created
core/__init__.pyre-exporting:Proxmark3,FirmwareInfo,PM3Transport,PM3Error,PM3Response,PM3Status,Cmd - Updated
pm3py/__init__.pyto import from.core.* - Updated all 10 test files (imports + attribute references)
- 30/30 tests passing
Backward compatibility
from pm3py import Proxmark3still 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 tablesformat.py— ANSI color formatting,format_sniff_line()
pm3py/sniff/ — sniff orchestration (consumes trace/):
session.py—SniffSessionwithiso15()method (replacessniff_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 ICsreader/lf/reader/modes/— inventory, programming, access control workflows
DX improvements
source activate— core imports (Proxmark3, Cmd)source activate sim— + SimSession, all transponder modelssource activate sniff— + SniffSession, trace decoderssource activate all— everything
Next Steps
- Reader modes: implement inventory, programming, access workflows in
reader/modes/ - Unify
sim/trace_fmt.pywithtrace/package (dedup 15693 decoders, move 14443-A decoders) - Sniff: add
decode_iso14a.pyusing decoders fromsim/trace_fmt.py - Sim worktree cleanup: verify parity with master, then remove
.worktrees/sim-framework/