pytestlab 0.2.3__tar.gz → 0.2.4__tar.gz
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.
- {pytestlab-0.2.3 → pytestlab-0.2.4}/.github/workflows/test.yml +1 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/.pre-commit-config.yaml +6 -9
- pytestlab-0.2.4/CHANGELOG.md +78 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/CONTRIBUTING.md +3 -3
- {pytestlab-0.2.3 → pytestlab-0.2.4}/PKG-INFO +32 -15
- {pytestlab-0.2.3 → pytestlab-0.2.4}/README.md +29 -12
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/api/measurements.md +18 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/changelog.md +14 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/contributing.md +1 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/installation.md +2 -2
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/profiles/creating.md +1 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/stylesheets/extra.css +55 -52
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/stylesheets/notebook-enhancements.css +48 -48
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/tutorials/10_minute_tour.ipynb +7 -68
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/tutorials/advanced_measurements.ipynb +2 -2
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/tutorials/compliance.ipynb +4 -3
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/tutorials/custom_validations.ipynb +2 -2
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/tutorials/example.ipynb +37 -57
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/tutorials/profile_creation.ipynb +5 -9
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/tutorials/replay_mode.ipynb +7 -2
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/tutorials/smartbench.ipynb +10 -5
- pytestlab-0.2.4/docs/en/user_guide/cli.md +330 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/user_guide/connecting.md +1 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/user_guide/errors.md +1 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/user_guide/getting_started.md +1 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/user_guide/measurement_session.md +16 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/user_guide/replay_mode.md +5 -5
- pytestlab-0.2.4/docs/mkdocs.yml +184 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/themes/labiium_photon/404.html +6 -5
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/themes/labiium_photon/css/theme.css +38 -34
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/themes/labiium_photon/home.html +63 -82
- pytestlab-0.2.4/docs/themes/labiium_photon/img/favicon.ico +9 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/themes/labiium_photon/js/theme.js +21 -17
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/themes/labiium_photon/main.html +39 -27
- pytestlab-0.2.4/examples/QUICKSTART.md +60 -0
- pytestlab-0.2.4/examples/auto_compliance_demo.py +167 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/bench_example.py +1 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/bench_session_integration.py +9 -5
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/bench_sweep_integration_example.py +17 -12
- pytestlab-0.2.4/examples/cli.md +129 -0
- pytestlab-0.2.4/examples/compliance_decorator_example.py +319 -0
- pytestlab-0.2.4/examples/database_integration_example.py +205 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/facade_example.py +46 -38
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/gui.ipynb +1 -1
- pytestlab-0.2.4/examples/measurement_patterns.py +224 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/measurement_session_example.py +7 -5
- pytestlab-0.2.4/examples/measurements/advanced_demo.py +93 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/parallel/bench_parallel.yaml +1 -1
- pytestlab-0.2.4/examples/parallel/parallel_sweep_example.py +106 -0
- pytestlab-0.2.4/examples/parallel_measurement_demo.py +138 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/plot_dsx1204g_channel.py +1 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/replay_mode/replay_system_demo.py +1 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/replay_mode/replay_system_final_demo.sh +4 -4
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/replay_mode/test_real_replay.py +20 -8
- pytestlab-0.2.4/examples/simple_bench.py +86 -0
- pytestlab-0.2.4/examples/simple_bench.yaml +37 -0
- pytestlab-0.2.4/examples/simple_bench_test.py +103 -0
- pytestlab-0.2.4/examples/simple_database.py +102 -0
- pytestlab-0.2.4/examples/simple_hello_world.py +59 -0
- pytestlab-0.2.4/examples/simple_instrument.py +139 -0
- pytestlab-0.2.4/examples/simple_plotting.py +90 -0
- pytestlab-0.2.4/examples/simple_sweep.py +113 -0
- pytestlab-0.2.4/examples/smarbench.yaml +145 -0
- pytestlab-0.2.4/examples/sweep_decorator_example.py +244 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/test.py +1 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/test_bench_system.py +2 -2
- pytestlab-0.2.4/examples/test_direct_instruments.py +106 -0
- pytestlab-0.2.4/examples/test_smarbench.py +327 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples_ci/__init__.py +1 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples_ci/simulated_psu_dmm_sweep.py +2 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/paper/joss/paper.md +1 -0
- pytestlab-0.2.4/prmpt.yaml +159 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pyproject.toml +11 -17
- pytestlab-0.2.4/pytestlab/__init__.py +85 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/bench.py +58 -42
- pytestlab-0.2.4/pytestlab/cli.py +164 -0
- pytestlab-0.2.3/pytestlab/cli.py → pytestlab-0.2.4/pytestlab/cli_typer.py +167 -33
- pytestlab-0.2.4/pytestlab/compliance/__init__.py +73 -0
- pytestlab-0.2.4/pytestlab/compliance/auto_config.py +281 -0
- pytestlab-0.2.4/pytestlab/compliance/decorators.py +594 -0
- pytestlab-0.2.4/pytestlab/compliance/defaults.py +381 -0
- pytestlab-0.2.4/pytestlab/compliance/interfaces.py +334 -0
- pytestlab-0.2.4/pytestlab/compliance/paths.py +65 -0
- pytestlab-0.2.4/pytestlab/compliance/session.py +487 -0
- pytestlab-0.2.4/pytestlab/compliance/verification.py +160 -0
- pytestlab-0.2.4/pytestlab/config/__init__.py +74 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/config/bench_config.py +3 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/config/loader.py +27 -54
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/config/waveform_generator_config.py +6 -0
- pytestlab-0.2.4/pytestlab/experiments/__init__.py +53 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/experiments/experiments.py +4 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/experiments/results.py +3 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/experiments/sweep.py +56 -21
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/gui/threading_utils.py +3 -2
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/instruments/AutoInstrument.py +102 -74
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/instruments/Oscilloscope.py +42 -5
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/instruments/PowerSupply.py +2 -3
- pytestlab-0.2.4/pytestlab/instruments/__init__.py +50 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/instruments/backends/recording_backend.py +31 -17
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/instruments/backends/sim_backend.py +3 -2
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/instruments/instrument.py +2 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/measurements/__init__.py +8 -2
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/measurements/session.py +141 -10
- pytestlab-0.2.4/pytestlab/measurements/steps.py +160 -0
- pytestlab-0.2.4/pytestlab/profiles/__init__.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/profiles/keysight/DSOX1202G.yaml +36 -38
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/profiles/keysight/DSOX1204G.yaml +4 -4
- pytestlab-0.2.4/pytestlab/profiles/keysight/DSOX3054G.yaml +118 -0
- pytestlab-0.2.4/pytestlab/profiles/keysight/EDU33212A.yaml +197 -0
- pytestlab-0.2.4/pytestlab/profiles/keysight/MSOX2024A.yaml +118 -0
- pytestlab-0.2.4/pytestlab/profiles/keysight/MXR404A.yaml +104 -0
- pytestlab-0.2.4/pytestlab/verification/__init__.py +17 -0
- pytestlab-0.2.4/pytestlab/verification/profile_verify.py +987 -0
- pytestlab-0.2.4/scripts/benchmark_cli.py +148 -0
- pytestlab-0.2.4/scripts/smoke_cli.py +77 -0
- pytestlab-0.2.4/tests/README.md +114 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/__init__.py +1 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/conftest.py +1 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/experiments/test_simulation.py +1 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/instruments/__init__.py +1 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/instruments/sim/__init__.py +1 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/instruments/sim/conftest.py +1 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/instruments/sim/keysight/DSOX1204G.yaml +219 -6
- pytestlab-0.2.4/tests/instruments/sim/test_oscilloscope_sim.py +268 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/instruments/test_awg.py +1 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/instruments/test_bench.py +9 -9
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/instruments/test_dc_load.py +1 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/instruments/test_multimeter.py +1 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/instruments/test_oscilloscope.py +1 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/instruments/test_psu.py +1 -1
- pytestlab-0.2.4/tests/test_auto_compliance.py +318 -0
- pytestlab-0.2.4/tests/test_cli_bootstrap.py +147 -0
- pytestlab-0.2.4/tests/test_cli_verify_profile.py +118 -0
- pytestlab-0.2.4/tests/test_compliance.py +252 -0
- pytestlab-0.2.4/tests/test_measurement_session.py +89 -0
- pytestlab-0.2.4/tests/test_profile_registry.py +22 -0
- pytestlab-0.2.4/tests/test_profile_verify.py +466 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/test_recording_backend_psu.py +1 -1
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/test_simulation_e2e.py +14 -4
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/test_uncertainty.py +2 -2
- {pytestlab-0.2.3 → pytestlab-0.2.4}/uv.lock +29 -51
- pytestlab-0.2.3/CHANGELOG.md +0 -62
- pytestlab-0.2.3/docs/README.md +0 -191
- pytestlab-0.2.3/docs/api/backends.md +0 -67
- pytestlab-0.2.3/docs/api/config.md +0 -96
- pytestlab-0.2.3/docs/api/errors.md +0 -58
- pytestlab-0.2.3/docs/api/instruments.md +0 -74
- pytestlab-0.2.3/docs/api/measurements.md +0 -73
- pytestlab-0.2.3/docs/build.sh +0 -40
- pytestlab-0.2.3/docs/en/api/common.md +0 -23
- pytestlab-0.2.3/docs/en/api/experiments.md +0 -24
- pytestlab-0.2.3/docs/en/user_guide/cli.md +0 -150
- pytestlab-0.2.3/docs/mkdocs.yml +0 -176
- pytestlab-0.2.3/docs/scripts/README.md +0 -206
- pytestlab-0.2.3/docs/scripts/generate_notebook.py +0 -561
- pytestlab-0.2.3/docs/scripts/normalize_notebooks.py +0 -385
- pytestlab-0.2.3/docs/scripts/validate_styling.py +0 -490
- pytestlab-0.2.3/docs/user_guide/plotting.md +0 -80
- pytestlab-0.2.3/examples/database_integration_example.py +0 -237
- pytestlab-0.2.3/examples/measurement_patterns.py +0 -325
- pytestlab-0.2.3/examples/measurements/advanced_demo.py +0 -63
- pytestlab-0.2.3/examples/parallel/parallel_sweep_example.py +0 -127
- pytestlab-0.2.3/examples/parallel_measurement_demo.py +0 -248
- pytestlab-0.2.3/prmpt.yaml +0 -147
- pytestlab-0.2.3/pytestlab/__init__.py +0 -79
- pytestlab-0.2.3/pytestlab/compliance/__init__.py +0 -22
- pytestlab-0.2.3/pytestlab/compliance/audit.py +0 -95
- pytestlab-0.2.3/pytestlab/compliance/patch.py +0 -123
- pytestlab-0.2.3/pytestlab/compliance/signature.py +0 -169
- pytestlab-0.2.3/pytestlab/compliance/tsa.py +0 -53
- pytestlab-0.2.3/pytestlab/config/__init__.py +0 -33
- pytestlab-0.2.3/pytestlab/experiments/__init__.py +0 -19
- pytestlab-0.2.3/pytestlab/instruments/__init__.py +0 -19
- pytestlab-0.2.3/pytestlab/profiles/keysight/DSOX3054G.yaml +0 -122
- pytestlab-0.2.3/pytestlab/profiles/keysight/EDU33212A.yaml +0 -120
- pytestlab-0.2.3/pytestlab/profiles/keysight/MSOX2024A.yaml +0 -122
- pytestlab-0.2.3/pytestlab/profiles/keysight/MXR404A.yaml +0 -102
- pytestlab-0.2.3/tests/README.md +0 -207
- pytestlab-0.2.3/tests/instruments/sim/test_oscilloscope_sim.py +0 -93
- pytestlab-0.2.3/tests/test_compliance.py +0 -252
- pytestlab-0.2.3/tests/test_measurement_session.py +0 -47
- {pytestlab-0.2.3 → pytestlab-0.2.4}/.github/workflows/build_wheels.yml +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/.github/workflows/draft-pdf.yml +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/.github/workflows/publish_release.yml +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/.gitignore +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/CODE_OF_CONDUCT.md +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/LICENSE +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/MANIFEST.in +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/404.md +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/CODE_OF_CONDUCT.md +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/api/backends.md +0 -0
- {pytestlab-0.2.3/docs → pytestlab-0.2.4/docs/en}/api/common.md +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/api/config.md +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/api/errors.md +0 -0
- {pytestlab-0.2.3/docs → pytestlab-0.2.4/docs/en}/api/experiments.md +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/api/instruments.md +0 -0
- {pytestlab-0.2.3/docs/themes/labiium_photon → pytestlab-0.2.4/docs/en}/img/favicon.ico +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/index.md +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/js/notebook-enhancements.js +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/profiles/gallery.md +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/scripts/README.md +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/scripts/index.md +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/user_guide/bench_descriptors.md +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/user_guide/notebook_styling.md +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/user_guide/simulation.md +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/en/user_guide/uncertainty.md +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/themes/labiium_photon/img/pytestlab_logo.png +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/themes/labiium_photon/img/pytestlab_logo.svg +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/themes/labiium_photon/landing.html +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/docs/themes/labiium_photon/mkdocs_theme.yml +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/advanced_sweep_strategies.py +0 -0
- /pytestlab-0.2.3/pytestlab/profiles/__init__.py → /pytestlab-0.2.4/examples/bench.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/bench.yaml +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/bench_session_integration.ipynb +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/example_database.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/example_experiment.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/logs/experiment.log +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/measurement_session_sweep.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/plot_experiment.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/plot_measurement_result_array.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/replay_mode/cli_test_measurement.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/replay_mode/exact_replay_test.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/replay_mode/example_bench.yaml +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/replay_mode/example_measurement.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/replay_mode/real_bench.yaml +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/replay_mode/real_instrument_session.yaml +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/replay_mode/recorded_session.yaml +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/replay_mode/replay_workflow_example.sh +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/replay_mode/test_replay.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/scripts/save_results.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/scripts/setup_environment.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/session_bench.yaml +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples/sweep_integration_example.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/examples_ci/conftest.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/paper/joss/paper.bib +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/production_server.log +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytest.ini +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/_log.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/analysis/__init__.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/analysis/fft.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/analysis/fr_analysis.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/common/__init__.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/common/enums.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/common/health.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/config/_mixins.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/config/accuracy.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/config/base.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/config/bench_loader.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/config/config.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/config/dc_active_load_config.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/config/instrument_config.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/config/multimeter_config.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/config/oscilloscope_config.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/config/power_meter_config.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/config/power_supply_config.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/config/schema_validator.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/config/scpi_schema.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/config/scpi_validator.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/config/spectrum_analyzer_config.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/config/virtual_instrument_config.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/config/vna_config.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/errors.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/experiments/database.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/gui/__init__.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/gui/builder.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/instruments/DCActiveLoad.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/instruments/Multimeter.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/instruments/PowerMeter.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/instruments/SpectrumAnalyser.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/instruments/VectorNetworkAnalyser.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/instruments/VirtualInstrument.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/instruments/WaveformGenerator.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/instruments/backends/__init__.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/instruments/backends/lamb.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/instruments/backends/replay_backend.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/instruments/backends/session_recording_backend.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/instruments/backends/visa_backend.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/instruments/scpi_engine.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/plotting/__init__.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/plotting/simple.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/profiles/keysight/34460A.yaml +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/profiles/keysight/34470A.yaml +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/profiles/keysight/E5071C_VNA.yaml +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/profiles/keysight/EDU34450A.yaml +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/profiles/keysight/EDU36311A.yaml +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/profiles/keysight/EDU36311A_recorded.yaml +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/profiles/keysight/EL33133A.yaml +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/profiles/keysight/HD304MSO.yaml +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/profiles/keysight/N9000A_SA.yaml +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/profiles/keysight/U2000A_PM.yaml +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/profiles/pytestlab/binary_wave_data.bin +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/profiles/pytestlab/virtual_instrument.yaml +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab/profiles/rohdeschwarz/NGE102B.yaml +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/pytestlab_logo.png +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/scripts/generate_profile_gallery.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/test_schemas/instrument_config.json +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/test_schemas/oscilloscope.json +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/test_schemas/scpi_command_spec.json +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/test_schemas/scpi_commands_queries.json +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/test_schemas/scpi_section.json +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/experiments/recorded_psu_sim.yaml +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/experiments/test_database.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/experiments/test_experiment.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/experiments/test_result.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/experiments/test_script.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/instruments/acquisition_test_results/acq_mode_test_real_time.csv +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/instruments/acquisition_test_results/acq_mode_test_segmented_segment_1.csv +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/instruments/acquisition_test_results/acq_mode_test_segmented_segment_2.csv +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/instruments/acquisition_test_results/acq_type_test_high_res.csv +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/instruments/acquisition_test_results/acq_type_test_normal.csv +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/instruments/acquisition_test_results/acq_type_test_peak.csv +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/instruments/test_bench_integration.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/instruments/test_oscilloscope_plotting.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/plotting/test_plotting.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/smoke/test_profile_loading.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/test_autoinstrument_backend_override.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/test_cli.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/test_cli_replay.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/test_logging.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/test_measurement_database.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/test_replay_backend.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/test_safety.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/test_session_recording_backend.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/test_warnings.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/unit/test_feature_mapping_validation.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/unit/test_instrument_error_handling.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/unit/test_instrument_helpers.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/unit/test_multimeter_uncertainty.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/unit/test_scpi_engine_introspection.py +0 -0
- {pytestlab-0.2.3 → pytestlab-0.2.4}/tests/unit/test_scpi_schema_generation.py +0 -0
|
@@ -12,14 +12,11 @@ repos:
|
|
|
12
12
|
- id: ruff
|
|
13
13
|
args: [--fix, --exit-non-zero-on-fix]
|
|
14
14
|
- id: ruff-format
|
|
15
|
-
- repo:
|
|
16
|
-
rev: v1.10.1
|
|
15
|
+
- repo: local
|
|
17
16
|
hooks:
|
|
18
|
-
- id:
|
|
19
|
-
|
|
17
|
+
- id: ty
|
|
18
|
+
name: ty
|
|
19
|
+
entry: uvx ty check
|
|
20
|
+
language: system
|
|
20
21
|
pass_filenames: false
|
|
21
|
-
|
|
22
|
-
- types-PyYAML
|
|
23
|
-
- types-requests
|
|
24
|
-
- types-Pillow
|
|
25
|
-
- types-tqdm
|
|
22
|
+
stages: [pre-commit]
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format follows Keep a Changelog (https://keepachangelog.com/en/1.0.0/)
|
|
6
|
+
and the project adheres to Semantic Versioning (https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [v0.2.4] - 2026-05-12
|
|
11
|
+
### Added
|
|
12
|
+
- Added `ptl` as the preferred short CLI entry point while keeping `pytestlab` as a compatibility alias.
|
|
13
|
+
- Added instrument profile verification utilities and CLI coverage for schema, connection, identity, SCPI, and safety-oriented probe checks.
|
|
14
|
+
- Added profile registry tests to lock built-in device type discovery.
|
|
15
|
+
- Added CLI smoke and benchmark scripts for startup and common command paths.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- Split the heavy Typer CLI implementation into a lazy-loaded module so common CLI commands start faster.
|
|
19
|
+
- Updated documentation, examples, and scripts to use `ptl` by default.
|
|
20
|
+
- Lazy-loaded selected package exports in config, experiment, and instrument modules to reduce import-time overhead.
|
|
21
|
+
- Cleaned examples, compliance modules, and tests to pass the current Ruff and ty gates.
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
- Fixed CLI bootstrap dispatch so option-bearing commands such as `ptl profile show --help`, `ptl bench validate --help`, and `ptl profile list --profile-dir ...` fall through to Typer instead of being intercepted by fast paths.
|
|
25
|
+
- Fixed compliance typing issues around generic callables and configuration dictionaries.
|
|
26
|
+
- Removed the tracked `.DS_Store` artifact.
|
|
27
|
+
|
|
28
|
+
## [v0.2.3] - 2025-10-05
|
|
29
|
+
### Added
|
|
30
|
+
- Initial SCPI engine integration for instrument control.
|
|
31
|
+
- Comprehensive plotting utilities and examples.
|
|
32
|
+
- CLI enhancements for a better command-line experience.
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
- Multimeter module overhaul with improved structure and behavior.
|
|
36
|
+
- Documentation site updates (MkDocs configuration and content).
|
|
37
|
+
- Type-checking and lint configuration refined (mypy and ruff) with project-wide cleanups.
|
|
38
|
+
- Pre-commit and CI adjustments to improve developer workflow and reliability.
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
- Type checking issues addressed across modules (targeted mypy fixes and cleaned ignores).
|
|
42
|
+
- Lint violations resolved with ruff adjustments.
|
|
43
|
+
- Release workflow corrections.
|
|
44
|
+
|
|
45
|
+
### Removed
|
|
46
|
+
- Full removal of legacy async code paths.
|
|
47
|
+
|
|
48
|
+
## [v0.2.1] - 2025-08-06
|
|
49
|
+
### Added
|
|
50
|
+
- Measurement sweeps and example workflows.
|
|
51
|
+
- Simulation v2 promoted and examples added.
|
|
52
|
+
- New instrument support and profiles (including MSOX2024A; PSU integration via SCPI).
|
|
53
|
+
- GUI and documentation site improvements; language support for docs/examples.
|
|
54
|
+
|
|
55
|
+
### Changed
|
|
56
|
+
- Significant test stabilization with “all tests passing” milestone and follow-up fixes.
|
|
57
|
+
- Documentation and notebooks improved; site build updated.
|
|
58
|
+
- Initial reduction/removal of legacy async components.
|
|
59
|
+
|
|
60
|
+
### Fixed
|
|
61
|
+
- Documentation site mobile menu behavior.
|
|
62
|
+
- CI workflows and packaging adjustments.
|
|
63
|
+
- Invalid or flaky tests removed/reworked.
|
|
64
|
+
|
|
65
|
+
## [0.1.3] - 2025-02-19
|
|
66
|
+
### Added
|
|
67
|
+
- DC Active Load instrument initial support and configuration scaffolding.
|
|
68
|
+
|
|
69
|
+
### Fixed
|
|
70
|
+
- Early integration fixes and stability improvements around DC Load support.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
[Unreleased]: https://github.com/labiium/pytestlab/compare/v0.2.4...HEAD
|
|
75
|
+
[v0.2.4]: https://github.com/labiium/pytestlab/compare/v0.2.3...v0.2.4
|
|
76
|
+
[v0.2.3]: https://github.com/labiium/pytestlab/compare/v0.2.1...v0.2.3
|
|
77
|
+
[v0.2.1]: https://github.com/labiium/pytestlab/compare/13b5439...v0.2.1
|
|
78
|
+
[0.1.3]: https://github.com/labiium/pytestlab/commit/13b5439
|
|
@@ -6,12 +6,12 @@ This document provides guidelines for contributing to PyTestLab. Please read it
|
|
|
6
6
|
|
|
7
7
|
## Code of Conduct
|
|
8
8
|
|
|
9
|
-
This project and everyone participating in it is governed by the [PyTestLab Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to `pytestlab
|
|
9
|
+
This project and everyone participating in it is governed by the [PyTestLab Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to `support@pytestlab.org`.
|
|
10
10
|
|
|
11
11
|
## Getting Started
|
|
12
12
|
|
|
13
13
|
1. **Fork the repository** on GitHub.
|
|
14
|
-
2. **Clone your fork** locally: `git clone https://github.com/
|
|
14
|
+
2. **Clone your fork** locally: `git clone https://github.com/labiium/pytestlab.git`
|
|
15
15
|
3. **Set up the development environment:**
|
|
16
16
|
* It's recommended to use a virtual environment:
|
|
17
17
|
```bash
|
|
@@ -74,7 +74,7 @@ Now, every time you run `git commit`, the pre-commit hooks will run and check yo
|
|
|
74
74
|
5. **Ensure pre-commit checks pass.** If they make changes, `git add` those files and re-commit.
|
|
75
75
|
6. **Commit your changes** using conventional commit messages (`cz c` or `git cz commit`).
|
|
76
76
|
7. **Push your branch** to your fork: `git push origin name-of-your-feature`
|
|
77
|
-
8. **Open a Pull Request (PR)** to the `
|
|
77
|
+
8. **Open a Pull Request (PR)** to the `master` branch of the official PyTestLab repository.
|
|
78
78
|
* Provide a clear title and description for your PR.
|
|
79
79
|
* Link to any relevant issues.
|
|
80
80
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pytestlab
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Scientific test & measurement toolbox
|
|
5
5
|
Author-email: Emmanuel Olowe <e.a.olowe@ed.ac.uk>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -9,7 +9,6 @@ Requires-Python: >=3.11
|
|
|
9
9
|
Requires-Dist: aiofiles
|
|
10
10
|
Requires-Dist: cryptography
|
|
11
11
|
Requires-Dist: httpx
|
|
12
|
-
Requires-Dist: mypy>=1.17.1
|
|
13
12
|
Requires-Dist: numpy
|
|
14
13
|
Requires-Dist: pillow
|
|
15
14
|
Requires-Dist: polars
|
|
@@ -21,6 +20,7 @@ Requires-Dist: pyyaml
|
|
|
21
20
|
Requires-Dist: requests
|
|
22
21
|
Requires-Dist: ruff>=0.12.9
|
|
23
22
|
Requires-Dist: tqdm
|
|
23
|
+
Requires-Dist: ty>=0.0.1a29
|
|
24
24
|
Requires-Dist: typer
|
|
25
25
|
Requires-Dist: types-pillow>=10.2.0.20240822
|
|
26
26
|
Requires-Dist: types-pyyaml>=6.0.12.20250809
|
|
@@ -30,11 +30,11 @@ Requires-Dist: uncertainties
|
|
|
30
30
|
Provides-Extra: dev
|
|
31
31
|
Requires-Dist: aiofiles; extra == 'dev'
|
|
32
32
|
Requires-Dist: httpx; extra == 'dev'
|
|
33
|
-
Requires-Dist: mypy; extra == 'dev'
|
|
34
33
|
Requires-Dist: pre-commit; extra == 'dev'
|
|
35
34
|
Requires-Dist: pytest; extra == 'dev'
|
|
36
35
|
Requires-Dist: pytest-cov; extra == 'dev'
|
|
37
36
|
Requires-Dist: ruff; extra == 'dev'
|
|
37
|
+
Requires-Dist: ty>=0.0.1a29; extra == 'dev'
|
|
38
38
|
Provides-Extra: docs
|
|
39
39
|
Requires-Dist: ghp-import>=2.1.0; extra == 'docs'
|
|
40
40
|
Requires-Dist: matplotlib>=3.10.3; extra == 'docs'
|
|
@@ -86,6 +86,9 @@ Description-Content-Type: text/markdown
|
|
|
86
86
|
src="https://img.shields.io/badge/docs-latest-blue"/></a>
|
|
87
87
|
<a href="https://opensource.org/licenses/Apache-2.0"><img alt="Apache License"
|
|
88
88
|
src="https://img.shields.io/badge/license-Apache%202.0-blue"/></a>
|
|
89
|
+
<a href="https://github.com/labiium/pytestlab/actions/workflows/test.yml"><img
|
|
90
|
+
alt="Tests"
|
|
91
|
+
src="https://github.com/labiium/pytestlab/actions/workflows/test.yml/badge.svg"/></a>
|
|
89
92
|
</p>
|
|
90
93
|
|
|
91
94
|
---
|
|
@@ -102,7 +105,7 @@ Description-Content-Type: text/markdown
|
|
|
102
105
|
* **Bench descriptors** – group multiple instruments in one `bench.yaml`, define safety limits, automation hooks, traceability and measurement plans.
|
|
103
106
|
* **High-level measurement builder** – notebook-friendly `MeasurementSession` for parameter sweeps that stores data as Polars DataFrames and exports straight to the experiment database.
|
|
104
107
|
* **Rich database** – compressed storage of experiments & measurements with full-text search (`MeasurementDatabase`).
|
|
105
|
-
* **Powerful CLI** – `
|
|
108
|
+
* **Powerful CLI** – `ptl ...` commands to list/validate profiles, query instruments, convert benches to simulation, replay sessions, etc.
|
|
106
109
|
* **Extensible back-ends** – VISA, Lamb server, pure simulation; drop-in new transports via the `InstrumentIO` protocol.
|
|
107
110
|
* **Docs & examples** – Jupyter tutorials, MkDocs site, and 40+ ready-to-run scripts in `examples/`.
|
|
108
111
|
|
|
@@ -122,7 +125,7 @@ pip install pytestlab[full] # + plotting, uncertainties, etc.
|
|
|
122
125
|
### 2. Hello Oscilloscope (simulated)
|
|
123
126
|
|
|
124
127
|
```python
|
|
125
|
-
from pytestlab
|
|
128
|
+
from pytestlab import AutoInstrument
|
|
126
129
|
|
|
127
130
|
def main():
|
|
128
131
|
scope = AutoInstrument.from_config("keysight/DSOX1204G", simulate=True)
|
|
@@ -175,14 +178,26 @@ Record real instrument interactions and replay them exactly:
|
|
|
175
178
|
|
|
176
179
|
```bash
|
|
177
180
|
# Record a measurement session
|
|
178
|
-
|
|
181
|
+
ptl replay record my_measurement.py --bench bench.yaml --output session.yaml
|
|
179
182
|
|
|
180
183
|
# Replay the recorded session
|
|
181
|
-
|
|
184
|
+
ptl replay run my_measurement.py --session session.yaml
|
|
182
185
|
```
|
|
183
186
|
|
|
184
187
|
Perfect for reproducible measurements, offline analysis, and catching script changes!
|
|
185
188
|
|
|
189
|
+
### 5. Run the Tests
|
|
190
|
+
|
|
191
|
+
The CI matrix runs `pytest` on Ubuntu for Python 3.11 - 3.14 (see the badges above).
|
|
192
|
+
Replicate the same checks locally with the dev extras installed:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
pip install -e .[dev]
|
|
196
|
+
pytest tests/ --cov=pytestlab
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
The suite writes `coverage.xml`, which the workflow uploads to Codecov for the coverage badge.
|
|
200
|
+
|
|
186
201
|
---
|
|
187
202
|
|
|
188
203
|
## 🔄 Record & Replay Mode
|
|
@@ -207,15 +222,15 @@ PyTestLab's **Record & Replay** system enables you to capture real instrument in
|
|
|
207
222
|
#### Basic Recording & Replay
|
|
208
223
|
```bash
|
|
209
224
|
# Record a measurement with real instruments
|
|
210
|
-
|
|
225
|
+
ptl replay record voltage_sweep.py --bench lab_bench.yaml --output sweep_session.yaml
|
|
211
226
|
|
|
212
227
|
# Replay the exact sequence (simulated)
|
|
213
|
-
|
|
228
|
+
ptl replay run voltage_sweep.py --session sweep_session.yaml
|
|
214
229
|
```
|
|
215
230
|
|
|
216
231
|
#### Programmatic Usage
|
|
217
232
|
```python
|
|
218
|
-
from pytestlab
|
|
233
|
+
from pytestlab import AutoInstrument
|
|
219
234
|
from pytestlab.instruments.backends import ReplayBackend
|
|
220
235
|
|
|
221
236
|
def main():
|
|
@@ -332,7 +347,7 @@ with MeasurementSession("Quick Session") as session:
|
|
|
332
347
|
|
|
333
348
|
### Oscilloscope example – Keysight DSOX1204G (simulated)
|
|
334
349
|
```python
|
|
335
|
-
from pytestlab
|
|
350
|
+
from pytestlab import AutoInstrument
|
|
336
351
|
from pytestlab.plotting import PlotSpec
|
|
337
352
|
|
|
338
353
|
scope = AutoInstrument.from_config("keysight/DSOX1204G", simulate=True)
|
|
@@ -354,7 +369,7 @@ PyTestLab features a fluent, chainable API that makes instrument control code cl
|
|
|
354
369
|
|
|
355
370
|
### Power Supply Example
|
|
356
371
|
```python
|
|
357
|
-
from pytestlab
|
|
372
|
+
from pytestlab import AutoInstrument
|
|
358
373
|
|
|
359
374
|
psu = AutoInstrument.from_config("keysight/E36312A")
|
|
360
375
|
|
|
@@ -429,13 +444,15 @@ PyTestLab's `MeasurementSession` provides a powerful framework for parameter swe
|
|
|
429
444
|
|
|
430
445
|
### Basic Parameter Sweep
|
|
431
446
|
```python
|
|
432
|
-
from pytestlab.measurements import MeasurementSession
|
|
447
|
+
from pytestlab.measurements import MeasurementSession, step
|
|
433
448
|
import numpy as np
|
|
434
449
|
|
|
435
450
|
with MeasurementSession("Voltage Response Test") as session:
|
|
436
451
|
# Define sweep parameters
|
|
437
452
|
session.parameter("voltage", np.linspace(0, 5, 10), unit="V")
|
|
438
453
|
session.parameter("delay", [0.1, 0.5], unit="s")
|
|
454
|
+
# Declarative helpers for non-linear sweeps are available via pytestlab.measurements.step
|
|
455
|
+
session.parameter("frequency", step.log(start=1e3, stop=1e6, count=50), unit="Hz")
|
|
439
456
|
|
|
440
457
|
# Setup instruments
|
|
441
458
|
psu = session.instrument("psu", "keysight/EDU36311A", simulate=True)
|
|
@@ -667,7 +684,7 @@ PyTestLab provides built-in compliance features for regulated environments:
|
|
|
667
684
|
### Automatic Measurement Signing
|
|
668
685
|
```python
|
|
669
686
|
# Compliance features are automatically enabled
|
|
670
|
-
from pytestlab
|
|
687
|
+
from pytestlab import AutoInstrument
|
|
671
688
|
|
|
672
689
|
dmm = AutoInstrument.from_config("keysight/34470A")
|
|
673
690
|
dmm.connect_backend()
|
|
@@ -745,7 +762,7 @@ else:
|
|
|
745
762
|
## 🧑💻 Contributing
|
|
746
763
|
|
|
747
764
|
Pull requests are welcome! See [`CONTRIBUTING.md`](CONTRIBUTING.md) and the [Code of Conduct](CODE_OF_CONDUCT.md).
|
|
748
|
-
Run the test-suite (`pytest`), type-check (`
|
|
765
|
+
Run the test-suite (`pytest`), type-check (`uvx ty check`), lint/format (`ruff`), and keep commits conventional (`cz c`).
|
|
749
766
|
|
|
750
767
|
---
|
|
751
768
|
|
|
@@ -24,6 +24,9 @@
|
|
|
24
24
|
src="https://img.shields.io/badge/docs-latest-blue"/></a>
|
|
25
25
|
<a href="https://opensource.org/licenses/Apache-2.0"><img alt="Apache License"
|
|
26
26
|
src="https://img.shields.io/badge/license-Apache%202.0-blue"/></a>
|
|
27
|
+
<a href="https://github.com/labiium/pytestlab/actions/workflows/test.yml"><img
|
|
28
|
+
alt="Tests"
|
|
29
|
+
src="https://github.com/labiium/pytestlab/actions/workflows/test.yml/badge.svg"/></a>
|
|
27
30
|
</p>
|
|
28
31
|
|
|
29
32
|
---
|
|
@@ -40,7 +43,7 @@
|
|
|
40
43
|
* **Bench descriptors** – group multiple instruments in one `bench.yaml`, define safety limits, automation hooks, traceability and measurement plans.
|
|
41
44
|
* **High-level measurement builder** – notebook-friendly `MeasurementSession` for parameter sweeps that stores data as Polars DataFrames and exports straight to the experiment database.
|
|
42
45
|
* **Rich database** – compressed storage of experiments & measurements with full-text search (`MeasurementDatabase`).
|
|
43
|
-
* **Powerful CLI** – `
|
|
46
|
+
* **Powerful CLI** – `ptl ...` commands to list/validate profiles, query instruments, convert benches to simulation, replay sessions, etc.
|
|
44
47
|
* **Extensible back-ends** – VISA, Lamb server, pure simulation; drop-in new transports via the `InstrumentIO` protocol.
|
|
45
48
|
* **Docs & examples** – Jupyter tutorials, MkDocs site, and 40+ ready-to-run scripts in `examples/`.
|
|
46
49
|
|
|
@@ -60,7 +63,7 @@ pip install pytestlab[full] # + plotting, uncertainties, etc.
|
|
|
60
63
|
### 2. Hello Oscilloscope (simulated)
|
|
61
64
|
|
|
62
65
|
```python
|
|
63
|
-
from pytestlab
|
|
66
|
+
from pytestlab import AutoInstrument
|
|
64
67
|
|
|
65
68
|
def main():
|
|
66
69
|
scope = AutoInstrument.from_config("keysight/DSOX1204G", simulate=True)
|
|
@@ -113,14 +116,26 @@ Record real instrument interactions and replay them exactly:
|
|
|
113
116
|
|
|
114
117
|
```bash
|
|
115
118
|
# Record a measurement session
|
|
116
|
-
|
|
119
|
+
ptl replay record my_measurement.py --bench bench.yaml --output session.yaml
|
|
117
120
|
|
|
118
121
|
# Replay the recorded session
|
|
119
|
-
|
|
122
|
+
ptl replay run my_measurement.py --session session.yaml
|
|
120
123
|
```
|
|
121
124
|
|
|
122
125
|
Perfect for reproducible measurements, offline analysis, and catching script changes!
|
|
123
126
|
|
|
127
|
+
### 5. Run the Tests
|
|
128
|
+
|
|
129
|
+
The CI matrix runs `pytest` on Ubuntu for Python 3.11 - 3.14 (see the badges above).
|
|
130
|
+
Replicate the same checks locally with the dev extras installed:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
pip install -e .[dev]
|
|
134
|
+
pytest tests/ --cov=pytestlab
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The suite writes `coverage.xml`, which the workflow uploads to Codecov for the coverage badge.
|
|
138
|
+
|
|
124
139
|
---
|
|
125
140
|
|
|
126
141
|
## 🔄 Record & Replay Mode
|
|
@@ -145,15 +160,15 @@ PyTestLab's **Record & Replay** system enables you to capture real instrument in
|
|
|
145
160
|
#### Basic Recording & Replay
|
|
146
161
|
```bash
|
|
147
162
|
# Record a measurement with real instruments
|
|
148
|
-
|
|
163
|
+
ptl replay record voltage_sweep.py --bench lab_bench.yaml --output sweep_session.yaml
|
|
149
164
|
|
|
150
165
|
# Replay the exact sequence (simulated)
|
|
151
|
-
|
|
166
|
+
ptl replay run voltage_sweep.py --session sweep_session.yaml
|
|
152
167
|
```
|
|
153
168
|
|
|
154
169
|
#### Programmatic Usage
|
|
155
170
|
```python
|
|
156
|
-
from pytestlab
|
|
171
|
+
from pytestlab import AutoInstrument
|
|
157
172
|
from pytestlab.instruments.backends import ReplayBackend
|
|
158
173
|
|
|
159
174
|
def main():
|
|
@@ -270,7 +285,7 @@ with MeasurementSession("Quick Session") as session:
|
|
|
270
285
|
|
|
271
286
|
### Oscilloscope example – Keysight DSOX1204G (simulated)
|
|
272
287
|
```python
|
|
273
|
-
from pytestlab
|
|
288
|
+
from pytestlab import AutoInstrument
|
|
274
289
|
from pytestlab.plotting import PlotSpec
|
|
275
290
|
|
|
276
291
|
scope = AutoInstrument.from_config("keysight/DSOX1204G", simulate=True)
|
|
@@ -292,7 +307,7 @@ PyTestLab features a fluent, chainable API that makes instrument control code cl
|
|
|
292
307
|
|
|
293
308
|
### Power Supply Example
|
|
294
309
|
```python
|
|
295
|
-
from pytestlab
|
|
310
|
+
from pytestlab import AutoInstrument
|
|
296
311
|
|
|
297
312
|
psu = AutoInstrument.from_config("keysight/E36312A")
|
|
298
313
|
|
|
@@ -367,13 +382,15 @@ PyTestLab's `MeasurementSession` provides a powerful framework for parameter swe
|
|
|
367
382
|
|
|
368
383
|
### Basic Parameter Sweep
|
|
369
384
|
```python
|
|
370
|
-
from pytestlab.measurements import MeasurementSession
|
|
385
|
+
from pytestlab.measurements import MeasurementSession, step
|
|
371
386
|
import numpy as np
|
|
372
387
|
|
|
373
388
|
with MeasurementSession("Voltage Response Test") as session:
|
|
374
389
|
# Define sweep parameters
|
|
375
390
|
session.parameter("voltage", np.linspace(0, 5, 10), unit="V")
|
|
376
391
|
session.parameter("delay", [0.1, 0.5], unit="s")
|
|
392
|
+
# Declarative helpers for non-linear sweeps are available via pytestlab.measurements.step
|
|
393
|
+
session.parameter("frequency", step.log(start=1e3, stop=1e6, count=50), unit="Hz")
|
|
377
394
|
|
|
378
395
|
# Setup instruments
|
|
379
396
|
psu = session.instrument("psu", "keysight/EDU36311A", simulate=True)
|
|
@@ -605,7 +622,7 @@ PyTestLab provides built-in compliance features for regulated environments:
|
|
|
605
622
|
### Automatic Measurement Signing
|
|
606
623
|
```python
|
|
607
624
|
# Compliance features are automatically enabled
|
|
608
|
-
from pytestlab
|
|
625
|
+
from pytestlab import AutoInstrument
|
|
609
626
|
|
|
610
627
|
dmm = AutoInstrument.from_config("keysight/34470A")
|
|
611
628
|
dmm.connect_backend()
|
|
@@ -683,7 +700,7 @@ else:
|
|
|
683
700
|
## 🧑💻 Contributing
|
|
684
701
|
|
|
685
702
|
Pull requests are welcome! See [`CONTRIBUTING.md`](CONTRIBUTING.md) and the [Code of Conduct](CODE_OF_CONDUCT.md).
|
|
686
|
-
Run the test-suite (`pytest`), type-check (`
|
|
703
|
+
Run the test-suite (`pytest`), type-check (`uvx ty check`), lint/format (`ruff`), and keep commits conventional (`cz c`).
|
|
687
704
|
|
|
688
705
|
---
|
|
689
706
|
|
|
@@ -31,7 +31,7 @@ This abstraction is ideal for automating multi-instrument experiments, batch mea
|
|
|
31
31
|
|
|
32
32
|
```python
|
|
33
33
|
from pytestlab.measurements import MeasurementSession
|
|
34
|
-
from pytestlab
|
|
34
|
+
from pytestlab import AutoInstrument
|
|
35
35
|
|
|
36
36
|
def main():
|
|
37
37
|
# Create instrument instances (simulated for this example)
|
|
@@ -70,4 +70,21 @@ main()
|
|
|
70
70
|
|
|
71
71
|
---
|
|
72
72
|
|
|
73
|
+
## Step Helpers for Parameters
|
|
74
|
+
|
|
75
|
+
PyTestLab exposes `pytestlab.measurements.step` helpers so you can succinctly define logarithmic, exponential, geometric, or fully custom sequences for `session.parameter(...)`:
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
from pytestlab.measurements import MeasurementSession, step
|
|
79
|
+
|
|
80
|
+
with MeasurementSession() as session:
|
|
81
|
+
session.parameter("freq", step.log(start=1e3, stop=1e6, count=100))
|
|
82
|
+
session.parameter("gain", step.exp(exponent_start=-3, exponent_stop=2, count=25))
|
|
83
|
+
session.parameter("impedance", step.points([1+1j, 1-1j, -1+1j]))
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Each helper returns a `StepSpec` that lazily generates the final iterable just before the sweep runs, keeping scripts tidy while still supporting exotic sweep shapes.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
73
90
|
For more advanced usage, see the [Experiments & Sweeps API](experiments.md) and the [10-Minute Tour](../tutorials/10_minute_tour.ipynb).
|
|
@@ -13,7 +13,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
|
13
13
|
|
|
14
14
|
## [Unreleased]
|
|
15
15
|
|
|
16
|
+
## [v0.2.4] - 2026-05-12
|
|
17
|
+
|
|
16
18
|
### Added
|
|
19
|
+
- Added `ptl` as the preferred short CLI entry point while retaining the existing `pytestlab` command.
|
|
20
|
+
- Added instrument profile verification utilities and tests.
|
|
21
|
+
- Added CLI smoke and benchmark scripts for startup-sensitive command paths.
|
|
17
22
|
- Initial migration to new documentation structure under `docs/en/`.
|
|
18
23
|
- Enhanced theme and navigation for multilingual and modern Material for MkDocs features.
|
|
19
24
|
- Improved simulation backend documentation and CLI reference.
|
|
@@ -21,12 +26,19 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
|
21
26
|
- Bench descriptor and safety limit documentation improvements.
|
|
22
27
|
|
|
23
28
|
### Changed
|
|
29
|
+
- Updated CLI documentation and examples to use `ptl` by default.
|
|
30
|
+
- Split the CLI into a lightweight bootstrap and lazy-loaded Typer implementation for faster common commands.
|
|
31
|
+
- Lazy-loaded selected package exports to reduce import-time overhead.
|
|
32
|
+
- Cleaned examples, compliance modules, and tests for Ruff and ty.
|
|
24
33
|
- Home page and quick start rewritten for clarity and improved onboarding.
|
|
25
34
|
- Installation instructions updated for clarity and VISA backend support.
|
|
26
35
|
- User guide reorganized for better onboarding and discoverability.
|
|
27
36
|
- Custom styles simplified for new theme.
|
|
28
37
|
|
|
29
38
|
### Fixed
|
|
39
|
+
- Fixed CLI help and option handling for bootstrap fast paths.
|
|
40
|
+
- Fixed compliance typing issues around generic callables and configuration dictionaries.
|
|
41
|
+
- Removed a tracked `.DS_Store` artifact.
|
|
30
42
|
- Navigation bugs and broken links in documentation.
|
|
31
43
|
- Outdated references to old profile and bench formats.
|
|
32
44
|
|
|
@@ -60,6 +72,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
|
60
72
|
|
|
61
73
|
---
|
|
62
74
|
|
|
63
|
-
[Unreleased]: https://github.com/labiium/pytestlab/compare/v0.
|
|
75
|
+
[Unreleased]: https://github.com/labiium/pytestlab/compare/v0.2.4...HEAD
|
|
76
|
+
[v0.2.4]: https://github.com/labiium/pytestlab/compare/v0.2.3...v0.2.4
|
|
64
77
|
[0.1.5]: https://github.com/labiium/pytestlab/releases/tag/v0.1.5
|
|
65
78
|
[0.1.0]: https://github.com/labiium/pytestlab/releases/tag/v0.1.0
|
|
@@ -67,7 +67,7 @@ All contributors are expected to follow the [PyTestLab Code of Conduct](CODE_OF_
|
|
|
67
67
|
## Code Style & Quality
|
|
68
68
|
|
|
69
69
|
- **Linting & Formatting:** PyTestLab uses [Ruff](https://docs.astral.sh/ruff/) for linting and formatting, and [Black](https://black.readthedocs.io/) for code style. These are enforced by pre-commit.
|
|
70
|
-
- **Type Checking:** Use [
|
|
70
|
+
- **Type Checking:** Use [ty](https://docs.astral.sh/ty/) for static type checking (e.g., `uvx ty check`).
|
|
71
71
|
- **Commit Messages:** Follow the [Conventional Commits](https://www.conventionalcommits.org/) specification. Use `cz c` to help format your commit messages.
|
|
72
72
|
|
|
73
73
|
---
|
|
@@ -59,8 +59,8 @@ pip install --upgrade pytestlab
|
|
|
59
59
|
After installation, you can verify that PyTestLab is installed and working:
|
|
60
60
|
|
|
61
61
|
```bash
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
ptl --version
|
|
63
|
+
ptl profile list
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
If you see a list of available instrument profiles, your installation is successful.
|
|
@@ -39,7 +39,7 @@ channels:
|
|
|
39
39
|
2. **Add Metadata:** Fill in the `manufacturer`, `model`, and `device_type`. The `device_type` must match one of the defined Pydantic config models in `pytestlab.config`.
|
|
40
40
|
3. **Add Configuration Data:** Refer to the corresponding Pydantic model in the [Configuration API Reference](../api/config.md) and fill in the fields with the specifications from your instrument's datasheet.
|
|
41
41
|
4. **Save the Profile:** Save the file in a known location. You can then load it directly by its path in `AutoInstrument.from_config()` or place it in `pytestlab/profiles/<vendor>/` to load it by key.
|
|
42
|
-
5. **Validate:** Use the CLI to validate your new profile: `
|
|
42
|
+
5. **Validate:** Use the CLI to validate your new profile: `ptl profile validate path/to/your/profile.yaml`.
|
|
43
43
|
|
|
44
44
|
For more complex instruments, you may need to define nested structures for triggers, channels, FFT, etc., as seen in the built-in profiles.
|
|
45
45
|
|