providerkit 0.1.0__tar.gz
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.
- providerkit-0.1.0/LICENSE +22 -0
- providerkit-0.1.0/PKG-INFO +310 -0
- providerkit-0.1.0/README.md +276 -0
- providerkit-0.1.0/pyproject.toml +159 -0
- providerkit-0.1.0/setup.cfg +4 -0
- providerkit-0.1.0/src/providerkit/__init__.py +35 -0
- providerkit-0.1.0/src/providerkit/__main__.py +9 -0
- providerkit-0.1.0/src/providerkit/cli.py +42 -0
- providerkit-0.1.0/src/providerkit/commands/__init__.py +3 -0
- providerkit-0.1.0/src/providerkit/commands/provider.py +148 -0
- providerkit-0.1.0/src/providerkit/helpers.py +1032 -0
- providerkit-0.1.0/src/providerkit/kit/__init__.py +60 -0
- providerkit-0.1.0/src/providerkit/kit/config.py +200 -0
- providerkit-0.1.0/src/providerkit/kit/cost.py +69 -0
- providerkit-0.1.0/src/providerkit/kit/package.py +163 -0
- providerkit-0.1.0/src/providerkit/kit/service.py +86 -0
- providerkit-0.1.0/src/providerkit/kit/urls.py +54 -0
- providerkit-0.1.0/src/providerkit.egg-info/PKG-INFO +310 -0
- providerkit-0.1.0/src/providerkit.egg-info/SOURCES.txt +23 -0
- providerkit-0.1.0/src/providerkit.egg-info/dependency_links.txt +1 -0
- providerkit-0.1.0/src/providerkit.egg-info/entry_points.txt +2 -0
- providerkit-0.1.0/src/providerkit.egg-info/requires.txt +15 -0
- providerkit-0.1.0/src/providerkit.egg-info/top_level.txt +1 -0
- providerkit-0.1.0/tests/test_config.py +164 -0
- providerkit-0.1.0/tests/test_helpers.py +319 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 providerkit contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: providerkit
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: ProviderKit - Generic provider management library
|
|
5
|
+
Author-email: Hicinformatic <hicinformatic@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/hicinformatic/python-providerkit
|
|
8
|
+
Project-URL: Repository, https://github.com/hicinformatic/python-providerkit
|
|
9
|
+
Project-URL: Documentation, https://github.com/hicinformatic/python-providerkit#readme
|
|
10
|
+
Project-URL: Issues, https://github.com/hicinformatic/python-providerkit/issues
|
|
11
|
+
Keywords: provider,service-provider,multi-provider,provider-management,python,abstraction,service-abstraction
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: qualitybase
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Provides-Extra: lint
|
|
26
|
+
Requires-Dist: qualitybase[lint]; extra == "lint"
|
|
27
|
+
Provides-Extra: quality
|
|
28
|
+
Requires-Dist: qualitybase[quality]; extra == "quality"
|
|
29
|
+
Provides-Extra: security
|
|
30
|
+
Requires-Dist: qualitybase[security]; extra == "security"
|
|
31
|
+
Provides-Extra: test
|
|
32
|
+
Requires-Dist: qualitybase[test]; extra == "test"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# python-providerkit
|
|
36
|
+
|
|
37
|
+
ProviderKit is a generic provider management library for Python. It provides a standardized way to manage, discover, and interact with multiple service providers in a unified manner.
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install providerkit
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
For development:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install -e .
|
|
49
|
+
pip install -e ".[dev,lint,quality,security,test]"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Usage
|
|
53
|
+
|
|
54
|
+
ProviderKit provides a mixin-based architecture for creating and managing providers.
|
|
55
|
+
|
|
56
|
+
### Basic Usage
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from providerkit import ProviderBase, get_providers
|
|
60
|
+
|
|
61
|
+
# Load providers from various sources
|
|
62
|
+
providers = get_providers(json="providers.json")
|
|
63
|
+
# or
|
|
64
|
+
providers = get_providers(dir_path="path/to/providers")
|
|
65
|
+
# or
|
|
66
|
+
providers = get_providers(config=[{"class": "mypackage.providers.MyProvider", "config": {...}}])
|
|
67
|
+
|
|
68
|
+
# Use providers
|
|
69
|
+
for name, provider in providers.items():
|
|
70
|
+
print(f"{provider.display_name}: {provider.name}")
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Creating a Provider
|
|
74
|
+
|
|
75
|
+
Create a provider by inheriting from `ProviderBase`:
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
from providerkit import ProviderBase
|
|
79
|
+
|
|
80
|
+
class EmailProvider(ProviderBase):
|
|
81
|
+
name = "email"
|
|
82
|
+
display_name = "Email Provider"
|
|
83
|
+
description = "Sends emails via SMTP"
|
|
84
|
+
|
|
85
|
+
def __init__(self, **kwargs):
|
|
86
|
+
super().__init__(
|
|
87
|
+
name="email",
|
|
88
|
+
display_name="Email Provider",
|
|
89
|
+
description="Sends emails via SMTP",
|
|
90
|
+
**kwargs
|
|
91
|
+
)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Provider Discovery
|
|
95
|
+
|
|
96
|
+
ProviderKit can automatically discover providers from directories:
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
from providerkit import autodiscover_providers
|
|
100
|
+
|
|
101
|
+
# Discover providers from a directory
|
|
102
|
+
providers = autodiscover_providers("path/to/providers", base_module="mypackage.providers")
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Loading from JSON
|
|
106
|
+
|
|
107
|
+
Create a JSON file with provider configurations:
|
|
108
|
+
|
|
109
|
+
```json
|
|
110
|
+
{
|
|
111
|
+
"providers": [
|
|
112
|
+
{
|
|
113
|
+
"class": "mypackage.providers.EmailProvider",
|
|
114
|
+
"config": {
|
|
115
|
+
"smtp_host": "smtp.example.com",
|
|
116
|
+
"smtp_port": 587
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Load it:
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
from providerkit import load_providers_from_json
|
|
127
|
+
|
|
128
|
+
providers = load_providers_from_json("providers.json")
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Loading from Configuration
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
from providerkit import load_providers_from_config
|
|
135
|
+
|
|
136
|
+
config = [
|
|
137
|
+
{
|
|
138
|
+
"class": "mypackage.providers.EmailProvider",
|
|
139
|
+
"config": {"smtp_host": "smtp.example.com"},
|
|
140
|
+
"kwargs": {}
|
|
141
|
+
}
|
|
142
|
+
]
|
|
143
|
+
|
|
144
|
+
providers = load_providers_from_config(config)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Provider Mixins
|
|
148
|
+
|
|
149
|
+
ProviderKit uses a mixin-based architecture. All mixins are automatically included in `ProviderBase`:
|
|
150
|
+
|
|
151
|
+
- **`PackageMixin`**: Package dependency management and validation
|
|
152
|
+
- **`ConfigMixin`**: Configuration management and validation
|
|
153
|
+
- **`ServiceMixin`**: Business logic implementation and service methods
|
|
154
|
+
- **`UrlsMixin`**: URL routing and endpoint management (if applicable)
|
|
155
|
+
|
|
156
|
+
## Architecture
|
|
157
|
+
|
|
158
|
+
ProviderKit uses a mixin-based architecture:
|
|
159
|
+
|
|
160
|
+
- Each provider inherits from `ProviderBase` which combines all mixins
|
|
161
|
+
- Mixins are organized in dedicated files for clear separation of concerns
|
|
162
|
+
- Providers can be discovered, queried, and used programmatically
|
|
163
|
+
- The system validates dependencies and configuration before allowing provider usage
|
|
164
|
+
|
|
165
|
+
### Project Structure
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
python-providerkit/
|
|
169
|
+
├── src/providerkit/ # Main package
|
|
170
|
+
│ ├── kit/ # Core provider infrastructure
|
|
171
|
+
│ │ ├── __init__.py # ProviderBase class
|
|
172
|
+
│ │ ├── package.py # PackageMixin
|
|
173
|
+
│ │ ├── config.py # ConfigMixin
|
|
174
|
+
│ │ ├── service.py # ServiceMixin
|
|
175
|
+
│ │ └── urls.py # UrlsMixin
|
|
176
|
+
│ ├── providers/ # Provider implementations
|
|
177
|
+
│ ├── helpers.py # Utility functions
|
|
178
|
+
│ └── cli.py # CLI interface
|
|
179
|
+
├── tests/ # Test suite
|
|
180
|
+
└── docs/ # Documentation
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## CLI System
|
|
184
|
+
|
|
185
|
+
ProviderKit includes a flexible CLI system that discovers commands from:
|
|
186
|
+
|
|
187
|
+
1. **`commands/` directory**: A directory next to `cli.py` containing command modules
|
|
188
|
+
2. **`.commands.json` configuration file**: A JSON file that can specify:
|
|
189
|
+
- `packages`: List of packages to discover commands from
|
|
190
|
+
- `directories`: List of directories to scan for commands
|
|
191
|
+
- `commands`: Direct command definitions
|
|
192
|
+
|
|
193
|
+
### Creating Commands
|
|
194
|
+
|
|
195
|
+
Commands can be created in two ways:
|
|
196
|
+
|
|
197
|
+
#### Method 1: Using the `Command` class
|
|
198
|
+
|
|
199
|
+
Create a file in the `commands/` directory (e.g., `commands/mycommand.py`):
|
|
200
|
+
|
|
201
|
+
```python
|
|
202
|
+
from .base import Command
|
|
203
|
+
|
|
204
|
+
def _mycommand_command(args: list[str]) -> bool:
|
|
205
|
+
"""Description of what this command does."""
|
|
206
|
+
# Command implementation
|
|
207
|
+
print("Hello from mycommand!")
|
|
208
|
+
return True
|
|
209
|
+
|
|
210
|
+
mycommand_command = Command(_mycommand_command, "Description of what this command does")
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
#### Method 2: Using functions ending with `_command`
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
def mycommand_command(args: list[str]) -> bool:
|
|
217
|
+
"""Description of what this command does."""
|
|
218
|
+
# Command implementation
|
|
219
|
+
print("Hello from mycommand!")
|
|
220
|
+
return True
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Command Structure
|
|
224
|
+
|
|
225
|
+
Commands receive a list of string arguments and return a boolean indicating success:
|
|
226
|
+
|
|
227
|
+
```python
|
|
228
|
+
def mycommand_command(args: list[str]) -> bool:
|
|
229
|
+
"""Command description for help text."""
|
|
230
|
+
if not args:
|
|
231
|
+
print("Usage: mycommand <arg1> <arg2>")
|
|
232
|
+
return False
|
|
233
|
+
|
|
234
|
+
# Process arguments
|
|
235
|
+
arg1 = args[0]
|
|
236
|
+
# ... command logic ...
|
|
237
|
+
|
|
238
|
+
return True # Success
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## Environment Variables
|
|
242
|
+
|
|
243
|
+
### `ENVFILE_PATH`
|
|
244
|
+
|
|
245
|
+
The `ENVFILE_PATH` environment variable allows you to automatically specify the path to a `.env` file to load when starting services.
|
|
246
|
+
|
|
247
|
+
**Usage:**
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
# Absolute path
|
|
251
|
+
ENVFILE_PATH=/path/to/.env ./service.py dev install-dev
|
|
252
|
+
|
|
253
|
+
# Relative path (relative to project root)
|
|
254
|
+
ENVFILE_PATH=.env.local ./service.py quality lint
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
**Behavior:**
|
|
258
|
+
|
|
259
|
+
- If the path is relative, it is resolved relative to the project root
|
|
260
|
+
- The `.env` file is automatically loaded before command execution
|
|
261
|
+
- Uses `python-dotenv` to parse the file (installed automatically if needed)
|
|
262
|
+
- Works with `dev` and `cli` services
|
|
263
|
+
|
|
264
|
+
### `ENSURE_VIRTUALENV`
|
|
265
|
+
|
|
266
|
+
The `ENSURE_VIRTUALENV` environment variable allows you to automatically activate the `.venv` virtual environment if it exists, before executing commands.
|
|
267
|
+
|
|
268
|
+
**Usage:**
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
ENSURE_VIRTUALENV=1 ./service.py dev help
|
|
272
|
+
ENSURE_VIRTUALENV=1 ./service.py quality lint
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
**Behavior:**
|
|
276
|
+
|
|
277
|
+
- Must be set to `1` to be active
|
|
278
|
+
- Automatically activates the `.venv` virtual environment at the project root
|
|
279
|
+
- Modifies `sys.executable`, `PATH`, and `sys.path` to use the venv's Python
|
|
280
|
+
- Only works if the `.venv` directory exists
|
|
281
|
+
- Compatible with Windows and Unix
|
|
282
|
+
|
|
283
|
+
**Note:** The `ensure_virtualenv()` function is also automatically called by the main service, but `ENSURE_VIRTUALENV` allows you to force activation even in contexts where it might not be automatic.
|
|
284
|
+
|
|
285
|
+
## Use Cases
|
|
286
|
+
|
|
287
|
+
- Multi-provider integrations (email, SMS, payment, etc.)
|
|
288
|
+
- Provider fallback mechanisms
|
|
289
|
+
- Provider discovery and selection
|
|
290
|
+
- Configuration validation across multiple providers
|
|
291
|
+
- Unified interface for heterogeneous services
|
|
292
|
+
|
|
293
|
+
## Development
|
|
294
|
+
|
|
295
|
+
ProviderKit uses qualitybase for development tooling:
|
|
296
|
+
|
|
297
|
+
```bash
|
|
298
|
+
# Quality checks
|
|
299
|
+
./service.py quality lint
|
|
300
|
+
./service.py quality security
|
|
301
|
+
./service.py quality all
|
|
302
|
+
|
|
303
|
+
# Development tools
|
|
304
|
+
./service.py dev venv
|
|
305
|
+
./service.py dev install-dev
|
|
306
|
+
./service.py dev clean
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
See `docs/` for project rules and guidelines.
|
|
310
|
+
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
# python-providerkit
|
|
2
|
+
|
|
3
|
+
ProviderKit is a generic provider management library for Python. It provides a standardized way to manage, discover, and interact with multiple service providers in a unified manner.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install providerkit
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
For development:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install -e .
|
|
15
|
+
pip install -e ".[dev,lint,quality,security,test]"
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
ProviderKit provides a mixin-based architecture for creating and managing providers.
|
|
21
|
+
|
|
22
|
+
### Basic Usage
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
from providerkit import ProviderBase, get_providers
|
|
26
|
+
|
|
27
|
+
# Load providers from various sources
|
|
28
|
+
providers = get_providers(json="providers.json")
|
|
29
|
+
# or
|
|
30
|
+
providers = get_providers(dir_path="path/to/providers")
|
|
31
|
+
# or
|
|
32
|
+
providers = get_providers(config=[{"class": "mypackage.providers.MyProvider", "config": {...}}])
|
|
33
|
+
|
|
34
|
+
# Use providers
|
|
35
|
+
for name, provider in providers.items():
|
|
36
|
+
print(f"{provider.display_name}: {provider.name}")
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Creating a Provider
|
|
40
|
+
|
|
41
|
+
Create a provider by inheriting from `ProviderBase`:
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from providerkit import ProviderBase
|
|
45
|
+
|
|
46
|
+
class EmailProvider(ProviderBase):
|
|
47
|
+
name = "email"
|
|
48
|
+
display_name = "Email Provider"
|
|
49
|
+
description = "Sends emails via SMTP"
|
|
50
|
+
|
|
51
|
+
def __init__(self, **kwargs):
|
|
52
|
+
super().__init__(
|
|
53
|
+
name="email",
|
|
54
|
+
display_name="Email Provider",
|
|
55
|
+
description="Sends emails via SMTP",
|
|
56
|
+
**kwargs
|
|
57
|
+
)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Provider Discovery
|
|
61
|
+
|
|
62
|
+
ProviderKit can automatically discover providers from directories:
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from providerkit import autodiscover_providers
|
|
66
|
+
|
|
67
|
+
# Discover providers from a directory
|
|
68
|
+
providers = autodiscover_providers("path/to/providers", base_module="mypackage.providers")
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Loading from JSON
|
|
72
|
+
|
|
73
|
+
Create a JSON file with provider configurations:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"providers": [
|
|
78
|
+
{
|
|
79
|
+
"class": "mypackage.providers.EmailProvider",
|
|
80
|
+
"config": {
|
|
81
|
+
"smtp_host": "smtp.example.com",
|
|
82
|
+
"smtp_port": 587
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Load it:
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from providerkit import load_providers_from_json
|
|
93
|
+
|
|
94
|
+
providers = load_providers_from_json("providers.json")
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Loading from Configuration
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from providerkit import load_providers_from_config
|
|
101
|
+
|
|
102
|
+
config = [
|
|
103
|
+
{
|
|
104
|
+
"class": "mypackage.providers.EmailProvider",
|
|
105
|
+
"config": {"smtp_host": "smtp.example.com"},
|
|
106
|
+
"kwargs": {}
|
|
107
|
+
}
|
|
108
|
+
]
|
|
109
|
+
|
|
110
|
+
providers = load_providers_from_config(config)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Provider Mixins
|
|
114
|
+
|
|
115
|
+
ProviderKit uses a mixin-based architecture. All mixins are automatically included in `ProviderBase`:
|
|
116
|
+
|
|
117
|
+
- **`PackageMixin`**: Package dependency management and validation
|
|
118
|
+
- **`ConfigMixin`**: Configuration management and validation
|
|
119
|
+
- **`ServiceMixin`**: Business logic implementation and service methods
|
|
120
|
+
- **`UrlsMixin`**: URL routing and endpoint management (if applicable)
|
|
121
|
+
|
|
122
|
+
## Architecture
|
|
123
|
+
|
|
124
|
+
ProviderKit uses a mixin-based architecture:
|
|
125
|
+
|
|
126
|
+
- Each provider inherits from `ProviderBase` which combines all mixins
|
|
127
|
+
- Mixins are organized in dedicated files for clear separation of concerns
|
|
128
|
+
- Providers can be discovered, queried, and used programmatically
|
|
129
|
+
- The system validates dependencies and configuration before allowing provider usage
|
|
130
|
+
|
|
131
|
+
### Project Structure
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
python-providerkit/
|
|
135
|
+
├── src/providerkit/ # Main package
|
|
136
|
+
│ ├── kit/ # Core provider infrastructure
|
|
137
|
+
│ │ ├── __init__.py # ProviderBase class
|
|
138
|
+
│ │ ├── package.py # PackageMixin
|
|
139
|
+
│ │ ├── config.py # ConfigMixin
|
|
140
|
+
│ │ ├── service.py # ServiceMixin
|
|
141
|
+
│ │ └── urls.py # UrlsMixin
|
|
142
|
+
│ ├── providers/ # Provider implementations
|
|
143
|
+
│ ├── helpers.py # Utility functions
|
|
144
|
+
│ └── cli.py # CLI interface
|
|
145
|
+
├── tests/ # Test suite
|
|
146
|
+
└── docs/ # Documentation
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## CLI System
|
|
150
|
+
|
|
151
|
+
ProviderKit includes a flexible CLI system that discovers commands from:
|
|
152
|
+
|
|
153
|
+
1. **`commands/` directory**: A directory next to `cli.py` containing command modules
|
|
154
|
+
2. **`.commands.json` configuration file**: A JSON file that can specify:
|
|
155
|
+
- `packages`: List of packages to discover commands from
|
|
156
|
+
- `directories`: List of directories to scan for commands
|
|
157
|
+
- `commands`: Direct command definitions
|
|
158
|
+
|
|
159
|
+
### Creating Commands
|
|
160
|
+
|
|
161
|
+
Commands can be created in two ways:
|
|
162
|
+
|
|
163
|
+
#### Method 1: Using the `Command` class
|
|
164
|
+
|
|
165
|
+
Create a file in the `commands/` directory (e.g., `commands/mycommand.py`):
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
from .base import Command
|
|
169
|
+
|
|
170
|
+
def _mycommand_command(args: list[str]) -> bool:
|
|
171
|
+
"""Description of what this command does."""
|
|
172
|
+
# Command implementation
|
|
173
|
+
print("Hello from mycommand!")
|
|
174
|
+
return True
|
|
175
|
+
|
|
176
|
+
mycommand_command = Command(_mycommand_command, "Description of what this command does")
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
#### Method 2: Using functions ending with `_command`
|
|
180
|
+
|
|
181
|
+
```python
|
|
182
|
+
def mycommand_command(args: list[str]) -> bool:
|
|
183
|
+
"""Description of what this command does."""
|
|
184
|
+
# Command implementation
|
|
185
|
+
print("Hello from mycommand!")
|
|
186
|
+
return True
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Command Structure
|
|
190
|
+
|
|
191
|
+
Commands receive a list of string arguments and return a boolean indicating success:
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
def mycommand_command(args: list[str]) -> bool:
|
|
195
|
+
"""Command description for help text."""
|
|
196
|
+
if not args:
|
|
197
|
+
print("Usage: mycommand <arg1> <arg2>")
|
|
198
|
+
return False
|
|
199
|
+
|
|
200
|
+
# Process arguments
|
|
201
|
+
arg1 = args[0]
|
|
202
|
+
# ... command logic ...
|
|
203
|
+
|
|
204
|
+
return True # Success
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Environment Variables
|
|
208
|
+
|
|
209
|
+
### `ENVFILE_PATH`
|
|
210
|
+
|
|
211
|
+
The `ENVFILE_PATH` environment variable allows you to automatically specify the path to a `.env` file to load when starting services.
|
|
212
|
+
|
|
213
|
+
**Usage:**
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
# Absolute path
|
|
217
|
+
ENVFILE_PATH=/path/to/.env ./service.py dev install-dev
|
|
218
|
+
|
|
219
|
+
# Relative path (relative to project root)
|
|
220
|
+
ENVFILE_PATH=.env.local ./service.py quality lint
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**Behavior:**
|
|
224
|
+
|
|
225
|
+
- If the path is relative, it is resolved relative to the project root
|
|
226
|
+
- The `.env` file is automatically loaded before command execution
|
|
227
|
+
- Uses `python-dotenv` to parse the file (installed automatically if needed)
|
|
228
|
+
- Works with `dev` and `cli` services
|
|
229
|
+
|
|
230
|
+
### `ENSURE_VIRTUALENV`
|
|
231
|
+
|
|
232
|
+
The `ENSURE_VIRTUALENV` environment variable allows you to automatically activate the `.venv` virtual environment if it exists, before executing commands.
|
|
233
|
+
|
|
234
|
+
**Usage:**
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
ENSURE_VIRTUALENV=1 ./service.py dev help
|
|
238
|
+
ENSURE_VIRTUALENV=1 ./service.py quality lint
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**Behavior:**
|
|
242
|
+
|
|
243
|
+
- Must be set to `1` to be active
|
|
244
|
+
- Automatically activates the `.venv` virtual environment at the project root
|
|
245
|
+
- Modifies `sys.executable`, `PATH`, and `sys.path` to use the venv's Python
|
|
246
|
+
- Only works if the `.venv` directory exists
|
|
247
|
+
- Compatible with Windows and Unix
|
|
248
|
+
|
|
249
|
+
**Note:** The `ensure_virtualenv()` function is also automatically called by the main service, but `ENSURE_VIRTUALENV` allows you to force activation even in contexts where it might not be automatic.
|
|
250
|
+
|
|
251
|
+
## Use Cases
|
|
252
|
+
|
|
253
|
+
- Multi-provider integrations (email, SMS, payment, etc.)
|
|
254
|
+
- Provider fallback mechanisms
|
|
255
|
+
- Provider discovery and selection
|
|
256
|
+
- Configuration validation across multiple providers
|
|
257
|
+
- Unified interface for heterogeneous services
|
|
258
|
+
|
|
259
|
+
## Development
|
|
260
|
+
|
|
261
|
+
ProviderKit uses qualitybase for development tooling:
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
# Quality checks
|
|
265
|
+
./service.py quality lint
|
|
266
|
+
./service.py quality security
|
|
267
|
+
./service.py quality all
|
|
268
|
+
|
|
269
|
+
# Development tools
|
|
270
|
+
./service.py dev venv
|
|
271
|
+
./service.py dev install-dev
|
|
272
|
+
./service.py dev clean
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
See `docs/` for project rules and guidelines.
|
|
276
|
+
|