nfcscript 0.0.14__tar.gz → 0.0.16__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 (29) hide show
  1. {nfcscript-0.0.14 → nfcscript-0.0.16}/PKG-INFO +40 -20
  2. {nfcscript-0.0.14 → nfcscript-0.0.16}/README.md +39 -19
  3. {nfcscript-0.0.14 → nfcscript-0.0.16}/pyproject.toml +2 -2
  4. {nfcscript-0.0.14 → nfcscript-0.0.16}/src/nfc/cli.py +19 -40
  5. {nfcscript-0.0.14 → nfcscript-0.0.16}/src/nfc/reader.py +5 -5
  6. {nfcscript-0.0.14 → nfcscript-0.0.16}/src/nfc/trace.py +35 -36
  7. {nfcscript-0.0.14 → nfcscript-0.0.16}/src/nfcscript.egg-info/PKG-INFO +40 -20
  8. {nfcscript-0.0.14 → nfcscript-0.0.16}/tests/test_cli.py +2 -42
  9. {nfcscript-0.0.14 → nfcscript-0.0.16}/tests/test_trace.py +10 -31
  10. {nfcscript-0.0.14 → nfcscript-0.0.16}/setup.cfg +0 -0
  11. {nfcscript-0.0.14 → nfcscript-0.0.16}/src/nfc/__init__.py +0 -0
  12. {nfcscript-0.0.14 → nfcscript-0.0.16}/src/nfc/assertions.py +0 -0
  13. {nfcscript-0.0.14 → nfcscript-0.0.16}/src/nfc/bits.py +0 -0
  14. {nfcscript-0.0.14 → nfcscript-0.0.16}/src/nfc/checksum.py +0 -0
  15. {nfcscript-0.0.14 → nfcscript-0.0.16}/src/nfc/delay.py +0 -0
  16. {nfcscript-0.0.14 → nfcscript-0.0.16}/src/nfc/hex_util.py +0 -0
  17. {nfcscript-0.0.14 → nfcscript-0.0.16}/src/nfc/nfc_cli.py +0 -0
  18. {nfcscript-0.0.14 → nfcscript-0.0.16}/src/nfcscript.egg-info/SOURCES.txt +0 -0
  19. {nfcscript-0.0.14 → nfcscript-0.0.16}/src/nfcscript.egg-info/dependency_links.txt +0 -0
  20. {nfcscript-0.0.14 → nfcscript-0.0.16}/src/nfcscript.egg-info/entry_points.txt +0 -0
  21. {nfcscript-0.0.14 → nfcscript-0.0.16}/src/nfcscript.egg-info/requires.txt +0 -0
  22. {nfcscript-0.0.14 → nfcscript-0.0.16}/src/nfcscript.egg-info/top_level.txt +0 -0
  23. {nfcscript-0.0.14 → nfcscript-0.0.16}/tests/test_assertions.py +0 -0
  24. {nfcscript-0.0.14 → nfcscript-0.0.16}/tests/test_bits.py +0 -0
  25. {nfcscript-0.0.14 → nfcscript-0.0.16}/tests/test_checksum.py +0 -0
  26. {nfcscript-0.0.14 → nfcscript-0.0.16}/tests/test_cli_collect.py +0 -0
  27. {nfcscript-0.0.14 → nfcscript-0.0.16}/tests/test_delay.py +0 -0
  28. {nfcscript-0.0.14 → nfcscript-0.0.16}/tests/test_hex_util.py +0 -0
  29. {nfcscript-0.0.14 → nfcscript-0.0.16}/tests/test_reader.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nfcscript
3
- Version: 0.0.14
3
+ Version: 0.0.16
4
4
  Summary: A plugin-based core engine for DSL-style NFC testing automation.
5
5
  Author: crthu
6
6
  Requires-Python: >=3.14
@@ -36,13 +36,13 @@ nfcscript test_card.py -p COM21
36
36
  nfcscript test_card.py -r acr122u
37
37
 
38
38
  # 开启追踪层
39
- nfcscript test_card.py --trace-driver --trace-protocol
39
+ nfcscript test_card.py --trace-layer=protocol,debug
40
40
 
41
41
  # 设置日志级别
42
- nfcscript test_card.py --trace-level DEBUG
42
+ nfcscript test_card.py --trace-level=driver
43
43
 
44
44
  # 组合使用
