Skip to content

refactor: restructure a little and add tests #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.8", "3.11", "3.12"]
python-version: ["3.8", "3.12"]
runs-on: [ubuntu-latest, macos-latest, windows-latest]

include:
- python-version: pypy-3.9
- python-version: pypy-3.10
runs-on: ubuntu-latest

steps:
Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ dynamic_metadata
```

```{eval-rst}
.. click:: scikit_build_core.cli.main:skbuild
.. click:: scikit_build_core.cli.__main__:skbuild
:prog: skbuild

```
Expand Down
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,16 @@ Discussions = "https://github.com/scikit-build/scikit-build-cli/discussions"
Changelog = "https://github.com/scikit-build/scikit-build-cli/releases"

[project.scripts]
skbuild = "scikit_build_cli.__main__:run_cli"
skbuild = "scikit_build_cli.__main__:skbuild"

[project.entry-points."skbuild.commands"]
build = "scikit_build_cli.commands.build:build"
configure = "scikit_build_cli.commands.configure:configure"
dynamic-metadata = "scikit_build_cli.commands.dynamic_metadata:dynamic_metadata"
metadata = "scikit_build_cli.commands.metadata:metadata"
install = "scikit_build_cli.commands.install:install"
new = "scikit_build_cli.commands.new:new"
init = "scikit_build_cli.commands.init:init"

[tool.hatch]
version.source = "vcs"
Expand Down
6 changes: 1 addition & 5 deletions src/scikit_build_cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,4 @@

from ._version import version as __version__

# Load all subcommands
# Load and expose the main CLI interface
from .main import skbuild

__all__: list[str] = ["skbuild", "__version__"]
__all__: list[str] = ["__version__"]
79 changes: 74 additions & 5 deletions src/scikit_build_cli/__main__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,83 @@
from __future__ import annotations

from . import skbuild
import pathlib
from collections.abc import MutableMapping, Sequence
from importlib.metadata import EntryPoint

import click

def run_cli() -> None:
from . import __version__
from ._compat.importlib import metadata

__all__ = ["skbuild"]


def __dir__() -> list[str]:
return __all__


class LazyGroup(click.Group):
"""
Entry point to skbuild command.
Lazy loader for click commands. Based on Click's documentation, but uses
EntryPoints.
"""
skbuild()

def __init__(
self,
name: str | None = None,
commands: MutableMapping[str, click.Command]
| Sequence[click.Command]
| None = None,
*,
lazy_subcommands: Sequence[EntryPoint] = (),
**kwargs: object,
):
super().__init__(name, commands, **kwargs)
self.lazy_subcommands = {v.name: v for v in lazy_subcommands}

def list_commands(self, ctx: click.Context) -> list[str]:
return sorted([*super().list_commands(ctx), *self.lazy_subcommands])

def get_command(self, ctx: click.Context, cmd_name: str) -> click.Command | None:
if cmd_name in self.lazy_subcommands:
return self._lazy_load(cmd_name)
return super().get_command(ctx, cmd_name)

def _lazy_load(self, cmd_name: str) -> click.Command:
ep = self.lazy_subcommands[cmd_name]
cmd_object = ep.load()
if not isinstance(cmd_object, click.Command):
msg = f"Lazy loading of {ep} failed by returning a non-command object"
raise ValueError(msg)
return cmd_object


# Add all plugin commands.
CMDS = list(metadata.entry_points(group="skbuild.commands"))


@click.group("skbuild", cls=LazyGroup, lazy_subcommands=CMDS)
@click.version_option(__version__)
@click.help_option("--help", "-h")
@click.option(
"--root",
"-r",
type=click.Path(
exists=True,
file_okay=False,
dir_okay=True,
writable=True,
path_type=pathlib.Path,
),
help="Path to the Python project's root",
)
@click.pass_context
def skbuild(ctx: click.Context, root: pathlib.Path) -> None: # noqa: ARG001
"""
scikit-build Main CLI interface
"""
# TODO: Add specific implementations


if __name__ == "__main__":
run_cli()
skbuild()
3 changes: 2 additions & 1 deletion src/scikit_build_cli/commands/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ def __dir__() -> list[str]:

@click.command()
@_build_dir
@click.help_option("--help", "-h")
@click.pass_context
def build(ctx: click.Context, build_dir: Path) -> None: # noqa: ARG001
"""
Run cmake build step
Run CMake build step
"""
# TODO: Add specific implementations
3 changes: 2 additions & 1 deletion src/scikit_build_cli/commands/configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ def __dir__() -> list[str]:

@click.command()
@_build_dir
@click.help_option("--help", "-h")
@click.pass_context
def configure(ctx: click.Context, build_dir: Path) -> None: # noqa: ARG001
"""
Run cmake configure step
Run CMake configure step
"""
# TODO: Add specific implementations
1 change: 1 addition & 0 deletions src/scikit_build_cli/commands/dynamic_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ def __dir__() -> list[str]:


@click.command()
@click.help_option("--help", "-h")
@click.pass_context
def dynamic_metadata(ctx: click.Context) -> None: # noqa: ARG001
"""
Expand Down
19 changes: 19 additions & 0 deletions src/scikit_build_cli/commands/init.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from __future__ import annotations

import click

__all__: list[str] = ["init"]


def __dir__() -> list[str]:
return __all__


@click.command()
@click.help_option("--help", "-h")
@click.pass_context
def init(ctx: click.Context) -> None: # noqa: ARG001
"""
Add scikit-build to an existing project
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Existing CMake or Python project? Or have to have both?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not totally sure. :) I was thinking it could be like new but not overwrite existing files, and maybe adapt to some extent to what is already written.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CMake wise it could ve tricky as everyone is having a different format. We would need a build-dir if we want to do some parsing to find the libraries that link to python-devel. Or we could add_subdirectory with an example path.

Python-side though should be easier to introspect, but custom setup.py might be harder to figure out the intent?

Or we could assume the project is either pure-python or pure-cmake for this case? That could be the simplest to support.

"""
# TODO: Add specific implementations
3 changes: 2 additions & 1 deletion src/scikit_build_cli/commands/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ def __dir__() -> list[str]:

@click.command()
@_build_dir
@click.help_option("--help", "-h")
@click.pass_context
def install(ctx: click.Context, build_dir: Path) -> None: # noqa: ARG001
"""
Run cmake install step
Run CMake install step
"""
# TODO: Add specific implementations
1 change: 1 addition & 0 deletions src/scikit_build_cli/commands/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ def __dir__() -> list[str]:


@click.command()
@click.help_option("--help", "-h")
@click.pass_context
def metadata(ctx: click.Context) -> None: # noqa: ARG001
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking, this might make more sense to be dist_info and rename the dynamica_metadata to metadata? Are there any metadata outside of dist-info that might make it confusing?

"""
Expand Down
19 changes: 19 additions & 0 deletions src/scikit_build_cli/commands/new.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from __future__ import annotations

import click

__all__: list[str] = ["new"]


def __dir__() -> list[str]:
return __all__


@click.command()
@click.help_option("--help", "-h")
@click.pass_context
def new(ctx: click.Context) -> None: # noqa: ARG001
"""
Start a new project
"""
# TODO: Add specific implementations
78 changes: 0 additions & 78 deletions src/scikit_build_cli/main.py

This file was deleted.

26 changes: 23 additions & 3 deletions tests/test_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,28 @@

import importlib.metadata

import scikit_build_cli as m
import pytest
from click.testing import CliRunner

import scikit_build_cli
import scikit_build_cli.__main__

def test_version():
assert importlib.metadata.version("scikit_build_cli") == m.__version__

def test_version() -> None:
assert (
importlib.metadata.version("scikit_build_cli") == scikit_build_cli.__version__
)


@pytest.mark.parametrize("flag", ["--help", "-h"])
def test_help_text(flag: str) -> None:
runner = CliRunner()
result = runner.invoke(scikit_build_cli.__main__.skbuild, [flag])
assert result.exit_code == 0
assert "Run CMake build step" in result.output
assert "Run CMake configure step" in result.output
assert "Get the generated dynamic metadata" in result.output
assert "Run CMake install step" in result.output
assert "Write out the project's metadata" in result.output
assert "Start a new project" in result.output
assert "Add scikit-build to an existing project" in result.output