unitysvc-services 0.1.4__py3-none-any.whl → 0.1.5__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.
- unitysvc_services/api.py +58 -15
- unitysvc_services/cli.py +2 -1
- unitysvc_services/models/base.py +12 -0
- unitysvc_services/populate.py +18 -0
- unitysvc_services/publisher.py +329 -199
- unitysvc_services/query.py +310 -302
- unitysvc_services/test.py +769 -0
- unitysvc_services/utils.py +53 -0
- unitysvc_services/validator.py +19 -7
- {unitysvc_services-0.1.4.dist-info → unitysvc_services-0.1.5.dist-info}/METADATA +40 -33
- unitysvc_services-0.1.5.dist-info/RECORD +26 -0
- {unitysvc_services-0.1.4.dist-info → unitysvc_services-0.1.5.dist-info}/entry_points.txt +1 -0
- unitysvc_services-0.1.4.dist-info/RECORD +0 -25
- {unitysvc_services-0.1.4.dist-info → unitysvc_services-0.1.5.dist-info}/WHEEL +0 -0
- {unitysvc_services-0.1.4.dist-info → unitysvc_services-0.1.5.dist-info}/licenses/LICENSE +0 -0
- {unitysvc_services-0.1.4.dist-info → unitysvc_services-0.1.5.dist-info}/top_level.txt +0 -0
unitysvc_services/utils.py
CHANGED
@@ -7,6 +7,7 @@ from pathlib import Path
|
|
7
7
|
from typing import Any
|
8
8
|
|
9
9
|
import tomli_w
|
10
|
+
from jinja2 import Template
|
10
11
|
|
11
12
|
|
12
13
|
def load_data_file(file_path: Path) -> tuple[dict[str, Any], str]:
|
@@ -336,3 +337,55 @@ def convert_convenience_fields_to_documents(
|
|
336
337
|
del data[terms_field]
|
337
338
|
|
338
339
|
return data
|
340
|
+
|
341
|
+
|
342
|
+
def render_template_file(
|
343
|
+
file_path: Path,
|
344
|
+
listing: dict[str, Any] | None = None,
|
345
|
+
offering: dict[str, Any] | None = None,
|
346
|
+
provider: dict[str, Any] | None = None,
|
347
|
+
seller: dict[str, Any] | None = None,
|
348
|
+
) -> tuple[str, str]:
|
349
|
+
"""Render a Jinja2 template file and return content and new filename.
|
350
|
+
|
351
|
+
If the file is not a template (.j2 extension), returns the file content as-is
|
352
|
+
and the original filename.
|
353
|
+
|
354
|
+
Args:
|
355
|
+
file_path: Path to the file (may or may not be a .j2 template)
|
356
|
+
listing: Listing data for template rendering (optional)
|
357
|
+
offering: Offering data for template rendering (optional)
|
358
|
+
provider: Provider data for template rendering (optional)
|
359
|
+
seller: Seller data for template rendering (optional)
|
360
|
+
|
361
|
+
Returns:
|
362
|
+
Tuple of (rendered_content, new_filename_without_j2)
|
363
|
+
|
364
|
+
Raises:
|
365
|
+
Exception: If template rendering fails
|
366
|
+
"""
|
367
|
+
# Read file content
|
368
|
+
with open(file_path, encoding="utf-8") as f:
|
369
|
+
file_content = f.read()
|
370
|
+
|
371
|
+
# Check if this is a Jinja2 template
|
372
|
+
is_template = file_path.name.endswith(".j2")
|
373
|
+
|
374
|
+
if is_template:
|
375
|
+
# Render the template
|
376
|
+
template = Template(file_content)
|
377
|
+
rendered_content = template.render(
|
378
|
+
listing=listing or {},
|
379
|
+
offering=offering or {},
|
380
|
+
provider=provider or {},
|
381
|
+
seller=seller or {},
|
382
|
+
)
|
383
|
+
|
384
|
+
# Strip .j2 from filename
|
385
|
+
# Example: test.py.j2 -> test.py
|
386
|
+
new_filename = file_path.name[:-3] # Remove last 3 characters (.j2)
|
387
|
+
|
388
|
+
return rendered_content, new_filename
|
389
|
+
else:
|
390
|
+
# Not a template - return as-is
|
391
|
+
return file_content, file_path.name
|
unitysvc_services/validator.py
CHANGED
@@ -322,8 +322,15 @@ class DataValidator:
|
|
322
322
|
|
323
323
|
return len(errors) == 0, errors
|
324
324
|
|
325
|
-
def
|
326
|
-
"""Validate a
|
325
|
+
def validate_jinja2_file(self, file_path: Path) -> tuple[bool, list[str]]:
|
326
|
+
"""Validate a file with Jinja2 template syntax.
|
327
|
+
|
328
|
+
This validates any file ending with .j2 extension, including:
|
329
|
+
- .md.j2 (Jinja2 markdown templates)
|
330
|
+
- .py.j2 (Jinja2 Python code example templates)
|
331
|
+
- .js.j2 (Jinja2 JavaScript code example templates)
|
332
|
+
- .sh.j2 (Jinja2 shell script templates)
|
333
|
+
"""
|
327
334
|
errors: list[str] = []
|
328
335
|
|
329
336
|
try:
|
@@ -344,7 +351,7 @@ class DataValidator:
|
|
344
351
|
|
345
352
|
return len(errors) == 0, errors
|
346
353
|
except Exception as e:
|
347
|
-
return False, [f"Failed to read
|
354
|
+
return False, [f"Failed to read template file: {e}"]
|
348
355
|
|
349
356
|
def validate_seller_uniqueness(self) -> tuple[bool, list[str]]:
|
350
357
|
"""
|
@@ -502,13 +509,18 @@ class DataValidator:
|
|
502
509
|
if any(part.startswith(".") for part in file_path.parts):
|
503
510
|
continue
|
504
511
|
|
505
|
-
|
512
|
+
# Check if file should be validated
|
513
|
+
# Only .j2 files (Jinja2 templates) are validated for Jinja2 syntax
|
514
|
+
is_template = file_path.name.endswith(".j2")
|
515
|
+
is_data_file = file_path.suffix in [".json", ".toml"]
|
516
|
+
|
517
|
+
if file_path.is_file() and (is_data_file or is_template):
|
506
518
|
relative_path = file_path.relative_to(self.data_dir)
|
507
519
|
|
508
|
-
if
|
520
|
+
if is_data_file:
|
509
521
|
is_valid, errors = self.validate_data_file(file_path)
|
510
|
-
elif
|
511
|
-
is_valid, errors = self.
|
522
|
+
elif is_template:
|
523
|
+
is_valid, errors = self.validate_jinja2_file(file_path)
|
512
524
|
else:
|
513
525
|
continue
|
514
526
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: unitysvc-services
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.5
|
4
4
|
Summary: SDK for digital service providers on UnitySVC
|
5
5
|
Author-email: Bo Peng <bo.peng@unitysvc.com>
|
6
6
|
Maintainer-email: Bo Peng <bo.peng@unitysvc.com>
|
@@ -40,22 +40,23 @@ Requires-Dist: mkdocs-material; extra == "docs"
|
|
40
40
|
Requires-Dist: mkdocs-autorefs; extra == "docs"
|
41
41
|
Dynamic: license-file
|
42
42
|
|
43
|
-
# UnitySVC
|
43
|
+
# UnitySVC Services SDK
|
44
44
|
|
45
45
|

|
46
46
|
[](https://unitysvc-services.readthedocs.io/en/latest/?version=latest)
|
47
47
|
|
48
|
-
Client library and CLI tools for digital service
|
48
|
+
Client library and CLI tools for sellers and providers of digital service to interact with the UnitySVC platform.
|
49
49
|
|
50
50
|
**📚 [Full Documentation](https://unitysvc-services.readthedocs.io)** | **🚀 [Getting Started](https://unitysvc-services.readthedocs.io/en/latest/getting-started/)** | **📖 [CLI Reference](https://unitysvc-services.readthedocs.io/en/latest/cli-reference/)**
|
51
51
|
|
52
52
|
## Overview
|
53
53
|
|
54
|
-
UnitySVC
|
54
|
+
UnitySVC Services SDK enables digital service sellers and providers to manage their service offerings through a **local-first, version-controlled workflow**:
|
55
55
|
|
56
56
|
- **Define** service data using schema-validated files (JSON/TOML)
|
57
57
|
- **Manage** everything locally in git-controlled directories
|
58
|
-
- **Validate** data against schemas
|
58
|
+
- **Validate** data against schemas
|
59
|
+
- **Test** code examples using provider credentials
|
59
60
|
- **Publish** to UnitySVC platform when ready
|
60
61
|
- **Automate** with populate scripts for dynamic catalogs
|
61
62
|
|
@@ -67,31 +68,34 @@ pip install unitysvc-services
|
|
67
68
|
|
68
69
|
Requires Python 3.11+
|
69
70
|
|
71
|
+
**CLI Alias:** The command `unitysvc_services` can also be invoked using the shorter alias `usvc`.
|
72
|
+
|
70
73
|
## Quick Example
|
71
74
|
|
72
75
|
```bash
|
73
|
-
# Initialize provider and service
|
74
|
-
|
75
|
-
|
76
|
-
|
76
|
+
# Initialize provider and service (using short alias 'usvc')
|
77
|
+
usvc init provider my-provider
|
78
|
+
usvc init offering my-service
|
79
|
+
usvc init seller my-marketplace
|
77
80
|
|
78
81
|
# Validate and format
|
79
|
-
|
80
|
-
|
82
|
+
usvc validate
|
83
|
+
usvc format
|
84
|
+
|
85
|
+
# Test code examples with upstream credentials
|
86
|
+
usvc test list --provider fireworks
|
87
|
+
usvc test run --provider fireworks --services "llama*"
|
88
|
+
|
89
|
+
# if you write a script to manage services
|
90
|
+
usvc populate
|
81
91
|
|
82
92
|
# Publish to platform (publishes all: sellers, providers, offerings, listings)
|
83
93
|
export UNITYSVC_BASE_URL="https://api.unitysvc.com/api/v1"
|
84
94
|
export UNITYSVC_API_KEY="your-api-key"
|
85
|
-
|
86
|
-
|
87
|
-
# Or publish specific types only
|
88
|
-
unitysvc_services publish providers
|
89
|
-
|
90
|
-
# Verify with default fields
|
91
|
-
unitysvc_services query offerings
|
95
|
+
usvc publish
|
92
96
|
|
93
|
-
# Query
|
94
|
-
|
97
|
+
# Query unitysvc backend to verify data
|
98
|
+
usvc query providers --fields id,name,contact_email
|
95
99
|
```
|
96
100
|
|
97
101
|
## Key Features
|
@@ -108,13 +112,13 @@ unitysvc_services query providers --fields id,name,contact_email
|
|
108
112
|
### Manual Workflow (small catalogs)
|
109
113
|
|
110
114
|
```bash
|
111
|
-
init → edit files → validate → format → publish → verify
|
115
|
+
init → edit files → validate → test → format → publish → verify
|
112
116
|
```
|
113
117
|
|
114
118
|
### Automated Workflow (large/dynamic catalogs)
|
115
119
|
|
116
120
|
```bash
|
117
|
-
init
|
121
|
+
init → configure populate script → populate → validate → publish
|
118
122
|
```
|
119
123
|
|
120
124
|
See [Workflows Documentation](https://unitysvc-services.readthedocs.io/en/latest/workflows/) for details.
|
@@ -137,24 +141,27 @@ See [Data Structure Documentation](https://unitysvc-services.readthedocs.io/en/l
|
|
137
141
|
|
138
142
|
## CLI Commands
|
139
143
|
|
140
|
-
| Command | Description
|
141
|
-
| ---------- |
|
142
|
-
| `init` | Initialize new data files from schemas
|
143
|
-
| `list` | List local data files
|
144
|
-
| `query` | Query backend API for published data
|
145
|
-
| `publish` | Publish data to backend
|
146
|
-
| `update` | Update local file fields
|
147
|
-
| `validate` | Validate data consistency
|
148
|
-
| `format` | Format data files
|
149
|
-
| `populate` | Execute provider populate scripts
|
144
|
+
| Command | Description |
|
145
|
+
| ---------- | ------------------------------------------------ |
|
146
|
+
| `init` | Initialize new data files from schemas |
|
147
|
+
| `list` | List local data files |
|
148
|
+
| `query` | Query backend API for published data |
|
149
|
+
| `publish` | Publish data to backend |
|
150
|
+
| `update` | Update local file fields |
|
151
|
+
| `validate` | Validate data consistency |
|
152
|
+
| `format` | Format data files |
|
153
|
+
| `populate` | Execute provider populate scripts |
|
154
|
+
| `test` | Test code examples with upstream API credentials |
|
150
155
|
|
151
|
-
Run `
|
156
|
+
Run `usvc --help` or see [CLI Reference](https://unitysvc-services.readthedocs.io/en/latest/cli-reference/) for complete documentation.
|
152
157
|
|
153
158
|
## Documentation
|
154
159
|
|
155
160
|
- **[Getting Started](https://unitysvc-services.readthedocs.io/en/latest/getting-started/)** - Installation and first steps
|
156
161
|
- **[Data Structure](https://unitysvc-services.readthedocs.io/en/latest/data-structure/)** - File organization rules
|
157
162
|
- **[Workflows](https://unitysvc-services.readthedocs.io/en/latest/workflows/)** - Manual and automated patterns
|
163
|
+
- **[Documenting Service Listings](https://unitysvc-services.readthedocs.io/en/latest/documenting-services/)** - Add documentation to services
|
164
|
+
- **[Creating Code Examples](https://unitysvc-services.readthedocs.io/en/latest/code-examples/)** - Develop and test code examples
|
158
165
|
- **[CLI Reference](https://unitysvc-services.readthedocs.io/en/latest/cli-reference/)** - All commands and options
|
159
166
|
- **[File Schemas](https://unitysvc-services.readthedocs.io/en/latest/file-schemas/)** - Schema specifications
|
160
167
|
- **[Python API](https://unitysvc-services.readthedocs.io/en/latest/api-reference/)** - Programmatic usage
|
@@ -0,0 +1,26 @@
|
|
1
|
+
unitysvc_services/__init__.py,sha256=J6F3RlZCJUVjhZoprfbrYCxe3l9ynQQbGO7pf7FyqlM,110
|
2
|
+
unitysvc_services/api.py,sha256=d3xY4ElA4aCAl62xrwjZ6qIWUoYT-4Q8wJ8BJbyZzXI,11990
|
3
|
+
unitysvc_services/cli.py,sha256=omHzrWk8iZJUjZTE5KCmEK1wnRGGnQk_BNV-hKqucnA,725
|
4
|
+
unitysvc_services/format_data.py,sha256=Jl9Vj3fRX852fHSUa5DzO-oiFQwuQHC3WMCDNIlo1Lc,5460
|
5
|
+
unitysvc_services/list.py,sha256=QDp9BByaoeFeJxXJN9RQ-jU99mH9Guq9ampfXCbpZmI,7033
|
6
|
+
unitysvc_services/populate.py,sha256=jiqS2D3_widV6siPe3OBvw7ZdG9MuddEIOuTUCtMM5c,7605
|
7
|
+
unitysvc_services/publisher.py,sha256=mKlY7-zEP8dtldcO8DJtbXVrdOACZCYsu49yP2iSD4w,53855
|
8
|
+
unitysvc_services/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
+
unitysvc_services/query.py,sha256=q0_g5YAl9cPlHpW7k7Y6A-t4fQSdI-_4Jl6g2KgkEm0,24049
|
10
|
+
unitysvc_services/scaffold.py,sha256=Y73IX8vskImxSvxDgR0mvEFuAMYnBKfttn3bjcz3jmQ,40331
|
11
|
+
unitysvc_services/test.py,sha256=ZwWr2WCfzRBY39tuijK5P2v0VZ7PXwg3tFtJkTOsGrU,28341
|
12
|
+
unitysvc_services/update.py,sha256=K9swocTUnqqiSgARo6GmuzTzUySSpyqqPPW4xF7ZU-g,9659
|
13
|
+
unitysvc_services/utils.py,sha256=9htuxyzEjjbbAi704td9mOrtPzSOJzY46ALuup6bJW0,13093
|
14
|
+
unitysvc_services/validator.py,sha256=sasMpdDhoWZJZ-unrnDhaJfyxHSm3IgQjEdmPvXrFEE,29525
|
15
|
+
unitysvc_services/models/__init__.py,sha256=hJCc2KSZmIHlKWKE6GpLGdeVB6LIpyVUKiOKnwmKvCs,200
|
16
|
+
unitysvc_services/models/base.py,sha256=cSxOYs_YSrqkQLBKIGVZmK627MyMft7cDn0WnrQlzPM,18736
|
17
|
+
unitysvc_services/models/listing_v1.py,sha256=PPb9hIdWQp80AWKLxFXYBDcWXzNcDrO4v6rqt5_i2qo,3083
|
18
|
+
unitysvc_services/models/provider_v1.py,sha256=76EK1i0hVtdx_awb00-ZMtSj4Oc9Zp4xZ-DeXmG3iTY,2701
|
19
|
+
unitysvc_services/models/seller_v1.py,sha256=oll2ZZBPBDX8wslHrbsCKf_jIqHNte2VEj5RJ9bawR4,3520
|
20
|
+
unitysvc_services/models/service_v1.py,sha256=Xpk-K-95M1LRqYM8nNJcll8t-lsW9Xdi2_bVbYNs8-M,3019
|
21
|
+
unitysvc_services-0.1.5.dist-info/licenses/LICENSE,sha256=_p8V6A8OMPu2HIztn3O01v0-urZFwk0Dd3Yk_PTIlL8,1065
|
22
|
+
unitysvc_services-0.1.5.dist-info/METADATA,sha256=LZrIRYvKsl0t2mptoidJVkjOeNJFbx_a-QgUxEJLsgY,7234
|
23
|
+
unitysvc_services-0.1.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
24
|
+
unitysvc_services-0.1.5.dist-info/entry_points.txt,sha256=RBhVHKky3rsOly4jVa29c7UAw5ZwNNWnttmtzozr5O0,97
|
25
|
+
unitysvc_services-0.1.5.dist-info/top_level.txt,sha256=GIotQj-Ro2ruR7eupM1r58PWqIHTAq647ORL7E2kneo,18
|
26
|
+
unitysvc_services-0.1.5.dist-info/RECORD,,
|
@@ -1,25 +0,0 @@
|
|
1
|
-
unitysvc_services/__init__.py,sha256=J6F3RlZCJUVjhZoprfbrYCxe3l9ynQQbGO7pf7FyqlM,110
|
2
|
-
unitysvc_services/api.py,sha256=FKIid1gUJcEcN_4P9d5-SgmJfW73WHBg5wXsVHeqNHQ,9888
|
3
|
-
unitysvc_services/cli.py,sha256=OK0IZyAckxP15jRWU_W49hl3t7XcNRtd8BoDMyRKqNM,682
|
4
|
-
unitysvc_services/format_data.py,sha256=Jl9Vj3fRX852fHSUa5DzO-oiFQwuQHC3WMCDNIlo1Lc,5460
|
5
|
-
unitysvc_services/list.py,sha256=QDp9BByaoeFeJxXJN9RQ-jU99mH9Guq9ampfXCbpZmI,7033
|
6
|
-
unitysvc_services/populate.py,sha256=zkcjIy8BWuQSO7JwiRNHKgGoxQvc3ujluUQdYixdBvY,6626
|
7
|
-
unitysvc_services/publisher.py,sha256=dkufYcuBJ0dDoTQJm7BMOug_Pr2RyXMVI8nvZjy-zdM,50420
|
8
|
-
unitysvc_services/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
-
unitysvc_services/query.py,sha256=2Rn6gioAN3W6KIumVzCpSJXzhJLJUDLkDla_GVwNx9I,24793
|
10
|
-
unitysvc_services/scaffold.py,sha256=Y73IX8vskImxSvxDgR0mvEFuAMYnBKfttn3bjcz3jmQ,40331
|
11
|
-
unitysvc_services/update.py,sha256=K9swocTUnqqiSgARo6GmuzTzUySSpyqqPPW4xF7ZU-g,9659
|
12
|
-
unitysvc_services/utils.py,sha256=GN0gkVTU8fOx2G0EbqnWmx8w9eFsoPfRprPjwCyPYkE,11371
|
13
|
-
unitysvc_services/validator.py,sha256=VAII5mu_Jdyr96v4nwXzihsoAj7DJiXN6LjhL8lGGUo,29054
|
14
|
-
unitysvc_services/models/__init__.py,sha256=hJCc2KSZmIHlKWKE6GpLGdeVB6LIpyVUKiOKnwmKvCs,200
|
15
|
-
unitysvc_services/models/base.py,sha256=3FdlR-_tBOFC2JbVNFNQA4-D1Lhlo5UZQh1QDgKnS_I,18293
|
16
|
-
unitysvc_services/models/listing_v1.py,sha256=PPb9hIdWQp80AWKLxFXYBDcWXzNcDrO4v6rqt5_i2qo,3083
|
17
|
-
unitysvc_services/models/provider_v1.py,sha256=76EK1i0hVtdx_awb00-ZMtSj4Oc9Zp4xZ-DeXmG3iTY,2701
|
18
|
-
unitysvc_services/models/seller_v1.py,sha256=oll2ZZBPBDX8wslHrbsCKf_jIqHNte2VEj5RJ9bawR4,3520
|
19
|
-
unitysvc_services/models/service_v1.py,sha256=Xpk-K-95M1LRqYM8nNJcll8t-lsW9Xdi2_bVbYNs8-M,3019
|
20
|
-
unitysvc_services-0.1.4.dist-info/licenses/LICENSE,sha256=_p8V6A8OMPu2HIztn3O01v0-urZFwk0Dd3Yk_PTIlL8,1065
|
21
|
-
unitysvc_services-0.1.4.dist-info/METADATA,sha256=7LiJhVwEw0fL72bOWwX7kU5KjQ-PDmt23CD4FgEI8YU,6628
|
22
|
-
unitysvc_services-0.1.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
23
|
-
unitysvc_services-0.1.4.dist-info/entry_points.txt,sha256=-vodnbPmo7QQmFu8jdG6sCyGRVM727w9Nhwp4Vwau_k,64
|
24
|
-
unitysvc_services-0.1.4.dist-info/top_level.txt,sha256=GIotQj-Ro2ruR7eupM1r58PWqIHTAq647ORL7E2kneo,18
|
25
|
-
unitysvc_services-0.1.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|