Skip to content

Commit e09dcf4

Browse files
committed
✨(cli) make the -b/--backend option a CLI sub-command
With the addition of more backends, the usage documentation of the ralph list/read/write and runserver commands became cluttered as we list all available backends with all their options. Thus, to keep the documentation concise, we choose to remove the -b/--backend option and use a backend sub-command instead. This allows us to have dedicated usage documentation for each backend. We also improve backend documentation by parsing method and settings docstrings to construct option help strings.
1 parent dede576 commit e09dcf4

19 files changed

+2315
-886
lines changed

.env.dist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ RALPH_BACKENDS__DATA__CLICKHOUSE__TEST_TABLE_NAME=test_xapi_events_all
136136

137137
# LRS HTTP backend
138138

139-
RALPH_BACKENDS__DATA__LRS__BASE_URL=http://ralph:secret@0.0.0.0:8100/
139+
RALPH_BACKENDS__DATA__LRS__BASE_URL=http://0.0.0.0:8100/
140140
RALPH_BACKENDS__DATA__LRS__USERNAME=ralph
141141
RALPH_BACKENDS__DATA__LRS__PASSWORD=secret
142142
RALPH_BACKENDS__DATA__LRS__HEADERS__X_EXPERIENCE_API_VERSION=1.0.3

docs/commands.md renamed to docs/cli.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Commands
1+
# CLI
22

33
::: mkdocs-click
44
:module: ralph.cli

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ markdown_extensions:
4444
nav:
4545
- Ralph: index.md
4646
- Features:
47+
- CLI: cli.md
4748
- LRS HTTP server: features/api.md
4849
- Backends for data storage: features/backends.md
4950
- Learning statements models: features/models.md

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ cli = [
8484
"bcrypt>=4.0.0",
8585
"click>=8.1.0",
8686
"click-option-group>=0.5.0",
87+
"docstring-parser>=0.15",
8788
"sentry-sdk[fastapi]>=1.9.0",
8889
]
8990
dev = [

src/ralph/backends/data/async_ws.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from typing import AsyncIterator, Optional, Union
55

66
import websockets
7-
from pydantic import AnyUrl, PositiveInt
7+
from pydantic import AnyUrl, PositiveInt, parse_obj_as
88
from websockets.http import USER_AGENT
99

1010
from ralph.backends.data.base import (
@@ -74,7 +74,7 @@ class Config(BaseSettingsConfig):
7474
env_prefix = "RALPH_BACKENDS__DATA__WS__"
7575

7676
CLIENT_OPTIONS: WSClientOptions = WSClientOptions()
77-
URI: AnyUrl
77+
URI: Optional[AnyUrl] = parse_obj_as(AnyUrl, "ws://localhost:8765")
7878

7979

8080
class AsyncWSDataBackend(BaseAsyncDataBackend[WSDataBackendSettings, str]):

src/ralph/backends/data/base.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -666,8 +666,11 @@ async def _queue_records(
666666
await queue.put(None)
667667

668668

669+
DataBackend = TypeVar("DataBackend", BaseDataBackend, BaseAsyncDataBackend)
670+
671+
669672
def get_backend_generic_argument(
670-
backend_class: Type[Union[BaseDataBackend, BaseAsyncDataBackend]],
673+
backend_class: Type[DataBackend],
671674
position: DataBackendArgument,
672675
) -> Optional[Type]:
673676
"""Return the generic argument of `backend_class` at specified `position`."""
@@ -700,9 +703,7 @@ def get_backend_generic_argument(
700703
return None
701704

702705

703-
def set_backend_settings_class(
704-
backend_class: Type[Union[BaseDataBackend, BaseAsyncDataBackend]]
705-
) -> None:
706+
def set_backend_settings_class(backend_class: Type[DataBackend]) -> None:
706707
"""Set `settings_class` attribute with `Config.env_prefix` for `backend_class`."""
707708
settings_class = get_backend_generic_argument(
708709
backend_class, DataBackendArgument.SETTINGS
@@ -711,9 +712,7 @@ def set_backend_settings_class(
711712
backend_class.settings_class = settings_class
712713

713714

714-
def set_backend_query_class(
715-
backend_class: Type[Union[BaseDataBackend, BaseAsyncDataBackend]]
716-
) -> None:
715+
def set_backend_query_class(backend_class: Type[DataBackend]) -> None:
717716
"""Set `query_class` attribute for `backend_class`."""
718717
query_class = get_backend_generic_argument(backend_class, DataBackendArgument.QUERY)
719718
if query_class:

src/ralph/backends/data/mixins.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import json
44
import logging
5+
from typing import Callable
56

67
from ralph.conf import settings
78

@@ -16,7 +17,7 @@ class HistoryMixin:
1617
"""
1718

1819
@property
19-
def history(self):
20+
def history(self) -> list:
2021
"""Get backend history."""
2122
logger.debug("Loading history file: %s", str(settings.HISTORY_FILE))
2223

@@ -25,12 +26,12 @@ def history(self):
2526
with settings.HISTORY_FILE.open(
2627
encoding=settings.LOCALE_ENCODING
2728
) as history_file:
28-
self._history = json.load(history_file)
29+
self._history: list = json.load(history_file)
2930
except FileNotFoundError:
3031
self._history = []
3132
return self._history
3233

33-
def write_history(self, history):
34+
def write_history(self, history: list) -> None:
3435
"""Write given history as a JSON file."""
3536
logger.debug("Writing history file: %s", str(settings.HISTORY_FILE))
3637

@@ -45,22 +46,22 @@ def write_history(self, history):
4546
# Update history
4647
self._history = history
4748

48-
def clean_history(self, selector):
49+
def clean_history(self, selector: Callable[[dict], bool]) -> None:
4950
"""Clean selected events from the history.
5051
5152
selector: a callable that selects events that need to be removed
5253
"""
5354
self._history = list(filter(lambda event: not selector(event), self.history))
5455
self.write_history(self._history)
5556

56-
def append_to_history(self, event):
57+
def append_to_history(self, event: dict) -> None:
5758
"""Append event to history."""
5859
self.write_history(self.history + [event])
5960

60-
def get_command_history(self, backend_name, command):
61+
def get_command_history(self, backend_name: str, command: str) -> list:
6162
"""Extract entry ids from the history for a given command and backend_name."""
6263

63-
def filter_by_name_and_command(entry):
64+
def filter_by_name_and_command(entry: dict) -> bool:
6465
"""Check whether the history entry matches the backend_name and command."""
6566
return entry.get("backend") == backend_name and (
6667
command in [entry.get("command"), entry.get("action")]

0 commit comments

Comments
 (0)