surreal-orm-lite 0.2.0__tar.gz → 0.2.2__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.
- {surreal_orm_lite-0.2.0 → surreal_orm_lite-0.2.2}/CHANGELOG.md +33 -0
- {surreal_orm_lite-0.2.0 → surreal_orm_lite-0.2.2}/PKG-INFO +6 -6
- {surreal_orm_lite-0.2.0 → surreal_orm_lite-0.2.2}/pyproject.toml +6 -6
- {surreal_orm_lite-0.2.0 → surreal_orm_lite-0.2.2}/src/surreal_orm_lite/__init__.py +3 -0
- {surreal_orm_lite-0.2.0 → surreal_orm_lite-0.2.2}/src/surreal_orm_lite/connection_manager.py +4 -11
- {surreal_orm_lite-0.2.0 → surreal_orm_lite-0.2.2}/src/surreal_orm_lite/exceptions.py +2 -1
- {surreal_orm_lite-0.2.0 → surreal_orm_lite-0.2.2}/src/surreal_orm_lite/model_base.py +28 -14
- {surreal_orm_lite-0.2.0 → surreal_orm_lite-0.2.2}/src/surreal_orm_lite/query_set.py +8 -8
- {surreal_orm_lite-0.2.0 → surreal_orm_lite-0.2.2}/src/surreal_orm_lite/utils.py +1 -1
- {surreal_orm_lite-0.2.0 → surreal_orm_lite-0.2.2}/.gitignore +0 -0
- {surreal_orm_lite-0.2.0 → surreal_orm_lite-0.2.2}/LICENSE +0 -0
- {surreal_orm_lite-0.2.0 → surreal_orm_lite-0.2.2}/Makefile +0 -0
- {surreal_orm_lite-0.2.0 → surreal_orm_lite-0.2.2}/README.md +0 -0
- {surreal_orm_lite-0.2.0 → surreal_orm_lite-0.2.2}/src/__init__.py +0 -0
- {surreal_orm_lite-0.2.0 → surreal_orm_lite-0.2.2}/src/surreal_orm_lite/constants.py +0 -0
- {surreal_orm_lite-0.2.0 → surreal_orm_lite-0.2.2}/src/surreal_orm_lite/enum.py +0 -0
- {surreal_orm_lite-0.2.0 → surreal_orm_lite-0.2.2}/src/surreal_orm_lite/py.typed +0 -0
|
@@ -5,6 +5,39 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.2.2] - 2026-02-05
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Corrected project URLs in package metadata (case sensitivity)
|
|
13
|
+
|
|
14
|
+
## [0.2.1] - 2026-02-04
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Fixed `refresh()` method not updating the model instance
|
|
19
|
+
- Fixed `refresh()` not handling SDK 1.0.8 list responses
|
|
20
|
+
- Fixed `save()` not updating instance with auto-generated ID
|
|
21
|
+
- Fixed SQL query order: `ORDER BY` now comes before `LIMIT/START` (SurrealDB requirement)
|
|
22
|
+
- Fixed `set_data` validator not always returning data
|
|
23
|
+
- Fixed typo in error message: `primirary_key` → `primary_key`
|
|
24
|
+
- Removed ineffective `del self` in `delete()` method
|
|
25
|
+
- Fixed dead test `failed_model_validation` that was never executed
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- `SurrealDbNotFoundError` now inherits from `SurrealDbError` for backward compatibility
|
|
30
|
+
- Test database connection now configurable via `SURREALDB_HOST` and `SURREALDB_PORT` environment variables
|
|
31
|
+
- Improved docstrings for `unset_connection()` and `is_password_set()`
|
|
32
|
+
- Translated French comments to English in `connection_manager.py`
|
|
33
|
+
- Renamed variable `test` → `result` in `update()` method
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
|
|
37
|
+
- Added `codecov.yml` configuration (disabled patch coverage check)
|
|
38
|
+
- Added test for `save()` with auto-generated ID
|
|
39
|
+
- Added test for `contains` lookup operator
|
|
40
|
+
|
|
8
41
|
## [0.2.0] - 2026-02-02
|
|
9
42
|
|
|
10
43
|
### Added
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: surreal-orm-lite
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Lightweight Django-style ORM for SurrealDB using the official Python SDK. Async support with Pydantic validation.
|
|
5
|
-
Project-URL: Homepage, https://github.com/EulogySnowfall/
|
|
6
|
-
Project-URL: Documentation, https://github.com/EulogySnowfall/
|
|
7
|
-
Project-URL: Repository, https://github.com/EulogySnowfall/
|
|
8
|
-
Project-URL: Issues, https://github.com/EulogySnowfall/
|
|
9
|
-
Project-URL: Changelog, https://github.com/EulogySnowfall/
|
|
5
|
+
Project-URL: Homepage, https://github.com/EulogySnowfall/SurrealDB-ORM-lite
|
|
6
|
+
Project-URL: Documentation, https://github.com/EulogySnowfall/SurrealDB-ORM-lite
|
|
7
|
+
Project-URL: Repository, https://github.com/EulogySnowfall/SurrealDB-ORM-lite.git
|
|
8
|
+
Project-URL: Issues, https://github.com/EulogySnowfall/SurrealDB-ORM-lite/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/EulogySnowfall/SurrealDB-ORM-lite/blob/main/CHANGELOG.md
|
|
10
10
|
Author-email: Yannick Croteau <croteau.yannick@gmail.com>
|
|
11
11
|
License: # MIT License
|
|
12
12
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "surreal-orm-lite"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.2"
|
|
4
4
|
description = "Lightweight Django-style ORM for SurrealDB using the official Python SDK. Async support with Pydantic validation."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -30,11 +30,11 @@ dependencies = [
|
|
|
30
30
|
]
|
|
31
31
|
|
|
32
32
|
[project.urls]
|
|
33
|
-
Homepage = "https://github.com/EulogySnowfall/
|
|
34
|
-
Documentation = "https://github.com/EulogySnowfall/
|
|
35
|
-
Repository = "https://github.com/EulogySnowfall/
|
|
36
|
-
Issues = "https://github.com/EulogySnowfall/
|
|
37
|
-
Changelog = "https://github.com/EulogySnowfall/
|
|
33
|
+
Homepage = "https://github.com/EulogySnowfall/SurrealDB-ORM-lite"
|
|
34
|
+
Documentation = "https://github.com/EulogySnowfall/SurrealDB-ORM-lite"
|
|
35
|
+
Repository = "https://github.com/EulogySnowfall/SurrealDB-ORM-lite.git"
|
|
36
|
+
Issues = "https://github.com/EulogySnowfall/SurrealDB-ORM-lite/issues"
|
|
37
|
+
Changelog = "https://github.com/EulogySnowfall/SurrealDB-ORM-lite/blob/main/CHANGELOG.md"
|
|
38
38
|
|
|
39
39
|
[tool.setuptools]
|
|
40
40
|
packages = ["src/surreal_orm_lite"]
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
__version__ = "0.2.2"
|
|
2
|
+
|
|
1
3
|
from .connection_manager import SurrealDBConnectionManager
|
|
2
4
|
from .enum import OrderBy
|
|
3
5
|
from .exceptions import (
|
|
@@ -11,6 +13,7 @@ from .model_base import BaseSurrealModel, SurrealConfigDict
|
|
|
11
13
|
from .query_set import QuerySet
|
|
12
14
|
|
|
13
15
|
__all__ = [
|
|
16
|
+
"__version__",
|
|
14
17
|
"SurrealDBConnectionManager",
|
|
15
18
|
"BaseSurrealModel",
|
|
16
19
|
"QuerySet",
|
{surreal_orm_lite-0.2.0 → surreal_orm_lite-0.2.2}/src/surreal_orm_lite/connection_manager.py
RENAMED
|
@@ -39,9 +39,7 @@ class SurrealDBConnectionManager:
|
|
|
39
39
|
@classmethod
|
|
40
40
|
async def unset_connection(cls) -> None:
|
|
41
41
|
"""
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
:param kwargs: The connection kwargs for the SurrealDB instance.
|
|
42
|
+
Clear all connection settings and close the connection.
|
|
45
43
|
"""
|
|
46
44
|
cls.__url = None
|
|
47
45
|
cls.__user = None
|
|
@@ -80,7 +78,7 @@ class SurrealDBConnectionManager:
|
|
|
80
78
|
assert cls.__user is not None
|
|
81
79
|
assert cls.__password is not None
|
|
82
80
|
|
|
83
|
-
#
|
|
81
|
+
# Establish the connection
|
|
84
82
|
try:
|
|
85
83
|
url = cls.__url
|
|
86
84
|
_client = AsyncSurreal(url)
|
|
@@ -107,8 +105,6 @@ class SurrealDBConnectionManager:
|
|
|
107
105
|
"""
|
|
108
106
|
Close the connection to the SurrealDB instance.
|
|
109
107
|
"""
|
|
110
|
-
# Fermer la connexion
|
|
111
|
-
|
|
112
108
|
if cls.__client is None:
|
|
113
109
|
return
|
|
114
110
|
|
|
@@ -121,9 +117,7 @@ class SurrealDBConnectionManager:
|
|
|
121
117
|
"""
|
|
122
118
|
Reconnect to the SurrealDB instance.
|
|
123
119
|
"""
|
|
124
|
-
# Fermer la connexion
|
|
125
120
|
await cls.close_connection()
|
|
126
|
-
# Établir la connexion
|
|
127
121
|
return await cls.get_client()
|
|
128
122
|
|
|
129
123
|
@classmethod
|
|
@@ -133,7 +127,6 @@ class SurrealDBConnectionManager:
|
|
|
133
127
|
|
|
134
128
|
:return: True if the connection is valid, False otherwise.
|
|
135
129
|
"""
|
|
136
|
-
# Valider la connexion
|
|
137
130
|
try:
|
|
138
131
|
await cls.reconnect()
|
|
139
132
|
return True
|
|
@@ -296,9 +289,9 @@ class SurrealDBConnectionManager:
|
|
|
296
289
|
@classmethod
|
|
297
290
|
def is_password_set(cls) -> bool:
|
|
298
291
|
"""
|
|
299
|
-
|
|
292
|
+
Check if the password is set.
|
|
300
293
|
|
|
301
|
-
:return:
|
|
294
|
+
:return: True if the password is set, False otherwise.
|
|
302
295
|
"""
|
|
303
296
|
return cls.__password is not None
|
|
304
297
|
|
|
@@ -44,11 +44,12 @@ class SurrealDbValidationError(SurrealORMError):
|
|
|
44
44
|
pass
|
|
45
45
|
|
|
46
46
|
|
|
47
|
-
class SurrealDbNotFoundError(
|
|
47
|
+
class SurrealDbNotFoundError(SurrealDbError):
|
|
48
48
|
"""
|
|
49
49
|
Not found error.
|
|
50
50
|
|
|
51
51
|
Raised when a requested record or resource is not found.
|
|
52
|
+
Inherits from SurrealDbError for backward compatibility.
|
|
52
53
|
"""
|
|
53
54
|
|
|
54
55
|
pass
|
|
@@ -76,12 +76,12 @@ class BaseSurrealModel(BaseModel):
|
|
|
76
76
|
@classmethod
|
|
77
77
|
def set_data(cls, data: Any) -> Any:
|
|
78
78
|
"""
|
|
79
|
-
|
|
79
|
+
Pre-process data before model validation.
|
|
80
|
+
Extracts the ID from RecordID if present.
|
|
80
81
|
"""
|
|
81
|
-
if isinstance(data, dict)
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
return data
|
|
82
|
+
if isinstance(data, dict) and "id" in data and isinstance(data["id"], RecordID):
|
|
83
|
+
data["id"] = str(data["id"]).split(":")[1]
|
|
84
|
+
return data
|
|
85
85
|
|
|
86
86
|
async def refresh(self) -> None:
|
|
87
87
|
"""
|
|
@@ -96,8 +96,19 @@ class BaseSurrealModel(BaseModel):
|
|
|
96
96
|
if record is None:
|
|
97
97
|
raise SurrealDbError("Can't refresh data, no record found.") # pragma: no cover
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
# SDK 1.0.8 returns a list even for single record select
|
|
100
|
+
if isinstance(record, list):
|
|
101
|
+
if len(record) == 0:
|
|
102
|
+
raise SurrealDbError("Can't refresh data, no record found.") # pragma: no cover
|
|
103
|
+
record = record[0]
|
|
104
|
+
|
|
105
|
+
# Update current instance with refreshed data
|
|
106
|
+
if isinstance(record, dict):
|
|
107
|
+
for key, value in record.items():
|
|
108
|
+
if key == "id" and isinstance(value, RecordID):
|
|
109
|
+
value = str(value).split(":")[1]
|
|
110
|
+
if hasattr(self, key):
|
|
111
|
+
object.__setattr__(self, key, value)
|
|
101
112
|
|
|
102
113
|
async def save(self) -> Self:
|
|
103
114
|
"""
|
|
@@ -131,9 +142,13 @@ class BaseSurrealModel(BaseModel):
|
|
|
131
142
|
if record is None:
|
|
132
143
|
raise SurrealDbError("Can't save data, no record returned.") # pragma: no cover
|
|
133
144
|
|
|
134
|
-
|
|
135
|
-
if isinstance(
|
|
136
|
-
|
|
145
|
+
# Update current instance with the auto-generated ID
|
|
146
|
+
if isinstance(record, dict):
|
|
147
|
+
for key, value in record.items():
|
|
148
|
+
if key == "id" and isinstance(value, RecordID):
|
|
149
|
+
value = str(value).split(":")[1]
|
|
150
|
+
if hasattr(self, key):
|
|
151
|
+
object.__setattr__(self, key, value)
|
|
137
152
|
return self
|
|
138
153
|
|
|
139
154
|
raise SurrealDbError("Can't save data, no record returned.") # pragma: no cover
|
|
@@ -148,8 +163,8 @@ class BaseSurrealModel(BaseModel):
|
|
|
148
163
|
id = self.get_id()
|
|
149
164
|
if id is not None:
|
|
150
165
|
thing = f"{self.__class__.__name__}:{id}"
|
|
151
|
-
|
|
152
|
-
return
|
|
166
|
+
result = await client.update(thing, data)
|
|
167
|
+
return result
|
|
153
168
|
raise SurrealDbError("Can't update data, no id found.")
|
|
154
169
|
|
|
155
170
|
async def merge(self, **data: Any) -> Any:
|
|
@@ -187,7 +202,6 @@ class BaseSurrealModel(BaseModel):
|
|
|
187
202
|
raise SurrealDbError(f"Can't delete Record id -> '{id}' not found!")
|
|
188
203
|
|
|
189
204
|
logger.info(f"Record deleted -> {deleted}.")
|
|
190
|
-
del self
|
|
191
205
|
|
|
192
206
|
@model_validator(mode="after")
|
|
193
207
|
def check_config(self) -> Self:
|
|
@@ -197,7 +211,7 @@ class BaseSurrealModel(BaseModel):
|
|
|
197
211
|
|
|
198
212
|
if not self.get_index_primary_key() and not hasattr(self, "id"):
|
|
199
213
|
raise SurrealDbError( # pragma: no cover
|
|
200
|
-
"Can't create model, the model
|
|
214
|
+
"Can't create model, the model needs either 'id' field or primary_key in 'model_config'."
|
|
201
215
|
)
|
|
202
216
|
|
|
203
217
|
return self
|
|
@@ -6,7 +6,7 @@ from pydantic_core import ValidationError
|
|
|
6
6
|
from . import BaseSurrealModel, SurrealDBConnectionManager
|
|
7
7
|
from .constants import LOOKUP_OPERATORS
|
|
8
8
|
from .enum import OrderBy
|
|
9
|
-
from .exceptions import SurrealDbError
|
|
9
|
+
from .exceptions import SurrealDbError, SurrealDbNotFoundError
|
|
10
10
|
from .utils import remove_quotes_for_variables
|
|
11
11
|
|
|
12
12
|
logger = logging.getLogger(__name__)
|
|
@@ -261,6 +261,10 @@ class QuerySet:
|
|
|
261
261
|
if where_clauses:
|
|
262
262
|
query += " WHERE " + " AND ".join(where_clauses)
|
|
263
263
|
|
|
264
|
+
# Append ORDER BY if set (must come before LIMIT/START in SurrealDB)
|
|
265
|
+
if self._order_by:
|
|
266
|
+
query += f" ORDER BY {self._order_by}"
|
|
267
|
+
|
|
264
268
|
# Append LIMIT if set
|
|
265
269
|
if self._limit is not None:
|
|
266
270
|
query += f" LIMIT {self._limit}"
|
|
@@ -269,10 +273,6 @@ class QuerySet:
|
|
|
269
273
|
if self._offset is not None:
|
|
270
274
|
query += f" START {self._offset}"
|
|
271
275
|
|
|
272
|
-
# Append ORDER BY if set
|
|
273
|
-
if self._order_by:
|
|
274
|
-
query += f" ORDER BY {self._order_by}"
|
|
275
|
-
|
|
276
276
|
query += ";"
|
|
277
277
|
return query
|
|
278
278
|
|
|
@@ -333,7 +333,7 @@ class QuerySet:
|
|
|
333
333
|
if results:
|
|
334
334
|
return results[0]
|
|
335
335
|
|
|
336
|
-
raise
|
|
336
|
+
raise SurrealDbNotFoundError("No result found.")
|
|
337
337
|
|
|
338
338
|
async def get(self, id_item: Any = None) -> Any:
|
|
339
339
|
"""
|
|
@@ -363,7 +363,7 @@ class QuerySet:
|
|
|
363
363
|
# SDK 1.0.8 returns a list even for single record select
|
|
364
364
|
if isinstance(data, list):
|
|
365
365
|
if len(data) == 0:
|
|
366
|
-
raise
|
|
366
|
+
raise SurrealDbNotFoundError("No result found.")
|
|
367
367
|
data = data[0]
|
|
368
368
|
return self.model.from_db(data)
|
|
369
369
|
else:
|
|
@@ -372,7 +372,7 @@ class QuerySet:
|
|
|
372
372
|
raise SurrealDbError("More than one result found.")
|
|
373
373
|
|
|
374
374
|
if len(result) == 0:
|
|
375
|
-
raise
|
|
375
|
+
raise SurrealDbNotFoundError("No result found.")
|
|
376
376
|
return result[0]
|
|
377
377
|
|
|
378
378
|
async def all(self) -> Any:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|