1+ # /// script
2+ # requires-python = ">=3.11"
3+ # dependencies = [
4+ # "parse",
5+ # "pydantic",
6+ # "pydantic-settings",
7+ # ]
8+ # ///
19# pylint: disable=unused-argument
210# pylint: disable=no-self-use
311# pylint: disable=no-name-in-module
412
13+ import importlib .util
14+ import inspect
515import json
616from datetime import timedelta
717from pathlib import Path
18+ from types import ModuleType
819from typing import Final
920
1021from parse import Result , parse
2637assert _LOCUST_FILES_DIR .is_dir ()
2738
2839
40+ def _check_load_and_instantiate_settings_classes (file_path : str ):
41+ module_name = Path (file_path ).stem
42+ spec = importlib .util .spec_from_file_location (module_name , file_path )
43+ if spec is None or spec .loader is None :
44+ msg = f"Invalid { file_path = } "
45+ raise ValueError (msg )
46+
47+ module : ModuleType = importlib .util .module_from_spec (spec )
48+
49+ # Execute the module in its own namespace
50+ try :
51+ spec .loader .exec_module (module )
52+ except Exception as e :
53+ msg = f"Failed to load module { module_name } from { file_path } "
54+ raise ValueError (msg ) from e
55+
56+ # Filter subclasses of BaseSettings
57+ settings_classes = [
58+ obj
59+ for _ , obj in inspect .getmembers (module , inspect .isclass )
60+ if issubclass (obj , BaseSettings ) and obj is not BaseSettings
61+ ]
62+
63+ for settings_class in settings_classes :
64+ try :
65+ settings_class ()
66+ except Exception as e :
67+ msg = f"Missing env vars for { settings_class .__name__ } in { file_path = } : { e } "
68+ raise ValueError (msg ) from e
69+
70+
2971class LocustSettings (BaseSettings ):
3072 model_config = SettingsConfigDict (cli_parse_args = True )
3173
@@ -44,8 +86,8 @@ class LocustSettings(BaseSettings):
4486 LOCUST_RUN_TIME : timedelta
4587 LOCUST_SPAWN_RATE : PositiveInt = Field (default = 20 )
4688
47- # Options for Timescale + Grafana Dashboards
48- # SEE https://github.com/SvenskaSpel/locust-plugins/blob /master/locust_plugins/timescale/
89+ # Timescale: Log and graph results using TimescaleDB and Grafana dashboards
90+ # SEE https://github.com/SvenskaSpel/locust-plugins/tree /master/locust_plugins/dashboards
4991 #
5092 LOCUST_TIMESCALE : NonNegativeInt = Field (
5193 default = 1 ,
@@ -87,6 +129,10 @@ def _validate_locust_file(cls, v: Path) -> Path:
87129 if not v .is_relative_to (_LOCUST_FILES_DIR ):
88130 msg = f"{ v } must be a test file relative to { _LOCUST_FILES_DIR } "
89131 raise ValueError (msg )
132+
133+ # NOTE: CHECK that all the env-vars are defined for this test
134+ # _check_load_and_instantiate_settings_classes(f"{v}")
135+
90136 return v .relative_to (_TEST_DIR )
91137
92138 @field_serializer ("LOCUST_RUN_TIME" )
0 commit comments