Skip to content

Commit 0c4e4f4

Browse files
authored
publish Command + Test Organization (#115)
1 parent 618f451 commit 0c4e4f4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+2992
-1435
lines changed

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,18 @@ TestResults/
1010
*.pyc
1111
dist/
1212
.vs/
13+
.venv/
14+
15+
#Pytest
16+
.pytest_cache/
1317

1418
#PDM
1519
.pdm-python
1620
__pypackages__/
21+
.pdm-build/
22+
23+
#ruff
24+
.ruff_cache/
1725

1826
#Coverage
1927
.coverage

.vscode/extensions.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"recommendations": [
3-
"ms-python.mypy-type-checker",
43
"asciidoctor.asciidoctor-vscode",
54
"charliermarsh.ruff",
6-
"tamasfe.even-better-toml"
5+
"tamasfe.even-better-toml",
6+
"meta.pyrefly"
77
]
88
}

.vscode/settings.json

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@
55
"python.testing.unittestEnabled": false,
66
"python.testing.pytestEnabled": true,
77
"editor.formatOnSave": true,
8-
"editor.codeActionsOnSave": {
9-
"source.organizeImports": "explicit"
10-
},
118
"mypy-type-checker.reportingScope": "workspace",
129
"mypy-type-checker.preferDaemon": true,
1310
"mypy-type-checker.importStrategy": "fromEnvironment",
11+
"[python]": {
12+
"editor.codeActionsOnSave": {
13+
"source.fixAll": "explicit",
14+
"source.organizeImports": "explicit"
15+
},
16+
"editor.defaultFormatter": "charliermarsh.ruff"
17+
}
1418
}

cppython/builder.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
from importlib.metadata import entry_points
55
from inspect import getmodule
66
from logging import Logger
7-
from typing import Any
7+
from typing import Any, cast
88

