csrd-models 0.1.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.
- csrd_models-0.1.1/PKG-INFO +14 -0
- csrd_models-0.1.1/README.md +0 -0
- csrd_models-0.1.1/pyproject.toml +19 -0
- csrd_models-0.1.1/src/csrd_models/__init__.py +3 -0
- csrd_models-0.1.1/src/csrd_models/entity/__init__.py +1 -0
- csrd_models-0.1.1/src/csrd_models/entity/_schema.py +99 -0
- csrd_models-0.1.1/src/csrd_models/entity/entity.py +24 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: csrd-models
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary:
|
|
5
|
+
Author: aaron
|
|
6
|
+
Author-email: aaron@frostmn.com
|
|
7
|
+
Requires-Python: >=3.12,<4.0
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
+
Requires-Dist: csrd-utils (>=0.1,<0.2)
|
|
11
|
+
Requires-Dist: pre-commit (>=3.8.0,<4.0.0)
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
|
|
File without changes
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "csrd-models"
|
|
3
|
+
version = "0.1.1"
|
|
4
|
+
description = ""
|
|
5
|
+
authors = ["aaron <aaron@frostmn.com>"]
|
|
6
|
+
readme = "README.md"
|
|
7
|
+
|
|
8
|
+
[tool.poetry.dependencies]
|
|
9
|
+
python = "^3.12"
|
|
10
|
+
pre-commit = "^3.8.0"
|
|
11
|
+
csrd-utils = "^0.1"
|
|
12
|
+
|
|
13
|
+
[[tool.poetry.source]]
|
|
14
|
+
name = "PyPI"
|
|
15
|
+
priority = "primary"
|
|
16
|
+
|
|
17
|
+
[build-system]
|
|
18
|
+
requires = ["poetry-core"]
|
|
19
|
+
build-backend = "poetry.core.masonry.api"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .entity import Entity
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
from typing import Any, Union, get_origin, get_args
|
|
2
|
+
from csrd_utils.string_utils import to_camel, to_title
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def get_name(obj: Any) -> str:
|
|
6
|
+
return obj.__name__
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _get_properties(obj: Any) -> dict:
|
|
10
|
+
return {k: obj.__dict__[k] for k in obj.__dict__ if not k.startswith('_')}
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def map_type(type_: Any):
|
|
14
|
+
if type(type_) is not str:
|
|
15
|
+
type_ = get_name(type_)
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
"str": "string",
|
|
19
|
+
"int": "integer",
|
|
20
|
+
"float": "number",
|
|
21
|
+
"bool": "boolean",
|
|
22
|
+
"List": "array",
|
|
23
|
+
"NoneType": 'null'
|
|
24
|
+
}[type_]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def is_union(value: Any) -> bool:
|
|
28
|
+
return get_origin(get_args(value)[0]) == Union
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def handle_union(key, name, value):
|
|
32
|
+
return {
|
|
33
|
+
# 'title': to_title(key),
|
|
34
|
+
'items': {'anyOf': [{"type": map_type(x)} for x in get_args(get_args(value)[0])]}, 'type': map_type(name)}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def handle_optional(key, name, value, props):
|
|
38
|
+
return {
|
|
39
|
+
'type': map_type([x for x in get_args(value) if x is not type(None)][0]),
|
|
40
|
+
'default': props.get(key, None),
|
|
41
|
+
'title': to_title(key),
|
|
42
|
+
'required': False
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def build_type(key, value: Any, props = None):
|
|
47
|
+
name = get_name(value)
|
|
48
|
+
|
|
49
|
+
if name in ('str', 'int', 'float', 'bool'):
|
|
50
|
+
return {
|
|
51
|
+
'title': to_title(key),
|
|
52
|
+
'type': map_type(name)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if name in ("List",):
|
|
56
|
+
args = get_args(value)[0]
|
|
57
|
+
if is_union(value):
|
|
58
|
+
return handle_union(key, name, value)
|
|
59
|
+
else:
|
|
60
|
+
return {
|
|
61
|
+
'title': to_title(key),
|
|
62
|
+
'type': map_type(name),
|
|
63
|
+
'items': {'type': map_type(args)}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if name in ("Optional",):
|
|
67
|
+
return handle_optional(key, name, value, props)
|
|
68
|
+
|
|
69
|
+
# this is probably missing some cases
|
|
70
|
+
return {'$ref': f'#/definitions/{value.__name__}'}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _build_properties(value: Any):
|
|
74
|
+
props = getattr(value, '__properties__', None)
|
|
75
|
+
annno = getattr(value, '__annotations__', None)
|
|
76
|
+
return { to_camel(key): build_type(key, annno[key], props) for key in annno }
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _build_schema(cls: Any):
|
|
80
|
+
return {
|
|
81
|
+
"properties": _build_properties(cls),
|
|
82
|
+
"title": get_name(cls),
|
|
83
|
+
"type": "object"
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class _Schema:
|
|
88
|
+
def __init__(self, __class__):
|
|
89
|
+
self._set_schema(__class__)
|
|
90
|
+
|
|
91
|
+
@classmethod
|
|
92
|
+
def _set_schema(cls, __class__):
|
|
93
|
+
setattr(cls, '__annotations__', __class__.__annotations__)
|
|
94
|
+
setattr(cls, '__name__', __class__.__name__)
|
|
95
|
+
setattr(cls, '__properties__', _get_properties(__class__))
|
|
96
|
+
|
|
97
|
+
@classmethod
|
|
98
|
+
def dump_schema(cls):
|
|
99
|
+
return _build_schema(cls)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from ._schema import _Schema
|
|
2
|
+
|
|
3
|
+
from csrd_utils.string_utils import to_camel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Entity:
|
|
7
|
+
_schema = _Schema
|
|
8
|
+
|
|
9
|
+
def __init__(self, /, **data):
|
|
10
|
+
self._schema = _Schema(self.__class__)
|
|
11
|
+
for key, value in data.items():
|
|
12
|
+
self.__dict__[key] = value
|
|
13
|
+
|
|
14
|
+
@property
|
|
15
|
+
def name(self):
|
|
16
|
+
return self.__name__
|
|
17
|
+
|
|
18
|
+
@classmethod
|
|
19
|
+
def schema(cls):
|
|
20
|
+
cls._schema._set_schema(cls)
|
|
21
|
+
return cls._schema.dump_schema()
|
|
22
|
+
|
|
23
|
+
def json(self):
|
|
24
|
+
return {to_camel(k): self.__dict__[k] for k in self.__dict__ if not k.startswith('_')}
|