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.
- oscura/__init__.py +169 -167
- oscura/analyzers/__init__.py +3 -0
- oscura/analyzers/classification.py +659 -0
- oscura/analyzers/digital/__init__.py +0 -48
- oscura/analyzers/digital/edges.py +325 -65
- oscura/analyzers/digital/extraction.py +0 -195
- oscura/analyzers/digital/quality.py +293 -166
- oscura/analyzers/digital/timing.py +260 -115
- oscura/analyzers/digital/timing_numba.py +334 -0
- oscura/analyzers/entropy.py +605 -0
- oscura/analyzers/eye/diagram.py +176 -109
- oscura/analyzers/eye/metrics.py +5 -5
- oscura/analyzers/jitter/__init__.py +6 -4
- oscura/analyzers/jitter/ber.py +52 -52
- oscura/analyzers/jitter/classification.py +156 -0
- oscura/analyzers/jitter/decomposition.py +163 -113
- oscura/analyzers/jitter/spectrum.py +80 -64
- oscura/analyzers/ml/__init__.py +39 -0
- oscura/analyzers/ml/features.py +600 -0
- oscura/analyzers/ml/signal_classifier.py +604 -0
- oscura/analyzers/packet/daq.py +246 -158
- oscura/analyzers/packet/parser.py +12 -1
- oscura/analyzers/packet/payload.py +50 -2110
- oscura/analyzers/packet/payload_analysis.py +361 -181
- oscura/analyzers/packet/payload_patterns.py +133 -70
- oscura/analyzers/packet/stream.py +84 -23
- oscura/analyzers/patterns/__init__.py +26 -5
- oscura/analyzers/patterns/anomaly_detection.py +908 -0
- oscura/analyzers/patterns/clustering.py +169 -108
- oscura/analyzers/patterns/clustering_optimized.py +227 -0
- oscura/analyzers/patterns/discovery.py +1 -1
- oscura/analyzers/patterns/matching.py +581 -197
- oscura/analyzers/patterns/pattern_mining.py +778 -0
- oscura/analyzers/patterns/periodic.py +121 -38
- oscura/analyzers/patterns/sequences.py +175 -78
- oscura/analyzers/power/conduction.py +1 -1
- oscura/analyzers/power/soa.py +6 -6
- oscura/analyzers/power/switching.py +250 -110
- oscura/analyzers/protocol/__init__.py +17 -1
- oscura/analyzers/protocols/__init__.py +1 -22
- oscura/analyzers/protocols/base.py +6 -6
- oscura/analyzers/protocols/ble/__init__.py +38 -0
- oscura/analyzers/protocols/ble/analyzer.py +809 -0
- oscura/analyzers/protocols/ble/uuids.py +288 -0
- oscura/analyzers/protocols/can.py +257 -127
- oscura/analyzers/protocols/can_fd.py +107 -80
- oscura/analyzers/protocols/flexray.py +139 -80
- oscura/analyzers/protocols/hdlc.py +93 -58
- oscura/analyzers/protocols/i2c.py +247 -106
- oscura/analyzers/protocols/i2s.py +138 -86
- oscura/analyzers/protocols/industrial/__init__.py +40 -0
- oscura/analyzers/protocols/industrial/bacnet/__init__.py +33 -0
- oscura/analyzers/protocols/industrial/bacnet/analyzer.py +708 -0
- oscura/analyzers/protocols/industrial/bacnet/encoding.py +412 -0
- oscura/analyzers/protocols/industrial/bacnet/services.py +622 -0
- oscura/analyzers/protocols/industrial/ethercat/__init__.py +30 -0
- oscura/analyzers/protocols/industrial/ethercat/analyzer.py +474 -0
- oscura/analyzers/protocols/industrial/ethercat/mailbox.py +339 -0
- oscura/analyzers/protocols/industrial/ethercat/topology.py +166 -0
- oscura/analyzers/protocols/industrial/modbus/__init__.py +31 -0
- oscura/analyzers/protocols/industrial/modbus/analyzer.py +525 -0
- oscura/analyzers/protocols/industrial/modbus/crc.py +79 -0
- oscura/analyzers/protocols/industrial/modbus/functions.py +436 -0
- oscura/analyzers/protocols/industrial/opcua/__init__.py +21 -0
- oscura/analyzers/protocols/industrial/opcua/analyzer.py +552 -0
- oscura/analyzers/protocols/industrial/opcua/datatypes.py +446 -0
- oscura/analyzers/protocols/industrial/opcua/services.py +264 -0
- oscura/analyzers/protocols/industrial/profinet/__init__.py +23 -0
- oscura/analyzers/protocols/industrial/profinet/analyzer.py +441 -0
- oscura/analyzers/protocols/industrial/profinet/dcp.py +263 -0
- oscura/analyzers/protocols/industrial/profinet/ptcp.py +200 -0
- oscura/analyzers/protocols/jtag.py +180 -98
- oscura/analyzers/protocols/lin.py +219 -114
- oscura/analyzers/protocols/manchester.py +4 -4
- oscura/analyzers/protocols/onewire.py +253 -149
- oscura/analyzers/protocols/parallel_bus/__init__.py +20 -0
- oscura/analyzers/protocols/parallel_bus/centronics.py +92 -0
- oscura/analyzers/protocols/parallel_bus/gpib.py +137 -0
- oscura/analyzers/protocols/spi.py +192 -95
- oscura/analyzers/protocols/swd.py +321 -167
- oscura/analyzers/protocols/uart.py +267 -125
- oscura/analyzers/protocols/usb.py +235 -131
- oscura/analyzers/side_channel/power.py +17 -12
- oscura/analyzers/signal/__init__.py +15 -0
- oscura/analyzers/signal/timing_analysis.py +1086 -0
- oscura/analyzers/signal_integrity/__init__.py +4 -1
- oscura/analyzers/signal_integrity/sparams.py +2 -19
- oscura/analyzers/spectral/chunked.py +129 -60
- oscura/analyzers/spectral/chunked_fft.py +300 -94
- oscura/analyzers/spectral/chunked_wavelet.py +100 -80
- oscura/analyzers/statistical/checksum.py +376 -217
- oscura/analyzers/statistical/classification.py +229 -107
- oscura/analyzers/statistical/entropy.py +78 -53
- oscura/analyzers/statistics/correlation.py +407 -211
- oscura/analyzers/statistics/outliers.py +2 -2
- oscura/analyzers/statistics/streaming.py +30 -5
- oscura/analyzers/validation.py +216 -101
- oscura/analyzers/waveform/measurements.py +9 -0
- oscura/analyzers/waveform/measurements_with_uncertainty.py +31 -15
- oscura/analyzers/waveform/spectral.py +500 -228
- oscura/api/__init__.py +31 -5
- oscura/api/dsl/__init__.py +582 -0
- oscura/{dsl → api/dsl}/commands.py +43 -76
- oscura/{dsl → api/dsl}/interpreter.py +26 -51
- oscura/{dsl → api/dsl}/parser.py +107 -77
- oscura/{dsl → api/dsl}/repl.py +2 -2
- oscura/api/dsl.py +1 -1
- oscura/{integrations → api/integrations}/__init__.py +1 -1
- oscura/{integrations → api/integrations}/llm.py +201 -102
- oscura/api/operators.py +3 -3
- oscura/api/optimization.py +144 -30
- oscura/api/rest_server.py +921 -0
- oscura/api/server/__init__.py +17 -0
- oscura/api/server/dashboard.py +850 -0
- oscura/api/server/static/README.md +34 -0
- oscura/api/server/templates/base.html +181 -0
- oscura/api/server/templates/export.html +120 -0
- oscura/api/server/templates/home.html +284 -0
- oscura/api/server/templates/protocols.html +58 -0
- oscura/api/server/templates/reports.html +43 -0
- oscura/api/server/templates/session_detail.html +89 -0
- oscura/api/server/templates/sessions.html +83 -0
- oscura/api/server/templates/waveforms.html +73 -0
- oscura/automotive/__init__.py +8 -1
- oscura/automotive/can/__init__.py +10 -0
- oscura/automotive/can/checksum.py +3 -1
- oscura/automotive/can/dbc_generator.py +590 -0
- oscura/automotive/can/message_wrapper.py +121 -74
- oscura/automotive/can/patterns.py +98 -21
- oscura/automotive/can/session.py +292 -56
- oscura/automotive/can/state_machine.py +6 -3
- oscura/automotive/can/stimulus_response.py +97 -75
- oscura/automotive/dbc/__init__.py +10 -2
- oscura/automotive/dbc/generator.py +84 -56
- oscura/automotive/dbc/parser.py +6 -6
- oscura/automotive/dtc/data.json +2763 -0
- oscura/automotive/dtc/database.py +2 -2
- oscura/automotive/flexray/__init__.py +31 -0
- oscura/automotive/flexray/analyzer.py +504 -0
- oscura/automotive/flexray/crc.py +185 -0
- oscura/automotive/flexray/fibex.py +449 -0
- oscura/automotive/j1939/__init__.py +45 -8
- oscura/automotive/j1939/analyzer.py +605 -0
- oscura/automotive/j1939/spns.py +326 -0
- oscura/automotive/j1939/transport.py +306 -0
- oscura/automotive/lin/__init__.py +47 -0
- oscura/automotive/lin/analyzer.py +612 -0
- oscura/automotive/loaders/blf.py +13 -2
- oscura/automotive/loaders/csv_can.py +143 -72
- oscura/automotive/loaders/dispatcher.py +50 -2
- oscura/automotive/loaders/mdf.py +86 -45
- oscura/automotive/loaders/pcap.py +111 -61
- oscura/automotive/uds/__init__.py +4 -0
- oscura/automotive/uds/analyzer.py +725 -0
- oscura/automotive/uds/decoder.py +140 -58
- oscura/automotive/uds/models.py +7 -1
- oscura/automotive/visualization.py +1 -1
- oscura/cli/analyze.py +348 -0
- oscura/cli/batch.py +142 -122
- oscura/cli/benchmark.py +275 -0
- oscura/cli/characterize.py +137 -82
- oscura/cli/compare.py +224 -131
- oscura/cli/completion.py +250 -0
- oscura/cli/config_cmd.py +361 -0
- oscura/cli/decode.py +164 -87
- oscura/cli/export.py +286 -0
- oscura/cli/main.py +115 -31
- oscura/{onboarding → cli/onboarding}/__init__.py +3 -3
- oscura/{onboarding → cli/onboarding}/help.py +80 -58
- oscura/{onboarding → cli/onboarding}/tutorials.py +97 -72
- oscura/{onboarding → cli/onboarding}/wizard.py +55 -36
- oscura/cli/progress.py +147 -0
- oscura/cli/shell.py +157 -135
- oscura/cli/validate_cmd.py +204 -0
- oscura/cli/visualize.py +158 -0
- oscura/convenience.py +125 -79
- oscura/core/__init__.py +4 -2
- oscura/core/backend_selector.py +3 -3
- oscura/core/cache.py +126 -15
- oscura/core/cancellation.py +1 -1
- oscura/{config → core/config}/__init__.py +20 -11
- oscura/{config → core/config}/defaults.py +1 -1
- oscura/{config → core/config}/loader.py +7 -5
- oscura/{config → core/config}/memory.py +5 -5
- oscura/{config → core/config}/migration.py +1 -1
- oscura/{config → core/config}/pipeline.py +99 -23
- oscura/{config → core/config}/preferences.py +1 -1
- oscura/{config → core/config}/protocol.py +3 -3
- oscura/{config → core/config}/schema.py +426 -272
- oscura/{config → core/config}/settings.py +1 -1
- oscura/{config → core/config}/thresholds.py +195 -153
- oscura/core/correlation.py +5 -6
- oscura/core/cross_domain.py +0 -2
- oscura/core/debug.py +9 -5
- oscura/{extensibility → core/extensibility}/docs.py +158 -70
- oscura/{extensibility → core/extensibility}/extensions.py +160 -76
- oscura/{extensibility → core/extensibility}/logging.py +1 -1
- oscura/{extensibility → core/extensibility}/measurements.py +1 -1
- oscura/{extensibility → core/extensibility}/plugins.py +1 -1
- oscura/{extensibility → core/extensibility}/templates.py +73 -3
- oscura/{extensibility → core/extensibility}/validation.py +1 -1
- oscura/core/gpu_backend.py +11 -7
- oscura/core/log_query.py +101 -11
- oscura/core/logging.py +126 -54
- oscura/core/logging_advanced.py +5 -5
- oscura/core/memory_limits.py +108 -70
- oscura/core/memory_monitor.py +2 -2
- oscura/core/memory_progress.py +7 -7
- oscura/core/memory_warnings.py +1 -1
- oscura/core/numba_backend.py +13 -13
- oscura/{plugins → core/plugins}/__init__.py +9 -9
- oscura/{plugins → core/plugins}/base.py +7 -7
- oscura/{plugins → core/plugins}/cli.py +3 -3
- oscura/{plugins → core/plugins}/discovery.py +186 -106
- oscura/{plugins → core/plugins}/lifecycle.py +1 -1
- oscura/{plugins → core/plugins}/manager.py +7 -7
- oscura/{plugins → core/plugins}/registry.py +3 -3
- oscura/{plugins → core/plugins}/versioning.py +1 -1
- oscura/core/progress.py +16 -1
- oscura/core/provenance.py +8 -2
- oscura/{schemas → core/schemas}/__init__.py +2 -2
- oscura/core/schemas/bus_configuration.json +322 -0
- oscura/core/schemas/device_mapping.json +182 -0
- oscura/core/schemas/packet_format.json +418 -0
- oscura/core/schemas/protocol_definition.json +363 -0
- oscura/core/types.py +4 -0
- oscura/core/uncertainty.py +3 -3
- oscura/correlation/__init__.py +52 -0
- oscura/correlation/multi_protocol.py +811 -0
- oscura/discovery/auto_decoder.py +117 -35
- oscura/discovery/comparison.py +191 -86
- oscura/discovery/quality_validator.py +155 -68
- oscura/discovery/signal_detector.py +196 -79
- oscura/export/__init__.py +18 -20
- oscura/export/kaitai_struct.py +513 -0
- oscura/export/scapy_layer.py +801 -0
- oscura/export/wireshark/README.md +15 -15
- oscura/export/wireshark/generator.py +1 -1
- oscura/export/wireshark/templates/dissector.lua.j2 +2 -2
- oscura/export/wireshark_dissector.py +746 -0
- oscura/guidance/wizard.py +207 -111
- oscura/hardware/__init__.py +19 -0
- oscura/{acquisition → hardware/acquisition}/__init__.py +4 -4
- oscura/{acquisition → hardware/acquisition}/file.py +2 -2
- oscura/{acquisition → hardware/acquisition}/hardware.py +7 -7
- oscura/{acquisition → hardware/acquisition}/saleae.py +15 -12
- oscura/{acquisition → hardware/acquisition}/socketcan.py +1 -1
- oscura/{acquisition → hardware/acquisition}/streaming.py +2 -2
- oscura/{acquisition → hardware/acquisition}/synthetic.py +3 -3
- oscura/{acquisition → hardware/acquisition}/visa.py +33 -11
- oscura/hardware/firmware/__init__.py +29 -0
- oscura/hardware/firmware/pattern_recognition.py +874 -0
- oscura/hardware/hal_detector.py +736 -0
- oscura/hardware/security/__init__.py +37 -0
- oscura/hardware/security/side_channel_detector.py +1126 -0
- oscura/inference/__init__.py +4 -0
- oscura/inference/active_learning/README.md +7 -7
- oscura/inference/active_learning/observation_table.py +4 -1
- oscura/inference/alignment.py +216 -123
- oscura/inference/bayesian.py +113 -33
- oscura/inference/crc_reverse.py +101 -55
- oscura/inference/logic.py +6 -2
- oscura/inference/message_format.py +342 -183
- oscura/inference/protocol.py +95 -44
- oscura/inference/protocol_dsl.py +180 -82
- oscura/inference/signal_intelligence.py +1439 -706
- oscura/inference/spectral.py +99 -57
- oscura/inference/state_machine.py +810 -158
- oscura/inference/stream.py +270 -110
- oscura/iot/__init__.py +34 -0
- oscura/iot/coap/__init__.py +32 -0
- oscura/iot/coap/analyzer.py +668 -0
- oscura/iot/coap/options.py +212 -0
- oscura/iot/lorawan/__init__.py +21 -0
- oscura/iot/lorawan/crypto.py +206 -0
- oscura/iot/lorawan/decoder.py +801 -0
- oscura/iot/lorawan/mac_commands.py +341 -0
- oscura/iot/mqtt/__init__.py +27 -0
- oscura/iot/mqtt/analyzer.py +999 -0
- oscura/iot/mqtt/properties.py +315 -0
- oscura/iot/zigbee/__init__.py +31 -0
- oscura/iot/zigbee/analyzer.py +615 -0
- oscura/iot/zigbee/security.py +153 -0
- oscura/iot/zigbee/zcl.py +349 -0
- oscura/jupyter/display.py +125 -45
- oscura/{exploratory → jupyter/exploratory}/__init__.py +8 -8
- oscura/{exploratory → jupyter/exploratory}/error_recovery.py +298 -141
- oscura/jupyter/exploratory/fuzzy.py +746 -0
- oscura/{exploratory → jupyter/exploratory}/fuzzy_advanced.py +258 -100
- oscura/{exploratory → jupyter/exploratory}/legacy.py +464 -242
- oscura/{exploratory → jupyter/exploratory}/parse.py +167 -145
- oscura/{exploratory → jupyter/exploratory}/recovery.py +119 -87
- oscura/jupyter/exploratory/sync.py +612 -0
- oscura/{exploratory → jupyter/exploratory}/unknown.py +299 -176
- oscura/jupyter/magic.py +4 -4
- oscura/{ui → jupyter/ui}/__init__.py +2 -2
- oscura/{ui → jupyter/ui}/formatters.py +3 -3
- oscura/{ui → jupyter/ui}/progressive_display.py +153 -82
- oscura/loaders/__init__.py +171 -63
- oscura/loaders/binary.py +88 -1
- oscura/loaders/chipwhisperer.py +153 -137
- oscura/loaders/configurable.py +208 -86
- oscura/loaders/csv_loader.py +458 -215
- oscura/loaders/hdf5_loader.py +278 -119
- oscura/loaders/lazy.py +87 -54
- oscura/loaders/mmap_loader.py +1 -1
- oscura/loaders/numpy_loader.py +253 -116
- oscura/loaders/pcap.py +226 -151
- oscura/loaders/rigol.py +110 -49
- oscura/loaders/sigrok.py +201 -78
- oscura/loaders/tdms.py +81 -58
- oscura/loaders/tektronix.py +291 -174
- oscura/loaders/touchstone.py +182 -87
- oscura/loaders/vcd.py +215 -117
- oscura/loaders/wav.py +155 -68
- oscura/reporting/__init__.py +9 -7
- oscura/reporting/analyze.py +352 -146
- oscura/reporting/argument_preparer.py +69 -14
- oscura/reporting/auto_report.py +97 -61
- oscura/reporting/batch.py +131 -58
- oscura/reporting/chart_selection.py +57 -45
- oscura/reporting/comparison.py +63 -17
- oscura/reporting/content/executive.py +76 -24
- oscura/reporting/core_formats/multi_format.py +11 -8
- oscura/reporting/engine.py +312 -158
- oscura/reporting/enhanced_reports.py +949 -0
- oscura/reporting/export.py +86 -43
- oscura/reporting/formatting/numbers.py +69 -42
- oscura/reporting/html.py +139 -58
- oscura/reporting/index.py +137 -65
- oscura/reporting/output.py +158 -67
- oscura/reporting/pdf.py +67 -102
- oscura/reporting/plots.py +191 -112
- oscura/reporting/sections.py +88 -47
- oscura/reporting/standards.py +104 -61
- oscura/reporting/summary_generator.py +75 -55
- oscura/reporting/tables.py +138 -54
- oscura/reporting/templates/enhanced/protocol_re.html +525 -0
- oscura/reporting/templates/index.md +13 -13
- oscura/sessions/__init__.py +14 -23
- oscura/sessions/base.py +3 -3
- oscura/sessions/blackbox.py +106 -10
- oscura/sessions/generic.py +2 -2
- oscura/sessions/legacy.py +783 -0
- oscura/side_channel/__init__.py +63 -0
- oscura/side_channel/dpa.py +1025 -0
- oscura/utils/__init__.py +15 -1
- oscura/utils/autodetect.py +1 -5
- oscura/utils/bitwise.py +118 -0
- oscura/{builders → utils/builders}/__init__.py +1 -1
- oscura/{comparison → utils/comparison}/__init__.py +6 -6
- oscura/{comparison → utils/comparison}/compare.py +202 -101
- oscura/{comparison → utils/comparison}/golden.py +83 -63
- oscura/{comparison → utils/comparison}/limits.py +313 -89
- oscura/{comparison → utils/comparison}/mask.py +151 -45
- oscura/{comparison → utils/comparison}/trace_diff.py +1 -1
- oscura/{comparison → utils/comparison}/visualization.py +147 -89
- oscura/{component → utils/component}/__init__.py +3 -3
- oscura/{component → utils/component}/impedance.py +122 -58
- oscura/{component → utils/component}/reactive.py +165 -168
- oscura/{component → utils/component}/transmission_line.py +3 -3
- oscura/{filtering → utils/filtering}/__init__.py +6 -6
- oscura/{filtering → utils/filtering}/base.py +1 -1
- oscura/{filtering → utils/filtering}/convenience.py +2 -2
- oscura/{filtering → utils/filtering}/design.py +169 -93
- oscura/{filtering → utils/filtering}/filters.py +2 -2
- oscura/{filtering → utils/filtering}/introspection.py +2 -2
- oscura/utils/geometry.py +31 -0
- oscura/utils/imports.py +184 -0
- oscura/utils/lazy.py +1 -1
- oscura/{math → utils/math}/__init__.py +2 -2
- oscura/{math → utils/math}/arithmetic.py +114 -48
- oscura/{math → utils/math}/interpolation.py +139 -106
- oscura/utils/memory.py +129 -66
- oscura/utils/memory_advanced.py +92 -9
- oscura/utils/memory_extensions.py +10 -8
- oscura/{optimization → utils/optimization}/__init__.py +1 -1
- oscura/{optimization → utils/optimization}/search.py +2 -2
- oscura/utils/performance/__init__.py +58 -0
- oscura/utils/performance/caching.py +889 -0
- oscura/utils/performance/lsh_clustering.py +333 -0
- oscura/utils/performance/memory_optimizer.py +699 -0
- oscura/utils/performance/optimizations.py +675 -0
- oscura/utils/performance/parallel.py +654 -0
- oscura/utils/performance/profiling.py +661 -0
- oscura/{pipeline → utils/pipeline}/base.py +1 -1
- oscura/{pipeline → utils/pipeline}/composition.py +11 -3
- oscura/{pipeline → utils/pipeline}/parallel.py +3 -2
- oscura/{pipeline → utils/pipeline}/pipeline.py +1 -1
- oscura/{pipeline → utils/pipeline}/reverse_engineering.py +412 -221
- oscura/{search → utils/search}/__init__.py +3 -3
- oscura/{search → utils/search}/anomaly.py +188 -58
- oscura/utils/search/context.py +294 -0
- oscura/{search → utils/search}/pattern.py +138 -10
- oscura/utils/serial.py +51 -0
- oscura/utils/storage/__init__.py +61 -0
- oscura/utils/storage/database.py +1166 -0
- oscura/{streaming → utils/streaming}/chunked.py +302 -143
- oscura/{streaming → utils/streaming}/progressive.py +1 -1
- oscura/{streaming → utils/streaming}/realtime.py +3 -2
- oscura/{triggering → utils/triggering}/__init__.py +6 -6
- oscura/{triggering → utils/triggering}/base.py +6 -6
- oscura/{triggering → utils/triggering}/edge.py +2 -2
- oscura/{triggering → utils/triggering}/pattern.py +2 -2
- oscura/{triggering → utils/triggering}/pulse.py +115 -74
- oscura/{triggering → utils/triggering}/window.py +2 -2
- oscura/utils/validation.py +32 -0
- oscura/validation/__init__.py +121 -0
- oscura/{compliance → validation/compliance}/__init__.py +5 -5
- oscura/{compliance → validation/compliance}/advanced.py +5 -5
- oscura/{compliance → validation/compliance}/masks.py +1 -1
- oscura/{compliance → validation/compliance}/reporting.py +127 -53
- oscura/{compliance → validation/compliance}/testing.py +114 -52
- oscura/validation/compliance_tests.py +915 -0
- oscura/validation/fuzzer.py +990 -0
- oscura/validation/grammar_tests.py +596 -0
- oscura/validation/grammar_validator.py +904 -0
- oscura/validation/hil_testing.py +977 -0
- oscura/{quality → validation/quality}/__init__.py +4 -4
- oscura/{quality → validation/quality}/ensemble.py +251 -171
- oscura/{quality → validation/quality}/explainer.py +3 -3
- oscura/{quality → validation/quality}/scoring.py +1 -1
- oscura/{quality → validation/quality}/warnings.py +4 -4
- oscura/validation/regression_suite.py +808 -0
- oscura/validation/replay.py +788 -0
- oscura/{testing → validation/testing}/__init__.py +2 -2
- oscura/{testing → validation/testing}/synthetic.py +5 -5
- oscura/visualization/__init__.py +9 -0
- oscura/visualization/accessibility.py +1 -1
- oscura/visualization/annotations.py +64 -67
- oscura/visualization/colors.py +7 -7
- oscura/visualization/digital.py +180 -81
- oscura/visualization/eye.py +236 -85
- oscura/visualization/interactive.py +320 -143
- oscura/visualization/jitter.py +587 -247
- oscura/visualization/layout.py +169 -134
- oscura/visualization/optimization.py +103 -52
- oscura/visualization/palettes.py +1 -1
- oscura/visualization/power.py +427 -211
- oscura/visualization/power_extended.py +626 -297
- oscura/visualization/presets.py +2 -0
- oscura/visualization/protocols.py +495 -181
- oscura/visualization/render.py +79 -63
- oscura/visualization/reverse_engineering.py +171 -124
- oscura/visualization/signal_integrity.py +460 -279
- oscura/visualization/specialized.py +190 -100
- oscura/visualization/spectral.py +670 -255
- oscura/visualization/thumbnails.py +166 -137
- oscura/visualization/waveform.py +150 -63
- oscura/workflows/__init__.py +3 -0
- oscura/{batch → workflows/batch}/__init__.py +5 -5
- oscura/{batch → workflows/batch}/advanced.py +150 -75
- oscura/workflows/batch/aggregate.py +531 -0
- oscura/workflows/batch/analyze.py +236 -0
- oscura/{batch → workflows/batch}/logging.py +2 -2
- oscura/{batch → workflows/batch}/metrics.py +1 -1
- oscura/workflows/complete_re.py +1144 -0
- oscura/workflows/compliance.py +44 -54
- oscura/workflows/digital.py +197 -51
- oscura/workflows/legacy/__init__.py +12 -0
- oscura/{workflow → workflows/legacy}/dag.py +4 -1
- oscura/workflows/multi_trace.py +9 -9
- oscura/workflows/power.py +42 -62
- oscura/workflows/protocol.py +82 -49
- oscura/workflows/reverse_engineering.py +351 -150
- oscura/workflows/signal_integrity.py +157 -82
- oscura-0.6.0.dist-info/METADATA +643 -0
- oscura-0.6.0.dist-info/RECORD +590 -0
- oscura/analyzers/digital/ic_database.py +0 -498
- oscura/analyzers/digital/timing_paths.py +0 -339
- oscura/analyzers/digital/vintage.py +0 -377
- oscura/analyzers/digital/vintage_result.py +0 -148
- oscura/analyzers/protocols/parallel_bus.py +0 -449
- oscura/batch/aggregate.py +0 -300
- oscura/batch/analyze.py +0 -139
- oscura/dsl/__init__.py +0 -73
- oscura/exceptions.py +0 -59
- oscura/exploratory/fuzzy.py +0 -513
- oscura/exploratory/sync.py +0 -384
- oscura/export/wavedrom.py +0 -430
- oscura/exporters/__init__.py +0 -94
- oscura/exporters/csv.py +0 -303
- oscura/exporters/exporters.py +0 -44
- oscura/exporters/hdf5.py +0 -217
- oscura/exporters/html_export.py +0 -701
- oscura/exporters/json_export.py +0 -338
- oscura/exporters/markdown_export.py +0 -367
- oscura/exporters/matlab_export.py +0 -354
- oscura/exporters/npz_export.py +0 -219
- oscura/exporters/spice_export.py +0 -210
- oscura/exporters/vintage_logic_csv.py +0 -247
- oscura/reporting/vintage_logic_report.py +0 -523
- oscura/search/context.py +0 -149
- oscura/session/__init__.py +0 -34
- oscura/session/annotations.py +0 -289
- oscura/session/history.py +0 -313
- oscura/session/session.py +0 -520
- oscura/visualization/digital_advanced.py +0 -718
- oscura/visualization/figure_manager.py +0 -156
- oscura/workflow/__init__.py +0 -13
- oscura-0.5.0.dist-info/METADATA +0 -407
- oscura-0.5.0.dist-info/RECORD +0 -486
- /oscura/core/{config.py → config/legacy.py} +0 -0
- /oscura/{extensibility → core/extensibility}/__init__.py +0 -0
- /oscura/{extensibility → core/extensibility}/registry.py +0 -0
- /oscura/{plugins → core/plugins}/isolation.py +0 -0
- /oscura/{builders → utils/builders}/signal_builder.py +0 -0
- /oscura/{optimization → utils/optimization}/parallel.py +0 -0
- /oscura/{pipeline → utils/pipeline}/__init__.py +0 -0
- /oscura/{streaming → utils/streaming}/__init__.py +0 -0
- {oscura-0.5.0.dist-info → oscura-0.6.0.dist-info}/WHEEL +0 -0
- {oscura-0.5.0.dist-info → oscura-0.6.0.dist-info}/entry_points.txt +0 -0
- {oscura-0.5.0.dist-info → oscura-0.6.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -16,13 +16,20 @@ from dataclasses import asdict, dataclass, field
|
|
|
16
16
|
from pathlib import Path
|
|
17
17
|
from typing import TYPE_CHECKING, Any, Literal
|
|
18
18
|
|
|
19
|
-
import
|
|
19
|
+
# Lazy import for optional dataframe support
|
|
20
|
+
try:
|
|
21
|
+
import pandas as pd
|
|
22
|
+
|
|
23
|
+
_HAS_PANDAS = True
|
|
24
|
+
except ImportError:
|
|
25
|
+
pd = None # type: ignore[assignment]
|
|
26
|
+
_HAS_PANDAS = False
|
|
20
27
|
|
|
21
28
|
if TYPE_CHECKING:
|
|
22
29
|
from collections.abc import Callable
|
|
23
30
|
|
|
24
31
|
try:
|
|
25
|
-
from tqdm import tqdm
|
|
32
|
+
from tqdm import tqdm
|
|
26
33
|
|
|
27
34
|
HAS_TQDM = True
|
|
28
35
|
except ImportError:
|
|
@@ -269,7 +276,7 @@ def _run_with_timeout(
|
|
|
269
276
|
if result_container["error"] is not None:
|
|
270
277
|
raise result_container["error"]
|
|
271
278
|
|
|
272
|
-
return result_container["result"], False
|
|
279
|
+
return result_container["result"], False
|
|
273
280
|
|
|
274
281
|
|
|
275
282
|
class AdvancedBatchProcessor:
|
|
@@ -287,7 +294,7 @@ class AdvancedBatchProcessor:
|
|
|
287
294
|
- Processing continues to the next file
|
|
288
295
|
|
|
289
296
|
Example:
|
|
290
|
-
>>> from oscura.batch.advanced import AdvancedBatchProcessor, BatchConfig
|
|
297
|
+
>>> from oscura.workflows.batch.advanced import AdvancedBatchProcessor, BatchConfig
|
|
291
298
|
>>> config = BatchConfig(
|
|
292
299
|
... on_error='skip',
|
|
293
300
|
... checkpoint_dir='./checkpoints',
|
|
@@ -335,9 +342,21 @@ class AdvancedBatchProcessor:
|
|
|
335
342
|
... analysis_fn=analyze_trace
|
|
336
343
|
... )
|
|
337
344
|
|
|
345
|
+
Raises:
|
|
346
|
+
ImportError: If pandas is not installed.
|
|
347
|
+
|
|
338
348
|
References:
|
|
339
349
|
API-012: Advanced Batch Control
|
|
340
350
|
"""
|
|
351
|
+
if not _HAS_PANDAS:
|
|
352
|
+
raise ImportError(
|
|
353
|
+
"Batch processing requires pandas.\n\n"
|
|
354
|
+
"Install with:\n"
|
|
355
|
+
" pip install oscura[dataframes] # DataFrame support\n"
|
|
356
|
+
" pip install oscura[standard] # Recommended\n"
|
|
357
|
+
" pip install oscura[all] # Everything\n"
|
|
358
|
+
)
|
|
359
|
+
|
|
341
360
|
# Try to resume from checkpoint
|
|
342
361
|
remaining_files = self._resume_or_start(files, checkpoint_name)
|
|
343
362
|
|
|
@@ -392,39 +411,38 @@ class AdvancedBatchProcessor:
|
|
|
392
411
|
|
|
393
412
|
return files
|
|
394
413
|
|
|
395
|
-
def
|
|
414
|
+
def _create_progress_bar(self) -> Any:
|
|
415
|
+
"""Create progress bar if requested.
|
|
416
|
+
|
|
417
|
+
Returns:
|
|
418
|
+
tqdm progress bar or None.
|
|
419
|
+
"""
|
|
420
|
+
if not (self.config.progress_bar and HAS_TQDM):
|
|
421
|
+
return None
|
|
422
|
+
|
|
423
|
+
total = self.checkpoint.total_files if self.checkpoint else 0
|
|
424
|
+
initial = (
|
|
425
|
+
len(self.checkpoint.completed_files) + len(self.checkpoint.failed_files)
|
|
426
|
+
if self.checkpoint
|
|
427
|
+
else 0
|
|
428
|
+
)
|
|
429
|
+
return tqdm(total=total, initial=initial, desc="Processing files")
|
|
430
|
+
|
|
431
|
+
def _create_file_processor(
|
|
396
432
|
self,
|
|
397
|
-
files: list[str | Path],
|
|
398
433
|
analysis_fn: Callable[[str | Path], dict[str, Any]],
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
"""Process files with parallel execution and checkpointing.
|
|
434
|
+
kwargs: dict[str, Any],
|
|
435
|
+
) -> Callable[[str | Path], FileResult]:
|
|
436
|
+
"""Create wrapper function for processing a single file.
|
|
403
437
|
|
|
404
438
|
Args:
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
checkpoint_name: Checkpoint file name.
|
|
408
|
-
**kwargs: Additional arguments for analysis_fn.
|
|
439
|
+
analysis_fn: Analysis function to apply.
|
|
440
|
+
kwargs: Keyword arguments for analysis_fn.
|
|
409
441
|
|
|
410
|
-
|
|
411
|
-
|
|
442
|
+
Returns:
|
|
443
|
+
Wrapper function that returns FileResult.
|
|
412
444
|
"""
|
|
413
|
-
if not files:
|
|
414
|
-
return
|
|
415
445
|
|
|
416
|
-
# Create progress bar if requested
|
|
417
|
-
pbar = None
|
|
418
|
-
if self.config.progress_bar and HAS_TQDM:
|
|
419
|
-
total = self.checkpoint.total_files if self.checkpoint else len(files)
|
|
420
|
-
initial = (
|
|
421
|
-
len(self.checkpoint.completed_files) + len(self.checkpoint.failed_files)
|
|
422
|
-
if self.checkpoint
|
|
423
|
-
else 0
|
|
424
|
-
)
|
|
425
|
-
pbar = tqdm(total=total, initial=initial, desc="Processing files")
|
|
426
|
-
|
|
427
|
-
# Wrapper for file processing with error handling and timeout
|
|
428
446
|
def _process_one(file_path: str | Path) -> FileResult:
|
|
429
447
|
import time
|
|
430
448
|
|
|
@@ -469,6 +487,105 @@ class AdvancedBatchProcessor:
|
|
|
469
487
|
duration=duration,
|
|
470
488
|
)
|
|
471
489
|
|
|
490
|
+
return _process_one
|
|
491
|
+
|
|
492
|
+
def _retrieve_future_result(
|
|
493
|
+
self, future: concurrent.futures.Future[FileResult], file_path: str | Path
|
|
494
|
+
) -> FileResult:
|
|
495
|
+
"""Retrieve result from future with timeout handling.
|
|
496
|
+
|
|
497
|
+
Args:
|
|
498
|
+
future: Future to retrieve result from.
|
|
499
|
+
file_path: Path being processed (for error messages).
|
|
500
|
+
|
|
501
|
+
Returns:
|
|
502
|
+
FileResult from future or error result if timeout/exception.
|
|
503
|
+
"""
|
|
504
|
+
try:
|
|
505
|
+
# Apply timeout on result retrieval as backup enforcement
|
|
506
|
+
retrieval_timeout = (
|
|
507
|
+
self.config.timeout_per_file * 1.1 if self.config.timeout_per_file else None
|
|
508
|
+
)
|
|
509
|
+
return future.result(timeout=retrieval_timeout)
|
|
510
|
+
except concurrent.futures.TimeoutError:
|
|
511
|
+
# Backup timeout triggered
|
|
512
|
+
return FileResult(
|
|
513
|
+
file=str(file_path),
|
|
514
|
+
success=False,
|
|
515
|
+
error=f"Processing timed out (backup enforcement) "
|
|
516
|
+
f"after {self.config.timeout_per_file}s",
|
|
517
|
+
timed_out=True,
|
|
518
|
+
)
|
|
519
|
+
except Exception as e:
|
|
520
|
+
# Unexpected error during result retrieval
|
|
521
|
+
return FileResult(
|
|
522
|
+
file=str(file_path),
|
|
523
|
+
success=False,
|
|
524
|
+
error=f"Error retrieving result: {e}",
|
|
525
|
+
traceback=traceback.format_exc(),
|
|
526
|
+
)
|
|
527
|
+
|
|
528
|
+
def _update_checkpoint_with_result(self, file_result: FileResult) -> None:
|
|
529
|
+
"""Update checkpoint with processing result.
|
|
530
|
+
|
|
531
|
+
Args:
|
|
532
|
+
file_result: Result to add to checkpoint.
|
|
533
|
+
"""
|
|
534
|
+
if not self.checkpoint:
|
|
535
|
+
return
|
|
536
|
+
|
|
537
|
+
self.checkpoint.results.append(file_result)
|
|
538
|
+
if file_result.success:
|
|
539
|
+
self.checkpoint.completed_files.append(file_result.file)
|
|
540
|
+
else:
|
|
541
|
+
self.checkpoint.failed_files.append(file_result.file)
|
|
542
|
+
|
|
543
|
+
def _handle_file_error(self, file_result: FileResult, pbar: Any) -> None:
|
|
544
|
+
"""Handle error from file processing.
|
|
545
|
+
|
|
546
|
+
Args:
|
|
547
|
+
file_result: Result with error.
|
|
548
|
+
pbar: Progress bar to close if stopping.
|
|
549
|
+
|
|
550
|
+
Raises:
|
|
551
|
+
RuntimeError: If on_error is "stop".
|
|
552
|
+
"""
|
|
553
|
+
if self.config.on_error == "stop":
|
|
554
|
+
if pbar:
|
|
555
|
+
pbar.close()
|
|
556
|
+
raise RuntimeError(
|
|
557
|
+
f"Processing stopped due to error in {file_result.file}: {file_result.error}"
|
|
558
|
+
)
|
|
559
|
+
elif self.config.on_error == "warn":
|
|
560
|
+
timeout_note = " (TIMEOUT)" if file_result.timed_out else ""
|
|
561
|
+
print(
|
|
562
|
+
f"Warning: Error processing {file_result.file}{timeout_note}: {file_result.error}"
|
|
563
|
+
)
|
|
564
|
+
|
|
565
|
+
def _process_files(
|
|
566
|
+
self,
|
|
567
|
+
files: list[str | Path],
|
|
568
|
+
analysis_fn: Callable[[str | Path], dict[str, Any]],
|
|
569
|
+
checkpoint_name: str,
|
|
570
|
+
**kwargs: Any,
|
|
571
|
+
) -> None:
|
|
572
|
+
"""Process files with parallel execution and checkpointing.
|
|
573
|
+
|
|
574
|
+
Args:
|
|
575
|
+
files: Files to process.
|
|
576
|
+
analysis_fn: Analysis function.
|
|
577
|
+
checkpoint_name: Checkpoint file name.
|
|
578
|
+
**kwargs: Additional arguments for analysis_fn.
|
|
579
|
+
|
|
580
|
+
Raises:
|
|
581
|
+
RuntimeError: If processing is stopped due to error and on_error is "stop".
|
|
582
|
+
"""
|
|
583
|
+
if not files:
|
|
584
|
+
return
|
|
585
|
+
|
|
586
|
+
pbar = self._create_progress_bar()
|
|
587
|
+
_process_one = self._create_file_processor(analysis_fn, kwargs)
|
|
588
|
+
|
|
472
589
|
# Process files
|
|
473
590
|
processed_count = 0
|
|
474
591
|
executor_class = ThreadPoolExecutor if self.config.use_threads else ProcessPoolExecutor
|
|
@@ -478,58 +595,16 @@ class AdvancedBatchProcessor:
|
|
|
478
595
|
futures = {executor.submit(_process_one, f): f for f in files}
|
|
479
596
|
|
|
480
597
|
# Process results as they complete
|
|
481
|
-
# Use future.result() with timeout for additional enforcement layer
|
|
482
598
|
for future in as_completed(futures):
|
|
483
599
|
file_path = futures[future]
|
|
484
|
-
|
|
485
|
-
# Apply timeout on result retrieval as backup enforcement
|
|
486
|
-
# This catches cases where the thread-based timeout didn't work
|
|
487
|
-
# (e.g., CPU-bound operations that don't release the GIL)
|
|
488
|
-
retrieval_timeout = (
|
|
489
|
-
self.config.timeout_per_file * 1.1 if self.config.timeout_per_file else None
|
|
490
|
-
)
|
|
491
|
-
file_result = future.result(timeout=retrieval_timeout)
|
|
492
|
-
except concurrent.futures.TimeoutError:
|
|
493
|
-
# Backup timeout triggered - future.result() timed out
|
|
494
|
-
file_result = FileResult(
|
|
495
|
-
file=str(file_path),
|
|
496
|
-
success=False,
|
|
497
|
-
error=f"Processing timed out (backup enforcement) "
|
|
498
|
-
f"after {self.config.timeout_per_file}s",
|
|
499
|
-
timed_out=True,
|
|
500
|
-
)
|
|
501
|
-
except Exception as e:
|
|
502
|
-
# Unexpected error during result retrieval
|
|
503
|
-
file_result = FileResult(
|
|
504
|
-
file=str(file_path),
|
|
505
|
-
success=False,
|
|
506
|
-
error=f"Error retrieving result: {e}",
|
|
507
|
-
traceback=traceback.format_exc(),
|
|
508
|
-
)
|
|
600
|
+
file_result = self._retrieve_future_result(future, file_path)
|
|
509
601
|
|
|
510
602
|
# Update checkpoint
|
|
511
|
-
|
|
512
|
-
self.checkpoint.results.append(file_result)
|
|
513
|
-
if file_result.success:
|
|
514
|
-
self.checkpoint.completed_files.append(file_result.file)
|
|
515
|
-
else:
|
|
516
|
-
self.checkpoint.failed_files.append(file_result.file)
|
|
603
|
+
self._update_checkpoint_with_result(file_result)
|
|
517
604
|
|
|
518
605
|
# Handle errors
|
|
519
606
|
if not file_result.success:
|
|
520
|
-
|
|
521
|
-
if pbar:
|
|
522
|
-
pbar.close()
|
|
523
|
-
raise RuntimeError(
|
|
524
|
-
f"Processing stopped due to error in {file_result.file}: "
|
|
525
|
-
f"{file_result.error}"
|
|
526
|
-
)
|
|
527
|
-
elif self.config.on_error == "warn":
|
|
528
|
-
timeout_note = " (TIMEOUT)" if file_result.timed_out else ""
|
|
529
|
-
print(
|
|
530
|
-
f"Warning: Error processing {file_result.file}{timeout_note}: "
|
|
531
|
-
f"{file_result.error}"
|
|
532
|
-
)
|
|
607
|
+
self._handle_file_error(file_result, pbar)
|
|
533
608
|
|
|
534
609
|
# Update progress
|
|
535
610
|
processed_count += 1
|