feat: scaffolding + init and print configuration
This commit is contained in:
commit
dc57ecd228
14 changed files with 671 additions and 0 deletions
31
.forgejo/workflows/main.yml
Normal file
31
.forgejo/workflows/main.yml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
on: [push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
static-analysis:
|
||||||
|
name: Static Analysis
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: 3.12
|
||||||
|
- run: |
|
||||||
|
pip install -r ./requirements.txt
|
||||||
|
pip install -r ./requirements_sast.txt
|
||||||
|
- name: Formatting
|
||||||
|
run: python -m black .
|
||||||
|
- name: Linting
|
||||||
|
run: python -m pylint .
|
||||||
|
test:
|
||||||
|
name: Tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: 3.12
|
||||||
|
- run: |
|
||||||
|
pip install -r ./requirements.txt
|
||||||
|
pip install -r ./requirements_test.txt
|
||||||
|
- name: Test suites
|
||||||
|
run: python -m pytest
|
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
*egg-info*
|
||||||
|
*venv*
|
||||||
|
*.pyc
|
||||||
|
|
1
.python-version
Normal file
1
.python-version
Normal file
|
@ -0,0 +1 @@
|
||||||
|
3.12
|
27
pyproject.toml
Normal file
27
pyproject.toml
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
[project]
|
||||||
|
name = "spud"
|
||||||
|
version = "0.0.0"
|
||||||
|
requires-python = "~=3.12"
|
||||||
|
dependencies = [
|
||||||
|
"click~=8.0",
|
||||||
|
"httpx",
|
||||||
|
"pydantic~=2.0",
|
||||||
|
"fastapi~=0.110.0",
|
||||||
|
"uvicorn[standard]~=0.29",
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.optional-dependencies]
|
||||||
|
sast = [
|
||||||
|
"black",
|
||||||
|
"pylint"
|
||||||
|
]
|
||||||
|
test = [
|
||||||
|
"pytest"
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.scripts]
|
||||||
|
spud = "spud.cli:cli"
|
||||||
|
|
||||||
|
[tool.setuptools]
|
||||||
|
packages = ["spud"]
|
||||||
|
|
60
requirements.txt
Normal file
60
requirements.txt
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
annotated-types==0.6.0
|
||||||
|
# via pydantic
|
||||||
|
anyio==4.3.0
|
||||||
|
# via
|
||||||
|
# httpx
|
||||||
|
# starlette
|
||||||
|
# watchfiles
|
||||||
|
certifi==2024.2.2
|
||||||
|
# via
|
||||||
|
# httpcore
|
||||||
|
# httpx
|
||||||
|
click==8.1.7
|
||||||
|
# via
|
||||||
|
# spud (pyproject.toml)
|
||||||
|
# uvicorn
|
||||||
|
fastapi==0.110.1
|
||||||
|
# via spud (pyproject.toml)
|
||||||
|
h11==0.14.0
|
||||||
|
# via
|
||||||
|
# httpcore
|
||||||
|
# uvicorn
|
||||||
|
httpcore==1.0.5
|
||||||
|
# via httpx
|
||||||
|
httptools==0.6.1
|
||||||
|
# via uvicorn
|
||||||
|
httpx==0.27.0
|
||||||
|
# via spud (pyproject.toml)
|
||||||
|
idna==3.7
|
||||||
|
# via
|
||||||
|
# anyio
|
||||||
|
# httpx
|
||||||
|
pydantic==2.6.4
|
||||||
|
# via
|
||||||
|
# fastapi
|
||||||
|
# spud (pyproject.toml)
|
||||||
|
pydantic-core==2.16.3
|
||||||
|
# via pydantic
|
||||||
|
python-dotenv==1.0.1
|
||||||
|
# via uvicorn
|
||||||
|
pyyaml==6.0.1
|
||||||
|
# via uvicorn
|
||||||
|
sniffio==1.3.1
|
||||||
|
# via
|
||||||
|
# anyio
|
||||||
|
# httpx
|
||||||
|
starlette==0.37.2
|
||||||
|
# via fastapi
|
||||||
|
typing-extensions==4.11.0
|
||||||
|
# via
|
||||||
|
# fastapi
|
||||||
|
# pydantic
|
||||||
|
# pydantic-core
|
||||||
|
uvicorn[standard]==0.29.0
|
||||||
|
# via spud (pyproject.toml)
|
||||||
|
uvloop==0.19.0
|
||||||
|
# via uvicorn
|
||||||
|
watchfiles==0.21.0
|
||||||
|
# via uvicorn
|
||||||
|
websockets==12.0
|
||||||
|
# via uvicorn
|
127
requirements_dev.txt
Normal file
127
requirements_dev.txt
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
annotated-types==0.6.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# pydantic
|
||||||
|
anyio==4.3.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# httpx
|
||||||
|
# starlette
|
||||||
|
# watchfiles
|
||||||
|
astroid==3.1.0
|
||||||
|
# via pylint
|
||||||
|
black==24.3.0
|
||||||
|
# via spud (pyproject.toml)
|
||||||
|
certifi==2024.2.2
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# httpcore
|
||||||
|
# httpx
|
||||||
|
click==8.1.7
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# black
|
||||||
|
# spud (pyproject.toml)
|
||||||
|
# uvicorn
|
||||||
|
dill==0.3.8
|
||||||
|
# via pylint
|
||||||
|
fastapi==0.110.1
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# spud (pyproject.toml)
|
||||||
|
h11==0.14.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# httpcore
|
||||||
|
# uvicorn
|
||||||
|
httpcore==1.0.5
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# httpx
|
||||||
|
httptools==0.6.1
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# uvicorn
|
||||||
|
httpx==0.27.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# spud (pyproject.toml)
|
||||||
|
idna==3.7
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# anyio
|
||||||
|
# httpx
|
||||||
|
iniconfig==2.0.0
|
||||||
|
# via pytest
|
||||||
|
isort==5.13.2
|
||||||
|
# via pylint
|
||||||
|
mccabe==0.7.0
|
||||||
|
# via pylint
|
||||||
|
mypy-extensions==1.0.0
|
||||||
|
# via black
|
||||||
|
packaging==24.0
|
||||||
|
# via
|
||||||
|
# black
|
||||||
|
# pytest
|
||||||
|
pathspec==0.12.1
|
||||||
|
# via black
|
||||||
|
platformdirs==4.2.0
|
||||||
|
# via
|
||||||
|
# black
|
||||||
|
# pylint
|
||||||
|
pluggy==1.4.0
|
||||||
|
# via pytest
|
||||||
|
pydantic==2.6.4
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# fastapi
|
||||||
|
# spud (pyproject.toml)
|
||||||
|
pydantic-core==2.16.3
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# pydantic
|
||||||
|
pylint==3.1.0
|
||||||
|
# via spud (pyproject.toml)
|
||||||
|
pytest==8.1.1
|
||||||
|
# via spud (pyproject.toml)
|
||||||
|
python-dotenv==1.0.1
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# uvicorn
|
||||||
|
pyyaml==6.0.1
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# uvicorn
|
||||||
|
sniffio==1.3.1
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# anyio
|
||||||
|
# httpx
|
||||||
|
starlette==0.37.2
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# fastapi
|
||||||
|
tomlkit==0.12.4
|
||||||
|
# via pylint
|
||||||
|
typing-extensions==4.11.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# fastapi
|
||||||
|
# pydantic
|
||||||
|
# pydantic-core
|
||||||
|
uvicorn[standard]==0.29.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# spud (pyproject.toml)
|
||||||
|
uvloop==0.19.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# uvicorn
|
||||||
|
watchfiles==0.21.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# uvicorn
|
||||||
|
websockets==12.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# uvicorn
|
119
requirements_sast.txt
Normal file
119
requirements_sast.txt
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
annotated-types==0.6.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# pydantic
|
||||||
|
anyio==4.3.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# httpx
|
||||||
|
# starlette
|
||||||
|
# watchfiles
|
||||||
|
astroid==3.1.0
|
||||||
|
# via pylint
|
||||||
|
black==24.3.0
|
||||||
|
# via spud (pyproject.toml)
|
||||||
|
certifi==2024.2.2
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# httpcore
|
||||||
|
# httpx
|
||||||
|
click==8.1.7
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# black
|
||||||
|
# spud (pyproject.toml)
|
||||||
|
# uvicorn
|
||||||
|
dill==0.3.8
|
||||||
|
# via pylint
|
||||||
|
fastapi==0.110.1
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# spud (pyproject.toml)
|
||||||
|
h11==0.14.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# httpcore
|
||||||
|
# uvicorn
|
||||||
|
httpcore==1.0.5
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# httpx
|
||||||
|
httptools==0.6.1
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# uvicorn
|
||||||
|
httpx==0.27.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# spud (pyproject.toml)
|
||||||
|
idna==3.7
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# anyio
|
||||||
|
# httpx
|
||||||
|
isort==5.13.2
|
||||||
|
# via pylint
|
||||||
|
mccabe==0.7.0
|
||||||
|
# via pylint
|
||||||
|
mypy-extensions==1.0.0
|
||||||
|
# via black
|
||||||
|
packaging==24.0
|
||||||
|
# via black
|
||||||
|
pathspec==0.12.1
|
||||||
|
# via black
|
||||||
|
platformdirs==4.2.0
|
||||||
|
# via
|
||||||
|
# black
|
||||||
|
# pylint
|
||||||
|
pydantic==2.6.4
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# fastapi
|
||||||
|
# spud (pyproject.toml)
|
||||||
|
pydantic-core==2.16.3
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# pydantic
|
||||||
|
pylint==3.1.0
|
||||||
|
# via spud (pyproject.toml)
|
||||||
|
python-dotenv==1.0.1
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# uvicorn
|
||||||
|
pyyaml==6.0.1
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# uvicorn
|
||||||
|
sniffio==1.3.1
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# anyio
|
||||||
|
# httpx
|
||||||
|
starlette==0.37.2
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# fastapi
|
||||||
|
tomlkit==0.12.4
|
||||||
|
# via pylint
|
||||||
|
typing-extensions==4.11.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# fastapi
|
||||||
|
# pydantic
|
||||||
|
# pydantic-core
|
||||||
|
uvicorn[standard]==0.29.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# spud (pyproject.toml)
|
||||||
|
uvloop==0.19.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# uvicorn
|
||||||
|
watchfiles==0.21.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# uvicorn
|
||||||
|
websockets==12.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# uvicorn
|
119
requirements_test.txt
Normal file
119
requirements_test.txt
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
annotated-types==0.6.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# pydantic
|
||||||
|
anyio==4.3.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# httpx
|
||||||
|
# starlette
|
||||||
|
# watchfiles
|
||||||
|
astroid==3.1.0
|
||||||
|
# via pylint
|
||||||
|
black==24.3.0
|
||||||
|
# via spud (pyproject.toml)
|
||||||
|
certifi==2024.2.2
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# httpcore
|
||||||
|
# httpx
|
||||||
|
click==8.1.7
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# black
|
||||||
|
# spud (pyproject.toml)
|
||||||
|
# uvicorn
|
||||||
|
dill==0.3.8
|
||||||
|
# via pylint
|
||||||
|
fastapi==0.110.1
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# spud (pyproject.toml)
|
||||||
|
h11==0.14.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# httpcore
|
||||||
|
# uvicorn
|
||||||
|
httpcore==1.0.5
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# httpx
|
||||||
|
httptools==0.6.1
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# uvicorn
|
||||||
|
httpx==0.27.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# spud (pyproject.toml)
|
||||||
|
idna==3.7
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# anyio
|
||||||
|
# httpx
|
||||||
|
isort==5.13.2
|
||||||
|
# via pylint
|
||||||
|
mccabe==0.7.0
|
||||||
|
# via pylint
|
||||||
|
mypy-extensions==1.0.0
|
||||||
|
# via black
|
||||||
|
packaging==24.0
|
||||||
|
# via black
|
||||||
|
pathspec==0.12.1
|
||||||
|
# via black
|
||||||
|
platformdirs==4.2.0
|
||||||
|
# via
|
||||||
|
# black
|
||||||
|
# pylint
|
||||||
|
pydantic==2.6.4
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# fastapi
|
||||||
|
# spud (pyproject.toml)
|
||||||
|
pydantic-core==2.16.3
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# pydantic
|
||||||
|
pylint==3.1.0
|
||||||
|
# via spud (pyproject.toml)
|
||||||
|
python-dotenv==1.0.1
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# uvicorn
|
||||||
|
pyyaml==6.0.1
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# uvicorn
|
||||||
|
sniffio==1.3.1
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# anyio
|
||||||
|
# httpx
|
||||||
|
starlette==0.37.2
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# fastapi
|
||||||
|
tomlkit==0.12.4
|
||||||
|
# via pylint
|
||||||
|
typing-extensions==4.11.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# fastapi
|
||||||
|
# pydantic
|
||||||
|
# pydantic-core
|
||||||
|
uvicorn[standard]==0.29.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# spud (pyproject.toml)
|
||||||
|
uvloop==0.19.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# uvicorn
|
||||||
|
watchfiles==0.21.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# uvicorn
|
||||||
|
websockets==12.0
|
||||||
|
# via
|
||||||
|
# -c requirements.txt
|
||||||
|
# uvicorn
|
12
script/bootstrap.sh
Executable file
12
script/bootstrap.sh
Executable file
|
@ -0,0 +1,12 @@
|
||||||
|
#!/usr/bin/bash
|
||||||
|
|
||||||
|
VENV=spud.venv
|
||||||
|
|
||||||
|
python -m venv --upgrade "$VENV"
|
||||||
|
|
||||||
|
. "$VENV/bin/activate"
|
||||||
|
|
||||||
|
pip install -U pip pip-tools
|
||||||
|
pip-sync requirements.txt requirements_dev.txt
|
||||||
|
|
||||||
|
pip install -e .
|
33
script/lock-deps.sh
Executable file
33
script/lock-deps.sh
Executable file
|
@ -0,0 +1,33 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
|
||||||
|
echo "Generating requirements.txt..."
|
||||||
|
|
||||||
|
python -m piptools compile \
|
||||||
|
-o requirements.txt \
|
||||||
|
pyproject.toml \
|
||||||
|
--no-header
|
||||||
|
|
||||||
|
echo "Generating requirements_dev.txt..."
|
||||||
|
|
||||||
|
python -m piptools compile \
|
||||||
|
-o requirements_dev.txt \
|
||||||
|
--no-header \
|
||||||
|
--extra sast \
|
||||||
|
--extra test \
|
||||||
|
--constraint requirements.txt \
|
||||||
|
pyproject.toml
|
||||||
|
|
||||||
|
python -m piptools compile \
|
||||||
|
-o requirements_sast.txt \
|
||||||
|
--no-header \
|
||||||
|
--extra sast \
|
||||||
|
--constraint requirements.txt \
|
||||||
|
pyproject.toml
|
||||||
|
|
||||||
|
python -m piptools compile \
|
||||||
|
-o requirements_test.txt \
|
||||||
|
--no-header \
|
||||||
|
--extra sast \
|
||||||
|
--constraint requirements.txt \
|
||||||
|
pyproject.toml
|
9
spud/base.py
Normal file
9
spud/base.py
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
"""
|
||||||
|
Models and datastructures
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pydantic
|
||||||
|
|
||||||
|
|
||||||
|
class Configuration(pydantic.BaseModel):
|
||||||
|
"""Command line application configuration options"""
|
71
spud/cli.py
Normal file
71
spud/cli.py
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
"""
|
||||||
|
Command-line application entry-point.
|
||||||
|
|
||||||
|
Logic for the command-line spud tooling.
|
||||||
|
"""
|
||||||
|
import pathlib
|
||||||
|
import json
|
||||||
|
|
||||||
|
import click
|
||||||
|
|
||||||
|
from spud.base import Configuration
|
||||||
|
|
||||||
|
DEFAULT_CONFIGURATION_PATH = "~/.config/spud/config.json"
|
||||||
|
|
||||||
|
|
||||||
|
@click.group()
|
||||||
|
@click.option(
|
||||||
|
"--config",
|
||||||
|
type=str,
|
||||||
|
default=None,
|
||||||
|
help="Configuration path",
|
||||||
|
)
|
||||||
|
@click.pass_context
|
||||||
|
def cli(context, config):
|
||||||
|
"""CLI root"""
|
||||||
|
context.ensure_object(dict)
|
||||||
|
config = config if config is not None else DEFAULT_CONFIGURATION_PATH
|
||||||
|
context.obj["config_path"] = pathlib.Path(config).expanduser()
|
||||||
|
|
||||||
|
|
||||||
|
@click.command()
|
||||||
|
@click.pass_context
|
||||||
|
def init(context):
|
||||||
|
"""Generates a default configuration and writes it to disk."""
|
||||||
|
config_path = context.obj["config_path"]
|
||||||
|
|
||||||
|
config_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
if config_path.exists():
|
||||||
|
raise RuntimeError(
|
||||||
|
f"File already exists ({str(config_path)}), cannot initialize."
|
||||||
|
)
|
||||||
|
|
||||||
|
default_configuration = Configuration()
|
||||||
|
|
||||||
|
with open(config_path, "w", encoding="utf8") as config_file:
|
||||||
|
config_file.write(default_configuration.model_dump_json(indent=2))
|
||||||
|
|
||||||
|
|
||||||
|
@click.command()
|
||||||
|
@click.pass_context
|
||||||
|
def print_config(context):
|
||||||
|
"""Prints the current configuration."""
|
||||||
|
config_path = context.obj["config_path"]
|
||||||
|
|
||||||
|
if not config_path.exists():
|
||||||
|
raise RuntimeError(f"Configuration file not found at {str(config_path)}.")
|
||||||
|
|
||||||
|
with open(config_path, "r", encoding="utf8") as config_file:
|
||||||
|
config_json = json.loads(config_file.read())
|
||||||
|
|
||||||
|
config = Configuration(**config_json)
|
||||||
|
|
||||||
|
click.echo(config.model_dump_json(indent=2))
|
||||||
|
|
||||||
|
|
||||||
|
cli.add_command(init)
|
||||||
|
cli.add_command(print_config)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
cli(None, None)
|
18
tests/conftest.py
Normal file
18
tests/conftest.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import pytest
|
||||||
|
import click.testing
|
||||||
|
import importlib
|
||||||
|
|
||||||
|
import spud.cli
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def mock_default_config_path(monkeypatch, tmpdir):
|
||||||
|
monkeypatch.setattr(spud.cli, "DEFAULT_CONFIGURATION_PATH", tmpdir / ".config" / "spud" / "config.json")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="invoke_cli")
|
||||||
|
def invoke_cli_fixture():
|
||||||
|
def _call_cli(args: list[str]):
|
||||||
|
runner = click.testing.CliRunner()
|
||||||
|
return runner.invoke(spud.cli.cli, args)
|
||||||
|
|
||||||
|
return _call_cli
|
40
tests/test_cli.py
Normal file
40
tests/test_cli.py
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import pytest
|
||||||
|
import click
|
||||||
|
|
||||||
|
import pathlib
|
||||||
|
|
||||||
|
def test_init_raises_if_config_file_exists_default_path(invoke_cli, tmpdir, monkeypatch):
|
||||||
|
expected_default_path = tmpdir / ".config" / "spud" / "config.json"
|
||||||
|
|
||||||
|
pathlib.Path(expected_default_path).parent.mkdir(parents=True)
|
||||||
|
expected_default_path.write("{}")
|
||||||
|
|
||||||
|
result = invoke_cli(["init"])
|
||||||
|
|
||||||
|
assert result.exit_code == 1
|
||||||
|
assert str(result.exception) == f"File already exists ({str(expected_default_path)}), cannot initialize."
|
||||||
|
|
||||||
|
def test_init_raises_if_config_file_exists_custom_path(invoke_cli, tmpdir, monkeypatch):
|
||||||
|
expected_default_path = tmpdir / "config.json"
|
||||||
|
|
||||||
|
expected_default_path.write("{}")
|
||||||
|
|
||||||
|
result = invoke_cli(["--config", str(expected_default_path), "init"])
|
||||||
|
|
||||||
|
assert result.exit_code == 1
|
||||||
|
assert str(result.exception) == f"File already exists ({str(expected_default_path)}), cannot initialize."
|
||||||
|
|
||||||
|
def test_print_config_raises_if_no_config_file_default_path(invoke_cli, tmpdir, monkeypatch):
|
||||||
|
expected_default_path = tmpdir / ".config" / "spud" / "config.json"
|
||||||
|
result = invoke_cli(["print-config"])
|
||||||
|
|
||||||
|
assert result.exit_code == 1
|
||||||
|
assert str(result.exception) == f"Configuration file not found at {str(expected_default_path)}."
|
||||||
|
|
||||||
|
def test_print_config_raises_if_no_config_file_custom_path(invoke_cli, tmpdir, monkeypatch):
|
||||||
|
config_file = tmpdir / "config.json"
|
||||||
|
|
||||||
|
result = invoke_cli(["--config", str(config_file), "print-config"])
|
||||||
|
|
||||||
|
assert result.exit_code == 1
|
||||||
|
assert str(result.exception) == f"Configuration file not found at {str(config_file)}."
|
Reference in a new issue