45
- nfcscript test_card.py -p COM21 -r pn532 --trace-driver --trace-protocol --trace-level DEBUG
45
+ nfcscript test_card.py -p COM21 -r pn532 --trace-layer=protocol,debug --trace-level=driver
46
46
  ```
47
47
 
48
48
  ### nfc-cli - 交互式命令行
@@ -120,13 +120,13 @@ from nfc import *
120
120
  connect()
121
121
 
122
122
  # 开启追踪
123
- trace.set_layer("DRIVER", True)
124
- trace.set_layer("PROTOCOL", True)
123
+ trace.filter.driver = True
124
+ trace.filter.protocol = True
125
125
 
126
126
  # 寻卡(自动切换协议解析器)
127
127
  card_info = active()
128
128
  ASSERT_IS_NOT_NONE(card_info, "未扫描到卡片")
129
- print(f"UID: {' '.join(f'{b:02X}' for b in card_info.uid)}")
129
+ trace.app(f"UID: {' '.join(f'{b:02X}' for b in card_info.uid)}")
130
130
 
131
131
  # 创建卡片实例
132
132
  from nfctester.registry import CardRegistry
@@ -143,7 +143,7 @@ from nfc import *
143
143
 
144
144
  with session() as reader:
145
145
  card_info = reader.active()
146
- print(card_info.uid)
146
+ trace.app(f"UID: {card_info.uid}")
147
147
  # 自动断开连接
148
148
  ```
149
149
 
@@ -181,14 +181,36 @@ with session() as reader:
181
181
 
182
182
  ### trace.py
183
183
 
184
+ **简洁写法(推荐):**
185
+
184
186
  | 函数 | 说明 |
185
187
  |------|------|
186
- | `trace.set_layer(layer, enable)` | 开启/关闭追踪层 |
187
- | `trace.set_level(level)` | 设置日志级别 |
188
- | `trace.set_parse(level)` | 设置解析级别 (0=关闭, 1=hex+摘要) |
189
- | `trace.add_sink(fn)` | 注册结构化 trace 事件回调 |
190
- | `trace.remove_sink(fn)` | 移除已注册的回调 |
191
- | `trace.info(msg)` / `trace.error(msg)` / `trace.warning(msg)` / `trace.success(msg)` / `trace.debug(msg)` | 输出日志 |
188
+ | `trace.app(msg)` | 输出到 app 层 (level=50) |
189
+ | `trace.debug(msg)` | 输出到 debug 层 (level=10) |
190
+ | `trace.warning(msg)` | 输出到 warning 层 (level=30) |
191
+ | `trace.error(msg)` | 输出到 error 层 (level=40) |
192
+ | `trace.log(msg, layer="app")` | 通用文本日志,指定层 |
193
+
194
+ **属性控制(推荐):**
195
+
196
+ | 属性 | 说明 |
197
+ |------|------|
198
+ | `trace.filter.driver = True` | 启用 driver 层 |
199
+ | `trace.filter.protocol = True` | 启用 protocol 层 |
200
+ | `trace.filter.debug = False` | 禁用 debug 层 |
201
+ | `trace.filter.level = "warning"` | 设置最低日志级别 |
202
+ | `trace.filter.level = 30` | 或用数字 |
203
+
204
+ ```python
205
+ # 简洁写法
206
+ trace.app("UID: AA BB CC DD")
207
+ trace.debug("[auth] Rt: 80 81")
208
+
209
+ # 属性控制
210
+ trace.filter.driver = True
211
+ trace.filter.protocol = True
212
+ trace.filter.level = "debug"
213
+ ```
192
214
 
193
215
  ### assertions.py
194
216
 
@@ -235,9 +257,8 @@ with session() as reader:
235
257
  |------|------|--------|
236
258
  | `NFC_PORT` | 串口号 | - |
237
259
  | `NFC_READER` | 读卡器类型 | - |
238
- | `NFC_TRACE_LEVEL` | 日志级别 | `INFO` |
239
- | `NFC_TRACE_DRIVER` | 开启 DRIVER 层追踪 | `false` |
240
- | `NFC_TRACE_PROTOCOL` | 开启 PROTOCOL 层追踪 | `false` |
260
+ | `NFC_TRACE_LAYER` | 启用的层 (逗号分隔) | - |
261
+ | `NFC_TRACE_LEVEL` | 最低日志级别 | `warning` |
241
262
  | `NFC_CARD_PATH` | 外部卡片模块搜索路径 (分号分隔) | - |
242
263
 
243
264
  支持多层 `.env` 加载:从脚本目录向上搜索所有 `.env` 文件,按从外到内的顺序依次加载(内层覆盖外层同名变量)。
