unitysvc-data 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.
- unitysvc_data-0.1.0/LICENSE +21 -0
- unitysvc_data-0.1.0/PKG-INFO +189 -0
- unitysvc_data-0.1.0/README.md +168 -0
- unitysvc_data-0.1.0/pyproject.toml +40 -0
- unitysvc_data-0.1.0/setup.cfg +4 -0
- unitysvc_data-0.1.0/src/unitysvc_data/__init__.py +119 -0
- unitysvc_data-0.1.0/src/unitysvc_data/_manifest.json +91 -0
- unitysvc_data-0.1.0/src/unitysvc_data/_version.py +1 -0
- unitysvc_data-0.1.0/src/unitysvc_data/cli.py +222 -0
- unitysvc_data-0.1.0/src/unitysvc_data/examples/api/connectivity/README.md +45 -0
- unitysvc_data-0.1.0/src/unitysvc_data/examples/api/connectivity/connectivity-v1.sh.j2 +42 -0
- unitysvc_data-0.1.0/src/unitysvc_data/examples/llm/request-template/README.md +50 -0
- unitysvc_data-0.1.0/src/unitysvc_data/examples/llm/request-template/request-template-v1.json +13 -0
- unitysvc_data-0.1.0/src/unitysvc_data/examples/s3/code-example/README.md +49 -0
- unitysvc_data-0.1.0/src/unitysvc_data/examples/s3/code-example/code-example-v1.py.j2 +48 -0
- unitysvc_data-0.1.0/src/unitysvc_data/examples/s3/connectivity/README.md +53 -0
- unitysvc_data-0.1.0/src/unitysvc_data/examples/s3/connectivity/connectivity-v1.py.j2 +63 -0
- unitysvc_data-0.1.0/src/unitysvc_data/examples/s3/description/README.md +45 -0
- unitysvc_data-0.1.0/src/unitysvc_data/examples/s3/description/description-v1.md +21 -0
- unitysvc_data-0.1.0/src/unitysvc_data/examples/smtp/connectivity/README.md +50 -0
- unitysvc_data-0.1.0/src/unitysvc_data/examples/smtp/connectivity/connectivity-v1.sh.j2 +34 -0
- unitysvc_data-0.1.0/src/unitysvc_data/presets.py +259 -0
- unitysvc_data-0.1.0/src/unitysvc_data/py.typed +0 -0
- unitysvc_data-0.1.0/src/unitysvc_data.egg-info/PKG-INFO +189 -0
- unitysvc_data-0.1.0/src/unitysvc_data.egg-info/SOURCES.txt +30 -0
- unitysvc_data-0.1.0/src/unitysvc_data.egg-info/dependency_links.txt +1 -0
- unitysvc_data-0.1.0/src/unitysvc_data.egg-info/entry_points.txt +2 -0
- unitysvc_data-0.1.0/src/unitysvc_data.egg-info/requires.txt +4 -0
- unitysvc_data-0.1.0/src/unitysvc_data.egg-info/top_level.txt +1 -0
- unitysvc_data-0.1.0/tests/test_build.py +329 -0
- unitysvc_data-0.1.0/tests/test_cli.py +200 -0
- unitysvc_data-0.1.0/tests/test_presets.py +310 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 UnitySVC
|
|
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.
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: unitysvc-data
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Standard examples and presets for UnitySVC data packages
|
|
5
|
+
Author-email: Bo Peng <bo.peng@unitysvc.com>
|
|
6
|
+
Maintainer-email: Bo Peng <bo.peng@unitysvc.com>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/unitysvc/unitysvc-data
|
|
9
|
+
Project-URL: Issues, https://github.com/unitysvc/unitysvc-sellers/issues
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Typing :: Typed
|
|
14
|
+
Requires-Python: >=3.11
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Provides-Extra: test
|
|
18
|
+
Requires-Dist: pytest>=7; extra == "test"
|
|
19
|
+
Requires-Dist: ruff; extra == "test"
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
22
|
+
# unitysvc-data
|
|
23
|
+
|
|
24
|
+
Standard examples and presets for UnitySVC — primary consumer is
|
|
25
|
+
[unitysvc-sellers](https://github.com/unitysvc/unitysvc-sellers), but the
|
|
26
|
+
same preset / manifest machinery is intended to serve other parts of the
|
|
27
|
+
platform too.
|
|
28
|
+
|
|
29
|
+
A data-first Python package that ships:
|
|
30
|
+
|
|
31
|
+
- Example files (connectivity tests, usage snippets, descriptions)
|
|
32
|
+
organised under `src/unitysvc_data/examples/<gateway>/<family>/`.
|
|
33
|
+
- A generated manifest (`_manifest.json`) mapping every preset name to
|
|
34
|
+
its metadata and bundled file.
|
|
35
|
+
- Two primitives for consumers:
|
|
36
|
+
- `doc_preset(source, **overrides)` — returns a full document
|
|
37
|
+
record (category, description, mime_type, file_path, ...) ready
|
|
38
|
+
to drop into `listing.json`. This is the expansion the SDK
|
|
39
|
+
applies to `$preset` JSON sentinels at upload time.
|
|
40
|
+
- `file_preset(source)` — returns the raw UTF-8 content of the
|
|
41
|
+
preset's bundled file. Useful when the example isn't a listing
|
|
42
|
+
document (embed as snippet, feed to a test harness, etc.).
|
|
43
|
+
|
|
44
|
+
Both accept either a bare name (`"s3_connectivity"`,
|
|
45
|
+
`"s3_connectivity_v1"`) or a `{"$preset": "...", "$with": {...}}`
|
|
46
|
+
sentinel, so the same function works from JSON walkers and from
|
|
47
|
+
programmatic Python code.
|
|
48
|
+
|
|
49
|
+
Sellers reference a preset from their `listing.json` like this:
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"documents": {
|
|
54
|
+
"Connectivity test": { "$preset": "s3_connectivity" },
|
|
55
|
+
"Usage (Python)": { "$preset": "s3_code_example_v1",
|
|
56
|
+
"$with": { "description": "Lists objects in our bucket" } }
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The SDK walks the parsed listing and calls `doc_preset(...)` on each
|
|
62
|
+
sentinel, substituting the bundled file's absolute path into
|
|
63
|
+
`file_path`, then feeds the result into the existing upload pipeline.
|
|
64
|
+
No custom URL scheme, no extra render pass.
|
|
65
|
+
|
|
66
|
+
## CLI
|
|
67
|
+
|
|
68
|
+
Installing the package provides a `usvc_data` command for shell-level
|
|
69
|
+
access to the same data:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
usvc_data list # every preset + aliases
|
|
73
|
+
usvc_data list --json # machine-readable form
|
|
74
|
+
|
|
75
|
+
usvc_data info s3_connectivity # README prose for a preset
|
|
76
|
+
|
|
77
|
+
usvc_data doc-preset s3_connectivity # expanded JSON record
|
|
78
|
+
usvc_data doc-preset s3_connectivity --with '{"description":"ours"}'
|
|
79
|
+
usvc_data doc-preset s3_connectivity --compact # single-line JSON
|
|
80
|
+
|
|
81
|
+
usvc_data file-preset s3_connectivity # raw file content to stdout
|
|
82
|
+
usvc_data file-preset s3_connectivity > /tmp/s3.py # pipe to file (raw template)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Note that `file-preset` returns the raw file content — `.j2` templates
|
|
86
|
+
come through with Jinja2 markers intact. The sellers SDK renders them
|
|
87
|
+
with per-listing context at upload time; if you pipe a `.j2` preset
|
|
88
|
+
directly to an executable file you'll get a template, not a runnable
|
|
89
|
+
script.
|
|
90
|
+
|
|
91
|
+
`--with` accepts a JSON object whose keys are the overridable fields
|
|
92
|
+
(`description`, `is_active`, `is_public`, `meta`). Forbidden keys and
|
|
93
|
+
unknown preset names exit with status 1 and a message on stderr.
|
|
94
|
+
|
|
95
|
+
## Layout
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
src/unitysvc_data/
|
|
99
|
+
├── __init__.py # example_path / read_example / list_examples
|
|
100
|
+
├── presets.py # doc_preset / file_preset / PRESETS / ALIASES
|
|
101
|
+
├── cli.py # usvc_data entry point
|
|
102
|
+
├── _manifest.json # generated — committed — source of truth at runtime
|
|
103
|
+
└── examples/
|
|
104
|
+
├── api/ # generic HTTP services
|
|
105
|
+
│ └── connectivity/
|
|
106
|
+
│ ├── README.md # front-matter + prose
|
|
107
|
+
│ └── connectivity-v1.sh.j2
|
|
108
|
+
├── llm/ # LLM gateway
|
|
109
|
+
│ └── request-template/
|
|
110
|
+
│ ├── README.md
|
|
111
|
+
│ └── request-template-v1.json
|
|
112
|
+
├── s3/ # S3-compatible storage gateway
|
|
113
|
+
│ ├── code-example/ ...
|
|
114
|
+
│ ├── connectivity/ ...
|
|
115
|
+
│ └── description/ ...
|
|
116
|
+
└── smtp/ # SMTP relay
|
|
117
|
+
└── connectivity/ ...
|
|
118
|
+
|
|
119
|
+
tools/
|
|
120
|
+
└── build.py # regenerate _manifest.json + MANIFEST.md
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Each gateway holds one or more **preset families** (e.g. `s3/connectivity/`).
|
|
124
|
+
A family directory contains:
|
|
125
|
+
|
|
126
|
+
- `README.md` with TOML front-matter delimited by `+++` lines. The
|
|
127
|
+
front-matter has every piece of metadata for the family
|
|
128
|
+
(`preset_name`, `category`, `mime_type`, `file`, `description`,
|
|
129
|
+
`is_active`, `is_public`, `meta`). Prose under the front-matter
|
|
130
|
+
documents the example and any per-version differences.
|
|
131
|
+
- One file per version, named `<stem>-v<N>.<suffix>` where stem and
|
|
132
|
+
suffix come from the `file` field — so `file = "connectivity.sh.j2"`
|
|
133
|
+
matches `connectivity-v1.sh.j2`, `connectivity-v2.sh.j2`, ....
|
|
134
|
+
|
|
135
|
+
Versions are **discovered automatically** by scanning the family
|
|
136
|
+
directory; authors never list them explicitly. Adding a new version
|
|
137
|
+
is purely "drop a new `-v<N>.<ext>` file and rebuild."
|
|
138
|
+
|
|
139
|
+
[`MANIFEST.md`](MANIFEST.md) at the repo root is the human-readable
|
|
140
|
+
roster of every preset, also generated by `tools/build.py`.
|
|
141
|
+
|
|
142
|
+
## Preset naming
|
|
143
|
+
|
|
144
|
+
| Form | Resolves to | Use when |
|
|
145
|
+
|-----------------------------------|--------------------------------------------|----------------------|
|
|
146
|
+
| `s3_connectivity_v1` | version 1 of the `s3/connectivity` family | pinning to an exact version |
|
|
147
|
+
| `s3_connectivity` (alias) | latest version of that family | tracking the latest |
|
|
148
|
+
|
|
149
|
+
Seller data that pins to a versioned name stays byte-identical across
|
|
150
|
+
`pip upgrade`s. Data that uses the alias tracks the newest version
|
|
151
|
+
automatically.
|
|
152
|
+
|
|
153
|
+
## Versioning discipline
|
|
154
|
+
|
|
155
|
+
- Example files are **append-only**. `connectivity-v1.py.j2` is
|
|
156
|
+
frozen forever; fixes ship as `connectivity-v2.py.j2` dropped into
|
|
157
|
+
the same directory.
|
|
158
|
+
- The version-less alias always points at the highest-`v` file in the
|
|
159
|
+
family. Landing a new version shifts the alias automatically the
|
|
160
|
+
next time `python tools/build.py` runs.
|
|
161
|
+
- `preset_name` is globally unique across the whole tree — declaring
|
|
162
|
+
the same `preset_name` in two READMEs is a build error.
|
|
163
|
+
- Package version bumps are additive (new version or new family →
|
|
164
|
+
minor bump; never mutate existing `_vN` → no breaking release).
|
|
165
|
+
Bump major only to remove a `_vN` (should be vanishingly rare).
|
|
166
|
+
|
|
167
|
+
## Contributing
|
|
168
|
+
|
|
169
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the full walkthrough: how
|
|
170
|
+
to add a new family, how to publish a new version, front-matter
|
|
171
|
+
reference, filename conventions, and the pre-submission checklist.
|
|
172
|
+
|
|
173
|
+
In one line: drop your file at
|
|
174
|
+
`src/unitysvc_data/examples/<gateway>/<family>/<stem>-v<N>.<ext>[.j2]`,
|
|
175
|
+
write the family's `README.md`, run `python tools/build.py`, open the PR.
|
|
176
|
+
|
|
177
|
+
## Development
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
uv pip install -e '.[test]'
|
|
181
|
+
pytest -q # runs tests + manifest-freshness check
|
|
182
|
+
python tools/build.py # regenerate manifest + roster
|
|
183
|
+
python tools/build.py --check # CI mode: non-zero exit if stale
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
CI ([`.github/workflows/ci.yml`](.github/workflows/ci.yml)) runs
|
|
187
|
+
`tools/build.py --check`, `ruff`, `pytest` on Python 3.11 and 3.12,
|
|
188
|
+
then builds a wheel and verifies it includes every example file and
|
|
189
|
+
the manifest.
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# unitysvc-data
|
|
2
|
+
|
|
3
|
+
Standard examples and presets for UnitySVC — primary consumer is
|
|
4
|
+
[unitysvc-sellers](https://github.com/unitysvc/unitysvc-sellers), but the
|
|
5
|
+
same preset / manifest machinery is intended to serve other parts of the
|
|
6
|
+
platform too.
|
|
7
|
+
|
|
8
|
+
A data-first Python package that ships:
|
|
9
|
+
|
|
10
|
+
- Example files (connectivity tests, usage snippets, descriptions)
|
|
11
|
+
organised under `src/unitysvc_data/examples/<gateway>/<family>/`.
|
|
12
|
+
- A generated manifest (`_manifest.json`) mapping every preset name to
|
|
13
|
+
its metadata and bundled file.
|
|
14
|
+
- Two primitives for consumers:
|
|
15
|
+
- `doc_preset(source, **overrides)` — returns a full document
|
|
16
|
+
record (category, description, mime_type, file_path, ...) ready
|
|
17
|
+
to drop into `listing.json`. This is the expansion the SDK
|
|
18
|
+
applies to `$preset` JSON sentinels at upload time.
|
|
19
|
+
- `file_preset(source)` — returns the raw UTF-8 content of the
|
|
20
|
+
preset's bundled file. Useful when the example isn't a listing
|
|
21
|
+
document (embed as snippet, feed to a test harness, etc.).
|
|
22
|
+
|
|
23
|
+
Both accept either a bare name (`"s3_connectivity"`,
|
|
24
|
+
`"s3_connectivity_v1"`) or a `{"$preset": "...", "$with": {...}}`
|
|
25
|
+
sentinel, so the same function works from JSON walkers and from
|
|
26
|
+
programmatic Python code.
|
|
27
|
+
|
|
28
|
+
Sellers reference a preset from their `listing.json` like this:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"documents": {
|
|
33
|
+
"Connectivity test": { "$preset": "s3_connectivity" },
|
|
34
|
+
"Usage (Python)": { "$preset": "s3_code_example_v1",
|
|
35
|
+
"$with": { "description": "Lists objects in our bucket" } }
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The SDK walks the parsed listing and calls `doc_preset(...)` on each
|
|
41
|
+
sentinel, substituting the bundled file's absolute path into
|
|
42
|
+
`file_path`, then feeds the result into the existing upload pipeline.
|
|
43
|
+
No custom URL scheme, no extra render pass.
|
|
44
|
+
|
|
45
|
+
## CLI
|
|
46
|
+
|
|
47
|
+
Installing the package provides a `usvc_data` command for shell-level
|
|
48
|
+
access to the same data:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
usvc_data list # every preset + aliases
|
|
52
|
+
usvc_data list --json # machine-readable form
|
|
53
|
+
|
|
54
|
+
usvc_data info s3_connectivity # README prose for a preset
|
|
55
|
+
|
|
56
|
+
usvc_data doc-preset s3_connectivity # expanded JSON record
|
|
57
|
+
usvc_data doc-preset s3_connectivity --with '{"description":"ours"}'
|
|
58
|
+
usvc_data doc-preset s3_connectivity --compact # single-line JSON
|
|
59
|
+
|
|
60
|
+
usvc_data file-preset s3_connectivity # raw file content to stdout
|
|
61
|
+
usvc_data file-preset s3_connectivity > /tmp/s3.py # pipe to file (raw template)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Note that `file-preset` returns the raw file content — `.j2` templates
|
|
65
|
+
come through with Jinja2 markers intact. The sellers SDK renders them
|
|
66
|
+
with per-listing context at upload time; if you pipe a `.j2` preset
|
|
67
|
+
directly to an executable file you'll get a template, not a runnable
|
|
68
|
+
script.
|
|
69
|
+
|
|
70
|
+
`--with` accepts a JSON object whose keys are the overridable fields
|
|
71
|
+
(`description`, `is_active`, `is_public`, `meta`). Forbidden keys and
|
|
72
|
+
unknown preset names exit with status 1 and a message on stderr.
|
|
73
|
+
|
|
74
|
+
## Layout
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
src/unitysvc_data/
|
|
78
|
+
├── __init__.py # example_path / read_example / list_examples
|
|
79
|
+
├── presets.py # doc_preset / file_preset / PRESETS / ALIASES
|
|
80
|
+
├── cli.py # usvc_data entry point
|
|
81
|
+
├── _manifest.json # generated — committed — source of truth at runtime
|
|
82
|
+
└── examples/
|
|
83
|
+
├── api/ # generic HTTP services
|
|
84
|
+
│ └── connectivity/
|
|
85
|
+
│ ├── README.md # front-matter + prose
|
|
86
|
+
│ └── connectivity-v1.sh.j2
|
|
87
|
+
├── llm/ # LLM gateway
|
|
88
|
+
│ └── request-template/
|
|
89
|
+
│ ├── README.md
|
|
90
|
+
│ └── request-template-v1.json
|
|
91
|
+
├── s3/ # S3-compatible storage gateway
|
|
92
|
+
│ ├── code-example/ ...
|
|
93
|
+
│ ├── connectivity/ ...
|
|
94
|
+
│ └── description/ ...
|
|
95
|
+
└── smtp/ # SMTP relay
|
|
96
|
+
└── connectivity/ ...
|
|
97
|
+
|
|
98
|
+
tools/
|
|
99
|
+
└── build.py # regenerate _manifest.json + MANIFEST.md
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Each gateway holds one or more **preset families** (e.g. `s3/connectivity/`).
|
|
103
|
+
A family directory contains:
|
|
104
|
+
|
|
105
|
+
- `README.md` with TOML front-matter delimited by `+++` lines. The
|
|
106
|
+
front-matter has every piece of metadata for the family
|
|
107
|
+
(`preset_name`, `category`, `mime_type`, `file`, `description`,
|
|
108
|
+
`is_active`, `is_public`, `meta`). Prose under the front-matter
|
|
109
|
+
documents the example and any per-version differences.
|
|
110
|
+
- One file per version, named `<stem>-v<N>.<suffix>` where stem and
|
|
111
|
+
suffix come from the `file` field — so `file = "connectivity.sh.j2"`
|
|
112
|
+
matches `connectivity-v1.sh.j2`, `connectivity-v2.sh.j2`, ....
|
|
113
|
+
|
|
114
|
+
Versions are **discovered automatically** by scanning the family
|
|
115
|
+
directory; authors never list them explicitly. Adding a new version
|
|
116
|
+
is purely "drop a new `-v<N>.<ext>` file and rebuild."
|
|
117
|
+
|
|
118
|
+
[`MANIFEST.md`](MANIFEST.md) at the repo root is the human-readable
|
|
119
|
+
roster of every preset, also generated by `tools/build.py`.
|
|
120
|
+
|
|
121
|
+
## Preset naming
|
|
122
|
+
|
|
123
|
+
| Form | Resolves to | Use when |
|
|
124
|
+
|-----------------------------------|--------------------------------------------|----------------------|
|
|
125
|
+
| `s3_connectivity_v1` | version 1 of the `s3/connectivity` family | pinning to an exact version |
|
|
126
|
+
| `s3_connectivity` (alias) | latest version of that family | tracking the latest |
|
|
127
|
+
|
|
128
|
+
Seller data that pins to a versioned name stays byte-identical across
|
|
129
|
+
`pip upgrade`s. Data that uses the alias tracks the newest version
|
|
130
|
+
automatically.
|
|
131
|
+
|
|
132
|
+
## Versioning discipline
|
|
133
|
+
|
|
134
|
+
- Example files are **append-only**. `connectivity-v1.py.j2` is
|
|
135
|
+
frozen forever; fixes ship as `connectivity-v2.py.j2` dropped into
|
|
136
|
+
the same directory.
|
|
137
|
+
- The version-less alias always points at the highest-`v` file in the
|
|
138
|
+
family. Landing a new version shifts the alias automatically the
|
|
139
|
+
next time `python tools/build.py` runs.
|
|
140
|
+
- `preset_name` is globally unique across the whole tree — declaring
|
|
141
|
+
the same `preset_name` in two READMEs is a build error.
|
|
142
|
+
- Package version bumps are additive (new version or new family →
|
|
143
|
+
minor bump; never mutate existing `_vN` → no breaking release).
|
|
144
|
+
Bump major only to remove a `_vN` (should be vanishingly rare).
|
|
145
|
+
|
|
146
|
+
## Contributing
|
|
147
|
+
|
|
148
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the full walkthrough: how
|
|
149
|
+
to add a new family, how to publish a new version, front-matter
|
|
150
|
+
reference, filename conventions, and the pre-submission checklist.
|
|
151
|
+
|
|
152
|
+
In one line: drop your file at
|
|
153
|
+
`src/unitysvc_data/examples/<gateway>/<family>/<stem>-v<N>.<ext>[.j2]`,
|
|
154
|
+
write the family's `README.md`, run `python tools/build.py`, open the PR.
|
|
155
|
+
|
|
156
|
+
## Development
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
uv pip install -e '.[test]'
|
|
160
|
+
pytest -q # runs tests + manifest-freshness check
|
|
161
|
+
python tools/build.py # regenerate manifest + roster
|
|
162
|
+
python tools/build.py --check # CI mode: non-zero exit if stale
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
CI ([`.github/workflows/ci.yml`](.github/workflows/ci.yml)) runs
|
|
166
|
+
`tools/build.py --check`, `ruff`, `pytest` on Python 3.11 and 3.12,
|
|
167
|
+
then builds a wheel and verifies it includes every example file and
|
|
168
|
+
the manifest.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "unitysvc-data"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Standard examples and presets for UnitySVC data packages"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
authors = [{ name = "Bo Peng", email = "bo.peng@unitysvc.com" }]
|
|
11
|
+
maintainers = [{ name = "Bo Peng", email = "bo.peng@unitysvc.com" }]
|
|
12
|
+
license = "MIT"
|
|
13
|
+
requires-python = ">=3.11"
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
"Typing :: Typed",
|
|
19
|
+
]
|
|
20
|
+
dependencies = []
|
|
21
|
+
|
|
22
|
+
[project.optional-dependencies]
|
|
23
|
+
test = ["pytest>=7", "ruff"]
|
|
24
|
+
|
|
25
|
+
[project.scripts]
|
|
26
|
+
usvc_data = "unitysvc_data.cli:main"
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Homepage = "https://github.com/unitysvc/unitysvc-data"
|
|
30
|
+
Issues = "https://github.com/unitysvc/unitysvc-sellers/issues"
|
|
31
|
+
|
|
32
|
+
[tool.setuptools.packages.find]
|
|
33
|
+
where = ["src"]
|
|
34
|
+
|
|
35
|
+
[tool.setuptools.package-data]
|
|
36
|
+
unitysvc_data = ["examples/**/*", "_manifest.json", "py.typed"]
|
|
37
|
+
|
|
38
|
+
[tool.ruff]
|
|
39
|
+
line-length = 120
|
|
40
|
+
target-version = "py311"
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"""Standard examples and presets for UnitySVC data packages.
|
|
2
|
+
|
|
3
|
+
Pure-data package: ships example files under ``examples/`` organised by
|
|
4
|
+
gateway and preset family, preset factories that return populated
|
|
5
|
+
document records, and a JSON sentinel walker the sellers SDK calls at
|
|
6
|
+
upload time. The same machinery is intended to serve other parts of the
|
|
7
|
+
platform that need versioned, named references to bundled content.
|
|
8
|
+
|
|
9
|
+
Preferred (preset-name) API:
|
|
10
|
+
|
|
11
|
+
- :func:`doc_preset` — return a full document record for a preset,
|
|
12
|
+
from a bare name or a ``{"$preset": ..., "$with": {...}}`` sentinel.
|
|
13
|
+
- :func:`file_preset` — return the raw UTF-8 content of a preset's
|
|
14
|
+
bundled example file.
|
|
15
|
+
- :func:`list_presets` — enumerate every registered preset name
|
|
16
|
+
(versioned + aliases).
|
|
17
|
+
- :data:`PRESETS` — mapping of preset name → factory function.
|
|
18
|
+
- :data:`ALIASES` — mapping of version-less family name → latest
|
|
19
|
+
versioned preset name.
|
|
20
|
+
- :data:`MANIFEST` — parsed ``_manifest.json`` content.
|
|
21
|
+
- :data:`OVERRIDABLE` — fields that may be overridden in ``$with``.
|
|
22
|
+
- :func:`register_jinja_globals` — expose every preset factory as a
|
|
23
|
+
Jinja2 global (for generated repos that render ``listing.json.j2``).
|
|
24
|
+
|
|
25
|
+
Low-level (path-based) API — prefer the preset API above unless you
|
|
26
|
+
specifically need to address files by their on-disk layout:
|
|
27
|
+
|
|
28
|
+
- :func:`example_path`, :func:`read_example`, :func:`list_examples` —
|
|
29
|
+
resolve and read bundled example files by their path under
|
|
30
|
+
``examples/``. These break if we ever reorganise the tree; preset
|
|
31
|
+
names don't.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
from __future__ import annotations
|
|
35
|
+
|
|
36
|
+
from importlib.resources import files as _files
|
|
37
|
+
from pathlib import Path
|
|
38
|
+
|
|
39
|
+
from ._version import __version__
|
|
40
|
+
|
|
41
|
+
_ROOT = _files(__name__).joinpath("examples")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def example_path(name: str) -> Path:
|
|
45
|
+
"""Return an absolute filesystem path for the bundled example *name*.
|
|
46
|
+
|
|
47
|
+
**Low-level.** Prefer :func:`file_preset` and :func:`doc_preset`
|
|
48
|
+
for anything that can key off a preset name — those are stable
|
|
49
|
+
across any future reorganisation of ``examples/``.
|
|
50
|
+
|
|
51
|
+
*name* is a path relative to ``examples/`` (e.g.
|
|
52
|
+
``"s3/connectivity/connectivity-v1.py.j2"``). Raises
|
|
53
|
+
:class:`FileNotFoundError` if the file is not part of the
|
|
54
|
+
installed package.
|
|
55
|
+
"""
|
|
56
|
+
target = _ROOT.joinpath(name)
|
|
57
|
+
if not target.is_file():
|
|
58
|
+
raise FileNotFoundError(f"Unknown example: {name!r}")
|
|
59
|
+
return Path(str(target))
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def read_example(name: str) -> str:
|
|
63
|
+
"""Read the raw UTF-8 content of a bundled example by path.
|
|
64
|
+
|
|
65
|
+
**Low-level.** See :func:`example_path` for the name contract and
|
|
66
|
+
why :func:`file_preset` is usually the right choice.
|
|
67
|
+
"""
|
|
68
|
+
return example_path(name).read_text(encoding="utf-8")
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def list_examples() -> list[str]:
|
|
72
|
+
"""Return every bundled example filename, relative to ``examples/``.
|
|
73
|
+
|
|
74
|
+
**Low-level.** For enumerating presets by name, use
|
|
75
|
+
:func:`list_presets`. This function exposes on-disk paths
|
|
76
|
+
(including the gateway/family structure), which is rarely what a
|
|
77
|
+
consumer wants.
|
|
78
|
+
|
|
79
|
+
README files and hidden files are excluded.
|
|
80
|
+
"""
|
|
81
|
+
root = Path(str(_ROOT))
|
|
82
|
+
return sorted(
|
|
83
|
+
path.relative_to(root).as_posix()
|
|
84
|
+
for path in root.rglob("*")
|
|
85
|
+
if path.is_file()
|
|
86
|
+
and path.name != "README.md"
|
|
87
|
+
and not path.name.startswith(".")
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
# Imported last so presets.py can compute its own _EXAMPLES_ROOT without
|
|
92
|
+
# reaching back into this module while __init__ is still loading.
|
|
93
|
+
from .presets import ( # noqa: E402 (placement is deliberate)
|
|
94
|
+
ALIASES,
|
|
95
|
+
MANIFEST,
|
|
96
|
+
OVERRIDABLE,
|
|
97
|
+
PRESETS,
|
|
98
|
+
doc_preset,
|
|
99
|
+
file_preset,
|
|
100
|
+
list_presets,
|
|
101
|
+
register_jinja_globals,
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
__all__ = [
|
|
105
|
+
"__version__",
|
|
106
|
+
# Preferred preset API.
|
|
107
|
+
"doc_preset",
|
|
108
|
+
"file_preset",
|
|
109
|
+
"list_presets",
|
|
110
|
+
"PRESETS",
|
|
111
|
+
"ALIASES",
|
|
112
|
+
"MANIFEST",
|
|
113
|
+
"OVERRIDABLE",
|
|
114
|
+
"register_jinja_globals",
|
|
115
|
+
# Low-level path-based API.
|
|
116
|
+
"example_path",
|
|
117
|
+
"read_example",
|
|
118
|
+
"list_examples",
|
|
119
|
+
]
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
{
|
|
2
|
+
"aliases": {
|
|
3
|
+
"api_connectivity": "api_connectivity_v1",
|
|
4
|
+
"llm_request_template": "llm_request_template_v1",
|
|
5
|
+
"s3_code_example": "s3_code_example_v1",
|
|
6
|
+
"s3_connectivity": "s3_connectivity_v1",
|
|
7
|
+
"s3_description": "s3_description_v1",
|
|
8
|
+
"smtp_connectivity": "smtp_connectivity_v1"
|
|
9
|
+
},
|
|
10
|
+
"presets": {
|
|
11
|
+
"api_connectivity_v1": {
|
|
12
|
+
"category": "connectivity_test",
|
|
13
|
+
"description": "Verify HTTP endpoint is reachable and returns a healthy status",
|
|
14
|
+
"example_file": "api/connectivity/connectivity-v1.sh.j2",
|
|
15
|
+
"is_active": true,
|
|
16
|
+
"is_public": false,
|
|
17
|
+
"meta": {
|
|
18
|
+
"output_contains": "connectivity ok"
|
|
19
|
+
},
|
|
20
|
+
"mime_type": "bash",
|
|
21
|
+
"preset_name": "api_connectivity",
|
|
22
|
+
"source_readme": "api/connectivity/README.md",
|
|
23
|
+
"version": 1
|
|
24
|
+
},
|
|
25
|
+
"llm_request_template_v1": {
|
|
26
|
+
"category": "request_template",
|
|
27
|
+
"description": "Minimal OpenAI-compatible chat completion request body",
|
|
28
|
+
"example_file": "llm/request-template/request-template-v1.json",
|
|
29
|
+
"is_active": true,
|
|
30
|
+
"is_public": false,
|
|
31
|
+
"meta": {},
|
|
32
|
+
"mime_type": "json",
|
|
33
|
+
"preset_name": "llm_request_template",
|
|
34
|
+
"source_readme": "llm/request-template/README.md",
|
|
35
|
+
"version": 1
|
|
36
|
+
},
|
|
37
|
+
"s3_code_example_v1": {
|
|
38
|
+
"category": "usage_example",
|
|
39
|
+
"description": "Python example: list objects in an S3 bucket via boto3",
|
|
40
|
+
"example_file": "s3/code-example/code-example-v1.py.j2",
|
|
41
|
+
"is_active": true,
|
|
42
|
+
"is_public": true,
|
|
43
|
+
"meta": {},
|
|
44
|
+
"mime_type": "python",
|
|
45
|
+
"preset_name": "s3_code_example",
|
|
46
|
+
"source_readme": "s3/code-example/README.md",
|
|
47
|
+
"version": 1
|
|
48
|
+
},
|
|
49
|
+
"s3_connectivity_v1": {
|
|
50
|
+
"category": "connectivity_test",
|
|
51
|
+
"description": "Verify S3 endpoint accepts the configured credentials",
|
|
52
|
+
"example_file": "s3/connectivity/connectivity-v1.py.j2",
|
|
53
|
+
"is_active": true,
|
|
54
|
+
"is_public": false,
|
|
55
|
+
"meta": {
|
|
56
|
+
"output_contains": "connectivity ok"
|
|
57
|
+
},
|
|
58
|
+
"mime_type": "python",
|
|
59
|
+
"preset_name": "s3_connectivity",
|
|
60
|
+
"source_readme": "s3/connectivity/README.md",
|
|
61
|
+
"version": 1
|
|
62
|
+
},
|
|
63
|
+
"s3_description_v1": {
|
|
64
|
+
"category": "description",
|
|
65
|
+
"description": "Customer-facing overview of the S3 gateway service",
|
|
66
|
+
"example_file": "s3/description/description-v1.md",
|
|
67
|
+
"is_active": true,
|
|
68
|
+
"is_public": true,
|
|
69
|
+
"meta": {},
|
|
70
|
+
"mime_type": "markdown",
|
|
71
|
+
"preset_name": "s3_description",
|
|
72
|
+
"source_readme": "s3/description/README.md",
|
|
73
|
+
"version": 1
|
|
74
|
+
},
|
|
75
|
+
"smtp_connectivity_v1": {
|
|
76
|
+
"category": "connectivity_test",
|
|
77
|
+
"description": "Verify SMTP server returns a 220 greeting on connect",
|
|
78
|
+
"example_file": "smtp/connectivity/connectivity-v1.sh.j2",
|
|
79
|
+
"is_active": true,
|
|
80
|
+
"is_public": false,
|
|
81
|
+
"meta": {
|
|
82
|
+
"output_contains": "connectivity ok"
|
|
83
|
+
},
|
|
84
|
+
"mime_type": "bash",
|
|
85
|
+
"preset_name": "smtp_connectivity",
|
|
86
|
+
"source_readme": "smtp/connectivity/README.md",
|
|
87
|
+
"version": 1
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"version": "1"
|
|
91
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|