summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRomain Gonçalves <me@rgoncalves.se>2022-10-08 14:08:16 +0200
committerRomain Gonçalves <me@rgoncalves.se>2022-10-08 14:08:16 +0200
commit037ab915bd455cccf46391f02f61949e5c84f1c3 (patch)
tree65a93d90a540a6e53fc6e618a9904529060964ca
parente667cd7e2dd0a7ac14ac30db38ca630ec0c5409b (diff)
downloadpydanclick-037ab915bd455cccf46391f02f61949e5c84f1c3.tar.gz
wip: saturday fixup
-rw-r--r--README.md53
-rw-r--r--pydanclick/_logging.py12
-rw-r--r--pydanclick/core.py6
-rw-r--r--pydanclick/examples/__main__.py15
-rw-r--r--pyproject.toml3
5 files changed, 85 insertions, 4 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..01a8ac0
--- /dev/null
+++ b/README.md
@@ -0,0 +1,53 @@
+Leverage the power of `pydantic` to create `click` command line applications!
+
+# Getting started
+
+Invoke the example module:
+
+```
+$ python -m pydanclick.examples --help
+```
+
+# Architecture
+
+```
+┌─────────────────────────────────────────────────┐
+│ Pydantic Schema │
+├─────────────────────────────────────────────────┤
+│ class MainArguments(BaseModel): │
+│ verbose: bool │
+│ name: str = Field(description="Service name.")│
+│ ... │
+└──┬──▲───────────────────────────────────────────┘
+ │ │
+ │ │
+ │ │ Reads schema
+ │ │ + generate click interface
+ │ ┌┴────────────────────────┐
+ │ │ Pydanclick decorator ├─────────────────────────────┐
+ │ ├─────────────────────────┤ │
+ │ │ pydanclick.core.command │ │
+ │ │ pydanclick.core.group │ │
+ │ └─────────────────────────┘ │
+ │ │
+┌──▼───────────────────────────────────────────────────────┐ │
+│ Click Interface │ │
+├──────────────────────────────────────────────────────────┤ │
+│ click.Option("--verbose", required=True, type=click.BOOL)│ │
+│ type=click.BOOL) │ │
+│ click.Option("--name", required=True, │ │
+│ type=click.STR, │ │
+│ help="Service Name.") │ │
+└──────────────────────────────────────────────────────────┘ │
+ │
+┌────────────────────────────────────┐ │
+│ Entrypoint invocation │◄──────────────────────┘
+├────────────────────────────────────┤ Read annotation(s)
+│ @command() │ + invoke with arguments
+│ def main(parameter: MainArguments):│ from click
+│ ... │
+│ │
+│ if __name__ == "__main__": │
+│ main() │
+└────────────────────────────────────┘
+```
diff --git a/pydanclick/_logging.py b/pydanclick/_logging.py
new file mode 100644
index 0000000..c90d8d1
--- /dev/null
+++ b/pydanclick/_logging.py
@@ -0,0 +1,12 @@
+import logging
+
+config = {
+ "version": 1,
+ "loggers": {
+ "__main__": {
+ "handlers": ["default"],
+ "level": logging.INFO,
+ "propagate": True,
+ }
+ },
+}
diff --git a/pydanclick/core.py b/pydanclick/core.py
index a513852..6eb2280 100644
--- a/pydanclick/core.py
+++ b/pydanclick/core.py
@@ -2,6 +2,7 @@ from __future__ import annotations
import click
import inspect
+import logging
from typing import Any
from pydantic import BaseModel
@@ -9,6 +10,8 @@ from typing import Callable, Type
from pydanclick.schemas import CliSchema, OptionArgumentsSchema
+logger = logging.getLogger(__name__)
+
class Command(click.Command):
"""
@@ -88,8 +91,6 @@ def get_option_arguments(
schema: CliSchema,
parameter: CliSchema.PropertySchema,
key: str,
- *args,
- **kwargs
) -> OptionArgumentsSchema:
"""
Generate the option information only of a click.Command.
@@ -118,6 +119,7 @@ def get_option_arguments(
arguments.type = bool
arguments.is_flag = True
+ logger.debug(f"Generated arguments: {dict(arguments)}")
return arguments
diff --git a/pydanclick/examples/__main__.py b/pydanclick/examples/__main__.py
index 012f110..ee2e881 100644
--- a/pydanclick/examples/__main__.py
+++ b/pydanclick/examples/__main__.py
@@ -1,11 +1,21 @@
+import logging
+
from enum import Enum
from pydantic import BaseModel, Field
from pydanclick.decorators import command, group
+logger = logging.getLogger()
+handler = logging.StreamHandler()
+handler.setLevel(logging.DEBUG)
+logger.addHandler(handler)
+logger.setLevel(logging.DEBUG)
+handler.setFormatter(
+ logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
+)
-class MainArguments(BaseModel):
+class MainArguments(BaseModel):
class NetworkEnum(str, Enum):
dhcp = "dhcp"
static = "static"
@@ -19,7 +29,7 @@ class MainArguments(BaseModel):
)
force_download: bool = Field(
default=False,
- description="Force the download on a different API version"
+ description="Force the download on a different API version",
)
network_type: NetworkEnum
@@ -42,4 +52,5 @@ main.add_command(show)
if __name__ == "__main__":
+ logger.debug("AAAAAAAAAAAAA")
main()
diff --git a/pyproject.toml b/pyproject.toml
index 619f2a8..0e901b1 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -45,6 +45,9 @@ show_missing = true
fail_under = 100
exclude_lines = ["pragma: no cover"]
+[tool.black]
+line-length = 80
+
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
remember that computers suck.