@@ -252,9 +273,8 @@ with session() as reader:
252
273
  ```
253
274
  NFC_PORT=COM20
254
275
  NFC_READER=pn532
255
- NFC_TRACE_LEVEL=DEBUG
256
- NFC_TRACE_DRIVER=true
257
- NFC_TRACE_PROTOCOL=true
276
+ NFC_TRACE_LAYER=protocol,warning,error,app
277
+ NFC_TRACE_LEVEL=protocol
258
278
  ```
259
279
 
260
280
  ## AI 编写脚本
@@ -26,13 +26,13 @@ nfcscript test_card.py -p COM21
26
26
  nfcscript test_card.py -r acr122u
27
27
 
28
28
  # 开启追踪层
29
- nfcscript test_card.py --trace-driver --trace-protocol
29
+ nfcscript test_card.py --trace-layer=protocol,debug
30
30
 
31
31
  # 设置日志级别
32
- nfcscript test_card.py --trace-level DEBUG
32
+ nfcscript test_card.py --trace-level=driver
33
33
 
34
34
  # 组合使用
35
- nfcscript test_card.py -p COM21 -r pn532 --trace-driver --trace-protocol --trace-level DEBUG
35
+ nfcscript test_card.py -p COM21 -r pn532 --trace-layer=protocol,debug --trace-level=driver
36
36
  ```
37
37
 
38
38
  ### nfc-cli - 交互式命令行
@@ -110,13 +110,13 @@ from nfc import *
110
110
  connect()
111
111
 
112
112
  # 开启追踪
113
- trace.set_layer("DRIVER", True)
114
- trace.set_layer("PROTOCOL", True)
113
+ trace.filter.driver = True
114
+ trace.filter.protocol = True
115
115
 
116
116
  # 寻卡(自动切换协议解析器)
117
117
  card_info = active()
118
118
  ASSERT_IS_NOT_NONE(card_info, "未扫描到卡片")
119
- print(f"UID: {' '.join(f'{b:02X}' for b in card_info.uid)}")
119
+ trace.app(f"UID: {' '.join(f'{b:02X}' for b in card_info.uid)}")
120
120
 
121
121
  # 创建卡片实例
122
122
  from nfctester.registry import CardRegistry
@@ -133,7 +133,7 @@ from nfc import *
133
133
 
134
134
  with session() as reader:
135
135
  card_info = reader.active()
136
- print(card_info.uid)
136
+ trace.app(f"UID: {card_info.uid}")
137
137
  # 自动断开连接
138
138
  ```
139
139
 
@@ -171,14 +171,36 @@ with session() as reader:
171
171
 
172
172
  ### trace.py
173
173
 
174
+ **简洁写法(推荐):**
175
+
174
176
  | 函数 | 说明 |
175
177
  |------|------|
176
- | `trace.set_layer(layer, enable)` | 开启/关闭追踪层 |
177
- | `trace.set_level(level)` | 设置日志级别 |
178
- | `trace.set_parse(level)` | 设置解析级别 (0=关闭, 1=hex+摘要) |
179
- | `trace.add_sink(fn)` | 注册结构化 trace 事件回调 |
180
- | `trace.remove_sink(fn)` | 移除已注册的回调 |
181
- | `trace.info(msg)` / `trace.error(msg)` / `trace.warning(msg)` / `trace.success(msg)` / `trace.debug(msg)` | 输出日志 |
178
+ | `trace.app(msg)` | 输出到 app 层 (level=50) |
179
+ | `trace.debug(msg)` | 输出到 debug 层 (level=10) |
180
+ | `trace.warning(msg)` | 输出到 warning 层 (level=30) |
181
+ | `trace.error(msg)` | 输出到 error 层 (level=40) |
182
+ | `trace.log(msg, layer="app")` | 通用文本日志,指定层 |
183
+
184
+ **属性控制(推荐):**
185
+
186
+ | 属性 | 说明 |
187
+ |------|------|
188
+ | `trace.filter.driver = True` | 启用 driver 层 |
189
+ | `trace.filter.protocol = True` | 启用 protocol 层 |
190
+ | `trace.filter.debug = False` | 禁用 debug 层 |
191
+ | `trace.filter.level = "warning"` | 设置最低日志级别 |
192
+ | `trace.filter.level = 30` | 或用数字 |
193
+
194
+ ```python
195
+ # 简洁写法
196
+ trace.app("UID: AA BB CC DD")
197
+ trace.debug("[auth] Rt: 80 81")
198
+
199
+ # 属性控制
200
+ trace.filter.driver = True
201
+ trace.filter.protocol = True
202
+ trace.filter.level = "debug"
203
+ ```
182
204
 
