rats-apps 0.5.1.dev20250206185646__py3-none-any.whl → 0.6.0.dev20250207152453__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -63,10 +63,11 @@ be used easily in functions that need to defer the construction of an applicatio
63
63
 
64
64
  class PluginMixin:
65
65
  """
66
- Mix into your [Container][] classes to add our default constructor.
66
+ Mix into your [rats.apps.Container][] classes to add our default constructor.
67
67
 
68
68
  This mixin adds a common constructor to a `Container` in order to quickly create types that
69
- are compatible with functions asking for `AppPlugin` and `ContainerPlugin` arguments.
69
+ are compatible with functions asking for [rats.apps.AppPlugin][] and
70
+ [rats.apps.ContainerPlugin][] arguments.
70
71
 
71
72
  !!! warning
72
73
  Avoid using mixins as an input type to your functions, because we don't want to restrict
rats/cli/__init__.py CHANGED
@@ -1,16 +1,23 @@
1
- """Uses `rats.cli` to streamline the creation of CLI commands written with Click."""
1
+ """Use `rats.cli` to streamline the creation of CLI commands written with Click."""
2
2
 
3
- from ._annotations import CommandId, command, get_class_commands, get_class_groups, group
3
+ from ._annotations import (
4
+ AUTO_COMMAND,
5
+ CommandId,
6
+ command,
7
+ get_class_commands,
8
+ get_class_groups,
9
+ group,
10
+ )
4
11
  from ._app import ClickApp
5
12
  from ._container import CompositeContainer, Container
6
- from ._plugin import PluginServices, attach, create_group
13
+ from ._plugin import attach, create_group
7
14
 
8
15
  __all__ = [
16
+ "AUTO_COMMAND",
9
17
  "ClickApp",
10
18
  "CommandId",
11
19
  "CompositeContainer",
12
20
  "Container",
13
- "PluginServices",
14
21
  "attach",
15
22
  "command",
16
23
  "create_group",
rats/cli/_annotations.py CHANGED
@@ -8,14 +8,47 @@ from rats import apps
8
8
 
9
9
 
10
10
  class CommandId(NamedTuple):
11
+ """
12
+ A small wrapper around the string name of a [click.Command][].
13
+
14
+ Used when wanting to specify a custom name for a command within a [rats.cli.Container][] class.
15
+ See [rats.cli.command][] for more details.
16
+ """
17
+
11
18
  name: str
12
19
 
13
20
 
14
21
  AUTO_COMMAND = CommandId("__auto__")
22
+ """
23
+ Causes command names to be generated from the method names in [rats.cli.Container][]'s.
24
+
25
+ This is the default option for [rats.cli.command][] and [rats.cli.group][] and typically does not
26
+ need to be used directly.
27
+ """
15
28
  T = TypeVar("T", bound=Callable[[Any], Any])
16
29
 
17
30
 
18
31
  def command(command_id: CommandId = AUTO_COMMAND) -> Callable[..., apps.Executable]:
32
+ """
33
+ Mark a method in [rats.cli.Container][] instances as a [click.Command][].
34
+
35
+ By default, the name of the method is used to generate a dash-separated command name. You can
36
+ provide a [rats.cli.CommandId][] argument to specify a custom name, for example, if the desired
37
+ command contains characters that are invalid in method names, like periods.
38
+
39
+ ```python
40
+ from rats import cli
41
+
42
+ class Example(cli.Container):
43
+ @cli.command(cli.CommandId("some.example-command")
44
+ def _any_method_name(self) -> None:
45
+ print("this cli command is called some.example-command")
46
+ ```
47
+
48
+ Args:
49
+ command_id: An optional [rats.cli.CommandId][] to specify the command name.
50
+ """
51
+
19
52
  def decorator(fn: T) -> T:
20
53
  if command_id == AUTO_COMMAND:
21
54
  cmd_name = fn.__name__.replace("_", "-").strip("-")
@@ -26,17 +59,31 @@ def command(command_id: CommandId = AUTO_COMMAND) -> Callable[..., apps.Executab
26
59
 
27
60
 
28
61
  def group(command_id: CommandId = AUTO_COMMAND) -> Callable[..., apps.Executable]:
62
+ """
63
+ Mark a method in [rats.cli.Container][] instances as a [click.Group][].
64
+
65
+ !!! warning
66
+ It's unclear if this API is useful as-is and will most likely change soon.
67
+
68
+ See [rats.cli.command][] for more details.
69
+
70
+ Args:
71
+ command_id: An optional [rats.cli.CommandId][] to specify the group name.
72
+ """
73
+
29
74
  def decorator(fn: T) -> T:
30
75
  if command_id == AUTO_COMMAND:
31
76
  return anns.annotation("command-groups", CommandId(fn.__name__.replace("_", "-")))(fn)
32
- return anns.annotation("commands", command_id)(fn)
77
+ return anns.annotation("command-groups", command_id)(fn)
33
78
 
34
79
  return decorator # type: ignore[reportReturnType]
35
80
 
36
81
 
37
82
  def get_class_commands(cls: type) -> anns.AnnotationsContainer:
83
+ """Extracts class methods decorated with [rats.cli.command][]."""
38
84
  return anns.get_class_annotations(cls).with_namespace("commands")
39
85
 
40
86
 
41
87
  def get_class_groups(cls: type) -> anns.AnnotationsContainer:
88
+ """Extracts class methods decorated with [rats.cli.group][]."""
42
89
  return anns.get_class_annotations(cls).with_namespace("command-groups")
rats/cli/_app.py CHANGED
@@ -9,7 +9,13 @@ from ._container import Container
9
9
 
10
10
  @final
11
11
  class ClickApp(apps.Executable):
12
- """..."""
12
+ """
13
+ A wrapper to configure and run a [click.Group][] as a [rats.apps.Executable][].
14
+
15
+ The [rats.cli.Container][] is attached to the provided [click.Group][] when the
16
+ [rats.cli.ClickApp.execute][] is called, allowing some simple forms of lazy-loading to keep
17
+ commands snappy.
18
+ """
13
19
 
14
20
  _group: click.Group
15
21
  _commands: Container
@@ -19,11 +25,24 @@ class ClickApp(apps.Executable):
19
25
  group: click.Group,
20
26
  commands: Container,
21
27
  ) -> None:
22
- """Not sure this is the right interface."""
28
+ """
29
+ Provide the [rats.cli.Container][] instance that makes up the wanted cli commands.
30
+
31
+ Args:
32
+ group: group that will be executed by this application.
33
+ commands: container that will be attached before executing the above group.
34
+ """
23
35
  self._group = group
24
36
  self._commands = commands
25
37
 
26
38
  def execute(self) -> None:
27
- """This app executes a click application after letting rats plugins attach commands."""
39
+ """
40
+ Attach any commands provided by the [rats.cli.Container][] and then execute the group.
41
+
42
+ !!! note
43
+ Currently, this method runs [click.BaseCommand.main][] without arguments, causing Click
44
+ to pull the command arguments from [sys.argv][]. If you are needing to change this,
45
+ skip using this class and implement the custom logic yourself.
46
+ """
28
47
  self._commands.attach(self._group)
29
48
  self._group.main()
rats/cli/_container.py CHANGED
@@ -11,10 +11,34 @@ logger = logging.getLogger(__name__)
11
11
 
12
12
 
13
13
  class Container(Protocol):
14
- """A container that can attach click commands to a click group."""
14
+ """
15
+ A container that can attach click commands to a click group.
16
+
17
+ !!! example
18
+ The default protocol implementation detects any methods in the class decorated with the
19
+ [rats.cli.command][] annotation. Apart from marking the method as a cli command, you can
20
+ add [click.argument][] and [click.option][] decorators as defined by the click docs.
21
+
22
+ ```python
23
+ from rats import cli
24
+
25
+
26
+ class ExampleCli(cli.Container):
27
+ @cli.command()
28
+ @click.argument("something")
29
+ def my_cmd(self, something: str) -> None:
30
+ print("this command is automatically detected and attached as my-cmd")
31
+ print("add a docstring to the method to be used as the --help text")
32
+ ```
33
+ """
15
34
 
16
35
  def attach(self, group: click.Group) -> None:
17
- """..."""
36
+ """
37
+ Attach this container's provided cli commands to the provided [click.Group][].
38
+
39
+ Args:
40
+ group: The [click.Group][] we are attaching our commands to.
41
+ """
18
42
 
19
43
  def cb(_method: Callable[..., None], *args: Any, **kwargs: Any) -> None:
20
44
  """
