Skip to content

Commit 2cdfd57

Browse files
minimal plugin system ideas (#24)
* add pluggy dependency * move imports out of cli and add initialy pluggy init calls * add cmd pluggins * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * rename implhook to register * change default plugins to use register and add machanism to load default plugins * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix linting * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix import * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent b233bc2 commit 2cdfd57

File tree

7 files changed

+81
-10
lines changed

7 files changed

+81
-10
lines changed

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Jinja2 = "^3.1.2"
2121
rich = "^12.3.0"
2222
rich-click = {extras = ["typer"], version = "^1.3.0"}
2323
typer = "^0.4.1"
24+
pluggy = "^1.0.0"
2425

2526
[tool.poetry.dev-dependencies]
2627
coverage = "^6.3.2"

src/pyscript/__init__.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,16 @@
55
except ImportError: # pragma: no cover
66
import importlib_metadata as metadata # type: ignore
77

8+
try:
9+
import rich_click.typer as typer
10+
except ImportError: # pragma: no cover
11+
import typer # type: ignore
12+
from rich.console import Console
13+
814
try:
915
__version__ = metadata.version("pyscript-cli")
1016
except metadata.PackageNotFoundError: # pragma: no cover
1117
__version__ = "unknown"
18+
19+
console = Console()
20+
app = typer.Typer(add_completion=False)

src/pyscript/cli.py

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
11
"""The main CLI entrypoint and commands."""
2+
import sys
23
import time
34
import webbrowser
45
from pathlib import Path
56
from typing import Any, Optional
67

7-
from pyscript._generator import file_to_html, string_to_html
8-
9-
try:
10-
import rich_click.typer as typer
11-
except ImportError: # pragma: no cover
12-
import typer # type: ignore
13-
from rich.console import Console
8+
from pluggy import PluginManager
149

15-
from pyscript import __version__
10+
from pyscript import __version__, app, console, plugins, typer
11+
from pyscript._generator import file_to_html, string_to_html
12+
from pyscript.plugins import hookspecs
1613

17-
console = Console()
18-
app = typer.Typer(add_completion=False)
14+
DEFAULT_PLUGINS = ["create", "delete"]
1915

2016

2117
def _print_version():
@@ -108,3 +104,27 @@ def wrap(
108104
if remove_output:
109105
time.sleep(1)
110106
output.unlink()
107+
108+
109+
pm = PluginManager("pyscript-cli")
110+
111+
pm.add_hookspecs(hookspecs)
112+
113+
for modname in DEFAULT_PLUGINS:
114+
importspec = f"pyscript.plugins.{modname}"
115+
116+
try:
117+
__import__(importspec)
118+
except ImportError as e:
119+
raise ImportError(
120+
f'Error importing plugin "{modname}": {e.args[0]}'
121+
).with_traceback(e.__traceback__) from e
122+
123+
else:
124+
mod = sys.modules[importspec]
125+
pm.register(mod, modname)
126+
127+
loaded = pm.load_setuptools_entrypoints("pyscript-cli")
128+
129+
for cmd in pm.hook.pyscript_subcommand():
130+
plugins._add_cmd(cmd)

src/pyscript/plugins/__init__.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from pluggy import HookimplMarker
2+
3+
from pyscript import app
4+
5+
register = HookimplMarker("pyscript-cli")
6+
7+
8+
def _add_cmd(f):
9+
app.command()(f)

src/pyscript/plugins/create.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from pyscript import console, plugins
2+
3+
4+
def create():
5+
"""Creates a new PyScript Project from scratch."""
6+
console.print("pyscript create cmd not yet available..", style="bold green")
7+
return True
8+
9+
10+
@plugins.register
11+
def pyscript_subcommand():
12+
return create

src/pyscript/plugins/delete.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from pyscript import console
2+
from pyscript.plugins import register
3+
4+
5+
def delete():
6+
console.print("pyscript delete cmd not yet available..", style="bold red")
7+
return True
8+
9+
10+
@register
11+
def pyscript_subcommand():
12+
return delete

src/pyscript/plugins/hookspecs.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from pluggy import HookspecMarker
2+
3+
hookspec = HookspecMarker("pyscript-cli")
4+
5+
6+
@hookspec
7+
def pyscript_subcommand():
8+
"""My special little hook that you can customize."""

0 commit comments

Comments
 (0)