oscura 0.5.0__py3-none-any.whl → 0.6.0__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.
Files changed (513) hide show
  1. oscura/__init__.py +169 -167
  2. oscura/analyzers/__init__.py +3 -0
  3. oscura/analyzers/classification.py +659 -0
  4. oscura/analyzers/digital/__init__.py +0 -48
  5. oscura/analyzers/digital/edges.py +325 -65
  6. oscura/analyzers/digital/extraction.py +0 -195
  7. oscura/analyzers/digital/quality.py +293 -166
  8. oscura/analyzers/digital/timing.py +260 -115
  9. oscura/analyzers/digital/timing_numba.py +334 -0
  10. oscura/analyzers/entropy.py +605 -0
  11. oscura/analyzers/eye/diagram.py +176 -109
  12. oscura/analyzers/eye/metrics.py +5 -5
  13. oscura/analyzers/jitter/__init__.py +6 -4
  14. oscura/analyzers/jitter/ber.py +52 -52
  15. oscura/analyzers/jitter/classification.py +156 -0
  16. oscura/analyzers/jitter/decomposition.py +163 -113
  17. oscura/analyzers/jitter/spectrum.py +80 -64
  18. oscura/analyzers/ml/__init__.py +39 -0
  19. oscura/analyzers/ml/features.py +600 -0
  20. oscura/analyzers/ml/signal_classifier.py +604 -0
  21. oscura/analyzers/packet/daq.py +246 -158
  22. oscura/analyzers/packet/parser.py +12 -1
  23. oscura/analyzers/packet/payload.py +50 -2110
  24. oscura/analyzers/packet/payload_analysis.py +361 -181
  25. oscura/analyzers/packet/payload_patterns.py +133 -70
  26. oscura/analyzers/packet/stream.py +84 -23
  27. oscura/analyzers/patterns/__init__.py +26 -5
  28. oscura/analyzers/patterns/anomaly_detection.py +908 -0
  29. oscura/analyzers/patterns/clustering.py +169 -108
  30. oscura/analyzers/patterns/clustering_optimized.py +227 -0
  31. oscura/analyzers/patterns/discovery.py +1 -1
  32. oscura/analyzers/patterns/matching.py +581 -197
  33. oscura/analyzers/patterns/pattern_mining.py +778 -0
  34. oscura/analyzers/patterns/periodic.py +121 -38
  35. oscura/analyzers/patterns/sequences.py +175 -78
  36. oscura/analyzers/power/conduction.py +1 -1
  37. oscura/analyzers/power/soa.py +6 -6
  38. oscura/analyzers/power/switching.py +250 -110
  39. oscura/analyzers/protocol/__init__.py +17 -1
  40. oscura/analyzers/protocols/__init__.py +1 -22
  41. oscura/analyzers/protocols/base.py +6 -6
  42. oscura/analyzers/protocols/ble/__init__.py +38 -0
  43. oscura/analyzers/protocols/ble/analyzer.py +809 -0
  44. oscura/analyzers/protocols/ble/uuids.py +288 -0
  45. oscura/analyzers/protocols/can.py +257 -127
  46. oscura/analyzers/protocols/can_fd.py +107 -80
  47. oscura/analyzers/protocols/flexray.py +139 -80
  48. oscura/analyzers/protocols/hdlc.py +93 -58
  49. oscura/analyzers/protocols/i2c.py +247 -106
  50. oscura/analyzers/protocols/i2s.py +138 -86
  51. oscura/analyzers/protocols/industrial/__init__.py +40 -0
  52. oscura/analyzers/protocols/industrial/bacnet/__init__.py +33 -0
  53. oscura/analyzers/protocols/industrial/bacnet/analyzer.py +708 -0
  54. oscura/analyzers/protocols/industrial/bacnet/encoding.py +412 -0
  55. oscura/analyzers/protocols/industrial/bacnet/services.py +622 -0
  56. oscura/analyzers/protocols/industrial/ethercat/__init__.py +30 -0
  57. oscura/analyzers/protocols/industrial/ethercat/analyzer.py +474 -0
  58. oscura/analyzers/protocols/industrial/ethercat/mailbox.py +339 -0
  59. oscura/analyzers/protocols/industrial/ethercat/topology.py +166 -0
  60. oscura/analyzers/protocols/industrial/modbus/__init__.py +31 -0
  61. oscura/analyzers/protocols/industrial/modbus/analyzer.py +525 -0
  62. oscura/analyzers/protocols/industrial/modbus/crc.py +79 -0
  63. oscura/analyzers/protocols/industrial/modbus/functions.py +436 -0
  64. oscura/analyzers/protocols/industrial/opcua/__init__.py +21 -0
  65. oscura/analyzers/protocols/industrial/opcua/analyzer.py +552 -0
  66. oscura/analyzers/protocols/industrial/opcua/datatypes.py +446 -0
  67. oscura/analyzers/protocols/industrial/opcua/services.py +264 -0
  68. oscura/analyzers/protocols/industrial/profinet/__init__.py +23 -0
  69. oscura/analyzers/protocols/industrial/profinet/analyzer.py +441 -0
  70. oscura/analyzers/protocols/industrial/profinet/dcp.py +263 -0
  71. oscura/analyzers/protocols/industrial/profinet/ptcp.py +200 -0
  72. oscura/analyzers/protocols/jtag.py +180 -98
  73. oscura/analyzers/protocols/lin.py +219 -114
  74. oscura/analyzers/protocols/manchester.py +4 -4
  75. oscura/analyzers/protocols/onewire.py +253 -149
  76. oscura/analyzers/protocols/parallel_bus/__init__.py +20 -0
  77. oscura/analyzers/protocols/parallel_bus/centronics.py +92 -0
  78. oscura/analyzers/protocols/parallel_bus/gpib.py +137 -0
  79. oscura/analyzers/protocols/spi.py +192 -95
  80. oscura/analyzers/protocols/swd.py +321 -167
  81. oscura/analyzers/protocols/uart.py +267 -125
  82. oscura/analyzers/protocols/usb.py +235 -131
  83. oscura/analyzers/side_channel/power.py +17 -12
  84. oscura/analyzers/signal/__init__.py +15 -0
  85. oscura/analyzers/signal/timing_analysis.py +1086 -0
  86. oscura/analyzers/signal_integrity/__init__.py +4 -1
  87. oscura/analyzers/signal_integrity/sparams.py +2 -19
  88. oscura/analyzers/spectral/chunked.py +129 -60
  89. oscura/analyzers/spectral/chunked_fft.py +300 -94
  90. oscura/analyzers/spectral/chunked_wavelet.py +100 -80
  91. oscura/analyzers/statistical/checksum.py +376 -217
  92. oscura/analyzers/statistical/classification.py +229 -107
  93. oscura/analyzers/statistical/entropy.py +78 -53
  94. oscura/analyzers/statistics/correlation.py +407 -211
  95. oscura/analyzers/statistics/outliers.py +2 -2
  96. oscura/analyzers/statistics/streaming.py +30 -5
  97. oscura/analyzers/validation.py +216 -101
  98. oscura/analyzers/waveform/measurements.py +9 -0
  99. oscura/analyzers/waveform/measurements_with_uncertainty.py +31 -15
  100. oscura/analyzers/waveform/spectral.py +500 -228
  101. oscura/api/__init__.py +31 -5
  102. oscura/api/dsl/__init__.py +582 -0
  103. oscura/{dsl → api/dsl}/commands.py +43 -76
  104. oscura/{dsl → api/dsl}/interpreter.py +26 -51
  105. oscura/{dsl → api/dsl}/parser.py +107 -77
  106. oscura/{dsl → api/dsl}/repl.py +2 -2
  107. oscura/api/dsl.py +1 -1
  108. oscura/{integrations → api/integrations}/__init__.py +1 -1
  109. oscura/{integrations → api/integrations}/llm.py +201 -102
  110. oscura/api/operators.py +3 -3
  111. oscura/api/optimization.py +144 -30
  112. oscura/api/rest_server.py +921 -0
  113. oscura/api/server/__init__.py +17 -0
  114. oscura/api/server/dashboard.py +850 -0
  115. oscura/api/server/static/README.md +34 -0
  116. oscura/api/server/templates/base.html +181 -0
  117. oscura/api/server/templates/export.html +120 -0
  118. oscura/api/server/templates/home.html +284 -0
  119. oscura/api/server/templates/protocols.html +58 -0
  120. oscura/api/server/templates/reports.html +43 -0
  121. oscura/api/server/templates/session_detail.html +89 -0
  122. oscura/api/server/templates/sessions.html +83 -0
  123. oscura/api/server/templates/waveforms.html +73 -0
  124. oscura/automotive/__init__.py +8 -1
  125. oscura/automotive/can/__init__.py +10 -0
  126. oscura/automotive/can/checksum.py +3 -1
  127. oscura/automotive/can/dbc_generator.py +590 -0
  128. oscura/automotive/can/message_wrapper.py +121 -74
  129. oscura/automotive/can/patterns.py +98 -21
  130. oscura/automotive/can/session.py +292 -56
  131. oscura/automotive/can/state_machine.py +6 -3
  132. oscura/automotive/can/stimulus_response.py +97 -75
  133. oscura/automotive/dbc/__init__.py +10 -2
  134. oscura/automotive/dbc/generator.py +84 -56
  135. oscura/automotive/dbc/parser.py +6 -6
  136. oscura/automotive/dtc/data.json +2763 -0
  137. oscura/automotive/dtc/database.py +2 -2
  138. oscura/automotive/flexray/__init__.py +31 -0
  139. oscura/automotive/flexray/analyzer.py +504 -0
  140. oscura/automotive/flexray/crc.py +185 -0
  141. oscura/automotive/flexray/fibex.py +449 -0
  142. oscura/automotive/j1939/__init__.py +45 -8
  143. oscura/automotive/j1939/analyzer.py +605 -0
  144. oscura/automotive/j1939/spns.py +326 -0
  145. oscura/automotive/j1939/transport.py +306 -0
  146. oscura/automotive/lin/__init__.py +47 -0
  147. oscura/automotive/lin/analyzer.py +612 -0
  148. oscura/automotive/loaders/blf.py +13 -2
  149. oscura/automotive/loaders/csv_can.py +143 -72
  150. oscura/automotive/loaders/dispatcher.py +50 -2
  151. oscura/automotive/loaders/mdf.py +86 -45
  152. oscura/automotive/loaders/pcap.py +111 -61
  153. oscura/automotive/uds/__init__.py +4 -0
  154. oscura/automotive/uds/analyzer.py +725 -0
  155. oscura/automotive/uds/decoder.py +140 -58
  156. oscura/automotive/uds/models.py +7 -1
  157. oscura/automotive/visualization.py +1 -1
  158. oscura/cli/analyze.py +348 -0
  159. oscura/cli/batch.py +142 -122
  160. oscura/cli/benchmark.py +275 -0
  161. oscura/cli/characterize.py +137 -82
  162. oscura/cli/compare.py +224 -131
  163. oscura/cli/completion.py +250 -0
  164. oscura/cli/config_cmd.py +361 -0
  165. oscura/cli/decode.py +164 -87
  166. oscura/cli/export.py +286 -0
  167. oscura/cli/main.py +115 -31
  168. oscura/{onboarding → cli/onboarding}/__init__.py +3 -3
  169. oscura/{onboarding → cli/onboarding}/help.py +80 -58
  170. oscura/{onboarding → cli/onboarding}/tutorials.py +97 -72
  171. oscura/{onboarding → cli/onboarding}/wizard.py +55 -36
  172. oscura/cli/progress.py +147 -0
  173. oscura/cli/shell.py +157 -135
  174. oscura/cli/validate_cmd.py +204 -0
  175. oscura/cli/visualize.py +158 -0
  176. oscura/convenience.py +125 -79
  177. oscura/core/__init__.py +4 -2
  178. oscura/core/backend_selector.py +3 -3
  179. oscura/core/cache.py +126 -15
  180. oscura/core/cancellation.py +1 -1
  181. oscura/{config → core/config}/__init__.py +20 -11
  182. oscura/{config → core/config}/defaults.py +1 -1
  183. oscura/{config → core/config}/loader.py +7 -5
  184. oscura/{config → core/config}/memory.py +5 -5
  185. oscura/{config → core/config}/migration.py +1 -1
  186. oscura/{config → core/config}/pipeline.py +99 -23
  187. oscura/{config → core/config}/preferences.py +1 -1
  188. oscura/{config → core/config}/protocol.py +3 -3
  189. oscura/{config → core/config}/schema.py +426 -272
  190. oscura/{config → core/config}/settings.py +1 -1
  191. oscura/{config → core/config}/thresholds.py +195 -153
  192. oscura/core/correlation.py +5 -6
  193. oscura/core/cross_domain.py +0 -2
  194. oscura/core/debug.py +9 -5
  195. oscura/{extensibility → core/extensibility}/docs.py +158 -70
  196. oscura/{extensibility → core/extensibility}/extensions.py +160 -76
  197. oscura/{extensibility → core/extensibility}/logging.py +1 -1
  198. oscura/{extensibility → core/extensibility}/measurements.py +1 -1
  199. oscura/{extensibility → core/extensibility}/plugins.py +1 -1
  200. oscura/{extensibility → core/extensibility}/templates.py +73 -3
  201. oscura/{extensibility → core/extensibility}/validation.py +1 -1
  202. oscura/core/gpu_backend.py +11 -7
  203. oscura/core/log_query.py +101 -11
  204. oscura/core/logging.py +126 -54
  205. oscura/core/logging_advanced.py +5 -5
  206. oscura/core/memory_limits.py +108 -70
  207. oscura/core/memory_monitor.py +2 -2
  208. oscura/core/memory_progress.py +7 -7
  209. oscura/core/memory_warnings.py +1 -1
  210. oscura/core/numba_backend.py +13 -13
  211. oscura/{plugins → core/plugins}/__init__.py +9 -9
  212. oscura/{plugins → core/plugins}/base.py +7 -7
  213. oscura/{plugins → core/plugins}/cli.py +3 -3
  214. oscura/{plugins → core/plugins}/discovery.py +186 -106
  215. oscura/{plugins → core/plugins}/lifecycle.py +1 -1
  216. oscura/{plugins → core/plugins}/manager.py +7 -7
  217. oscura/{plugins → core/plugins}/registry.py +3 -3
  218. oscura/{plugins → core/plugins}/versioning.py +1 -1
  219. oscura/core/progress.py +16 -1
  220. oscura/core/provenance.py +8 -2
  221. oscura/{schemas → core/schemas}/__init__.py +2 -2
  222. oscura/core/schemas/bus_configuration.json +322 -0
  223. oscura/core/schemas/device_mapping.json +182 -0
  224. oscura/core/schemas/packet_format.json +418 -0
  225. oscura/core/schemas/protocol_definition.json +363 -0
  226. oscura/core/types.py +4 -0
  227. oscura/core/uncertainty.py +3 -3
  228. oscura/correlation/__init__.py +52 -0
  229. oscura/correlation/multi_protocol.py +811 -0
  230. oscura/discovery/auto_decoder.py +117 -35
  231. oscura/discovery/comparison.py +191 -86
  232. oscura/discovery/quality_validator.py +155 -68
  233. oscura/discovery/signal_detector.py +196 -79
  234. oscura/export/__init__.py +18 -20
  235. oscura/export/kaitai_struct.py +513 -0
  236. oscura/export/scapy_layer.py +801 -0
  237. oscura/export/wireshark/README.md +15 -15
  238. oscura/export/wireshark/generator.py +1 -1
  239. oscura/export/wireshark/templates/dissector.lua.j2 +2 -2
  240. oscura/export/wireshark_dissector.py +746 -0
  241. oscura/guidance/wizard.py +207 -111
  242. oscura/hardware/__init__.py +19 -0
  243. oscura/{acquisition → hardware/acquisition}/__init__.py +4 -4
  244. oscura/{acquisition → hardware/acquisition}/file.py +2 -2
  245. oscura/{acquisition → hardware/acquisition}/hardware.py +7 -7
  246. oscura/{acquisition → hardware/acquisition}/saleae.py +15 -12
  247. oscura/{acquisition → hardware/acquisition}/socketcan.py +1 -1
  248. oscura/{acquisition → hardware/acquisition}/streaming.py +2 -2
  249. oscura/{acquisition → hardware/acquisition}/synthetic.py +3 -3
  250. oscura/{acquisition → hardware/acquisition}/visa.py +33 -11
  251. oscura/hardware/firmware/__init__.py +29 -0
  252. oscura/hardware/firmware/pattern_recognition.py +874 -0
  253. oscura/hardware/hal_detector.py +736 -0
  254. oscura/hardware/security/__init__.py +37 -0
  255. oscura/hardware/security/side_channel_detector.py +1126 -0
  256. oscura/inference/__init__.py +4 -0
  257. oscura/inference/active_learning/README.md +7 -7
  258. oscura/inference/active_learning/observation_table.py +4 -1
  259. oscura/inference/alignment.py +216 -123
  260. oscura/inference/bayesian.py +113 -33
  261. oscura/inference/crc_reverse.py +101 -55
  262. oscura/inference/logic.py +6 -2
  263. oscura/inference/message_format.py +342 -183
  264. oscura/inference/protocol.py +95 -44
  265. oscura/inference/protocol_dsl.py +180 -82
  266. oscura/inference/signal_intelligence.py +1439 -706
  267. oscura/inference/spectral.py +99 -57
  268. oscura/inference/state_machine.py +810 -158
  269. oscura/inference/stream.py +270 -110
  270. oscura/iot/__init__.py +34 -0
  271. oscura/iot/coap/__init__.py +32 -0
  272. oscura/iot/coap/analyzer.py +668 -0
  273. oscura/iot/coap/options.py +212 -0
  274. oscura/iot/lorawan/__init__.py +21 -0
  275. oscura/iot/lorawan/crypto.py +206 -0
  276. oscura/iot/lorawan/decoder.py +801 -0
  277. oscura/iot/lorawan/mac_commands.py +341 -0
  278. oscura/iot/mqtt/__init__.py +27 -0
  279. oscura/iot/mqtt/analyzer.py +999 -0
  280. oscura/iot/mqtt/properties.py +315 -0
  281. oscura/iot/zigbee/__init__.py +31 -0
  282. oscura/iot/zigbee/analyzer.py +615 -0
  283. oscura/iot/zigbee/security.py +153 -0
  284. oscura/iot/zigbee/zcl.py +349 -0
  285. oscura/jupyter/display.py +125 -45
  286. oscura/{exploratory → jupyter/exploratory}/__init__.py +8 -8
  287. oscura/{exploratory → jupyter/exploratory}/error_recovery.py +298 -141
  288. oscura/jupyter/exploratory/fuzzy.py +746 -0
  289. oscura/{exploratory → jupyter/exploratory}/fuzzy_advanced.py +258 -100
  290. oscura/{exploratory → jupyter/exploratory}/legacy.py +464 -242
  291. oscura/{exploratory → jupyter/exploratory}/parse.py +167 -145
  292. oscura/{exploratory → jupyter/exploratory}/recovery.py +119 -87
  293. oscura/jupyter/exploratory/sync.py +612 -0
  294. oscura/{exploratory → jupyter/exploratory}/unknown.py +299 -176
  295. oscura/jupyter/magic.py +4 -4
  296. oscura/{ui → jupyter/ui}/__init__.py +2 -2
  297. oscura/{ui → jupyter/ui}/formatters.py +3 -3
  298. oscura/{ui → jupyter/ui}/progressive_display.py +153 -82
  299. oscura/loaders/__init__.py +171 -63
  300. oscura/loaders/binary.py +88 -1
  301. oscura/loaders/chipwhisperer.py +153 -137
  302. oscura/loaders/configurable.py +208 -86
  303. oscura/loaders/csv_loader.py +458 -215
  304. oscura/loaders/hdf5_loader.py +278 -119
  305. oscura/loaders/lazy.py +87 -54
  306. oscura/loaders/mmap_loader.py +1 -1
  307. oscura/loaders/numpy_loader.py +253 -116
  308. oscura/loaders/pcap.py +226 -151
  309. oscura/loaders/rigol.py +110 -49
  310. oscura/loaders/sigrok.py +201 -78
  311. oscura/loaders/tdms.py +81 -58
  312. oscura/loaders/tektronix.py +291 -174
  313. oscura/loaders/touchstone.py +182 -87
  314. oscura/loaders/vcd.py +215 -117
  315. oscura/loaders/wav.py +155 -68
  316. oscura/reporting/__init__.py +9 -7
  317. oscura/reporting/analyze.py +352 -146
  318. oscura/reporting/argument_preparer.py +69 -14
  319. oscura/reporting/auto_report.py +97 -61
  320. oscura/reporting/batch.py +131 -58
  321. oscura/reporting/chart_selection.py +57 -45
  322. oscura/reporting/comparison.py +63 -17
  323. oscura/reporting/content/executive.py +76 -24
  324. oscura/reporting/core_formats/multi_format.py +11 -8
  325. oscura/reporting/engine.py +312 -158
  326. oscura/reporting/enhanced_reports.py +949 -0
  327. oscura/reporting/export.py +86 -43
  328. oscura/reporting/formatting/numbers.py +69 -42
  329. oscura/reporting/html.py +139 -58
  330. oscura/reporting/index.py +137 -65
  331. oscura/reporting/output.py +158 -67
  332. oscura/reporting/pdf.py +67 -102
  333. oscura/reporting/plots.py +191 -112
  334. oscura/reporting/sections.py +88 -47
  335. oscura/reporting/standards.py +104 -61
  336. oscura/reporting/summary_generator.py +75 -55
  337. oscura/reporting/tables.py +138 -54
  338. oscura/reporting/templates/enhanced/protocol_re.html +525 -0
  339. oscura/reporting/templates/index.md +13 -13
  340. oscura/sessions/__init__.py +14 -23
  341. oscura/sessions/base.py +3 -3
  342. oscura/sessions/blackbox.py +106 -10
  343. oscura/sessions/generic.py +2 -2
  344. oscura/sessions/legacy.py +783 -0
  345. oscura/side_channel/__init__.py +63 -0
  346. oscura/side_channel/dpa.py +1025 -0
  347. oscura/utils/__init__.py +15 -1
  348. oscura/utils/autodetect.py +1 -5
  349. oscura/utils/bitwise.py +118 -0
  350. oscura/{builders → utils/builders}/__init__.py +1 -1
  351. oscura/{comparison → utils/comparison}/__init__.py +6 -6
  352. oscura/{comparison → utils/comparison}/compare.py +202 -101
  353. oscura/{comparison → utils/comparison}/golden.py +83 -63
  354. oscura/{comparison → utils/comparison}/limits.py +313 -89
  355. oscura/{comparison → utils/comparison}/mask.py +151 -45
  356. oscura/{comparison → utils/comparison}/trace_diff.py +1 -1
  357. oscura/{comparison → utils/comparison}/visualization.py +147 -89
  358. oscura/{component → utils/component}/__init__.py +3 -3
  359. oscura/{component → utils/component}/impedance.py +122 -58
  360. oscura/{component → utils/component}/reactive.py +165 -168
  361. oscura/{component → utils/component}/transmission_line.py +3 -3
  362. oscura/{filtering → utils/filtering}/__init__.py +6 -6
  363. oscura/{filtering → utils/filtering}/base.py +1 -1
  364. oscura/{filtering → utils/filtering}/convenience.py +2 -2
  365. oscura/{filtering → utils/filtering}/design.py +169 -93
  366. oscura/{filtering → utils/filtering}/filters.py +2 -2
  367. oscura/{filtering → utils/filtering}/introspection.py +2 -2
  368. oscura/utils/geometry.py +31 -0
  369. oscura/utils/imports.py +184 -0
  370. oscura/utils/lazy.py +1 -1
  371. oscura/{math → utils/math}/__init__.py +2 -2
  372. oscura/{math → utils/math}/arithmetic.py +114 -48
  373. oscura/{math → utils/math}/interpolation.py +139 -106
  374. oscura/utils/memory.py +129 -66
  375. oscura/utils/memory_advanced.py +92 -9
  376. oscura/utils/memory_extensions.py +10 -8
  377. oscura/{optimization → utils/optimization}/__init__.py +1 -1
  378. oscura/{optimization → utils/optimization}/search.py +2 -2
  379. oscura/utils/performance/__init__.py +58 -0
  380. oscura/utils/performance/caching.py +889 -0
  381. oscura/utils/performance/lsh_clustering.py +333 -0
  382. oscura/utils/performance/memory_optimizer.py +699 -0
  383. oscura/utils/performance/optimizations.py +675 -0
  384. oscura/utils/performance/parallel.py +654 -0
  385. oscura/utils/performance/profiling.py +661 -0
  386. oscura/{pipeline → utils/pipeline}/base.py +1 -1
  387. oscura/{pipeline → utils/pipeline}/composition.py +11 -3
  388. oscura/{pipeline → utils/pipeline}/parallel.py +3 -2
  389. oscura/{pipeline → utils/pipeline}/pipeline.py +1 -1
  390. oscura/{pipeline → utils/pipeline}/reverse_engineering.py +412 -221
  391. oscura/{search → utils/search}/__init__.py +3 -3
  392. oscura/{search → utils/search}/anomaly.py +188 -58
  393. oscura/utils/search/context.py +294 -0
  394. oscura/{search → utils/search}/pattern.py +138 -10
  395. oscura/utils/serial.py +51 -0
  396. oscura/utils/storage/__init__.py +61 -0
  397. oscura/utils/storage/database.py +1166 -0
  398. oscura/{streaming → utils/streaming}/chunked.py +302 -143
  399. oscura/{streaming → utils/streaming}/progressive.py +1 -1
  400. oscura/{streaming → utils/streaming}/realtime.py +3 -2
  401. oscura/{triggering → utils/triggering}/__init__.py +6 -6
  402. oscura/{triggering → utils/triggering}/base.py +6 -6
  403. oscura/{triggering → utils/triggering}/edge.py +2 -2
  404. oscura/{triggering → utils/triggering}/pattern.py +2 -2
  405. oscura/{triggering → utils/triggering}/pulse.py +115 -74
  406. oscura/{triggering → utils/triggering}/window.py +2 -2
  407. oscura/utils/validation.py +32 -0
  408. oscura/validation/__init__.py +121 -0
  409. oscura/{compliance → validation/compliance}/__init__.py +5 -5
  410. oscura/{compliance → validation/compliance}/advanced.py +5 -5
  411. oscura/{compliance → validation/compliance}/masks.py +1 -1
  412. oscura/{compliance → validation/compliance}/reporting.py +127 -53
  413. oscura/{compliance → validation/compliance}/testing.py +114 -52
  414. oscura/validation/compliance_tests.py +915 -0
  415. oscura/validation/fuzzer.py +990 -0
  416. oscura/validation/grammar_tests.py +596 -0
  417. oscura/validation/grammar_validator.py +904 -0
  418. oscura/validation/hil_testing.py +977 -0
  419. oscura/{quality → validation/quality}/__init__.py +4 -4
  420. oscura/{quality → validation/quality}/ensemble.py +251 -171
  421. oscura/{quality → validation/quality}/explainer.py +3 -3
  422. oscura/{quality → validation/quality}/scoring.py +1 -1
  423. oscura/{quality → validation/quality}/warnings.py +4 -4
  424. oscura/validation/regression_suite.py +808 -0
  425. oscura/validation/replay.py +788 -0
  426. oscura/{testing → validation/testing}/__init__.py +2 -2
  427. oscura/{testing → validation/testing}/synthetic.py +5 -5
  428. oscura/visualization/__init__.py +9 -0
  429. oscura/visualization/accessibility.py +1 -1
  430. oscura/visualization/annotations.py +64 -67
  431. oscura/visualization/colors.py +7 -7
  432. oscura/visualization/digital.py +180 -81
  433. oscura/visualization/eye.py +236 -85
  434. oscura/visualization/interactive.py +320 -143
  435. oscura/visualization/jitter.py +587 -247
  436. oscura/visualization/layout.py +169 -134
  437. oscura/visualization/optimization.py +103 -52
  438. oscura/visualization/palettes.py +1 -1
  439. oscura/visualization/power.py +427 -211
  440. oscura/visualization/power_extended.py +626 -297
  441. oscura/visualization/presets.py +2 -0
  442. oscura/visualization/protocols.py +495 -181
  443. oscura/visualization/render.py +79 -63
  444. oscura/visualization/reverse_engineering.py +171 -124
  445. oscura/visualization/signal_integrity.py +460 -279
  446. oscura/visualization/specialized.py +190 -100
  447. oscura/visualization/spectral.py +670 -255
  448. oscura/visualization/thumbnails.py +166 -137
  449. oscura/visualization/waveform.py +150 -63
  450. oscura/workflows/__init__.py +3 -0
  451. oscura/{batch → workflows/batch}/__init__.py +5 -5
  452. oscura/{batch → workflows/batch}/advanced.py +150 -75
  453. oscura/workflows/batch/aggregate.py +531 -0
  454. oscura/workflows/batch/analyze.py +236 -0
  455. oscura/{batch → workflows/batch}/logging.py +2 -2
  456. oscura/{batch → workflows/batch}/metrics.py +1 -1
  457. oscura/workflows/complete_re.py +1144 -0
  458. oscura/workflows/compliance.py +44 -54
  459. oscura/workflows/digital.py +197 -51
  460. oscura/workflows/legacy/__init__.py +12 -0
  461. oscura/{workflow → workflows/legacy}/dag.py +4 -1
  462. oscura/workflows/multi_trace.py +9 -9
  463. oscura/workflows/power.py +42 -62
  464. oscura/workflows/protocol.py +82 -49
  465. oscura/workflows/reverse_engineering.py +351 -150
  466. oscura/workflows/signal_integrity.py +157 -82
  467. oscura-0.6.0.dist-info/METADATA +643 -0
  468. oscura-0.6.0.dist-info/RECORD +590 -0
  469. oscura/analyzers/digital/ic_database.py +0 -498
  470. oscura/analyzers/digital/timing_paths.py +0 -339
  471. oscura/analyzers/digital/vintage.py +0 -377
  472. oscura/analyzers/digital/vintage_result.py +0 -148
  473. oscura/analyzers/protocols/parallel_bus.py +0 -449
  474. oscura/batch/aggregate.py +0 -300
  475. oscura/batch/analyze.py +0 -139
  476. oscura/dsl/__init__.py +0 -73
  477. oscura/exceptions.py +0 -59
  478. oscura/exploratory/fuzzy.py +0 -513
  479. oscura/exploratory/sync.py +0 -384
  480. oscura/export/wavedrom.py +0 -430
  481. oscura/exporters/__init__.py +0 -94
  482. oscura/exporters/csv.py +0 -303
  483. oscura/exporters/exporters.py +0 -44
  484. oscura/exporters/hdf5.py +0 -217
  485. oscura/exporters/html_export.py +0 -701
  486. oscura/exporters/json_export.py +0 -338
  487. oscura/exporters/markdown_export.py +0 -367
  488. oscura/exporters/matlab_export.py +0 -354
  489. oscura/exporters/npz_export.py +0 -219
  490. oscura/exporters/spice_export.py +0 -210
  491. oscura/exporters/vintage_logic_csv.py +0 -247
  492. oscura/reporting/vintage_logic_report.py +0 -523
  493. oscura/search/context.py +0 -149
  494. oscura/session/__init__.py +0 -34
  495. oscura/session/annotations.py +0 -289
  496. oscura/session/history.py +0 -313
  497. oscura/session/session.py +0 -520
  498. oscura/visualization/digital_advanced.py +0 -718
  499. oscura/visualization/figure_manager.py +0 -156
  500. oscura/workflow/__init__.py +0 -13
  501. oscura-0.5.0.dist-info/METADATA +0 -407
  502. oscura-0.5.0.dist-info/RECORD +0 -486
  503. /oscura/core/{config.py → config/legacy.py} +0 -0
  504. /oscura/{extensibility → core/extensibility}/__init__.py +0 -0
  505. /oscura/{extensibility → core/extensibility}/registry.py +0 -0
  506. /oscura/{plugins → core/plugins}/isolation.py +0 -0
  507. /oscura/{builders → utils/builders}/signal_builder.py +0 -0
  508. /oscura/{optimization → utils/optimization}/parallel.py +0 -0
  509. /oscura/{pipeline → utils/pipeline}/__init__.py +0 -0
  510. /oscura/{streaming → utils/streaming}/__init__.py +0 -0
  511. {oscura-0.5.0.dist-info → oscura-0.6.0.dist-info}/WHEEL +0 -0
  512. {oscura-0.5.0.dist-info → oscura-0.6.0.dist-info}/entry_points.txt +0 -0
  513. {oscura-0.5.0.dist-info → oscura-0.6.0.dist-info}/licenses/LICENSE +0 -0
