oscura 0.0.1__py3-none-any.whl → 0.1.1__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 (465) hide show
  1. oscura/__init__.py +813 -8
  2. oscura/__main__.py +392 -0
  3. oscura/analyzers/__init__.py +37 -0
  4. oscura/analyzers/digital/__init__.py +177 -0
  5. oscura/analyzers/digital/bus.py +691 -0
  6. oscura/analyzers/digital/clock.py +805 -0
  7. oscura/analyzers/digital/correlation.py +720 -0
  8. oscura/analyzers/digital/edges.py +632 -0
  9. oscura/analyzers/digital/extraction.py +413 -0
  10. oscura/analyzers/digital/quality.py +878 -0
  11. oscura/analyzers/digital/signal_quality.py +877 -0
  12. oscura/analyzers/digital/thresholds.py +708 -0
  13. oscura/analyzers/digital/timing.py +1104 -0
  14. oscura/analyzers/eye/__init__.py +46 -0
  15. oscura/analyzers/eye/diagram.py +434 -0
  16. oscura/analyzers/eye/metrics.py +555 -0
  17. oscura/analyzers/jitter/__init__.py +83 -0
  18. oscura/analyzers/jitter/ber.py +333 -0
  19. oscura/analyzers/jitter/decomposition.py +759 -0
  20. oscura/analyzers/jitter/measurements.py +413 -0
  21. oscura/analyzers/jitter/spectrum.py +220 -0
  22. oscura/analyzers/measurements.py +40 -0
  23. oscura/analyzers/packet/__init__.py +171 -0
  24. oscura/analyzers/packet/daq.py +1077 -0
  25. oscura/analyzers/packet/metrics.py +437 -0
  26. oscura/analyzers/packet/parser.py +327 -0
  27. oscura/analyzers/packet/payload.py +2156 -0
  28. oscura/analyzers/packet/payload_analysis.py +1312 -0
  29. oscura/analyzers/packet/payload_extraction.py +236 -0
  30. oscura/analyzers/packet/payload_patterns.py +670 -0
  31. oscura/analyzers/packet/stream.py +359 -0
  32. oscura/analyzers/patterns/__init__.py +266 -0
  33. oscura/analyzers/patterns/clustering.py +1036 -0
  34. oscura/analyzers/patterns/discovery.py +539 -0
  35. oscura/analyzers/patterns/learning.py +797 -0
  36. oscura/analyzers/patterns/matching.py +1091 -0
  37. oscura/analyzers/patterns/periodic.py +650 -0
  38. oscura/analyzers/patterns/sequences.py +767 -0
  39. oscura/analyzers/power/__init__.py +116 -0
  40. oscura/analyzers/power/ac_power.py +391 -0
  41. oscura/analyzers/power/basic.py +383 -0
  42. oscura/analyzers/power/conduction.py +314 -0
  43. oscura/analyzers/power/efficiency.py +297 -0
  44. oscura/analyzers/power/ripple.py +356 -0
  45. oscura/analyzers/power/soa.py +372 -0
  46. oscura/analyzers/power/switching.py +479 -0
  47. oscura/analyzers/protocol/__init__.py +150 -0
  48. oscura/analyzers/protocols/__init__.py +150 -0
  49. oscura/analyzers/protocols/base.py +500 -0
  50. oscura/analyzers/protocols/can.py +620 -0
  51. oscura/analyzers/protocols/can_fd.py +448 -0
  52. oscura/analyzers/protocols/flexray.py +405 -0
  53. oscura/analyzers/protocols/hdlc.py +399 -0
  54. oscura/analyzers/protocols/i2c.py +368 -0
  55. oscura/analyzers/protocols/i2s.py +296 -0
  56. oscura/analyzers/protocols/jtag.py +393 -0
  57. oscura/analyzers/protocols/lin.py +445 -0
  58. oscura/analyzers/protocols/manchester.py +333 -0
  59. oscura/analyzers/protocols/onewire.py +501 -0
  60. oscura/analyzers/protocols/spi.py +334 -0
  61. oscura/analyzers/protocols/swd.py +325 -0
  62. oscura/analyzers/protocols/uart.py +393 -0
  63. oscura/analyzers/protocols/usb.py +495 -0
  64. oscura/analyzers/signal_integrity/__init__.py +63 -0
  65. oscura/analyzers/signal_integrity/embedding.py +294 -0
  66. oscura/analyzers/signal_integrity/equalization.py +370 -0
  67. oscura/analyzers/signal_integrity/sparams.py +484 -0
  68. oscura/analyzers/spectral/__init__.py +53 -0
  69. oscura/analyzers/spectral/chunked.py +273 -0
  70. oscura/analyzers/spectral/chunked_fft.py +571 -0
  71. oscura/analyzers/spectral/chunked_wavelet.py +391 -0
  72. oscura/analyzers/spectral/fft.py +92 -0
  73. oscura/analyzers/statistical/__init__.py +250 -0
  74. oscura/analyzers/statistical/checksum.py +923 -0
  75. oscura/analyzers/statistical/chunked_corr.py +228 -0
  76. oscura/analyzers/statistical/classification.py +778 -0
  77. oscura/analyzers/statistical/entropy.py +1113 -0
  78. oscura/analyzers/statistical/ngrams.py +614 -0
  79. oscura/analyzers/statistics/__init__.py +119 -0
  80. oscura/analyzers/statistics/advanced.py +885 -0
  81. oscura/analyzers/statistics/basic.py +263 -0
  82. oscura/analyzers/statistics/correlation.py +630 -0
  83. oscura/analyzers/statistics/distribution.py +298 -0
  84. oscura/analyzers/statistics/outliers.py +463 -0
  85. oscura/analyzers/statistics/streaming.py +93 -0
  86. oscura/analyzers/statistics/trend.py +520 -0
  87. oscura/analyzers/validation.py +598 -0
  88. oscura/analyzers/waveform/__init__.py +36 -0
  89. oscura/analyzers/waveform/measurements.py +943 -0
  90. oscura/analyzers/waveform/measurements_with_uncertainty.py +371 -0
  91. oscura/analyzers/waveform/spectral.py +1689 -0
  92. oscura/analyzers/waveform/wavelets.py +298 -0
  93. oscura/api/__init__.py +62 -0
  94. oscura/api/dsl.py +538 -0
  95. oscura/api/fluent.py +571 -0
  96. oscura/api/operators.py +498 -0
  97. oscura/api/optimization.py +392 -0
  98. oscura/api/profiling.py +396 -0
  99. oscura/automotive/__init__.py +73 -0
  100. oscura/automotive/can/__init__.py +52 -0
  101. oscura/automotive/can/analysis.py +356 -0
  102. oscura/automotive/can/checksum.py +250 -0
  103. oscura/automotive/can/correlation.py +212 -0
  104. oscura/automotive/can/discovery.py +355 -0
  105. oscura/automotive/can/message_wrapper.py +375 -0
  106. oscura/automotive/can/models.py +385 -0
  107. oscura/automotive/can/patterns.py +381 -0
  108. oscura/automotive/can/session.py +452 -0
  109. oscura/automotive/can/state_machine.py +300 -0
  110. oscura/automotive/can/stimulus_response.py +461 -0
  111. oscura/automotive/dbc/__init__.py +15 -0
  112. oscura/automotive/dbc/generator.py +156 -0
  113. oscura/automotive/dbc/parser.py +146 -0
  114. oscura/automotive/dtc/__init__.py +30 -0
  115. oscura/automotive/dtc/database.py +3036 -0
  116. oscura/automotive/j1939/__init__.py +14 -0
  117. oscura/automotive/j1939/decoder.py +745 -0
  118. oscura/automotive/loaders/__init__.py +35 -0
  119. oscura/automotive/loaders/asc.py +98 -0
  120. oscura/automotive/loaders/blf.py +77 -0
  121. oscura/automotive/loaders/csv_can.py +136 -0
  122. oscura/automotive/loaders/dispatcher.py +136 -0
  123. oscura/automotive/loaders/mdf.py +331 -0
  124. oscura/automotive/loaders/pcap.py +132 -0
  125. oscura/automotive/obd/__init__.py +14 -0
  126. oscura/automotive/obd/decoder.py +707 -0
  127. oscura/automotive/uds/__init__.py +48 -0
  128. oscura/automotive/uds/decoder.py +265 -0
  129. oscura/automotive/uds/models.py +64 -0
  130. oscura/automotive/visualization.py +369 -0
  131. oscura/batch/__init__.py +55 -0
  132. oscura/batch/advanced.py +627 -0
  133. oscura/batch/aggregate.py +300 -0
  134. oscura/batch/analyze.py +139 -0
  135. oscura/batch/logging.py +487 -0
  136. oscura/batch/metrics.py +556 -0
  137. oscura/builders/__init__.py +41 -0
  138. oscura/builders/signal_builder.py +1131 -0
  139. oscura/cli/__init__.py +14 -0
  140. oscura/cli/batch.py +339 -0
  141. oscura/cli/characterize.py +273 -0
  142. oscura/cli/compare.py +775 -0
  143. oscura/cli/decode.py +551 -0
  144. oscura/cli/main.py +247 -0
  145. oscura/cli/shell.py +350 -0
  146. oscura/comparison/__init__.py +66 -0
  147. oscura/comparison/compare.py +397 -0
  148. oscura/comparison/golden.py +487 -0
  149. oscura/comparison/limits.py +391 -0
  150. oscura/comparison/mask.py +434 -0
  151. oscura/comparison/trace_diff.py +30 -0
  152. oscura/comparison/visualization.py +481 -0
  153. oscura/compliance/__init__.py +70 -0
  154. oscura/compliance/advanced.py +756 -0
  155. oscura/compliance/masks.py +363 -0
  156. oscura/compliance/reporting.py +483 -0
  157. oscura/compliance/testing.py +298 -0
  158. oscura/component/__init__.py +38 -0
  159. oscura/component/impedance.py +365 -0
  160. oscura/component/reactive.py +598 -0
  161. oscura/component/transmission_line.py +312 -0
  162. oscura/config/__init__.py +191 -0
  163. oscura/config/defaults.py +254 -0
  164. oscura/config/loader.py +348 -0
  165. oscura/config/memory.py +271 -0
  166. oscura/config/migration.py +458 -0
  167. oscura/config/pipeline.py +1077 -0
  168. oscura/config/preferences.py +530 -0
  169. oscura/config/protocol.py +875 -0
  170. oscura/config/schema.py +713 -0
  171. oscura/config/settings.py +420 -0
  172. oscura/config/thresholds.py +599 -0
  173. oscura/convenience.py +457 -0
  174. oscura/core/__init__.py +299 -0
  175. oscura/core/audit.py +457 -0
  176. oscura/core/backend_selector.py +405 -0
  177. oscura/core/cache.py +590 -0
  178. oscura/core/cancellation.py +439 -0
  179. oscura/core/confidence.py +225 -0
  180. oscura/core/config.py +506 -0
  181. oscura/core/correlation.py +216 -0
  182. oscura/core/cross_domain.py +422 -0
  183. oscura/core/debug.py +301 -0
  184. oscura/core/edge_cases.py +541 -0
  185. oscura/core/exceptions.py +535 -0
  186. oscura/core/gpu_backend.py +523 -0
  187. oscura/core/lazy.py +832 -0
  188. oscura/core/log_query.py +540 -0
  189. oscura/core/logging.py +931 -0
  190. oscura/core/logging_advanced.py +952 -0
  191. oscura/core/memoize.py +171 -0
  192. oscura/core/memory_check.py +274 -0
  193. oscura/core/memory_guard.py +290 -0
  194. oscura/core/memory_limits.py +336 -0
  195. oscura/core/memory_monitor.py +453 -0
  196. oscura/core/memory_progress.py +465 -0
  197. oscura/core/memory_warnings.py +315 -0
  198. oscura/core/numba_backend.py +362 -0
  199. oscura/core/performance.py +352 -0
  200. oscura/core/progress.py +524 -0
  201. oscura/core/provenance.py +358 -0
  202. oscura/core/results.py +331 -0
  203. oscura/core/types.py +504 -0
  204. oscura/core/uncertainty.py +383 -0
  205. oscura/discovery/__init__.py +52 -0
  206. oscura/discovery/anomaly_detector.py +672 -0
  207. oscura/discovery/auto_decoder.py +415 -0
  208. oscura/discovery/comparison.py +497 -0
  209. oscura/discovery/quality_validator.py +528 -0
  210. oscura/discovery/signal_detector.py +769 -0
  211. oscura/dsl/__init__.py +73 -0
  212. oscura/dsl/commands.py +246 -0
  213. oscura/dsl/interpreter.py +455 -0
  214. oscura/dsl/parser.py +689 -0
  215. oscura/dsl/repl.py +172 -0
  216. oscura/exceptions.py +59 -0
  217. oscura/exploratory/__init__.py +111 -0
  218. oscura/exploratory/error_recovery.py +642 -0
  219. oscura/exploratory/fuzzy.py +513 -0
  220. oscura/exploratory/fuzzy_advanced.py +786 -0
  221. oscura/exploratory/legacy.py +831 -0
  222. oscura/exploratory/parse.py +358 -0
  223. oscura/exploratory/recovery.py +275 -0
  224. oscura/exploratory/sync.py +382 -0
  225. oscura/exploratory/unknown.py +707 -0
  226. oscura/export/__init__.py +25 -0
  227. oscura/export/wireshark/README.md +265 -0
  228. oscura/export/wireshark/__init__.py +47 -0
  229. oscura/export/wireshark/generator.py +312 -0
  230. oscura/export/wireshark/lua_builder.py +159 -0
  231. oscura/export/wireshark/templates/dissector.lua.j2 +92 -0
  232. oscura/export/wireshark/type_mapping.py +165 -0
  233. oscura/export/wireshark/validator.py +105 -0
  234. oscura/exporters/__init__.py +94 -0
  235. oscura/exporters/csv.py +303 -0
  236. oscura/exporters/exporters.py +44 -0
  237. oscura/exporters/hdf5.py +219 -0
  238. oscura/exporters/html_export.py +701 -0
  239. oscura/exporters/json_export.py +291 -0
  240. oscura/exporters/markdown_export.py +367 -0
  241. oscura/exporters/matlab_export.py +354 -0
  242. oscura/exporters/npz_export.py +219 -0
  243. oscura/exporters/spice_export.py +210 -0
  244. oscura/extensibility/__init__.py +131 -0
  245. oscura/extensibility/docs.py +752 -0
  246. oscura/extensibility/extensions.py +1125 -0
  247. oscura/extensibility/logging.py +259 -0
  248. oscura/extensibility/measurements.py +485 -0
  249. oscura/extensibility/plugins.py +414 -0
  250. oscura/extensibility/registry.py +346 -0
  251. oscura/extensibility/templates.py +913 -0
  252. oscura/extensibility/validation.py +651 -0
  253. oscura/filtering/__init__.py +89 -0
  254. oscura/filtering/base.py +563 -0
  255. oscura/filtering/convenience.py +564 -0
  256. oscura/filtering/design.py +725 -0
  257. oscura/filtering/filters.py +32 -0
  258. oscura/filtering/introspection.py +605 -0
  259. oscura/guidance/__init__.py +24 -0
  260. oscura/guidance/recommender.py +429 -0
  261. oscura/guidance/wizard.py +518 -0
  262. oscura/inference/__init__.py +251 -0
  263. oscura/inference/active_learning/README.md +153 -0
  264. oscura/inference/active_learning/__init__.py +38 -0
  265. oscura/inference/active_learning/lstar.py +257 -0
  266. oscura/inference/active_learning/observation_table.py +230 -0
  267. oscura/inference/active_learning/oracle.py +78 -0
  268. oscura/inference/active_learning/teachers/__init__.py +15 -0
  269. oscura/inference/active_learning/teachers/simulator.py +192 -0
  270. oscura/inference/adaptive_tuning.py +453 -0
  271. oscura/inference/alignment.py +653 -0
  272. oscura/inference/bayesian.py +943 -0
  273. oscura/inference/binary.py +1016 -0
  274. oscura/inference/crc_reverse.py +711 -0
  275. oscura/inference/logic.py +288 -0
  276. oscura/inference/message_format.py +1305 -0
  277. oscura/inference/protocol.py +417 -0
  278. oscura/inference/protocol_dsl.py +1084 -0
  279. oscura/inference/protocol_library.py +1230 -0
  280. oscura/inference/sequences.py +809 -0
  281. oscura/inference/signal_intelligence.py +1509 -0
  282. oscura/inference/spectral.py +215 -0
  283. oscura/inference/state_machine.py +634 -0
  284. oscura/inference/stream.py +918 -0
  285. oscura/integrations/__init__.py +59 -0
  286. oscura/integrations/llm.py +1827 -0
  287. oscura/jupyter/__init__.py +32 -0
  288. oscura/jupyter/display.py +268 -0
  289. oscura/jupyter/magic.py +334 -0
  290. oscura/loaders/__init__.py +526 -0
  291. oscura/loaders/binary.py +69 -0
  292. oscura/loaders/configurable.py +1255 -0
  293. oscura/loaders/csv.py +26 -0
  294. oscura/loaders/csv_loader.py +473 -0
  295. oscura/loaders/hdf5.py +9 -0
  296. oscura/loaders/hdf5_loader.py +510 -0
  297. oscura/loaders/lazy.py +370 -0
  298. oscura/loaders/mmap_loader.py +583 -0
  299. oscura/loaders/numpy_loader.py +436 -0
  300. oscura/loaders/pcap.py +432 -0
  301. oscura/loaders/preprocessing.py +368 -0
  302. oscura/loaders/rigol.py +287 -0
  303. oscura/loaders/sigrok.py +321 -0
  304. oscura/loaders/tdms.py +367 -0
  305. oscura/loaders/tektronix.py +711 -0
  306. oscura/loaders/validation.py +584 -0
  307. oscura/loaders/vcd.py +464 -0
  308. oscura/loaders/wav.py +233 -0
  309. oscura/math/__init__.py +45 -0
  310. oscura/math/arithmetic.py +824 -0
  311. oscura/math/interpolation.py +413 -0
  312. oscura/onboarding/__init__.py +39 -0
  313. oscura/onboarding/help.py +498 -0
  314. oscura/onboarding/tutorials.py +405 -0
  315. oscura/onboarding/wizard.py +466 -0
  316. oscura/optimization/__init__.py +19 -0
  317. oscura/optimization/parallel.py +440 -0
  318. oscura/optimization/search.py +532 -0
  319. oscura/pipeline/__init__.py +43 -0
  320. oscura/pipeline/base.py +338 -0
  321. oscura/pipeline/composition.py +242 -0
  322. oscura/pipeline/parallel.py +448 -0
  323. oscura/pipeline/pipeline.py +375 -0
  324. oscura/pipeline/reverse_engineering.py +1119 -0
  325. oscura/plugins/__init__.py +122 -0
  326. oscura/plugins/base.py +272 -0
  327. oscura/plugins/cli.py +497 -0
  328. oscura/plugins/discovery.py +411 -0
  329. oscura/plugins/isolation.py +418 -0
  330. oscura/plugins/lifecycle.py +959 -0
  331. oscura/plugins/manager.py +493 -0
  332. oscura/plugins/registry.py +421 -0
  333. oscura/plugins/versioning.py +372 -0
  334. oscura/py.typed +0 -0
  335. oscura/quality/__init__.py +65 -0
  336. oscura/quality/ensemble.py +740 -0
  337. oscura/quality/explainer.py +338 -0
  338. oscura/quality/scoring.py +616 -0
  339. oscura/quality/warnings.py +456 -0
  340. oscura/reporting/__init__.py +248 -0
  341. oscura/reporting/advanced.py +1234 -0
  342. oscura/reporting/analyze.py +448 -0
  343. oscura/reporting/argument_preparer.py +596 -0
  344. oscura/reporting/auto_report.py +507 -0
  345. oscura/reporting/batch.py +615 -0
  346. oscura/reporting/chart_selection.py +223 -0
  347. oscura/reporting/comparison.py +330 -0
  348. oscura/reporting/config.py +615 -0
  349. oscura/reporting/content/__init__.py +39 -0
  350. oscura/reporting/content/executive.py +127 -0
  351. oscura/reporting/content/filtering.py +191 -0
  352. oscura/reporting/content/minimal.py +257 -0
  353. oscura/reporting/content/verbosity.py +162 -0
  354. oscura/reporting/core.py +508 -0
  355. oscura/reporting/core_formats/__init__.py +17 -0
  356. oscura/reporting/core_formats/multi_format.py +210 -0
  357. oscura/reporting/engine.py +836 -0
  358. oscura/reporting/export.py +366 -0
  359. oscura/reporting/formatting/__init__.py +129 -0
  360. oscura/reporting/formatting/emphasis.py +81 -0
  361. oscura/reporting/formatting/numbers.py +403 -0
  362. oscura/reporting/formatting/standards.py +55 -0
  363. oscura/reporting/formatting.py +466 -0
  364. oscura/reporting/html.py +578 -0
  365. oscura/reporting/index.py +590 -0
  366. oscura/reporting/multichannel.py +296 -0
  367. oscura/reporting/output.py +379 -0
  368. oscura/reporting/pdf.py +373 -0
  369. oscura/reporting/plots.py +731 -0
  370. oscura/reporting/pptx_export.py +360 -0
  371. oscura/reporting/renderers/__init__.py +11 -0
  372. oscura/reporting/renderers/pdf.py +94 -0
  373. oscura/reporting/sections.py +471 -0
  374. oscura/reporting/standards.py +680 -0
  375. oscura/reporting/summary_generator.py +368 -0
  376. oscura/reporting/tables.py +397 -0
  377. oscura/reporting/template_system.py +724 -0
  378. oscura/reporting/templates/__init__.py +15 -0
  379. oscura/reporting/templates/definition.py +205 -0
  380. oscura/reporting/templates/index.html +649 -0
  381. oscura/reporting/templates/index.md +173 -0
  382. oscura/schemas/__init__.py +158 -0
  383. oscura/schemas/bus_configuration.json +322 -0
  384. oscura/schemas/device_mapping.json +182 -0
  385. oscura/schemas/packet_format.json +418 -0
  386. oscura/schemas/protocol_definition.json +363 -0
  387. oscura/search/__init__.py +16 -0
  388. oscura/search/anomaly.py +292 -0
  389. oscura/search/context.py +149 -0
  390. oscura/search/pattern.py +160 -0
  391. oscura/session/__init__.py +34 -0
  392. oscura/session/annotations.py +289 -0
  393. oscura/session/history.py +313 -0
  394. oscura/session/session.py +445 -0
  395. oscura/streaming/__init__.py +43 -0
  396. oscura/streaming/chunked.py +611 -0
  397. oscura/streaming/progressive.py +393 -0
  398. oscura/streaming/realtime.py +622 -0
  399. oscura/testing/__init__.py +54 -0
  400. oscura/testing/synthetic.py +808 -0
  401. oscura/triggering/__init__.py +68 -0
  402. oscura/triggering/base.py +229 -0
  403. oscura/triggering/edge.py +353 -0
  404. oscura/triggering/pattern.py +344 -0
  405. oscura/triggering/pulse.py +581 -0
  406. oscura/triggering/window.py +453 -0
  407. oscura/ui/__init__.py +48 -0
  408. oscura/ui/formatters.py +526 -0
  409. oscura/ui/progressive_display.py +340 -0
  410. oscura/utils/__init__.py +99 -0
  411. oscura/utils/autodetect.py +338 -0
  412. oscura/utils/buffer.py +389 -0
  413. oscura/utils/lazy.py +407 -0
  414. oscura/utils/lazy_imports.py +147 -0
  415. oscura/utils/memory.py +836 -0
  416. oscura/utils/memory_advanced.py +1326 -0
  417. oscura/utils/memory_extensions.py +465 -0
  418. oscura/utils/progressive.py +352 -0
  419. oscura/utils/windowing.py +362 -0
  420. oscura/visualization/__init__.py +321 -0
  421. oscura/visualization/accessibility.py +526 -0
  422. oscura/visualization/annotations.py +374 -0
  423. oscura/visualization/axis_scaling.py +305 -0
  424. oscura/visualization/colors.py +453 -0
  425. oscura/visualization/digital.py +337 -0
  426. oscura/visualization/eye.py +420 -0
  427. oscura/visualization/histogram.py +281 -0
  428. oscura/visualization/interactive.py +858 -0
  429. oscura/visualization/jitter.py +702 -0
  430. oscura/visualization/keyboard.py +394 -0
  431. oscura/visualization/layout.py +365 -0
  432. oscura/visualization/optimization.py +1028 -0
  433. oscura/visualization/palettes.py +446 -0
  434. oscura/visualization/plot.py +92 -0
  435. oscura/visualization/power.py +290 -0
  436. oscura/visualization/power_extended.py +626 -0
  437. oscura/visualization/presets.py +467 -0
  438. oscura/visualization/protocols.py +932 -0
  439. oscura/visualization/render.py +207 -0
  440. oscura/visualization/rendering.py +444 -0
  441. oscura/visualization/reverse_engineering.py +791 -0
  442. oscura/visualization/signal_integrity.py +808 -0
  443. oscura/visualization/specialized.py +553 -0
  444. oscura/visualization/spectral.py +811 -0
  445. oscura/visualization/styles.py +381 -0
  446. oscura/visualization/thumbnails.py +311 -0
  447. oscura/visualization/time_axis.py +351 -0
  448. oscura/visualization/waveform.py +367 -0
  449. oscura/workflow/__init__.py +13 -0
  450. oscura/workflow/dag.py +377 -0
  451. oscura/workflows/__init__.py +58 -0
  452. oscura/workflows/compliance.py +280 -0
  453. oscura/workflows/digital.py +272 -0
  454. oscura/workflows/multi_trace.py +502 -0
  455. oscura/workflows/power.py +178 -0
  456. oscura/workflows/protocol.py +492 -0
  457. oscura/workflows/reverse_engineering.py +639 -0
  458. oscura/workflows/signal_integrity.py +227 -0
  459. oscura-0.1.1.dist-info/METADATA +300 -0
  460. oscura-0.1.1.dist-info/RECORD +463 -0
  461. oscura-0.1.1.dist-info/entry_points.txt +2 -0
  462. {oscura-0.0.1.dist-info → oscura-0.1.1.dist-info}/licenses/LICENSE +1 -1
  463. oscura-0.0.1.dist-info/METADATA +0 -63
  464. oscura-0.0.1.dist-info/RECORD +0 -5
  465. {oscura-0.0.1.dist-info → oscura-0.1.1.dist-info}/WHEEL +0 -0