183
205
  ### assertions.py
184
206
 
@@ -225,9 +247,8 @@ with session() as reader:
225
247
  |------|------|--------|
226
248
  | `NFC_PORT` | 串口号 | - |
227
249
  | `NFC_READER` | 读卡器类型 | - |
228
- | `NFC_TRACE_LEVEL` | 日志级别 | `INFO` |
229
- | `NFC_TRACE_DRIVER` | 开启 DRIVER 层追踪 | `false` |
230
- | `NFC_TRACE_PROTOCOL` | 开启 PROTOCOL 层追踪 | `false` |
250
+ | `NFC_TRACE_LAYER` | 启用的层 (逗号分隔) | - |
251
+ | `NFC_TRACE_LEVEL` | 最低日志级别 | `warning` |
231
252
  | `NFC_CARD_PATH` | 外部卡片模块搜索路径 (分号分隔) | - |
232
253
 
233
254
  支持多层 `.env` 加载:从脚本目录向上搜索所有 `.env` 文件,按从外到内的顺序依次加载(内层覆盖外层同名变量)。
@@ -242,9 +263,8 @@ with session() as reader:
242
263
  ```
243
264
  NFC_PORT=COM20
244
265
  NFC_READER=pn532
245
- NFC_TRACE_LEVEL=DEBUG
246
- NFC_TRACE_DRIVER=true
247
- NFC_TRACE_PROTOCOL=true
266
+ NFC_TRACE_LAYER=protocol,warning,error,app
267
+ NFC_TRACE_LEVEL=protocol
248
268
  ```
249
269
 
250
270
  ## AI 编写脚本
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "nfcscript"
3
- version = "0.0.14"
3
+ version = "0.0.16"
4
4
  description = "A plugin-based core engine for DSL-style NFC testing automation."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.14"
@@ -34,7 +34,7 @@ dev = [
34
34
  ]
35
35
 
36
36
  [tool.bumpversion]
37
- current_version = "0.0.14"
37
+ current_version = "0.0.16"
38
38
  commit = true
39
39
  tag = true
40
40
  allow_dirty = true
@@ -19,20 +19,6 @@ def _find_dotenv_all(start_dir):
19
19
  chain.reverse()
20
20
  return chain
21
21
 
22
- def _parse_level(value: str) -> int:
23
- """将字符串解析为解析级别,支持数字和别名"""
24
- val = value.lower().strip()
25
- if val in ("0", "false", "no", "off"):
26
- return 0
27
- if val in ("1", "simple", "summary"):
28
- return 1
29
- if val in ("2", "full", "tree"):
30
- return 2
31
- try:
32
- return int(value)
33
- except ValueError:
34
- return 1
35
-
36
22
  def run_script(script_path):
37
23
  script_dir = os.path.dirname(os.path.abspath(script_path))
38
24
  cwd = os.getcwd()
@@ -55,11 +41,8 @@ def main():
55
41
  parser.add_argument("script", help="脚本文件路径")
56
42
  parser.add_argument("-p", "--port", default=None, help="串口号 (默认: NFC_PORT 环境变量或 COM20)")
57
43
  parser.add_argument("-r", "--reader", default=None, help="读卡器类型 (默认: NFC_READER 环境变量或 pn532)")
58
- parser.add_argument("--trace-driver", action="store_true", help="开启 DRIVER 层追踪")
59
- parser.add_argument("--trace-protocol", action="store_true", help="开启 PROTOCOL 层追踪")
60
- parser.add_argument("--trace-parse", type=int, default=None, choices=[0, 1, 2],
61
- help="解析级别: 0=关闭 1=简单 2=复杂 (默认: NFC_TRACE_PARSE 或 1)")
62
- parser.add_argument("--trace-level", default="INFO", help="日志级别 (默认: INFO)")
44
+ parser.add_argument("--trace-layer", default=None, help="启用的层 (逗号分隔: driver,debug,protocol,warning,error,app,all)")
45
+ parser.add_argument("--trace-level", default=None, help="最低日志级别 (driver/debug/protocol/warning/error/app, 默认: warning)")
63
46
 
64
47
  args, extra = parser.parse_known_args()
65
48
 
@@ -81,27 +64,23 @@ def main():
81
64
 
82
65
  from nfc import trace
83
66
 