@@ -6,7 +6,7 @@ threshold configurations.
6
6
 
7
7
 
8
8
  Example:
9
- >>> from oscura.config.schema import validate_against_schema
9
+ >>> from oscura.core.config.schema import validate_against_schema
10
10
  >>> config = {"name": "uart", "baud_rate": 115200}
11
11
  >>> validate_against_schema(config, "protocol")
12
12
  True
@@ -26,7 +26,7 @@ try:
26
26
  JSONSCHEMA_AVAILABLE = True
27
27
  except ImportError:
28
28
  JSONSCHEMA_AVAILABLE = False
29
- JsonSchemaError = Exception # type: ignore[ignore-without-code]
29
+ JsonSchemaError = Exception
30
30
 
31
31
  from oscura.core.exceptions import ConfigurationError
32
32
  from oscura.core.exceptions import ValidationError as OscuraValidationError
@@ -391,318 +391,472 @@ def _register_builtin_schemas(registry: SchemaRegistry) -> None:
391
391
  Args:
392
392
  registry: Registry to populate.
393
393
  """
394
- # Protocol definition schema
394
+ _register_protocol_schema(registry)
395
+ _register_pipeline_schema(registry)
396
+ _register_logic_family_schema(registry)
397
+ _register_threshold_profile_schema(registry)
398
+ _register_preferences_schema(registry)
399
+
400
+
401
+ def _register_protocol_schema(registry: SchemaRegistry) -> None:
402
+ """Register protocol definition schema.
403
+
404
+ Args:
405
+ registry: Schema registry to populate.
406
+ """
407
+ schema = _build_protocol_schema()
395
408
  registry.register(
396
409
  ConfigSchema(
397
410
  name="protocol",
398
411
  version="1.0.0",
399
412
  description="Protocol decoder configuration",
400
- schema={
401
- "$schema": "http://json-schema.org/draft-07/schema#",
402
- "type": "object",
403
- "required": ["name"],
404
- "properties": {
405
- "name": {
406
- "type": "string",
407
- "description": "Protocol identifier",
408
- "pattern": "^[a-z][a-z0-9_]*$",
409
- },
410
- "version": {
411
- "type": "string",
412
- "description": "Protocol version (semver)",
413
- "pattern": "^\\d+\\.\\d+\\.\\d+$",
414
- },
415
- "description": {
416
- "type": "string",
417
- },
418
- "author": {
419
- "type": "string",
420
- },
421
- "timing": {
422
- "type": "object",
423
- "properties": {
424
- "baud_rates": {
425
- "type": "array",
426
- "items": {"type": "integer", "minimum": 1},
427
- },
428
- "data_bits": {
429
- "type": "array",
430
- "items": {
431
- "type": "integer",
432
- "minimum": 1,
433
- "maximum": 32,
434
- },
435
- },
436
- "stop_bits": {
437
- "type": "array",
438
- "items": {
439
- "type": "number",
440
- "minimum": 0.5,
441
- "maximum": 2,
442
- },
443
- },
444
- "parity": {
445
- "type": "array",
446
- "items": {
447
- "type": "string",
448
- "enum": ["none", "even", "odd", "mark", "space"],
449
- },
450
- },
451
- },
452
- },
453
- "voltage_levels": {
454
- "type": "object",
455
- "properties": {
456
- "logic_family": {"type": "string"},
457
- "idle_state": {"type": "string", "enum": ["high", "low"]},
458
- "mark_voltage": {"type": "number"},
459
- "space_voltage": {"type": "number"},
460
- },
461
- },
462
- "state_machine": {
463
- "type": "object",
464
- "properties": {
465
- "states": {
466
- "type": "array",
467
- "items": {"type": "string"},
468
- },
469
- "initial_state": {"type": "string"},
470
- "transitions": {
471
- "type": "array",
472
- "items": {
473
- "type": "object",
474
- "required": ["from", "to", "condition"],
475
- "properties": {
476
- "from": {"type": "string"},
477
- "to": {"type": "string"},
478
- "condition": {"type": "string"},
479
- },
480
- },
481
- },
482
- },
413
+ schema=schema,
414
+ )
415
+ )
416
+
417
+
418
+ def _build_protocol_schema() -> dict[str, Any]:
419
+ """Build protocol schema definition.
420
+
421
+ Returns:
422
+ JSON Schema dictionary for protocol configuration.
423
+ """
424
+ return {
425
+ "$schema": "http://json-schema.org/draft-07/schema#",
426
+ "type": "object",
427
+ "required": ["name"],
428
+ "properties": {
429
+ "name": _build_protocol_name_property(),
430
+ "version": _build_semver_property(),
431
+ "description": {"type": "string"},
432
+ "author": {"type": "string"},
433
+ "timing": _build_timing_property(),
434
+ "voltage_levels": _build_voltage_levels_property(),
435
+ "state_machine": _build_state_machine_property(),
436
+ },
437
+ "additionalProperties": True,
438
+ }
439
+
440
+
441
+ def _build_protocol_name_property() -> dict[str, Any]:
442
+ """Build protocol name property definition.
443
+
444
+ Returns:
445
+ Property schema for protocol name.
446
+ """
447
+ return {
448
+ "type": "string",
449
+ "description": "Protocol identifier",
450
+ "pattern": "^[a-z][a-z0-9_]*$",
451
+ }
452
+
453
+
454
+ def _build_semver_property() -> dict[str, Any]:
455
+ """Build semantic version property definition.
456
+
457
+ Returns:
458
+ Property schema for semver strings.
459
+ """
460
+ return {
461
+ "type": "string",
462
+ "description": "Protocol version (semver)",
463
+ "pattern": "^\\d+\\.\\d+\\.\\d+$",
464
+ }
465
+
466
+
467
+ def _build_timing_property() -> dict[str, Any]:
468
+ """Build timing configuration property.
469
+
470
+ Returns:
471
+ Property schema for timing parameters.
472
+ """
473
+ return {
474
+ "type": "object",
475
+ "properties": {
476
+ "baud_rates": {
477
+ "type": "array",
478
+ "items": {"type": "integer", "minimum": 1},
479
+ },
480
+ "data_bits": {
481
+ "type": "array",
482
+ "items": {"type": "integer", "minimum": 1, "maximum": 32},
483
+ },
484
+ "stop_bits": {
485
+ "type": "array",
486
+ "items": {"type": "number", "minimum": 0.5, "maximum": 2},
487
+ },
488
+ "parity": {
489
+ "type": "array",
490
+ "items": {
491
+ "type": "string",
492
+ "enum": ["none", "even", "odd", "mark", "space"],
493
+ },
494
+ },
495
+ },
496
+ }
497
+
498
+
499
+ def _build_voltage_levels_property() -> dict[str, Any]:
500
+ """Build voltage levels property.
501
+
502
+ Returns:
503
+ Property schema for voltage level specifications.
504
+ """
505
+ return {
506
+ "type": "object",
507
+ "properties": {
508
+ "logic_family": {"type": "string"},
509
+ "idle_state": {"type": "string", "enum": ["high", "low"]},
510
+ "mark_voltage": {"type": "number"},
511
+ "space_voltage": {"type": "number"},
512
+ },
513
+ }
514
+
515
+
516
+ def _build_state_machine_property() -> dict[str, Any]:
517
+ """Build state machine property.
518
+
519
+ Returns:
520
+ Property schema for state machine definitions.
521
+ """
522
+ return {
523
+ "type": "object",
524
+ "properties": {
525
+ "states": {
526
+ "type": "array",
527
+ "items": {"type": "string"},
528
+ },
529
+ "initial_state": {"type": "string"},
530
+ "transitions": {
531
+ "type": "array",
532
+ "items": {
533
+ "type": "object",
534
+ "required": ["from", "to", "condition"],
535
+ "properties": {
536
+ "from": {"type": "string"},
537
+ "to": {"type": "string"},
538
+ "condition": {"type": "string"},
483
539
  },
484
540
  },
485
- "additionalProperties": True,
486
541
  },
487
- )
488
- )
542
+ },
543
+ }
544
+
545
+
546
+ def _register_pipeline_schema(registry: SchemaRegistry) -> None:
547
+ """Register pipeline definition schema.
489
548
 
