Skip to content

Commit

Permalink
Add lazy commands (#51)
Browse files Browse the repository at this point in the history
* Add lazy commands

* Add Lazy group
  • Loading branch information
lsbardel authored Feb 2, 2025
1 parent b9f9b1e commit 4d9a989
Show file tree
Hide file tree
Showing 13 changed files with 162 additions and 112 deletions.
4 changes: 4 additions & 0 deletions .dev/lint
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
#!/usr/bin/env bash
set -e

ISORT_ARGS="-c"
BLACK_ARG="--check"
RUFF_ARG=""

if [ "$1" = "fix" ] ; then
ISORT_ARGS=""
BLACK_ARG=""
RUFF_ARG="--fix"
fi

echo isort
isort fluid tests examples ${ISORT_ARGS}
echo "run black"
black fluid tests examples ${BLACK_ARG}
echo "run ruff"
Expand Down
12 changes: 12 additions & 0 deletions examples/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import dotenv

dotenv.load_dotenv()

from fluid.scheduler.cli import TaskManagerCLI # isort:skip # noqa: E402

task_manager_cli = TaskManagerCLI(
"examples.tasks:task_app", lazy_subcommands={"db": "examples.db.cli:cli"}
)


task_manager_cli()
3 changes: 3 additions & 0 deletions examples/db/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from examples.db import get_db

cli = get_db().cli()
2 changes: 1 addition & 1 deletion examples/db/migrations/versions/1f91ed2b2f26_initial.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""initial
Revision ID: 1f91ed2b2f26
Revises:
Revises:
Create Date: 2024-08-18 10:19:38.372777
"""
Expand Down
10 changes: 0 additions & 10 deletions examples/main_db.py

This file was deleted.

7 changes: 0 additions & 7 deletions examples/main_tasks.py

This file was deleted.

2 changes: 1 addition & 1 deletion fluid/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Reusable server side python modules"""

__version__ = "1.2.2"
__version__ = "1.2.3"
9 changes: 7 additions & 2 deletions fluid/scheduler/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from uvicorn.importer import import_from_string

from fluid.utils import log
from fluid.utils.lazy import LazyGroup

if TYPE_CHECKING:
from .consumer import TaskManager
Expand All @@ -19,8 +20,12 @@
TaskManagerApp = FastAPI | Callable[..., Any] | str


class TaskManagerCLI(click.Group):
def __init__(self, task_manager_app: TaskManagerApp, **kwargs: Any):
class TaskManagerCLI(LazyGroup):
def __init__(
self,
task_manager_app: TaskManagerApp,
**kwargs: Any,
):
kwargs.setdefault("commands", DEFAULT_COMMANDS)
super().__init__(**kwargs)
self.task_manager_app = task_manager_app
Expand Down
3 changes: 1 addition & 2 deletions fluid/scheduler/crontab.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""Originally from https://github.com/coleifer/huey
"""
"""Originally from https://github.com/coleifer/huey"""

import re
from abc import ABC, abstractmethod
Expand Down
41 changes: 41 additions & 0 deletions fluid/utils/lazy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from importlib import import_module
from typing import Any

import click


class LazyGroup(click.Group):
def __init__(
self,
*,
lazy_subcommands: dict[str, str] | None = None,
**kwargs: Any,
):
super().__init__(**kwargs)
self.lazy_subcommands = lazy_subcommands or {}

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

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:
# lazily loading a command, first get the module name and attribute name
import_path = self.lazy_subcommands[cmd_name]
modname, cmd_object_name = import_path.rsplit(":", 1)
# do the import
mod = import_module(modname)
# get the Command object from that module
cmd_object = getattr(mod, cmd_object_name)
# check the result to make debugging easier
if not isinstance(cmd_object, click.Command):
raise ValueError(
f"Lazy loading of {import_path} failed by returning "
"a non-command object"
)
return cmd_object
Loading

0 comments on commit 4d9a989

Please sign in to comment.