84
- trace_level = os.environ.get("NFC_TRACE_LEVEL", "INFO")
85
- trace_driver = os.environ.get("NFC_TRACE_DRIVER", "").lower() in ("1", "true", "yes")
86
- trace_protocol = os.environ.get("NFC_TRACE_PROTOCOL", "").lower() in ("1", "true", "yes")
87
- trace_parse = os.environ.get("NFC_TRACE_PARSE", "1")
88
- trace_width = os.environ.get("NFC_TRACE_WIDTH")
89
-
90
- if args.trace_level != "INFO":
91
- trace_level = args.trace_level
92
- if args.trace_driver:
93
- trace_driver = True
94
- if args.trace_protocol:
95
- trace_protocol = True
96
- if args.trace_parse is not None:
97
- trace_parse = str(args.trace_parse)
98
-
99
- trace.set_level(trace_level)
100
- trace.set_layer("DRIVER", trace_driver)
101
- trace.set_layer("PROTOCOL", trace_protocol)
102
- trace.set_parse(_parse_level(trace_parse))
103
- if trace_width is not None:
104
- os.environ["CRFT_TRACE_WIDTH"] = trace_width
67
+ # 解析 --trace-layer: 启用指定层 (调试用,默认已开启 protocol/warning/error/app)
68
+ trace_env = os.environ.get("NFC_TRACE_LAYER", "")
69
+ trace_arg = args.trace_layer or trace_env
70
+ if trace_arg:
71
+ trace.filter.level = "driver" # 允许所有层可见
72
+ for name in trace_arg.split(","):
73
+ name = name.strip().lower()
74
+ if name == "all":
75
+ for layer in ["driver", "debug", "protocol", "warning", "error", "app"]:
76
+ setattr(trace.filter, layer, True)
77
+ elif name:
78
+ setattr(trace.filter, name, True)
79
+
80
+ # 解析 --trace-level: 最低级别过滤
81
+ level_env = os.environ.get("NFC_TRACE_LEVEL", "warning")
82
+ level_arg = args.trace_level or level_env
83
+ trace.filter.level = level_arg
105
84
 
106
85
  run_script(args.script)
107
86
 
@@ -28,14 +28,14 @@ class _NFCState:
28
28
  self._reader = CardReaderRegistry.create(reader_type, transport="serial", port=port)
29
29
  self._reader.open()
30
30
  self._connected = True
31
- print(f"Connected to {reader_type.upper()} on port {port}")
31
+ _trace.log(f"Connected to {reader_type.upper()} on port {port}", layer="app")
32
32
 
33
33
  def disconnect(self):
34
34
  if self._connected and self._reader:
35
35
  self._reader.close()
36
36
  self._connected = False
37
37
  self._reader = None
38
- print("Disconnected")
38
+ _trace.log("Disconnected", layer="app")
39
39
 
40
40
  def ensure_connected(self):
41
41
  ASSERT_IS_NOT_NONE(self._reader, msg="NFC driver not connected. Call connect() first.")
