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
oscura/batch/aggregate.py DELETED
@@ -1,300 +0,0 @@
1
- """Result aggregation for batch analysis.
2
-
3
-
4
- This module provides statistical aggregation and reporting for batch
5
- analysis results, including outlier detection and export capabilities.
6
- """
7
-
8
- from pathlib import Path
9
- from typing import Any
10
-
11
- import numpy as np
12
- import pandas as pd
13
-
14
-
15
- def aggregate_results(
16
- results: pd.DataFrame,
17
- *,
18
- metrics: list[str] | None = None,
19
- outlier_threshold: float = 3.0,
20
- include_plots: bool = False,
21
- output_format: str = "dict",
22
- output_file: str | Path | None = None,
23
- ) -> dict[str, Any] | pd.DataFrame:
24
- """Aggregate results from batch analysis into summary statistics.
25
-
26
- : Computes comprehensive statistics (mean, std, min, max,
27
- outliers) for each metric in the batch results. Supports export to various
28
- formats and optional visualization generation.
29
-
30
- Args:
31
- results: DataFrame from batch_analyze() containing analysis results
32
- metrics: List of column names to aggregate (default: all numeric columns)
33
- outlier_threshold: Z-score threshold for outlier detection (default: 3.0)
34
- include_plots: Generate comparison plots across files (default: False)
35
- output_format: Output format - 'dict', 'dataframe', 'csv', 'excel', 'html'
36
- output_file: Optional output file path for export formats
37
-
38
- Returns:
39
- Dictionary or DataFrame with summary statistics:
40
- - count: Number of valid values
41
- - mean: Mean value
42
- - std: Standard deviation
43
- - min: Minimum value
44
- - max: Maximum value
45
- - median: Median value
46
- - q25: 25th percentile
47
- - q75: 75th percentile
48
- - outliers: List of outlier values
49
- - outlier_files: List of files containing outliers
50
-
51
- Raises:
52
- ValueError: If no numeric metrics are found in results.
53
-
54
- Examples:
55
- >>> results = osc.batch_analyze(files, osc.characterize_buffer)
56
- >>> summary = osc.aggregate_results(
57
- ... results,
58
- ... metrics=['rise_time', 'fall_time'],
59
- ... outlier_threshold=2.5
60
- ... )
61
- >>> print(summary['rise_time']['mean'])
62
- >>> print(summary['rise_time']['outlier_files'])
63
-
64
- Notes:
65
- - Outliers detected using IQR method: values outside [Q1 - k*IQR, Q3 + k*IQR]
66
- where k = (threshold / 3.0) * 1.5 (more robust than z-score for heavy-tailed data)
67
- - Non-numeric columns are automatically skipped
68
- - Missing values (NaN) are excluded from statistics
69
- - CSV/Excel/HTML export requires output_file parameter
70
-
71
- References:
72
- BATCH-002: Result Aggregation
73
- """
74
- if results.empty:
75
- return {} if output_format == "dict" else pd.DataFrame()
76
-
77
- # Determine metrics to analyze
78
- if metrics is None:
79
- # Auto-select all numeric columns except 'file' and 'error'
80
- metrics = results.select_dtypes(include=[np.number]).columns.tolist()
81
- metrics = [m for m in metrics if m not in ["file", "error"]]
82
-
83
- if not metrics:
84
- raise ValueError("No numeric metrics found in results")
85
-
86
- # Compute aggregated statistics
87
- aggregated: dict[str, dict[str, Any]] = {}
88
-
89
- for metric in metrics:
90
- if metric not in results.columns:
91
- continue
92
-
93
- # Extract valid (non-null) values
94
- values = results[metric].dropna()
95
-
96
- if values.empty:
97
- aggregated[metric] = {
98
- "count": 0,
99
- "mean": np.nan,
100
- "std": np.nan,
101
- "min": np.nan,
102
- "max": np.nan,
103
- "median": np.nan,
104
- "q25": np.nan,
105
- "q75": np.nan,
106
- "outliers": [],
107
- "outlier_files": [],
108
- }
109
- continue
110
-
111
- # Basic statistics
112
- stats = {
113
- "count": len(values),
114
- "mean": float(values.mean()),
115
- "std": float(values.std()),
116
- "min": float(values.min()),
117
- "max": float(values.max()),
118
- "median": float(values.median()),
119
- "q25": float(values.quantile(0.25)),
120
- "q75": float(values.quantile(0.75)),
121
- }
122
-
123
- # Outlier detection using IQR method (more robust than z-score)
124
- # IQR method: outliers are values outside [Q1 - k*IQR, Q3 + k*IQR]
125
- # where k = outlier_threshold * 1.5 (standard is k=1.5, we scale by threshold)
126
- if len(values) > 3: # Need at least 4 values for meaningful IQR
127
- q1 = stats["q25"]
128
- q3 = stats["q75"]
129
- iqr = q3 - q1
130
-
131
- # Scale IQR multiplier by threshold (default 3.0 -> 2.0 * 1.5 = 3.0)
132
- k = (outlier_threshold / 3.0) * 1.5
133
-
134
- lower_bound = q1 - k * iqr
135
- upper_bound = q3 + k * iqr
136
-
137
- outlier_mask = (values < lower_bound) | (values > upper_bound)
138
- outlier_indices = values[outlier_mask].index.tolist()
139
- stats["outliers"] = values[outlier_mask].tolist()
140
-
141
- # Get corresponding filenames if available
142
- if "file" in results.columns:
143
- stats["outlier_files"] = results.loc[outlier_indices, "file"].tolist()
144
- else:
145
- stats["outlier_files"] = outlier_indices
146
- else:
147
- stats["outliers"] = [] # type: ignore[assignment]
148
- stats["outlier_files"] = [] # type: ignore[assignment]
149
-
150
- aggregated[metric] = stats
151
-
152
- # Generate plots if requested
153
- if include_plots:
154
- # Import here to avoid circular dependency
155
- try:
156
- import matplotlib.pyplot as plt
157
-
158
- for metric in metrics:
159
- if metric not in aggregated:
160
- continue
161
-
162
- _fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))
163
-
164
- # Histogram
165
- results[metric].dropna().hist(ax=ax1, bins=30)
166
- ax1.axvline(
167
- aggregated[metric]["mean"],
168
- color="r",
169
- linestyle="--",
170
- label="Mean",
171
- )
172
- ax1.axvline(
173
- aggregated[metric]["median"],
174
- color="g",
175
- linestyle="--",
176
- label="Median",
177
- )
178
- ax1.set_xlabel(metric)
179
- ax1.set_ylabel("Count")
180
- ax1.legend()
181
- ax1.set_title(f"{metric} Distribution")
182
-
183
- # Box plot
184
- ax2.boxplot(results[metric].dropna())
185
- ax2.set_ylabel(metric)
186
- ax2.set_title(f"{metric} Box Plot")
187
-
188
- plt.tight_layout()
189
-
190
- # Save or show based on output_file
191
- if output_file:
192
- plot_file = Path(output_file).with_suffix("") / f"{metric}_plot.png"
193
- plot_file.parent.mkdir(parents=True, exist_ok=True)
194
- plt.savefig(plot_file)
195
- else:
196
- plt.show()
197
-
198
- plt.close()
199
-
200
- except ImportError:
201
- pass # Silently skip plotting if matplotlib not available
202
-
203
- # Format output
204
- if output_format == "dict":
205
- return aggregated
206
-
207
- elif output_format == "dataframe":
208
- # Convert to DataFrame with metrics as rows
209
- df = pd.DataFrame(aggregated).T
210
- # Drop list columns for DataFrame format
211
- df = df.drop(columns=["outliers", "outlier_files"], errors="ignore")
212
- return df
213
-
214
- elif output_format in ["csv", "excel", "html"]:
215
- if not output_file:
216
- raise ValueError(f"{output_format} format requires output_file parameter")
217
-
218
- df = pd.DataFrame(aggregated).T
219
- df = df.drop(columns=["outliers", "outlier_files"], errors="ignore")
220
-
221
- if output_format == "csv":
222
- df.to_csv(output_file)
223
- elif output_format == "excel":
224
- df.to_excel(output_file)
225
- elif output_format == "html":
226
- # Generate HTML report
227
- html = _generate_html_report(results, aggregated, metrics)
228
- Path(output_file).write_text(html)
229
-
230
- return df
231
-
232
- else:
233
- raise ValueError(f"Unknown output_format: {output_format}")
234
-
235
-
236
- def _generate_html_report(
237
- results: pd.DataFrame,
238
- aggregated: dict[str, dict[str, Any]],
239
- metrics: list[str],
240
- ) -> str:
241
- """Generate HTML report for batch analysis results."""
242
- html = """
243
- <!DOCTYPE html>
244
- <html>
245
- <head>
246
- <title>Batch Analysis Report</title>
247
- <style>
248
- body { font-family: Arial, sans-serif; margin: 20px; }
249
- h1 { color: #333; }
250
- h2 { color: #666; margin-top: 30px; }
251
- table { border-collapse: collapse; width: 100%; margin: 20px 0; }
252
- th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
253
- th { background-color: #4CAF50; color: white; }
254
- tr:nth-child(even) { background-color: #f2f2f2; }
255
- .outlier { background-color: #ffcccc; }
256
- </style>
257
- </head>
258
- <body>
259
- <h1>Batch Analysis Report</h1>
260
- """
261
- # Summary statistics table
262
- html += "<h2>Summary Statistics</h2>\n<table>\n"
263
- html += "<tr><th>Metric</th><th>Count</th><th>Mean</th><th>Std</th>"
264
- html += "<th>Min</th><th>Median</th><th>Max</th><th>Outliers</th></tr>\n"
265
-
266
- for metric in metrics:
267
- if metric not in aggregated:
268
- continue
269
- stats = aggregated[metric]
270
- html += "<tr>"
271
- html += f"<td>{metric}</td>"
272
- html += f"<td>{stats['count']}</td>"
273
- html += f"<td>{stats['mean']:.4g}</td>"
274
- html += f"<td>{stats['std']:.4g}</td>"
275
- html += f"<td>{stats['min']:.4g}</td>"
276
- html += f"<td>{stats['median']:.4g}</td>"
277
- html += f"<td>{stats['max']:.4g}</td>"
278
- html += f"<td>{len(stats['outliers'])}</td>"
279
- html += "</tr>\n"
280
-
281
- html += "</table>\n"
282
-
283
- # Outlier details
284
- has_outliers = any(len(aggregated[m]["outliers"]) > 0 for m in metrics if m in aggregated)
285
-
286
- if has_outliers:
287
- html += "<h2>Outliers Detected</h2>\n"
288
- for metric in metrics:
289
- if metric not in aggregated:
290
- continue
291
- stats = aggregated[metric]
292
- if stats["outliers"]:
293
- html += f"<h3>{metric}</h3>\n<table>\n"
294
- html += "<tr><th>File</th><th>Value</th></tr>\n"
295
- for file, value in zip(stats["outlier_files"], stats["outliers"], strict=False):
296
- html += f"<tr class='outlier'><td>{file}</td><td>{value:.4g}</td></tr>\n"
297
- html += "</table>\n"
298
-
299
- html += "</body>\n</html>"
300
- return html
oscura/batch/analyze.py DELETED
@@ -1,139 +0,0 @@
1
- """Multi-file batch analysis with parallel execution support.
2
-
3
-
4
- This module provides parallel batch processing of signal files using
5
- concurrent.futures for efficient multi-core utilization.
6
- """
7
-
8
- from collections.abc import Callable
9
- from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor, as_completed
10
- from pathlib import Path
11
- from typing import Any
12
-
13
- import pandas as pd
14
-
15
-
16
- def batch_analyze(
17
- files: list[str | Path],
18
- analysis_fn: Callable[[str | Path], dict[str, Any]],
19
- *,
20
- parallel: bool = False,
21
- workers: int | None = None,
22
- progress_callback: Callable[[int, int, str], None] | None = None,
23
- use_threads: bool = False,
24
- **config: Any,
25
- ) -> pd.DataFrame:
26
- """Analyze multiple files with the same analysis configuration.
27
-
28
- : Multi-file analysis with parallel execution support
29
- via concurrent.futures. Returns aggregated results as a DataFrame for
30
- easy statistical analysis and export.
31
-
32
- Args:
33
- files: List of file paths to analyze
34
- analysis_fn: Analysis function to apply to each file.
35
- Must accept a file path and return a dict of results.
36
- parallel: Enable parallel processing (default: False)
37
- workers: Number of parallel workers (default: CPU count)
38
- progress_callback: Optional callback for progress updates.
39
- Called with (current, total, filename) after each file.
40
- use_threads: Use ThreadPoolExecutor instead of ProcessPoolExecutor
41
- (useful for I/O-bound tasks, default: False)
42
- **config: Additional keyword arguments passed to analysis_fn
43
-
44
- Returns:
45
- DataFrame with one row per file, columns from analysis results.
46
- Always includes a 'file' column with the input filename.
47
-
48
- Examples:
49
- >>> import oscura as osc
50
- >>> import glob
51
- >>> files = glob.glob('captures/*.wfm')
52
- >>> results = osc.batch_analyze(
53
- ... files,
54
- ... analysis_fn=osc.characterize_buffer,
55
- ... parallel=True,
56
- ... workers=4
57
- ... )
58
- >>> print(results[['file', 'rise_time', 'fall_time', 'status']])
59
- >>> results.to_csv('batch_results.csv')
60
-
61
- Notes:
62
- - Use parallel=True for CPU-bound analysis functions
63
- - Use use_threads=True for I/O-bound operations (file loading)
64
- - Progress callback is called from worker threads/processes
65
- - All exceptions during analysis are caught and stored in 'error' column
66
-
67
- References:
68
- BATCH-001: Multi-File Analysis
69
- """
70
- if not files:
71
- return pd.DataFrame()
72
-
73
- # Wrapper to include config in analysis calls
74
- def _wrapped_analysis(filepath: str | Path) -> dict[str, Any]:
75
- try:
76
- result = analysis_fn(filepath, **config)
77
- # Ensure result is a dict
78
- if not isinstance(result, dict):
79
- result = {"result": result} # type: ignore[unreachable]
80
- result["file"] = str(filepath)
81
- result["error"] = None
82
- return result
83
- except Exception as e:
84
- # Return error info on failure
85
- return {
86
- "file": str(filepath),
87
- "error": str(e),
88
- }
89
-
90
- results: list[dict[str, Any]] = []
91
- total = len(files)
92
-
93
- if parallel:
94
- # Use concurrent.futures for parallel execution
95
- executor_class = ThreadPoolExecutor if use_threads else ProcessPoolExecutor
96
- with executor_class(max_workers=workers) as executor:
97
- # Submit all tasks
98
- future_to_file = {executor.submit(_wrapped_analysis, f): f for f in files}
99
-
100
- # Process results as they complete
101
- for i, future in enumerate(as_completed(future_to_file), 1):
102
- filepath = future_to_file[future]
103
- try:
104
- result = future.result()
105
- results.append(result)
106
-
107
- if progress_callback:
108
- progress_callback(i, total, str(filepath))
109
- except Exception as e:
110
- # Catch execution errors
111
- results.append(
112
- {
113
- "file": str(filepath),
114
- "error": f"Execution error: {e}",
115
- }
116
- )
117
-
118
- else:
119
- # Sequential processing
120
- for i, filepath in enumerate(files, 1):
121
- result = _wrapped_analysis(filepath)
122
- results.append(result)
123
-
124
- if progress_callback:
125
- progress_callback(i, total, str(filepath))
126
-
127
- # Convert to DataFrame
128
- df = pd.DataFrame(results)
129
-
130
- # Reorder columns: file first, error last
131
- cols = df.columns.tolist()
132
- if "file" in cols:
133
- cols.remove("file")
134
- cols = ["file", *cols]
135
- if "error" in cols:
136
- cols.remove("error")
137
- cols = [*cols, "error"]
138
-
139
- return df[cols]
oscura/dsl/__init__.py DELETED
@@ -1,73 +0,0 @@
1
- """Oscura DSL - Domain-Specific Language for trace analysis.
2
-
3
- Provides a simple, declarative language for defining trace analysis workflows.
4
-
5
- Example usage:
6
- ```python
7
- from oscura.dsl import execute_dsl
8
-
9
- # Execute DSL script
10
- script = '''
11
- $data = load "capture.csv"
12
- $filtered = $data | filter lowpass 1000
13
- $rise = $filtered | measure rise_time
14
- '''
15
-
16
- env = execute_dsl(script)
17
- print(f"Rise time: {env['$rise']}")
18
- ```
19
-
20
- Or start interactive REPL:
21
- ```python
22
- from oscura.dsl import start_repl
23
- start_repl()
24
- ```
25
- """
26
-
27
- from oscura.dsl.commands import BUILTIN_COMMANDS
28
- from oscura.dsl.interpreter import Interpreter, InterpreterError, execute_dsl
29
- from oscura.dsl.parser import (
30
- Assignment,
31
- Command,
32
- Expression,
33
- ForLoop,
34
- FunctionCall,
35
- Lexer,
36
- Literal,
37
- Parser,
38
- Pipeline,
39
- Statement,
40
- Token,
41
- TokenType,
42
- Variable,
43
- parse_dsl,
44
- )
45
- from oscura.dsl.repl import REPL, start_repl
46
-
47
- __all__ = [
48
- # Commands
49
- "BUILTIN_COMMANDS",
50
- # REPL
51
- "REPL",
52
- # AST nodes
53
- "Assignment",
54
- "Command",
55
- "Expression",
56
- "ForLoop",
57
- "FunctionCall",
58
- # Interpreter
59
- "Interpreter",
60
- "InterpreterError",
61
- # Parser
62
- "Lexer",
63
- "Literal",
64
- "Parser",
65
- "Pipeline",
66
- "Statement",
67
- "Token",
68
- "TokenType",
69
- "Variable",
70
- "execute_dsl",
71
- "parse_dsl",
72
- "start_repl",
73
- ]
oscura/exceptions.py DELETED
@@ -1,59 +0,0 @@
1
- """Oscura exception hierarchy - DEPRECATED compatibility module.
2
-
3
- .. deprecated:: 1.0.0
4
- This module is deprecated for backward compatibility only.
5
- New code MUST import from `oscura.core.exceptions` directly.
6
- This module will be removed in a future major version.
7
-
8
- This module re-exports exceptions from oscura.core.exceptions.
9
- The canonical location for all exception classes is `oscura.core.exceptions`.
10
-
11
- Why two files exist:
12
- - `oscura/core/exceptions.py`: Canonical implementation of all exception classes
13
- - `oscura/exceptions.py` (this file): Deprecated re-export for backward compatibility
14
-
15
- Migration guide:
16
- Old (deprecated):
17
- from oscura.exceptions import LoaderError
18
-
19
- New (preferred):
20
- from oscura.core.exceptions import LoaderError
21
- """
22
-
23
- import warnings
24
-
25
- # Issue deprecation warning on import
26
- warnings.warn(
27
- "oscura.exceptions is deprecated. "
28
- "Import from oscura.core.exceptions instead. "
29
- "This module will be removed in a future major version.",
30
- DeprecationWarning,
31
- stacklevel=2,
32
- )
33
-
34
- # Re-export all exceptions from core.exceptions
35
- from oscura.core.exceptions import ( # noqa: E402
36
- AnalysisError,
37
- ConfigurationError,
38
- ExportError,
39
- FormatError,
40
- InsufficientDataError,
41
- LoaderError,
42
- OscuraError,
43
- SampleRateError,
44
- UnsupportedFormatError,
45
- ValidationError,
46
- )
47
-
48
- __all__ = [
49
- "AnalysisError",
50
- "ConfigurationError",
51
- "ExportError",
52
- "FormatError",
53
- "InsufficientDataError",
54
- "LoaderError",
55
- "OscuraError",
56
- "SampleRateError",
57
- "UnsupportedFormatError",
58
- "ValidationError",
59
- ]