cli improved
This commit is contained in:
parent
44bfa767a6
commit
2fc2732a65
@ -1,3 +1,12 @@
|
||||
## Usage
|
||||
|
||||
```
|
||||
por bkr --recipe examples.fruits.recipe show
|
||||
por bkr --recipe examples.fruits.recipe reset
|
||||
por bkr --recipe examples.fruits.recipe run --input words=examples/fruits.csv
|
||||
por bkr --recipe examples.fruits.recipe show
|
||||
```
|
||||
|
||||
## Michael's Email
|
||||
|
||||
### Data Dictionay
|
||||
|
@ -5,6 +5,10 @@ description = ""
|
||||
authors = ["James Turk <dev@jamesturk.net>"]
|
||||
readme = "README.md"
|
||||
|
||||
[tool.poetry.scripts]
|
||||
bkr = 'beakers.cli:app'
|
||||
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.11"
|
||||
scrapeghost = {path = "../scrapeghost", develop = true}
|
||||
|
@ -23,6 +23,10 @@ class Beaker(abc.ABC):
|
||||
def add_item(self, item: dict, from_table=None, from_id=None) -> None:
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def reset(self):
|
||||
pass
|
||||
|
||||
|
||||
class TempBeaker(Beaker):
|
||||
def __init__(self, name: str, recipe):
|
||||
@ -38,6 +42,9 @@ class TempBeaker(Beaker):
|
||||
def items(self):
|
||||
yield from self._items
|
||||
|
||||
def reset(self):
|
||||
self._items = []
|
||||
|
||||
|
||||
class SqliteBeaker(Beaker):
|
||||
def __init__(self, name: str, recipe):
|
||||
@ -64,3 +71,7 @@ class SqliteBeaker(Beaker):
|
||||
f"INSERT INTO {self.name} (data) VALUES (?)", (json.dumps(item),)
|
||||
)
|
||||
self.recipe.db.commit()
|
||||
|
||||
def reset(self):
|
||||
self.cursor.execute(f"DELETE FROM {self.name}")
|
||||
self.recipe.db.commit()
|
||||
|
@ -1,9 +1,12 @@
|
||||
import importlib
|
||||
from types import SimpleNamespace
|
||||
import typer
|
||||
import sys
|
||||
from typing import List, Optional
|
||||
from typing_extensions import Annotated
|
||||
|
||||
from beakers.beakers import SqliteBeaker
|
||||
|
||||
app = typer.Typer()
|
||||
|
||||
|
||||
@ -14,28 +17,49 @@ def _load_recipe(dotted_path: str):
|
||||
return getattr(mod, name)
|
||||
|
||||
|
||||
@app.command()
|
||||
def reset(recipe: Annotated[str, typer.Option(...)]):
|
||||
mod = _load_recipe(recipe)
|
||||
mod.reset()
|
||||
@app.callback()
|
||||
def main(
|
||||
ctx: typer.Context,
|
||||
recipe: str = typer.Option(None, envvar="BEAKER_RECIPE"),
|
||||
):
|
||||
if not recipe:
|
||||
typer.secho(
|
||||
"Missing recipe; pass --recipe or set env[BEAKER_RECIPE]",
|
||||
fg=typer.colors.RED,
|
||||
)
|
||||
raise typer.Exit(1)
|
||||
ctx.obj = _load_recipe(recipe)
|
||||
|
||||
|
||||
@app.command()
|
||||
def show(recipe: Annotated[str, typer.Option(...)]):
|
||||
mod = _load_recipe(recipe)
|
||||
mod.show()
|
||||
def reset(ctx: typer.Context):
|
||||
for beaker in ctx.obj.beakers.values():
|
||||
if isinstance(beaker, SqliteBeaker):
|
||||
if bl := len(beaker):
|
||||
beaker.reset()
|
||||
typer.secho(f"{beaker.name} reset ({bl})", fg=typer.colors.RED)
|
||||
else:
|
||||
typer.secho(f"{beaker.name} empty", fg=typer.colors.GREEN)
|
||||
|
||||
|
||||
@app.command()
|
||||
def show(ctx: typer.Context):
|
||||
ctx.obj.show()
|
||||
|
||||
|
||||
@app.command()
|
||||
def run(
|
||||
recipe: Annotated[str, typer.Option(...)],
|
||||
ctx: typer.Context,
|
||||
input: Annotated[Optional[List[str]], typer.Option(...)] = None,
|
||||
):
|
||||
mod = _load_recipe(recipe)
|
||||
has_data = any(ctx.obj.beakers.values())
|
||||
if not has_data and not input:
|
||||
typer.secho("No data; pass --input to seed beaker(s)", fg=typer.colors.RED)
|
||||
raise typer.Exit(1)
|
||||
for input_str in input:
|
||||
beaker, filename = input_str.split("=")
|
||||
mod.csv_to_beaker(filename, beaker)
|
||||
mod.run_once()
|
||||
ctx.obj.csv_to_beaker(filename, beaker)
|
||||
ctx.obj.run_once()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -152,6 +152,14 @@ class Recipe:
|
||||
for from_b, to_b, edge in self.graph.out_edges(node, data=True):
|
||||
print(f" {from_b} -> {to_b} ({edge})")
|
||||
|
||||
def reset(self):
|
||||
count = 0
|
||||
for beaker in self.beakers.values():
|
||||
if isinstance(beaker, SqliteBeaker):
|
||||
beaker.reset()
|
||||
count += 1
|
||||
typer.secho(f"reset {count} beakers")
|
||||
|
||||
def run_once(self):
|
||||
log.info("run_once", recipe=self)
|
||||
loop = asyncio.get_event_loop()
|
||||
|
Loading…
Reference in New Issue
Block a user