Skip to content
This repository has been archived by the owner on Dec 27, 2023. It is now read-only.

Commit

Permalink
wip moving to cappa
Browse files Browse the repository at this point in the history
  • Loading branch information
Tobi-De committed Nov 18, 2023
1 parent 5bbfc89 commit 05d012d
Show file tree
Hide file tree
Showing 8 changed files with 289 additions and 109 deletions.
57 changes: 57 additions & 0 deletions fuzzy_couscous/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from dataclasses import dataclass, field
import cappa
from typing import Any, Literal
from typing_extensions import Annotated
import rich


from .commands import Make, HtmxExt




@cappa.command(help="Download the latest version of htmx.")
class Htmx:
pass



@cappa.command(help="Clean up all migrations.")
class RmMigrations:
pass


@cappa.command(help="Remove poetry from your project.")
class RmPoetry:
pass


@cappa.command(help="Run multiple processes in parallel.")
class Work:
pass


@cappa.command(help="Update or create a .env file from a .env.template file.")
class WriteEnv:
pass


@cappa.command(
help="Initialize a new django project using the fuzzy-couscous project template.",
description="""This is a wrapper around the django-admin startproject command using my custom project template at
https://github.com/Tobi-De/fuzzy-couscous. This cli also includes some additional commands to make setting up
a new project faster.
""",
)
class Toji:
subcommand: cappa.Subcommands[
Make | Htmx | HtmxExt | RmMigrations | RmPoetry | Work | WriteEnv
]


def main():
cappa.invoke(Toji)


if __name__ == "__main__":
main()
3 changes: 2 additions & 1 deletion fuzzy_couscous/commands/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from .htmx import htmx # noqa
from .make import make_project # noqa
from .htmx_ext import HtmxExt # noqa
from .make import Make # noqa
from .remove_poetry import remove_poetry # noqa
from .rm_migrations import rm_migrations # noqa
from .work import work # noqa
Expand Down
52 changes: 52 additions & 0 deletions fuzzy_couscous/commands/htmx_ext.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from typing import Any
import cappa

from pathlib import Path

THIRD_PARY_REGISTRY = {
"htmx-template": {
"file": "https://raw.githubusercontent.com/KatrinaKitten/htmx-template/master/htmx-template.min.js",
"url": "https://github.com/KatrinaKitten/htmx-template",
},
"hx-take": {
"file": "https://github.com/oriol-martinez/hx-take/blob/main/dist/hx-take.min.js",
"url": "https://github.com/oriol-martinez/hx-take",
},
}



@cappa.command(help="Download one of htmx extensions.")
class HtmxExt:
name: str | None = cappa.Arg(
None,
help="The name of the extension to download.",
choices=THIRD_PARY_REGISTRY.keys(),
)
version: str = cappa.Arg(
"latest",
short="-v",
long="--version",
help="The version of htmx to use to look for the extension.",
)
output : Path = cappa.Arg(default=Path.cwd(), help="The directory to write the downloaded file to.", short="-o", long="--output")


def __call__(self) -> None:
if self.name:
self.download(self.name)
else:
self.list_all()


def download(self):
pass

def list_all(self):
pass

@classmethod
def official_regitry(cls, htmx_version: str):
base_url = f"https://unpkg.com/htmx.org@{htmx_version}/dist/ext/"


230 changes: 126 additions & 104 deletions fuzzy_couscous/commands/make.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,119 +19,124 @@
from ..utils import RICH_INFO_MARKER
from ..utils import RICH_SUCCESS_MARKER
from ..utils import write_toml
from typing import Annotated
import cappa
import rich
from rich.prompt import Prompt

__all__ = ["make_project"]
__all__ = ["Make"]

try:
from enum import StrEnum
except ImportError:
from enum import Enum

class StrEnum(str, Enum):
pass


class Branch(StrEnum):
main = "main"
tailwind = "tailwind"
bootstrap = "bootstrap"

def _get_user_git_infos() -> tuple[str, str] | None:
git_config_cmd = ["git", "config", "--global", "--get"]
try:
user_name_cmd = subprocess.run(
git_config_cmd + ["user.name"], capture_output=True, text=True
)
user_email_cmd = subprocess.run(
git_config_cmd + ["user.email"], capture_output=True, text=True
)
except FileNotFoundError:
return None
if user_email_cmd.returncode != 0:
return None
return (
user_name_cmd.stdout.strip("\n"),
user_email_cmd.stdout.strip("\n"),
)


def _set_authors_in_pyproject(file: Path, name: str, email: str) -> None:
config = read_toml(file)
deep_set(config, "tool.poetry.authors", [f"{name} <{email}>"])
write_toml(file, config)


def make_project(
project_name: str = typer.Argument(..., callback=clean_project_name),
repo: str = typer.Option(
"Tobi-De/fuzzy-couscous",
"-r",
"--repo",
help="The github repository to pull the template from. The format to use is `username/repo`",
formats=["username/repo"],
),
branch: Branch = typer.Option(
"main", "-b", "--branch", help="The github branch to use."
),
skip_deps_install: bool = typer.Option(
False,
"-s",
"--skip-install",
flag_value=True,
help="Skip dependencies installation",
),
):
"""Initialize a new django project."""

version = django.get_version()
if int(version.split(".")[0]) < 4:
rich_print(f"{RICH_ERROR_MARKER} Django version must be greater than 4.0")
raise typer.Abort()

if Path(project_name).exists():
rich_print(
f"{RICH_ERROR_MARKER} A directory with the name {project_name} already exists in the current directory "
f":disappointed_face:"
)
raise typer.Abort()

