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,420 @@
1
+ """Application settings management system.
2
+
3
+ This module provides application-wide settings management for Oscura,
4
+ including feature flags, CLI defaults, output formats, and runtime
5
+ configuration options.
6
+
7
+
8
+ Example:
9
+ >>> from oscura.config.settings import get_settings, Settings
10
+ >>> settings = get_settings()
11
+ >>> settings.enable_feature("advanced_analysis")
12
+ >>> if settings.is_feature_enabled("advanced_analysis"):
13
+ ... perform_advanced_analysis()
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import json
19
+ import logging
20
+ from dataclasses import dataclass, field
21
+ from pathlib import Path
22
+ from typing import Any
23
+
24
+ from oscura.core.exceptions import ConfigurationError
25
+
26
+ logger = logging.getLogger(__name__)
27
+
28
+
29
+ @dataclass
30
+ class CLIDefaults:
31
+ """CLI default settings.
32
+
33
+ Attributes:
34
+ output_format: Default output format (json, yaml, text)
35
+ verbosity: Default verbosity level (0-3)
36
+ color_output: Enable colored output
37
+ progress_bar: Show progress bars
38
+ parallel_workers: Number of parallel workers
39
+ """
40
+
41
+ output_format: str = "text"
42
+ verbosity: int = 1
43
+ color_output: bool = True
44
+ progress_bar: bool = True
45
+ parallel_workers: int = 4
46
+
47
+
48
+ @dataclass
49
+ class AnalysisSettings:
50
+ """Analysis configuration settings.
51
+
52
+ Attributes:
53
+ max_trace_size: Maximum trace size in bytes (0 = unlimited)
54
+ enable_caching: Enable result caching
55
+ cache_dir: Cache directory path
56
+ timeout: Default timeout for analysis in seconds
57
+ streaming_mode: Enable streaming mode for large files
58
+ """
59
+
60
+ max_trace_size: int = 0
61
+ enable_caching: bool = True
62
+ cache_dir: str | None = None
63
+ timeout: float = 300.0
64
+ streaming_mode: bool = False
65
+
66
+
67
+ @dataclass
68
+ class OutputSettings:
69
+ """Output and export configuration.
70
+
71
+ Attributes:
72
+ default_format: Default export format (csv, json, hdf5)
73
+ include_raw_data: Include raw waveform data in exports
74
+ compress_output: Compress output files
75
+ decimal_places: Decimal precision for numeric output
76
+ timestamp_format: Format for timestamps
77
+ """
78
+
79
+ default_format: str = "csv"
80
+ include_raw_data: bool = False
81
+ compress_output: bool = False
82
+ decimal_places: int = 6
83
+ timestamp_format: str = "iso8601"
84
+
85
+
86
+ @dataclass
87
+ class Settings:
88
+ """Application-wide settings.
89
+
90
+ Attributes:
91
+ cli: CLI defaults
92
+ analysis: Analysis settings
93
+ output: Output settings
94
+ features: Feature flags
95
+ custom: Custom user-defined settings
96
+
97
+ Example:
98
+ >>> settings = Settings()
99
+ >>> settings.cli.verbosity = 2
100
+ >>> settings.analysis.max_trace_size = 1024**3 # 1 GB
101
+ """
102
+
103
+ cli: CLIDefaults = field(default_factory=CLIDefaults)
104
+ analysis: AnalysisSettings = field(default_factory=AnalysisSettings)
105
+ output: OutputSettings = field(default_factory=OutputSettings)
106
+ features: dict[str, bool] = field(default_factory=dict)
107
+ custom: dict[str, Any] = field(default_factory=dict)
108
+
109
+ def enable_feature(self, name: str) -> None:
110
+ """Enable a feature flag.
111
+
112
+ Args:
113
+ name: Feature name
114
+
115
+ Example:
116
+ >>> settings.enable_feature("advanced_analysis")
117
+ """
118
+ self.features[name] = True
119
+ logger.debug(f"Feature enabled: {name}")
120
+
121
+ def disable_feature(self, name: str) -> None:
122
+ """Disable a feature flag.
123
+
124
+ Args:
125
+ name: Feature name
126
+
127
+ Example:
128
+ >>> settings.disable_feature("experimental_mode")
129
+ """
130
+ self.features[name] = False
131
+ logger.debug(f"Feature disabled: {name}")
132
+
133
+ def is_feature_enabled(self, name: str) -> bool:
134
+ """Check if a feature is enabled.
135
+
136
+ Args:
137
+ name: Feature name
138
+
139
+ Returns:
140
+ True if feature is enabled, False otherwise
141
+
142
+ Example:
143
+ >>> if settings.is_feature_enabled("advanced_analysis"):
144
+ ... perform_analysis()
145
+ """
146
+ return self.features.get(name, False)
147
+
148
+ def get(self, key: str, default: Any = None) -> Any:
149
+ """Get setting value by dot-notation key.
150
+
151
+ Args:
152
+ key: Key path (e.g., "cli.verbosity" or "custom.my_setting")
153
+ default: Default value if not found
154
+
155
+ Returns:
156
+ Setting value
157
+
158
+ Example:
159
+ >>> settings.get("cli.verbosity")
160
+ 1
161
+ >>> settings.get("custom.undefined", "fallback")
162
+ 'fallback'
163
+ """
164
+ parts = key.split(".")
165
+ obj: Any = self
166
+
167
+ for part in parts:
168
+ if isinstance(obj, dict):
169
+ obj = obj.get(part, default)
170
+ if obj is default:
171
+ return default
172
+ elif hasattr(obj, part):
173
+ obj = getattr(obj, part)
174
+ else:
175
+ return default
176
+
177
+ return obj
178
+
179
+ def set(self, key: str, value: Any) -> None:
180
+ """Set setting value by dot-notation key.
181
+
182
+ Args:
183
+ key: Key path (e.g., "cli.verbosity" or "custom.my_setting")
184
+ value: Value to set
185
+
186
+ Raises:
187
+ KeyError: If path is invalid
188
+
189
+ Example:
190
+ >>> settings.set("cli.verbosity", 2)
191
+ >>> settings.set("custom.my_setting", 42)
192
+ """
193
+ parts = key.split(".")
194
+
195
+ if parts[0] == "custom":
196
+ # Custom settings are a dict
197
+ if len(parts) == 2:
198
+ self.custom[parts[1]] = value
199
+ else:
200
+ # Nested custom settings
201
+ current = self.custom
202
+ for part in parts[1:-1]:
203
+ if part not in current:
204
+ current[part] = {}
205
+ current = current[part]
206
+ current[parts[-1]] = value
207
+ return
208
+
209
+ # Navigate to parent
210
+ obj: Any = self
211
+ for part in parts[:-1]:
212
+ if hasattr(obj, part):
213
+ obj = getattr(obj, part)
214
+ else:
215
+ raise KeyError(f"Invalid setting path: {key}")
216
+
217
+ # Set value
218
+ final_part = parts[-1]
219
+ if hasattr(obj, final_part):
220
+ setattr(obj, final_part, value)
221
+ else:
222
+ raise KeyError(f"Unknown setting: {key}")
223
+
224
+ def to_dict(self) -> dict[str, Any]:
225
+ """Convert settings to dictionary.
226
+
227
+ Returns:
228
+ Dictionary representation
229
+ """
230
+ return {
231
+ "cli": {
232
+ "output_format": self.cli.output_format,
233
+ "verbosity": self.cli.verbosity,
234
+ "color_output": self.cli.color_output,
235
+ "progress_bar": self.cli.progress_bar,
236
+ "parallel_workers": self.cli.parallel_workers,
237
+ },
238
+ "analysis": {
239
+ "max_trace_size": self.analysis.max_trace_size,
240
+ "enable_caching": self.analysis.enable_caching,
241
+ "cache_dir": self.analysis.cache_dir,
242
+ "timeout": self.analysis.timeout,
243
+ "streaming_mode": self.analysis.streaming_mode,
244
+ },
245
+ "output": {
246
+ "default_format": self.output.default_format,
247
+ "include_raw_data": self.output.include_raw_data,
248
+ "compress_output": self.output.compress_output,
249
+ "decimal_places": self.output.decimal_places,
250
+ "timestamp_format": self.output.timestamp_format,
251
+ },
252
+ "features": self.features,
253
+ "custom": self.custom,
254
+ }
255
+
256
+ @classmethod
257
+ def from_dict(cls, data: dict[str, Any]) -> Settings:
258
+ """Create settings from dictionary.
259
+
260
+ Args:
261
+ data: Dictionary representation
262
+
263
+ Returns:
264
+ Settings instance
265
+ """
266
+ settings = cls()
267
+
268
+ # CLI settings
269
+ if "cli" in data:
270
+ c = data["cli"]
271
+ settings.cli = CLIDefaults(
272
+ output_format=c.get("output_format", settings.cli.output_format),
273
+ verbosity=c.get("verbosity", settings.cli.verbosity),
274
+ color_output=c.get("color_output", settings.cli.color_output),
275
+ progress_bar=c.get("progress_bar", settings.cli.progress_bar),
276
+ parallel_workers=c.get("parallel_workers", settings.cli.parallel_workers),
277
+ )
278
+
279
+ # Analysis settings
280
+ if "analysis" in data:
281
+ a = data["analysis"]
282
+ settings.analysis = AnalysisSettings(
283
+ max_trace_size=a.get("max_trace_size", settings.analysis.max_trace_size),
284
+ enable_caching=a.get("enable_caching", settings.analysis.enable_caching),
285
+ cache_dir=a.get("cache_dir", settings.analysis.cache_dir),
286
+ timeout=a.get("timeout", settings.analysis.timeout),
287
+ streaming_mode=a.get("streaming_mode", settings.analysis.streaming_mode),
288
+ )
289
+
290
+ # Output settings
291
+ if "output" in data:
292
+ o = data["output"]
293
+ settings.output = OutputSettings(
294
+ default_format=o.get("default_format", settings.output.default_format),
295
+ include_raw_data=o.get("include_raw_data", settings.output.include_raw_data),
296
+ compress_output=o.get("compress_output", settings.output.compress_output),
297
+ decimal_places=o.get("decimal_places", settings.output.decimal_places),
298
+ timestamp_format=o.get("timestamp_format", settings.output.timestamp_format),
299
+ )
300
+
301
+ settings.features = data.get("features", {})
302
+ settings.custom = data.get("custom", {})
303
+
304
+ return settings
305
+
306
+
307
+ # Global settings instance
308
+ _global_settings: Settings | None = None
309
+
310
+
311
+ def get_settings() -> Settings:
312
+ """Get global application settings.
313
+
314
+ Returns:
315
+ Global Settings instance
316
+ """
317
+ global _global_settings
318
+ if _global_settings is None:
319
+ _global_settings = Settings()
320
+ return _global_settings
321
+
322
+
323
+ def set_settings(settings: Settings) -> None:
324
+ """Set global application settings.
325
+
326
+ Args:
327
+ settings: Settings instance to use globally
328
+ """
329
+ global _global_settings
330
+ _global_settings = settings
331
+ logger.debug("Global settings updated")
332
+
333
+
334
+ def reset_settings() -> None:
335
+ """Reset settings to defaults."""
336
+ global _global_settings
337
+ _global_settings = Settings()
338
+ logger.debug("Settings reset to defaults")
339
+
340
+
341
+ def load_settings(path: Path | str) -> Settings:
342
+ """Load settings from a JSON file.
343
+
344
+ Args:
345
+ path: Path to settings file
346
+
347
+ Returns:
348
+ Loaded Settings instance
349
+
350
+ Raises:
351
+ ConfigurationError: If file cannot be read or parsed
352
+
353
+ Example:
354
+ >>> settings = load_settings("settings.json")
355
+ """
356
+ try:
357
+ path_obj = Path(path).expanduser()
358
+
359
+ if not path_obj.exists():
360
+ raise ConfigurationError(f"Settings file not found: {path}")
361
+
362
+ with open(path_obj, encoding="utf-8") as f:
363
+ data = json.load(f)
364
+
365
+ if not isinstance(data, dict):
366
+ raise ConfigurationError("Settings file must contain a JSON object")
367
+
368
+ logger.debug(f"Loaded settings from {path_obj}")
369
+ return Settings.from_dict(data)
370
+
371
+ except json.JSONDecodeError as e:
372
+ raise ConfigurationError(f"Failed to parse settings JSON: {e}") from e
373
+ except OSError as e:
374
+ raise ConfigurationError(f"Failed to read settings file: {e}") from e
375
+ except Exception as e:
376
+ raise ConfigurationError(f"Error loading settings: {e}") from e
377
+
378
+
379
+ def save_settings(settings: Settings, path: Path | str) -> None:
380
+ """Save settings to a JSON file.
381
+
382
+ Args:
383
+ settings: Settings to save
384
+ path: Path to save settings to
385
+
386
+ Raises:
387
+ ConfigurationError: If file cannot be written
388
+
389
+ Example:
390
+ >>> settings = get_settings()
391
+ >>> save_settings(settings, "settings.json")
392
+ """
393
+ try:
394
+ path_obj = Path(path).expanduser()
395
+
396
+ # Create parent directory if needed
397
+ path_obj.parent.mkdir(parents=True, exist_ok=True)
398
+
399
+ with open(path_obj, "w", encoding="utf-8") as f:
400
+ json.dump(settings.to_dict(), f, indent=2)
401
+
402
+ logger.debug(f"Saved settings to {path_obj}")
403
+
404
+ except OSError as e:
405
+ raise ConfigurationError(f"Failed to write settings file: {e}") from e
406
+ except Exception as e:
407
+ raise ConfigurationError(f"Error saving settings: {e}") from e
408
+
409
+
410
+ __all__ = [
411
+ "AnalysisSettings",
412
+ "CLIDefaults",
413
+ "OutputSettings",
414
+ "Settings",
415
+ "get_settings",
416
+ "load_settings",
417
+ "reset_settings",
418
+ "save_settings",
419
+ "set_settings",
420
+ ]