surrealdb-orm 0.1.3__py3-none-any.whl → 0.1.4__py3-none-any.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.
Potentially problematic release.
This version of surrealdb-orm might be problematic. Click here for more details.
- surreal_orm/__init__.py +8 -2
- surreal_orm/model_base.py +92 -119
- surreal_orm/py.typed +0 -0
- surreal_orm/query_set.py +0 -1
- {surrealdb_orm-0.1.3.dist-info → surrealdb_orm-0.1.4.dist-info}/METADATA +2 -2
- surrealdb_orm-0.1.4.dist-info/RECORD +12 -0
- surrealdb_orm-0.1.3.dist-info/RECORD +0 -11
- {surrealdb_orm-0.1.3.dist-info → surrealdb_orm-0.1.4.dist-info}/WHEEL +0 -0
- {surrealdb_orm-0.1.3.dist-info → surrealdb_orm-0.1.4.dist-info}/licenses/LICENSE +0 -0
surreal_orm/__init__.py
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
from .model_base import BaseSurrealModel
|
|
1
|
+
from .model_base import BaseSurrealModel, SurrealConfigDict
|
|
2
2
|
from .connection_manager import SurrealDBConnectionManager
|
|
3
3
|
from .query_set import QuerySet
|
|
4
4
|
from .enum import OrderBy
|
|
5
5
|
|
|
6
|
-
__all__ = [
|
|
6
|
+
__all__ = [
|
|
7
|
+
"SurrealDBConnectionManager",
|
|
8
|
+
"BaseSurrealModel",
|
|
9
|
+
"QuerySet",
|
|
10
|
+
"OrderBy",
|
|
11
|
+
"SurrealConfigDict",
|
|
12
|
+
]
|
surreal_orm/model_base.py
CHANGED
|
@@ -1,129 +1,132 @@
|
|
|
1
|
-
from typing import Any,
|
|
2
|
-
from pydantic import BaseModel,
|
|
1
|
+
from typing import Any, Self
|
|
2
|
+
from pydantic import BaseModel, ConfigDict, model_validator
|
|
3
3
|
from .connection_manager import SurrealDBConnectionManager
|
|
4
4
|
from surrealdb import RecordID, SurrealDbError
|
|
5
5
|
|
|
6
|
-
import warnings
|
|
7
6
|
import logging
|
|
8
7
|
|
|
9
|
-
warnings.filterwarnings("ignore", message="fields may not start with an underscore", category=RuntimeWarning)
|
|
10
8
|
|
|
11
9
|
logger = logging.getLogger(__name__)
|
|
12
10
|
|
|
13
11
|
|
|
12
|
+
class SurrealConfigDict(ConfigDict):
|
|
13
|
+
"""
|
|
14
|
+
SurrealConfigDict is a configuration dictionary for SurrealDB models.
|
|
15
|
+
|
|
16
|
+
Attributes:
|
|
17
|
+
primary_key (str | None): The primary key field name for the model.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
primary_key: str | None
|
|
21
|
+
" The primary key field name for the model. "
|
|
22
|
+
|
|
23
|
+
|
|
14
24
|
class BaseSurrealModel(BaseModel):
|
|
15
25
|
"""
|
|
16
26
|
Base class for models interacting with SurrealDB.
|
|
17
27
|
"""
|
|
18
28
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
object.__setattr__(self, "_table_name", self.__class__.__name__)
|
|
29
|
+
@classmethod
|
|
30
|
+
def get_table_name(cls) -> str:
|
|
31
|
+
"""
|
|
32
|
+
Get the table name for the model.
|
|
33
|
+
"""
|
|
34
|
+
return cls.__name__
|
|
26
35
|
|
|
27
|
-
|
|
36
|
+
@classmethod
|
|
37
|
+
def get_index_primary_key(cls) -> str | None:
|
|
28
38
|
"""
|
|
29
|
-
|
|
30
|
-
otherwise, let the normal mechanism raise AttributeError.
|
|
39
|
+
Get the primary key field name for the model.
|
|
31
40
|
"""
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
41
|
+
if hasattr(cls, "model_config"): # pragma: no cover
|
|
42
|
+
primary_key = cls.model_config.get("primary_key", None)
|
|
43
|
+
if isinstance(primary_key, str):
|
|
44
|
+
return primary_key
|
|
36
45
|
|
|
37
|
-
|
|
38
|
-
return f"{self._data}"
|
|
46
|
+
return None
|
|
39
47
|
|
|
40
|
-
def
|
|
48
|
+
def get_id(self) -> None | str | RecordID:
|
|
41
49
|
"""
|
|
42
|
-
|
|
43
|
-
with the new value.
|
|
50
|
+
Get the ID of the model instance.
|
|
44
51
|
"""
|
|
45
|
-
if
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
if hasattr(self, "id"):
|
|
53
|
+
id_value = getattr(self, "id")
|
|
54
|
+
return str(id_value) if id_value is not None else None
|
|
55
|
+
|
|
56
|
+
if hasattr(self, "model_config"):
|
|
57
|
+
primary_key = self.model_config.get("primary_key", None)
|
|
58
|
+
if isinstance(primary_key, str) and hasattr(self, primary_key):
|
|
59
|
+
primary_key_value = getattr(self, primary_key)
|
|
60
|
+
return str(primary_key_value) if primary_key_value is not None else None
|
|
61
|
+
|
|
62
|
+
return None # pragma: no cover
|
|
53
63
|
|
|
54
64
|
@classmethod
|
|
55
|
-
def from_db(cls, record: dict | list) ->
|
|
65
|
+
def from_db(cls, record: dict | list) -> Self | list[Self]:
|
|
56
66
|
"""
|
|
57
67
|
Create an instance from a SurrealDB record.
|
|
58
68
|
"""
|
|
59
69
|
if isinstance(record, list):
|
|
60
|
-
return [cls.from_db(rs) for rs in record]
|
|
61
|
-
|
|
62
|
-
record = cls.__set_data(record)
|
|
70
|
+
return [cls.from_db(rs) for rs in record] # type: ignore
|
|
63
71
|
|
|
64
72
|
return cls(**record)
|
|
65
73
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
"""
|
|
70
|
-
data_set = {key: value for key, value in self._data.items() if not key.startswith("_") and key != "id"}
|
|
71
|
-
return data_set
|
|
72
|
-
|
|
73
|
-
def show_config(self) -> ConfigDict:
|
|
74
|
-
# Accès depuis une méthode d'instance
|
|
75
|
-
return type(self).model_config
|
|
76
|
-
|
|
77
|
-
def get_id(self) -> str | RecordID | None:
|
|
78
|
-
if "id" in self._data:
|
|
79
|
-
return self._data["id"]
|
|
80
|
-
|
|
81
|
-
config = self.show_config()
|
|
82
|
-
pk_field = config.get("primary_key", "id")
|
|
83
|
-
return self._data.get(pk_field, None)
|
|
84
|
-
|
|
85
|
-
@staticmethod
|
|
86
|
-
def __set_data(data: Any) -> dict:
|
|
74
|
+
@model_validator(mode="before")
|
|
75
|
+
@classmethod
|
|
76
|
+
def set_data(cls, data: Any) -> Any:
|
|
87
77
|
"""
|
|
88
|
-
Set the model instance
|
|
78
|
+
Set the ID of the model instance.
|
|
89
79
|
"""
|
|
90
80
|
if isinstance(data, dict): # pragma: no cover
|
|
91
|
-
if "id" in data and isinstance(data["id"], RecordID):
|
|
81
|
+
if "id" in data and isinstance(data["id"], RecordID):
|
|
92
82
|
data["id"] = str(data["id"]).split(":")[1]
|
|
93
83
|
return data
|
|
94
84
|
|
|
95
|
-
raise TypeError("Data must be a dictionary.") # pragma: no cover
|
|
96
|
-
|
|
97
85
|
async def refresh(self) -> None:
|
|
98
86
|
"""
|
|
99
87
|
Refresh the model instance from the database.
|
|
100
88
|
"""
|
|
89
|
+
if not self.get_id():
|
|
90
|
+
raise SurrealDbError("Can't refresh data, not recorded yet.") # pragma: no cover
|
|
91
|
+
|
|
101
92
|
client = await SurrealDBConnectionManager.get_client()
|
|
102
|
-
record =
|
|
93
|
+
record = await client.select(f"{self.get_table_name()}:{self.get_id()}")
|
|
103
94
|
|
|
104
|
-
|
|
105
|
-
|
|
95
|
+
if record is None:
|
|
96
|
+
raise SurrealDbError("Can't refresh data, no record found.") # pragma: no cover
|
|
106
97
|
|
|
107
|
-
self.
|
|
98
|
+
self.from_db(record)
|
|
99
|
+
return None
|
|
108
100
|
|
|
109
101
|
async def save(self) -> Self:
|
|
110
102
|
"""
|
|
111
103
|
Save the model instance to the database.
|
|
112
104
|
"""
|
|
113
105
|
client = await SurrealDBConnectionManager.get_client()
|
|
114
|
-
|
|
115
|
-
data = self.to_db_dict()
|
|
106
|
+
data = self.model_dump(exclude={"id"})
|
|
116
107
|
id = self.get_id()
|
|
117
|
-
|
|
118
|
-
|
|
108
|
+
table = self.get_table_name()
|
|
109
|
+
|
|
110
|
+
if id is not None:
|
|
111
|
+
thing = f"{table}:{id}"
|
|
119
112
|
await client.create(thing, data)
|
|
120
113
|
return self
|
|
114
|
+
|
|
121
115
|
# Auto-generate the ID
|
|
122
|
-
record = await client.create(
|
|
123
|
-
if isinstance(record, dict): # pragma: no cover
|
|
124
|
-
self._data = self.__set_data(record)
|
|
116
|
+
record = await client.create(table, data) # pragma: no cover
|
|
125
117
|
|
|
126
|
-
|
|
118
|
+
if isinstance(record, list):
|
|
119
|
+
raise SurrealDbError("Can't save data, multiple records returned.") # pragma: no cover
|
|
120
|
+
|
|
121
|
+
if record is None:
|
|
122
|
+
raise SurrealDbError("Can't save data, no record returned.") # pragma: no cover
|
|
123
|
+
|
|
124
|
+
obj = self.from_db(record)
|
|
125
|
+
if isinstance(obj, type(self)):
|
|
126
|
+
self = obj
|
|
127
|
+
return self
|
|
128
|
+
|
|
129
|
+
raise SurrealDbError("Can't save data, no record returned.") # pragma: no cover
|
|
127
130
|
|
|
128
131
|
async def update(self) -> Any:
|
|
129
132
|
"""
|
|
@@ -131,12 +134,12 @@ class BaseSurrealModel(BaseModel):
|
|
|
131
134
|
"""
|
|
132
135
|
client = await SurrealDBConnectionManager.get_client()
|
|
133
136
|
|
|
134
|
-
data = self.
|
|
137
|
+
data = self.model_dump(exclude={"id"})
|
|
135
138
|
id = self.get_id()
|
|
136
|
-
if id:
|
|
137
|
-
thing = f"{self.
|
|
138
|
-
|
|
139
|
-
|
|
139
|
+
if id is not None:
|
|
140
|
+
thing = f"{self.__class__.__name__}:{id}"
|
|
141
|
+
test = await client.update(thing, data)
|
|
142
|
+
return test
|
|
140
143
|
raise SurrealDbError("Can't update data, no id found.")
|
|
141
144
|
|
|
142
145
|
async def merge(self, **data: Any) -> Any:
|
|
@@ -149,7 +152,7 @@ class BaseSurrealModel(BaseModel):
|
|
|
149
152
|
|
|
150
153
|
id = self.get_id()
|
|
151
154
|
if id:
|
|
152
|
-
thing = f"{self.
|
|
155
|
+
thing = f"{self.get_table_name()}:{id}"
|
|
153
156
|
|
|
154
157
|
await client.merge(thing, data_set)
|
|
155
158
|
await self.refresh()
|
|
@@ -166,7 +169,7 @@ class BaseSurrealModel(BaseModel):
|
|
|
166
169
|
|
|
167
170
|
id = self.get_id()
|
|
168
171
|
|
|
169
|
-
thing = f"{self.
|
|
172
|
+
thing = f"{self.get_table_name()}:{id}"
|
|
170
173
|
|
|
171
174
|
deleted = await client.delete(thing)
|
|
172
175
|
|
|
@@ -174,50 +177,20 @@ class BaseSurrealModel(BaseModel):
|
|
|
174
177
|
raise SurrealDbError(f"Can't delete Record id -> '{id}' not found!")
|
|
175
178
|
|
|
176
179
|
logger.info(f"Record deleted -> {deleted}.")
|
|
177
|
-
self._data = {}
|
|
178
180
|
del self
|
|
179
181
|
|
|
180
|
-
@
|
|
181
|
-
def
|
|
182
|
-
"""
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
# Retrieve the annotations declared in the class (e.g., ModelTest)
|
|
190
|
-
hints: dict[str, Any] = {}
|
|
191
|
-
config_dict = None
|
|
192
|
-
for base in reversed(cls.__mro__): # To capture all annotations
|
|
193
|
-
hints.update(getattr(base, "__annotations__", {}))
|
|
194
|
-
# Optionally, check if the class has 'model_config' to inject it
|
|
195
|
-
if hasattr(base, "model_config"):
|
|
196
|
-
config_dict = getattr(base, "model_config")
|
|
197
|
-
|
|
198
|
-
# Create the Pydantic model (dynamically)
|
|
199
|
-
fields = {}
|
|
200
|
-
for field_name, field_type in hints.items():
|
|
201
|
-
# Read the object already defined in the class (if Field(...))
|
|
202
|
-
default_val = getattr(cls, field_name, ...)
|
|
203
|
-
fields[field_name] = (field_type, default_val)
|
|
204
|
-
|
|
205
|
-
# Create model
|
|
206
|
-
if config_dict:
|
|
207
|
-
pyd_model = create_model( # type: ignore
|
|
208
|
-
f"{cls.__name__}PydModel",
|
|
209
|
-
__config__=config_dict,
|
|
210
|
-
**fields,
|
|
211
|
-
)
|
|
212
|
-
else:
|
|
213
|
-
pyd_model = create_model( # type: ignore
|
|
214
|
-
f"{cls.__name__}PydModel",
|
|
215
|
-
__base__=BaseModel,
|
|
216
|
-
**fields,
|
|
182
|
+
@model_validator(mode="after")
|
|
183
|
+
def check_config(self) -> Self:
|
|
184
|
+
"""
|
|
185
|
+
Check the model configuration.
|
|
186
|
+
"""
|
|
187
|
+
|
|
188
|
+
if not self.get_index_primary_key() and not hasattr(self, "id"):
|
|
189
|
+
raise SurrealDbError( # pragma: no cover
|
|
190
|
+
"Can't create model, the model need either 'id' field or primirary_key in 'model_config'."
|
|
217
191
|
)
|
|
218
192
|
|
|
219
|
-
|
|
220
|
-
return pyd_model
|
|
193
|
+
return self
|
|
221
194
|
|
|
222
195
|
@classmethod
|
|
223
196
|
def objects(cls) -> Any:
|
surreal_orm/py.typed
ADDED
|
File without changes
|
surreal_orm/query_set.py
CHANGED
|
@@ -301,7 +301,6 @@ class QuerySet:
|
|
|
301
301
|
results = await self._execute_query(query)
|
|
302
302
|
try:
|
|
303
303
|
data = cast(dict, results[0])
|
|
304
|
-
|
|
305
304
|
return self.model.from_db(data["result"])
|
|
306
305
|
except ValidationError as e:
|
|
307
306
|
logger.info(f"Pydantic invalid format for the class, returning dict value: {e}")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: surrealdb-orm
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: SurrealDB ORM as 'DJango style' for Python with async support. Works with pydantic validation.
|
|
5
5
|
Project-URL: Homepage, https://github.com/EulogySnowfall/SurrealDB-ORM
|
|
6
6
|
Project-URL: Documentation, https://github.com/EulogySnowfall/SurrealDB-ORM
|
|
@@ -70,7 +70,7 @@ Description-Content-Type: text/markdown
|
|
|
70
70
|
|
|
71
71
|
## ✅ Version
|
|
72
72
|
|
|
73
|
-
Alpha 0.1.
|
|
73
|
+
Alpha 0.1.4
|
|
74
74
|
|
|
75
75
|
---
|
|
76
76
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
surreal_orm/__init__.py,sha256=p2dnNi1Ar0FNrLlC7oHtYiUrrdYwQKt--72_-omCElk,306
|
|
2
|
+
surreal_orm/connection_manager.py,sha256=kRAK6qhkKRVbhTjWZV6LaOGiH_jClwQ3zzmjca1A5Ro,8561
|
|
3
|
+
surreal_orm/constants.py,sha256=CLavEca1M6cLJLqVl4l4KoE-cBrgVQNsuGxW9zGJBmg,429
|
|
4
|
+
surreal_orm/enum.py,sha256=kR-vzkHqnqy9YaYOvWTwAHdl2-WCzPcSEch-YTyJv1Y,158
|
|
5
|
+
surreal_orm/model_base.py,sha256=zz6y8TQavk0XvLhunzQflJpPG85FizeCR-mAy-LHlK8,6082
|
|
6
|
+
surreal_orm/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
surreal_orm/query_set.py,sha256=VD8F2vKv5_uIXRCV_0HCx6lnarF-Qx3x8MYJq2LH78U,18155
|
|
8
|
+
surreal_orm/utils.py,sha256=mni_dTtb4VGTdge8eWSZpBw5xoWci2m-XThKFHYPKTo,171
|
|
9
|
+
surrealdb_orm-0.1.4.dist-info/METADATA,sha256=AFDw-vOKASG0mGa73Zo9CcaQKe-E-ocia3tOUJdcELY,5980
|
|
10
|
+
surrealdb_orm-0.1.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
11
|
+
surrealdb_orm-0.1.4.dist-info/licenses/LICENSE,sha256=TO3Ub0nPPx5NxwjsDuBAu3RBdBLmdDybqC5dem4oGts,1074
|
|
12
|
+
surrealdb_orm-0.1.4.dist-info/RECORD,,
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
surreal_orm/__init__.py,sha256=RNoDt0Gt7_jTjzxzXGPXKUqe7EnCdt31b35tnA-JcOM,243
|
|
2
|
-
surreal_orm/connection_manager.py,sha256=kRAK6qhkKRVbhTjWZV6LaOGiH_jClwQ3zzmjca1A5Ro,8561
|
|
3
|
-
surreal_orm/constants.py,sha256=CLavEca1M6cLJLqVl4l4KoE-cBrgVQNsuGxW9zGJBmg,429
|
|
4
|
-
surreal_orm/enum.py,sha256=kR-vzkHqnqy9YaYOvWTwAHdl2-WCzPcSEch-YTyJv1Y,158
|
|
5
|
-
surreal_orm/model_base.py,sha256=U9ZJeOS75uJXMvhKTNy8I2QDXMxoF5eVUkQe-vesggk,7358
|
|
6
|
-
surreal_orm/query_set.py,sha256=ng-jTFWiUpxPJH-KC7SNxZ2PwmciCnkOifOWa7A2KEs,18156
|
|
7
|
-
surreal_orm/utils.py,sha256=mni_dTtb4VGTdge8eWSZpBw5xoWci2m-XThKFHYPKTo,171
|
|
8
|
-
surrealdb_orm-0.1.3.dist-info/METADATA,sha256=T9tXMFp3th-r4FMnFQt2s8z4Pz5zCs0_KoE33k64-gU,5980
|
|
9
|
-
surrealdb_orm-0.1.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
10
|
-
surrealdb_orm-0.1.3.dist-info/licenses/LICENSE,sha256=TO3Ub0nPPx5NxwjsDuBAu3RBdBLmdDybqC5dem4oGts,1074
|
|
11
|
-
surrealdb_orm-0.1.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|