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.
Files changed (25) hide show
  1. validibot_shared-0.2.1/PKG-INFO +420 -0
  2. validibot_shared-0.2.1/README.md +388 -0
  3. {validibot_shared-0.1.0 → validibot_shared-0.2.1}/pyproject.toml +1 -1
  4. {validibot_shared-0.1.0 → validibot_shared-0.2.1}/validibot_shared/validations/envelopes.py +51 -12
  5. validibot_shared-0.1.0/PKG-INFO +0 -168
  6. validibot_shared-0.1.0/README.md +0 -136
  7. {validibot_shared-0.1.0 → validibot_shared-0.2.1}/.gitignore +0 -0
  8. {validibot_shared-0.1.0 → validibot_shared-0.2.1}/LICENSE +0 -0
  9. {validibot_shared-0.1.0 → validibot_shared-0.2.1}/NOTICE +0 -0
  10. {validibot_shared-0.1.0 → validibot_shared-0.2.1}/tests/__init__.py +0 -0
  11. {validibot_shared-0.1.0 → validibot_shared-0.2.1}/tests/test_energyplus_envelopes.py +0 -0
  12. {validibot_shared-0.1.0 → validibot_shared-0.2.1}/tests/test_energyplus_models.py +0 -0
  13. {validibot_shared-0.1.0 → validibot_shared-0.2.1}/tests/test_fmi_envelopes.py +0 -0
  14. {validibot_shared-0.1.0 → validibot_shared-0.2.1}/tests/test_fmi_models.py +0 -0
  15. {validibot_shared-0.1.0 → validibot_shared-0.2.1}/tests/test_package_init.py +0 -0
  16. {validibot_shared-0.1.0 → validibot_shared-0.2.1}/tests/test_validations_envelopes.py +0 -0
  17. {validibot_shared-0.1.0 → validibot_shared-0.2.1}/validibot_shared/__init__.py +0 -0
  18. {validibot_shared-0.1.0 → validibot_shared-0.2.1}/validibot_shared/energyplus/__init__.py +0 -0
  19. {validibot_shared-0.1.0 → validibot_shared-0.2.1}/validibot_shared/energyplus/envelopes.py +0 -0
  20. {validibot_shared-0.1.0 → validibot_shared-0.2.1}/validibot_shared/energyplus/models.py +0 -0
  21. {validibot_shared-0.1.0 → validibot_shared-0.2.1}/validibot_shared/fmi/__init__.py +0 -0
  22. {validibot_shared-0.1.0 → validibot_shared-0.2.1}/validibot_shared/fmi/envelopes.py +0 -0
  23. {validibot_shared-0.1.0 → validibot_shared-0.2.1}/validibot_shared/fmi/models.py +0 -0
  24. {validibot_shared-0.1.0 → validibot_shared-0.2.1}/validibot_shared/py.typed +0 -0
  25. {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
+ [![PyPI version](https://badge.fury.io/py/validibot-shared.svg)](https://pypi.org/project/validibot-shared/)
40
+ [![Python versions](https://img.shields.io/pypi/pyversions/validibot-shared.svg)](https://pypi.org/project/validibot-shared/)
41
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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
+ [![PyPI version](https://badge.fury.io/py/validibot-shared.svg)](https://pypi.org/project/validibot-shared/)
8
+ [![Python versions](https://img.shields.io/pypi/pyversions/validibot-shared.svg)](https://pypi.org/project/validibot-shared/)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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>
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "validibot-shared"
7
- version = "0.1.0"
7
+ version = "0.2.1"
8
8
  description = "Shared library for data interchange between Validibot and validator containers"
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -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 Two Separate Fields: input_files vs inputs?
40
+ ## Why Three Separate Fields: input_files, resource_files, and inputs?
41
41
 
42
- - **input_files**: Generic list of GCS file URIs (IDF, EPW, FMU, XML, etc.)
43
- - NEVER changes in subclasses - all validators need file inputs
44
- - Role field distinguishes file purposes (e.g., 'primary-model' vs 'weather')
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 file handling generic while allowing type-safe config.
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
- Files are stored in GCS and referenced by URI. The 'role' field allows
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
- "Validator-specific role (e.g., 'primary-model', 'weather', 'config')"
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)"),
@@ -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.
@@ -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.