testerkit 0.4.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.
- testerkit/__init__.py +68 -0
- testerkit/_docs/_assets/operator-ui/channels/table.png +0 -0
- testerkit/_docs/_assets/operator-ui/dashboard/runs.png +0 -0
- testerkit/_docs/_assets/operator-ui/dashboard/stations.png +0 -0
- testerkit/_docs/_assets/operator-ui/events/filters.png +0 -0
- testerkit/_docs/_assets/operator-ui/events/table.png +0 -0
- testerkit/_docs/_assets/operator-ui/explore/chart.png +0 -0
- testerkit/_docs/_assets/operator-ui/explore/filters.png +0 -0
- testerkit/_docs/_assets/operator-ui/explore/plot-controls.png +0 -0
- testerkit/_docs/_assets/operator-ui/files/table.png +0 -0
- testerkit/_docs/_assets/operator-ui/launch/form.png +0 -0
- testerkit/_docs/_assets/operator-ui/metrics/filters.png +0 -0
- testerkit/_docs/_assets/operator-ui/metrics/pareto.png +0 -0
- testerkit/_docs/_assets/operator-ui/metrics/ppk.png +0 -0
- testerkit/_docs/_assets/operator-ui/metrics/yield.png +0 -0
- testerkit/_docs/_assets/operator-ui/results/detail-header.png +0 -0
- testerkit/_docs/_assets/operator-ui/results/detail-measurements.png +0 -0
- testerkit/_docs/_assets/operator-ui/results/detail-overview.png +0 -0
- testerkit/_docs/_assets/operator-ui/results/detail-steps.png +0 -0
- testerkit/_docs/_assets/operator-ui/results/stats.png +0 -0
- testerkit/_docs/_assets/operator-ui/results/table.png +0 -0
- testerkit/_docs/_assets/operator-ui/tour/designer.png +0 -0
- testerkit/_docs/_assets/operator-ui/tour/docs.png +0 -0
- testerkit/_docs/_assets/operator-ui/tour/fixtures.png +0 -0
- testerkit/_docs/_assets/operator-ui/tour/instruments.png +0 -0
- testerkit/_docs/_assets/operator-ui/tour/parts.png +0 -0
- testerkit/_docs/_assets/operator-ui/tour/profiles.png +0 -0
- testerkit/_docs/_assets/operator-ui/tour/stations.png +0 -0
- testerkit/_docs/_assets/operator-ui/tour/tests.png +0 -0
- testerkit/_docs/_assets/operator-ui/tour/uuts.png +0 -0
- testerkit/_docs/concepts/configuration/capabilities.md +447 -0
- testerkit/_docs/concepts/configuration/fixtures.md +335 -0
- testerkit/_docs/concepts/configuration/index.md +14 -0
- testerkit/_docs/concepts/configuration/parts.md +276 -0
- testerkit/_docs/concepts/configuration/stations.md +214 -0
- testerkit/_docs/concepts/data/data-stores.md +199 -0
- testerkit/_docs/concepts/data/event-log.md +185 -0
- testerkit/_docs/concepts/data/event-sourcing.md +76 -0
- testerkit/_docs/concepts/data/flight-streaming.md +58 -0
- testerkit/_docs/concepts/data/index.md +17 -0
- testerkit/_docs/concepts/data/sessions.md +78 -0
- testerkit/_docs/concepts/data/three-verbs.md +260 -0
- testerkit/_docs/concepts/execution/index.md +13 -0
- testerkit/_docs/concepts/execution/outcomes.md +199 -0
- testerkit/_docs/concepts/execution/step-hierarchy.md +170 -0
- testerkit/_docs/concepts/execution/step-manifest.md +115 -0
- testerkit/_docs/concepts/index.md +40 -0
- testerkit/_docs/concepts/overview/ai-integration.md +57 -0
- testerkit/_docs/concepts/overview/architecture.md +357 -0
- testerkit/_docs/concepts/overview/index.md +14 -0
- testerkit/_docs/concepts/overview/platform-vs-framework.md +147 -0
- testerkit/_docs/concepts/overview/pytest.md +53 -0
- testerkit/_docs/concepts/overview/tiers.md +46 -0
- testerkit/_docs/how-to/catalog/datasheet-to-test.md +169 -0
- testerkit/_docs/how-to/catalog/index.md +11 -0
- testerkit/_docs/how-to/configuration/configuring-stations.md +364 -0
- testerkit/_docs/how-to/configuration/custom-drivers.md +484 -0
- testerkit/_docs/how-to/configuration/index.md +13 -0
- testerkit/_docs/how-to/configuration/mock-mode.md +342 -0
- testerkit/_docs/how-to/data/benchmarking.md +120 -0
- testerkit/_docs/how-to/data/capture-an-artifact.md +84 -0
- testerkit/_docs/how-to/data/capture-waveform.md +110 -0
- testerkit/_docs/how-to/data/choosing-a-channel-verb.md +108 -0
- testerkit/_docs/how-to/data/compare-runs.md +120 -0
- testerkit/_docs/how-to/data/export-results.md +104 -0
- testerkit/_docs/how-to/data/find-flaky-tests.md +108 -0
- testerkit/_docs/how-to/data/grafana-dashboards.md +148 -0
- testerkit/_docs/how-to/data/index.md +23 -0
- testerkit/_docs/how-to/data/mcp-debug-failures.md +125 -0
- testerkit/_docs/how-to/data/mcp-query-runs.md +120 -0
- testerkit/_docs/how-to/data/querying-channels.md +117 -0
- testerkit/_docs/how-to/data/querying-events.md +85 -0
- testerkit/_docs/how-to/data/stream-live-channel.md +134 -0
- testerkit/_docs/how-to/execution/custom-operator-ui.md +136 -0
- testerkit/_docs/how-to/execution/index.md +21 -0
- testerkit/_docs/how-to/execution/limits.md +193 -0
- testerkit/_docs/how-to/execution/managing-sessions.md +100 -0
- testerkit/_docs/how-to/execution/multi-uut-testing.md +211 -0
- testerkit/_docs/how-to/execution/operator-prompts.md +151 -0
- testerkit/_docs/how-to/execution/profiles.md +304 -0
- testerkit/_docs/how-to/execution/spec-driven-testing.md +169 -0
- testerkit/_docs/how-to/execution/test-context.md +212 -0
- testerkit/_docs/how-to/execution/traceability.md +252 -0
- testerkit/_docs/how-to/execution/vector-expansion.md +394 -0
- testerkit/_docs/how-to/execution/writing-tests.md +363 -0
- testerkit/_docs/how-to/index.md +59 -0
- testerkit/_docs/how-to/overview/index.md +11 -0
- testerkit/_docs/how-to/overview/mcp-integration.md +168 -0
- testerkit/_docs/how-to/overview/operator-ui-tour.md +234 -0
- testerkit/_docs/integration/data/grafana.md +162 -0
- testerkit/_docs/integration/data/index.md +15 -0
- testerkit/_docs/integration/data/lakehouse-import.md +226 -0
- testerkit/_docs/integration/data/logging.md +131 -0
- testerkit/_docs/integration/data/results-api.md +51 -0
- testerkit/_docs/integration/index.md +20 -0
- testerkit/_docs/integration/runtime/harness.md +281 -0
- testerkit/_docs/integration/runtime/index.md +13 -0
- testerkit/_docs/integration/runtime/instruments.md +284 -0
- testerkit/_docs/integration/runtime/pytest-existing.md +315 -0
- testerkit/_docs/reference/catalog/cookbook.md +389 -0
- testerkit/_docs/reference/catalog/index.md +11 -0
- testerkit/_docs/reference/catalog/schema.md +375 -0
- testerkit/_docs/reference/cli.md +660 -0
- testerkit/_docs/reference/configuration.md +406 -0
- testerkit/_docs/reference/data/channels-schema.md +145 -0
- testerkit/_docs/reference/data/event-types.md +554 -0
- testerkit/_docs/reference/data/events-schema.md +120 -0
- testerkit/_docs/reference/data/files-schema.md +141 -0
- testerkit/_docs/reference/data/index.md +18 -0
- testerkit/_docs/reference/data/models.md +2229 -0
- testerkit/_docs/reference/data/outputs.md +82 -0
- testerkit/_docs/reference/data/parquet-schema.md +529 -0
- testerkit/_docs/reference/data/performance-limits.md +224 -0
- testerkit/_docs/reference/data/query-api.md +247 -0
- testerkit/_docs/reference/index.md +69 -0
- testerkit/_docs/reference/operator-ui/channels/detail.md +82 -0
- testerkit/_docs/reference/operator-ui/channels/list.md +70 -0
- testerkit/_docs/reference/operator-ui/dashboard.md +87 -0
- testerkit/_docs/reference/operator-ui/designer.md +167 -0
- testerkit/_docs/reference/operator-ui/events.md +89 -0
- testerkit/_docs/reference/operator-ui/files.md +74 -0
- testerkit/_docs/reference/operator-ui/fixtures.md +100 -0
- testerkit/_docs/reference/operator-ui/instruments.md +126 -0
- testerkit/_docs/reference/operator-ui/launch.md +79 -0
- testerkit/_docs/reference/operator-ui/live.md +102 -0
- testerkit/_docs/reference/operator-ui/measurements.md +159 -0
- testerkit/_docs/reference/operator-ui/metrics.md +217 -0
- testerkit/_docs/reference/operator-ui/parts.md +98 -0
- testerkit/_docs/reference/operator-ui/profiles.md +103 -0
- testerkit/_docs/reference/operator-ui/results/detail.md +214 -0
- testerkit/_docs/reference/operator-ui/results/list.md +106 -0
- testerkit/_docs/reference/operator-ui/stations.md +98 -0
- testerkit/_docs/reference/operator-ui/tests.md +173 -0
- testerkit/_docs/reference/operator-ui/uuts.md +67 -0
- testerkit/_docs/reference/overview/index.md +11 -0
- testerkit/_docs/reference/overview/pytest-native.md +142 -0
- testerkit/_docs/reference/overview/skills.md +177 -0
- testerkit/_docs/reference/pytest/fixtures.md +342 -0
- testerkit/_docs/reference/pytest/index.md +12 -0
- testerkit/_docs/reference/pytest/markers.md +257 -0
- testerkit/_docs/reference/runtime/api.md +246 -0
- testerkit/_docs/reference/runtime/client.md +280 -0
- testerkit/_docs/reference/runtime/connect.md +140 -0
- testerkit/_docs/reference/runtime/index.md +13 -0
- testerkit/_docs/tutorial/01-first-test.md +113 -0
- testerkit/_docs/tutorial/02-mock-instruments.md +88 -0
- testerkit/_docs/tutorial/03-fixtures.md +169 -0
- testerkit/_docs/tutorial/04-limits.md +139 -0
- testerkit/_docs/tutorial/05-configuration.md +194 -0
- testerkit/_docs/tutorial/06-specifications.md +273 -0
- testerkit/_docs/tutorial/07-real-instruments.md +245 -0
- testerkit/_docs/tutorial/08-capabilities.md +223 -0
- testerkit/_docs/tutorial/09-production.md +374 -0
- testerkit/_docs/tutorial/10-live-monitoring.md +156 -0
- testerkit/_docs/tutorial/11-waveforms-and-evidence.md +169 -0
- testerkit/_docs/tutorial/12-continuous-monitoring.md +145 -0
- testerkit/_docs/tutorial/13-parallel-testing.md +233 -0
- testerkit/_docs/tutorial/index.md +61 -0
- testerkit/_docs/tutorial/quickstart.md +282 -0
- testerkit/analysis/__init__.py +9 -0
- testerkit/analysis/_common.py +24 -0
- testerkit/analysis/measurement_facets.py +524 -0
- testerkit/analysis/measurements_query.py +1458 -0
- testerkit/analysis/metrics.py +389 -0
- testerkit/analysis/runs_query.py +434 -0
- testerkit/analysis/steps_query.py +413 -0
- testerkit/api/__init__.py +6 -0
- testerkit/api/_mime.py +71 -0
- testerkit/api/app.py +1171 -0
- testerkit/api/dialogs/__init__.py +36 -0
- testerkit/api/dialogs/manager.py +617 -0
- testerkit/api/dialogs/models.py +79 -0
- testerkit/api/models.py +80 -0
- testerkit/api/responses.py +205 -0
- testerkit/api/runner.py +222 -0
- testerkit/api/schemas.py +311 -0
- testerkit/benchmark/__init__.py +34 -0
- testerkit/benchmark/concurrency.py +248 -0
- testerkit/benchmark/core.py +232 -0
- testerkit/benchmark/runner.py +628 -0
- testerkit/benchmark/scenario.py +313 -0
- testerkit/benchmark/system.py +191 -0
- testerkit/benchmark/workloads.py +507 -0
- testerkit/catalog/__init__.py +6 -0
- testerkit/catalog/generic/generic_dmm.yaml +61 -0
- testerkit/catalog/generic/generic_eload.yaml +31 -0
- testerkit/catalog/generic/generic_fgen.yaml +56 -0
- testerkit/catalog/generic/generic_oscilloscope.yaml +45 -0
- testerkit/catalog/generic/generic_psu.yaml +77 -0
- testerkit/catalog/generic/generic_smu.yaml +73 -0
- testerkit/channels.py +538 -0
- testerkit/cli/__init__.py +32 -0
- testerkit/cli/_common.py +113 -0
- testerkit/cli/_time.py +179 -0
- testerkit/cli/benchmark_cmd.py +56 -0
- testerkit/cli/catalog_cmd.py +39 -0
- testerkit/cli/daemon.py +157 -0
- testerkit/cli/data_cmd.py +1040 -0
- testerkit/cli/discover_cmd.py +94 -0
- testerkit/cli/docs_cmd.py +100 -0
- testerkit/cli/instrument.py +172 -0
- testerkit/cli/mcp_cmd.py +37 -0
- testerkit/cli/metrics.py +366 -0
- testerkit/cli/project.py +312 -0
- testerkit/cli/root.py +14 -0
- testerkit/cli/runs.py +412 -0
- testerkit/cli/schema_cmd.py +87 -0
- testerkit/cli/serve_cmd.py +50 -0
- testerkit/cli/setup_cmd.py +604 -0
- testerkit/cli/station.py +294 -0
- testerkit/cli/validate.py +112 -0
- testerkit/client.py +463 -0
- testerkit/connect.py +635 -0
- testerkit/data/__init__.py +8 -0
- testerkit/data/_accumulator_pool.py +455 -0
- testerkit/data/_atomic.py +59 -0
- testerkit/data/_collection_indices.py +67 -0
- testerkit/data/_daemon_lifecycle.py +535 -0
- testerkit/data/_duckdb_daemon.py +695 -0
- testerkit/data/_duckdb_flight_server.py +813 -0
- testerkit/data/_event_filters.py +15 -0
- testerkit/data/_event_reader.py +101 -0
- testerkit/data/_flight_errors.py +199 -0
- testerkit/data/_flight_query.py +202 -0
- testerkit/data/_flight_retry.py +148 -0
- testerkit/data/_flight_subscribe.py +67 -0
- testerkit/data/_index_epoch.py +342 -0
- testerkit/data/_ipc_writer.py +185 -0
- testerkit/data/_json_safe.py +63 -0
- testerkit/data/_process.py +18 -0
- testerkit/data/_push_relay.py +124 -0
- testerkit/data/_runs_duckdb_daemon.py +2704 -0
- testerkit/data/_session_reaper.py +110 -0
- testerkit/data/_sql_helpers.py +30 -0
- testerkit/data/_store.py +24 -0
- testerkit/data/backends/__init__.py +7 -0
- testerkit/data/backends/_event_accumulator.py +957 -0
- testerkit/data/backends/_row_helpers.py +1172 -0
- testerkit/data/backends/parquet.py +1143 -0
- testerkit/data/backends/protocol.py +35 -0
- testerkit/data/channels/__init__.py +8 -0
- testerkit/data/channels/_flight_daemon.py +75 -0
- testerkit/data/channels/client.py +242 -0
- testerkit/data/channels/flight_manager.py +88 -0
- testerkit/data/channels/index.py +664 -0
- testerkit/data/channels/models.py +418 -0
- testerkit/data/channels/server.py +162 -0
- testerkit/data/channels/store.py +1481 -0
- testerkit/data/data_dir.py +61 -0
- testerkit/data/duckdb_manager.py +79 -0
- testerkit/data/event_log.py +384 -0
- testerkit/data/event_store.py +768 -0
- testerkit/data/events.py +1025 -0
- testerkit/data/exporters/__init__.py +6 -0
- testerkit/data/exporters/_helpers.py +40 -0
- testerkit/data/exporters/csv_exporter.py +168 -0
- testerkit/data/exporters/hdf5.py +234 -0
- testerkit/data/exporters/json_exporter.py +229 -0
- testerkit/data/exporters/mdf4.py +201 -0
- testerkit/data/exporters/stdf.py +255 -0
- testerkit/data/exporters/tdms.py +292 -0
- testerkit/data/files/__init__.py +71 -0
- testerkit/data/files/_backend.py +207 -0
- testerkit/data/files/_catalog_daemon.py +84 -0
- testerkit/data/files/catalog.py +218 -0
- testerkit/data/files/catalog_manager.py +325 -0
- testerkit/data/files/models.py +60 -0
- testerkit/data/files/serializers.py +414 -0
- testerkit/data/files/store.py +463 -0
- testerkit/data/files/streaming.py +783 -0
- testerkit/data/models.py +604 -0
- testerkit/data/ref.py +152 -0
- testerkit/data/retention.py +297 -0
- testerkit/data/run_store.py +367 -0
- testerkit/data/runs_duckdb_manager.py +103 -0
- testerkit/data/schema_dispatch.py +191 -0
- testerkit/data/schema_migrate.py +76 -0
- testerkit/data/schema_versions.py +85 -0
- testerkit/data/schemas.py +288 -0
- testerkit/data/subscribers/__init__.py +48 -0
- testerkit/data/subscribers/_base.py +20 -0
- testerkit/data/subscribers/_output_file.py +25 -0
- testerkit/data/subscribers/replay.py +55 -0
- testerkit/environment.py +84 -0
- testerkit/execution/__init__.py +11 -0
- testerkit/execution/_git.py +190 -0
- testerkit/execution/_state.py +740 -0
- testerkit/execution/accessors.py +54 -0
- testerkit/execution/audit.py +51 -0
- testerkit/execution/cascade.py +85 -0
- testerkit/execution/connections.py +491 -0
- testerkit/execution/harness.py +1931 -0
- testerkit/execution/instrument_events.py +42 -0
- testerkit/execution/limits.py +154 -0
- testerkit/execution/metadata.py +102 -0
- testerkit/execution/mocks.py +63 -0
- testerkit/execution/profiles.py +616 -0
- testerkit/execution/run_scope.py +1331 -0
- testerkit/execution/session_scope.py +196 -0
- testerkit/execution/sidecar.py +280 -0
- testerkit/execution/site_runner.py +705 -0
- testerkit/execution/sites.py +183 -0
- testerkit/execution/sync.py +294 -0
- testerkit/execution/uut_provider.py +231 -0
- testerkit/execution/vectors.py +205 -0
- testerkit/execution/verify.py +396 -0
- testerkit/expand.py +75 -0
- testerkit/files.py +235 -0
- testerkit/fixtures/__init__.py +6 -0
- testerkit/fixtures/manager.py +357 -0
- testerkit/grafana/__init__.py +1 -0
- testerkit/grafana/bootstrap.py +61 -0
- testerkit/grafana/cli.py +314 -0
- testerkit/grafana/dashboards/asset_utilization.json +92 -0
- testerkit/grafana/dashboards/channel_explorer.json +77 -0
- testerkit/grafana/dashboards/event_log.json +92 -0
- testerkit/grafana/dashboards/failure_pareto.json +104 -0
- testerkit/grafana/dashboards/measurement_distribution.json +97 -0
- testerkit/grafana/dashboards/measurement_trend.json +161 -0
- testerkit/grafana/dashboards/station_comparison.json +95 -0
- testerkit/grafana/dashboards/test_duration.json +104 -0
- testerkit/grafana/dashboards/unit_traceability.json +73 -0
- testerkit/grafana/dashboards/yield_overview.json +189 -0
- testerkit/grafana/provisioning/dashboards.yaml.j2 +12 -0
- testerkit/grafana/provisioning/datasources.yaml.j2 +17 -0
- testerkit/grafana/server.py +282 -0
- testerkit/init.py +724 -0
- testerkit/instruments/__init__.py +10 -0
- testerkit/instruments/base.py +82 -0
- testerkit/instruments/discovery/__init__.py +62 -0
- testerkit/instruments/discovery/_base.py +174 -0
- testerkit/instruments/discovery/lxi.py +152 -0
- testerkit/instruments/discovery/ni.py +95 -0
- testerkit/instruments/discovery/serial.py +73 -0
- testerkit/instruments/discovery/visa.py +98 -0
- testerkit/instruments/lifecycle.py +213 -0
- testerkit/instruments/loader.py +79 -0
- testerkit/instruments/locks.py +178 -0
- testerkit/instruments/mocks.py +230 -0
- testerkit/instruments/observer.py +270 -0
- testerkit/instruments/observers/__init__.py +36 -0
- testerkit/instruments/observers/_base.py +68 -0
- testerkit/instruments/observers/daqmx.py +70 -0
- testerkit/instruments/observers/descriptor.py +69 -0
- testerkit/instruments/observers/generic.py +92 -0
- testerkit/instruments/observers/lantz.py +31 -0
- testerkit/instruments/observers/modbus.py +96 -0
- testerkit/instruments/observers/motion.py +68 -0
- testerkit/instruments/observers/ni_modular.py +73 -0
- testerkit/instruments/observers/ophyd.py +80 -0
- testerkit/instruments/observers/pymeasure.py +120 -0
- testerkit/instruments/observers/qcodes.py +66 -0
- testerkit/instruments/observers/scpi.py +88 -0
- testerkit/instruments/observers/tektronix.py +57 -0
- testerkit/instruments/observers/visa.py +103 -0
- testerkit/instruments/pool.py +459 -0
- testerkit/instruments/proxy.py +59 -0
- testerkit/instruments/route_manager.py +329 -0
- testerkit/instruments/routed_proxy.py +88 -0
- testerkit/instruments/server.py +508 -0
- testerkit/instruments/switch.py +43 -0
- testerkit/instruments/visa.py +294 -0
- testerkit/matching/__init__.py +6 -0
- testerkit/matching/service.py +969 -0
- testerkit/mcp/__init__.py +6 -0
- testerkit/mcp/server.py +681 -0
- testerkit/mcp/tools.py +1868 -0
- testerkit/models/__init__.py +18 -0
- testerkit/models/capability.py +598 -0
- testerkit/models/catalog.py +76 -0
- testerkit/models/data_options.py +153 -0
- testerkit/models/enums.py +334 -0
- testerkit/models/instrument.py +152 -0
- testerkit/models/instrument_asset.py +25 -0
- testerkit/models/part.py +271 -0
- testerkit/models/part_manifest.py +96 -0
- testerkit/models/project.py +114 -0
- testerkit/models/station.py +140 -0
- testerkit/models/test_config.py +748 -0
- testerkit/ontology/__init__.py +39 -0
- testerkit/ontology/schema.py +188 -0
- testerkit/ontology/testerkit.yaml +1420 -0
- testerkit/parts/__init__.py +8 -0
- testerkit/parts/context.py +181 -0
- testerkit/parts/folder.py +251 -0
- testerkit/parts/loader.py +27 -0
- testerkit/prompts/__init__.py +17 -0
- testerkit/prompts/core.py +133 -0
- testerkit/pytest_plugin/__init__.py +1287 -0
- testerkit/pytest_plugin/autouse.py +369 -0
- testerkit/pytest_plugin/helpers.py +354 -0
- testerkit/pytest_plugin/hooks.py +1982 -0
- testerkit/pytest_plugin/markers.py +203 -0
- testerkit/pytest_plugin/retry.py +37 -0
- testerkit/pytest_plugin/sweeps.py +117 -0
- testerkit/queries.py +78 -0
- testerkit/reports/__init__.py +6 -0
- testerkit/reports/core.py +492 -0
- testerkit/reports/datasheet.py +831 -0
- testerkit/reports/templates/datasheet.html +383 -0
- testerkit/reports/templates/default.html +153 -0
- testerkit/sbom.py +142 -0
- testerkit/schema_export.py +101 -0
- testerkit/signals.py +63 -0
- testerkit/skills/README.md +58 -0
- testerkit/skills/templates/project-instructions.md +125 -0
- testerkit/skills/testerkit-analysis/SKILL.md +87 -0
- testerkit/skills/testerkit-capture/SKILL.md +114 -0
- testerkit/skills/testerkit-data/SKILL.md +138 -0
- testerkit/skills/testerkit-datasheets/SKILL.md +100 -0
- testerkit/skills/testerkit-datasheets/agents/scaffold-writer.md +115 -0
- testerkit/skills/testerkit-datasheets/agents/section-extractor.md +98 -0
- testerkit/skills/testerkit-datasheets/agents/section-reviewer.md +153 -0
- testerkit/skills/testerkit-datasheets/agents/section-splitter.md +89 -0
- testerkit/skills/testerkit-datasheets/agents/section-writer.md +226 -0
- testerkit/skills/testerkit-datasheets/references/catalog-pipeline.md +271 -0
- testerkit/skills/testerkit-datasheets/references/process-queue.md +42 -0
- testerkit/skills/testerkit-datasheets/references/scaffold.md +156 -0
- testerkit/skills/testerkit-datasheets/references/test-pipeline.md +312 -0
- testerkit/skills/testerkit-debug/SKILL.md +127 -0
- testerkit/skills/testerkit-interactive/SKILL.md +188 -0
- testerkit/skills/testerkit-interactive/references/live-ui-patterns.md +102 -0
- testerkit/skills/testerkit-mocks/SKILL.md +128 -0
- testerkit/skills/testerkit-parts/SKILL.md +126 -0
- testerkit/skills/testerkit-profiles/SKILL.md +139 -0
- testerkit/skills/testerkit-sites/SKILL.md +140 -0
- testerkit/skills/testerkit-stations/SKILL.md +146 -0
- testerkit/skills/testerkit-tests/SKILL.md +136 -0
- testerkit/store.py +1639 -0
- testerkit/ui/__init__.py +71 -0
- testerkit/ui/_asgi.py +162 -0
- testerkit/ui/app.py +32 -0
- testerkit/ui/components/__init__.py +13 -0
- testerkit/ui/components/artifact_viewer.py +250 -0
- testerkit/ui/components/channel_values.py +159 -0
- testerkit/ui/components/event_timeline.py +222 -0
- testerkit/ui/components/execution_gantt.py +210 -0
- testerkit/ui/components/file_streams.py +147 -0
- testerkit/ui/components/instrument_activity.py +146 -0
- testerkit/ui/components/session_table.py +118 -0
- testerkit/ui/pages/__init__.py +25 -0
- testerkit/ui/pages/channels/__init__.py +4 -0
- testerkit/ui/pages/channels/detail.py +932 -0
- testerkit/ui/pages/channels/list.py +515 -0
- testerkit/ui/pages/dashboard.py +236 -0
- testerkit/ui/pages/designer/__init__.py +5 -0
- testerkit/ui/pages/designer/graph.py +635 -0
- testerkit/ui/pages/designer/matching.py +663 -0
- testerkit/ui/pages/designer/page.py +593 -0
- testerkit/ui/pages/designer/properties.py +591 -0
- testerkit/ui/pages/designer/state.py +468 -0
- testerkit/ui/pages/docs/__init__.py +6 -0
- testerkit/ui/pages/docs/index.py +95 -0
- testerkit/ui/pages/docs/page.py +698 -0
- testerkit/ui/pages/events/__init__.py +3 -0
- testerkit/ui/pages/events/list.py +263 -0
- testerkit/ui/pages/explore.py +1108 -0
- testerkit/ui/pages/files/__init__.py +4 -0
- testerkit/ui/pages/files/detail.py +426 -0
- testerkit/ui/pages/files/list.py +447 -0
- testerkit/ui/pages/fixtures/__init__.py +8 -0
- testerkit/ui/pages/fixtures/detail.py +280 -0
- testerkit/ui/pages/fixtures/edit.py +370 -0
- testerkit/ui/pages/fixtures/list.py +180 -0
- testerkit/ui/pages/fixtures/new.py +195 -0
- testerkit/ui/pages/instruments/__init__.py +4 -0
- testerkit/ui/pages/instruments/detail.py +320 -0
- testerkit/ui/pages/instruments/edit.py +482 -0
- testerkit/ui/pages/instruments/list.py +249 -0
- testerkit/ui/pages/instruments/new.py +200 -0
- testerkit/ui/pages/launch.py +261 -0
- testerkit/ui/pages/live.py +124 -0
- testerkit/ui/pages/metrics_page.py +1229 -0
- testerkit/ui/pages/parts/__init__.py +11 -0
- testerkit/ui/pages/parts/detail.py +202 -0
- testerkit/ui/pages/parts/edit.py +310 -0
- testerkit/ui/pages/parts/list.py +160 -0
- testerkit/ui/pages/parts/new.py +170 -0
- testerkit/ui/pages/parts/requirements.py +153 -0
- testerkit/ui/pages/parts/stations.py +199 -0
- testerkit/ui/pages/profiles/__init__.py +4 -0
- testerkit/ui/pages/profiles/detail.py +113 -0
- testerkit/ui/pages/profiles/list.py +86 -0
- testerkit/ui/pages/results/__init__.py +4 -0
- testerkit/ui/pages/results/detail.py +631 -0
- testerkit/ui/pages/results/list.py +230 -0
- testerkit/ui/pages/stations/__init__.py +4 -0
- testerkit/ui/pages/stations/detail.py +256 -0
- testerkit/ui/pages/stations/edit.py +273 -0
- testerkit/ui/pages/stations/list.py +180 -0
- testerkit/ui/pages/stations/new.py +311 -0
- testerkit/ui/pages/tests/__init__.py +4 -0
- testerkit/ui/pages/tests/detail.py +152 -0
- testerkit/ui/pages/tests/list.py +194 -0
- testerkit/ui/pages/uuts/__init__.py +4 -0
- testerkit/ui/pages/uuts/list.py +97 -0
- testerkit/ui/shared/__init__.py +8 -0
- testerkit/ui/shared/components.py +1826 -0
- testerkit/ui/shared/dialogs.py +105 -0
- testerkit/ui/shared/event_binding.py +194 -0
- testerkit/ui/shared/layout.py +314 -0
- testerkit/ui/shared/services.py +1719 -0
- testerkit/ui/shared/timestamps.py +21 -0
- testerkit/ui/static/branding/favicon-16.png +0 -0
- testerkit/ui/static/branding/favicon-32.png +0 -0
- testerkit/ui/static/branding/favicon-48.png +0 -0
- testerkit/ui/static/branding/testerkit-icon-256.png +0 -0
- testerkit/ui/static/branding/testerkit-mark.svg +1 -0
- testerkit/ui/static/branding/testerkit-wordmark.svg +1 -0
- testerkit/ui/static/global.css +465 -0
- testerkit/utils/__init__.py +17 -0
- testerkit/utils/enum_meta.py +800 -0
- testerkit/utils/paths.py +75 -0
- testerkit/utils/ranges.py +257 -0
- testerkit/validation.py +82 -0
- testerkit/verbs.py +142 -0
- testerkit-0.4.0.dist-info/METADATA +250 -0
- testerkit-0.4.0.dist-info/RECORD +521 -0
- testerkit-0.4.0.dist-info/WHEEL +4 -0
- testerkit-0.4.0.dist-info/entry_points.txt +5 -0
- testerkit-0.4.0.dist-info/licenses/LICENSE +191 -0
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
"""VISA instrument protocol family.
|
|
2
|
+
|
|
3
|
+
VisaInstrument is the base class for all SCPI/IEEE 488.2 instruments
|
|
4
|
+
that communicate via PyVISA. When simulate=True, it uses pyvisa-sim
|
|
5
|
+
for realistic simulation based on the instrument library YAML.
|
|
6
|
+
|
|
7
|
+
Example usage:
|
|
8
|
+
class DMM(VisaInstrument, VoltageInput, CurrentInput):
|
|
9
|
+
def measure_voltage(self, signal_type=SignalType.DC) -> float:
|
|
10
|
+
return float(self.query("MEAS:VOLT:DC?"))
|
|
11
|
+
|
|
12
|
+
# Real hardware
|
|
13
|
+
dmm = DMM("TCPIP::192.168.1.100::INSTR")
|
|
14
|
+
dmm.connect()
|
|
15
|
+
v = dmm.measure_voltage()
|
|
16
|
+
|
|
17
|
+
# Simulation
|
|
18
|
+
dmm = DMM("TCPIP::192.168.1.100::INSTR", simulate=True)
|
|
19
|
+
dmm.connect()
|
|
20
|
+
v = dmm.measure_voltage() # Returns value from pyvisa-sim
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
import random
|
|
24
|
+
import tempfile
|
|
25
|
+
from pathlib import Path
|
|
26
|
+
from typing import Any
|
|
27
|
+
|
|
28
|
+
import pyvisa
|
|
29
|
+
from pyvisa.resources import MessageBasedResource
|
|
30
|
+
|
|
31
|
+
from testerkit.instruments.base import Instrument
|
|
32
|
+
from testerkit.instruments.discovery import parse_idn
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class VisaInstrument(Instrument):
|
|
36
|
+
"""Base class for VISA/SCPI instruments with automatic simulation.
|
|
37
|
+
|
|
38
|
+
This is the protocol family base for all SCPI instruments. It extends
|
|
39
|
+
Instrument and provides:
|
|
40
|
+
|
|
41
|
+
- Real hardware communication via PyVISA
|
|
42
|
+
- Simulation via pyvisa-sim (auto-generated from instrument library)
|
|
43
|
+
- Standard SCPI methods: write(), query(), read()
|
|
44
|
+
|
|
45
|
+
Concrete drivers (DMM, PSU, Scope, etc.) extend this class and
|
|
46
|
+
implement capability interfaces.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
# Class-level simulation defaults (override in subclasses or via sim_config)
|
|
50
|
+
_default_idn: str = "TesterKit,SimulatedVisa,SN001,1.0"
|
|
51
|
+
_sim_responses: dict[str, str | float] = {}
|
|
52
|
+
|
|
53
|
+
def __init__(
|
|
54
|
+
self,
|
|
55
|
+
resource: str,
|
|
56
|
+
simulate: bool = False,
|
|
57
|
+
sim_config: dict[str, Any] | None = None,
|
|
58
|
+
timeout_ms: int = 5000,
|
|
59
|
+
):
|
|
60
|
+
"""Initialize VISA instrument.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
resource: VISA resource string (e.g., "TCPIP::192.168.1.100::INSTR")
|
|
64
|
+
simulate: If True, use pyvisa-sim instead of real hardware
|
|
65
|
+
sim_config: Simulation configuration with keys like:
|
|
66
|
+
- idn: Custom *IDN? response
|
|
67
|
+
- responses: Dict of SCPI command -> response value
|
|
68
|
+
- noise: Dict of measurement name -> noise percentage
|
|
69
|
+
timeout_ms: Communication timeout in milliseconds
|
|
70
|
+
"""
|
|
71
|
+
super().__init__(resource=resource, simulate=simulate, sim_config=sim_config)
|
|
72
|
+
self.timeout_ms = timeout_ms
|
|
73
|
+
|
|
74
|
+
self._rm: pyvisa.ResourceManager | None = None
|
|
75
|
+
self._inst: MessageBasedResource | None = None
|
|
76
|
+
self._sim_yaml_path: Path | None = None
|
|
77
|
+
|
|
78
|
+
def connect(self) -> None:
|
|
79
|
+
"""Connect to instrument (real or simulated).
|
|
80
|
+
|
|
81
|
+
For simulated mode, generates a pyvisa-sim configuration file
|
|
82
|
+
and connects to the simulated instrument.
|
|
83
|
+
"""
|
|
84
|
+
if self._connected:
|
|
85
|
+
return
|
|
86
|
+
|
|
87
|
+
if self.simulate:
|
|
88
|
+
# Generate pyvisa-sim config and connect
|
|
89
|
+
self._sim_yaml_path = self._generate_sim_config()
|
|
90
|
+
self._rm = pyvisa.ResourceManager(f"{self._sim_yaml_path}@sim")
|
|
91
|
+
else:
|
|
92
|
+
# Connect to real hardware
|
|
93
|
+
self._rm = pyvisa.ResourceManager()
|
|
94
|
+
|
|
95
|
+
assert self._rm is not None
|
|
96
|
+
# open_resource returns Resource, but VISA/SCPI instruments are MessageBasedResource
|
|
97
|
+
resource = self._rm.open_resource(self.resource)
|
|
98
|
+
assert isinstance(resource, MessageBasedResource)
|
|
99
|
+
self._inst = resource
|
|
100
|
+
self._inst.timeout = self.timeout_ms
|
|
101
|
+
self._inst.write_termination = "\n"
|
|
102
|
+
self._inst.read_termination = "\n"
|
|
103
|
+
self._connected = True
|
|
104
|
+
|
|
105
|
+
# All VISA instruments support *IDN? (IEEE 488.2 mandatory)
|
|
106
|
+
# Parse and set identity fields automatically
|
|
107
|
+
try:
|
|
108
|
+
info = parse_idn(self.query("*IDN?"))
|
|
109
|
+
self.manufacturer = info.manufacturer
|
|
110
|
+
self.model = info.model
|
|
111
|
+
self.serial = info.serial
|
|
112
|
+
self.firmware = info.firmware
|
|
113
|
+
except (OSError, ValueError, pyvisa.errors.VisaIOError):
|
|
114
|
+
pass # Identity fields remain None if query fails
|
|
115
|
+
|
|
116
|
+
def disconnect(self) -> None:
|
|
117
|
+
"""Disconnect from instrument and clean up resources."""
|
|
118
|
+
if self._inst:
|
|
119
|
+
self._inst.close()
|
|
120
|
+
self._inst = None
|
|
121
|
+
if self._rm:
|
|
122
|
+
self._rm.close()
|
|
123
|
+
self._rm = None
|
|
124
|
+
|
|
125
|
+
# Clean up temp sim config file
|
|
126
|
+
if self._sim_yaml_path and self._sim_yaml_path.exists():
|
|
127
|
+
try:
|
|
128
|
+
self._sim_yaml_path.unlink()
|
|
129
|
+
except OSError:
|
|
130
|
+
pass
|
|
131
|
+
self._sim_yaml_path = None
|
|
132
|
+
|
|
133
|
+
self._connected = False
|
|
134
|
+
|
|
135
|
+
def write(self, command: str) -> None:
|
|
136
|
+
"""Send command to instrument.
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
command: SCPI command string
|
|
140
|
+
|
|
141
|
+
Raises:
|
|
142
|
+
RuntimeError: If not connected
|
|
143
|
+
"""
|
|
144
|
+
if self._inst is None:
|
|
145
|
+
raise RuntimeError("Not connected to instrument")
|
|
146
|
+
self._inst.write(command)
|
|
147
|
+
|
|
148
|
+
def query(self, command: str) -> str:
|
|
149
|
+
"""Send command and return response.
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
command: SCPI query string (typically ends with ?)
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
Response string from instrument
|
|
156
|
+
|
|
157
|
+
Raises:
|
|
158
|
+
RuntimeError: If not connected
|
|
159
|
+
"""
|
|
160
|
+
if self._inst is None:
|
|
161
|
+
raise RuntimeError("Not connected to instrument")
|
|
162
|
+
return self._inst.query(command).strip()
|
|
163
|
+
|
|
164
|
+
def read(self) -> str:
|
|
165
|
+
"""Read response from instrument.
|
|
166
|
+
|
|
167
|
+
Returns:
|
|
168
|
+
Response string
|
|
169
|
+
|
|
170
|
+
Raises:
|
|
171
|
+
RuntimeError: If not connected
|
|
172
|
+
"""
|
|
173
|
+
if self._inst is None:
|
|
174
|
+
raise RuntimeError("Not connected to instrument")
|
|
175
|
+
return self._inst.read().strip()
|
|
176
|
+
|
|
177
|
+
def _generate_sim_config(self) -> Path:
|
|
178
|
+
"""Generate pyvisa-sim YAML configuration.
|
|
179
|
+
|
|
180
|
+
Creates a temporary YAML file with simulation configuration using
|
|
181
|
+
pyvisa-sim's stateful properties system. This allows:
|
|
182
|
+
- Commands like "VOLT 5.0" to set state
|
|
183
|
+
- Queries like "VOLT?" or "MEAS:VOLT?" to read that state
|
|
184
|
+
|
|
185
|
+
Configuration sources (in order of precedence):
|
|
186
|
+
1. Instance sim_config overrides
|
|
187
|
+
2. Class-level _sim_responses (for backwards compatibility)
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
Path to generated YAML file
|
|
191
|
+
"""
|
|
192
|
+
# Merge class defaults with instance config
|
|
193
|
+
idn = self.sim_config.get("idn", self._default_idn)
|
|
194
|
+
responses = {**self._sim_responses, **self.sim_config.get("responses", {})}
|
|
195
|
+
|
|
196
|
+
# Get default values from sim_config
|
|
197
|
+
default_voltage = self.sim_config.get("voltage", 0.0)
|
|
198
|
+
default_current = self.sim_config.get("current", 0.0)
|
|
199
|
+
|
|
200
|
+
# Build pyvisa-sim YAML content with stateful properties
|
|
201
|
+
#
|
|
202
|
+
# specs.type must be 'float' so values are stored as float (not string),
|
|
203
|
+
# otherwise "{:f}".format() fails with "Unknown format code 'f' for str"
|
|
204
|
+
#
|
|
205
|
+
# Getter/setter must match actual SCPI queries used by the driver:
|
|
206
|
+
# - PSU.measure_output_voltage() queries "MEAS:VOLT?"
|
|
207
|
+
# - PSU.set_voltage() writes "VOLT {value}"
|
|
208
|
+
yaml_lines = [
|
|
209
|
+
"spec: '1.0'",
|
|
210
|
+
"devices:",
|
|
211
|
+
" device 1:",
|
|
212
|
+
" eom:",
|
|
213
|
+
" TCPIP INSTR:",
|
|
214
|
+
' q: "\\n"',
|
|
215
|
+
' r: "\\n"',
|
|
216
|
+
" GPIB INSTR:",
|
|
217
|
+
' q: "\\n"',
|
|
218
|
+
' r: "\\n"',
|
|
219
|
+
" USB INSTR:",
|
|
220
|
+
' q: "\\n"',
|
|
221
|
+
' r: "\\n"',
|
|
222
|
+
"",
|
|
223
|
+
" properties:",
|
|
224
|
+
" voltage:",
|
|
225
|
+
f" default: {default_voltage}",
|
|
226
|
+
" specs:",
|
|
227
|
+
" type: float",
|
|
228
|
+
" getter:",
|
|
229
|
+
' q: "MEAS:VOLT?"',
|
|
230
|
+
' r: "{:f}"',
|
|
231
|
+
" setter:",
|
|
232
|
+
' q: "VOLT {:f}"',
|
|
233
|
+
" current:",
|
|
234
|
+
f" default: {default_current}",
|
|
235
|
+
" specs:",
|
|
236
|
+
" type: float",
|
|
237
|
+
" getter:",
|
|
238
|
+
' q: "MEAS:CURR?"',
|
|
239
|
+
' r: "{:f}"',
|
|
240
|
+
" setter:",
|
|
241
|
+
' q: "CURR {:f}"',
|
|
242
|
+
"",
|
|
243
|
+
" dialogues:",
|
|
244
|
+
' - q: "*IDN?"',
|
|
245
|
+
f' r: "{idn}"',
|
|
246
|
+
' - q: "OUTP ON"',
|
|
247
|
+
' - q: "OUTP OFF"',
|
|
248
|
+
' - q: "OUTP:PROT:CLE"',
|
|
249
|
+
]
|
|
250
|
+
|
|
251
|
+
# Add any additional static response dialogues
|
|
252
|
+
for cmd, response in responses.items():
|
|
253
|
+
# Skip voltage/current - handled by properties above
|
|
254
|
+
if cmd in ("VOLT?", "CURR?", "MEAS:VOLT?", "MEAS:CURR?"):
|
|
255
|
+
continue
|
|
256
|
+
if isinstance(response, (int, float)):
|
|
257
|
+
response = str(response)
|
|
258
|
+
yaml_lines.append(f' - q: "{cmd}"')
|
|
259
|
+
yaml_lines.append(f' r: "{response}"')
|
|
260
|
+
|
|
261
|
+
# Add resources section to map resource string to device
|
|
262
|
+
yaml_lines.append("")
|
|
263
|
+
yaml_lines.append("resources:")
|
|
264
|
+
yaml_lines.append(f" {self.resource}:")
|
|
265
|
+
yaml_lines.append(" device: device 1")
|
|
266
|
+
|
|
267
|
+
# Write to temp file
|
|
268
|
+
yaml_content = "\n".join(yaml_lines)
|
|
269
|
+
with tempfile.NamedTemporaryFile(
|
|
270
|
+
mode="w", suffix=".yaml", delete=False, prefix="testerkit_sim_"
|
|
271
|
+
) as f:
|
|
272
|
+
f.write(yaml_content)
|
|
273
|
+
return Path(f.name)
|
|
274
|
+
|
|
275
|
+
def _get_sim_value(self, name: str, default: float = 0.0) -> float:
|
|
276
|
+
"""Get a simulated measurement value with optional noise.
|
|
277
|
+
|
|
278
|
+
Helper method for concrete drivers implementing measurement methods.
|
|
279
|
+
|
|
280
|
+
Args:
|
|
281
|
+
name: Measurement name (e.g., "voltage", "current")
|
|
282
|
+
default: Default value if not configured
|
|
283
|
+
|
|
284
|
+
Returns:
|
|
285
|
+
Simulated value as float
|
|
286
|
+
"""
|
|
287
|
+
base = float(self.sim_config.get(name, default))
|
|
288
|
+
noise_pct = float(self.sim_config.get("noise", {}).get(name, 0))
|
|
289
|
+
|
|
290
|
+
if noise_pct > 0:
|
|
291
|
+
noise = base * noise_pct / 100
|
|
292
|
+
base = base + random.uniform(-noise, noise)
|
|
293
|
+
|
|
294
|
+
return round(base, 9)
|