Skip to content

Commit 54cd645

Browse files
refactor: use pathlib instead of os.path for cross-platform path handling
1 parent 7345283 commit 54cd645

4 files changed

Lines changed: 40 additions & 42 deletions

File tree

src/vipat_cli_scripts/generate_all.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import argparse
2-
import os
2+
from pathlib import Path
33

44
from vipat_cli_scripts.generate_driver_models import main as generate_driver_models
55
from vipat_cli_scripts.version_utils import ROOT_DIR, list_available_schema_versions, load_module
@@ -10,9 +10,9 @@
1010

1111
def main():
1212
args = parser.parse_args()
13-
schema_file = os.path.join(ROOT_DIR, "apps", "inventory", "model", "driver_schema", f"{args.version}.json")
13+
schema_file = Path(ROOT_DIR) / "apps" / "inventory" / "model" / "driver_schema" / f"{args.version}.json"
1414

15-
if not os.path.exists(schema_file):
15+
if not schema_file.exists():
1616
print(
1717
f"VideoIPath version {args.version} is currently not supported. Please create an issue on https://github.com/SWR-MoIP/VideoIPath-Automation-Tool/issues to request support for this version or use one of the following versions:"
1818
)
@@ -24,7 +24,8 @@ def main():
2424
generate_driver_models(schema_file)
2525

2626
# Note: Module should be loaded after generate_driver_models to ensure it imports the correct version of the drivers module
27-
generate_overloads_mod = load_module("generate_overloads", "src/vipat_cli_scripts/generate_overloads.py")
27+
generate_overloads_path = ROOT_DIR.parent / "vipat_cli_scripts" / "generate_overloads.py"
28+
generate_overloads_mod = load_module("generate_overloads", generate_overloads_path)
2829
generate_overloads = generate_overloads_mod.main
2930
generate_overloads()
3031

src/vipat_cli_scripts/generate_driver_models.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,33 @@
11
import argparse
22
import json
3-
import os
3+
from pathlib import Path
44

55
from vipat_cli_scripts.version_utils import ROOT_DIR, list_available_schema_versions, load_module
66

77
DEFAULT_VERSION = "2024.4.12"
8-
DEFAULT_SCHEMA_FILE = os.path.join(ROOT_DIR, "apps", "inventory", "model", "driver_schema", f"{DEFAULT_VERSION}.json")
9-
DEFAULT_OUTPUT_FILE = os.path.join(ROOT_DIR, "apps", "inventory", "model", "drivers.py")
8+
DEFAULT_SCHEMA_FILE = Path(ROOT_DIR) / "apps" / "inventory" / "model" / "driver_schema" / f"{DEFAULT_VERSION}.json"
9+
DEFAULT_OUTPUT_FILE = Path(ROOT_DIR) / "apps" / "inventory" / "model" / "drivers.py"
10+
1011

1112
parser = argparse.ArgumentParser(description="Generate Pydantic models from driver schema")
1213
parser.add_argument(
1314
"schema_file",
1415
nargs="?",
16+
type=Path,
1517
default=DEFAULT_SCHEMA_FILE,
1618
help="Path to the driver schema JSON file",
1719
)
1820
parser.add_argument(
1921
"output_file",
2022
nargs="?",
23+
type=Path,
2124
default=DEFAULT_OUTPUT_FILE,
2225
help="Path where the generated Python file will be saved",
2326
)
2427

2528

2629
def _generate_driver_model(driver_schema: dict) -> str:
27-
pmb_module = load_module("pydantic_model_builder", os.path.join(ROOT_DIR, "utils", "pydantic_model_builder.py"))
30+
pmb_module = load_module("pydantic_model_builder", Path(ROOT_DIR) / "utils" / "pydantic_model_builder.py")
2831
PydanticModelBuilder = pmb_module.PydanticModelBuilder
2932
PydanticModelField = pmb_module.PydanticModelField
3033

@@ -119,11 +122,9 @@ def format_value(value: str | int | float) -> str:
119122
return field["_schema"]["type"], None
120123

121124

122-
def main(
123-
schema_file: str = DEFAULT_SCHEMA_FILE,
124-
output_file: str = DEFAULT_OUTPUT_FILE,
125-
):
126-
schema = json.load(open(schema_file))
125+
def main(schema_file: Path = DEFAULT_SCHEMA_FILE, output_file: Path = DEFAULT_OUTPUT_FILE):
126+
with open(schema_file, "r", encoding="utf-8") as f:
127+
schema = json.load(f)
127128