@@ -0,0 +1,159 @@
1
+ """Lua code builder for programmatic dissector generation.
2
+
3
+ This module provides a builder class for constructing Lua code with
4
+ proper indentation and structure.
5
+ """
6
+
7
+
8
+ class LuaCodeBuilder:
9
+ """Build Lua dissector code programmatically.
10
+
11
+ This class helps construct well-formatted Lua code with proper
12
+ indentation and structure management.
13
+
14
+ Example:
15
+ >>> builder = LuaCodeBuilder()
16
+ >>> builder.add_comment("Initialize protocol")
17
+ >>> builder.add_variable("proto", 'Proto("myproto", "My Protocol")')
18
+ >>> builder.begin_function("dissector", ["buffer", "pinfo", "tree"])
19
+ >>> builder.add_line("pinfo.cols.protocol = proto.name")
20
+ >>> builder.end_function()
21
+ >>> print(builder.to_string())
22
+ """
23
+
24
+ def __init__(self, indent_size: int = 4) -> None:
25
+ """Initialize the builder.
26
+
27
+ Args:
28
+ indent_size: Number of spaces per indentation level
29
+ """
30
+ self.lines: list[str] = []
31
+ self.indent_level = 0
32
+ self.indent_size = indent_size
33
+
34
+ def add_line(self, line: str) -> None:
35
+ """Add a line with current indentation.
36
+
37
+ Args:
38
+ line: Line content (without indentation)
39
+ """
40
+ if line.strip(): # Don't indent empty lines
41
+ indent = " " * (self.indent_level * self.indent_size)
42
+ self.lines.append(f"{indent}{line}")
43
+ else:
44
+ self.lines.append("")
45
+
46
+ def add_blank_line(self) -> None:
47
+ """Add a blank line."""
48
+ self.lines.append("")
49
+
50
+ def add_comment(self, comment: str, prefix: str = "--") -> None:
51
+ """Add a Lua comment.
52
+
53
+ Args:
54
+ comment: Comment text
55
+ prefix: Comment prefix (default: "--")
56
+ """
57
+ self.add_line(f"{prefix} {comment}")
58
+
59
+ def begin_function(self, name: str, params: list[str]) -> None:
60
+ """Start a function definition.
61
+
62
+ Args:
63
+ name: Function name
64
+ params: List of parameter names
65
+ """
66
+ param_list = ", ".join(params)
67
+ self.add_line(f"function {name}({param_list})")
68
+ self.indent_level += 1
69
+
70
+ def end_function(self) -> None:
71
+ """End a function definition."""
72
+ self.indent_level -= 1
73
+ self.add_line("end")
74
+
75
+ def begin_if(self, condition: str) -> None:
76
+ """Start an if statement.
77
+
78
+ Args:
79
+ condition: If condition
80
+ """
81
+ self.add_line(f"if {condition} then")
82
+ self.indent_level += 1
83
+
84
+ def add_else(self) -> None:
85
+ """Add else clause."""
86
+ self.indent_level -= 1
87
+ self.add_line("else")
88
+ self.indent_level += 1
89
+
90
+ def add_elseif(self, condition: str) -> None:
91
+ """Add elseif clause.
92
+
93
+ Args:
94
+ condition: Elseif condition
95
+ """
96
+ self.indent_level -= 1
97
+ self.add_line(f"elseif {condition} then")
98
+ self.indent_level += 1
99
+
100
+ def end_if(self) -> None:
101
+ """End an if statement."""
102
+ self.indent_level -= 1
103
+ self.add_line("end")
104
+
105
+ def begin_for(self, loop_var: str, start: str, end: str) -> None:
106
+ """Start a for loop.
107
+
108
+ Args:
109
+ loop_var: Loop variable name
110
+ start: Start value
111
+ end: End value
112
+ """
113
+ self.add_line(f"for {loop_var} = {start}, {end} do")
114
+ self.indent_level += 1
115
+
116
+ def end_for(self) -> None:
117
+ """End a for loop."""
118
+ self.indent_level -= 1
119
+ self.add_line("end")
120
+
121
+ def add_variable(self, name: str, value: str, local: bool = True) -> None:
122
+ """Add a variable declaration.
123
+
124
+ Args:
125
+ name: Variable name
126
+ value: Variable value
127
+ local: Whether to use 'local' keyword
128
+ """
129
+ prefix = "local " if local else ""
130
+ self.add_line(f"{prefix}{name} = {value}")
131
+
132
+ def add_return(self, value: str) -> None:
133
+ """Add a return statement.
134
+
135
+ Args:
136
+ value: Return value
137
+ """
138
+ self.add_line(f"return {value}")
139
+
140
+ def indent(self) -> None:
141
+ """Increase indentation level."""
142
+ self.indent_level += 1
143
+
144
+ def dedent(self) -> None:
145
+ """Decrease indentation level."""
146
+ if self.indent_level > 0:
147
+ self.indent_level -= 1
148
+
149
+ def to_string(self) -> str:
150
+ """Generate final Lua code.
151
+
152
+ Returns:
153
+ Complete Lua code as a string
154
+ """
155
+ return "\n".join(self.lines)
156
+
157
+ def __str__(self) -> str:
158
+ """String representation."""
159
+ return self.to_string()
@@ -0,0 +1,92 @@
1
+ -- {{ protocol.name }}.lua
2
+ -- Generated by Oscura on {{ timestamp }}
3
+ --
4
+ -- Protocol: {{ protocol.description }}
5
+ -- Version: {{ protocol.version }}
6
+ {% if protocol.endian %}-- Endianness: {{ protocol.endian }}
7
+ {% endif %}
8
+
9
+ -- Protocol declaration
10
+ local {{ proto_var }} = Proto("{{ protocol.name }}", "{{ protocol.description }}")
11
+
12
+ -- Field declarations
13
+ {% for field in fields %}
14
+ local f_{{ field.name }} = {{ field.protofield_type }}(
15
+ "{{ protocol.name }}.{{ field.name }}",
16
+ "{{ field.display_name }}",
17
+ {{ field.display_base }}
18
+ {%- if field.value_string %}, {{ field.value_string }}{% endif %}
19
+ )
20
+ {% endfor %}
21
+
22
+ -- Register fields
23
+ {{ proto_var }}.fields = { {% for field in fields %}f_{{ field.name }}{% if not loop.last %}, {% endif %}{% endfor %} }
24
+
25
+ -- Dissector function
26
+ function {{ proto_var }}.dissector(buffer, pinfo, tree)
27
+ local pktlen = buffer:len()
28
+
29
+ -- Check minimum length
30
+ if pktlen < {{ min_length }} then
31
+ return 0 -- Not enough data
32
+ end
33
+
34
+ -- Set protocol column
35
+ pinfo.cols.protocol = {{ proto_var }}.name
36
+
37
+ -- Create protocol subtree
38
+ local subtree = tree:add({{ proto_var }}, buffer(), "{{ protocol.description }}")
39
+ local offset = 0
40
+
41
+ -- Decode fields
42
+ {% for field in fields %}
43
+ {% if field.condition %}
44
+ -- Conditional field: {{ field.name }} ({{ field.condition }})
45
+ -- TODO: Implement condition evaluation
46
+ {% endif %}
47
+ {% if field.is_variable_length %}
48
+ -- Variable-length field: {{ field.name }}
49
+ {% if field.size_field %}
50
+ local {{ field.name }}_len = buffer({{ field.size_offset }}, {{ field.size_field_size }}):{{ field.size_reader }}()
51
+ if offset + {{ field.name }}_len > pktlen then
52
+ subtree:add_expert_info(PI_MALFORMED, PI_ERROR, "Truncated {{ field.name }}")
53
+ return pktlen
54
+ end
55
+ subtree:add(f_{{ field.name }}, buffer(offset, {{ field.name }}_len))
56
+ offset = offset + {{ field.name }}_len
57
+ {% else %}
58
+ -- Use remaining data for {{ field.name }}
59
+ local {{ field.name }}_len = pktlen - offset
60
+ subtree:add(f_{{ field.name }}, buffer(offset, {{ field.name }}_len))
61
+ offset = offset + {{ field.name }}_len
62
+ {% endif %}
63
+ {% else %}
64
+ -- Fixed-length field: {{ field.name }} ({{ field.size }} bytes)
65
+ if offset + {{ field.size }} > pktlen then
66
+ subtree:add_expert_info(PI_MALFORMED, PI_ERROR, "Truncated {{ field.name }}")
67
+ return pktlen
68
+ end
69
+ subtree:add(f_{{ field.name }}, buffer(offset, {{ field.size }}))
70
+ offset = offset + {{ field.size }}
71
+ {% endif %}
72
+
73
+ {% endfor %}
74
+ return offset
75
+ end
76
+
77
+ -- Protocol registration
78
+ {% if transport == "tcp" %}
79
+ -- Register on TCP port {{ port }}
80
+ local tcp_table = DissectorTable.get("tcp.port")
81
+ tcp_table:add({{ port }}, {{ proto_var }})
82
+ {% elif transport == "udp" %}
83
+ -- Register on UDP port {{ port }}
84
+ local udp_table = DissectorTable.get("udp.port")
85
+ udp_table:add({{ port }}, {{ proto_var }})
86
+ {% elif pattern %}
87
+ -- Register on pattern match
88
+ -- TODO: Implement heuristic dissector for pattern "{{ pattern }}"
89
+ {% else %}
90
+ -- No automatic registration - manually register as needed
91
+ -- Example: DissectorTable.get("tcp.port"):add(PORT, {{ proto_var }})
92
+ {% endif %}
@@ -0,0 +1,165 @@
1
+ """Type mapping between Oscura field types and Wireshark ProtoField types.
2
+
3
+ This module provides mappings from Oscura protocol field types to their
4
+ corresponding Wireshark Lua ProtoField types and display bases.
5
+
6
+ References:
7
+ https://wiki.wireshark.org/LuaAPI/Proto
8
+ """
9
+
10
+ from typing import Literal
11
+
12
+ # Map Oscura field types to Wireshark ProtoField types
13
+ FIELD_TYPE_MAPPING: dict[str, str] = {
14
+ "uint8": "ProtoField.uint8",
15
+ "uint16": "ProtoField.uint16",
16
+ "uint32": "ProtoField.uint32",
17
+ "uint64": "ProtoField.uint64",
18
+ "int8": "ProtoField.int8",
19
+ "int16": "ProtoField.int16",
20
+ "int32": "ProtoField.int32",
21
+ "int64": "ProtoField.int64",
22
+ "bytes": "ProtoField.bytes",
23
+ "string": "ProtoField.string",
24
+ "bool": "ProtoField.bool",
25
+ "float32": "ProtoField.float",
26
+ "float64": "ProtoField.double",
27
+ }
28
+
29
+ # Map display base names to Wireshark base constants
30
+ BASE_MAPPING: dict[str, str] = {
31
+ "dec": "base.DEC",
32
+ "hex": "base.HEX",
33
+ "oct": "base.OCT",
34
+ "bin": "base.BIN",
35
+ "none": "base.NONE",
36
+ }
37
+
38
+ # Default display base for each field type
39
+ DEFAULT_BASE: dict[str, str] = {
40
+ "uint8": "hex",
41
+ "uint16": "hex",
42
+ "uint32": "hex",
43
+ "uint64": "hex",
44
+ "int8": "dec",
45
+ "int16": "dec",
46
+ "int32": "dec",
47
+ "int64": "dec",
48
+ "bytes": "none",
49
+ "string": "none",
50
+ "bool": "none",
51
+ "float32": "none",
52
+ "float64": "none",
53
+ }
54
+
55
+
56
+ def get_protofield_type(field_type: str, display_base: str | None = None) -> tuple[str, str]:
57
+ """Map Oscura field type to Wireshark ProtoField and display base.
58
+
59
+ Args:
60
+ field_type: Oscura field type (uint8, uint16, string, etc.)
61
+ display_base: Optional display base (dec, hex, oct, bin, none)
62
+
63
+ Returns:
64
+ Tuple of (protofield_type, base_constant)
65
+ Example: ("ProtoField.uint16", "base.HEX")
66
+
67
+ Raises:
68
+ ValueError: If field type is unknown
69
+ """
70
+ if field_type not in FIELD_TYPE_MAPPING:
71
+ raise ValueError(f"Unknown field type: {field_type}")
72
+
73
+ protofield = FIELD_TYPE_MAPPING[field_type]
74
+
75
+ # Determine display base
76
+ if display_base is None:
77
+ display_base = DEFAULT_BASE[field_type]
78
+
79
+ if display_base not in BASE_MAPPING:
80
+ raise ValueError(f"Unknown display base: {display_base}")
81
+
82
+ base_constant = BASE_MAPPING[display_base]
83
+
84
+ return protofield, base_constant
85
+
86
+
87
+ def get_field_size(field_type: str) -> int | None:
88
+ """Get the fixed size in bytes for a field type.
89
+
90
+ Args:
91
+ field_type: Oscura field type
92
+
93
+ Returns:
94
+ Field size in bytes, or None for variable-length types
95
+ """
96
+ size_map: dict[str, int | None] = {
97
+ "uint8": 1,
98
+ "int8": 1,
99
+ "uint16": 2,
100
+ "int16": 2,
101
+ "uint32": 4,
102
+ "int32": 4,
103
+ "uint64": 8,
104
+ "int64": 8,
105
+ "float32": 4,
106
+ "float64": 8,
107
+ "bool": 1,
108
+ "bytes": None, # Variable length
109
+ "string": None, # Variable length
110
+ }
111
+ return size_map.get(field_type)
112
+
113
+
114
+ def is_variable_length(field_type: str) -> bool:
115
+ """Check if a field type is variable length.
116
+
117
+ Args:
118
+ field_type: Oscura field type
119
+
120
+ Returns:
121
+ True if field is variable length
122
+ """
123
+ return get_field_size(field_type) is None
124
+
125
+
126
+ def get_lua_reader_function(field_type: str, endian: Literal["big", "little"] = "big") -> str:
127
+ """Get the Lua buffer reader function for a field type.
128
+
129
+ Args:
130
+ field_type: Oscura field type
131
+ endian: Byte order (big or little endian)
132
+
133
+ Returns:
134
+ Lua function name (e.g., "uint16", "le_uint16")
135
+
136
+ Raises:
137
+ ValueError: If field type is unknown
138
+ """
139
+ if field_type not in FIELD_TYPE_MAPPING:
140
+ raise ValueError(f"Unknown field type: {field_type}")
141
+
142
+ # Map field types to Lua buffer reader methods
143
+ reader_map: dict[str, str] = {
144
+ "uint8": "uint",
145
+ "int8": "int",
146
+ "uint16": "uint16",
147
+ "int16": "int16",
148
+ "uint32": "uint32",
149
+ "int32": "int32",
150
+ "uint64": "uint64",
151
+ "int64": "int64",
152
+ "float32": "float",
153
+ "float64": "double",
154
+ "bool": "uint",
155
+ "bytes": "bytes",
156
+ "string": "string",
157
+ }
158
+
159
+ reader = reader_map[field_type]
160
+
161
+ # Add little-endian prefix if needed
162
+ if endian == "little" and field_type not in ["uint8", "int8", "bool", "bytes", "string"]:
163
+ return f"le_{reader}"
164
+
165
+ return reader
@@ -0,0 +1,105 @@
1
+ """Lua syntax validator using luac compiler.
2
+
3
+ This module validates generated Lua code syntax using the luac compiler
4
+ if available on the system.
5
+ """
6
+
7
+ import subprocess
8
+ from pathlib import Path
9
+
10
+
11
+ def validate_lua_syntax(lua_code: str) -> tuple[bool, str]:
12
+ """Validate Lua syntax using luac compiler.
13
+
14
+ This function attempts to validate Lua code by passing it through
15
+ the luac compiler. If luac is not available, validation is skipped.
16
+
17
+ Args:
18
+ lua_code: Lua code to validate
19
+
20
+ Returns:
21
+ Tuple of (is_valid, error_message)
22
+ - is_valid: True if syntax is valid or validation skipped
23
+ - error_message: Empty string if valid, error details if invalid,
24
+ or skip message if luac not available
25
+
26
+ Example:
27
+ >>> valid, error = validate_lua_syntax("local x = 1")
28
+ >>> if not valid:
29
+ ... print(f"Syntax error: {error}")
30
+ """
31
+ try:
32
+ # Try to validate using luac
33
+ result = subprocess.run(
34
+ ["luac", "-p", "-"],
35
+ input=lua_code.encode(),
36
+ capture_output=True,
37
+ timeout=5,
38
+ check=False,
39
+ )
40
+ if result.returncode == 0:
41
+ return True, ""
42
+ return False, result.stderr.decode()
43
+ except FileNotFoundError:
44
+ # luac not available, skip validation
45
+ return True, "luac not found, syntax validation skipped"
46
+ except subprocess.TimeoutExpired:
47
+ return False, "Validation timeout"
48
+ except Exception as e:
49
+ # Other errors - treat as unable to validate
50
+ return True, f"Validation skipped: {e!s}"
51
+
52
+
53
+ def validate_lua_file(lua_path: Path) -> tuple[bool, str]:
54
+ """Validate a Lua file using luac compiler.
55
+
56
+ Args:
57
+ lua_path: Path to Lua file
58
+
59
+ Returns:
60
+ Tuple of (is_valid, error_message)
61
+
62
+ Raises:
63
+ FileNotFoundError: If the file does not exist
64
+ """
65
+ if not lua_path.exists():
66
+ raise FileNotFoundError(f"Lua file not found: {lua_path}")
67
+
68
+ lua_code = lua_path.read_text()
69
+ return validate_lua_syntax(lua_code)
70
+
71
+
72
+ def check_luac_available() -> bool:
73
+ """Check if luac compiler is available on the system.
74
+
75
+ Returns:
76
+ True if luac is available, False otherwise
77
+ """
78
+ try:
79
+ result = subprocess.run(
80
+ ["luac", "-v"],
81
+ capture_output=True,
82
+ timeout=2,
83
+ check=False,
84
+ )
85
+ return result.returncode == 0
86
+ except (FileNotFoundError, subprocess.TimeoutExpired):
87
+ return False
88
+
89
+
90
+ def save_and_validate(lua_code: str, output_path: Path) -> tuple[bool, str]:
91
+ """Save Lua code to file and validate it.
92
+
93
+ Args:
94
+ lua_code: Lua code to save
95
+ output_path: Where to save the file
96
+
97
+ Returns:
98
+ Tuple of (is_valid, error_message)
99
+ """
100
+ # Save the file first
101
+ output_path.parent.mkdir(parents=True, exist_ok=True)
102
+ output_path.write_text(lua_code)
103
+
104
+ # Validate
105
+ return validate_lua_file(output_path)
@@ -0,0 +1,94 @@
1
+ """Data export module for Oscura.
2
+
3
+ Provides export functionality to various file formats including CSV, HDF5,
4
+ JSON, MATLAB, Markdown, HTML, NumPy NPZ, and SPICE PWL.
5
+
6
+
7
+ Example:
8
+ >>> from oscura.exporters import export_csv, export_hdf5, export_json, export_mat
9
+ >>> export_csv(trace, "waveform.csv")
10
+ >>> export_hdf5(trace, "waveform.h5")
11
+ >>> export_json(trace, "waveform.json")
12
+ >>> export_mat(trace, "waveform.mat")
13
+ >>> export_markdown(data, "report.md")
14
+ >>> export_html(data, "report.html")
15
+ >>> export_npz(trace, "waveform.npz")
16
+ >>> export_pwl(trace, "stimulus.pwl")
17
+ """
18
+
19
+ # Import exporters module as namespace for DSL compatibility
20
+ from oscura.exporters import exporters
21
+ from oscura.exporters.csv import (
22
+ export_csv,
23
+ export_multi_trace_csv,
24
+ )
25
+ from oscura.exporters.hdf5 import (
26
+ append_trace,
27
+ export_hdf5,
28
+ export_measurement_results,
29
+ )
30
+ from oscura.exporters.html_export import (
31
+ export_html,
32
+ generate_html_report,
33
+ )
34
+ from oscura.exporters.json_export import (
35
+ OscuraJSONEncoder,
36
+ export_json,
37
+ export_measurements,
38
+ export_protocol_decode,
39
+ load_json,
40
+ )
41
+ from oscura.exporters.markdown_export import (
42
+ export_markdown,
43
+ generate_markdown_report,
44
+ )
45
+ from oscura.exporters.matlab_export import (
46
+ export_mat,
47
+ export_multi_trace_mat,
48
+ )
49
+ from oscura.exporters.npz_export import (
50
+ export_npz,
51
+ load_npz,
52
+ )
53
+ from oscura.exporters.spice_export import (
54
+ export_pwl,
55
+ export_pwl_multi,
56
+ generate_spice_source,
57
+ )
58
+
59
+ __all__ = [
60
+ "OscuraJSONEncoder",
61
+ "append_trace",
62
+ # CSV export (EXP-001)
63
+ "export_csv",
64
+ # HDF5 export (EXP-002)
65
+ "export_hdf5",
66
+ # HTML export (EXP-007)
67
+ "export_html",
68
+ # JSON export (EXP-003)
69
+ "export_json",
70
+ # Markdown export (EXP-006)
71
+ "export_markdown",
72
+ # MATLAB export (EXP-008)
73
+ "export_mat",
74
+ "export_measurement_results",
75
+ "export_measurements",
76
+ "export_multi_trace_csv",
77
+ "export_multi_trace_mat",
78
+ # NPZ export (EXP-004)
79
+ "export_npz",
80
+ "export_protocol_decode",
81
+ # SPICE PWL export (EXP-005)
82
+ "export_pwl",
83
+ "export_pwl_multi",
84
+ "exporters",
85
+ # HTML report generation
86
+ "generate_html_report",
87
+ # Markdown report generation
88
+ "generate_markdown_report",
89
+ # SPICE source generation
90
+ "generate_spice_source",
91
+ "load_json",
92
+ # NPZ loading
93
+ "load_npz",
94
+ ]