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.
@@ -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.0
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/surreal-orm-lite
6
- Project-URL: Documentation, https://github.com/EulogySnowfall/surreal-orm-lite
7
- Project-URL: Repository, https://github.com/EulogySnowfall/surreal-orm-lite.git
8
- Project-URL: Issues, https://github.com/EulogySnowfall/surreal-orm-lite/issues
9
- Project-URL: Changelog, https://github.com/EulogySnowfall/surreal-orm-lite/blob/main/CHANGELOG.md
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.0"
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/surreal-orm-lite"
34
- Documentation = "https://github.com/EulogySnowfall/surreal-orm-lite"
35
- Repository = "https://github.com/EulogySnowfall/surreal-orm-lite.git"
36
- Issues = "https://github.com/EulogySnowfall/surreal-orm-lite/issues"
37
- Changelog = "https://github.com/EulogySnowfall/surreal-orm-lite/blob/main/CHANGELOG.md"
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",
@@ -39,9 +39,7 @@ class SurrealDBConnectionManager:
39
39
  @classmethod
40
40
  async def unset_connection(cls) -> None:
41
41
  """
42
- Set the connection kwargs for the SurrealDB instance.
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
- # Établir la connexion
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
- Get the database to use.
292
+ Check if the password is set.
300
293
 
301
- :return: The database to use.
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(SurrealORMError):
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
- Set the ID of the model instance.
79
+ Pre-process data before model validation.
80
+ Extracts the ID from RecordID if present.
80
81
  """
81
- if isinstance(data, dict): # pragma: no cover
82
- if "id" in data and isinstance(data["id"], RecordID):
83
- data["id"] = str(data["id"]).split(":")[1]
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
- self.from_db(record)
100
- return None
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
- obj = self.from_db(record)
135
- if isinstance(obj, type(self)):
136
- self = obj
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
- test = await client.update(thing, data)
152
- return test
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 need either 'id' field or primirary_key in 'model_config'."
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 SurrealDbError("No result found.")
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 SurrealDbError("No result found.")
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 SurrealDbError("No result found.")
375
+ raise SurrealDbNotFoundError("No result found.")
376
376
  return result[0]
377
377
 
378
378
  async def all(self) -> Any:
@@ -2,5 +2,5 @@ import re
2
2
 
3
3
 
4
4
  def remove_quotes_for_variables(query: str) -> str:
5
- # Regex for remove single cote on variables ($)
5
+ # Regex to remove single quotes around variables ($)
6
6
  return re.sub(r"'(\$[a-zA-Z_]\w*)'", r"\1", query)