koia-scene-model 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,10 @@
1
+ node_modules/
2
+ dist/
3
+ packages/java/target/
4
+ packages/python/dist/
5
+ packages/python/**/__pycache__/
6
+ packages/python/*.egg-info/
7
+ *.tgz
8
+ bash.exe.stackdump
9
+ .venv/
10
+ packages/java/.flattened-pom.xml
@@ -0,0 +1,27 @@
1
+ Metadata-Version: 2.5
2
+ Name: koia-scene-model
3
+ Version: 1.0.0
4
+ Summary: Pydantic models generated from the Koia scene JSON Schema, for programs that write scenes into CouchDB for Koia
5
+ Project-URL: Homepage, https://github.com/centeractive/koia-scene-schema
6
+ Author-email: centeractive ag <info@centeractive.com>
7
+ License-Expression: MIT
8
+ Requires-Python: >=3.10
9
+ Requires-Dist: pydantic<3,>=2
10
+ Provides-Extra: test
11
+ Requires-Dist: jsonschema==4.26.0; extra == 'test'
12
+ Requires-Dist: pytest; extra == 'test'
13
+ Description-Content-Type: text/markdown
14
+
15
+ # koia-scene-model
16
+
17
+ Pydantic models generated from the [Koia scene JSON Schema](https://github.com/centeractive/koia-scene-schema), plus the packaged schemas.
18
+
19
+ ```python
20
+ from koia_scene_model import SceneDocument, SceneColumn, schema_path
21
+
22
+ scene = SceneDocument(creationTime=1767225600000, name='Logs', shortDescription='', database='data_1',
23
+ columns=[SceneColumn(name='Data', dataType='Text')], schemaVersion='1.0')
24
+ print(scene.model_dump_json(by_alias=True, exclude_none=True))
25
+ ```
26
+
27
+ See [SPEC.md](https://github.com/centeractive/koia-scene-schema/blob/main/docs/SPEC.md) for the rules beyond the schema.
@@ -0,0 +1,13 @@
1
+ # koia-scene-model
2
+
3
+ Pydantic models generated from the [Koia scene JSON Schema](https://github.com/centeractive/koia-scene-schema), plus the packaged schemas.
4
+
5
+ ```python
6
+ from koia_scene_model import SceneDocument, SceneColumn, schema_path
7
+
8
+ scene = SceneDocument(creationTime=1767225600000, name='Logs', shortDescription='', database='data_1',
9
+ columns=[SceneColumn(name='Data', dataType='Text')], schemaVersion='1.0')
10
+ print(scene.model_dump_json(by_alias=True, exclude_none=True))
11
+ ```
12
+
13
+ See [SPEC.md](https://github.com/centeractive/koia-scene-schema/blob/main/docs/SPEC.md) for the rules beyond the schema.
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env sh
2
+ # generates the pydantic models of the newest major into the file passed as $1 (default: koia_scene_model/v1.py)
3
+ set -e
4
+ cd "$(dirname "$0")"
5
+ datamodel-codegen \
6
+ --input ../../schemas/1.0/scene.schema.json \
7
+ --input-file-type jsonschema \
8
+ --output-model-type pydantic_v2.BaseModel \
9
+ --use-title-as-name \
10
+ --disable-timestamp \
11
+ --target-python-version 3.10 \
12
+ --formatters black isort \
13
+ --output "${1:-koia_scene_model/v1.py}"
@@ -0,0 +1,15 @@
1
+ from pathlib import Path
2
+
3
+ from hatchling.builders.hooks.plugin.interface import BuildHookInterface
4
+
5
+ SCHEMAS = Path(__file__).parent.parent.parent / "schemas"
6
+
7
+
8
+ class SchemasBuildHook(BuildHookInterface):
9
+ """
10
+ includes the repository schemas when building from the source tree, a build from the sdist finds them inside the package
11
+ """
12
+
13
+ def initialize(self, version, build_data):
14
+ if SCHEMAS.is_dir():
15
+ build_data["force_include"][str(SCHEMAS)] = "koia_scene_model/schemas"
@@ -0,0 +1,14 @@
1
+ from importlib.resources import files
2
+
3
+ from .v1 import ContextInfo, SceneColumn, SceneConfig, SceneDocument
4
+
5
+ __all__ = ["ContextInfo", "SceneColumn", "SceneConfig", "SceneDocument", "schema_path"]
6
+
7
+
8
+ def schema_path(version: str, kind: str):
9
+ """
10
+ :param version: scene format version, e.g. '1.0'
11
+ :param kind: 'scene' or 'entry'
12
+ :returns: the packaged JSON Schema file
13
+ """
14
+ return files(__package__) / "schemas" / version / f"{kind}.schema.json"
@@ -0,0 +1,20 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://www.koia.io/assets/scene-format/1.0/entry.schema.json",
4
+ "title": "EntryDocument",
5
+ "description": "Entry document in the entries database of a scene, format 1.0; property names equal the column names of the scene",
6
+ "type": "object",
7
+ "properties": {
8
+ "_id": {
9
+ "type": "string",
10
+ "description": "entry id, generated by CouchDB when omitted"
11
+ }
12
+ },
13
+ "additionalProperties": {
14
+ "anyOf": [
15
+ { "type": "string" },
16
+ { "type": "number" },
17
+ { "type": "boolean" }
18
+ ]
19
+ }
20
+ }
@@ -0,0 +1,99 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://www.koia.io/assets/scene-format/1.0/scene.schema.json",
4
+ "title": "SceneDocument",
5
+ "description": "Scene document in the CouchDB database 'scenes', format 1.0",
6
+ "type": "object",
7
+ "required": ["creationTime", "name", "shortDescription", "database", "columns"],
8
+ "properties": {
9
+ "_id": {
10
+ "type": "string",
11
+ "description": "scene id, generated by CouchDB when omitted"
12
+ },
13
+ "_rev": {
14
+ "type": "string",
15
+ "description": "CouchDB revision, omitted on insert"
16
+ },
17
+ "schemaVersion": {
18
+ "type": "string",
19
+ "pattern": "^[0-9]+\\.[0-9]+$",
20
+ "description": "scene format the document complies with; documents without it are read as format 1.0"
21
+ },
22
+ "creationTime": {
23
+ "type": "integer",
24
+ "description": "creation time in milliseconds since the epoch; scenes without it are not listed by Koia"
25
+ },
26
+ "name": {
27
+ "type": "string",
28
+ "minLength": 1
29
+ },
30
+ "shortDescription": {
31
+ "type": "string"
32
+ },
33
+ "database": {
34
+ "type": "string",
35
+ "minLength": 1,
36
+ "description": "name of the CouchDB database that holds the entries of the scene"
37
+ },
38
+ "context": {
39
+ "type": "array",
40
+ "description": "name/value pairs describing the origin of the data",
41
+ "items": { "$ref": "#/definitions/contextInfo" }
42
+ },
43
+ "columns": {
44
+ "type": "array",
45
+ "minItems": 1,
46
+ "items": { "$ref": "#/definitions/column" }
47
+ },
48
+ "config": { "$ref": "#/definitions/config" }
49
+ },
50
+ "definitions": {
51
+ "column": {
52
+ "title": "SceneColumn",
53
+ "type": "object",
54
+ "required": ["name", "dataType"],
55
+ "properties": {
56
+ "name": {
57
+ "type": "string",
58
+ "minLength": 1,
59
+ "description": "column name, equal to the property name in the entries"
60
+ },
61
+ "dataType": {
62
+ "type": "string",
63
+ "enum": ["Boolean", "Number", "Object", "Text", "Time"],
64
+ "description": "Time values are milliseconds since the epoch, Object values are JSON strings"
65
+ },
66
+ "width": {
67
+ "type": "number",
68
+ "minimum": 0
69
+ },
70
+ "format": {
71
+ "type": "string",
72
+ "description": "display format of Time values (e.g. 'yyyy-MM-dd HH:mm:ss,SSS')"
73
+ },
74
+ "indexed": {
75
+ "type": "boolean",
76
+ "description": "requires exactly one CouchDB index on this column in the entries database"
77
+ }
78
+ }
79
+ },
80
+ "contextInfo": {
81
+ "title": "ContextInfo",
82
+ "type": "object",
83
+ "required": ["name", "value"],
84
+ "properties": {
85
+ "name": { "type": "string" },
86
+ "value": { "type": "string" }
87
+ }
88
+ },
89
+ "config": {
90
+ "title": "SceneConfig",
91
+ "description": "owned by Koia; writers of format 1.0 SHOULD write {\"records\":[],\"views\":[]}, the form accepted by every Koia deployment",
92
+ "type": "object",
93
+ "properties": {
94
+ "records": { "type": "array", "items": {} },
95
+ "views": { "type": "array", "items": {} }
96
+ }
97
+ }
98
+ }
99
+ }
@@ -0,0 +1,74 @@
1
+ # generated by datamodel-codegen:
2
+ # filename: scene.schema.json
3
+
4
+ from __future__ import annotations
5
+
6
+ from enum import Enum
7
+ from typing import Any
8
+
9
+ from pydantic import BaseModel, Field, confloat, constr
10
+
11
+
12
+ class DataType(Enum):
13
+ Boolean = 'Boolean'
14
+ Number = 'Number'
15
+ Object = 'Object'
16
+ Text = 'Text'
17
+ Time = 'Time'
18
+
19
+
20
+ class SceneColumn(BaseModel):
21
+ name: constr(min_length=1) = Field(
22
+ ..., description='column name, equal to the property name in the entries'
23
+ )
24
+ dataType: DataType = Field(
25
+ ...,
26
+ description='Time values are milliseconds since the epoch, Object values are JSON strings',
27
+ )
28
+ width: confloat(ge=0.0) | None = None
29
+ format: str | None = Field(
30
+ None,
31
+ description="display format of Time values (e.g. 'yyyy-MM-dd HH:mm:ss,SSS')",
32
+ )
33
+ indexed: bool | None = Field(
34
+ None,
35
+ description='requires exactly one CouchDB index on this column in the entries database',
36
+ )
37
+
38
+
39
+ class ContextInfo(BaseModel):
40
+ name: str
41
+ value: str
42
+
43
+
44
+ class SceneConfig(BaseModel):
45
+ records: list[Any] | None = None
46
+ views: list[Any] | None = None
47
+
48
+
49
+ class SceneDocument(BaseModel):
50
+ field_id: str | None = Field(
51
+ None, alias='_id', description='scene id, generated by CouchDB when omitted'
52
+ )
53
+ field_rev: str | None = Field(
54
+ None, alias='_rev', description='CouchDB revision, omitted on insert'
55
+ )
56
+ schemaVersion: constr(pattern=r'^[0-9]+\.[0-9]+$') | None = Field(
57
+ None,
58
+ description='scene format the document complies with; documents without it are read as format 1.0',
59
+ )
60
+ creationTime: int = Field(
61
+ ...,
62
+ description='creation time in milliseconds since the epoch; scenes without it are not listed by Koia',
63
+ )
64
+ name: constr(min_length=1)
65
+ shortDescription: str
66
+ database: constr(min_length=1) = Field(
67
+ ...,
68
+ description='name of the CouchDB database that holds the entries of the scene',
69
+ )
70
+ context: list[ContextInfo] | None = Field(
71
+ None, description='name/value pairs describing the origin of the data'
72
+ )
73
+ columns: list[SceneColumn] = Field(..., min_length=1)
74
+ config: SceneConfig | None = None
@@ -0,0 +1,32 @@
1
+ [build-system]
2
+ requires = ["hatchling", "hatch-vcs"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "koia-scene-model"
7
+ dynamic = ["version"]
8
+ description = "Pydantic models generated from the Koia scene JSON Schema, for programs that write scenes into CouchDB for Koia"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ authors = [{ name = "centeractive ag", email = "info@centeractive.com" }]
12
+ requires-python = ">=3.10"
13
+ dependencies = ["pydantic>=2,<3"]
14
+
15
+ [project.urls]
16
+ Homepage = "https://github.com/centeractive/koia-scene-schema"
17
+
18
+ [project.optional-dependencies]
19
+ test = ["pytest", "jsonschema==4.26.0"]
20
+
21
+ [tool.hatch.version]
22
+ source = "vcs"
23
+ raw-options = { root = "../.." }
24
+
25
+ [tool.hatch.build.hooks.custom]
26
+ path = "hatch_build.py"
27
+
28
+ [tool.hatch.build.targets.wheel]
29
+ packages = ["koia_scene_model"]
30
+
31
+ [tool.pytest.ini_options]
32
+ testpaths = ["tests"]
@@ -0,0 +1,20 @@
1
+ import json
2
+ from pathlib import Path
3
+
4
+ import jsonschema
5
+ import pytest
6
+
7
+ from koia_scene_model import SceneDocument, schema_path
8
+
9
+ VALID_EXAMPLES = sorted((Path(__file__).parent.parent.parent.parent / "examples" / "1.0" / "valid").glob("*.json"))
10
+
11
+
12
+ @pytest.mark.parametrize("example", VALID_EXAMPLES, ids=lambda p: p.stem)
13
+ def test_valid_example_validates_and_parses(example):
14
+ document = json.loads(example.read_text(encoding="utf-8"))
15
+ schema = json.loads(schema_path("1.0", "scene").read_text(encoding="utf-8"))
16
+
17
+ jsonschema.Draft7Validator(schema).validate(document)
18
+ scene = SceneDocument.model_validate(document)
19
+
20
+ jsonschema.Draft7Validator(schema).validate(scene.model_dump(mode="json", by_alias=True, exclude_none=True))