validibot-shared 0.1.0__tar.gz → 0.2.1__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.
- validibot_shared-0.2.1/PKG-INFO +420 -0
- validibot_shared-0.2.1/README.md +388 -0
- {validibot_shared-0.1.0 → validibot_shared-0.2.1}/pyproject.toml +1 -1
- {validibot_shared-0.1.0 → validibot_shared-0.2.1}/validibot_shared/validations/envelopes.py +51 -12
- validibot_shared-0.1.0/PKG-INFO +0 -168
- validibot_shared-0.1.0/README.md +0 -136
- {validibot_shared-0.1.0 → validibot_shared-0.2.1}/.gitignore +0 -0
- {validibot_shared-0.1.0 → validibot_shared-0.2.1}/LICENSE +0 -0
- {validibot_shared-0.1.0 → validibot_shared-0.2.1}/NOTICE +0 -0
- {validibot_shared-0.1.0 → validibot_shared-0.2.1}/tests/__init__.py +0 -0
- {validibot_shared-0.1.0 → validibot_shared-0.2.1}/tests/test_energyplus_envelopes.py +0 -0
- {validibot_shared-0.1.0 → validibot_shared-0.2.1}/tests/test_energyplus_models.py +0 -0
- {validibot_shared-0.1.0 → validibot_shared-0.2.1}/tests/test_fmi_envelopes.py +0 -0
- {validibot_shared-0.1.0 → validibot_shared-0.2.1}/tests/test_fmi_models.py +0 -0
- {validibot_shared-0.1.0 → validibot_shared-0.2.1}/tests/test_package_init.py +0 -0
- {validibot_shared-0.1.0 → validibot_shared-0.2.1}/tests/test_validations_envelopes.py +0 -0
- {validibot_shared-0.1.0 → validibot_shared-0.2.1}/validibot_shared/__init__.py +0 -0
- {validibot_shared-0.1.0 → validibot_shared-0.2.1}/validibot_shared/energyplus/__init__.py +0 -0
- {validibot_shared-0.1.0 → validibot_shared-0.2.1}/validibot_shared/energyplus/envelopes.py +0 -0
- {validibot_shared-0.1.0 → validibot_shared-0.2.1}/validibot_shared/energyplus/models.py +0 -0
- {validibot_shared-0.1.0 → validibot_shared-0.2.1}/validibot_shared/fmi/__init__.py +0 -0
- {validibot_shared-0.1.0 → validibot_shared-0.2.1}/validibot_shared/fmi/envelopes.py +0 -0
- {validibot_shared-0.1.0 → validibot_shared-0.2.1}/validibot_shared/fmi/models.py +0 -0
- {validibot_shared-0.1.0 → validibot_shared-0.2.1}/validibot_shared/py.typed +0 -0
- {validibot_shared-0.1.0 → validibot_shared-0.2.1}/validibot_shared/validations/__init__.py +0 -0
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: validibot-shared
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Shared library for data interchange between Validibot and validator containers
|
|
5
|
+
Project-URL: Homepage, https://validibot.com
|
|
6
|
+
Project-URL: Documentation, https://docs.validibot.com
|
|
7
|
+
Project-URL: Repository, https://github.com/danielmcquillen/validibot-shared
|
|
8
|
+
Project-URL: Issues, https://github.com/danielmcquillen/validibot-shared/issues
|
|
9
|
+
Author-email: Daniel McQuillen <daniel@validibot.com>
|
|
10
|
+
Maintainer-email: Daniel McQuillen <daniel@validibot.com>
|
|
11
|
+
License: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
License-File: NOTICE
|
|
14
|
+
Keywords: data-interchange,energyplus,fmu,simulation,validation,validibot
|
|
15
|
+
Classifier: Development Status :: 4 - Beta
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Topic :: Scientific/Engineering
|
|
25
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
26
|
+
Requires-Python: >=3.10
|
|
27
|
+
Requires-Dist: pydantic>=2.8.0
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=8.3.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: ruff>=0.8.0; extra == 'dev'
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
<div align="center">
|
|
34
|
+
|
|
35
|
+
# Validibot Shared
|
|
36
|
+
|
|
37
|
+
**Shared Pydantic models for Validibot Advanced Validator containers**
|
|
38
|
+
|
|
39
|
+
[](https://pypi.org/project/validibot-shared/)
|
|
40
|
+
[](https://pypi.org/project/validibot-shared/)
|
|
41
|
+
[](LICENSE)
|
|
42
|
+
|
|
43
|
+
[Installation](#installation) •
|
|
44
|
+
[Core Concepts](#core-concepts) •
|
|
45
|
+
[Usage](#usage-examples) •
|
|
46
|
+
[API Reference](#api-reference)
|
|
47
|
+
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
> [!NOTE]
|
|
53
|
+
> This library is part of the [Validibot](https://github.com/danielmcquillen/validibot) open-source data validation platform. It defines the data interchange contract between the core platform and advanced validator containers.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Part of the Validibot Project
|
|
58
|
+
|
|
59
|
+
| Repository | Description |
|
|
60
|
+
|------------|-------------|
|
|
61
|
+
| **[validibot](https://github.com/danielmcquillen/validibot)** | Core platform — web UI, REST API, workflow engine |
|
|
62
|
+
| **[validibot-cli](https://github.com/danielmcquillen/validibot-cli)** | Command-line interface |
|
|
63
|
+
| **[validibot-validators](https://github.com/danielmcquillen/validibot-validators)** | Advanced validator containers (EnergyPlus, FMI) |
|
|
64
|
+
| **[validibot-shared](https://github.com/danielmcquillen/validibot-shared)** (this repo) | Shared Pydantic models for data interchange |
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## What is Validibot Shared?
|
|
69
|
+
|
|
70
|
+
Validibot Shared provides the Pydantic models that define how the Validibot core platform communicates with advanced validator containers. When Validibot needs to run a complex validation (like an EnergyPlus simulation or FMU probe), it:
|
|
71
|
+
|
|
72
|
+
1. **Creates an input envelope** containing the files to validate and configuration
|
|
73
|
+
2. **Launches a validator container** with the envelope as input
|
|
74
|
+
3. **Receives an output envelope** with validation results, metrics, and artifacts
|
|
75
|
+
|
|
76
|
+
This library ensures both sides speak the same language with full type safety and runtime validation.
|
|
77
|
+
|
|
78
|
+
## Features
|
|
79
|
+
|
|
80
|
+
- **Type-safe envelopes** — Pydantic models with full IDE autocomplete and type checking
|
|
81
|
+
- **Runtime validation** — Automatic validation of all data at serialization boundaries
|
|
82
|
+
- **Domain-specific extensions** — Typed subclasses for EnergyPlus, FMI, and custom validators
|
|
83
|
+
- **Lightweight** — Only depends on Pydantic, no heavy dependencies
|
|
84
|
+
|
|
85
|
+
## Installation
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Using pip
|
|
89
|
+
pip install validibot-shared
|
|
90
|
+
|
|
91
|
+
# Using uv (recommended)
|
|
92
|
+
uv add validibot-shared
|
|
93
|
+
|
|
94
|
+
# Using poetry
|
|
95
|
+
poetry add validibot-shared
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Requirements
|
|
99
|
+
|
|
100
|
+
- Python 3.10 or later
|
|
101
|
+
- Pydantic 2.8.0 or later
|
|
102
|
+
|
|
103
|
+
## Core Concepts
|
|
104
|
+
|
|
105
|
+
### The Envelope Pattern
|
|
106
|
+
|
|
107
|
+
Validibot uses an "envelope" pattern for validator communication. Every validation job is wrapped in a standardized envelope that carries:
|
|
108
|
+
|
|
109
|
+
- **Job metadata** — Run ID, validator info, execution context
|
|
110
|
+
- **Input files** — References to files being validated (URIs, not raw data)
|
|
111
|
+
- **Configuration** — Validator-specific settings
|
|
112
|
+
- **Results** — Status, messages, metrics, and artifacts (output only)
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
116
|
+
│ Validibot Core Platform │
|
|
117
|
+
│ │
|
|
118
|
+
│ 1. Creates ValidationInputEnvelope with: │
|
|
119
|
+
│ • run_id, validator info │
|
|
120
|
+
│ • input_files[] (GCS/S3 URIs) │
|
|
121
|
+
│ • inputs (validator-specific config) │
|
|
122
|
+
│ • callback_url for async notification │
|
|
123
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
124
|
+
│
|
|
125
|
+
▼ JSON
|
|
126
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
127
|
+
│ Validator Container │
|
|
128
|
+
│ (EnergyPlus, FMI, etc.) │
|
|
129
|
+
│ │
|
|
130
|
+
│ 1. Parses input envelope │
|
|
131
|
+
│ 2. Downloads input files from URIs │
|
|
132
|
+
│ 3. Runs validation/simulation │
|
|
133
|
+
│ 4. Creates ValidationOutputEnvelope with results │
|
|
134
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
135
|
+
│
|
|
136
|
+
▼ JSON (callback or response)
|
|
137
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
138
|
+
│ Validibot Core Platform │
|
|
139
|
+
│ │
|
|
140
|
+
│ 1. Receives output envelope │
|
|
141
|
+
│ 2. Parses and validates with Pydantic │
|
|
142
|
+
│ 3. Stores findings, metrics, artifacts │
|
|
143
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Base Envelope Classes
|
|
147
|
+
|
|
148
|
+
The library provides these base classes in `validibot_shared.validations.envelopes`:
|
|
149
|
+
|
|
150
|
+
| Class | Purpose |
|
|
151
|
+
|-------|---------|
|
|
152
|
+
| `ValidationInputEnvelope` | Standard input format for validation jobs |
|
|
153
|
+
| `ValidationOutputEnvelope` | Standard output format with results |
|
|
154
|
+
| `ValidationCallback` | Callback payload for async job completion |
|
|
155
|
+
|
|
156
|
+
Supporting models include:
|
|
157
|
+
|
|
158
|
+
| Class | Purpose |
|
|
159
|
+
|-------|---------|
|
|
160
|
+
| `InputFileItem` | File reference with URI, MIME type, and role |
|
|
161
|
+
| `ValidatorInfo` | Validator identification (ID, type, version) |
|
|
162
|
+
| `ExecutionContext` | Callback URL, execution bundle URI, timeout |
|
|
163
|
+
| `ValidationMessage` | Individual finding (error, warning, info) |
|
|
164
|
+
| `ValidationMetric` | Named numeric metric with optional unit |
|
|
165
|
+
| `ValidationArtifact` | Output file reference (reports, logs, etc.) |
|
|
166
|
+
|
|
167
|
+
### Typed Subclassing Pattern
|
|
168
|
+
|
|
169
|
+
Domain-specific validators extend the base envelopes with typed fields. This gives you:
|
|
170
|
+
|
|
171
|
+
- **Type safety** — mypy/pyright catch errors at compile time
|
|
172
|
+
- **Runtime validation** — Pydantic validates all data
|
|
173
|
+
- **IDE support** — Full autocomplete for domain-specific fields
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
from validibot_shared.energyplus import EnergyPlusInputEnvelope, EnergyPlusInputs
|
|
177
|
+
|
|
178
|
+
# The envelope has typed inputs instead of dict[str, Any]
|
|
179
|
+
envelope = EnergyPlusInputEnvelope(
|
|
180
|
+
run_id="abc-123",
|
|
181
|
+
inputs=EnergyPlusInputs(timestep_per_hour=4),
|
|
182
|
+
# ... other fields
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
# IDE autocomplete and type checking work
|
|
186
|
+
timestep = envelope.inputs.timestep_per_hour # ✓ Known to be int
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Package Structure
|
|
190
|
+
|
|
191
|
+
```
|
|
192
|
+
validibot_shared/
|
|
193
|
+
├── validations/ # Base validation envelope schemas
|
|
194
|
+
│ └── envelopes.py # Input/output envelopes for all validators
|
|
195
|
+
├── energyplus/ # EnergyPlus-specific models and envelopes
|
|
196
|
+
│ ├── models.py # Simulation output models (metrics, results)
|
|
197
|
+
│ └── envelopes.py # Typed envelope subclasses
|
|
198
|
+
└── fmi/ # FMI/FMU-specific models
|
|
199
|
+
├── models.py # Probe result models
|
|
200
|
+
└── envelopes.py # FMI envelope subclasses
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Usage Examples
|
|
204
|
+
|
|
205
|
+
### Creating an Input Envelope
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
from validibot_shared.energyplus import EnergyPlusInputEnvelope, EnergyPlusInputs
|
|
209
|
+
from validibot_shared.validations.envelopes import (
|
|
210
|
+
InputFileItem,
|
|
211
|
+
ValidatorInfo,
|
|
212
|
+
ExecutionContext,
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
envelope = EnergyPlusInputEnvelope(
|
|
216
|
+
run_id="run-123",
|
|
217
|
+
validator=ValidatorInfo(id="v1", type="energyplus", version="24.2.0"),
|
|
218
|
+
input_files=[
|
|
219
|
+
InputFileItem(
|
|
220
|
+
name="model.idf",
|
|
221
|
+
mime_type="application/vnd.energyplus.idf",
|
|
222
|
+
role="primary-model",
|
|
223
|
+
uri="gs://bucket/model.idf",
|
|
224
|
+
),
|
|
225
|
+
],
|
|
226
|
+
inputs=EnergyPlusInputs(timestep_per_hour=4),
|
|
227
|
+
context=ExecutionContext(
|
|
228
|
+
callback_url="https://api.example.com/callback",
|
|
229
|
+
execution_bundle_uri="gs://bucket/run-123/",
|
|
230
|
+
),
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
# Serialize to JSON for the validator container
|
|
234
|
+
json_payload = envelope.model_dump_json()
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Deserializing Results
|
|
238
|
+
|
|
239
|
+
```python
|
|
240
|
+
from validibot_shared.energyplus import EnergyPlusOutputEnvelope
|
|
241
|
+
|
|
242
|
+
# Parse JSON response from validator
|
|
243
|
+
envelope = EnergyPlusOutputEnvelope.model_validate_json(response_json)
|
|
244
|
+
|
|
245
|
+
# Check status
|
|
246
|
+
if envelope.status == "success":
|
|
247
|
+
# Access typed outputs with full autocomplete
|
|
248
|
+
if envelope.outputs and envelope.outputs.metrics:
|
|
249
|
+
print(f"EUI: {envelope.outputs.metrics.eui_kbtu_per_sqft} kBtu/sqft")
|
|
250
|
+
|
|
251
|
+
# Iterate over validation messages
|
|
252
|
+
for message in envelope.messages:
|
|
253
|
+
print(f"[{message.severity}] {message.text}")
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### FMI Probe Results
|
|
257
|
+
|
|
258
|
+
```python
|
|
259
|
+
from validibot_shared.fmi.models import FMIProbeResult, FMIVariableMeta
|
|
260
|
+
|
|
261
|
+
# Create a successful probe result
|
|
262
|
+
result = FMIProbeResult.success(
|
|
263
|
+
variables=[
|
|
264
|
+
FMIVariableMeta(name="temperature", causality="output", value_type="Real"),
|
|
265
|
+
FMIVariableMeta(name="pressure", causality="output", value_type="Real"),
|
|
266
|
+
],
|
|
267
|
+
execution_seconds=0.5,
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
# Create a failure result
|
|
271
|
+
result = FMIProbeResult.failure(
|
|
272
|
+
errors=["Invalid FMU: missing modelDescription.xml"]
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
# Serialize for response
|
|
276
|
+
json_response = result.model_dump_json()
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Creating a Custom Validator
|
|
280
|
+
|
|
281
|
+
If you're building a custom validator, create typed envelope subclasses:
|
|
282
|
+
|
|
283
|
+
```python
|
|
284
|
+
from pydantic import BaseModel
|
|
285
|
+
from validibot_shared.validations.envelopes import (
|
|
286
|
+
ValidationInputEnvelope,
|
|
287
|
+
ValidationOutputEnvelope,
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
# Define your validator's input configuration
|
|
291
|
+
class MyValidatorInputs(BaseModel):
|
|
292
|
+
strict_mode: bool = False
|
|
293
|
+
max_errors: int = 100
|
|
294
|
+
|
|
295
|
+
# Define your validator's output data
|
|
296
|
+
class MyValidatorOutputs(BaseModel):
|
|
297
|
+
items_checked: int
|
|
298
|
+
items_passed: int
|
|
299
|
+
|
|
300
|
+
# Create typed envelope subclasses
|
|
301
|
+
class MyValidatorInputEnvelope(ValidationInputEnvelope):
|
|
302
|
+
inputs: MyValidatorInputs
|
|
303
|
+
|
|
304
|
+
class MyValidatorOutputEnvelope(ValidationOutputEnvelope):
|
|
305
|
+
outputs: MyValidatorOutputs | None = None
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
## API Reference
|
|
309
|
+
|
|
310
|
+
### ValidationInputEnvelope
|
|
311
|
+
|
|
312
|
+
```python
|
|
313
|
+
class ValidationInputEnvelope(BaseModel):
|
|
314
|
+
run_id: str # Unique identifier for this validation run
|
|
315
|
+
validator: ValidatorInfo # Validator identification
|
|
316
|
+
input_files: list[InputFileItem] # Files to validate
|
|
317
|
+
inputs: dict[str, Any] # Validator-specific configuration
|
|
318
|
+
context: ExecutionContext # Callback URL, bundle URI, etc.
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### ValidationOutputEnvelope
|
|
322
|
+
|
|
323
|
+
```python
|
|
324
|
+
class ValidationOutputEnvelope(BaseModel):
|
|
325
|
+
run_id: str # Matches input run_id
|
|
326
|
+
status: str # "success", "failure", "error"
|
|
327
|
+
messages: list[ValidationMessage] # Validation findings
|
|
328
|
+
metrics: list[ValidationMetric] # Numeric metrics
|
|
329
|
+
artifacts: list[ValidationArtifact] # Output files
|
|
330
|
+
outputs: dict[str, Any] | None # Validator-specific results
|
|
331
|
+
execution_seconds: float | None # Execution time
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### ValidationMessage
|
|
335
|
+
|
|
336
|
+
```python
|
|
337
|
+
class ValidationMessage(BaseModel):
|
|
338
|
+
severity: str # "error", "warning", "info"
|
|
339
|
+
code: str | None # Machine-readable code
|
|
340
|
+
text: str # Human-readable message
|
|
341
|
+
location: str | None # File/line reference
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
## Part of the Validibot Project
|
|
345
|
+
|
|
346
|
+
This library is one component of the Validibot open-source data validation platform:
|
|
347
|
+
|
|
348
|
+
| Repository | Description |
|
|
349
|
+
|------------|-------------|
|
|
350
|
+
| **[validibot](https://github.com/danielmcquillen/validibot)** | Core platform — web UI, REST API, workflow engine |
|
|
351
|
+
| **[validibot-cli](https://github.com/danielmcquillen/validibot-cli)** | Command-line interface |
|
|
352
|
+
| **[validibot-validators](https://github.com/danielmcquillen/validibot-validators)** | Advanced validator containers (EnergyPlus, FMI) |
|
|
353
|
+
| **[validibot-shared](https://github.com/danielmcquillen/validibot-shared)** (this repo) | Shared Pydantic models for data interchange |
|
|
354
|
+
|
|
355
|
+
### How It Fits Together
|
|
356
|
+
|
|
357
|
+
```
|
|
358
|
+
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
359
|
+
│ End Users │
|
|
360
|
+
│ (Web UI, CLI, REST API clients) │
|
|
361
|
+
└─────────────────────────────────────────────────────────────────────────────┘
|
|
362
|
+
│
|
|
363
|
+
▼
|
|
364
|
+
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
365
|
+
│ validibot (core platform) │
|
|
366
|
+
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
|
367
|
+
│ │ Web UI │ REST API │ Workflow Engine │ Built-in Validators │ │
|
|
368
|
+
│ └─────────────────────────────────────────────────────────────────────┘ │
|
|
369
|
+
│ │ │
|
|
370
|
+
│ Triggers Docker containers for advanced validations │
|
|
371
|
+
└─────────────────────────────────────────────────────────────────────────────┘
|
|
372
|
+
│
|
|
373
|
+
┌──────────────────────────┼──────────────────────────┐
|
|
374
|
+
▼ ▼ ▼
|
|
375
|
+
┌─────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐
|
|
376
|
+
│ validibot-cli │ │ validibot-validators│ │ validibot-shared │
|
|
377
|
+
│ │ │ │ │ (this repo) │
|
|
378
|
+
│ Terminal access │ │ EnergyPlus, FMI │ │ │
|
|
379
|
+
│ to API │ │ containers │ │ Pydantic models │
|
|
380
|
+
│ │ │ │ │ │ (shared contract) │
|
|
381
|
+
└─────────────────┘ └────────┼────────────┘ └─────────────────────┘
|
|
382
|
+
│ ▲
|
|
383
|
+
└──────────────────────────┘
|
|
384
|
+
validators import shared
|
|
385
|
+
models for type safety
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
## Development
|
|
389
|
+
|
|
390
|
+
```bash
|
|
391
|
+
# Clone the repository
|
|
392
|
+
git clone https://github.com/danielmcquillen/validibot-shared.git
|
|
393
|
+
cd validibot-shared
|
|
394
|
+
|
|
395
|
+
# Install with dev dependencies
|
|
396
|
+
uv sync --extra dev
|
|
397
|
+
|
|
398
|
+
# Run tests
|
|
399
|
+
uv run pytest
|
|
400
|
+
|
|
401
|
+
# Run linter
|
|
402
|
+
uv run ruff check .
|
|
403
|
+
|
|
404
|
+
# Run type checker
|
|
405
|
+
uv run mypy src/
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
## License
|
|
409
|
+
|
|
410
|
+
MIT License — see [LICENSE](LICENSE) for details.
|
|
411
|
+
|
|
412
|
+
---
|
|
413
|
+
|
|
414
|
+
<div align="center">
|
|
415
|
+
|
|
416
|
+
[Validibot Platform](https://github.com/danielmcquillen/validibot) •
|
|
417
|
+
[Documentation](https://docs.validibot.com) •
|
|
418
|
+
[Report Issues](https://github.com/danielmcquillen/validibot-shared/issues)
|
|
419
|
+
|
|
420
|
+
</div>
|
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# Validibot Shared
|
|
4
|
+
|
|
5
|
+
**Shared Pydantic models for Validibot Advanced Validator containers**
|
|
6
|
+
|
|
7
|
+
[](https://pypi.org/project/validibot-shared/)
|
|
8
|
+
[](https://pypi.org/project/validibot-shared/)
|
|
9
|
+
[](LICENSE)
|
|
10
|
+
|
|
11
|
+
[Installation](#installation) •
|
|
12
|
+
[Core Concepts](#core-concepts) •
|
|
13
|
+
[Usage](#usage-examples) •
|
|
14
|
+
[API Reference](#api-reference)
|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
> [!NOTE]
|
|
21
|
+
> This library is part of the [Validibot](https://github.com/danielmcquillen/validibot) open-source data validation platform. It defines the data interchange contract between the core platform and advanced validator containers.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Part of the Validibot Project
|
|
26
|
+
|
|
27
|
+
| Repository | Description |
|
|
28
|
+
|------------|-------------|
|
|
29
|
+
| **[validibot](https://github.com/danielmcquillen/validibot)** | Core platform — web UI, REST API, workflow engine |
|
|
30
|
+
| **[validibot-cli](https://github.com/danielmcquillen/validibot-cli)** | Command-line interface |
|
|
31
|
+
| **[validibot-validators](https://github.com/danielmcquillen/validibot-validators)** | Advanced validator containers (EnergyPlus, FMI) |
|
|
32
|
+
| **[validibot-shared](https://github.com/danielmcquillen/validibot-shared)** (this repo) | Shared Pydantic models for data interchange |
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## What is Validibot Shared?
|
|
37
|
+
|
|
38
|
+
Validibot Shared provides the Pydantic models that define how the Validibot core platform communicates with advanced validator containers. When Validibot needs to run a complex validation (like an EnergyPlus simulation or FMU probe), it:
|
|
39
|
+
|
|
40
|
+
1. **Creates an input envelope** containing the files to validate and configuration
|
|
41
|
+
2. **Launches a validator container** with the envelope as input
|
|
42
|
+
3. **Receives an output envelope** with validation results, metrics, and artifacts
|
|
43
|
+
|
|
44
|
+
This library ensures both sides speak the same language with full type safety and runtime validation.
|
|
45
|
+
|
|
46
|
+
## Features
|
|
47
|
+
|
|
48
|
+
- **Type-safe envelopes** — Pydantic models with full IDE autocomplete and type checking
|
|
49
|
+
- **Runtime validation** — Automatic validation of all data at serialization boundaries
|
|
50
|
+
- **Domain-specific extensions** — Typed subclasses for EnergyPlus, FMI, and custom validators
|
|
51
|
+
- **Lightweight** — Only depends on Pydantic, no heavy dependencies
|
|
52
|
+
|
|
53
|
+
## Installation
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Using pip
|
|
57
|
+
pip install validibot-shared
|
|
58
|
+
|
|
59
|
+
# Using uv (recommended)
|
|
60
|
+
uv add validibot-shared
|
|
61
|
+
|
|
62
|
+
# Using poetry
|
|
63
|
+
poetry add validibot-shared
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Requirements
|
|
67
|
+
|
|
68
|
+
- Python 3.10 or later
|
|
69
|
+
- Pydantic 2.8.0 or later
|
|
70
|
+
|
|
71
|
+
## Core Concepts
|
|
72
|
+
|
|
73
|
+
### The Envelope Pattern
|
|
74
|
+
|
|
75
|
+
Validibot uses an "envelope" pattern for validator communication. Every validation job is wrapped in a standardized envelope that carries:
|
|
76
|
+
|
|
77
|
+
- **Job metadata** — Run ID, validator info, execution context
|
|
78
|
+
- **Input files** — References to files being validated (URIs, not raw data)
|
|
79
|
+
- **Configuration** — Validator-specific settings
|
|
80
|
+
- **Results** — Status, messages, metrics, and artifacts (output only)
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
84
|
+
│ Validibot Core Platform │
|
|
85
|
+
│ │
|
|
86
|
+
│ 1. Creates ValidationInputEnvelope with: │
|
|
87
|
+
│ • run_id, validator info │
|
|
88
|
+
│ • input_files[] (GCS/S3 URIs) │
|
|
89
|
+
│ • inputs (validator-specific config) │
|
|
90
|
+
│ • callback_url for async notification │
|
|
91
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
92
|
+
│
|
|
93
|
+
▼ JSON
|
|
94
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
95
|
+
│ Validator Container │
|
|
96
|
+
│ (EnergyPlus, FMI, etc.) │
|
|
97
|
+
│ │
|
|
98
|
+
│ 1. Parses input envelope │
|
|
99
|
+
│ 2. Downloads input files from URIs │
|
|
100
|
+
│ 3. Runs validation/simulation │
|
|
101
|
+
│ 4. Creates ValidationOutputEnvelope with results │
|
|
102
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
103
|
+
│
|
|
104
|
+
▼ JSON (callback or response)
|
|
105
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
106
|
+
│ Validibot Core Platform │
|
|
107
|
+
│ │
|
|
108
|
+
│ 1. Receives output envelope │
|
|
109
|
+
│ 2. Parses and validates with Pydantic │
|
|
110
|
+
│ 3. Stores findings, metrics, artifacts │
|
|
111
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Base Envelope Classes
|
|
115
|
+
|
|
116
|
+
The library provides these base classes in `validibot_shared.validations.envelopes`:
|
|
117
|
+
|
|
118
|
+
| Class | Purpose |
|
|
119
|
+
|-------|---------|
|
|
120
|
+
| `ValidationInputEnvelope` | Standard input format for validation jobs |
|
|
121
|
+
| `ValidationOutputEnvelope` | Standard output format with results |
|
|
122
|
+
| `ValidationCallback` | Callback payload for async job completion |
|
|
123
|
+
|
|
124
|
+
Supporting models include:
|
|
125
|
+
|
|
126
|
+
| Class | Purpose |
|
|
127
|
+
|-------|---------|
|
|
128
|
+
| `InputFileItem` | File reference with URI, MIME type, and role |
|
|
129
|
+
| `ValidatorInfo` | Validator identification (ID, type, version) |
|
|
130
|
+
| `ExecutionContext` | Callback URL, execution bundle URI, timeout |
|
|
131
|
+
| `ValidationMessage` | Individual finding (error, warning, info) |
|
|
132
|
+
| `ValidationMetric` | Named numeric metric with optional unit |
|
|
133
|
+
| `ValidationArtifact` | Output file reference (reports, logs, etc.) |
|
|
134
|
+
|
|
135
|
+
### Typed Subclassing Pattern
|
|
136
|
+
|
|
137
|
+
Domain-specific validators extend the base envelopes with typed fields. This gives you:
|
|
138
|
+
|
|
139
|
+
- **Type safety** — mypy/pyright catch errors at compile time
|
|
140
|
+
- **Runtime validation** — Pydantic validates all data
|
|
141
|
+
- **IDE support** — Full autocomplete for domain-specific fields
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
from validibot_shared.energyplus import EnergyPlusInputEnvelope, EnergyPlusInputs
|
|
145
|
+
|
|
146
|
+
# The envelope has typed inputs instead of dict[str, Any]
|
|
147
|
+
envelope = EnergyPlusInputEnvelope(
|
|
148
|
+
run_id="abc-123",
|
|
149
|
+
inputs=EnergyPlusInputs(timestep_per_hour=4),
|
|
150
|
+
# ... other fields
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
# IDE autocomplete and type checking work
|
|
154
|
+
timestep = envelope.inputs.timestep_per_hour # ✓ Known to be int
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Package Structure
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
validibot_shared/
|
|
161
|
+
├── validations/ # Base validation envelope schemas
|
|
162
|
+
│ └── envelopes.py # Input/output envelopes for all validators
|
|
163
|
+
├── energyplus/ # EnergyPlus-specific models and envelopes
|
|
164
|
+
│ ├── models.py # Simulation output models (metrics, results)
|
|
165
|
+
│ └── envelopes.py # Typed envelope subclasses
|
|
166
|
+
└── fmi/ # FMI/FMU-specific models
|
|
167
|
+
├── models.py # Probe result models
|
|
168
|
+
└── envelopes.py # FMI envelope subclasses
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Usage Examples
|
|
172
|
+
|
|
173
|
+
### Creating an Input Envelope
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
from validibot_shared.energyplus import EnergyPlusInputEnvelope, EnergyPlusInputs
|
|
177
|
+
from validibot_shared.validations.envelopes import (
|
|
178
|
+
InputFileItem,
|
|
179
|
+
ValidatorInfo,
|
|
180
|
+
ExecutionContext,
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
envelope = EnergyPlusInputEnvelope(
|
|
184
|
+
run_id="run-123",
|
|
185
|
+
validator=ValidatorInfo(id="v1", type="energyplus", version="24.2.0"),
|
|
186
|
+
input_files=[
|
|
187
|
+
InputFileItem(
|
|
188
|
+
name="model.idf",
|
|
189
|
+
mime_type="application/vnd.energyplus.idf",
|
|
190
|
+
role="primary-model",
|
|
191
|
+
uri="gs://bucket/model.idf",
|
|
192
|
+
),
|
|
193
|
+
],
|
|
194
|
+
inputs=EnergyPlusInputs(timestep_per_hour=4),
|
|
195
|
+
context=ExecutionContext(
|
|
196
|
+
callback_url="https://api.example.com/callback",
|
|
197
|
+
execution_bundle_uri="gs://bucket/run-123/",
|
|
198
|
+
),
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
# Serialize to JSON for the validator container
|
|
202
|
+
json_payload = envelope.model_dump_json()
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Deserializing Results
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
from validibot_shared.energyplus import EnergyPlusOutputEnvelope
|
|
209
|
+
|
|
210
|
+
# Parse JSON response from validator
|
|
211
|
+
envelope = EnergyPlusOutputEnvelope.model_validate_json(response_json)
|
|
212
|
+
|
|
213
|
+
# Check status
|
|
214
|
+
if envelope.status == "success":
|
|
215
|
+
# Access typed outputs with full autocomplete
|
|
216
|
+
if envelope.outputs and envelope.outputs.metrics:
|
|
217
|
+
print(f"EUI: {envelope.outputs.metrics.eui_kbtu_per_sqft} kBtu/sqft")
|
|
218
|
+
|
|
219
|
+
# Iterate over validation messages
|
|
220
|
+
for message in envelope.messages:
|
|
221
|
+
print(f"[{message.severity}] {message.text}")
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### FMI Probe Results
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
from validibot_shared.fmi.models import FMIProbeResult, FMIVariableMeta
|
|
228
|
+
|
|
229
|
+
# Create a successful probe result
|
|
230
|
+
result = FMIProbeResult.success(
|
|
231
|
+
variables=[
|
|
232
|
+
FMIVariableMeta(name="temperature", causality="output", value_type="Real"),
|
|
233
|
+
FMIVariableMeta(name="pressure", causality="output", value_type="Real"),
|
|
234
|
+
],
|
|
235
|
+
execution_seconds=0.5,
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
# Create a failure result
|
|
239
|
+
result = FMIProbeResult.failure(
|
|
240
|
+
errors=["Invalid FMU: missing modelDescription.xml"]
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
# Serialize for response
|
|
244
|
+
json_response = result.model_dump_json()
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Creating a Custom Validator
|
|
248
|
+
|
|
249
|
+
If you're building a custom validator, create typed envelope subclasses:
|
|
250
|
+
|
|
251
|
+
```python
|
|
252
|
+
from pydantic import BaseModel
|
|
253
|
+
from validibot_shared.validations.envelopes import (
|
|
254
|
+
ValidationInputEnvelope,
|
|
255
|
+
ValidationOutputEnvelope,
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
# Define your validator's input configuration
|
|
259
|
+
class MyValidatorInputs(BaseModel):
|
|
260
|
+
strict_mode: bool = False
|
|
261
|
+
max_errors: int = 100
|
|
262
|
+
|
|
263
|
+
# Define your validator's output data
|
|
264
|
+
class MyValidatorOutputs(BaseModel):
|
|
265
|
+
items_checked: int
|
|
266
|
+
items_passed: int
|
|
267
|
+
|
|
268
|
+
# Create typed envelope subclasses
|
|
269
|
+
class MyValidatorInputEnvelope(ValidationInputEnvelope):
|
|
270
|
+
inputs: MyValidatorInputs
|
|
271
|
+
|
|
272
|
+
class MyValidatorOutputEnvelope(ValidationOutputEnvelope):
|
|
273
|
+
outputs: MyValidatorOutputs | None = None
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## API Reference
|
|
277
|
+
|
|
278
|
+
### ValidationInputEnvelope
|
|
279
|
+
|
|
280
|
+
```python
|
|
281
|
+
class ValidationInputEnvelope(BaseModel):
|
|
282
|
+
run_id: str # Unique identifier for this validation run
|
|
283
|
+
validator: ValidatorInfo # Validator identification
|
|
284
|
+
input_files: list[InputFileItem] # Files to validate
|
|
285
|
+
inputs: dict[str, Any] # Validator-specific configuration
|
|
286
|
+
context: ExecutionContext # Callback URL, bundle URI, etc.
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### ValidationOutputEnvelope
|
|
290
|
+
|
|
291
|
+
```python
|
|
292
|
+
class ValidationOutputEnvelope(BaseModel):
|
|
293
|
+
run_id: str # Matches input run_id
|
|
294
|
+
status: str # "success", "failure", "error"
|
|
295
|
+
messages: list[ValidationMessage] # Validation findings
|
|
296
|
+
metrics: list[ValidationMetric] # Numeric metrics
|
|
297
|
+
artifacts: list[ValidationArtifact] # Output files
|
|
298
|
+
outputs: dict[str, Any] | None # Validator-specific results
|
|
299
|
+
execution_seconds: float | None # Execution time
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### ValidationMessage
|
|
303
|
+
|
|
304
|
+
```python
|
|
305
|
+
class ValidationMessage(BaseModel):
|
|
306
|
+
severity: str # "error", "warning", "info"
|
|
307
|
+
code: str | None # Machine-readable code
|
|
308
|
+
text: str # Human-readable message
|
|
309
|
+
location: str | None # File/line reference
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## Part of the Validibot Project
|
|
313
|
+
|
|
314
|
+
This library is one component of the Validibot open-source data validation platform:
|
|
315
|
+
|
|
316
|
+
| Repository | Description |
|
|
317
|
+
|------------|-------------|
|
|
318
|
+
| **[validibot](https://github.com/danielmcquillen/validibot)** | Core platform — web UI, REST API, workflow engine |
|
|
319
|
+
| **[validibot-cli](https://github.com/danielmcquillen/validibot-cli)** | Command-line interface |
|
|
320
|
+
| **[validibot-validators](https://github.com/danielmcquillen/validibot-validators)** | Advanced validator containers (EnergyPlus, FMI) |
|
|
321
|
+
| **[validibot-shared](https://github.com/danielmcquillen/validibot-shared)** (this repo) | Shared Pydantic models for data interchange |
|
|
322
|
+
|
|
323
|
+
### How It Fits Together
|
|
324
|
+
|
|
325
|
+
```
|
|
326
|
+
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
327
|
+
│ End Users │
|
|
328
|
+
│ (Web UI, CLI, REST API clients) │
|
|
329
|
+
└─────────────────────────────────────────────────────────────────────────────┘
|
|
330
|
+
│
|
|
331
|
+
▼
|
|
332
|
+
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
333
|
+
│ validibot (core platform) │
|
|
334
|
+
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
|
335
|
+
│ │ Web UI │ REST API │ Workflow Engine │ Built-in Validators │ │
|
|
336
|
+
│ └─────────────────────────────────────────────────────────────────────┘ │
|
|
337
|
+
│ │ │
|
|
338
|
+
│ Triggers Docker containers for advanced validations │
|
|
339
|
+
└─────────────────────────────────────────────────────────────────────────────┘
|
|
340
|
+
│
|
|
341
|
+
┌──────────────────────────┼──────────────────────────┐
|
|
342
|
+
▼ ▼ ▼
|
|
343
|
+
┌─────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐
|
|
344
|
+
│ validibot-cli │ │ validibot-validators│ │ validibot-shared │
|
|
345
|
+
│ │ │ │ │ (this repo) │
|
|
346
|
+
│ Terminal access │ │ EnergyPlus, FMI │ │ │
|
|
347
|
+
│ to API │ │ containers │ │ Pydantic models │
|
|
348
|
+
│ │ │ │ │ │ (shared contract) │
|
|
349
|
+
└─────────────────┘ └────────┼────────────┘ └─────────────────────┘
|
|
350
|
+
│ ▲
|
|
351
|
+
└──────────────────────────┘
|
|
352
|
+
validators import shared
|
|
353
|
+
models for type safety
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
## Development
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
# Clone the repository
|
|
360
|
+
git clone https://github.com/danielmcquillen/validibot-shared.git
|
|
361
|
+
cd validibot-shared
|
|
362
|
+
|
|
363
|
+
# Install with dev dependencies
|
|
364
|
+
uv sync --extra dev
|
|
365
|
+
|
|
366
|
+
# Run tests
|
|
367
|
+
uv run pytest
|
|
368
|
+
|
|
369
|
+
# Run linter
|
|
370
|
+
uv run ruff check .
|
|
371
|
+
|
|
372
|
+
# Run type checker
|
|
373
|
+
uv run mypy src/
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
## License
|
|
377
|
+
|
|
378
|
+
MIT License — see [LICENSE](LICENSE) for details.
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
<div align="center">
|
|
383
|
+
|
|
384
|
+
[Validibot Platform](https://github.com/danielmcquillen/validibot) •
|
|
385
|
+
[Documentation](https://docs.validibot.com) •
|
|
386
|
+
[Report Issues](https://github.com/danielmcquillen/validibot-shared/issues)
|
|
387
|
+
|
|
388
|
+
</div>
|
|
@@ -37,18 +37,23 @@ app and Advanced validator containers:
|
|
|
37
37
|
3. Validator reads inputs, runs validation, writes outputs to local storage
|
|
38
38
|
4. Docker container exits, Django reads output.json directly
|
|
39
39
|
|
|
40
|
-
## Why
|
|
40
|
+
## Why Three Separate Fields: input_files, resource_files, and inputs?
|
|
41
41
|
|
|
42
|
-
- **input_files**:
|
|
43
|
-
-
|
|
44
|
-
- Role field distinguishes file purposes (e.g., 'primary-model'
|
|
42
|
+
- **input_files**: User-submitted files (IDF, FMU, XML, etc.)
|
|
43
|
+
- Files uploaded by users as part of their submission
|
|
44
|
+
- Role field distinguishes file purposes (e.g., 'primary-model')
|
|
45
|
+
|
|
46
|
+
- **resource_files**: Auxiliary files needed by validators (weather files, libraries)
|
|
47
|
+
- Managed by system admins, not user-submitted
|
|
48
|
+
- Examples: EPW weather files for EnergyPlus, FMU libraries for FMI
|
|
49
|
+
- Stored in ValidatorResourceFile model with org/system scoping
|
|
45
50
|
|
|
46
51
|
- **inputs**: Domain-specific configuration parameters
|
|
47
52
|
- Base class uses dict[str, Any] for flexibility
|
|
48
53
|
- Subclasses override with typed Pydantic models (e.g., EnergyPlusInputs)
|
|
49
54
|
- Examples: timestep settings, output variables, simulation options
|
|
50
55
|
|
|
51
|
-
This separation keeps
|
|
56
|
+
This separation keeps user submissions, system resources, and config distinct.
|
|
52
57
|
|
|
53
58
|
## Why Separate outputs Field?
|
|
54
59
|
|
|
@@ -167,11 +172,12 @@ class SupportedMimeType(str, Enum):
|
|
|
167
172
|
|
|
168
173
|
class InputFileItem(BaseModel):
|
|
169
174
|
"""
|
|
170
|
-
A file input for the validator.
|
|
175
|
+
A user-submitted file input for the validator.
|
|
176
|
+
|
|
177
|
+
Files are stored in GCS/local storage and referenced by URI. The 'role' field
|
|
178
|
+
allows validators to understand what each file is for (e.g., 'primary-model').
|
|
171
179
|
|
|
172
|
-
|
|
173
|
-
validators to understand what each file is for (e.g., 'primary-model' vs
|
|
174
|
-
'weather' for EnergyPlus).
|
|
180
|
+
Note: Auxiliary files like weather files are in resource_files, not input_files.
|
|
175
181
|
"""
|
|
176
182
|
|
|
177
183
|
name: str = Field(description="Human-readable name of the file")
|
|
@@ -180,9 +186,34 @@ class InputFileItem(BaseModel):
|
|
|
180
186
|
|
|
181
187
|
role: str | None = Field(
|
|
182
188
|
default=None,
|
|
183
|
-
description=(
|
|
184
|
-
|
|
185
|
-
|
|
189
|
+
description="Validator-specific role (e.g., 'primary-model', 'config')",
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
uri: str = Field(
|
|
193
|
+
description="Storage URI to the file (gs:// or file:// for self-hosted)"
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
model_config = {"extra": "forbid"}
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
class ResourceFileItem(BaseModel):
|
|
200
|
+
"""
|
|
201
|
+
A resource file needed by the validator.
|
|
202
|
+
|
|
203
|
+
Resource files are auxiliary files that validators need to run, but are not
|
|
204
|
+
submission data. Examples: weather files for EnergyPlus, libraries for FMI.
|
|
205
|
+
|
|
206
|
+
Unlike InputFileItem (which is per-submission), resource files are reusable
|
|
207
|
+
across validations and managed via the Validator Library UI in Django.
|
|
208
|
+
|
|
209
|
+
The 'type' field indicates what kind of resource this is (weather, library, etc.)
|
|
210
|
+
and validators use this to locate the appropriate file for their needs.
|
|
211
|
+
"""
|
|
212
|
+
|
|
213
|
+
id: str = Field(description="Resource file UUID from Django database")
|
|
214
|
+
|
|
215
|
+
type: str = Field(
|
|
216
|
+
description="Resource type (e.g., 'weather', 'library', 'config')"
|
|
186
217
|
)
|
|
187
218
|
|
|
188
219
|
uri: str = Field(
|
|
@@ -349,6 +380,14 @@ class ValidationInputEnvelope(BaseModel):
|
|
|
349
380
|
description="File inputs for the validator (GCS URIs with roles)",
|
|
350
381
|
)
|
|
351
382
|
|
|
383
|
+
resource_files: list[ResourceFileItem] = Field(
|
|
384
|
+
default_factory=list,
|
|
385
|
+
description=(
|
|
386
|
+
"Resource files needed by the validator (weather, libraries, configs). "
|
|
387
|
+
"These are auxiliary files managed via Validator Library, not submission data."
|
|
388
|
+
),
|
|
389
|
+
)
|
|
390
|
+
|
|
352
391
|
inputs: dict[str, Any] = Field(
|
|
353
392
|
default_factory=dict,
|
|
354
393
|
description=("Domain-specific inputs (subclasses override with typed model)"),
|
validibot_shared-0.1.0/PKG-INFO
DELETED
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: validibot-shared
|
|
3
|
-
Version: 0.1.0
|
|
4
|
-
Summary: Shared library for data interchange between Validibot and validator containers
|
|
5
|
-
Project-URL: Homepage, https://validibot.com
|
|
6
|
-
Project-URL: Documentation, https://docs.validibot.com
|
|
7
|
-
Project-URL: Repository, https://github.com/danielmcquillen/validibot-shared
|
|
8
|
-
Project-URL: Issues, https://github.com/danielmcquillen/validibot-shared/issues
|
|
9
|
-
Author-email: Daniel McQuillen <daniel@validibot.com>
|
|
10
|
-
Maintainer-email: Daniel McQuillen <daniel@validibot.com>
|
|
11
|
-
License: MIT
|
|
12
|
-
License-File: LICENSE
|
|
13
|
-
License-File: NOTICE
|
|
14
|
-
Keywords: data-interchange,energyplus,fmu,simulation,validation,validibot
|
|
15
|
-
Classifier: Development Status :: 4 - Beta
|
|
16
|
-
Classifier: Intended Audience :: Developers
|
|
17
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
-
Classifier: Operating System :: OS Independent
|
|
19
|
-
Classifier: Programming Language :: Python :: 3
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
-
Classifier: Topic :: Scientific/Engineering
|
|
25
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
26
|
-
Requires-Python: >=3.10
|
|
27
|
-
Requires-Dist: pydantic>=2.8.0
|
|
28
|
-
Provides-Extra: dev
|
|
29
|
-
Requires-Dist: pytest>=8.3.0; extra == 'dev'
|
|
30
|
-
Requires-Dist: ruff>=0.8.0; extra == 'dev'
|
|
31
|
-
Description-Content-Type: text/markdown
|
|
32
|
-
|
|
33
|
-
# validibot-shared
|
|
34
|
-
|
|
35
|
-
Shared Pydantic models for [Validibot](https://validibot.com) validator containers.
|
|
36
|
-
|
|
37
|
-
This library defines the data interchange types used between Validibot and its advanced validator services, ensuring type safety and contract consistency.
|
|
38
|
-
|
|
39
|
-
## Installation
|
|
40
|
-
|
|
41
|
-
```bash
|
|
42
|
-
pip install validibot-shared
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
Or with uv:
|
|
46
|
-
|
|
47
|
-
```bash
|
|
48
|
-
uv add validibot-shared
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
## Package Structure
|
|
52
|
-
|
|
53
|
-
```
|
|
54
|
-
validibot_shared/
|
|
55
|
-
├── validations/ # Base validation envelope schemas
|
|
56
|
-
│ └── envelopes.py # Input/output envelopes for all validators
|
|
57
|
-
├── energyplus/ # EnergyPlus-specific models and envelopes
|
|
58
|
-
│ ├── models.py # Simulation output models
|
|
59
|
-
│ └── envelopes.py # Typed envelope subclasses
|
|
60
|
-
└── fmi/ # FMI/FMU-specific models
|
|
61
|
-
├── models.py # Probe result models
|
|
62
|
-
└── envelopes.py # FMI envelope subclasses
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## Core Concepts
|
|
66
|
-
|
|
67
|
-
### Validation Envelopes
|
|
68
|
-
|
|
69
|
-
The library provides base envelope classes for validator communication:
|
|
70
|
-
|
|
71
|
-
- `ValidationInputEnvelope` - Standard input format for validation jobs
|
|
72
|
-
- `ValidationOutputEnvelope` - Standard output format with results
|
|
73
|
-
- `ValidationCallback` - Callback payload for async job completion
|
|
74
|
-
|
|
75
|
-
Supporting classes include `InputFileItem`, `ValidatorInfo`, `ExecutionContext`, `ValidationMessage`, `ValidationMetric`, and `ValidationArtifact`.
|
|
76
|
-
|
|
77
|
-
### Typed Subclassing Pattern
|
|
78
|
-
|
|
79
|
-
Domain-specific validators extend the base envelopes with typed fields:
|
|
80
|
-
|
|
81
|
-
```python
|
|
82
|
-
from validibot_shared.energyplus import EnergyPlusInputEnvelope, EnergyPlusInputs
|
|
83
|
-
|
|
84
|
-
# The envelope has typed inputs instead of dict[str, Any]
|
|
85
|
-
envelope = EnergyPlusInputEnvelope(
|
|
86
|
-
run_id="abc-123",
|
|
87
|
-
inputs=EnergyPlusInputs(timestep_per_hour=4),
|
|
88
|
-
# ... other fields
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
# IDE autocomplete and type checking work
|
|
92
|
-
timestep = envelope.inputs.timestep_per_hour
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
This provides:
|
|
96
|
-
|
|
97
|
-
- **Type safety** - mypy/pyright catch errors at compile time
|
|
98
|
-
- **Runtime validation** - Pydantic validates all data
|
|
99
|
-
- **IDE support** - Full autocomplete for domain-specific fields
|
|
100
|
-
|
|
101
|
-
## Usage Examples
|
|
102
|
-
|
|
103
|
-
### Creating an Input Envelope
|
|
104
|
-
|
|
105
|
-
```python
|
|
106
|
-
from validibot_shared.energyplus import EnergyPlusInputEnvelope, EnergyPlusInputs
|
|
107
|
-
from validibot_shared.validations.envelopes import (
|
|
108
|
-
InputFileItem,
|
|
109
|
-
ValidatorInfo,
|
|
110
|
-
ExecutionContext,
|
|
111
|
-
)
|
|
112
|
-
|
|
113
|
-
envelope = EnergyPlusInputEnvelope(
|
|
114
|
-
run_id="run-123",
|
|
115
|
-
validator=ValidatorInfo(id="v1", type="energyplus", version="24.2.0"),
|
|
116
|
-
input_files=[
|
|
117
|
-
InputFileItem(
|
|
118
|
-
name="model.idf",
|
|
119
|
-
mime_type="application/vnd.energyplus.idf",
|
|
120
|
-
role="primary-model",
|
|
121
|
-
uri="gs://bucket/model.idf",
|
|
122
|
-
),
|
|
123
|
-
],
|
|
124
|
-
inputs=EnergyPlusInputs(timestep_per_hour=4),
|
|
125
|
-
context=ExecutionContext(
|
|
126
|
-
callback_url="https://api.example.com/callback",
|
|
127
|
-
execution_bundle_uri="gs://bucket/run-123/",
|
|
128
|
-
),
|
|
129
|
-
)
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
### Deserializing Results
|
|
133
|
-
|
|
134
|
-
```python
|
|
135
|
-
from validibot_shared.energyplus import EnergyPlusOutputEnvelope
|
|
136
|
-
|
|
137
|
-
# Parse JSON response from validator
|
|
138
|
-
envelope = EnergyPlusOutputEnvelope.model_validate_json(response_json)
|
|
139
|
-
|
|
140
|
-
# Access typed outputs
|
|
141
|
-
if envelope.outputs:
|
|
142
|
-
print(f"EUI: {envelope.outputs.metrics.eui_kbtu_per_sqft}")
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
### FMI Probe Results
|
|
146
|
-
|
|
147
|
-
```python
|
|
148
|
-
from validibot_shared.fmi.models import FMIProbeResult, FMIVariableMeta
|
|
149
|
-
|
|
150
|
-
# Create a successful probe result
|
|
151
|
-
result = FMIProbeResult.success(
|
|
152
|
-
variables=[
|
|
153
|
-
FMIVariableMeta(name="temperature", causality="output", value_type="Real"),
|
|
154
|
-
],
|
|
155
|
-
execution_seconds=0.5,
|
|
156
|
-
)
|
|
157
|
-
|
|
158
|
-
# Create a failure result
|
|
159
|
-
result = FMIProbeResult.failure(errors=["Invalid FMU: missing modelDescription.xml"])
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
## Dependencies
|
|
163
|
-
|
|
164
|
-
- `pydantic>=2.8.0`
|
|
165
|
-
|
|
166
|
-
## License
|
|
167
|
-
|
|
168
|
-
MIT License - see [LICENSE](LICENSE) for details.
|
validibot_shared-0.1.0/README.md
DELETED
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
# validibot-shared
|
|
2
|
-
|
|
3
|
-
Shared Pydantic models for [Validibot](https://validibot.com) validator containers.
|
|
4
|
-
|
|
5
|
-
This library defines the data interchange types used between Validibot and its advanced validator services, ensuring type safety and contract consistency.
|
|
6
|
-
|
|
7
|
-
## Installation
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
pip install validibot-shared
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Or with uv:
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
uv add validibot-shared
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Package Structure
|
|
20
|
-
|
|
21
|
-
```
|
|
22
|
-
validibot_shared/
|
|
23
|
-
├── validations/ # Base validation envelope schemas
|
|
24
|
-
│ └── envelopes.py # Input/output envelopes for all validators
|
|
25
|
-
├── energyplus/ # EnergyPlus-specific models and envelopes
|
|
26
|
-
│ ├── models.py # Simulation output models
|
|
27
|
-
│ └── envelopes.py # Typed envelope subclasses
|
|
28
|
-
└── fmi/ # FMI/FMU-specific models
|
|
29
|
-
├── models.py # Probe result models
|
|
30
|
-
└── envelopes.py # FMI envelope subclasses
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## Core Concepts
|
|
34
|
-
|
|
35
|
-
### Validation Envelopes
|
|
36
|
-
|
|
37
|
-
The library provides base envelope classes for validator communication:
|
|
38
|
-
|
|
39
|
-
- `ValidationInputEnvelope` - Standard input format for validation jobs
|
|
40
|
-
- `ValidationOutputEnvelope` - Standard output format with results
|
|
41
|
-
- `ValidationCallback` - Callback payload for async job completion
|
|
42
|
-
|
|
43
|
-
Supporting classes include `InputFileItem`, `ValidatorInfo`, `ExecutionContext`, `ValidationMessage`, `ValidationMetric`, and `ValidationArtifact`.
|
|
44
|
-
|
|
45
|
-
### Typed Subclassing Pattern
|
|
46
|
-
|
|
47
|
-
Domain-specific validators extend the base envelopes with typed fields:
|
|
48
|
-
|
|
49
|
-
```python
|
|
50
|
-
from validibot_shared.energyplus import EnergyPlusInputEnvelope, EnergyPlusInputs
|
|
51
|
-
|
|
52
|
-
# The envelope has typed inputs instead of dict[str, Any]
|
|
53
|
-
envelope = EnergyPlusInputEnvelope(
|
|
54
|
-
run_id="abc-123",
|
|
55
|
-
inputs=EnergyPlusInputs(timestep_per_hour=4),
|
|
56
|
-
# ... other fields
|
|
57
|
-
)
|
|
58
|
-
|
|
59
|
-
# IDE autocomplete and type checking work
|
|
60
|
-
timestep = envelope.inputs.timestep_per_hour
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
This provides:
|
|
64
|
-
|
|
65
|
-
- **Type safety** - mypy/pyright catch errors at compile time
|
|
66
|
-
- **Runtime validation** - Pydantic validates all data
|
|
67
|
-
- **IDE support** - Full autocomplete for domain-specific fields
|
|
68
|
-
|
|
69
|
-
## Usage Examples
|
|
70
|
-
|
|
71
|
-
### Creating an Input Envelope
|
|
72
|
-
|
|
73
|
-
```python
|
|
74
|
-
from validibot_shared.energyplus import EnergyPlusInputEnvelope, EnergyPlusInputs
|
|
75
|
-
from validibot_shared.validations.envelopes import (
|
|
76
|
-
InputFileItem,
|
|
77
|
-
ValidatorInfo,
|
|
78
|
-
ExecutionContext,
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
envelope = EnergyPlusInputEnvelope(
|
|
82
|
-
run_id="run-123",
|
|
83
|
-
validator=ValidatorInfo(id="v1", type="energyplus", version="24.2.0"),
|
|
84
|
-
input_files=[
|
|
85
|
-
InputFileItem(
|
|
86
|
-
name="model.idf",
|
|
87
|
-
mime_type="application/vnd.energyplus.idf",
|
|
88
|
-
role="primary-model",
|
|
89
|
-
uri="gs://bucket/model.idf",
|
|
90
|
-
),
|
|
91
|
-
],
|
|
92
|
-
inputs=EnergyPlusInputs(timestep_per_hour=4),
|
|
93
|
-
context=ExecutionContext(
|
|
94
|
-
callback_url="https://api.example.com/callback",
|
|
95
|
-
execution_bundle_uri="gs://bucket/run-123/",
|
|
96
|
-
),
|
|
97
|
-
)
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
### Deserializing Results
|
|
101
|
-
|
|
102
|
-
```python
|
|
103
|
-
from validibot_shared.energyplus import EnergyPlusOutputEnvelope
|
|
104
|
-
|
|
105
|
-
# Parse JSON response from validator
|
|
106
|
-
envelope = EnergyPlusOutputEnvelope.model_validate_json(response_json)
|
|
107
|
-
|
|
108
|
-
# Access typed outputs
|
|
109
|
-
if envelope.outputs:
|
|
110
|
-
print(f"EUI: {envelope.outputs.metrics.eui_kbtu_per_sqft}")
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
### FMI Probe Results
|
|
114
|
-
|
|
115
|
-
```python
|
|
116
|
-
from validibot_shared.fmi.models import FMIProbeResult, FMIVariableMeta
|
|
117
|
-
|
|
118
|
-
# Create a successful probe result
|
|
119
|
-
result = FMIProbeResult.success(
|
|
120
|
-
variables=[
|
|
121
|
-
FMIVariableMeta(name="temperature", causality="output", value_type="Real"),
|
|
122
|
-
],
|
|
123
|
-
execution_seconds=0.5,
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
# Create a failure result
|
|
127
|
-
result = FMIProbeResult.failure(errors=["Invalid FMU: missing modelDescription.xml"])
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
## Dependencies
|
|
131
|
-
|
|
132
|
-
- `pydantic>=2.8.0`
|
|
133
|
-
|
|
134
|
-
## License
|
|
135
|
-
|
|
136
|
-
MIT License - see [LICENSE](LICENSE) for details.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|