with Progress(
SpinnerColumn(),
TextColumn("[progress.description]{task.description}"),
transient=True,
) as progress:
progress.add_task(
description="Initializing your new django project... :sunglasses:",
total=None,
)

if template_dir := get_template_dir(repo, branch):
# run the django-admin command
subprocess.run(
[
"django-admin",
"startproject",
project_name,
"--template",
template_dir,
"-e=py,html,toml,md,json,js,sh",
"--exclude=docs",
"--exclude=fuzzy_couscous",
"--exclude=.github",
"--exclude=.idea",
]
@cappa.command(help="Initialize a new django project.")
class Make:
@staticmethod
def clean_project_name(project_name: str) -> str:
return project_name.strip("/")

project_name: Annotated[
str,
cappa.Arg(parse=clean_project_name),
]
branch: Annotated[Branch, cappa.Arg(default=Branch.main, short="-b", long="--branch")]

def __post_init__(self):
self.project_path = Path(self.project_name)

def __call__(self) -> None:
if self.project_path.exists():
rich_print(
f"{RICH_ERROR_MARKER} A directory with the name {self.project_name} already exists in the current directory "
f":disappointed_face:"
)
raise cappa.Exit()


self.init_project()

else:
raise typer.Abort(
f"{RICH_ERROR_MARKER} Couldn't download or find the template to use, check your connection."
self.update_authors()

if self.branch != "main":
self.apply_branch_patch()

if (
Prompt.ask(
"Do you want to install the dependencies? (y/N)", choices=["y", "n"]
)
== "y"
):
self.install_dependencies()

project_dir = Path(project_name)
msg = f"{RICH_SUCCESS_MARKER} Project initialized, keep up the good work!\n"
msg += (
f"{RICH_INFO_MARKER} If you like the project consider dropping a star at "
f"https://github.com/Tobi-De/fuzzy-couscous"
)

if user_infos := _get_user_git_infos():
name, email = user_infos
_set_authors_in_pyproject(
project_dir / "pyproject.toml", name=name, email=email
)

msg = f"{RICH_SUCCESS_MARKER} Project initialized, keep up the good work!\n"
msg += (
f"\n{RICH_INFO_MARKER} A git global user configuration was found and used to update the authors in your "
f"pyproject.toml file."
f"{RICH_INFO_MARKER} If you like the project consider dropping a star at "
f"https://github.com/Tobi-De/fuzzy-couscous"
)

if not skip_deps_install:
rich_print(msg)

def init_project(self) -> None:
with Progress(
SpinnerColumn(),
TextColumn("[progress.description]{task.description}"),
transient=True,
) as progress:
progress.add_task(
description="Initializing your new django project... :sunglasses:",
total=None,
)

if template_dir := get_template_dir(self.branch):
# run the django-admin command
subprocess.run(
[
"django-admin",
"startproject",
self.project_name,
"--template",
template_dir,
"-e=py,html,toml,md,json,js,sh",
"--exclude=docs",
"--exclude=fuzzy_couscous",
"--exclude=.github",
"--exclude=.idea",
]
)

else:
raise typer.Abort(
f"{RICH_ERROR_MARKER} Couldn't download or find the template to use, check your connection."
)

def update_authors(self) -> None:
name, email = self.get_git_user_infos()
if not name:
name = Prompt.ask("Enter your name")
if not email:
email = Prompt.ask("Enter your email")
pyproject_file = self.project_path / "pyproject.toml"
project_config = read_toml(self.project_path / "pyproject.toml")
deep_set(project_config, "tool.poetry.authors", [f"{name} <{email}>"])
write_toml(pyproject_file, project_config)

def apply_branch_patch(self) -> None:
pass

def install_dependencies(self) -> None:
with Progress(
SpinnerColumn(),
TextColumn("[progress.description]{task.description}"),
Expand All @@ -142,10 +147,27 @@ def make_project(
)
subprocess.call(
["poetry install --with dev"],
cwd=project_dir,
cwd=self.project_path,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
shell=True,
)

rich_print(msg)
@staticmethod
def get_git_user_infos():
git_config_cmd = ["git", "config", "--global", "--get"]
try:
user_name_cmd = subprocess.run(
git_config_cmd + ["user.name"], capture_output=True, text=True
)
user_email_cmd = subprocess.run(
git_config_cmd + ["user.email"], capture_output=True, text=True
)
except FileNotFoundError:
return None
if user_email_cmd.returncode != 0:
return None
return (
user_name_cmd.stdout.strip("\n"),
user_email_cmd.stdout.strip("\n"),
)
6 changes: 3 additions & 3 deletions fuzzy_couscous/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def _get_project_template_folder(root_folder: Path) -> str:
return str((root_folder / "templates" / "project_name").resolve(strict=True))


def get_template_dir(repo: str, branch: Branch) -> str | None:
def get_template_dir(branch: Branch) -> str | None:
app_dir = Path(typer.get_app_dir(APP_NAME))
app_dir.mkdir(exist_ok=True, parents=True)
# check if connection is available
Expand All @@ -48,11 +48,11 @@ def get_template_dir(repo: str, branch: Branch) -> str | None:
templates_dir = app_dir / username
templates_dir.mkdir(exist_ok=True, parents=True)

template_dir = templates_dir / f"{repository}-{branch}"
template_dir = templates_dir / f"{repo}-{branch}"

try:
# download the archive
archive_url = f"https://github.com/{repo}/archive/{branch}.zip"
archive_url = f"https://github.com/tobi-de/fuzzy-couscous/archive/main.zip"
archive_path = app_dir / f"{secrets.token_urlsafe(32)}.zip"
download_archive(archive_url, archive_path)
except httpx.ConnectError:
Expand Down
Loading

0 comments on commit 05d012d

Please sign in to comment.