half-orm 0.18.0__tar.gz → 0.18.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.
Files changed (38) hide show
  1. {half_orm-0.18.0/half_orm.egg-info → half_orm-0.18.2}/PKG-INFO +14 -1
  2. {half_orm-0.18.0 → half_orm-0.18.2}/README.md +13 -0
  3. {half_orm-0.18.0 → half_orm-0.18.2}/half_orm/model.py +8 -3
  4. half_orm-0.18.2/half_orm/null.py +46 -0
  5. half_orm-0.18.2/half_orm/version.txt +1 -0
  6. {half_orm-0.18.0 → half_orm-0.18.2/half_orm.egg-info}/PKG-INFO +14 -1
  7. half_orm-0.18.0/half_orm/null.py +0 -23
  8. half_orm-0.18.0/half_orm/version.txt +0 -1
  9. {half_orm-0.18.0 → half_orm-0.18.2}/AUTHORS +0 -0
  10. {half_orm-0.18.0 → half_orm-0.18.2}/LICENSE +0 -0
  11. {half_orm-0.18.0 → half_orm-0.18.2}/half_orm/__init__.py +0 -0
  12. {half_orm-0.18.0 → half_orm-0.18.2}/half_orm/__main__.py +0 -0
  13. {half_orm-0.18.0 → half_orm-0.18.2}/half_orm/cli.py +0 -0
  14. {half_orm-0.18.0 → half_orm-0.18.2}/half_orm/cli_utils.py +0 -0
  15. {half_orm-0.18.0 → half_orm-0.18.2}/half_orm/field.py +0 -0
  16. {half_orm-0.18.0 → half_orm-0.18.2}/half_orm/field_errors.py +0 -0
  17. {half_orm-0.18.0 → half_orm-0.18.2}/half_orm/fkey.py +0 -0
  18. {half_orm-0.18.0 → half_orm-0.18.2}/half_orm/hotest.py +0 -0
  19. {half_orm-0.18.0 → half_orm-0.18.2}/half_orm/model_errors.py +0 -0
  20. {half_orm-0.18.0 → half_orm-0.18.2}/half_orm/pg_meta.py +0 -0
  21. {half_orm-0.18.0 → half_orm-0.18.2}/half_orm/relation.py +0 -0
  22. {half_orm-0.18.0 → half_orm-0.18.2}/half_orm/relation_errors.py +0 -0
  23. {half_orm-0.18.0 → half_orm-0.18.2}/half_orm/relation_factory.py +0 -0
  24. {half_orm-0.18.0 → half_orm-0.18.2}/half_orm/sql_adapter.py +0 -0
  25. {half_orm-0.18.0 → half_orm-0.18.2}/half_orm/sql_ast.py +0 -0
  26. {half_orm-0.18.0 → half_orm-0.18.2}/half_orm/transaction.py +0 -0
  27. {half_orm-0.18.0 → half_orm-0.18.2}/half_orm/utils.py +0 -0
  28. {half_orm-0.18.0 → half_orm-0.18.2}/half_orm.egg-info/SOURCES.txt +0 -0
  29. {half_orm-0.18.0 → half_orm-0.18.2}/half_orm.egg-info/dependency_links.txt +0 -0
  30. {half_orm-0.18.0 → half_orm-0.18.2}/half_orm.egg-info/entry_points.txt +0 -0
  31. {half_orm-0.18.0 → half_orm-0.18.2}/half_orm.egg-info/requires.txt +0 -0
  32. {half_orm-0.18.0 → half_orm-0.18.2}/half_orm.egg-info/top_level.txt +0 -0
  33. {half_orm-0.18.0 → half_orm-0.18.2}/pyproject.toml +0 -0
  34. {half_orm-0.18.0 → half_orm-0.18.2}/setup.cfg +0 -0
  35. {half_orm-0.18.0 → half_orm-0.18.2}/setup.py +0 -0
  36. {half_orm-0.18.0 → half_orm-0.18.2}/test/test_cli.py +0 -0
  37. {half_orm-0.18.0 → half_orm-0.18.2}/test/test_main.py +0 -0
  38. {half_orm-0.18.0 → half_orm-0.18.2}/test/test_sql_ast.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: half_orm
3
- Version: 0.18.0
3
+ Version: 0.18.2
4
4
  Summary: A simple PostgreSQL to Python mapper.
5
5
  Home-page: https://github.com/half-orm/half-orm
6
6
  Author: Joël Maïzi