128129
drivers = schema["data"]["status"]["system"]["drivers"]["_items"]
129130
driver_models = "\n\n".join([_generate_driver_model(driver) for driver in drivers])
@@ -135,12 +136,12 @@ def main(
135136
136137
# Notes:
137138
# - The name of the custom settings model follows the naming convention: CustomSettings_<driver_organization>_<driver_name>_<driver_version> => "." and "-" are replaced by "_"!
138-
# - Schema {schema_file.split("/")[-1]} is used as reference to define the custom settings model!
139+
# - Schema {Path(schema_file).name} is used as reference to define the custom settings model!
139140
# - The "driver_id" attribute is necessary for the discriminator, which is used to determine the correct model for the custom settings in DeviceConfiguration!
140141
# - The "alias" attribute is used to map the attribute to the correct key (with driver organization & name) in the JSON payload for the API!
141142
# - "DriverLiteral" is used to provide a list of all possible drivers in the IDEs IntelliSense!
142143
143-
SELECTED_SCHEMA_VERSION = "{schema_file.split("/")[-1].split(".json")[0]}"
144+
SELECTED_SCHEMA_VERSION = "{Path(schema_file).stem}"
144145
AVAILABLE_SCHEMA_VERSIONS = {list_available_schema_versions()}
145146
146147
class DriverCustomSettings(ABC, BaseModel, validate_assignment=True): ...
@@ -163,7 +164,7 @@ class DriverCustomSettings(ABC, BaseModel, validate_assignment=True): ...
163164
"""
164165
print("Drivers generated successfully!")
165166

166-
with open(output_file, "w") as f:
167+
with open(output_file, "w", encoding="utf-8") as f:
167168
f.write(code)
168169
print(f"Updated {output_file}")
169170

src/vipat_cli_scripts/generate_overloads.py

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,10 @@
1-
import os
21
import re
3-
from pathlib import Path
42
from typing import Callable
53

6-
from vipat_cli_scripts.version_utils import load_module
4+
from vipat_cli_scripts.version_utils import ROOT_DIR, load_module
75

8-
current_file = Path(__file__).resolve()
9-
ROOT_DIR = current_file.parent.parent / "videoipath_automation_tool"
10-
11-
12-
DRIVERS_MODULE = load_module(
13-
"drivers_module",
14-
os.path.join(ROOT_DIR, "apps", "inventory", "model", "drivers.py"),
15-
)
6+
drivers_path = ROOT_DIR / "apps" / "inventory" / "model" / "drivers.py"
7+
DRIVERS_MODULE = load_module("drivers_module", drivers_path)
168
DRIVER_ID_TO_CUSTOM_SETTINGS = DRIVERS_MODULE.DRIVER_ID_TO_CUSTOM_SETTINGS
179

1810

@@ -41,21 +33,24 @@ def generate_get_device_overloads() -> str:
4133

4234

4335
def generate_overloads(method: str, generate_overloads: Callable) -> None:
44-
FILE_PATH = os.path.join(ROOT_DIR, "apps", "inventory", "app", f"{method}.py")
36+
file_path = ROOT_DIR / "apps" / "inventory" / "app" / f"{method}.py"
37+
38+
if not file_path.exists():
39+
print(f"File not found: {file_path} ❌")
40+
return
4541

46-
with open(FILE_PATH, "r") as f:
47-
content = f.read()
42+
content = file_path.read_text()
4843

4944
overload_pattern = re.compile(
5045
r"# --------------------------------\n # Start Auto-Generated Overloads\n # --------------------------------\n(.*?)# ------------------------------\n # End Auto-Generated Overloads\n # ------------------------------",
5146
re.DOTALL,
5247
)
5348

5449
if not re.findall(overload_pattern, content):
55-
print(f"No overload section found in {FILE_PATH} ❌")
50+
print(f"No overload section found in {file_path} ❌")
5651
return
5752

58-
with open(FILE_PATH, "w") as f:
53+
with open(file_path, "w") as f:
5954
f.write(
6055
re.sub(
6156
overload_pattern,
@@ -64,7 +59,7 @@ def generate_overloads(method: str, generate_overloads: Callable) -> None:
6459
)
6560
)
6661

67-
print(f"Updated overloads in {FILE_PATH} ✅")
62+
print(f"Updated overloads in {file_path} ✅")
6863

6964

7065
def main():

src/vipat_cli_scripts/version_utils.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import importlib.util
2-
import os
32
from pathlib import Path
43
from types import ModuleType
4+
from typing import Union
55

66
from videoipath_automation_tool.apps.inventory.model.drivers import SELECTED_SCHEMA_VERSION
77

@@ -10,9 +10,9 @@
1010

1111

1212
def list_available_schema_versions() -> list[str]:
13-
schema_dir = os.path.join(ROOT_DIR, "apps", "inventory", "model", "driver_schema")
13+
schema_dir = ROOT_DIR / "apps" / "inventory" / "model" / "driver_schema"
1414
return sorted(
15-
[f.split(".json")[0] for f in os.listdir(schema_dir) if f.endswith(".json")],
15+
[f.stem for f in Path(schema_dir).glob("*.json")],
1616
key=lambda x: tuple(map(int, x.split("."))),
1717
)
1818

@@ -30,14 +30,15 @@ def get_videoipath_version():
3030
return None
3131

3232

33-
def load_module(module_name: str, file_path: str) -> ModuleType:
34-
spec = importlib.util.spec_from_file_location(
35-
module_name,
36-
file_path,
37-
)
33+
def load_module(module_name: str, file_path: Union[str, Path]) -> ModuleType:
34+
file_path = Path(file_path).resolve()
35+
36+
if not file_path.exists():
37+
raise FileNotFoundError(f"Module file not found: {file_path}")
3838

39+
spec = importlib.util.spec_from_file_location(module_name, str(file_path))
3940
if spec is None or spec.loader is None:
40-
raise ValueError("Failed to load drivers module")
41+
raise ImportError(f"Failed to load module: {module_name} from {file_path}")
4142

4243
module = importlib.util.module_from_spec(spec)
4344
spec.loader.exec_module(module)

0 commit comments

Comments
 (0)