pyxel-config-core 0.7.0__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.
Potentially problematic release.
This version of pyxel-config-core might be problematic. Click here for more details.
- pyxel_config_core-0.7.0/CHANGELOG.md +361 -0
- pyxel_config_core-0.7.0/LICENSE +21 -0
- pyxel_config_core-0.7.0/MANIFEST.in +7 -0
- pyxel_config_core-0.7.0/PKG-INFO +560 -0
- pyxel_config_core-0.7.0/README.md +507 -0
- pyxel_config_core-0.7.0/conftest.py +29 -0
- pyxel_config_core-0.7.0/pyproject.toml +131 -0
- pyxel_config_core-0.7.0/pyxel_config_core/__init__.py +107 -0
- pyxel_config_core-0.7.0/pyxel_config_core/_data.py +48 -0
- pyxel_config_core-0.7.0/pyxel_config_core/_deep_worker.py +95 -0
- pyxel_config_core-0.7.0/pyxel_config_core/banner.py +197 -0
- pyxel_config_core-0.7.0/pyxel_config_core/cli.py +1282 -0
- pyxel_config_core-0.7.0/pyxel_config_core/config_shape.py +236 -0
- pyxel_config_core-0.7.0/pyxel_config_core/console.py +200 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/BUNDLE.json +6 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/modelParameters.json +1153 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/pyxel_schema.json +8558 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeCollection_fixed_pattern_noise.md +151 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeCollection_glow.md +163 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeCollection_persistence.md +160 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeCollection_simple_collection.md +143 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeCollection_simple_full_well.md +153 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeCollection_simple_persistence.md +161 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeGeneration_apd_gain.md +182 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeGeneration_apply_qe_curve.md +163 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeGeneration_avalanche_gain.md +169 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeGeneration_charge_blocks.md +162 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeGeneration_charge_deposition.md +169 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeGeneration_charge_deposition_in_mct.md +168 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeGeneration_conversion_with_3d_qe_map.md +163 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeGeneration_conversion_with_qe_map.md +160 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeGeneration_cosmix.md +167 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeGeneration_dark_current.md +162 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeGeneration_dark_current_dd.md +174 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeGeneration_dark_current_prerad.md +177 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeGeneration_dark_current_rule07.md +165 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeGeneration_dark_current_rule22.md +172 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeGeneration_dark_current_saphira.md +164 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeGeneration_dark_current_tid.md +175 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeGeneration_exponential_qe.md +160 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeGeneration_load_charge.md +159 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeGeneration_radiation_induced_dark_current.md +172 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeGeneration_simple_conversion.md +159 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeGeneration_simple_dark_current.md +165 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeMeasurement_ac_crosstalk.md +168 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeMeasurement_alternating_column_noise_cmos.md +154 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeMeasurement_correlated_pink_noise_cmos.md +189 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeMeasurement_dc_crosstalk.md +165 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeMeasurement_dc_offset.md +156 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeMeasurement_ktc_noise.md +172 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeMeasurement_nghxrg.md +113 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeMeasurement_output_node_linearity_poly.md +162 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeMeasurement_output_node_noise.md +173 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeMeasurement_output_node_noise_cmos.md +175 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeMeasurement_output_pixel_reset_voltage_apd.md +168 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeMeasurement_physical_non_linearity.md +166 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeMeasurement_physical_non_linearity_with_saturation.md +169 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeMeasurement_readout_noise_saphira.md +171 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeMeasurement_simple_ipc.md +172 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeMeasurement_simple_measurement.md +155 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeMeasurement_simple_physical_non_linearity.md +162 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeMeasurement_uncorrelated_pink_noise_cmos.md +181 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeTransfer_arctic_add.md +162 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeTransfer_arctic_remove.md +165 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeTransfer_cdm.md +165 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeTransfer_multiplication_register.md +164 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ChargeTransfer_multiplication_register_cic.md +162 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/DataProcessing_extract_roi_to_xarray.md +171 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/DataProcessing_linear_regression.md +170 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/DataProcessing_mean_variance.md +171 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/DataProcessing_plot_roi.md +173 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/DataProcessing_remove_cosmic_rays.md +178 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/DataProcessing_signal_to_noise_ratio.md +169 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/DataProcessing_source_extractor.md +175 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/DataProcessing_statistics.md +171 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/Phasing_pulse_processing.md +171 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/PhotonCollection_illumination.md +138 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/PhotonCollection_load_image.md +138 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/PhotonCollection_load_psf.md +161 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/PhotonCollection_load_wavelength_psf.md +167 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/PhotonCollection_optical_psf.md +159 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/PhotonCollection_shot_noise.md +155 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/PhotonCollection_simple_collection.md +140 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/PhotonCollection_stripe_pattern.md +143 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/PhotonCollection_usaf_illumination.md +150 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/PhotonCollection_wavelength_dependence_airs.md +165 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ReadoutElectronics_dead_time_filter.md +171 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ReadoutElectronics_sar_adc.md +167 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ReadoutElectronics_sar_adc_with_noise.md +170 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ReadoutElectronics_simple_adc.md +160 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ReadoutElectronics_simple_amplifier.md +164 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/ReadoutElectronics_simple_phase_conversion.md +166 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/SceneGeneration_load_image.md +183 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/SceneGeneration_load_star_map.md +167 -0
- pyxel_config_core-0.7.0/pyxel_config_core/data/tutorials/SceneGeneration_usaf_illumination.md +179 -0
- pyxel_config_core-0.7.0/pyxel_config_core/diagnostics.py +58 -0
- pyxel_config_core-0.7.0/pyxel_config_core/discriminator.py +488 -0
- pyxel_config_core-0.7.0/pyxel_config_core/embedder.py +37 -0
- pyxel_config_core-0.7.0/pyxel_config_core/expressions.py +315 -0
- pyxel_config_core-0.7.0/pyxel_config_core/formats.py +265 -0
- pyxel_config_core-0.7.0/pyxel_config_core/fpa.py +489 -0
- pyxel_config_core-0.7.0/pyxel_config_core/knowledge.py +393 -0
- pyxel_config_core-0.7.0/pyxel_config_core/mcp_server.py +121 -0
- pyxel_config_core-0.7.0/pyxel_config_core/models.py +209 -0
- pyxel_config_core-0.7.0/pyxel_config_core/py.typed +0 -0
- pyxel_config_core-0.7.0/pyxel_config_core/rag.py +236 -0
- pyxel_config_core-0.7.0/pyxel_config_core/readout_times.py +177 -0
- pyxel_config_core-0.7.0/pyxel_config_core/run_rules.py +811 -0
- pyxel_config_core-0.7.0/pyxel_config_core/validation.py +945 -0
- pyxel_config_core-0.7.0/pyxel_config_core/yaml_dialect.py +60 -0
- pyxel_config_core-0.7.0/pyxel_config_core/yaml_read.py +174 -0
- pyxel_config_core-0.7.0/pyxel_config_core.egg-info/PKG-INFO +560 -0
- pyxel_config_core-0.7.0/pyxel_config_core.egg-info/SOURCES.txt +138 -0
- pyxel_config_core-0.7.0/pyxel_config_core.egg-info/dependency_links.txt +1 -0
- pyxel_config_core-0.7.0/pyxel_config_core.egg-info/entry_points.txt +4 -0
- pyxel_config_core-0.7.0/pyxel_config_core.egg-info/requires.txt +29 -0
- pyxel_config_core-0.7.0/pyxel_config_core.egg-info/top_level.txt +1 -0
- pyxel_config_core-0.7.0/setup.cfg +4 -0
- pyxel_config_core-0.7.0/tests/cmos_config.yaml +59 -0
- pyxel_config_core-0.7.0/tests/galaxy_config.yaml +114 -0
- pyxel_config_core-0.7.0/tests/observation_config.yaml +60 -0
- pyxel_config_core-0.7.0/tests/test_audit_findings.py +327 -0
- pyxel_config_core-0.7.0/tests/test_cli.py +542 -0
- pyxel_config_core-0.7.0/tests/test_deep.py +456 -0
- pyxel_config_core-0.7.0/tests/test_discriminator.py +186 -0
- pyxel_config_core-0.7.0/tests/test_docs_quickstart.py +40 -0
- pyxel_config_core-0.7.0/tests/test_expressions.py +325 -0
- pyxel_config_core-0.7.0/tests/test_fixtures.py +67 -0
- pyxel_config_core-0.7.0/tests/test_formats.py +266 -0
- pyxel_config_core-0.7.0/tests/test_fpa.py +370 -0
- pyxel_config_core-0.7.0/tests/test_mcp_enhancements.py +365 -0
- pyxel_config_core-0.7.0/tests/test_mcp_server_surface.py +224 -0
- pyxel_config_core-0.7.0/tests/test_packaging.py +373 -0
- pyxel_config_core-0.7.0/tests/test_rag.py +57 -0
- pyxel_config_core-0.7.0/tests/test_readout_times.py +66 -0
- pyxel_config_core-0.7.0/tests/test_run_rules.py +257 -0
- pyxel_config_core-0.7.0/tests/test_smoke.py +79 -0
- pyxel_config_core-0.7.0/tests/test_validation.py +359 -0
- pyxel_config_core-0.7.0/tests/test_yaml_dialect.py +53 -0
- pyxel_config_core-0.7.0/tests/test_yaml_read.py +187 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to pyxel-config-core are recorded here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project uses
|
|
5
|
+
[Semantic Versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
Releases up to 0.5.0 were published to PyPI before the repository tagged its
|
|
8
|
+
releases, so they link to PyPI. From 0.6.0 on, each release is published from a
|
|
9
|
+
`core-v` tag.
|
|
10
|
+
|
|
11
|
+
## [Unreleased]
|
|
12
|
+
|
|
13
|
+
## [0.7.0] - 2026-11-06
|
|
14
|
+
|
|
15
|
+
### Security
|
|
16
|
+
|
|
17
|
+
- The deep check's safety gate now refuses every file Pyxel opens or looks for
|
|
18
|
+
while it loads. `charge_to_volt`'s `value` and `from_capacitance`, plain or
|
|
19
|
+
under `sensitive` and `reference`, are read as images when they are text, so
|
|
20
|
+
a config could make the machine send a request to a URL, and the answer said
|
|
21
|
+
which local files exist. Any text in a detector's characteristics is now
|
|
22
|
+
refused as a file, along with a calibration's `target_data_path` and
|
|
23
|
+
`weights_from_file`. A new drift guard reads Pyxel's source and fails when a
|
|
24
|
+
release adds a place that opens or evaluates something during a load.
|
|
25
|
+
- An APD converter's `lambda` may no longer ask for unbounded arithmetic.
|
|
26
|
+
`lambda x: 9**9**9**9` never returned, and `lambda x: 1 << 10**11` asked for
|
|
27
|
+
about 12.5 GB. A power now takes a plain exponent of at most 64 and a base
|
|
28
|
+
with no power in it, and shifts and bit operations are refused.
|
|
29
|
+
- The deep check runs `pyxel.load()` in a process of its own, with a time limit
|
|
30
|
+
(120 seconds; `--deep-timeout` or `deep_timeout=` changes it). A load still
|
|
31
|
+
running then is stopped and reported as an error. Without trust, the process
|
|
32
|
+
also has a limit on its memory where the system allows one, and it never
|
|
33
|
+
imports modules from the current folder.
|
|
34
|
+
- Text past 20,000 characters is not read as Python. On Python 3.10 a chain of
|
|
35
|
+
some 100,000 operators in `times`, `values` or an APD `function` ended the
|
|
36
|
+
whole process with a segmentation fault, where a config now gets a refusal
|
|
37
|
+
that says why.
|
|
38
|
+
|
|
39
|
+
### Added
|
|
40
|
+
|
|
41
|
+
- `--deep-timeout SECONDS` on `validate`, and `deep_timeout=` in the library.
|
|
42
|
+
- More of what Pyxel refuses as it loads a config is refused without running
|
|
43
|
+
it: readout `times` that are zero, not increasing, empty, or not below
|
|
44
|
+
`start_time`; a custom observation with no file of values; and a
|
|
45
|
+
`charge_to_volt` value outside Pyxel's range.
|
|
46
|
+
- What stops a run once it has started is refused too: a pipeline with no step
|
|
47
|
+
to run, a `save_data_to_file` bucket Pyxel cannot save, an observation
|
|
48
|
+
parameter whose key or values Pyxel cannot use, a sweep whose parameters are
|
|
49
|
+
all disabled, and a model missing what it reads from the detector (such as
|
|
50
|
+
`dark_current` with no temperature).
|
|
51
|
+
- A focal plane's `scene_generation` steps are checked: their keys and their
|
|
52
|
+
`func`. So is a plane's geometry, where `height: 0` ends in a singular matrix
|
|
53
|
+
at run, and its readout, with the same rules as a flat config's.
|
|
54
|
+
- A `func` with no dot, with a trailing dot, or under a misspelled `pyxel.model.`
|
|
55
|
+
is refused, on flat configs and on tiles alike, since Pyxel cannot import it.
|
|
56
|
+
|
|
57
|
+
### Changed
|
|
58
|
+
|
|
59
|
+
- `validate` reads a readout's `times` the way Pyxel does, so a plane accepts
|
|
60
|
+
`numpy.linspace(1, 3, 3)`, `times_from_file` and `exposure: {}`, all of which
|
|
61
|
+
Pyxel runs.
|
|
62
|
+
- A step that is not a known model answers to the schema's generic branch. A
|
|
63
|
+
user's own model with `enabled: maybe` gets one finding instead of 21, and
|
|
64
|
+
`func: 123` gets one that names `func`.
|
|
65
|
+
- `-n` on `search` must be a positive number; 0 and negative numbers exit 2.
|
|
66
|
+
- `pyxel-config-mcp` without the `mcp` extra explains the fix, as
|
|
67
|
+
`pyxel-config mcp` does, rather than showing a traceback.
|
|
68
|
+
|
|
69
|
+
### Fixed
|
|
70
|
+
|
|
71
|
+
- Text Pyxel's reader cannot read is a finding at its line rather than an
|
|
72
|
+
internal error: `2026-13-45`, `!!int abc`, `0b_` and the like. So are a `row`
|
|
73
|
+
of hundreds of digits, a key holding a slash or written as both `1` and `"1"`,
|
|
74
|
+
a tile named `"²"`, a non-text stage in `fix`, and `range()` of a huge number
|
|
75
|
+
in `--deep`.
|
|
76
|
+
- `fix --json` works on a config holding `!!binary`, and `fix` on an unreadable
|
|
77
|
+
encoding reports it and exits as `validate` does.
|
|
78
|
+
- `validate --deep --strict` with no Pyxel installed exits 3, as the README says.
|
|
79
|
+
- A reader closing the pipe early on Windows no longer turns into exit 120.
|
|
80
|
+
- `params` takes the full path that `list_models` hands out.
|
|
81
|
+
- `explain` gives a next step on every finding, run rules and missing required
|
|
82
|
+
fields included.
|
|
83
|
+
- `fix` gives the same suggestion on every run, and never suggests the same name
|
|
84
|
+
it just refused. A `func` of 20,000 characters no longer takes seconds.
|
|
85
|
+
- A merging map shallower than its anchor is no longer reported as a duplicate
|
|
86
|
+
key.
|
|
87
|
+
|
|
88
|
+
## [0.6.1] - 2026-10-14
|
|
89
|
+
|
|
90
|
+
### Added
|
|
91
|
+
|
|
92
|
+
- A documentation site at https://pyxel-config-lab-ede25c.gitlab.io/docs/:
|
|
93
|
+
installation, a quickstart, guides to the command line, the library, the MCP
|
|
94
|
+
server and semantic search, how validation works, and an API reference read
|
|
95
|
+
from the docstrings. Its guide pages include sections of the README, so the
|
|
96
|
+
two cannot say different things, and the quickstart's printed output is a
|
|
97
|
+
test (`tests/test_docs_quickstart.py`).
|
|
98
|
+
- NumPy-style docstrings on every public function and result type.
|
|
99
|
+
- A `docs` extra with what builds the site.
|
|
100
|
+
- A pipeline step without `func` is refused: Pyxel builds every step from it,
|
|
101
|
+
a disabled one included, although its schema leaves it optional.
|
|
102
|
+
- A focal-plane tile with more than one detector block is refused, as Pyxel's
|
|
103
|
+
tile loader refuses it, and only Pyxel's four detector keys count as a
|
|
104
|
+
detector block.
|
|
105
|
+
- `model_parameters(model, stage=None)`, `pyxel-config params` and the
|
|
106
|
+
`get_pyxel_model_parameters` MCP tool cover every model the bundled schema
|
|
107
|
+
accepts (`glow`, the CMOS noise models, `load_detector` and `save_detector`
|
|
108
|
+
among the 19 that had nothing). Each argument carries its type, `required`,
|
|
109
|
+
`has_default`, Pyxel's own `default` and the `example` value Pyxel's example
|
|
110
|
+
configs use. `stage` picks between the two stages a name such as
|
|
111
|
+
`simple_collection` exists in.
|
|
112
|
+
|
|
113
|
+
### Changed
|
|
114
|
+
|
|
115
|
+
- The package's Documentation link points at the documentation site instead
|
|
116
|
+
of the README.
|
|
117
|
+
- Text that cannot be read as a config (a YAML syntax error, a key written
|
|
118
|
+
twice, an alias bomb, nesting hundreds of levels deep, text that is not
|
|
119
|
+
UTF-8) is a finding in the `validate` and `explain` reports, with exit code
|
|
120
|
+
1, rather than stopping the run with exit code 3. One such file no longer
|
|
121
|
+
leaves a SARIF or Code Quality report empty. A file that cannot be opened is
|
|
122
|
+
listed in the report too, and the run still exits with 3.
|
|
123
|
+
- A file saved as UTF-16 or UTF-32 (as Windows PowerShell 5.1's `>` writes
|
|
124
|
+
it) is an error, since Pyxel reads a config file as UTF-8 only. Its content
|
|
125
|
+
is still checked.
|
|
126
|
+
- `ParameterInfo.default` is Pyxel's own default rather than the catalogue's
|
|
127
|
+
example value, which is now `ParameterInfo.example`. A step that leaves an
|
|
128
|
+
argument out gets the default; writing the example overrides it (for
|
|
129
|
+
`simple_conversion`'s `quantum_efficiency`, the detector's own value).
|
|
130
|
+
Types are spelled as Python spells them: `float`, `list[int] | null`.
|
|
131
|
+
- A number written as text, such as `1e3`, is reported only where text is
|
|
132
|
+
not what the field takes: a step's `name` or an output folder is left
|
|
133
|
+
alone, while a number field, or one that takes a number or a file name
|
|
134
|
+
(`charge_to_volt`'s `value`), still is.
|
|
135
|
+
- `fix` refuses `-w` and `-o FILE` together (exit code 2) instead of quietly
|
|
136
|
+
repairing in place. With `-o` or to stdout, a config with nothing to repair
|
|
137
|
+
is written exactly as it was, comments included.
|
|
138
|
+
|
|
139
|
+
### Fixed
|
|
140
|
+
|
|
141
|
+
- `.nan` and `.inf` in a detector field Pyxel bounds (temperature, quantum
|
|
142
|
+
efficiency, full well capacity, the sizes) are refused, as Pyxel's own range
|
|
143
|
+
checks refuse them.
|
|
144
|
+
- A top-level key that is not text (`yes:`, `1:`, `~:`) no longer crashes
|
|
145
|
+
`validate_config`, `explain_config` or `autofix`.
|
|
146
|
+
- SARIF and Code Quality reports read each file once: a report with 3,000
|
|
147
|
+
findings took over four minutes and now takes well under a second. A
|
|
148
|
+
finding inside a mapping merged with `<<: *anchor` lands on its own line,
|
|
149
|
+
and a file outside the working directory is a `file:` URI in SARIF.
|
|
150
|
+
- The deep check hands Pyxel the file's text exactly as written, comments
|
|
151
|
+
included, and the deep check and `fix` write files as bytes: a config saved
|
|
152
|
+
with Windows line endings no longer arrives with every line break doubled.
|
|
153
|
+
- A semantic search tried before the index is built no longer makes the
|
|
154
|
+
index look built to `doctor` and to every later search.
|
|
155
|
+
- The semantic search guide installs `"pyxel-config-core[rag]"` from PyPI
|
|
156
|
+
rather than an editable install that only works in a clone, and the README
|
|
157
|
+
says which engine each tutorial search uses.
|
|
158
|
+
|
|
159
|
+
### Security
|
|
160
|
+
|
|
161
|
+
- The deep check's safety gate refuses binary data (YAML `!!binary`) anywhere
|
|
162
|
+
in a config: Pyxel unpickles an APD converter function given that way, which
|
|
163
|
+
can run any code. Without trust it also refuses the files Pyxel opens while
|
|
164
|
+
it loads (`times_from_file`, a custom observation's `from_file`, an APD
|
|
165
|
+
converter's `filename`, URLs included) and a value range of more than a
|
|
166
|
+
million values. `--trust-config` (or `trusted=True`) lifts all three for a
|
|
167
|
+
config you wrote yourself; on the MCP server they apply whenever it was
|
|
168
|
+
started with `--allow-deep`.
|
|
169
|
+
|
|
170
|
+
## [0.6.0] - 2026-10-03
|
|
171
|
+
|
|
172
|
+
### Added
|
|
173
|
+
|
|
174
|
+
- `validate_config(config, deep=True)` hands the YAML to `pyxel.load()` when
|
|
175
|
+
Pyxel is installed and reports anything the loader rejects, which catches
|
|
176
|
+
what the JSON schema cannot express (readout times out of order, for
|
|
177
|
+
example).
|
|
178
|
+
`ValidationResult.deep_checked` says whether the loader actually ran. The
|
|
179
|
+
same switch is `--deep` on the `validate` and `explain` commands and
|
|
180
|
+
`deep=true` on the `validate_pyxel_config` and `explain_pyxel_config` MCP
|
|
181
|
+
tools.
|
|
182
|
+
- Loading runs part of a config: Pyxel evaluates text such as a readout's
|
|
183
|
+
`times` as Python and imports each model's module. Before it loads, the deep
|
|
184
|
+
check reads every such value and refuses to run the config unless each is
|
|
185
|
+
plain data or a known harmless call (`pyxel_config_core/expressions.py`).
|
|
186
|
+
`--trust-config` (or `trusted=True`) skips that reading for a config you
|
|
187
|
+
wrote yourself. On the MCP server the deep check is off unless the server is
|
|
188
|
+
started with `pyxel-config mcp --allow-deep`.
|
|
189
|
+
- The deep check names the Pyxel that judged the config:
|
|
190
|
+
`ValidationResult.deep_pyxel_version` and `Explanation.deep_pyxel_version`
|
|
191
|
+
carry the installed release whose loader ran, the summary says "and loads
|
|
192
|
+
in Pyxel 3.0.2", and the CLI's report and JSON say the same. Warnings
|
|
193
|
+
Pyxel raises while loading (those Python shows a user, not its own
|
|
194
|
+
deprecation notices) are reported as warning findings.
|
|
195
|
+
- `--deep` that cannot run (Pyxel missing, or installed but failing to import,
|
|
196
|
+
with the real import error named) exits with 3, "could not run", instead of
|
|
197
|
+
passing with 0. Any unexpected error also exits with 3, never with 1, which
|
|
198
|
+
means "the config has errors".
|
|
199
|
+
- `explain_config` returns an `Explanation`: `valid`, a one-sentence `summary`
|
|
200
|
+
("This CCD exposure config has 2 problems in the charge_generation stage"),
|
|
201
|
+
and the diagnostics, each carrying a concrete `next_step` (the model name to
|
|
202
|
+
rename to, the accepted types, the section to add, the release that renamed
|
|
203
|
+
a field).
|
|
204
|
+
- `pyxel_config_core/config_shape.py`, the Python port of the browser app's
|
|
205
|
+
`configShape.js`: it names the running mode and detector a config uses,
|
|
206
|
+
reports a missing or duplicated one, and offers a did-you-mean for a
|
|
207
|
+
misspelled top-level key (`ccd_detecor`, `exposre`). The root-level anyOf
|
|
208
|
+
chorus ("'ccd_detector' is a required property", four times) is gone.
|
|
209
|
+
- `--format {text,json,sarif,codequality}` on `validate` and `explain`.
|
|
210
|
+
`--json` remains as the short spelling of `--format json`. SARIF 2.1.0 and
|
|
211
|
+
GitLab Code Quality reports carry the line of the offending key, found by
|
|
212
|
+
walking the YAML.
|
|
213
|
+
- `pyxel_config_core/data/BUNDLE.json`, a manifest naming the Pyxel release
|
|
214
|
+
the bundled schema was generated from and the schema's SHA-256.
|
|
215
|
+
`schema_version()` exposes it, `ValidationResult.pyxel_version` and
|
|
216
|
+
`Explanation.pyxel_version` carry it on every verdict, and `doctor` prints
|
|
217
|
+
it alongside whether the shipped schema still matches the manifest.
|
|
218
|
+
- `Diagnostic.category` (`schema`, `func`, `shape`, `advisory`, `pyxel-load`),
|
|
219
|
+
which is the SARIF rule id and the Code Quality check name.
|
|
220
|
+
- `search_pyxel_tutorials` takes an explicit `semantic: bool = False`; it was
|
|
221
|
+
documented as keyword search but silently used the vector index when one
|
|
222
|
+
existed.
|
|
223
|
+
- `py.typed`, `[tool.ruff]` and `[tool.mypy]` configuration, a `dev` extra,
|
|
224
|
+
and Python 3.13 in the classifiers.
|
|
225
|
+
- A `.pre-commit-hooks.yaml` at the repo root exposing `pyxel-config-validate`.
|
|
226
|
+
- `scripts/refresh_bundle.py` at the repo root: the one reproducible command
|
|
227
|
+
for upgrading every bundled artifact to a new Pyxel release, with `--check`
|
|
228
|
+
for CI.
|
|
229
|
+
|
|
230
|
+
- Run rules (`run_rules.py`): what Pyxel 3.0.2 refuses at load or stops on at
|
|
231
|
+
run time although its schema accepts it, reported as errors in the new
|
|
232
|
+
`pyxel-rule` category. A readout with both `times` and `times_from_file`, a
|
|
233
|
+
calibration with both `weights` and `weights_from_file`, an observation with
|
|
234
|
+
no parameters, `simple_measurement` with neither a `gain` nor a detector
|
|
235
|
+
`charge_to_volt`, `simple_amplifier` without `pre_amplification`, and
|
|
236
|
+
`simple_adc` without its ADC settings. The browser applies the same rules,
|
|
237
|
+
and CI runs a fixture for each through the real Pyxel.
|
|
238
|
+
- A run rule for whole numbers written as decimals where Pyxel refuses one:
|
|
239
|
+
a detector's `row` or `col` and a CCD's `image_row` or `overscan_row` stop
|
|
240
|
+
`pyxel.load()` when written `128.0`, and an exposure's `pipeline_seed`
|
|
241
|
+
stops the run. Fields Pyxel takes a decimal in (`adc_bit_resolution`, a
|
|
242
|
+
wavelength's `resolution`) are left alone.
|
|
243
|
+
- A run rule for a model whose own code refuses the config's detector
|
|
244
|
+
class: 19 of Pyxel 3.0.2's models check the class and raise a TypeError
|
|
245
|
+
on any other (`cdm` on a CMOS detector, `apd_gain` on a CCD). Each was
|
|
246
|
+
found by calling the model on every class, and CI repeats that against
|
|
247
|
+
the installed Pyxel. Models Pyxel's metadata restricts but whose code runs
|
|
248
|
+
on any detector are left alone.
|
|
249
|
+
- Focal plane arrays, which the Config Lab exports and the bundled schema
|
|
250
|
+
has no branch for, are validated instead of refused as a config missing
|
|
251
|
+
its detector and pipeline (`pyxel_config_core/fpa.py`). The plane is
|
|
252
|
+
checked against Pyxel's focal-plane loader as the browser checks it (one
|
|
253
|
+
running mode, exposure only; a physical geometry with one scale above 0;
|
|
254
|
+
tile IDs 1..N; positions as mappings with an angle of 0, 90, 180 or 270;
|
|
255
|
+
a plane-wide scene; nothing beside `focal_plane_array`), and each tile is
|
|
256
|
+
validated against the schema and the run rules as the flat config Pyxel
|
|
257
|
+
builds it from. Every finding names its tile and its path in the plane; a
|
|
258
|
+
finding in the plane's running mode is said once. `fix` repairs model
|
|
259
|
+
names inside tiles, `explain` says which tiles hold the problems, and the
|
|
260
|
+
deep check reads every tile and the plane-wide scene before Pyxel loads
|
|
261
|
+
the plane. The pre-commit hook and the MCP tools follow.
|
|
262
|
+
|
|
263
|
+
### Changed
|
|
264
|
+
|
|
265
|
+
- Schema errors are grouped by path. The anyOf alternatives of a single field
|
|
266
|
+
collapse into one line naming every accepted type ("'x' is not one of the
|
|
267
|
+
accepted types: number, object, null"), at most eight paths are listed, and
|
|
268
|
+
a closing diagnostic counts what was left out. Previously the first five
|
|
269
|
+
unique (path, message) pairs were shown and the rest silently dropped.
|
|
270
|
+
- A pipeline step whose `func` is known is validated against that model's own
|
|
271
|
+
definition, so a mistyped argument reports as itself instead of alongside
|
|
272
|
+
the required arguments of every other model in the stage.
|
|
273
|
+
- The stale-detector heuristic in the advisory warnings now looks for any
|
|
274
|
+
`*_detector` key rather than requiring a `geometry` block under it.
|
|
275
|
+
- `search` exits 4 on zero hits with `--json` too; it was 0.
|
|
276
|
+
- `rag.semantic_search` reuses one embedder and one Qdrant client per index
|
|
277
|
+
directory instead of building both on every call.
|
|
278
|
+
- The bundled `tests/galaxy_config.yaml` fixture is valid under Pyxel 3.0.2
|
|
279
|
+
(`charge_to_volt` instead of the 2.x `charge_to_volt_conversion`).
|
|
280
|
+
|
|
281
|
+
### Deprecated
|
|
282
|
+
|
|
283
|
+
- The `pyxel-config-index` console script. It prints a notice and forwards
|
|
284
|
+
to `pyxel-config index`, which is the same operation.
|
|
285
|
+
|
|
286
|
+
### Fixed
|
|
287
|
+
|
|
288
|
+
- A model of the user's own (a `func` outside `pyxel.`, which Pyxel's schema
|
|
289
|
+
accepts through its generic ModelFunction branch) is no longer reported as
|
|
290
|
+
unknown, and `fix` no longer rewrites it into the built-in it resembles. A
|
|
291
|
+
typo under `pyxel.` is still caught.
|
|
292
|
+
- `pyxel-config fix --json -w` and `fix --json -o FILE` never wrote the
|
|
293
|
+
repaired config; the JSON branch returned before the write.
|
|
294
|
+
- `autofix` on a misspelled stage key moved the steps to the owning stage but
|
|
295
|
+
left the empty misspelled key behind, so the "fixed" config still failed
|
|
296
|
+
with "Additional properties are not allowed".
|
|
297
|
+
- Text that cannot be read as a config (a YAML syntax error, or a document
|
|
298
|
+
that is not a mapping) made `validate_config`, `explain_config` and
|
|
299
|
+
`autofix` raise, so an MCP client got a bare tool failure with no reason.
|
|
300
|
+
Each now returns a finding in the new `yaml` category that says what is
|
|
301
|
+
wrong and on which line.
|
|
302
|
+
- A few hundred bytes of nested YAML aliases load into a structure that
|
|
303
|
+
walks as tens of millions of values, and validating it kept the CLI, the
|
|
304
|
+
pre-commit hook or the MCP server busy for minutes. Text that expands past
|
|
305
|
+
its own length (or 100,000 values, whichever is larger) is now refused
|
|
306
|
+
before anything walks it (`pyxel_config_core/yaml_read.py`); no config
|
|
307
|
+
without aliases can reach that.
|
|
308
|
+
- A reader that closed the pipe early (`pyxel-config validate x.yaml | head`)
|
|
309
|
+
turned a failing check into exit 0. The verdict's exit code now stands.
|
|
310
|
+
- A config saved by Windows PowerShell 5.1's `>` or `Out-File` (UTF-16 with a
|
|
311
|
+
byte order mark) crashed the command line with exit 1. Files and stdin are
|
|
312
|
+
decoded by their byte order mark (UTF-8, UTF-16 or UTF-32), and other text
|
|
313
|
+
that is not UTF-8 is refused with exit 3, naming the byte that failed.
|
|
314
|
+
- `fix -w` wrote back a config with nothing to repair, which dropped its
|
|
315
|
+
comments and formatting. Such a config is now left exactly as it is.
|
|
316
|
+
- `fix -o -` and `tutorial --raw` wrote through the console's code page, so on
|
|
317
|
+
Windows a redirect turned characters outside it into question marks. Both
|
|
318
|
+
write UTF-8.
|
|
319
|
+
- A key written twice in one mapping (a second `pipeline:` block, say) was
|
|
320
|
+
accepted, while Pyxel keeps only the last. The reader now refuses it and
|
|
321
|
+
names both lines; keys a merge (`<<`) brings in may still be overridden.
|
|
322
|
+
- `fix` reported no remaining problems for any config without a root
|
|
323
|
+
`pipeline`, so it exited 0 on a config missing its pipeline. It now
|
|
324
|
+
reports the full verdict after its repairs, whatever the config holds.
|
|
325
|
+
- SARIF and Code Quality reports named each file as typed on the command
|
|
326
|
+
line, so a report written on Windows carried backslashes and pointed at
|
|
327
|
+
nothing on a CI runner, and stdin was "-". Files are now named relative to
|
|
328
|
+
the working directory with forward slashes (a `file:` URI in SARIF when
|
|
329
|
+
outside it, percent-encoded in SARIF either way), and stdin is "stdin".
|
|
330
|
+
- The `rag` extra allowed qdrant-client 1.7, but semantic search calls
|
|
331
|
+
`query_points` (added in 1.10), so with 1.7 to 1.9 every search fell back
|
|
332
|
+
to keywords with only "AttributeError" as the reason. The floor is now
|
|
333
|
+
1.10, an older client is named with the command that fixes it, and a
|
|
334
|
+
degraded result carries the cause's message.
|
|
335
|
+
- The pre-commit hook checked every YAML file by default, so a repository's
|
|
336
|
+
own `.gitlab-ci.yml` (or a GitHub workflow) failed the commit. It now
|
|
337
|
+
leaves the common CI and tooling YAML files alone.
|
|
338
|
+
- The sdist shipped the test suite without the three configs it reads, so
|
|
339
|
+
its tests stopped at collection. A MANIFEST.in now adds them and the
|
|
340
|
+
conftest; the cross-language tests skip outside the repository.
|
|
341
|
+
- The bundled schema and tutorials reached the wheel only because setuptools
|
|
342
|
+
guessed at their folders, with a warning that a later release may stop
|
|
343
|
+
guessing. Both folders are now declared packages, and a test holds every
|
|
344
|
+
file in the package to the declared list.
|
|
345
|
+
- The README's GitLab CI recipe ran the plain check first, so a failing
|
|
346
|
+
verdict stopped the job before the Code Quality report was written. The
|
|
347
|
+
report now comes first and is uploaded with `when: always`.
|
|
348
|
+
|
|
349
|
+
## [0.5.0] - 2026-09-19
|
|
350
|
+
|
|
351
|
+
### Added
|
|
352
|
+
|
|
353
|
+
- The `pyxel-config` command line: `validate`, `explain`, `fix`, `models`,
|
|
354
|
+
`params`, `tutorial`, `search`, `index`, `mcp`, `doctor` and `banner`, with
|
|
355
|
+
the exit code as the verdict and stdout kept clean for pipes.
|
|
356
|
+
|
|
357
|
+
[Unreleased]: https://gitlab.com/dobybaxter127/pyxel-config-lab/-/compare/core-v0.7.0...main
|
|
358
|
+
[0.7.0]: https://gitlab.com/dobybaxter127/pyxel-config-lab/-/tags/core-v0.7.0
|
|
359
|
+
[0.6.1]: https://gitlab.com/dobybaxter127/pyxel-config-lab/-/tags/core-v0.6.1
|
|
360
|
+
[0.6.0]: https://gitlab.com/dobybaxter127/pyxel-config-lab/-/tags/core-v0.6.0
|
|
361
|
+
[0.5.0]: https://pypi.org/project/pyxel-config-core/0.5.0/
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Doby Baxter
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# What the sdist carries beyond the package and its data: the test suite with
|
|
2
|
+
# the configs it reads and the conftest that points it at this copy, so the
|
|
3
|
+
# tests run from an unpacked sdist. The cross-language fixtures live at the
|
|
4
|
+
# repository root; the tests that need them skip outside it.
|
|
5
|
+
include conftest.py
|
|
6
|
+
include CHANGELOG.md
|
|
7
|
+
recursive-include tests *.py *.yaml
|