@@ -50,11 +74,25 @@ class Container(Protocol):
50
74
 
51
75
  @final
52
76
  class CompositeContainer(Container):
77
+ """Take any number of [rats.cli.Container][] instances and expose them as if they were one."""
78
+
53
79
  _containers: tuple[Container, ...]
54
80
 
55
81
  def __init__(self, *containers: Container) -> None:
82
+ """
83
+ Zero or more instances can be provided.
84
+
85
+ Args:
86
+ *containers: Any number of container instances wanting to be merged.
87
+ """
56
88
  self._containers = containers
57
89
 
58
90
  def attach(self, group: click.Group) -> None:
91
+ """
92
+ Attach the cli commands from all [rats.cli.Container][] instances to the [click.Group][].
93
+
94
+ Args:
95
+ group: The [click.Group][] we are attaching our commands to.
96
+ """
59
97
  for container in self._containers:
60
98
  container.attach(group)
rats/cli/_plugin.py CHANGED
@@ -1,13 +1,31 @@
1
- from typing import cast
2
-
3
1
  import click
4
2
 
5
- from rats import apps
6
-
7
3
  from ._container import Container
8
4
 
9
5
 
10
6
  def create_group(group: click.Group, container: Container) -> click.Group:
7
+ """
8
+ A simple shortcut to create a [click.Group][] with commands provided by `rats.cli.Container`'s.
9
+
10
+ ```python
11
+ import click
12
+ from rats import cli
13
+
14
+
15
+ class Example(cli.Container):
16
+ @cli.command()
17
+ def my_command(self) -> None:
18
+ print("hello, world. run me with `my-cli my-command`.")
19
+
20
+
21
+ if __name__ == "__main__":
22
+ cli.create_group(click.Group("my-cli"), Example()).main()
23
+ ```
24
+
25
+ Args:
26
+ group: The [click.Group][] commands will be added to.
27
+ container: The [rats.cli.Container][] instance to attach commands from
28
+ """
11
29
  container.attach(group)
