Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,18 @@ TestResults/
*.pyc
dist/
.vs/
.venv/

#Pytest
.pytest_cache/

#PDM
.pdm-python
__pypackages__/
.pdm-build/

#ruff
.ruff_cache/

#Coverage
.coverage
Expand Down
4 changes: 2 additions & 2 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"recommendations": [
"ms-python.mypy-type-checker",
"asciidoctor.asciidoctor-vscode",
"charliermarsh.ruff",
"tamasfe.even-better-toml"
"tamasfe.even-better-toml",
"meta.pyrefly"
]
}
10 changes: 7 additions & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true,
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit"
},
"mypy-type-checker.reportingScope": "workspace",
"mypy-type-checker.preferDaemon": true,
"mypy-type-checker.importStrategy": "fromEnvironment",
"[python]": {
"editor.codeActionsOnSave": {
"source.fixAll": "explicit",
"source.organizeImports": "explicit"
},
"editor.defaultFormatter": "charliermarsh.ruff"
}
}
12 changes: 6 additions & 6 deletions cppython/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
from importlib.metadata import entry_points
from inspect import getmodule
from logging import Logger
from typing import Any
from typing import Any, cast

from cppython.core.plugin_schema.generator import Generator
from cppython.core.plugin_schema.provider import Provider
from cppython.core.plugin_schema.scm import SCM
from cppython.core.plugin_schema.scm import SCM, SupportedSCMFeatures
from cppython.core.resolution import (
PluginBuildData,
PluginCPPythonData,
Expand Down Expand Up @@ -262,7 +262,7 @@ def select_scm(self, scm_plugins: list[type[SCM]], project_data: ProjectData) ->
The selected SCM plugin type
"""
for scm_type in scm_plugins:
if scm_type.features(project_data.project_root).repository:
if cast(SupportedSCMFeatures, scm_type.features(project_data.project_root)).repository:
return scm_type

self._logger.info('No SCM plugin was found that supports the given path')
Expand Down Expand Up @@ -317,7 +317,7 @@ def create_scm(
cppython_plugin_data = resolve_cppython_plugin(core_data.cppython_data, scm_type)
scm_data = resolve_scm(core_data.project_data, cppython_plugin_data)

plugin = scm_type(scm_data)
plugin = cast(SCM, scm_type(scm_data))

return plugin

Expand Down Expand Up @@ -354,7 +354,7 @@ def create_generator(
cppython_data=cppython_plugin_data,
)

return generator_type(generator_data, core_plugin_data, generator_configuration)
return cast(Generator, generator_type(generator_data, core_plugin_data, generator_configuration))

def create_provider(
self,
Expand Down Expand Up @@ -389,7 +389,7 @@ def create_provider(
cppython_data=cppython_plugin_data,
)

return provider_type(provider_data, core_plugin_data, provider_configuration)
return cast(Provider, provider_type(provider_data, core_plugin_data, provider_configuration))


class Builder:
Expand Down
51 changes: 36 additions & 15 deletions cppython/console/entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,29 @@
from typing import Annotated

import typer
from rich import print

from cppython.console.schema import ConsoleConfiguration, ConsoleInterface
from cppython.core.schema import ProjectConfiguration
from cppython.project import Project

app = typer.Typer()
app = typer.Typer(no_args_is_help=True)


def get_enabled_project(context: typer.Context) -> Project:
"""Helper to load and validate an enabled Project from CLI context."""
configuration = context.find_object(ConsoleConfiguration)
if configuration is None:
raise ValueError('The configuration object is missing')

path = configuration.project_configuration.project_root / 'pyproject.toml'
pyproject_data = loads(path.read_text(encoding='utf-8'))

project = Project(configuration.project_configuration, configuration.interface, pyproject_data)
if not project.enabled:
print('[bold red]Error[/bold red]: Project is not enabled. Please check your pyproject.toml configuration.')
raise typer.Exit(code=1)
return project


def _find_pyproject_file() -> Path:
Expand Down Expand Up @@ -75,13 +92,7 @@ def install(
Raises:
ValueError: If the configuration object is missing
"""
if (configuration := context.find_object(ConsoleConfiguration)) is None:
raise ValueError('The configuration object is missing')

path = configuration.project_configuration.project_root / 'pyproject.toml'
pyproject_data = loads(path.read_text(encoding='utf-8'))

project = Project(configuration.project_configuration, configuration.interface, pyproject_data)
project = get_enabled_project(context)
project.install()


Expand All @@ -97,13 +108,7 @@ def update(
Raises:
ValueError: If the configuration object is missing
"""
if (configuration := context.find_object(ConsoleConfiguration)) is None:
raise ValueError('The configuration object is missing')

path = configuration.project_configuration.project_root / 'pyproject.toml'
pyproject_data = loads(path.read_text(encoding='utf-8'))

project = Project(configuration.project_configuration, configuration.interface, pyproject_data)
project = get_enabled_project(context)
project.update()


Expand All @@ -112,3 +117,19 @@ def list_command(
_: typer.Context,
) -> None:
"""Prints project information"""


@app.command()
def publish(
context: typer.Context,
) -> None:
"""Publish API call

Args:
context: The CLI configuration object

Raises:
ValueError: If the configuration object is missing
"""
project = get_enabled_project(context)
project.publish()
5 changes: 3 additions & 2 deletions cppython/core/plugin_schema/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
DataPlugin,
DataPluginGroupData,
SupportedDataFeatures,
SupportedFeatures,
SyncData,
)

Expand Down Expand Up @@ -58,13 +59,13 @@ def __init__(

@staticmethod
@abstractmethod
def features(directory: DirectoryPath) -> SupportedGeneratorFeatures:
def features(directory: DirectoryPath) -> SupportedFeatures:
"""Broadcasts the shared features of the generator plugin to CPPython

Args:
directory: The root directory where features are evaluated

Returns:
The supported features
The supported features - `SupportedGeneratorFeatures`. Cast to this type to help us avoid generic typing
"""
raise NotImplementedError
10 changes: 8 additions & 2 deletions cppython/core/plugin_schema/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
DataPlugin,
DataPluginGroupData,
SupportedDataFeatures,
SupportedFeatures,
SyncData,
)

Expand Down Expand Up @@ -67,14 +68,14 @@ def __init__(

@staticmethod
@abstractmethod
def features(directory: DirectoryPath) -> SupportedProviderFeatures:
def features(directory: DirectoryPath) -> SupportedFeatures:
"""Broadcasts the shared features of the Provider plugin to CPPython

Args:
directory: The root directory where features are evaluated

Returns:
The supported features
The supported features - `SupportedProviderFeatures`. Cast to this type to help us avoid generic typing
"""
raise NotImplementedError

Expand All @@ -87,3 +88,8 @@ def install(self) -> None:
def update(self) -> None:
"""Called when dependencies need to be updated and written to the lock file."""
raise NotImplementedError

@abstractmethod
def publish(self) -> None:
"""Called when the project needs to be published."""
raise NotImplementedError
4 changes: 2 additions & 2 deletions cppython/core/plugin_schema/scm.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@ def __init__(self, group_data: SCMPluginGroupData) -> None:

@staticmethod
@abstractmethod
def features(directory: DirectoryPath) -> SupportedSCMFeatures:
def features(directory: DirectoryPath) -> SupportedFeatures:
"""Broadcasts the shared features of the SCM plugin to CPPython

Args:
directory: The root directory where features are evaluated

Returns:
The supported features
The supported features - `SupportedSCMFeatures`. Cast to this type to help us avoid generic typing
"""
raise NotImplementedError

Expand Down
8 changes: 4 additions & 4 deletions cppython/core/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class ProjectConfiguration(CPPythonModel, extra='forbid'):
bool, Field(description='Debug mode. Additional processing will happen to expose more debug information')
] = False

@field_validator('verbosity')
@field_validator('verbosity') # type: ignore
@classmethod
def min_max(cls, value: int) -> int:
"""Validator that clamps the input value
Expand Down Expand Up @@ -118,7 +118,7 @@ class CPPythonData(CPPythonModel, extra='forbid'):
scm_name: TypeName
dependencies: list[Requirement]

@field_validator('configuration_path', 'install_path', 'tool_path', 'build_path')
@field_validator('configuration_path', 'install_path', 'tool_path', 'build_path') # type: ignore
@classmethod
def validate_absolute_path(cls, value: Path) -> Path:
"""Enforce the input is an absolute path
Expand Down Expand Up @@ -234,14 +234,14 @@ def __init__(

@staticmethod
@abstractmethod
def features(directory: DirectoryPath) -> SupportedDataFeatures:
def features(directory: DirectoryPath) -> SupportedFeatures:
"""Broadcasts the shared features of the data plugin to CPPython

Args:
directory: The root directory where features are evaluated

Returns:
The supported features
The supported features - `SupportedDataFeatures`. Cast to this type to help us avoid generic typing
"""
raise NotImplementedError

Expand Down
8 changes: 4 additions & 4 deletions cppython/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
SCMPluginGroupData,
SupportedSCMFeatures,
)
from cppython.core.schema import Information
from cppython.core.schema import Information, SupportedFeatures


class DefaultSCM(SCM):
Expand All @@ -18,11 +18,11 @@ def __init__(self, group_data: SCMPluginGroupData) -> None:
self.group_data = group_data

@staticmethod
def features(_: DirectoryPath) -> SupportedSCMFeatures:
def features(directory: DirectoryPath) -> SupportedFeatures:
"""Broadcasts the shared features of the SCM plugin to CPPython

Returns:
The supported features
The supported features - `SupportedGeneratorFeatures`. Cast to this type to help us avoid generic typing
"""
return SupportedSCMFeatures(repository=True)

Expand All @@ -36,7 +36,7 @@ def information() -> Information:
return Information()

@staticmethod
def version(_: DirectoryPath) -> str:
def version(directory: DirectoryPath) -> str:
"""Extracts the system's version metadata

Returns:
Expand Down
20 changes: 15 additions & 5 deletions cppython/plugins/cmake/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def generate_provider_preset(provider_data: CMakeSyncData) -> CMakePresets:
provider_directory: The base directory to place the preset files
provider_data: The providers synchronization data
"""
generated_configure_preset = ConfigurePreset(name=provider_data.provider_name)
generated_configure_preset = ConfigurePreset(name=provider_data.provider_name, hidden=True)

# Toss in that sync data from the provider
generated_configure_preset.cacheVariables = {
Expand Down Expand Up @@ -67,7 +67,7 @@ def generate_cppython_preset(
Returns:
A CMakePresets object
"""
generated_configure_preset = ConfigurePreset(name='cppython', inherits=provider_data.provider_name)
generated_configure_preset = ConfigurePreset(name='cppython', inherits=provider_data.provider_name, hidden=True)
generated_preset = CMakePresets(configurePresets=[generated_configure_preset])

# Get the relative path to the provider preset file
Expand Down Expand Up @@ -114,20 +114,27 @@ def write_cppython_preset(
return cppython_preset_file

@staticmethod
def generate_root_preset(preset_file: Path, cppython_preset_file: Path, cmake_data: CMakeData) -> CMakePresets:
def generate_root_preset(
preset_file: Path, cppython_preset_file: Path, cmake_data: CMakeData, build_directory: Path
) -> CMakePresets:
"""Generates the top level root preset with the include reference.

Args:
preset_file: Preset file to modify
cppython_preset_file: Path to the cppython preset file to include
cmake_data: The CMake data to use
build_directory: The build directory to use

Returns:
A CMakePresets object
"""
default_configure_preset = ConfigurePreset(
name=cmake_data.configuration_name,
inherits='cppython',
binaryDir=build_directory.as_posix(),
cacheVariables={
'CMAKE_BUILD_TYPE': 'Release' # Ensure compatibility for single-config and multi-config generators
},
)

if preset_file.exists():
Expand Down Expand Up @@ -170,7 +177,9 @@ def generate_root_preset(preset_file: Path, cppython_preset_file: Path, cmake_da
return root_preset

@staticmethod
def write_root_presets(preset_file: Path, cppython_preset_file: Path, cmake_data: CMakeData) -> None:
def write_root_presets(
preset_file: Path, cppython_preset_file: Path, cmake_data: CMakeData, build_directory: Path
) -> None:
"""Read the top level json file and insert the include reference.

Receives a relative path to the tool cmake json file
Expand All @@ -182,6 +191,7 @@ def write_root_presets(preset_file: Path, cppython_preset_file: Path, cmake_data
preset_file: Preset file to modify
cppython_preset_file: Path to the cppython preset file to include
cmake_data: The CMake data to use
build_directory: The build directory to use
"""
initial_root_preset = None

Expand All @@ -190,7 +200,7 @@ def write_root_presets(preset_file: Path, cppython_preset_file: Path, cmake_data
initial_json = file.read()
initial_root_preset = CMakePresets.model_validate_json(initial_json)

root_preset = Builder.generate_root_preset(preset_file, cppython_preset_file, cmake_data)
root_preset = Builder.generate_root_preset(preset_file, cppython_preset_file, cmake_data, build_directory)

# Only write the file if the data has changed
if root_preset != initial_root_preset:
Expand Down
Loading