99
from cppython.core.plugin_schema.generator import Generator
1010
from cppython.core.plugin_schema.provider import Provider
11-
from cppython.core.plugin_schema.scm import SCM
11+
from cppython.core.plugin_schema.scm import SCM, SupportedSCMFeatures
1212
from cppython.core.resolution import (
1313
PluginBuildData,
1414
PluginCPPythonData,
@@ -262,7 +262,7 @@ def select_scm(self, scm_plugins: list[type[SCM]], project_data: ProjectData) ->
262262
The selected SCM plugin type
263263
"""
264264
for scm_type in scm_plugins:
265-
if scm_type.features(project_data.project_root).repository:
265+
if cast(SupportedSCMFeatures, scm_type.features(project_data.project_root)).repository:
266266
return scm_type
267267

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

320-
plugin = scm_type(scm_data)
320+
plugin = cast(SCM, scm_type(scm_data))
321321

322322
return plugin
323323

@@ -354,7 +354,7 @@ def create_generator(
354354
cppython_data=cppython_plugin_data,
355355
)
356356

357-
return generator_type(generator_data, core_plugin_data, generator_configuration)
357+
return cast(Generator, generator_type(generator_data, core_plugin_data, generator_configuration))
358358

359359
def create_provider(
360360
self,
@@ -389,7 +389,7 @@ def create_provider(
389389
cppython_data=cppython_plugin_data,
390390
)
391391

392-
return provider_type(provider_data, core_plugin_data, provider_configuration)
392+
return cast(Provider, provider_type(provider_data, core_plugin_data, provider_configuration))
393393

394394

395395
class Builder:

cppython/console/entry.py

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,29 @@
55
from typing import Annotated
66

77
import typer
8+
from rich import print
89

910
from cppython.console.schema import ConsoleConfiguration, ConsoleInterface
1011
from cppython.core.schema import ProjectConfiguration
1112
from cppython.project import Project
1213

13-
app = typer.Typer()
14+
app = typer.Typer(no_args_is_help=True)
15+
16+
17+
def get_enabled_project(context: typer.Context) -> Project:
18+
"""Helper to load and validate an enabled Project from CLI context."""
19+
configuration = context.find_object(ConsoleConfiguration)
20+
if configuration is None:
21+
raise ValueError('The configuration object is missing')
22+
23+
path = configuration.project_configuration.project_root / 'pyproject.toml'
24+
pyproject_data = loads(path.read_text(encoding='utf-8'))
25+
26+
project = Project(configuration.project_configuration, configuration.interface, pyproject_data)
27+
if not project.enabled:
28+
print('[bold red]Error[/bold red]: Project is not enabled. Please check your pyproject.toml configuration.')
29+
raise typer.Exit(code=1)
30+
return project
1431

1532

1633
def _find_pyproject_file() -> Path:
@@ -75,13 +92,7 @@ def install(
7592
Raises:
7693
ValueError: If the configuration object is missing
7794
"""
78-
if (configuration := context.find_object(ConsoleConfiguration)) is None:
79-
raise ValueError('The configuration object is missing')
80-
81-
path = configuration.project_configuration.project_root / 'pyproject.toml'
82-
pyproject_data = loads(path.read_text(encoding='utf-8'))
83-
84-
project = Project(configuration.project_configuration, configuration.interface, pyproject_data)
95+
project = get_enabled_project(context)
8596
project.install()
8697

8798

@@ -97,13 +108,7 @@ def update(
97108
Raises:
98109
ValueError: If the configuration object is missing
99110
"""
100-
if (configuration := context.find_object(ConsoleConfiguration)) is None:
101-
raise ValueError('The configuration object is missing')
102-
103-
path = configuration.project_configuration.project_root / 'pyproject.toml'
104-
pyproject_data = loads(path.read_text(encoding='utf-8'))
105-
106-
project = Project(configuration.project_configuration, configuration.interface, pyproject_data)
111+
project = get_enabled_project(context)
107112
project.update()
108113

109114

@@ -112,3 +117,19 @@ def list_command(
112117
_: typer.Context,
113118
) -> None:
114119
"""Prints project information"""
120+
121+
122+
@app.command()
123+
def publish(
124+
context: typer.Context,
125+
) -> None:
126+
"""Publish API call
127+
128+
Args:
129+
context: The CLI configuration object
130+
131+
Raises:
132+
ValueError: If the configuration object is missing
133+
"""
134+
project = get_enabled_project(context)
135+
project.publish()

cppython/core/plugin_schema/generator.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
DataPlugin,
1111
DataPluginGroupData,
1212
SupportedDataFeatures,
13+
SupportedFeatures,
1314
SyncData,
1415
)
1516

@@ -58,13 +59,13 @@ def __init__(
5859

5960
@staticmethod
6061
@abstractmethod
61-
def features(directory: DirectoryPath) -> SupportedGeneratorFeatures:
62+
def features(directory: DirectoryPath) -> SupportedFeatures:
6263
"""Broadcasts the shared features of the generator plugin to CPPython
6364
6465
Args:
6566
directory: The root directory where features are evaluated
6667
6768
Returns:
68-
The supported features
69+
The supported features - `SupportedGeneratorFeatures`. Cast to this type to help us avoid generic typing
6970
"""
7071
raise NotImplementedError

cppython/core/plugin_schema/provider.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
DataPlugin,
1212
DataPluginGroupData,
1313
SupportedDataFeatures,
14+
SupportedFeatures,
1415
SyncData,
1516
)
1617

@@ -67,14 +68,14 @@ def __init__(
6768

6869
@staticmethod
6970
@abstractmethod
70-
def features(directory: DirectoryPath) -> SupportedProviderFeatures:
71+
def features(directory: DirectoryPath) -> SupportedFeatures:
7172
"""Broadcasts the shared features of the Provider plugin to CPPython
7273
7374
Args:
7475
directory: The root directory where features are evaluated
7576
7677
Returns:
77-
The supported features
78+
The supported features - `SupportedProviderFeatures`. Cast to this type to help us avoid generic typing
7879
"""
7980
raise NotImplementedError
8081

@@ -87,3 +88,8 @@ def install(self) -> None:
8788
def update(self) -> None:
8889
"""Called when dependencies need to be updated and written to the lock file."""
8990
raise NotImplementedError
91+
92+
@abstractmethod
93+
def publish(self) -> None:
94+
"""Called when the project needs to be published."""
95+
raise NotImplementedError

cppython/core/plugin_schema/scm.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,14 @@ def __init__(self, group_data: SCMPluginGroupData) -> None:
3131

3232
@staticmethod
3333
@abstractmethod
34-
def features(directory: DirectoryPath) -> SupportedSCMFeatures:
34+
def features(directory: DirectoryPath) -> SupportedFeatures:
3535
"""Broadcasts the shared features of the SCM plugin to CPPython
3636
3737
Args:
3838
directory: The root directory where features are evaluated
3939
4040
Returns:
41-
The supported features
41+
The supported features - `SupportedSCMFeatures`. Cast to this type to help us avoid generic typing
4242
"""
4343
raise NotImplementedError
4444

cppython/core/schema.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class ProjectConfiguration(CPPythonModel, extra='forbid'):
4444
bool, Field(description='Debug mode. Additional processing will happen to expose more debug information')
4545
] = False
4646

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

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

235235
@staticmethod
236236
@abstractmethod
237-
def features(directory: DirectoryPath) -> SupportedDataFeatures:
237+
def features(directory: DirectoryPath) -> SupportedFeatures:
238238
"""Broadcasts the shared features of the data plugin to CPPython
239239
240240
Args:
241241
directory: The root directory where features are evaluated
242242
243243
Returns:
244-
The supported features
244+
The supported features - `SupportedDataFeatures`. Cast to this type to help us avoid generic typing
245245
"""
246246
raise NotImplementedError
247247

cppython/defaults.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
SCMPluginGroupData,
88
SupportedSCMFeatures,
99
)
10-
from cppython.core.schema import Information
10+
from cppython.core.schema import Information, SupportedFeatures
1111

1212

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

2020
@staticmethod
21-
def features(_: DirectoryPath) -> SupportedSCMFeatures:
21+
def features(directory: DirectoryPath) -> SupportedFeatures:
2222
"""Broadcasts the shared features of the SCM plugin to CPPython
2323
2424
Returns:
25-
The supported features
25+
The supported features - `SupportedGeneratorFeatures`. Cast to this type to help us avoid generic typing
2626
"""
2727
return SupportedSCMFeatures(repository=True)
2828

@@ -36,7 +36,7 @@ def information() -> Information:
3636
return Information()
3737

3838
@staticmethod
39-
def version(_: DirectoryPath) -> str:
39+
def version(directory: DirectoryPath) -> str:
4040
"""Extracts the system's version metadata
4141
4242
Returns:

0 commit comments

Comments
 (0)