12
30
  return group
13
31
 
@@ -17,27 +35,27 @@ def attach(
17
35
  command: click.Command | click.Group,
18
36
  *commands: click.Command | click.Group,
19
37
  ) -> None:
38
+ """
39
+ Convenience function to attach multiple [click.Command]'s to a [click.Group].
40
+
41
+ ```python
42
+ import click
43
+ from rats import cli
44
+
45
+ cli.attach(
46
+ click.Group("my-cli"),
47
+ click.Command("command-1"),
48
+ click.Command("command-2"),
49
+ )
50
+ ```
51
+
52
+ Args:
53
+ group: The [click.Group] we want to build.
54
+ command: A [click.Command] to attach to the provided group.
55
+ *commands: Any number of additional [click.Command]'s to attach.
56
+
57
+ Returns: The input [click.Group][] with all of the commands attached.
58
+ """
20
59
  group.add_command(command)
21
60
  for c in commands:
22
61
  group.add_command(c)
23
-
24
-
25
- @apps.autoscope
26
- class _PluginEvents:
27
- pass
28
-
29
-
30
- @apps.autoscope
31
- class PluginServices:
32
- EVENTS = _PluginEvents
33
-
34
- @staticmethod
35
- def sub_command(
36
- parent: apps.ServiceId[apps.Executable],
37
- name: str,
38
- ) -> apps.ServiceId[apps.Executable]:
39
- return apps.ServiceId(f"{parent.name}[{name}]")
40
-
41
- @staticmethod
42
- def click_command(cmd_id: apps.ServiceId[apps.Executable]) -> apps.ServiceId[click.Group]:
43
- return cast(apps.ServiceId[click.Group], cmd_id)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: rats-apps
3
- Version: 0.5.1.dev20250206185646
3
+ Version: 0.6.0.dev20250207152453
4
4
  Summary: research analysis tools for building applications
5
5
  License: MIT
6
6
  Keywords: pipelines,machine learning,research
@@ -4,7 +4,7 @@ rats/annotations/_functions.py,sha256=UkHh3zdBivluE7dBeGQ17zoIfGdyIokMAkFmpWaIlD
4
4
  rats/annotations/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  rats/apps/__init__.py,sha256=uTPk2ipOy7MgLoV0s9l22U1Qyo8aL2yKVwDukOY9WGw,1934
6
6
  rats/apps/_annotations.py,sha256=6M_M7K8haNVda0Tx02EpFf3s9EjnWYacNMjTIkNEdRU,4617
7
- rats/apps/_app_containers.py,sha256=Ym2NrRljmZVE7EXK2G8KgDHAGreYsuFlvu1QYTkhOsE,6109
7
+ rats/apps/_app_containers.py,sha256=ygZL0NM-fSRSemFddBsVMwcmSQw07sbb7bIqWTr-_yU,6147
8
8
  rats/apps/_composite_container.py,sha256=s_of6NyyrjFVYWGVehyEHe9WJIPRCnbB-tyWyNF8zyc,585
9
9
  rats/apps/_container.py,sha256=sYISCG-qVzl-bsBwX_CAWEP9gtXCnG-Jls3l8IKb4DQ,7208
10
10
  rats/apps/_executables.py,sha256=hXExNmAnuPU1KJXihNw1jEDAQpMlQ9E9_aPV8tpGbOY,1347
@@ -16,12 +16,12 @@ rats/apps/_runtimes.py,sha256=l5Z26jZVHk4CvT8VyKUK5tpcCAKt2N1DWipd4gX_Bls,2060
16
16
  rats/apps/_scoping.py,sha256=6C2-ID22cCPR9Cbexf3CvCF3o9F_7ieURbwqkf6DI68,1360
17
17
  rats/apps/_static_container.py,sha256=KH4AwRMX5QPIwYrD9W_HayIpQIrbVn7clEMx44LFAGc,2113
18
18
  rats/apps/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
- rats/cli/__init__.py,sha256=PFwnpWtiAkHyV_wyQRNslKHKAOI659HpU5KBfswq8RQ,540
19
+ rats/cli/__init__.py,sha256=0VDmmNP4JOW-hNjufYwO-e38kLpquWb_fo95geuNv5w,564
20
20
  rats/cli/__main__.py,sha256=WeldAKjA3Kmz9ZRnZVd3G8Ud66Y_gSRDLIPNE1JyhV0,1418
21
- rats/cli/_annotations.py,sha256=5voM1pNm7iybZpgQTSVpaq3rMIMz33jr4eUyoEmxWJ4,1359
22
- rats/cli/_app.py,sha256=EmLIJe1LTLob5u5gP8gpgxk3kFlALTvrpYlwxlILu0k,620
23
- rats/cli/_container.py,sha256=q3L6On6RS3PfUFZ67t6eUvKUQIK4Qxomz5ob86aNcR4,2143
24
- rats/cli/_plugin.py,sha256=IknKt0yLNpk2ZYH2yRiADC74jO5DowAGmoWOEvR6l4g,928
21
+ rats/cli/_annotations.py,sha256=TCjs2b7o6kUSseFwrHm63o9QurwGDO7YsK56ZNMQPGg,3014
22
+ rats/cli/_app.py,sha256=4z2jiRHafCAN7S-cbMhfQJhLGwl6ljFS3r6P1COgR00,1454
23
+ rats/cli/_container.py,sha256=FIQBqi9PTNpE2P52qkfGET51BczdD-JvcWXLTjCNPDI,3512
24
+ rats/cli/_plugin.py,sha256=BNmgWVquQUEqJAYsed_l8vLnlLP7u3XC1TDyEFI1AiU,1552
25
25
  rats/cli/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
26
  rats/logs/__init__.py,sha256=sizLa6JbqekhJGKDyRZUUQvTuqiJx6yxwA5jT-tDQck,152
27
27
  rats/logs/_app.py,sha256=TF6rfQXQfaHd3AFW2anAoAGaxzU31kqJMoKkjuBtbF0,1617
@@ -35,6 +35,6 @@ rats_e2e/apps/inputs/_app.py,sha256=FiaLgOZc-d1ryKSwKnL5XBNGcOP1bHbxxeMJqoU_RJg,
35
35
  rats_e2e/apps/minimal/__init__.py,sha256=bUR6Oexx6Jsouxor0cL9emXoVha4cm3WqyhU1pgchsI,521
36
36
  rats_e2e/apps/minimal/__main__.py,sha256=Mf-a2iQKTTgh9hMd6AeuzmU9araMIyf1AtdWkh_L07E,117
37
37
  rats_e2e/apps/minimal/_app.py,sha256=CQ09LVTNRarz7Pb1wiSuNHrZ_2KGcgH8nUqy4BjxMUY,849
38
- rats_apps-0.5.1.dev20250206185646.dist-info/METADATA,sha256=wONNll9olXOhYo3oMYUDXG0ZB1ySa0j96yyu1m_uEs0,779
39
- rats_apps-0.5.1.dev20250206185646.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
40
- rats_apps-0.5.1.dev20250206185646.dist-info/RECORD,,
38
+ rats_apps-0.6.0.dev20250207152453.dist-info/METADATA,sha256=NSS2NJbeZ1O-du3MXAgRdb68VYaRZ-O5mdHdAn9vqt0,779
39
+ rats_apps-0.6.0.dev20250207152453.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
40
+ rats_apps-0.6.0.dev20250207152453.dist-info/RECORD,,