hypern 0.3.2__cp312-cp312-win32.whl → 0.3.3__cp312-cp312-win32.whl
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.
- hypern/application.py +73 -13
- hypern/args_parser.py +27 -1
- hypern/config.py +97 -0
- hypern/db/addons/__init__.py +5 -0
- hypern/db/addons/sqlalchemy/__init__.py +71 -0
- hypern/db/sql/__init__.py +13 -179
- hypern/db/sql/field.py +606 -0
- hypern/db/sql/model.py +116 -0
- hypern/db/sql/query.py +879 -0
- hypern/exceptions.py +10 -0
- hypern/hypern.cp312-win32.pyd +0 -0
- hypern/hypern.pyi +33 -0
- hypern/processpool.py +7 -62
- hypern/routing/dispatcher.py +4 -0
- {hypern-0.3.2.dist-info → hypern-0.3.3.dist-info}/METADATA +3 -1
- {hypern-0.3.2.dist-info → hypern-0.3.3.dist-info}/RECORD +27 -22
- /hypern/db/{sql/addons → addons/sqlalchemy/fields}/__init__.py +0 -0
- /hypern/db/{sql/addons → addons/sqlalchemy/fields}/color.py +0 -0
- /hypern/db/{sql/addons → addons/sqlalchemy/fields}/daterange.py +0 -0
- /hypern/db/{sql/addons → addons/sqlalchemy/fields}/datetime.py +0 -0
- /hypern/db/{sql/addons → addons/sqlalchemy/fields}/encrypted.py +0 -0
- /hypern/db/{sql/addons → addons/sqlalchemy/fields}/password.py +0 -0
- /hypern/db/{sql/addons → addons/sqlalchemy/fields}/ts_vector.py +0 -0
- /hypern/db/{sql/addons → addons/sqlalchemy/fields}/unicode.py +0 -0
- /hypern/db/{sql → addons/sqlalchemy}/repository.py +0 -0
- {hypern-0.3.2.dist-info → hypern-0.3.3.dist-info}/WHEEL +0 -0
- {hypern-0.3.2.dist-info → hypern-0.3.3.dist-info}/licenses/LICENSE +0 -0
hypern/db/sql/model.py
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
import re
|
2
|
+
from datetime import date, datetime
|
3
|
+
|
4
|
+
from hypern.config import context_store
|
5
|
+
from hypern.exceptions import OutOfScopeApplicationException
|
6
|
+
from hypern.hypern import get_session_database
|
7
|
+
|
8
|
+
from .field import Field, ForeignKey
|
9
|
+
from .query import QuerySet
|
10
|
+
|
11
|
+
|
12
|
+
class MetaModel(type):
|
13
|
+
def __new__(mcs, name, bases, attrs):
|
14
|
+
# Skip initialization for base Model class
|
15
|
+
if name == "Model" and not bases:
|
16
|
+
return super().__new__(mcs, name, bases, attrs)
|
17
|
+
|
18
|
+
fields = {}
|
19
|
+
table_name = attrs.get("__tablename__")
|
20
|
+
|
21
|
+
# If table name not specified, convert CamelCase to snake_case
|
22
|
+
if not table_name:
|
23
|
+
table_name = re.sub("(?!^)([A-Z])", r"_\1", name).lower()
|
24
|
+
|
25
|
+
# Collect all fields
|
26
|
+
for key, value in list(attrs.items()):
|
27
|
+
if isinstance(value, Field):
|
28
|
+
fields[key] = value
|
29
|
+
value.name = key
|
30
|
+
|
31
|
+
# Store metadata in class
|
32
|
+
attrs["_fields"] = fields
|
33
|
+
attrs["_table_name"] = table_name
|
34
|
+
|
35
|
+
return super().__new__(mcs, name, bases, attrs)
|
36
|
+
|
37
|
+
|
38
|
+
class Model(metaclass=MetaModel):
|
39
|
+
def __init__(self, **kwargs):
|
40
|
+
self._data = {}
|
41
|
+
# Set default values
|
42
|
+
for name, field in self._fields.items():
|
43
|
+
if field.default is not None:
|
44
|
+
self._data[name] = field.default
|
45
|
+
|
46
|
+
# Set provided values
|
47
|
+
for key, value in kwargs.items():
|
48
|
+
if key in self._fields:
|
49
|
+
self._fields[key].validate(value)
|
50
|
+
self._data[key] = value
|
51
|
+
else:
|
52
|
+
raise ValueError(f"Unknown field {key}")
|
53
|
+
|
54
|
+
@classmethod
|
55
|
+
def get_session(cls):
|
56
|
+
try:
|
57
|
+
context_id = context_store.get_context()
|
58
|
+
except Exception:
|
59
|
+
raise OutOfScopeApplicationException("Context not set")
|
60
|
+
return get_session_database(context_id)
|
61
|
+
|
62
|
+
@classmethod
|
63
|
+
def objects(cls) -> QuerySet:
|
64
|
+
return QuerySet(cls)
|
65
|
+
|
66
|
+
@classmethod
|
67
|
+
def table_name(cls) -> str:
|
68
|
+
return cls._table_name
|
69
|
+
|
70
|
+
@classmethod
|
71
|
+
def create_table_sql(cls) -> str:
|
72
|
+
fields_sql = []
|
73
|
+
indexes_sql = []
|
74
|
+
foreign_keys = []
|
75
|
+
|
76
|
+
for name, field in cls._fields.items():
|
77
|
+
fields_sql.append(cls._get_field_sql(name, field))
|
78
|
+
if field.index:
|
79
|
+
indexes_sql.append(cls._get_index_sql(name))
|
80
|
+
if isinstance(field, ForeignKey):
|
81
|
+
foreign_keys.append(cls._get_foreign_key_sql(name, field))
|
82
|
+
|
83
|
+
fields_sql.extend(foreign_keys)
|
84
|
+
joined_fields_sql = ", \n ".join(fields_sql)
|
85
|
+
|
86
|
+
create_table = f"CREATE TABLE {cls.table_name()} (\n {joined_fields_sql} \n"
|
87
|
+
|
88
|
+
return f"{create_table};\n" + ";\n".join(indexes_sql)
|
89
|
+
|
90
|
+
@classmethod
|
91
|
+
def _get_field_sql(cls, name, field) -> str:
|
92
|
+
field_def = [f"{name} {field.sql_type()}"]
|
93
|
+
if field.primary_key:
|
94
|
+
field_def.append("PRIMARY KEY")
|
95
|
+
if not field.null:
|
96
|
+
field_def.append("NOT NULL")
|
97
|
+
if field.unique:
|
98
|
+
field_def.append("UNIQUE")
|
99
|
+
if field.default is not None:
|
100
|
+
if isinstance(field.default, (str, datetime, date)):
|
101
|
+
field_def.append(f"DEFAULT '{field.default}'")
|
102
|
+
else:
|
103
|
+
field_def.append(f"DEFAULT {field.default}")
|
104
|
+
return " ".join(field_def)
|
105
|
+
|
106
|
+
@classmethod
|
107
|
+
def _get_index_sql(cls, name) -> str:
|
108
|
+
return f"CREATE INDEX idx_{cls.table_name()}_{name} ON {cls.table_name()} ({name})"
|
109
|
+
|
110
|
+
@classmethod
|
111
|
+
def _get_foreign_key_sql(cls, name, field) -> str:
|
112
|
+
return f"FOREIGN KEY ({name}) REFERENCES {field.to_model}(id) ON DELETE {field.on_delete} ON UPDATE {field.on_update}"
|
113
|
+
|
114
|
+
def save(self):
|
115
|
+
query_object = QuerySet(self)
|
116
|
+
query_object.bulk_create([self])
|