rats-apps 0.11.1.dev20250527164753__py3-none-any.whl → 0.11.1.dev20250528185313__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.
rats/apps/_container.py CHANGED
@@ -108,7 +108,6 @@ class Container(Protocol):
108
108
  """Retrieve a service group by its id."""
109
109
  if not self.has_namespace(ProviderNamespaces.GROUPS, group_id):
110
110
  # groups are expected to return iterable services
111
- # TODO: we need to clean up the meaning of groups and services somehow
112
111
  for i in self.get_namespaced_group(ProviderNamespaces.FALLBACK_GROUPS, group_id):
113
112
  yield from cast(Iterator[T_ServiceType], i)
114
113
 
@@ -151,7 +150,14 @@ def _get_cached_services_for_group(
151
150
 
152
151
  for provider in info_cache[(namespace, group_id)]:
153
152
  if provider not in provider_cache:
154
- provider_cache[provider] = getattr(c, provider.attr)()
153
+ if namespace in [
154
+ ProviderNamespaces.CONTAINERS,
155
+ ProviderNamespaces.SERVICES,
156
+ ProviderNamespaces.FALLBACK_SERVICES,
157
+ ]:
158
+ provider_cache[provider] = getattr(c, provider.attr)()
159
+ else:
160
+ provider_cache[provider] = list(getattr(c, provider.attr)())
155
161
 
156
162
  yield provider_cache[provider]
157
163
 
@@ -0,0 +1,238 @@
1
+ Metadata-Version: 2.3
2
+ Name: rats-apps
3
+ Version: 0.11.1.dev20250528185313
4
+ Summary: research analysis tools for building applications
5
+ License: MIT
6
+ Keywords: pipelines,machine learning,research
7
+ Author: Elon Portugaly
8
+ Author-email: elonp@microsoft.com
9
+ Requires-Python: >=3.10,<4.0
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Requires-Dist: click
17
+ Requires-Dist: colorlog
18
+ Requires-Dist: dataclass-wizard
19
+ Requires-Dist: pyyaml
20
+ Requires-Dist: typing-extensions
21
+ Project-URL: Documentation, https://microsoft.github.io/rats
22
+ Project-URL: Repository, https://github.com/microsoft/rats
23
+ Description-Content-Type: text/markdown
24
+
25
+ ---
26
+ title: introduction
27
+ ---
28
+
29
+ The `rats-apps` package helps create applications; a small set of modules that eliminate the most
30
+ common boilerplate code when creating applications of any kind. We do this mainly by providing a
31
+ set of libraries to define service containers, and using the service containers to hide the
32
+ complexity of creating services–like authentication, storage, or database clients–from other parts
33
+ of the system, allowing developers to focus on the business logic of the application. Often referred
34
+ to as [Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection), we use our
35
+ service containers to separate the concerns of constructing objects and using them.
36
+
37
+ ## Installation
38
+
39
+ Use `pip` or your favorite packaging tool to install the package from PyPI.
40
+
41
+ ```bash
42
+ pip install rats-apps
43
+ ```
44
+
45
+ ## What is an application?
46
+
47
+ Let's start with a standard python script, and slowly migrate it to be a rats application in order
48
+ to explain a few main details. Creating a `__main__.py` file in a package makes it executable.
49
+ After the common python boilerplate code is added, this is typically what we find in the wild:
50
+
51
+ === ":material-language-python: ~/code/src/foo/\_\_main\_\_.py"
52
+ ```python
53
+ def main() -> None:
54
+ print("hello, world")
55
+
56
+
57
+ if __name__ == "__main__":
58
+ main()
59
+ ```
60
+
61
+ === ":material-console: ~/code"
62
+ ```bash
63
+ python -m foo
64
+ ```
65
+
66
+ Using this pattern, we can define our application with a small modification, turning our `main()`
67
+ function into a runnable rats application, and then running it:
68
+
69
+ === ":material-language-python: ~/code/src/foo/\_\_main\_\_.py"
70
+ ```python
71
+ from rats import apps
72
+
73
+
74
+ def main() -> None:
75
+ print("hello, world")
76
+
77
+
78
+ if __name__ == "__main__":
79
+ apps.run(apps.App(main))
80
+ ```
81
+
82
+ !!! info
83
+ The [rats.apps.App][] class is used to quickly turn a script entry point–`Callable[[], None]`
84
+ –into an object with an `execute()` method, defined by our [rats.apps.Executable][]
85
+ interface.
86
+
87
+ ## Application Containers & Plugins
88
+
89
+ We can start to leverage [rats.apps][] to make our application easy to extend. Let's replace our use
90
+ of the [rats.apps.App][] wrapper and move our `main()` function into a class. Using the
91
+ [rats.apps.AppContainer][] and [rats.apps.PluginMixin][] classes, we finish adapting our example
92
+ to be a rats application.
93
+
94
+ === ":material-language-python: ~/code/src/foo/\_\_main\_\_.py"
95
+
96
+ ```python
97
+ from rats import apps
98
+
99
+
100
+ class Application(apps.AppContainer, apps.PluginMixin):
101
+ def execute() -> None:
102
+ print("hello, world")
103
+
104
+
105
+ if __name__ == "__main__":
106
+ apps.run_plugin(Application)
107
+ ```
108
+
109
+ !!! info
110
+ If you're making these changes to an existing code base, you should be able to run things to
111
+ validate that everything still works as it did before. Your `main()` function is now in
112
+ the `execute()` method of your new `Application` class, but none of the behavior of your
113
+ application should have been affected.
114
+
115
+ Now that we have a fully defined rats application; we can use [rats.apps.Container][] instances to
116
+ make services available to our application while remaining decoupled from the details of how these
117
+ services are initialized. A common use case for this is to give our team access to the azure
118
+ storage clients without needing to specify the authentication details; allowing us to ensure our
119
+ application is functional in many compute environments.
120
+
121
+ === ":material-language-python: ~/code/src/foo/\_\_init\_\_.py"
122
+
123
+ ```python
124
+ from ._plugin import PluginContainer
125
+
126
+ __all__ = ["PluginContainer"]
127
+ ```
128
+
129
+ === ":material-language-python: ~/code/src/foo/\_\_main\_\_.py"
130
+
131
+ ```python
132
+ from rats import apps
133
+ import foo
134
+
135
+
136
+ class Application(apps.AppContainer, apps.PluginMixin):
137
+
138
+ def execute() -> None:
139
+ blob_client = self._app.get(foo.BLOB_SERVICE_ID)
140
+ print(f"hello, world. loaded blob client: {blob_client}")
141
+
142
+ @apps.container()
143
+ def _plugins(self) -> apps.Container:
144
+ return foo.PluginContainer(self._app)
145
+
146
+
147
+ if __name__ == "__main__":
148
+ apps.run_plugin(Application)
149
+ ```
150
+
151
+ === ":material-language-python: ~/code/src/foo/_plugin.py"
152
+
153
+ ```python
154
+ from rats import apps
155
+ from azure.storage.blob import BlobServiceClient
156
+
157
+ BLOB_SERVICE_ID = apps.ServiceId[BlobServiceClient]("blob-client")
158
+
159
+
160
+ class PluginContainer(apps.Container, apps.PluginMixin):
161
+
162
+ @apps.service(BLOB_SERVICE_ID)
163
+ def _blob_client(self) -> BlobServiceClient:
164
+ credential = DefaultAzureCredential()
165
+ return BlobServiceClient(
166
+ account_url=f"https://example.blob.core.windows.net/",
167
+ credential=credential,
168
+ )
169
+ ```
170
+
171
+ !!! success
172
+ Following these patterns, we can make services available to others with plugin containers; and
173
+ we can combine these containers to create applications. The [rats.apps][] module has additional
174
+ libraries to help define different types of applications, designed to help your solutions
175
+ evolve as ideas mature. Our first runnable example was a single instance of the
176
+ [rats.apps.AppContainer][] interface with an `execute()` method; but a larger project might
177
+ have a few modules providing different aspects of the application's needs by sharing a set of
178
+ service ids and a plugin container.
179
+
180
+ ## Installable Plugins
181
+
182
+ We use the standard [Entry Points](https://packaging.python.org/en/latest/specifications/entry-points/)
183
+ mechanism to allow authors to make their application extensible. These plugins are instances of
184
+ [rats.apps.Container][] and loaded into applications like our previous examples.
185
+
186
+ === ":material-file-settings: ~/code/pyproject.toml"
187
+ ```toml
188
+ [tool.poetry.plugins."foo.plugins"]
189
+ "foo" = "foo:PluginContainer"
190
+ ```
191
+
192
+ === ":material-language-python: ~/code/src/foo/\_\_main\_\_.py"
193
+ ```python
194
+ from rats import apps
195
+ import foo
196
+
197
+
198
+ class Application(apps.AppContainer, apps.PluginMixin):
199
+
200
+ def execute() -> None:
201
+ blob_client = self._app.get(foo.BLOB_SERVICE_ID)
202
+ print(f"hello, world. loaded blob client: {blob_client}")
203
+
204
+ @apps.container()
205
+ def _plugins(self) -> apps.Container:
206
+ return apps.PythonEntryPointContainer("foo.plugins")
207
+
208
+
209
+ if __name__ == "__main__":
210
+ apps.run_plugin(Application)
211
+ ```
212
+
213
+ !!! success
214
+ We used [rats.app] to define an application, and used a service provided by a plugin container
215
+ that is loaded through a python entry point. You can create a script entry in your
216
+ `pyproject.toml` file to expose your application through a terminal command:
217
+
218
+ === ":material-language-python: ~/code/src/foo/\_\_init\_\_.py"
219
+ ```python
220
+ from ._app import Application, main
221
+ from ._plugin import PluginContainer
222
+
223
+
224
+ __all__ = [
225
+ "Application",
226
+ "main",
227
+ "PluginContainer",
228
+ ]
229
+ ```
230
+ === ":material-file-settings: ~/code/pyproject.toml"
231
+ ```toml
232
+ [tool.poetry.plugins."foo.plugins"]
233
+ "foo" = "foo:PluginContainer"
234
+
235
+ [tool.poetry.scripts]
236
+ foo = "foo:main"
237
+ ```
238
+
@@ -11,7 +11,7 @@ rats/apps/__init__.py,sha256=6B5qQvzx1xlRrNRY4QJi6GEywuQ1MoW454kC4nO2Yqg,2084
11
11
  rats/apps/_annotations.py,sha256=6M_M7K8haNVda0Tx02EpFf3s9EjnWYacNMjTIkNEdRU,4617
12
12
  rats/apps/_app_containers.py,sha256=1rtq92rOGvCbroQmDgOM24jxxcNNFQHy65fBLO5LIXo,6920
13
13
  rats/apps/_composite_container.py,sha256=FdpmH_xIly6LxNZrA_nZCznukptjVLXttXTMtf_tnv8,695
14
- rats/apps/_container.py,sha256=sYISCG-qVzl-bsBwX_CAWEP9gtXCnG-Jls3l8IKb4DQ,7208
14
+ rats/apps/_container.py,sha256=N8qR0oBLi03xZvPfc8SxaSci0oVYfX_rftzfaBkTSfQ,7415
15
15
  rats/apps/_executables.py,sha256=hXExNmAnuPU1KJXihNw1jEDAQpMlQ9E9_aPV8tpGbOY,1347
16
16
  rats/apps/_ids.py,sha256=T8Onrj79t8NPfBMQBk0xI6fIWDKF0m2JfFNrdtXAbWg,353
17
17
  rats/apps/_mains.py,sha256=2Q97mNk1cBzYROc_pJcm57EEeHmwRbXOWpfYXH37qcA,995
@@ -55,7 +55,7 @@ rats_e2e/runtime/_data.py,sha256=3d1F_JO2gEOPUjBp_KYMP3TefyneiG_ktlJjdIIYUy8,125
55
55
  rats_e2e/runtime/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
56
  rats_resources/runtime/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
57
  rats_resources/runtime/example-context.yaml,sha256=eiLsNFquFfkIpUhxUCQLzLigH21QF2F00fzA_e_aOKk,215
58
- rats_apps-0.11.1.dev20250527164753.dist-info/METADATA,sha256=kgJQUzcaMgofZndS9ETn14z0uY0ZE50-Y1Yh8pqVqYA,889
59
- rats_apps-0.11.1.dev20250527164753.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
60
- rats_apps-0.11.1.dev20250527164753.dist-info/entry_points.txt,sha256=Gf6bPwxIVjWd3Xx71upZo7eDJA5cujniLew6fxJMgA4,117
61
- rats_apps-0.11.1.dev20250527164753.dist-info/RECORD,,
58
+ rats_apps-0.11.1.dev20250528185313.dist-info/METADATA,sha256=5ywdh1LvrSfuQ9ZP5oKGfYMxR98PRsvQCS-RIDstGvE,8292
59
+ rats_apps-0.11.1.dev20250528185313.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
60
+ rats_apps-0.11.1.dev20250528185313.dist-info/entry_points.txt,sha256=Gf6bPwxIVjWd3Xx71upZo7eDJA5cujniLew6fxJMgA4,117
61
+ rats_apps-0.11.1.dev20250528185313.dist-info/RECORD,,
@@ -1,27 +0,0 @@
1
- Metadata-Version: 2.3
2
- Name: rats-apps
3
- Version: 0.11.1.dev20250527164753
4
- Summary: research analysis tools for building applications
5
- License: MIT
6
- Keywords: pipelines,machine learning,research
7
- Author: Elon Portugaly
8
- Author-email: elonp@microsoft.com
9
- Requires-Python: >=3.10,<4.0
10
- Classifier: License :: OSI Approved :: MIT License
11
- Classifier: Programming Language :: Python :: 3
12
- Classifier: Programming Language :: Python :: 3.10
13
- Classifier: Programming Language :: Python :: 3.11
14
- Classifier: Programming Language :: Python :: 3.12
15
- Classifier: Programming Language :: Python :: 3.13
16
- Requires-Dist: click
17
- Requires-Dist: colorlog
18
- Requires-Dist: dataclass-wizard
19
- Requires-Dist: pyyaml
20
- Requires-Dist: typing-extensions
21
- Project-URL: Documentation, https://microsoft.github.io/rats
22
- Project-URL: Repository, https://github.com/microsoft/rats
23
- Description-Content-Type: text/markdown
24
-
25
- # rats-apps
26
- ...
27
-