@@ -40,6 +40,19 @@ Requires-Dist: importlib-metadata; python_version < "3.8"
40
40
  [![Coverage](https://coveralls.io/repos/github/half-orm/half-orm/badge.svg?branch=main)](https://coveralls.io/github/half-orm/half-orm?branch=main)
41
41
  [![Downloads](https://static.pepy.tech/badge/half_orm)](https://pepy.tech/project/half_orm)
42
42
 
43
+ > ## ⚠️ BREAKING CHANGE in v0.18 — psycopg2 → psycopg 3
44
+ >
45
+ > halfORM 0.18 **drops psycopg2** and requires **[psycopg 3](https://www.psycopg.org/psycopg3/)**.
46
+ >
47
+ > ```bash
48
+ > pip uninstall psycopg2-binary
49
+ > pip install "psycopg[binary]"
50
+ > ```
51
+ >
52
+ > If you use custom psycopg2 adapters in your own code, rewrite them with the
53
+ > psycopg 3 `Dumper`/`Loader` API.
54
+ > See the [full migration notes in CHANGELOG.md](CHANGELOG.md#0180-2026-03-19).
55
+
43
56
  **The PostgreSQL-native ORM that stays out of your way**
44
57
 
45
58
  > halfORM lets you keep your database schema in SQL where it belongs, while giving you the comfort of Python for data manipulation. No migrations, no schema conflicts, no ORM fighting — just PostgreSQL and Python working together.
@@ -8,6 +8,19 @@
8
8
  [![Coverage](https://coveralls.io/repos/github/half-orm/half-orm/badge.svg?branch=main)](https://coveralls.io/github/half-orm/half-orm?branch=main)
9
9
  [![Downloads](https://static.pepy.tech/badge/half_orm)](https://pepy.tech/project/half_orm)
10
10
 
11
+ > ## ⚠️ BREAKING CHANGE in v0.18 — psycopg2 → psycopg 3
12
+ >
13
+ > halfORM 0.18 **drops psycopg2** and requires **[psycopg 3](https://www.psycopg.org/psycopg3/)**.
14
+ >
15
+ > ```bash
16
+ > pip uninstall psycopg2-binary
17
+ > pip install "psycopg[binary]"
18
+ > ```
19
+ >
20
+ > If you use custom psycopg2 adapters in your own code, rewrite them with the
21
+ > psycopg 3 `Dumper`/`Loader` API.
22
+ > See the [full migration notes in CHANGELOG.md](CHANGELOG.md#0180-2026-03-19).
23
+
11
24
  **The PostgreSQL-native ORM that stays out of your way**
12
25
 
13
26
  > halfORM lets you keep your database schema in SQL where it belongs, while giving you the comfort of Python for data manipulation. No migrations, no schema conflicts, no ORM fighting — just PostgreSQL and Python working together.
@@ -151,9 +151,11 @@ class Model:
151
151
  f"(using peer authentication with dbname '{self.__config_file}')")
152
152
  raise psycopg.OperationalError(f"{exc}\n{config_info}") from exc
153
153
  # Register custom type dumpers on this connection
154
- from half_orm.null import Null, NullDumper
154
+ from half_orm.null import Null, NullDumper, FieldDumper
155
+ from half_orm.field import Field
155
156
  from psycopg.types.json import JsonbDumper
156
157
  self.__conn.adapters.register_dumper(Null, NullDumper)
158
+ self.__conn.adapters.register_dumper(Field, FieldDumper)
157
159
  self.__conn.adapters.register_dumper(dict, JsonbDumper)
158
160
  self.__pg_meta = pg_meta.PgMeta(self.__conn, reload)
159
161
  if reload:
@@ -253,9 +255,11 @@ class Model:
253
255
  return
254
256
  self.__aconn = await AsyncConnection.connect(
255
257
  **self._dbinfo, row_factory=dict_row, autocommit=True)
256
- from half_orm.null import Null, NullDumper
258
+ from half_orm.null import Null, NullDumper, FieldDumper
259
+ from half_orm.field import Field
257
260
  from psycopg.types.json import JsonbDumper
258
261
  self.__aconn.adapters.register_dumper(Null, NullDumper)
262
+ self.__aconn.adapters.register_dumper(Field, FieldDumper)
259
263
  self.__aconn.adapters.register_dumper(dict, JsonbDumper)
260
264
 
261
265
  async def adisconnect(self):
@@ -338,7 +342,8 @@ class Model:
338
342
  from half_orm.null import Null
339
343
  if isinstance(values, (list, tuple)):
340
344
  def _unwrap(v):
341
- if isinstance(v, Field):
345
+ # Recursively unwrap nested Field objects (e.g. Relation(col=other.col))
346
+ while isinstance(v, Field):
342
347
  v = v.value
343
348
  if isinstance(v, Null):
344
349
  return None
@@ -0,0 +1,46 @@
1
+ #-*- coding: utf-8 -*-
2
+ # pylint: disable=too-few-public-methods
3
+
4
+ """The null module provides the Null class
5
+ The Null class is used to set NULL value to relation fields.
6
+ """
7
+
8
+ from psycopg.adapt import Dumper
9
+
10
+ __all__ = ['NULL']
11
+
12
+ class Null:
13
+ """The Null class"""
14
+
15
+ class NullDumper(Dumper):
16
+ """Dumper for the Null class — renders as SQL NULL literal."""
17
+ def dump(self, obj):
18
+ return b"NULL"
19
+
20
+ def quote(self, obj):
21
+ return b"NULL"
22
+
23
+ NULL = Null()
24
+
25
+
26
+ class FieldDumper(Dumper):
27
+ """Psycopg 3 Dumper for Field objects.
28
+
29
+ Delegates serialization to the appropriate dumper for ``Field.value``.
30
+ This handles the case where a Field object is passed directly as a query
31
+ parameter (e.g. ``Relation(col=other_relation.col)``).
32
+ """
33
+
34
+ def upgrade(self, obj, format):
35
+ v = obj.value
36
+ if isinstance(v, Null) or v is None:
37
+ return NullDumper(type(obj), self.connection)
38
+ return self
39
+
40
+ def dump(self, obj):
41
+ v = obj.value
42
+ if isinstance(v, Null) or v is None:
43
+ return None
44
+ from psycopg.adapt import Transformer, PyFormat
45
+ tx = Transformer(self.connection)
46
+ return tx.get_dumper(v, PyFormat.AUTO).dump(v)
@@ -0,0 +1 @@
1
+ 0.18.2
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: half_orm
3
- Version: 0.18.0
3
+ Version: 0.18.2
4
4
  Summary: A simple PostgreSQL to Python mapper.
5
5
  Home-page: https://github.com/half-orm/half-orm
6
6
  Author: Joël Maïzi
@@ -40,6 +40,19 @@ Requires-Dist: importlib-metadata; python_version < "3.8"
40
40
  [![Coverage](https://coveralls.io/repos/github/half-orm/half-orm/badge.svg?branch=main)](https://coveralls.io/github/half-orm/half-orm?branch=main)
41
41
  [![Downloads](https://static.pepy.tech/badge/half_orm)](https://pepy.tech/project/half_orm)
42
42
 
43
+ > ## ⚠️ BREAKING CHANGE in v0.18 — psycopg2 → psycopg 3
44
+ >
45
+ > halfORM 0.18 **drops psycopg2** and requires **[psycopg 3](https://www.psycopg.org/psycopg3/)**.
46
+ >
47
+ > ```bash
48
+ > pip uninstall psycopg2-binary
49
+ > pip install "psycopg[binary]"
50
+ > ```
51
+ >
52
+ > If you use custom psycopg2 adapters in your own code, rewrite them with the
53
+ > psycopg 3 `Dumper`/`Loader` API.
54
+ > See the [full migration notes in CHANGELOG.md](CHANGELOG.md#0180-2026-03-19).
55
+
43
56
  **The PostgreSQL-native ORM that stays out of your way**
44
57
 
45
58
  > halfORM lets you keep your database schema in SQL where it belongs, while giving you the comfort of Python for data manipulation. No migrations, no schema conflicts, no ORM fighting — just PostgreSQL and Python working together.
@@ -1,23 +0,0 @@
1
- #-*- coding: utf-8 -*-
2
- # pylint: disable=too-few-public-methods
3
-
4
- """The null module provides the Null class
5
- The Null class is used to set NULL value to relation fields.
6
- """
7
-
8
- from psycopg.adapt import Dumper
9
-
10
- __all__ = ['NULL']
11
-
12
- class Null:
13
- """The Null class"""
14
-
15
- class NullDumper(Dumper):
16
- """Dumper for the Null class — renders as SQL NULL literal."""
17
- def dump(self, obj):
18
- return b"NULL"
19
-
20
- def quote(self, obj):
21
- return b"NULL"
22
-
23
- NULL = Null()
@@ -1 +0,0 @@
1
- 0.18.0
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes