python-mapper 0.3.0__tar.gz → 0.3.1__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 (23) hide show
  1. {python_mapper-0.3.0/src/python_mapper.egg-info → python_mapper-0.3.1}/PKG-INFO +41 -6
  2. {python_mapper-0.3.0 → python_mapper-0.3.1}/README.md +40 -5
  3. {python_mapper-0.3.0 → python_mapper-0.3.1}/pyproject.toml +1 -1
  4. {python_mapper-0.3.0 → python_mapper-0.3.1/src/python_mapper.egg-info}/PKG-INFO +41 -6
  5. {python_mapper-0.3.0 → python_mapper-0.3.1}/LICENSE +0 -0
  6. {python_mapper-0.3.0 → python_mapper-0.3.1}/setup.cfg +0 -0
  7. {python_mapper-0.3.0 → python_mapper-0.3.1}/src/python_mapper/__init__.py +0 -0
  8. {python_mapper-0.3.0 → python_mapper-0.3.1}/src/python_mapper/base.py +0 -0
  9. {python_mapper-0.3.0 → python_mapper-0.3.1}/src/python_mapper/compiler.py +0 -0
  10. {python_mapper-0.3.0 → python_mapper-0.3.1}/src/python_mapper/database.py +0 -0
  11. {python_mapper-0.3.0 → python_mapper-0.3.1}/src/python_mapper/errors.py +0 -0
  12. {python_mapper-0.3.0 → python_mapper-0.3.1}/src/python_mapper/extension.py +0 -0
  13. {python_mapper-0.3.0 → python_mapper-0.3.1}/src/python_mapper/mapping.py +0 -0
  14. {python_mapper-0.3.0 → python_mapper-0.3.1}/src/python_mapper/observability.py +0 -0
  15. {python_mapper-0.3.0 → python_mapper-0.3.1}/src/python_mapper/pagination.py +0 -0
  16. {python_mapper-0.3.0 → python_mapper-0.3.1}/src/python_mapper/plugins.py +0 -0
  17. {python_mapper-0.3.0 → python_mapper-0.3.1}/src/python_mapper/py.typed +0 -0
  18. {python_mapper-0.3.0 → python_mapper-0.3.1}/src/python_mapper/runtime.py +0 -0
  19. {python_mapper-0.3.0 → python_mapper-0.3.1}/src/python_mapper.egg-info/SOURCES.txt +0 -0
  20. {python_mapper-0.3.0 → python_mapper-0.3.1}/src/python_mapper.egg-info/dependency_links.txt +0 -0
  21. {python_mapper-0.3.0 → python_mapper-0.3.1}/src/python_mapper.egg-info/requires.txt +0 -0
  22. {python_mapper-0.3.0 → python_mapper-0.3.1}/src/python_mapper.egg-info/top_level.txt +0 -0
  23. {python_mapper-0.3.0 → python_mapper-0.3.1}/tests/test_framework.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-mapper
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: PostgreSQL XML mapper with asyncpg pooling and implicit transactions
5
5
  Author: z77777777777
6
6
  License-Expression: MIT
@@ -29,20 +29,55 @@ Dynamic: license-file
29
29
 
30
30
  # python-mapper
31
31
 