490
- # Pipeline definition schema
549
+ Args:
550
+ registry: Schema registry to populate.
551
+ """
552
+ schema = _build_pipeline_schema()
491
553
  registry.register(
492
554
  ConfigSchema(
493
555
  name="pipeline",
494
556
  version="1.0.0",
495
557
  description="Analysis pipeline configuration",
496
- schema={
497
- "$schema": "http://json-schema.org/draft-07/schema#",
498
- "type": "object",
499
- "required": ["name", "steps"],
500
- "properties": {
501
- "name": {
502
- "type": "string",
503
- "description": "Pipeline identifier",
504
- },
505
- "version": {
506
- "type": "string",
507
- "pattern": "^\\d+\\.\\d+\\.\\d+$",
508
- },
509
- "description": {
510
- "type": "string",
511
- },
512
- "steps": {
513
- "type": "array",
514
- "minItems": 1,
515
- "items": {
516
- "type": "object",
517
- "required": ["name", "type"],
518
- "properties": {
519
- "name": {"type": "string"},
520
- "type": {"type": "string"},
521
- "params": {"type": "object"},
522
- "inputs": {"type": "object"},
523
- "outputs": {"type": "object"},
524
- },
525
- },
526
- },
527
- "parallel_groups": {
528
- "type": "array",
529
- "items": {
530
- "type": "array",
531
- "items": {"type": "string"},
532
- },
533
- },
534
- },
535
- },
558
+ schema=schema,
536
559
  )
537
560
  )
538
561
 
539
- # Logic family schema
562
+
563
+ def _build_pipeline_schema() -> dict[str, Any]:
564
+ """Build pipeline schema definition.
565
+
566
+ Returns:
567
+ JSON Schema dictionary for pipeline configuration.
568
+ """
569
+ return {
570
+ "$schema": "http://json-schema.org/draft-07/schema#",
571
+ "type": "object",
572
+ "required": ["name", "steps"],
573
+ "properties": {
574
+ "name": {"type": "string", "description": "Pipeline identifier"},
575
+ "version": _build_semver_property(),
576
+ "description": {"type": "string"},
577
+ "steps": _build_pipeline_steps_property(),
578
+ "parallel_groups": _build_parallel_groups_property(),
579
+ },
580
+ }
581
+
582
+
583
+ def _build_pipeline_steps_property() -> dict[str, Any]:
584
+ """Build pipeline steps property.
585
+
586
+ Returns:
587
+ Property schema for pipeline step definitions.
588
+ """
589
+ return {
590
+ "type": "array",
591
+ "minItems": 1,
592
+ "items": {
593
+ "type": "object",
594
+ "required": ["name", "type"],
595
+ "properties": {
596
+ "name": {"type": "string"},
597
+ "type": {"type": "string"},
598
+ "params": {"type": "object"},
599
+ "inputs": {"type": "object"},
600
+ "outputs": {"type": "object"},
601
+ },
602
+ },
603
+ }
604
+
605
+
606
+ def _build_parallel_groups_property() -> dict[str, Any]:
607
+ """Build parallel groups property.
608
+
609
+ Returns:
610
+ Property schema for parallel execution groups.
611
+ """
612
+ return {
613
+ "type": "array",
614
+ "items": {
615
+ "type": "array",
616
+ "items": {"type": "string"},
617
+ },
618
+ }
619
+
620
+
621
+ def _register_logic_family_schema(registry: SchemaRegistry) -> None:
622
+ """Register logic family voltage threshold schema.
623
+
624
+ Args:
625
+ registry: Schema registry to populate.
626
+ """
627
+ schema = _build_logic_family_schema()
540
628
  registry.register(
541
629
  ConfigSchema(
542
630
  name="logic_family",
543
631
  version="1.0.0",
544
632
  description="Logic family voltage thresholds",
545
- schema={
546
- "$schema": "http://json-schema.org/draft-07/schema#",
547
- "type": "object",
548
- "required": ["name", "VIH", "VIL", "VOH", "VOL"],
549
- "properties": {
550
- "name": {
551
- "type": "string",
552
- "description": "Logic family name",
553
- },
554
- "description": {
555
- "type": "string",
556
- },
557
- "VIH": {
558
- "type": "number",
559
- "description": "Input high voltage threshold (V)",
560
- "minimum": 0,
561
- "maximum": 10,
562
- },
563
- "VIL": {
564
- "type": "number",
565
- "description": "Input low voltage threshold (V)",
566
- "minimum": 0,
567
- "maximum": 10,
568
- },
569
- "VOH": {
570
- "type": "number",
571
- "description": "Output high voltage (V)",
572
- "minimum": 0,
573
- "maximum": 10,
574
- },
575
- "VOL": {
576
- "type": "number",
577
- "description": "Output low voltage (V)",
578
- "minimum": 0,
579
- "maximum": 10,
580
- },
581
- "VCC": {
582
- "type": "number",
583
- "description": "Supply voltage (V)",
584
- "minimum": 0,
585
- "maximum": 15,
586
- },
587
- "temperature_range": {
588
- "type": "object",
589
- "properties": {
590
- "min": {"type": "number"},
591
- "max": {"type": "number"},
592
- },
593
- },
594
- "noise_margin_high": {
595
- "type": "number",
596
- "description": "High state noise margin (V)",
597
- },
598
- "noise_margin_low": {
599
- "type": "number",
600
- "description": "Low state noise margin (V)",
601
- },
602
- },
603
- },
633
+ schema=schema,
604
634
  )
605
635
  )
606
636
 
607
- # Threshold profile schema
637
+
638
+ def _build_logic_family_schema() -> dict[str, Any]:
639
+ """Build logic family schema definition.
640
+
641
+ Returns:
642
+ JSON Schema dictionary for logic family voltage specifications.
643
+ """
644
+ return {
645
+ "$schema": "http://json-schema.org/draft-07/schema#",
646
+ "type": "object",
647
+ "required": ["name", "VIH", "VIL", "VOH", "VOL"],
648
+ "properties": {
649
+ "name": {"type": "string", "description": "Logic family name"},
650
+ "description": {"type": "string"},
651
+ "VIH": _build_voltage_property("Input high voltage threshold (V)"),
652
+ "VIL": _build_voltage_property("Input low voltage threshold (V)"),
653
+ "VOH": _build_voltage_property("Output high voltage (V)"),
654
+ "VOL": _build_voltage_property("Output low voltage (V)"),
655
+ "VCC": _build_supply_voltage_property(),
656
+ "temperature_range": _build_temperature_range_property(),
657
+ "noise_margin_high": {"type": "number", "description": "High state noise margin (V)"},
658
+ "noise_margin_low": {"type": "number", "description": "Low state noise margin (V)"},
659
+ },
660
+ }
661
+
662
+
663
+ def _build_voltage_property(description: str) -> dict[str, Any]:
664
+ """Build standard voltage property with 0-10V range.
665
+
666
+ Args:
667
+ description: Property description.
668
+
669
+ Returns:
670
+ Property schema for voltage value.
671
+ """
672
+ return {"type": "number", "description": description, "minimum": 0, "maximum": 10}
673
+
674
+
675
+ def _build_supply_voltage_property() -> dict[str, Any]:
676
+ """Build supply voltage property.
677
+
678
+ Returns:
679
+ Property schema for VCC with 0-15V range.
680
+ """
681
+ return {"type": "number", "description": "Supply voltage (V)", "minimum": 0, "maximum": 15}
682
+
683
+
684
+ def _build_temperature_range_property() -> dict[str, Any]:
685
+ """Build temperature range property.
686
+
687
+ Returns:
688
+ Property schema for temperature range.
689
+ """
690
+ return {
691
+ "type": "object",
692
+ "properties": {
693
+ "min": {"type": "number"},
694
+ "max": {"type": "number"},
695
+ },
696
+ }
697
+
698
+
699
+ def _register_threshold_profile_schema(registry: SchemaRegistry) -> None:
700
+ """Register threshold profile schema.
701
+
702
+ Args:
703
+ registry: Schema registry to populate.
704
+ """
705
+ schema = _build_threshold_profile_schema()
608
706
  registry.register(
609
707
  ConfigSchema(
610
708
  name="threshold_profile",
611
709
  version="1.0.0",
612
710
  description="Analysis threshold profile",
613
- schema={
614
- "$schema": "http://json-schema.org/draft-07/schema#",
615
- "type": "object",
616
- "required": ["name"],
617
- "properties": {
618
- "name": {
619
- "type": "string",
620
- },
621
- "description": {
622
- "type": "string",
623
- },
624
- "base_family": {
625
- "type": "string",
626
- "description": "Base logic family to extend",
627
- },
628
- "overrides": {
629
- "type": "object",
630
- "additionalProperties": {"type": "number"},
631
- },
632
- "tolerance": {
633
- "type": "number",
634
- "description": "Tolerance percentage (0-100)",
635
- "minimum": 0,
636
- "maximum": 100,
637
- "default": 0,
638
- },
639
- },
640
- },
711
+ schema=schema,
641
712
  )
642
713
  )
643
714
 
644
- # Preferences schema
715
+
716
+ def _build_threshold_profile_schema() -> dict[str, Any]:
717
+ """Build threshold profile schema definition.
718
+
719
+ Returns:
720
+ JSON Schema dictionary for threshold profile configuration.
721
+ """
722
+ return {
723
+ "$schema": "http://json-schema.org/draft-07/schema#",
724
+ "type": "object",
725
+ "required": ["name"],
726
+ "properties": {
727
+ "name": {"type": "string"},
728
+ "description": {"type": "string"},
729
+ "base_family": {"type": "string", "description": "Base logic family to extend"},
730
+ "overrides": {"type": "object", "additionalProperties": {"type": "number"}},
731
+ "tolerance": _build_tolerance_property(),
732
+ },
733
+ }
734
+
735
+
736
+ def _build_tolerance_property() -> dict[str, Any]:
737
+ """Build tolerance property.
738
+
739
+ Returns:
740
+ Property schema for tolerance percentage (0-100).
741
+ """
742
+ return {
743
+ "type": "number",
744
+ "description": "Tolerance percentage (0-100)",
745
+ "minimum": 0,
746
+ "maximum": 100,
747
+ "default": 0,
748
+ }
749
+
750
+
751
+ def _register_preferences_schema(registry: SchemaRegistry) -> None:
752
+ """Register user preferences schema.
753
+
754
+ Args:
755
+ registry: Schema registry to populate.
756
+ """
757
+ schema = _build_preferences_schema()
645
758
  registry.register(
646
759
  ConfigSchema(
647
760
  name="preferences",
648
761
  version="1.0.0",
649
762
  description="User preferences",
650
- schema={
651
- "$schema": "http://json-schema.org/draft-07/schema#",
652
- "type": "object",
653
- "properties": {
654
- "defaults": {
655
- "type": "object",
656
- "properties": {
657
- "sample_rate": {"type": "number", "minimum": 0},
658
- "window_function": {"type": "string"},
659
- "fft_size": {"type": "integer", "minimum": 1},
660
- },
661
- },
662
- "visualization": {
663
- "type": "object",
664
- "properties": {
665
- "style": {"type": "string"},
666
- "figure_size": {
667
- "type": "array",
668
- "items": {"type": "number"},
669
- "minItems": 2,
670
- "maxItems": 2,
671
- },
672
- "dpi": {"type": "integer", "minimum": 50, "maximum": 600},
673
- "colormap": {"type": "string"},
674
- },
675
- },
676
- "export": {
677
- "type": "object",
678
- "properties": {
679
- "default_format": {
680
- "type": "string",
681
- "enum": ["csv", "hdf5", "npz", "json"],
682
- },
683
- "precision": {
684
- "type": "integer",
685
- "minimum": 1,
686
- "maximum": 15,
687
- },
688
- },
689
- },
690
- "logging": {
691
- "type": "object",
692
- "properties": {
693
- "level": {
694
- "type": "string",
695
- "enum": ["DEBUG", "INFO", "WARNING", "ERROR"],
696
- },
697
- "file": {"type": "string"},
698
- },
699
- },
700
- },
701
- },
763
+ schema=schema,
702
764
  )
703
765
  )
704
766
 
705
767
 
768
+ def _build_preferences_schema() -> dict[str, Any]:
769
+ """Build preferences schema definition.
770
+
771
+ Returns:
772
+ JSON Schema dictionary for user preferences.
773
+ """
774
+ return {
775
+ "$schema": "http://json-schema.org/draft-07/schema#",
776
+ "type": "object",
777
+ "properties": {
778
+ "defaults": _build_defaults_property(),
779
+ "visualization": _build_visualization_property(),
780
+ "export": _build_export_property(),
781
+ "logging": _build_logging_property(),
782
+ },
783
+ }
784
+
785
+
786
+ def _build_defaults_property() -> dict[str, Any]:
787
+ """Build defaults property for preferences.
788
+
789
+ Returns:
790
+ Property schema for default settings.
791
+ """
792
+ return {
793
+ "type": "object",
794
+ "properties": {
795
+ "sample_rate": {"type": "number", "minimum": 0},
796
+ "window_function": {"type": "string"},
797
+ "fft_size": {"type": "integer", "minimum": 1},
798
+ },
799
+ }
800
+
801
+
802
+ def _build_visualization_property() -> dict[str, Any]:
803
+ """Build visualization property for preferences.
804
+
805
+ Returns:
806
+ Property schema for visualization settings.
807
+ """
808
+ return {
809
+ "type": "object",
810
+ "properties": {
811
+ "style": {"type": "string"},
812
+ "figure_size": {
813
+ "type": "array",
814
+ "items": {"type": "number"},
815
+ "minItems": 2,
816
+ "maxItems": 2,
817
+ },
818
+ "dpi": {"type": "integer", "minimum": 50, "maximum": 600},
819
+ "colormap": {"type": "string"},
820
+ },
821
+ }
822
+
823
+
824
+ def _build_export_property() -> dict[str, Any]:
825
+ """Build export property for preferences.
826
+
827
+ Returns:
828
+ Property schema for export settings.
829
+ """
830
+ return {
831
+ "type": "object",
832
+ "properties": {
833
+ "default_format": {
834
+ "type": "string",
835
+ "enum": ["csv", "hdf5", "npz", "json"],
836
+ },
837
+ "precision": {"type": "integer", "minimum": 1, "maximum": 15},
838
+ },
839
+ }
840
+
841
+
842
+ def _build_logging_property() -> dict[str, Any]:
843
+ """Build logging property for preferences.
844
+
845
+ Returns:
846
+ Property schema for logging settings.
847
+ """
848
+ return {
849
+ "type": "object",
850
+ "properties": {
851
+ "level": {
852
+ "type": "string",
853
+ "enum": ["DEBUG", "INFO", "WARNING", "ERROR"],
854
+ },
855
+ "file": {"type": "string"},
856
+ },
857
+ }
858
+
859
+
706
860
  __all__ = [
707
861
  "ConfigSchema",
708
862
  "SchemaRegistry",