Skip to content

Commit

Permalink
feat: Documentation for metricq_command
Browse files Browse the repository at this point in the history
  • Loading branch information
devmaxde committed Nov 12, 2024
1 parent c491bda commit 497bd92
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 15 deletions.
82 changes: 82 additions & 0 deletions docs/api/cli.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
CLI
==================================



This package provides CLI utilities and decorators for MetricQ applications, including custom parameter types for choices, durations, timestamps, templates, and metrics.

To use this part of the package you need to install additional dependencies. You can install the dependencies using the following command:

.. code-block:: bash
pip install "metricq[cli]"
..
Wrapper
------------------

@metricq_command
^^^^^^^^^^^^^^^^^^

Decorates a function to create a MetricQ CLI command with options for server and token configuration.
Server and Token must be in the right order.

**Parameters**

- **default_token** (`str`): The default client token for the MetricQ network.

**Usage**

.. code-block:: python
@metricq_command(default_token="example.program")
def example(
server: str, token: str
) -> None:
pass
if __name__ == "__main__":
example()
..

@metricq_metric_option
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Defines an option for specifying one or more metrics. Should be used in combination with @metricq_command().
If multiple is set to true, the return type changes to List[metric]

**Parameters**

- **default** (`Optional[str]`, optional): The default metric. Defaults to `None`.
- **multiple** (`bool`, optional): If `True`, allows multiple metrics to be specified. Defaults to `False`.
- **required** (`bool`, optional): If `True`, makes the option required. Defaults to `False`.

**Usage**

.. code-block:: python
@metricq_command(default_token="example.program")
@metricq_metricq_option(required=true, default="example.metric")
def metric_example(
server: str, token: str, metric: Metric
) -> None:
pass
@metricq_command(default_token="example.program")
@metricq_metricq_option(required=true, multiple=True) # <-- multiple is set
def multi_metric_example(
server: str, token: str, metric: List[Metric]
) -> None:
pass
..
Parameter
----------------

.. automodule:: metricq.cli.params
:members:
:exclude-members: get_metavar, convert, name
1 change: 1 addition & 0 deletions docs/api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ API Reference
client-common
exceptions
misc
cli
9 changes: 1 addition & 8 deletions metricq/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,7 @@
TemplateStringParam,
TimestampParam,
)
from .wrapper import (
metricq_command,
metricq_metric_option,
metricq_server_option,
metricq_token_option,
)
from .wrapper import metricq_command, metricq_metric_option

__all__ = [
"ChoiceParam",
Expand All @@ -22,6 +17,4 @@
"MetricParam",
"metricq_command",
"metricq_metric_option",
"metricq_server_option",
"metricq_token_option",
]
38 changes: 31 additions & 7 deletions metricq/cli/params.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
from string import Template
from typing import Any, Generic, List, Optional, Type, TypeVar, Union, cast

from click import Context, Parameter, ParamType
import click
from click import Context, ParamType

from ..timeseries import Timedelta, Timestamp

Expand Down Expand Up @@ -50,13 +51,13 @@ def __init__(self, cls: Type[ChoiceType], name: str):
self.cls = cls
self.name = name

def get_metavar(self, param: Parameter) -> str:
def get_metavar(self, param: click.Parameter) -> str:
return f"({'|'.join(self.cls.as_choice_list())})"

def convert(
self,
value: Union[str, ChoiceType],
param: Optional[Parameter],
param: Optional[click.Parameter],
ctx: Optional[Context],
) -> Optional[ChoiceType]:
if value is None:
Expand All @@ -76,6 +77,13 @@ def convert(


class DurationParam(ParamType):
"""
Convert strings to ``metricq.Timedelta`` objects.
Accepts the following string inputs
- <value>[<unit>]
"""

name = "duration"

def __init__(self, default: Optional[Timedelta]):
Expand All @@ -84,7 +92,7 @@ def __init__(self, default: Optional[Timedelta]):
def convert(
self,
value: Union[str, Timedelta],
param: Optional[Parameter],
param: Optional[click.Parameter],
ctx: Optional[Context],
) -> Optional[Timedelta]:
if value is None:
Expand Down Expand Up @@ -131,7 +139,7 @@ def _convert(value: str) -> Timestamp:
return Timestamp.from_iso8601(value)

def convert(
self, value: Any, param: Optional[Parameter], ctx: Optional[Context]
self, value: Any, param: Optional[click.Parameter], ctx: Optional[Context]
) -> Optional[Timestamp]:
if value is None:
return None
Expand All @@ -152,6 +160,13 @@ def convert(


class TemplateStringParam(ParamType):
"""
A custom parameter type for Click, enabling template-based string substitution
with dynamic values for 'USER' and 'HOST'.
"""

name = "text"
mapping: dict[str, str]

Expand All @@ -163,18 +178,27 @@ def __init__(self) -> None:
self.mapping["HOST"] = gethostname()

def convert(
self, value: Any, param: Optional[Parameter], ctx: Optional[Context]
self, value: Any, param: Optional[click.Parameter], ctx: Optional[Context]
) -> str:
if not isinstance(value, str):
raise TypeError("expected a string type for TemplateStringParam")
return Template(value).safe_substitute(self.mapping)


class MetricParam(ParamType):
"""
Converts the input to a valid metric.
The String has to follow the following regex:
``([a-zA-Z][a-zA-Z0-9_]+\\.)+[a-zA-Z][a-zA-Z0-9_]+``
"""

pattern = re.compile(r"([a-zA-Z][a-zA-Z0-9_]+\.)+[a-zA-Z][a-zA-Z0-9_]+")

def convert(
self, value: Any, param: Optional[Parameter], ctx: Optional[Context]
self, value: Any, param: Optional[click.Parameter], ctx: Optional[Context]
) -> str:
if not isinstance(value, str):
raise TypeError("expected a string type for the MetricParam")
Expand Down

0 comments on commit 497bd92

Please sign in to comment.