32
- [English](README.md) · [简体中文](README.zh-CN.md)
32
+ [English](https://github.com/z77777777777/python-mapper/blob/main/README.md) ·
33
+ [简体中文](https://github.com/z77777777777/python-mapper/blob/main/README.zh-CN.md)
33
34
 
34
- PostgreSQL-first XML mapper runtime backed directly by asyncpg. The package is
35
- framework-neutral: it does not import FastAPI, a host application's settings,
36
- logging formatter, schema, or business models.
35
+ A lightweight asynchronous XML mapper for Python. It keeps SQL out of business code —
36
+ queries live in XML, Python keeps only the signature — so a service method reads as what
37
+ the business does, not as string assembly around a cursor.
38
+
39
+ PostgreSQL-first, backed directly by asyncpg. The package is framework-neutral: it does
40
+ not import FastAPI, a host application's settings, logging formatter, schema, or business
41
+ models.
37
42
 
38
43
  ## Installation
39
44
 
40
45
  ```bash
41
- pip install "git+https://github.com/z77777777777/python-mapper.git@v0.3.0"
46
+ pip install python-mapper
42
47
  ```
43
48
 
44
49
  Requires Python 3.12+. The only runtime dependencies are `asyncpg` and `Jinja2`.
45
50
 
51
+ ## Async only
52
+
53
+ Every execution path is asynchronous. Mapper calls, `query()` and `scalar()` return
54
+ coroutines, and `transactional()` raises `TypeError` at decoration time if handed a
55
+ synchronous function. This is not an omission — the driver underneath is asyncpg, which
56
+ has no synchronous API at all.
57
+
58
+ To use it from a synchronous framework (Flask, a classic Django view, a script), run one
59
+ long-lived event loop in a background thread and submit work to it:
60
+
61
+ ```python
62
+ import asyncio
63
+ import threading
64
+
65
+ loop = asyncio.new_event_loop()
66
+ threading.Thread(target=loop.run_forever, daemon=True).start()
67
+
68
+ # Open the pool once, on that loop.
69
+ asyncio.run_coroutine_threadsafe(open_database(...), loop).result()
70
+
71
+ # Then, from synchronous code:
72
+ rows = asyncio.run_coroutine_threadsafe(
73
+ OrdersMapper.find(order_id=1), loop,
74
+ ).result()
75
+ ```
76
+
77
+ Do **not** wrap individual calls in `asyncio.run()`. That builds a fresh event loop every
78
+ time, while an asyncpg pool stays bound to the loop that created it — you would either hit
79
+ "attached to a different loop" errors or rebuild the pool on every request.
80
+
46
81
  ## Package layout
47
82
 
48
83
  - `database.py`: asyncpg pool configuration, startup, shutdown, and connection checkout.
@@ -1,19 +1,54 @@
1
1
  # python-mapper
2
2
 
3
- [English](README.md) · [简体中文](README.zh-CN.md)
3
+ [English](https://github.com/z77777777777/python-mapper/blob/main/README.md) ·
4
+ [简体中文](https://github.com/z77777777777/python-mapper/blob/main/README.zh-CN.md)
4
5
 
5
- PostgreSQL-first XML mapper runtime backed directly by asyncpg. The package is
6
- framework-neutral: it does not import FastAPI, a host application's settings,
7
- logging formatter, schema, or business models.
6
+ A lightweight asynchronous XML mapper for Python. It keeps SQL out of business code —
7
+ queries live in XML, Python keeps only the signature — so a service method reads as what
8
+ the business does, not as string assembly around a cursor.
9
+
10
+ PostgreSQL-first, backed directly by asyncpg. The package is framework-neutral: it does
11
+ not import FastAPI, a host application's settings, logging formatter, schema, or business
12
+ models.
8
13
 
9
14
  ## Installation
10
15
 
11
16
  ```bash
12
- pip install "git+https://github.com/z77777777777/python-mapper.git@v0.3.0"
17
+ pip install python-mapper
13
18
  ```
14
19
 
15
20
  Requires Python 3.12+. The only runtime dependencies are `asyncpg` and `Jinja2`.
16
21
 
22
+ ## Async only
23
+
24
+ Every execution path is asynchronous. Mapper calls, `query()` and `scalar()` return
25
+ coroutines, and `transactional()` raises `TypeError` at decoration time if handed a
26
+ synchronous function. This is not an omission — the driver underneath is asyncpg, which
27
+ has no synchronous API at all.
28
+
29
+ To use it from a synchronous framework (Flask, a classic Django view, a script), run one
30
+ long-lived event loop in a background thread and submit work to it:
31
+
32
+ ```python
33
+ import asyncio
34
+ import threading
35
+
36
+ loop = asyncio.new_event_loop()
37
+ threading.Thread(target=loop.run_forever, daemon=True).start()
38
+
39
+ # Open the pool once, on that loop.
40
+ asyncio.run_coroutine_threadsafe(open_database(...), loop).result()
41
+
42
+ # Then, from synchronous code:
43
+ rows = asyncio.run_coroutine_threadsafe(
44
+ OrdersMapper.find(order_id=1), loop,
45
+ ).result()
46
+ ```
47
+
48
+ Do **not** wrap individual calls in `asyncio.run()`. That builds a fresh event loop every
49
+ time, while an asyncpg pool stays bound to the loop that created it — you would either hit
50
+ "attached to a different loop" errors or rebuild the pool on every request.
51
+
17
52
  ## Package layout
18
53
 
19
54
  - `database.py`: asyncpg pool configuration, startup, shutdown, and connection checkout.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "python-mapper"
7
- version = "0.3.0"
7
+ version = "0.3.1"
8
8
  description = "PostgreSQL XML mapper with asyncpg pooling and implicit transactions"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-mapper
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: PostgreSQL XML mapper with asyncpg pooling and implicit transactions
5
5
  Author: z77777777777
6
6
  License-Expression: MIT
@@ -29,20 +29,55 @@ Dynamic: license-file
29
29
 
30
30
  # python-mapper
31
31
 
32
- [English](README.md) · [简体中文](README.zh-CN.md)
32
+ [English](https://github.com/z77777777777/python-mapper/blob/main/README.md) ·
33
+ [简体中文](https://github.com/z77777777777/python-mapper/blob/main/README.zh-CN.md)
33
34
 
34
- PostgreSQL-first XML mapper runtime backed directly by asyncpg. The package is
35
- framework-neutral: it does not import FastAPI, a host application's settings,
36
- logging formatter, schema, or business models.
35
+ A lightweight asynchronous XML mapper for Python. It keeps SQL out of business code —
36
+ queries live in XML, Python keeps only the signature — so a service method reads as what
37
+ the business does, not as string assembly around a cursor.
38
+
39
+ PostgreSQL-first, backed directly by asyncpg. The package is framework-neutral: it does
40
+ not import FastAPI, a host application's settings, logging formatter, schema, or business
41
+ models.
37
42
 
38
43
  ## Installation
39
44
 
40
45
  ```bash
41
- pip install "git+https://github.com/z77777777777/python-mapper.git@v0.3.0"
46
+ pip install python-mapper
42
47
  ```
43
48
 
44
49
  Requires Python 3.12+. The only runtime dependencies are `asyncpg` and `Jinja2`.
45
50
 
51
+ ## Async only
52
+
53
+ Every execution path is asynchronous. Mapper calls, `query()` and `scalar()` return
54
+ coroutines, and `transactional()` raises `TypeError` at decoration time if handed a
55
+ synchronous function. This is not an omission — the driver underneath is asyncpg, which
56
+ has no synchronous API at all.
57
+
58
+ To use it from a synchronous framework (Flask, a classic Django view, a script), run one
59
+ long-lived event loop in a background thread and submit work to it:
60
+
61
+ ```python
62
+ import asyncio
63
+ import threading
64
+
65
+ loop = asyncio.new_event_loop()
66
+ threading.Thread(target=loop.run_forever, daemon=True).start()
67
+
68
+ # Open the pool once, on that loop.
69
+ asyncio.run_coroutine_threadsafe(open_database(...), loop).result()
70
+
71
+ # Then, from synchronous code:
72
+ rows = asyncio.run_coroutine_threadsafe(
73
+ OrdersMapper.find(order_id=1), loop,
74
+ ).result()
75
+ ```
76
+
77
+ Do **not** wrap individual calls in `asyncio.run()`. That builds a fresh event loop every
78
+ time, while an asyncpg pool stays bound to the loop that created it — you would either hit
79
+ "attached to a different loop" errors or rebuild the pool on every request.
80
+
46
81
  ## Package layout
47
82
 
48
83
  - `database.py`: asyncpg pool configuration, startup, shutdown, and connection checkout.
File without changes
File without changes