gammasimtools 0.22.0__py3-none-any.whl → 0.24.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.
- {gammasimtools-0.22.0.dist-info → gammasimtools-0.24.0.dist-info}/METADATA +2 -1
- {gammasimtools-0.22.0.dist-info → gammasimtools-0.24.0.dist-info}/RECORD +128 -125
- simtools/_version.py +2 -2
- simtools/application_control.py +118 -0
- simtools/applications/calculate_incident_angles.py +17 -22
- simtools/applications/convert_all_model_parameters_from_simtel.py +28 -43
- simtools/applications/convert_geo_coordinates_of_array_elements.py +26 -45
- simtools/applications/convert_model_parameter_from_simtel.py +21 -41
- simtools/applications/db_add_file_to_db.py +13 -14
- simtools/applications/db_add_simulation_model_from_repository_to_db.py +20 -33
- simtools/applications/db_add_value_from_json_to_db.py +29 -24
- simtools/applications/db_development_tools/write_array_elements_positions_to_repository.py +20 -35
- simtools/applications/db_generate_compound_indexes.py +11 -13
- simtools/applications/db_get_array_layouts_from_db.py +20 -40
- simtools/applications/db_get_file_from_db.py +15 -17
- simtools/applications/db_get_parameter_from_db.py +33 -35
- simtools/applications/db_inspect_databases.py +13 -12
- simtools/applications/db_upload_model_repository.py +13 -31
- simtools/applications/derive_ctao_array_layouts.py +16 -21
- simtools/applications/derive_mirror_rnda.py +9 -14
- simtools/applications/derive_photon_electron_spectrum.py +7 -10
- simtools/applications/derive_psf_parameters.py +13 -20
- simtools/applications/derive_trigger_rates.py +6 -9
- simtools/applications/docs_produce_array_element_report.py +22 -23
- simtools/applications/docs_produce_calibration_reports.py +26 -24
- simtools/applications/docs_produce_model_parameter_reports.py +15 -22
- simtools/applications/docs_produce_simulation_configuration_report.py +21 -22
- simtools/applications/generate_array_config.py +14 -33
- simtools/applications/generate_corsika_histograms.py +22 -43
- simtools/applications/generate_default_metadata.py +15 -36
- simtools/applications/generate_regular_arrays.py +11 -15
- simtools/applications/generate_simtel_event_data.py +23 -33
- simtools/applications/maintain_simulation_model_add_production.py +20 -37
- simtools/applications/maintain_simulation_model_compare_productions.py +10 -12
- simtools/applications/maintain_simulation_model_verify_production_tables.py +8 -11
- simtools/applications/merge_tables.py +14 -23
- simtools/applications/plot_array_layout.py +77 -54
- simtools/applications/plot_simtel_events.py +11 -13
- simtools/applications/plot_tabular_data.py +17 -38
- simtools/applications/plot_tabular_data_for_model_parameter.py +16 -23
- simtools/applications/print_version.py +14 -42
- simtools/applications/production_derive_corsika_limits.py +5 -9
- simtools/applications/production_derive_statistics.py +12 -25
- simtools/applications/production_generate_grid.py +20 -48
- simtools/applications/production_merge_corsika_limits.py +17 -21
- simtools/applications/run_application.py +12 -32
- simtools/applications/simulate_flasher.py +21 -25
- simtools/applications/simulate_illuminator.py +7 -14
- simtools/applications/simulate_pedestals.py +13 -13
- simtools/applications/simulate_prod.py +21 -33
- simtools/applications/simulate_prod_htcondor_generator.py +11 -25
- simtools/applications/submit_array_layouts.py +16 -19
- simtools/applications/submit_data_from_external.py +18 -34
- simtools/applications/submit_model_parameter_from_external.py +27 -40
- simtools/applications/validate_camera_efficiency.py +23 -21
- simtools/applications/validate_camera_fov.py +21 -26
- simtools/applications/validate_cumulative_psf.py +27 -35
- simtools/applications/validate_file_using_schema.py +15 -33
- simtools/applications/validate_optics.py +27 -33
- simtools/camera/camera_efficiency.py +0 -2
- simtools/configuration/commandline_parser.py +39 -13
- simtools/configuration/configurator.py +1 -6
- simtools/corsika/corsika_config.py +2 -9
- simtools/data_model/data_reader.py +0 -2
- simtools/data_model/metadata_collector.py +0 -2
- simtools/data_model/model_data_writer.py +1 -3
- simtools/data_model/schema.py +36 -34
- simtools/data_model/validate_data.py +0 -2
- simtools/db/db_handler.py +61 -296
- simtools/db/db_model_upload.py +1 -1
- simtools/db/mongo_db.py +535 -0
- simtools/dependencies.py +33 -8
- simtools/io/hdf5_handler.py +0 -5
- simtools/io/legacy_data_handler.py +0 -5
- simtools/job_execution/job_manager.py +0 -3
- simtools/layout/array_layout.py +7 -9
- simtools/layout/array_layout_utils.py +3 -3
- simtools/layout/telescope_position.py +0 -2
- simtools/model/array_model.py +38 -71
- simtools/model/calibration_model.py +12 -11
- simtools/model/camera.py +0 -2
- simtools/model/mirrors.py +0 -2
- simtools/model/model_parameter.py +200 -140
- simtools/model/model_repository.py +159 -35
- simtools/model/model_utils.py +3 -8
- simtools/model/site_model.py +59 -29
- simtools/model/telescope_model.py +21 -15
- simtools/production_configuration/calculate_statistical_uncertainties_grid_point.py +0 -2
- simtools/production_configuration/derive_production_statistics.py +0 -2
- simtools/production_configuration/interpolation_handler.py +0 -2
- simtools/ray_tracing/mirror_panel_psf.py +4 -4
- simtools/ray_tracing/psf_analysis.py +0 -2
- simtools/ray_tracing/psf_parameter_optimisation.py +1 -1
- simtools/ray_tracing/ray_tracing.py +0 -2
- simtools/reporting/docs_auto_report_generator.py +109 -1
- simtools/reporting/docs_read_parameters.py +4 -9
- simtools/runners/corsika_runner.py +0 -2
- simtools/runners/corsika_simtel_runner.py +0 -2
- simtools/runners/simtel_runner.py +0 -2
- simtools/schemas/model_parameters/transit_time_random.schema.yml +29 -0
- simtools/schemas/simulation_models_info.schema.yml +2 -1
- simtools/simtel/simtel_config_reader.py +0 -2
- simtools/simtel/simtel_config_writer.py +128 -33
- simtools/simtel/simtel_io_metadata.py +3 -3
- simtools/simtel/simulator_array.py +9 -21
- simtools/simtel/simulator_camera_efficiency.py +0 -2
- simtools/simtel/simulator_light_emission.py +1 -3
- simtools/simtel/simulator_ray_tracing.py +0 -2
- simtools/simulator.py +2 -6
- simtools/testing/assertions.py +52 -8
- simtools/testing/configuration.py +17 -4
- simtools/testing/validate_output.py +4 -8
- simtools/utils/general.py +5 -13
- simtools/utils/geometry.py +0 -5
- simtools/utils/names.py +1 -13
- simtools/utils/value_conversion.py +10 -5
- simtools/version.py +85 -0
- simtools/visualization/plot_array_layout.py +129 -23
- simtools/visualization/plot_incident_angles.py +0 -2
- simtools/visualization/plot_pixels.py +1 -1
- simtools/visualization/plot_psf.py +1 -1
- simtools/visualization/plot_simtel_events.py +0 -11
- simtools/visualization/plot_tables.py +1 -1
- simtools/visualization/visualize.py +0 -12
- {gammasimtools-0.22.0.dist-info → gammasimtools-0.24.0.dist-info}/WHEEL +0 -0
- {gammasimtools-0.22.0.dist-info → gammasimtools-0.24.0.dist-info}/entry_points.txt +0 -0
- {gammasimtools-0.22.0.dist-info → gammasimtools-0.24.0.dist-info}/licenses/LICENSE +0 -0
- {gammasimtools-0.22.0.dist-info → gammasimtools-0.24.0.dist-info}/top_level.txt +0 -0
simtools/simulator.py
CHANGED
|
@@ -22,11 +22,6 @@ from simtools.simtel.simulator_array import SimulatorArray
|
|
|
22
22
|
from simtools.testing.sim_telarray_metadata import assert_sim_telarray_metadata
|
|
23
23
|
from simtools.version import semver_to_int
|
|
24
24
|
|
|
25
|
-
__all__ = [
|
|
26
|
-
"InvalidRunsToSimulateError",
|
|
27
|
-
"Simulator",
|
|
28
|
-
]
|
|
29
|
-
|
|
30
25
|
|
|
31
26
|
class InvalidRunsToSimulateError(Exception):
|
|
32
27
|
"""Exception for invalid runs to simulate."""
|
|
@@ -130,7 +125,7 @@ class Simulator:
|
|
|
130
125
|
label=self.label,
|
|
131
126
|
site=self.args_dict.get("site"),
|
|
132
127
|
layout_name=self.args_dict.get("array_layout_name"),
|
|
133
|
-
|
|
128
|
+
db_config=self.db_config,
|
|
134
129
|
model_version=version,
|
|
135
130
|
sim_telarray_seeds={
|
|
136
131
|
"seed": self._get_seed_for_random_instrument_instances(
|
|
@@ -145,6 +140,7 @@ class Simulator:
|
|
|
145
140
|
calibration_device_types=self._get_calibration_device_types(
|
|
146
141
|
self.args_dict.get("run_mode")
|
|
147
142
|
),
|
|
143
|
+
overwrite_model_parameters=self.args_dict.get("overwrite_model_parameters", None),
|
|
148
144
|
)
|
|
149
145
|
for version in versions
|
|
150
146
|
]
|
simtools/testing/assertions.py
CHANGED
|
@@ -8,6 +8,8 @@ from pathlib import Path
|
|
|
8
8
|
import numpy as np
|
|
9
9
|
import yaml
|
|
10
10
|
|
|
11
|
+
from simtools.simtel.simtel_io_metadata import read_sim_telarray_metadata
|
|
12
|
+
|
|
11
13
|
_logger = logging.getLogger(__name__)
|
|
12
14
|
|
|
13
15
|
|
|
@@ -62,9 +64,9 @@ def assert_n_showers_and_energy_range(file):
|
|
|
62
64
|
|
|
63
65
|
simulated_energies = []
|
|
64
66
|
simulation_config = {}
|
|
65
|
-
with SimTelFile(file) as f:
|
|
67
|
+
with SimTelFile(file, skip_non_triggered=False) as f:
|
|
66
68
|
simulation_config = f.mc_run_headers[0]
|
|
67
|
-
for event in f
|
|
69
|
+
for event in f:
|
|
68
70
|
simulated_energies.append(event["mc_shower"]["energy"])
|
|
69
71
|
|
|
70
72
|
# The relative tolerance is set to 1% because ~0.5% shower simulations do not
|
|
@@ -124,7 +126,35 @@ def assert_expected_output(file, expected_output):
|
|
|
124
126
|
return True
|
|
125
127
|
|
|
126
128
|
|
|
127
|
-
def
|
|
129
|
+
def assert_expected_simtel_metadata(file, expected_metadata):
|
|
130
|
+
"""
|
|
131
|
+
Assert that expected metadata is present in the sim_telarray file.
|
|
132
|
+
|
|
133
|
+
Parameters
|
|
134
|
+
----------
|
|
135
|
+
file: Path
|
|
136
|
+
Path to the sim_telarray file.
|
|
137
|
+
expected_metadata: dict
|
|
138
|
+
Expected metadata values.
|
|
139
|
+
|
|
140
|
+
"""
|
|
141
|
+
global_meta, telescope_meta = read_sim_telarray_metadata(file)
|
|
142
|
+
|
|
143
|
+
for key, value in expected_metadata.items():
|
|
144
|
+
if key not in global_meta and key not in telescope_meta:
|
|
145
|
+
_logger.error(f"Metadata key {key} not found in sim_telarray file {file}")
|
|
146
|
+
return False
|
|
147
|
+
if key in global_meta and global_meta[key] != value:
|
|
148
|
+
_logger.error(
|
|
149
|
+
f"Metadata key {key} has value {global_meta[key]} instead of expected {value}"
|
|
150
|
+
)
|
|
151
|
+
return False
|
|
152
|
+
_logger.debug(f"Metadata key {key} matches expected value {value}")
|
|
153
|
+
|
|
154
|
+
return True
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def check_output_from_sim_telarray(file, file_test):
|
|
128
158
|
"""
|
|
129
159
|
Check that the sim_telarray simulation result is reasonable and matches the expected output.
|
|
130
160
|
|
|
@@ -132,20 +162,34 @@ def check_output_from_sim_telarray(file, expected_output):
|
|
|
132
162
|
----------
|
|
133
163
|
file: Path
|
|
134
164
|
Path to the sim_telarray file.
|
|
135
|
-
|
|
136
|
-
|
|
165
|
+
file_test: dict
|
|
166
|
+
File test description including expected output and metadata.
|
|
137
167
|
|
|
138
168
|
Raises
|
|
139
169
|
------
|
|
140
170
|
ValueError
|
|
141
171
|
If the file is not a zstd compressed file.
|
|
142
172
|
"""
|
|
173
|
+
if "expected_output" not in file_test and "expected_simtel_metadata" not in file_test:
|
|
174
|
+
_logger.debug(f"No expected output or metadata provided, skipping checks {file_test}")
|
|
175
|
+
return True
|
|
176
|
+
|
|
143
177
|
if file.suffix != ".zst":
|
|
144
178
|
raise ValueError(
|
|
145
179
|
f"Expected output file {file} is not a zstd compressed file "
|
|
146
180
|
f"(i.e., a sim_telarray file)."
|
|
147
181
|
)
|
|
148
182
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
183
|
+
assert_output = assert_metadata = True
|
|
184
|
+
|
|
185
|
+
if "expected_output" in file_test:
|
|
186
|
+
assert_output = assert_expected_output(
|
|
187
|
+
file=file, expected_output=file_test["expected_output"]
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
if "expected_simtel_metadata" in file_test:
|
|
191
|
+
assert_metadata = assert_expected_simtel_metadata(
|
|
192
|
+
file=file, expected_metadata=file_test["expected_simtel_metadata"]
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
return assert_n_showers_and_energy_range(file=file) and assert_output and assert_metadata
|
|
@@ -5,6 +5,7 @@ import os
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
|
|
7
7
|
import simtools.utils.general as gen
|
|
8
|
+
import simtools.version as simtools_version
|
|
8
9
|
from simtools.io import ascii_handler
|
|
9
10
|
|
|
10
11
|
_logger = logging.getLogger(__name__)
|
|
@@ -130,11 +131,23 @@ def configure(config, tmp_test_directory, request):
|
|
|
130
131
|
|
|
131
132
|
|
|
132
133
|
def _skip_test_for_model_version(config, model_version_requested):
|
|
133
|
-
"""
|
|
134
|
-
|
|
134
|
+
"""
|
|
135
|
+
Skip test if model version requested is not supported.
|
|
136
|
+
|
|
137
|
+
Compares full and major.minor version strings.
|
|
138
|
+
"""
|
|
139
|
+
if not (config.get("model_version_use_current") and model_version_requested):
|
|
135
140
|
return
|
|
136
|
-
model_version_config = config["configuration"]["model_version"]
|
|
137
|
-
|
|
141
|
+
model_version_config = str(config["configuration"]["model_version"])
|
|
142
|
+
|
|
143
|
+
if (
|
|
144
|
+
simtools_version.compare_versions(
|
|
145
|
+
model_version_requested,
|
|
146
|
+
model_version_config,
|
|
147
|
+
level=simtools_version.version_kind(model_version_requested),
|
|
148
|
+
)
|
|
149
|
+
!= 0
|
|
150
|
+
):
|
|
138
151
|
raise VersionError(
|
|
139
152
|
f"Model version requested {model_version_requested} not supported for this test"
|
|
140
153
|
)
|
|
@@ -117,11 +117,7 @@ def _validate_output_path_and_file(config, integration_file_tests):
|
|
|
117
117
|
except AssertionError as exc:
|
|
118
118
|
raise AssertionError(f"Output file {output_file_path} does not exist. ") from exc
|
|
119
119
|
|
|
120
|
-
|
|
121
|
-
assert assertions.check_output_from_sim_telarray(
|
|
122
|
-
output_file_path,
|
|
123
|
-
file_test["expected_output"],
|
|
124
|
-
)
|
|
120
|
+
assert assertions.check_output_from_sim_telarray(output_file_path, file_test)
|
|
125
121
|
|
|
126
122
|
|
|
127
123
|
def _validate_model_parameter_json_file(config, model_parameter_validation, db_config):
|
|
@@ -139,7 +135,7 @@ def _validate_model_parameter_json_file(config, model_parameter_validation, db_c
|
|
|
139
135
|
|
|
140
136
|
"""
|
|
141
137
|
_logger.info(f"Checking model parameter json file: {model_parameter_validation}")
|
|
142
|
-
db = db_handler.DatabaseHandler(
|
|
138
|
+
db = db_handler.DatabaseHandler(db_config=db_config)
|
|
143
139
|
|
|
144
140
|
reference_parameter_name = model_parameter_validation.get("reference_parameter_name")
|
|
145
141
|
|
|
@@ -346,7 +342,7 @@ def _validate_simtel_cfg_files(config, simtel_cfg_file):
|
|
|
346
342
|
f"Comparing simtel cfg files: {reference_file} and {test_file} "
|
|
347
343
|
f"for model version {config['configuration']['model_version']}"
|
|
348
344
|
)
|
|
349
|
-
|
|
345
|
+
assert _compare_simtel_cfg_files(reference_file, test_file)
|
|
350
346
|
|
|
351
347
|
|
|
352
348
|
def _compare_simtel_cfg_files(reference_file, test_file):
|
|
@@ -382,7 +378,7 @@ def _compare_simtel_cfg_files(reference_file, test_file):
|
|
|
382
378
|
return False
|
|
383
379
|
|
|
384
380
|
for ref_line, test_line in zip(reference_cfg, test_cfg):
|
|
385
|
-
if any(ignore in ref_line for ignore in ("config_release", "Label")):
|
|
381
|
+
if any(ignore in ref_line for ignore in ("config_release", "Label", "simtools_version")):
|
|
386
382
|
continue
|
|
387
383
|
if ref_line != test_line:
|
|
388
384
|
_logger.error(
|
simtools/utils/general.py
CHANGED
|
@@ -13,17 +13,6 @@ from urllib.parse import urlparse
|
|
|
13
13
|
|
|
14
14
|
import numpy as np
|
|
15
15
|
|
|
16
|
-
__all__ = [
|
|
17
|
-
"change_dict_keys_case",
|
|
18
|
-
"clear_default_sim_telarray_cfg_directories",
|
|
19
|
-
"collect_final_lines",
|
|
20
|
-
"collect_kwargs",
|
|
21
|
-
"get_log_excerpt",
|
|
22
|
-
"get_log_level_from_user",
|
|
23
|
-
"remove_substring_recursively_from_dict",
|
|
24
|
-
"set_default_kwargs",
|
|
25
|
-
]
|
|
26
|
-
|
|
27
16
|
_logger = logging.getLogger(__name__)
|
|
28
17
|
|
|
29
18
|
|
|
@@ -345,7 +334,7 @@ def resolve_file_patterns(file_names):
|
|
|
345
334
|
return _files
|
|
346
335
|
|
|
347
336
|
|
|
348
|
-
def pack_tar_file(tar_file_name, file_list):
|
|
337
|
+
def pack_tar_file(tar_file_name, file_list, sub_dir=None):
|
|
349
338
|
"""
|
|
350
339
|
Pack files into a tar.gz archive.
|
|
351
340
|
|
|
@@ -355,6 +344,8 @@ def pack_tar_file(tar_file_name, file_list):
|
|
|
355
344
|
Name of the output tar.gz file.
|
|
356
345
|
file_list: list
|
|
357
346
|
List of files to include in the archive.
|
|
347
|
+
sub_dir: str, optional
|
|
348
|
+
Subdirectory within the archive to place the files.
|
|
358
349
|
"""
|
|
359
350
|
file_list = [Path(f) for f in file_list]
|
|
360
351
|
base = Path(os.path.commonpath([f.resolve() for f in file_list]))
|
|
@@ -365,7 +356,8 @@ def pack_tar_file(tar_file_name, file_list):
|
|
|
365
356
|
|
|
366
357
|
with tarfile.open(tar_file_name, "w:gz") as tar:
|
|
367
358
|
for file in file_list:
|
|
368
|
-
|
|
359
|
+
arc_name = Path(sub_dir) / file.name if sub_dir else file.name
|
|
360
|
+
tar.add(file, arcname=str(arc_name))
|
|
369
361
|
|
|
370
362
|
|
|
371
363
|
def get_log_excerpt(log_file, n_last_lines=30):
|
simtools/utils/geometry.py
CHANGED
simtools/utils/names.py
CHANGED
|
@@ -28,18 +28,6 @@ from simtools.constants import (
|
|
|
28
28
|
|
|
29
29
|
_logger = logging.getLogger(__name__)
|
|
30
30
|
|
|
31
|
-
__all__ = [
|
|
32
|
-
"generate_file_name",
|
|
33
|
-
"get_array_element_type_from_name",
|
|
34
|
-
"get_site_from_array_element_name",
|
|
35
|
-
"sanitize_name",
|
|
36
|
-
"simtel_config_file_name",
|
|
37
|
-
"simtel_single_mirror_list_file_name",
|
|
38
|
-
"validate_array_element_id_name",
|
|
39
|
-
"validate_array_element_name",
|
|
40
|
-
"validate_site_name",
|
|
41
|
-
]
|
|
42
|
-
|
|
43
31
|
# Mapping of db collection names to class keys
|
|
44
32
|
db_collections_to_class_keys = {
|
|
45
33
|
"sites": ["Site"],
|
|
@@ -122,7 +110,7 @@ def site_names():
|
|
|
122
110
|
@cache
|
|
123
111
|
def array_element_design_types(array_element_type):
|
|
124
112
|
"""
|
|
125
|
-
Get array element
|
|
113
|
+
Get array element design type (e.g., 'design' or 'flashcam').
|
|
126
114
|
|
|
127
115
|
Default values are ['design', 'test'].
|
|
128
116
|
|
|
@@ -170,16 +170,21 @@ def get_value_as_quantity(value, unit):
|
|
|
170
170
|
|
|
171
171
|
Raises
|
|
172
172
|
------
|
|
173
|
-
|
|
173
|
+
ValueError
|
|
174
174
|
If the value cannot be converted to the given unit.
|
|
175
175
|
"""
|
|
176
176
|
if isinstance(value, u.Quantity):
|
|
177
177
|
try:
|
|
178
178
|
return value.to(unit)
|
|
179
|
-
except u.UnitConversionError:
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
179
|
+
except u.UnitConversionError as exc:
|
|
180
|
+
raise ValueError(f"Cannot convert {value} with unit {value.unit} to {unit}.") from exc
|
|
181
|
+
elif not isinstance(value, int | float):
|
|
182
|
+
return value
|
|
183
|
+
|
|
184
|
+
if unit is None or unit == "null":
|
|
185
|
+
return value * u.dimensionless_unscaled
|
|
186
|
+
|
|
187
|
+
return value * u.Unit(unit)
|
|
183
188
|
|
|
184
189
|
|
|
185
190
|
def _unit_as_string(unit):
|
simtools/version.py
CHANGED
|
@@ -4,8 +4,12 @@
|
|
|
4
4
|
# which is adapted from https://github.com/astropy/astropy/blob/master/astropy/version.py
|
|
5
5
|
# see https://github.com/astropy/astropy/pull/10774 for a discussion on why this needed.
|
|
6
6
|
|
|
7
|
+
from packaging.specifiers import SpecifierSet
|
|
7
8
|
from packaging.version import InvalidVersion, Version
|
|
8
9
|
|
|
10
|
+
MAJOR_MINOR_PATCH = "major.minor.patch"
|
|
11
|
+
MAJOR_MINOR = "major.minor"
|
|
12
|
+
|
|
9
13
|
try:
|
|
10
14
|
try:
|
|
11
15
|
from ._dev_version import version
|
|
@@ -128,3 +132,84 @@ def sort_versions(version_list, reverse=False):
|
|
|
128
132
|
return [str(v) for v in sorted(map(Version, version_list), reverse=reverse)]
|
|
129
133
|
except InvalidVersion as exc:
|
|
130
134
|
raise ValueError(f"Invalid version in list: {version_list}") from exc
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def version_kind(version_string):
|
|
138
|
+
"""
|
|
139
|
+
Determine the kind of version string.
|
|
140
|
+
|
|
141
|
+
Parameters
|
|
142
|
+
----------
|
|
143
|
+
version_string : str
|
|
144
|
+
The version string to analyze.
|
|
145
|
+
|
|
146
|
+
Returns
|
|
147
|
+
-------
|
|
148
|
+
str
|
|
149
|
+
The kind of version string ("major.minor", "major.minor.patch", or "major").
|
|
150
|
+
"""
|
|
151
|
+
try:
|
|
152
|
+
ver = Version(version_string)
|
|
153
|
+
except InvalidVersion as exc:
|
|
154
|
+
raise ValueError(f"Invalid version string: {version_string}") from exc
|
|
155
|
+
if ver.release and len(ver.release) >= 3:
|
|
156
|
+
return MAJOR_MINOR_PATCH
|
|
157
|
+
if len(ver.release) == 2:
|
|
158
|
+
return MAJOR_MINOR
|
|
159
|
+
return "major"
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def compare_versions(version_string_1, version_string_2, level=MAJOR_MINOR_PATCH):
|
|
163
|
+
"""
|
|
164
|
+
Compare two versions at the given level: "major", "major.minor", "major.minor.patch".
|
|
165
|
+
|
|
166
|
+
Parameters
|
|
167
|
+
----------
|
|
168
|
+
version_string_1 : str
|
|
169
|
+
First version string to compare.
|
|
170
|
+
version_string_2 : str
|
|
171
|
+
Second version string to compare.
|
|
172
|
+
level : str, optional
|
|
173
|
+
Level of comparison: "major", "major.minor", or "major.minor.patch"
|
|
174
|
+
|
|
175
|
+
Returns
|
|
176
|
+
-------
|
|
177
|
+
int
|
|
178
|
+
-1 if version_string_1 < version_string_2
|
|
179
|
+
0 if version_string_1 == version_string_2
|
|
180
|
+
1 if version_string_1 > version_string_2
|
|
181
|
+
"""
|
|
182
|
+
ver1 = Version(version_string_1).release
|
|
183
|
+
ver2 = Version(version_string_2).release
|
|
184
|
+
|
|
185
|
+
if level == "major":
|
|
186
|
+
ver1, ver2 = ver1[:1], ver2[:1]
|
|
187
|
+
elif level == MAJOR_MINOR:
|
|
188
|
+
ver1, ver2 = ver1[:2], ver2[:2]
|
|
189
|
+
elif level != MAJOR_MINOR_PATCH:
|
|
190
|
+
raise ValueError(f"Unknown level: {level}")
|
|
191
|
+
|
|
192
|
+
return (ver1 > ver2) - (ver1 < ver2)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def check_version_constraint(version_string, constraint):
|
|
196
|
+
"""
|
|
197
|
+
Check if a version satisfies a constraint.
|
|
198
|
+
|
|
199
|
+
Parameters
|
|
200
|
+
----------
|
|
201
|
+
version_string : str
|
|
202
|
+
The version string to check (e.g., "6.0.2").
|
|
203
|
+
constraint : str
|
|
204
|
+
The version constraint to check against (e.g., ">=6.0.0").
|
|
205
|
+
|
|
206
|
+
Returns
|
|
207
|
+
-------
|
|
208
|
+
bool
|
|
209
|
+
True if the version satisfies the constraint, False otherwise.
|
|
210
|
+
"""
|
|
211
|
+
spec = SpecifierSet(constraint.strip(), prereleases=True)
|
|
212
|
+
ver = Version(version_string)
|
|
213
|
+
if ver in spec:
|
|
214
|
+
return True
|
|
215
|
+
return False
|