@@ -125,9 +125,9 @@ def active(low_layer: bool = False, ignore_error: bool = False, reqa_cmd: int =
125
125
  if not ignore_error:
126
126
  ASSERT_EQUAL(expected_bcc, data[4], msg=f"CL{cl} BCC 校验失败: data={FORMAT_HEX(data)}")
127
127
  elif data[4] != expected_bcc:
128
- print(f"Warning: CL{cl} BCC 校验失败")
128
+ _trace.log(f"Warning: CL{cl} BCC 校验失败", layer="warning")
129
129
 
130
- print(f"cl{cl}.uid: {FORMAT_HEX(data)}")
130
+ _trace.log(f"cl{cl}.uid: {FORMAT_HEX(data)}", layer="app")
131
131
  has_next = (data[0] == 0x88)
132
132
  uid_to_select = data[0:5]
133
133
  sak_res = select(cl_level=cl, uid=uid_to_select)
@@ -137,7 +137,7 @@ def active(low_layer: bool = False, ignore_error: bool = False, reqa_cmd: int =
137
137
  if not ignore_error:
138
138
  ASSERT_IS_NOT_NONE(sak_res, msg=f"CL{cl} SAK 选择失败")
139
139
  else:
140
- print(f"Warning: CL{cl} SAK 选择失败")
140
+ _trace.log(f"Warning: CL{cl} SAK 选择失败", layer="warning")
141
141
 
142
142
  if has_next:
143
143
  full_uid.extend(data[1:4])
@@ -1,67 +1,66 @@
1
1
  """
2
2
  NFC Script Trace 模块
3
3
 
4
- 提供日志追踪控制,包装 nfctester.trace 的功能。
4
+ 统一日志 API,包装 nfctester.trace 的 6 层日志系统。
5
+ 层: driver, debug, protocol, warning, error, app
6
+
7
+ 过滤器控制: trace.filter.driver = True, trace.filter.level = "warning"
5
8
  """
6
9
 
7
10
  from typing import Callable
8
11
  from nfctester.trace import TraceEvent, trace as _trace
9
12
 
10
13
 
11
- def set_layer(layer: str, enable: bool = True):
12
- """
13
- 开启或关闭追踪层。
14
+ def log(msg: str, layer: str = "app"):
15
+ """通用文本日志,指定层"""
16
+ _trace.log(msg, layer)
14
17
 
15
- Args:
16
- layer: 层级名称 ("DRIVER" 或 "PROTOCOL")
17
- enable: True 开启,False 关闭
18
- """
19
- _trace.set_layer(layer, enable)
20
18
 
19
+ def app(msg: str):
20
+ """输出到 app 层 (level=50)"""
21
+ _trace.app(msg)
21
22
 
22
- def set_level(level: str):
23
- """
24
- 设置日志级别。
25
23
 
26
- Args:
27
- level: 级别名称 ("INFO", "DEBUG", "ERROR" 等)
28
- """
29
- _trace.set_level(level)
24
+ def debug(msg: str):
25
+ """输出到 debug 层 (level=10)"""
26
+ _trace.debug(msg)
30
27
 
31
28
 
32
- def set_parse(level: int = 1):
33
- """
34
- 设置解析级别。
29
+ def warning(msg: str):
30
+ """输出到 warning 层 (level=30)"""
31
+ _trace.warning(msg)
35
32
 
36
- Args:
37
- level: 0=关闭(hex), 1=简单(hex + 摘要标签)
38
- """
39
- _trace.set_parse(level)
33
+
34
+ def error(msg: str):
35
+ """输出到 error 层 (level=40)"""
36
+ _trace.error(msg)
40
37
 
41
38
 
42
39
  def info(msg: str):
43
- """输出 INFO 级别日志"""
40
+ """输出 INFO 级别日志 (无层标签)"""
44
41
  _trace.info(msg)
45
42
 
46
43
 
47
- def error(msg: str):
48
- """输出 ERROR 级别日志"""
49
- _trace.error(msg)
44
+ # --- 属性控制 ---
50
45
 
46
+ def __setattr__(name, value):
47
+ """属性控制: trace.driver = True"""
48
+ setattr(_trace, name, value)
51
49
 
52
- def warning(msg: str):
53
- """输出 WARNING 级别日志"""
54
- _trace.warning(msg)
55
50
 
51
+ def __getattr__(name):
52
+ """属性获取: trace.driver"""
53
+ return getattr(_trace, name)
56
54
 
57
- def success(msg: str):
58
- """输出 SUCCESS 级别日志"""
59
- _trace.success(msg)
60
55
 
56
+ def set_parse(level: int = 1):
57
+ """
58
+ 设置解析级别。
61
59
 
62
- def debug(msg: str):
63
- """输出 DEBUG 级别日志"""
64
- _trace.debug(msg)
60
+ Args:
61
+ level: 0=关闭(hex), 1=简单(hex + 摘要标签)
62
+ """
63
+ _trace.set_parse(level)
65
64
 
66
65
 
67
66
  def add_sink(fn: Callable[[TraceEvent], None]):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nfcscript
3
- Version: 0.0.14
3
+ Version: 0.0.16
4
4
  Summary: A plugin-based core engine for DSL-style NFC testing automation.
5
5
  Author: crthu
6
6
  Requires-Python: >=3.14
@@ -36,13 +36,13 @@ nfcscript test_card.py -p COM21
36
36
  nfcscript test_card.py -r acr122u
37
37
 
38
38
  # 开启追踪层
39
- nfcscript test_card.py --trace-driver --trace-protocol
39
+ nfcscript test_card.py --trace-layer=protocol,debug
40
40
 
41
41
  # 设置日志级别
42
- nfcscript test_card.py --trace-level DEBUG
42
+ nfcscript test_card.py --trace-level=driver
43
43
 
44
44
  # 组合使用
45
- nfcscript test_card.py -p COM21 -r pn532 --trace-driver --trace-protocol --trace-level DEBUG
45
+ nfcscript test_card.py -p COM21 -r pn532 --trace-layer=protocol,debug --trace-level=driver
46
46
  ```
47
47
 
48
48
  ### nfc-cli - 交互式命令行
@@ -120,13 +120,13 @@ from nfc import *
120
120
  connect()
121
121
 
122
122
  # 开启追踪
123
- trace.set_layer("DRIVER", True)
124
- trace.set_layer("PROTOCOL", True)
123
+ trace.filter.driver = True
124
+ trace.filter.protocol = True
125
125
 
126
126
  # 寻卡(自动切换协议解析器)
127
127
  card_info = active()
128
128
  ASSERT_IS_NOT_NONE(card_info, "未扫描到卡片")
129
- print(f"UID: {' '.join(f'{b:02X}' for b in card_info.uid)}")
129
+ trace.app(f"UID: {' '.join(f'{b:02X}' for b in card_info.uid)}")
130
130
 
131
131
  # 创建卡片实例
132
132
  from nfctester.registry import CardRegistry
@@ -143,7 +143,7 @@ from nfc import *
143
143
 
144
144
  with session() as reader:
145
145
  card_info = reader.active()
146
- print(card_info.uid)
146
+ trace.app(f"UID: {card_info.uid}")
147
147
  # 自动断开连接
148
148
  ```
149
149
 
@@ -181,14 +181,36 @@ with session() as reader:
181
181
 
182
182
  ### trace.py
183
183
 
184
+ **简洁写法(推荐):**
185
+
184
186
  | 函数 | 说明 |
185
187
  |------|------|
186
- | `trace.set_layer(layer, enable)` | 开启/关闭追踪层 |
187
- | `trace.set_level(level)` | 设置日志级别 |
188
- | `trace.set_parse(level)` | 设置解析级别 (0=关闭, 1=hex+摘要) |
189
- | `trace.add_sink(fn)` | 注册结构化 trace 事件回调 |
190
- | `trace.remove_sink(fn)` | 移除已注册的回调 |
191
- | `trace.info(msg)` / `trace.error(msg)` / `trace.warning(msg)` / `trace.success(msg)` / `trace.debug(msg)` | 输出日志 |
188
+ | `trace.app(msg)` | 输出到 app 层 (level=50) |
189
+ | `trace.debug(msg)` | 输出到 debug 层 (level=10) |
190
+ | `trace.warning(msg)` | 输出到 warning 层 (level=30) |
191
+ | `trace.error(msg)` | 输出到 error 层 (level=40) |
192
+ | `trace.log(msg, layer="app")` | 通用文本日志,指定层 |
193
+
194
+ **属性控制(推荐):**
195
+
196
+ | 属性 | 说明 |
197
+ |------|------|
198
+ | `trace.filter.driver = True` | 启用 driver 层 |
199
+ | `trace.filter.protocol = True` | 启用 protocol 层 |
200
+ | `trace.filter.debug = False` | 禁用 debug 层 |
201
+ | `trace.filter.level = "warning"` | 设置最低日志级别 |
202
+ | `trace.filter.level = 30` | 或用数字 |
203
+
204
+ ```python
205
+ # 简洁写法
206
+ trace.app("UID: AA BB CC DD")
207
+ trace.debug("[auth] Rt: 80 81")
208
+
209
+ # 属性控制
210
+ trace.filter.driver = True
211
+ trace.filter.protocol = True
212
+ trace.filter.level = "debug"
213
+ ```
192
214
 
193
215
  ### assertions.py
194
216
 
@@ -235,9 +257,8 @@ with session() as reader:
235
257
  |------|------|--------|
236
258
  | `NFC_PORT` | 串口号 | - |
237
259
  | `NFC_READER` | 读卡器类型 | - |
238
- | `NFC_TRACE_LEVEL` | 日志级别 | `INFO` |
239
- | `NFC_TRACE_DRIVER` | 开启 DRIVER 层追踪 | `false` |
240
- | `NFC_TRACE_PROTOCOL` | 开启 PROTOCOL 层追踪 | `false` |
260
+ | `NFC_TRACE_LAYER` | 启用的层 (逗号分隔) | - |
261
+ | `NFC_TRACE_LEVEL` | 最低日志级别 | `warning` |
241
262
  | `NFC_CARD_PATH` | 外部卡片模块搜索路径 (分号分隔) | - |
242
263
 
243
264
  支持多层 `.env` 加载:从脚本目录向上搜索所有 `.env` 文件,按从外到内的顺序依次加载(内层覆盖外层同名变量)。
@@ -252,9 +273,8 @@ with session() as reader:
252
273
  ```
253
274
  NFC_PORT=COM20
254
275
  NFC_READER=pn532
255
- NFC_TRACE_LEVEL=DEBUG
256
- NFC_TRACE_DRIVER=true
257
- NFC_TRACE_PROTOCOL=true
276
+ NFC_TRACE_LAYER=protocol,warning,error,app
277
+ NFC_TRACE_LEVEL=protocol
258
278
  ```
259
279
 
260
280
  ## AI 编写脚本
@@ -1,8 +1,8 @@
1
- """cli 模块测试 (_find_dotenv_all / _parse_level / run_script)"""
1
+ """cli 模块测试 (_find_dotenv_all / run_script)"""
2
2
  import os
3
3
  import pytest
4
4
  from unittest.mock import patch, MagicMock
5
- from nfc.cli import _find_dotenv_all, _parse_level
5
+ from nfc.cli import _find_dotenv_all
6
6
 
7
7
 
8
8
  class TestFindDotenvAll:
@@ -34,46 +34,6 @@ class TestFindDotenvAll:
34
34
  assert result[0] != result[1]
35
35
 
36
36
 
37
- class TestParseLevel:
38
-
39
- def test_zero(self):
40
- assert _parse_level("0") == 0
41
-
42
- def test_false(self):
43
- assert _parse_level("false") == 0
44
-
45
- def test_off(self):
46
- assert _parse_level("off") == 0
47
-
48
- def test_one(self):
49
- assert _parse_level("1") == 1
50
-
51
- def test_simple(self):
52
- assert _parse_level("simple") == 1
53
-
54
- def test_summary(self):
55
- assert _parse_level("summary") == 1
56
-
57
- def test_two(self):
58
- assert _parse_level("2") == 2
59
-
60
- def test_full(self):
61
- assert _parse_level("full") == 2
62
-
63
- def test_tree(self):
64
- assert _parse_level("tree") == 2
65
-
66
- def test_case_insensitive(self):
67
- assert _parse_level("FULL") == 2
68
- assert _parse_level("False") == 0
69
-
70
- def test_unknown_falls_to_1(self):
71
- assert _parse_level("unknown") == 1
72
-
73
- def test_whitespace(self):
74
- assert _parse_level(" 2 ") == 2
75
-
76
-
77
37
  class TestRunScript:
78
38
 
79
39
  def test_runs_script(self, tmp_path):
@@ -3,32 +3,6 @@ from unittest.mock import patch, MagicMock
3
3
  from nfc import trace
4
4
 
5
5
 
6
- class TestSetLayer:
7
-
8
- @patch("nfc.trace._trace")
9
- def test_set_layer_enable(self, mock_trace):
10
- trace.set_layer("DRIVER", True)
11
- mock_trace.set_layer.assert_called_once_with("DRIVER", True)
12
-
13
- @patch("nfc.trace._trace")
14
- def test_set_layer_disable(self, mock_trace):
15
- trace.set_layer("PROTOCOL", False)
16
- mock_trace.set_layer.assert_called_once_with("PROTOCOL", False)
17
-
18
- @patch("nfc.trace._trace")
19
- def test_set_layer_default_enable(self, mock_trace):
20
- trace.set_layer("DRIVER")
21
- mock_trace.set_layer.assert_called_once_with("DRIVER", True)
22
-
23
-
24
- class TestSetLevel:
25
-
26
- @patch("nfc.trace._trace")
27
- def test_set_level(self, mock_trace):
28
- trace.set_level("DEBUG")
29
- mock_trace.set_level.assert_called_once_with("DEBUG")
30
-
31
-
32
6
  class TestSetParse:
33
7
 
34
8
  @patch("nfc.trace._trace")
@@ -54,12 +28,17 @@ class TestLogFunctions:
54
28
  trace.warning("warn message")
55
29
  mock_trace.warning.assert_called_once_with("warn message")
56
30
 
57
- @patch("nfc.trace._trace")
58
- def test_success(self, mock_trace):
59
- trace.success("ok message")
60
- mock_trace.success.assert_called_once_with("ok message")
61
-
62
31
  @patch("nfc.trace._trace")
63
32
  def test_debug(self, mock_trace):
64
33
  trace.debug("debug message")
65
34
  mock_trace.debug.assert_called_once_with("debug message")
35
+
36
+ @patch("nfc.trace._trace")
37
+ def test_app(self, mock_trace):
38
+ trace.app("app message")
39
+ mock_trace.app.assert_called_once_with("app message")
40
+
41
+ @patch("nfc.trace._trace")
42
+ def test_log(self, mock_trace):
43
+ trace.log("log message", layer="debug")
44
+ mock_trace.log.assert_called_once_with("log message", "debug")
File without changes
File without changes
File without changes