From 7f98599c3882a6ab346dc27079f68e0304fa7344 Mon Sep 17 00:00:00 2001 From: OpenVMP Date: Thu, 28 Dec 2023 18:53:49 -0800 Subject: [PATCH] Make it possible for a package to require a compatible version of PartCAD (#1) --- requirements.txt | 3 +- src/partcad/project_config.py | 15 +++++++++- tests/unit/data/project_config_invalid_1.yaml | 2 ++ tests/unit/data/project_config_valid_1.yaml | 2 ++ tests/unit/test_project_config.py | 29 +++++++++++++++++++ 5 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 tests/unit/data/project_config_invalid_1.yaml create mode 100644 tests/unit/data/project_config_valid_1.yaml create mode 100644 tests/unit/test_project_config.py diff --git a/requirements.txt b/requirements.txt index 0118ee64..649c4c61 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,4 +9,5 @@ cairosvg==2.7.0 ocp_vscode==2.0.13 GitPython==3.1.40 progress==1.6 -ruamel.yaml==0.18.5 \ No newline at end of file +ruamel.yaml==0.18.5 +packaging==23.1 \ No newline at end of file diff --git a/src/partcad/project_config.py b/src/partcad/project_config.py index c794da6e..2f5e65c5 100644 --- a/src/partcad/project_config.py +++ b/src/partcad/project_config.py @@ -9,6 +9,8 @@ import os import json import yaml +from importlib.metadata import version +from packaging.specifiers import SpecifierSet DEFAULT_CONFIG_FILENAME = "partcad.yaml" @@ -22,7 +24,7 @@ def __init__(self, config_path=DEFAULT_CONFIG_FILENAME): if os.path.isdir(config_path): config_path += "/" + DEFAULT_CONFIG_FILENAME if not os.path.isfile(config_path): - print("PartCad configuration file is not found: %s" % config_path) + print("PartCAD configuration file is not found: %s" % config_path) return self.config_path = config_path @@ -32,3 +34,14 @@ def __init__(self, config_path=DEFAULT_CONFIG_FILENAME): self.config_obj = yaml.safe_load(open(config_path, "r")) if config_path.endswith(".json"): self.config_obj = json.load(open(config_path, "r")) + + if "partcad" in self.config_obj: + # See what version of PartCAD is required for this package + partcad_requirements = SpecifierSet(self.config_obj["partcad"]) + partcad_version = version("partcad") + if partcad_version not in partcad_requirements: + # TODO(clairbee): add better error and exception handling + raise Exception( + "ERROR: Incompatible PartCAD version! %s does not satisfy %s" + % (partcad_version, partcad_requirements) + ) diff --git a/tests/unit/data/project_config_invalid_1.yaml b/tests/unit/data/project_config_invalid_1.yaml new file mode 100644 index 00000000..75f142da --- /dev/null +++ b/tests/unit/data/project_config_invalid_1.yaml @@ -0,0 +1,2 @@ +# This configuration file has the version requirements that always fail +partcad: "<0.1.0" diff --git a/tests/unit/data/project_config_valid_1.yaml b/tests/unit/data/project_config_valid_1.yaml new file mode 100644 index 00000000..efb0182c --- /dev/null +++ b/tests/unit/data/project_config_valid_1.yaml @@ -0,0 +1,2 @@ +# This configuration file has the version requirements that always pass +partcad: ">=0.1.0" diff --git a/tests/unit/test_project_config.py b/tests/unit/test_project_config.py new file mode 100644 index 00000000..44911d02 --- /dev/null +++ b/tests/unit/test_project_config.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +# +# OpenVMP, 2023 +# +# Author: Roman Kuzmenko +# Created: 2023-12-27 +# +# Licensed under Apache License, Version 2.0. +# + +import partcad as pc + + +def test_project_config_version_1(): + """Positive test case for PartCAD version requirement in the package config file""" + try: + ctx = pc.Context("tests/unit/data/project_config_valid_1.yaml") + assert ctx.config_obj["partcad"] == ">=0.1.0" + except Exception as e: + assert False, "Valid configuration file caused an exception: %s" % e + + +def test_project_config_version_2(): + """Negative test case for PartCAD version requirement in the package config file""" + try: + ctx = pc.Context("tests/unit/data/project_config_invalid_1.yaml") + assert False, "Invalid configuration file did not cause an exception" + except: + _ignore = True