diff --git a/cppython/project.py b/cppython/project.py index 561698b..dd3dcd9 100644 --- a/cppython/project.py +++ b/cppython/project.py @@ -4,9 +4,9 @@ import logging from importlib import metadata +from pathlib import Path from typing import Any, Type, TypeVar -from cppython_core.core import cppython_logger from cppython_core.schema import ( PEP621, CPPythonData, @@ -18,10 +18,11 @@ PyProject, ToolData, ) +from cppython_core.utility import cppython_logger from pydantic import create_model -from cppython.schema import API, ProjectConfiguration -from cppython.utility import write_presets +from cppython.schema import API, CMakePresets, ConfigurePreset, ProjectConfiguration +from cppython.utility import write_model_json class ProjectBuilder: @@ -110,6 +111,49 @@ def generate_modified(self, original: CPPythonDataT) -> CPPythonDataT: return modified + def write_presets(self, tool_path: Path, generator_output: list[tuple[str, Path]]) -> None: + """ + Write the cppython presets + """ + + def write_generator_presets(tool_path: Path, generator_name: str, toolchain_path: Path) -> Path: + """ + Write a generator preset. + @returns - The written json file + """ + generator_tool_path = tool_path / generator_name + generator_tool_path.mkdir(parents=True, exist_ok=True) + + configure_preset = ConfigurePreset(name=generator_name, hidden=True, toolchainFile=str(toolchain_path)) + presets = CMakePresets(configurePresets=[configure_preset]) + + json_path = generator_tool_path / f"{generator_name}.json" + + write_model_json(json_path, presets) + + return json_path + + names = [] + includes = [] + + tool_path = tool_path / "cppython" + + for generator_name, toolchain in generator_output: + + preset_file = write_generator_presets(tool_path, generator_name, toolchain) + + relative_file = preset_file.relative_to(tool_path) + + names.append(generator_name) + includes.append(str(relative_file)) + + configure_preset = ConfigurePreset(name="cppython", hidden=True, inherits=names) + presets = CMakePresets(configurePresets=[configure_preset], include=includes) + + json_path = tool_path / "cppython.json" + + write_model_json(json_path, presets) + class Project(API): """ @@ -132,8 +176,8 @@ def __init__( cppython_logger.info("Initializing project") - builder = ProjectBuilder(self.configuration) - plugins = builder.gather_plugins(Generator) + self._builder = ProjectBuilder(self.configuration) + plugins = self._builder.gather_plugins(Generator) if not plugins: cppython_logger.error("No generator plugin was found") @@ -142,7 +186,7 @@ def __init__( for plugin in plugins: cppython_logger.warning(f"Generator plugin found: {plugin.name()}") - extended_pyproject_type = builder.generate_model(plugins) + extended_pyproject_type = self._builder.generate_model(plugins) pyproject = extended_pyproject_type(**pyproject_data) if pyproject is None: @@ -161,12 +205,14 @@ def __init__( self._project = pyproject.project - self._modified_cppython_data = builder.generate_modified(pyproject.tool.cppython) + self._modified_cppython_data = self._builder.generate_modified(pyproject.tool.cppython) self._interface = interface generator_configuration = GeneratorConfiguration() - self._generators = builder.create_generators(plugins, generator_configuration, self.project, self.cppython) + self._generators = self._builder.create_generators( + plugins, generator_configuration, self.project, self.cppython + ) cppython_logger.info("Initialized project successfully") @@ -251,7 +297,7 @@ def install(self) -> None: cppython_logger.error(f"Generator {generator.name()} failed to install") raise exception - write_presets(tool_path, generator_output) + self._builder.write_presets(tool_path, generator_output) def update(self) -> None: """ @@ -279,4 +325,4 @@ def update(self) -> None: cppython_logger.error(f"Generator {generator.name()} failed to update") raise exception - write_presets(tool_path, generator_output) + self._builder.write_presets(tool_path, generator_output) diff --git a/cppython/utility.py b/cppython/utility.py index b7d601a..1df313f 100644 --- a/cppython/utility.py +++ b/cppython/utility.py @@ -4,65 +4,25 @@ import json from pathlib import Path +from typing import Type -from cppython.schema import CMakePresets, ConfigurePreset +from cppython_core.schema import ModelT +from pydantic import BaseModel -def read_preset(name: str, path: Path) -> CMakePresets: +def read_model_json(path: Path, model: Type[ModelT]) -> ModelT: """ - Reading routing + Reading routine """ - preset_path = path / f"{name}.json" - return CMakePresets.parse_file(path=preset_path) + return model.parse_file(path=path) -def write_preset(name: str, path: Path, presets: CMakePresets) -> Path: +def write_model_json(path: Path, model: BaseModel) -> None: """ Writing routine """ - file = path / f"{name}.json" - serialized = json.loads(presets.json(exclude_none=True)) - with open(file, "w", encoding="utf8") as json_file: + serialized = json.loads(model.json(exclude_none=True)) + with open(path, "w", encoding="utf8") as json_file: json.dump(serialized, json_file, ensure_ascii=False, indent=2) - - return file - - -def write_presets(tool_path: Path, generator_output: list[tuple[str, Path]]) -> None: - """ - Write the cppython presets - """ - - def write_generator_presets(tool_path: Path, generator_name: str, toolchain_path: Path) -> Path: - """ - Write a generator preset. - @returns - The written json file - """ - generator_tool_path = tool_path / generator_name - generator_tool_path.mkdir(parents=True, exist_ok=True) - - configure_preset = ConfigurePreset(name=generator_name, hidden=True, toolchainFile=str(toolchain_path)) - presets = CMakePresets(configurePresets=[configure_preset]) - - return write_preset(generator_name, generator_tool_path, presets) - - names = [] - includes = [] - - tool_path = tool_path / "cppython" - - for generator_name, toolchain in generator_output: - - preset_file = write_generator_presets(tool_path, generator_name, toolchain) - - relative_file = preset_file.relative_to(tool_path) - - names.append(generator_name) - includes.append(str(relative_file)) - - configure_preset = ConfigurePreset(name="cppython", hidden=True, inherits=names) - presets = CMakePresets(configurePresets=[configure_preset], include=includes) - - write_preset("cppython", tool_path, presets) diff --git a/pdm.lock b/pdm.lock index 40e479b..45ace51 100644 --- a/pdm.lock +++ b/pdm.lock @@ -68,7 +68,7 @@ dependencies = [ [[package]] name = "cppython-core" -version = "0.3.3.dev21" +version = "0.3.3.dev25" requires_python = ">=3.10" summary = "Data definitions for CPPython" dependencies = [ @@ -153,11 +153,11 @@ dependencies = [ [[package]] name = "pylint" -version = "2.13.8" +version = "2.13.9" requires_python = ">=3.6.2" summary = "python code static checker" dependencies = [ - "astroid<=2.12.0-dev0,>=2.11.3", + "astroid<=2.12.0-dev0,>=2.11.5", "colorama; sys_platform == \"win32\"", "dill>=0.2", "isort<6,>=4.2.5", @@ -219,7 +219,7 @@ dependencies = [ [[package]] name = "setuptools" -version = "62.2.0" +version = "62.3.1" requires_python = ">=3.7" summary = "Easily download, build, install, upgrade, and uninstall Python packages" @@ -337,10 +337,12 @@ content_hash = "sha256:9842348d0ddc71440b500499ed71e9b60aea9edcf388f5d8ef170c125 {file = "coverage-6.3.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4d06380e777dd6b35ee936f333d55b53dc4a8271036ff884c909cf6e94be8b6c"}, {file = "coverage-6.3.3-cp39-cp39-win32.whl", hash = "sha256:f8cabc5fd0091976ab7b020f5708335033e422de25e20ddf9416bdce2b7e07d8"}, {file = "coverage-6.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:9c9441d57b0963cf8340268ad62fc83de61f1613034b79c2b1053046af0c5284"}, + {file = "coverage-6.3.3-pp36.pp37.pp38-none-any.whl", hash = "sha256:d522f1dc49127eab0bfbba4e90fa068ecff0899bbf61bf4065c790ddd6c177fe"}, + {file = "coverage-6.3.3.tar.gz", hash = "sha256:2781c43bffbbec2b8867376d4d61916f5e9c4cc168232528562a61d1b4b01879"}, ] -"cppython-core 0.3.3.dev21" = [ - {file = "cppython_core-0.3.3.dev21-py3-none-any.whl", hash = "sha256:9466bd293aede21956514698719e0514d9957a1b12433cebfa32076c8cb3f3c7"}, - {file = "cppython-core-0.3.3.dev21.tar.gz", hash = "sha256:ecc053a9f1228afb2937ad107c456fd001090cf1f2a5d8d5821177582ccbb78f"}, +"cppython-core 0.3.3.dev25" = [ + {file = "cppython_core-0.3.3.dev25-py3-none-any.whl", hash = "sha256:3922c2ad03557d7e6f777b686c3542e9840898579ab68573cb7e41e36ed8e964"}, + {file = "cppython-core-0.3.3.dev25.tar.gz", hash = "sha256:13bfc78b0c847eae260d521305a0354eeacb4c6d6bffa816a18c21ded1e3b087"}, ] "dill 0.3.4" = [ {file = "dill-0.3.4-py2.py3-none-any.whl", hash = "sha256:7e40e4a70304fd9ceab3535d36e58791d9c4a776b38ec7f7ec9afc8d3dca4d4f"}, @@ -458,9 +460,9 @@ content_hash = "sha256:9842348d0ddc71440b500499ed71e9b60aea9edcf388f5d8ef170c125 {file = "pydantic-1.9.0-py3-none-any.whl", hash = "sha256:085ca1de245782e9b46cefcf99deecc67d418737a1fd3f6a4f511344b613a5b3"}, {file = "pydantic-1.9.0.tar.gz", hash = "sha256:742645059757a56ecd886faf4ed2441b9c0cd406079c2b4bee51bcc3fbcd510a"}, ] -"pylint 2.13.8" = [ - {file = "pylint-2.13.8-py3-none-any.whl", hash = "sha256:f87e863a0b08f64b5230e7e779bcb75276346995737b2c0dc2793070487b1ff6"}, - {file = "pylint-2.13.8.tar.gz", hash = "sha256:ced8968c3b699df0615e2a709554dec3ddac2f5cd06efadb69554a69eeca364a"}, +"pylint 2.13.9" = [ + {file = "pylint-2.13.9-py3-none-any.whl", hash = "sha256:705c620d388035bdd9ff8b44c5bcdd235bfb49d276d488dd2c8ff1736aa42526"}, + {file = "pylint-2.13.9.tar.gz", hash = "sha256:095567c96e19e6f57b5b907e67d265ff535e588fe26b12b5ebe1fc5645b2c731"}, ] "pyparsing 3.0.9" = [ {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, @@ -482,9 +484,9 @@ content_hash = "sha256:9842348d0ddc71440b500499ed71e9b60aea9edcf388f5d8ef170c125 {file = "pytest_mock-3.7.0-py3-none-any.whl", hash = "sha256:6cff27cec936bf81dc5ee87f07132b807bcda51106b5ec4b90a04331cba76231"}, {file = "pytest-mock-3.7.0.tar.gz", hash = "sha256:5112bd92cc9f186ee96e1a92efc84969ea494939c3aead39c50f421c4cc69534"}, ] -"setuptools 62.2.0" = [ - {file = "setuptools-62.2.0-py3-none-any.whl", hash = "sha256:5534570b9980fc650d45c62877ff603c7aaaf24893371708736cc016bd221c3c"}, - {file = "setuptools-62.2.0.tar.gz", hash = "sha256:ca6ba73b7fd5f734ae70ece8c4c1f7062b07f3352f6428f6277e27c8f5c64237"}, +"setuptools 62.3.1" = [ + {file = "setuptools-62.3.1-py3-none-any.whl", hash = "sha256:588ffd1dc6e20e9f4f7057aa9873fcdc26e0270362602735d32476bad67d82c5"}, + {file = "setuptools-62.3.1.tar.gz", hash = "sha256:28c79c24d83c42a5e6d6cc711e5e9a6c1b89326229feaa5807fc277040658600"}, ] "tomli 2.0.1" = [ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, diff --git a/tests/unit/test_project.py b/tests/unit/test_project.py index e6cb3d2..8be1759 100644 --- a/tests/unit/test_project.py +++ b/tests/unit/test_project.py @@ -110,3 +110,33 @@ def test_generator_creation(self, mocker: MockerFixture): ) assert len(generators) == 1 + + def test_presets(self, tmpdir): + """ + TODO + """ + + configuration = ProjectConfiguration(root_path=Path()) + builder = ProjectBuilder(configuration) + + temporary_directory = Path(tmpdir) + + input_toolchain = temporary_directory / "input.cmake" + + with open(input_toolchain, "w", encoding="utf8") as file: + file.write("") + + generator_output = [("test", input_toolchain)] + builder.write_presets(temporary_directory, generator_output) + + cppython_tool = temporary_directory / "cppython" + assert cppython_tool.exists() + + cppython_file = cppython_tool / "cppython.json" + assert cppython_file.exists() + + test_tool = cppython_tool / "test" + assert test_tool.exists() + + test_file = test_tool / "test.json" + assert test_file.exists() diff --git a/tests/unit/test_utility.py b/tests/unit/test_utility.py index fde0f81..b113e84 100644 --- a/tests/unit/test_utility.py +++ b/tests/unit/test_utility.py @@ -3,8 +3,9 @@ """ from pathlib import Path -from cppython.schema import CMakePresets -from cppython.utility import read_preset, write_preset, write_presets +from pydantic.main import BaseModel + +from cppython.utility import read_model_json, write_model_json class TestBuilder: @@ -12,42 +13,26 @@ class TestBuilder: TODO """ - def test_preset_read_write(self, tmpdir): + def test_model_read_write(self, tmpdir): """ TODO """ - temporary_directory = Path(tmpdir) - - presets = CMakePresets() - write_preset("test", temporary_directory, presets) - output = read_preset("test", temporary_directory) + class TestModel(BaseModel): + """ + TODO + """ - assert presets == output + test_path: Path + test_int: int - def test_presets(self, tmpdir): - """ - TODO - """ + test_model = TestModel(test_path=Path(), test_int=3) temporary_directory = Path(tmpdir) - input_toolchain = temporary_directory / "input.cmake" - - with open(input_toolchain, "w", encoding="utf8") as file: - file.write("") - - generator_output = [("test", input_toolchain)] - write_presets(temporary_directory, generator_output) - - cppython_tool = temporary_directory / "cppython" - assert cppython_tool.exists() - - cppython_file = cppython_tool / "cppython.json" - assert cppython_file.exists() + json_path = temporary_directory / "test.json" - test_tool = cppython_tool / "test" - assert test_tool.exists() + write_model_json(json_path, test_model) + output = read_model_json(json_path, TestModel) - test_file = test_tool / "test.json" - assert test_file.exists() + assert test_model == output