pgdbm 0.1.0__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 (117) hide show
  1. pgdbm-0.1.0/.claude/settings.local.json +27 -0
  2. pgdbm-0.1.0/.gitattributes +60 -0
  3. pgdbm-0.1.0/.gitignore +50 -0
  4. pgdbm-0.1.0/.pre-commit-config.yaml +52 -0
  5. pgdbm-0.1.0/.python-version +1 -0
  6. pgdbm-0.1.0/CHANGELOG.md +52 -0
  7. pgdbm-0.1.0/LICENSE +21 -0
  8. pgdbm-0.1.0/PKG-INFO +288 -0
  9. pgdbm-0.1.0/README.md +256 -0
  10. pgdbm-0.1.0/docs/api-reference.md +918 -0
  11. pgdbm-0.1.0/docs/migrations.md +567 -0
  12. pgdbm-0.1.0/docs/patterns.md +539 -0
  13. pgdbm-0.1.0/docs/quickstart.md +255 -0
  14. pgdbm-0.1.0/docs/testing.md +407 -0
  15. pgdbm-0.1.0/examples/README.md +49 -0
  16. pgdbm-0.1.0/examples/microservices/Dockerfile +22 -0
  17. pgdbm-0.1.0/examples/microservices/README.md +294 -0
  18. pgdbm-0.1.0/examples/microservices/docker-compose.yml +95 -0
  19. pgdbm-0.1.0/examples/microservices/gateway/__init__.py +1 -0
  20. pgdbm-0.1.0/examples/microservices/gateway/main.py +134 -0
  21. pgdbm-0.1.0/examples/microservices/gateway/routes.py +250 -0
  22. pgdbm-0.1.0/examples/microservices/migrations/001_shared_tables.sql +40 -0
  23. pgdbm-0.1.0/examples/microservices/requirements.txt +21 -0
  24. pgdbm-0.1.0/examples/microservices/services/__init__.py +1 -0
  25. pgdbm-0.1.0/examples/microservices/services/inventory/__init__.py +1 -0
  26. pgdbm-0.1.0/examples/microservices/services/inventory/api.py +185 -0
  27. pgdbm-0.1.0/examples/microservices/services/inventory/db.py +260 -0
  28. pgdbm-0.1.0/examples/microservices/services/inventory/handlers.py +49 -0
  29. pgdbm-0.1.0/examples/microservices/services/inventory/main.py +115 -0
  30. pgdbm-0.1.0/examples/microservices/services/inventory/migrations/001_inventory_schema.sql +51 -0
  31. pgdbm-0.1.0/examples/microservices/services/notification/__init__.py +1 -0
  32. pgdbm-0.1.0/examples/microservices/services/notification/handlers.py +129 -0
  33. pgdbm-0.1.0/examples/microservices/services/notification/main.py +107 -0
  34. pgdbm-0.1.0/examples/microservices/services/orders/__init__.py +1 -0
  35. pgdbm-0.1.0/examples/microservices/services/orders/api.py +220 -0
  36. pgdbm-0.1.0/examples/microservices/services/orders/db.py +219 -0
  37. pgdbm-0.1.0/examples/microservices/services/orders/handlers.py +42 -0
  38. pgdbm-0.1.0/examples/microservices/services/orders/main.py +115 -0
  39. pgdbm-0.1.0/examples/microservices/services/orders/migrations/001_orders_schema.sql +54 -0
  40. pgdbm-0.1.0/examples/microservices/services/users/__init__.py +1 -0
  41. pgdbm-0.1.0/examples/microservices/services/users/api.py +186 -0
  42. pgdbm-0.1.0/examples/microservices/services/users/db.py +136 -0
  43. pgdbm-0.1.0/examples/microservices/services/users/main.py +113 -0
  44. pgdbm-0.1.0/examples/microservices/services/users/migrations/001_users_schema.sql +30 -0
  45. pgdbm-0.1.0/examples/microservices/shared/__init__.py +1 -0
  46. pgdbm-0.1.0/examples/microservices/shared/database.py +226 -0
  47. pgdbm-0.1.0/examples/microservices/shared/events.py +194 -0
  48. pgdbm-0.1.0/examples/microservices/shared/models.py +194 -0
  49. pgdbm-0.1.0/examples/microservices/shared/resilience.py +272 -0
  50. pgdbm-0.1.0/examples/microservices/tests/__init__.py +1 -0
  51. pgdbm-0.1.0/examples/microservices/tests/conftest.py +60 -0
  52. pgdbm-0.1.0/examples/microservices/tests/test_shared_pool.py +162 -0
  53. pgdbm-0.1.0/examples/saas-app/.gitignore +30 -0
  54. pgdbm-0.1.0/examples/saas-app/README.md +186 -0
  55. pgdbm-0.1.0/examples/saas-app/app/__init__.py +1 -0
  56. pgdbm-0.1.0/examples/saas-app/app/api/__init__.py +1 -0
  57. pgdbm-0.1.0/examples/saas-app/app/api/admin.py +212 -0
  58. pgdbm-0.1.0/examples/saas-app/app/api/auth.py +126 -0
  59. pgdbm-0.1.0/examples/saas-app/app/api/projects.py +199 -0
  60. pgdbm-0.1.0/examples/saas-app/app/api/tenants.py +202 -0
  61. pgdbm-0.1.0/examples/saas-app/app/config.py +80 -0
  62. pgdbm-0.1.0/examples/saas-app/app/db/__init__.py +1 -0
  63. pgdbm-0.1.0/examples/saas-app/app/db/__main__.py +117 -0
  64. pgdbm-0.1.0/examples/saas-app/app/db/admin.py +414 -0
  65. pgdbm-0.1.0/examples/saas-app/app/db/base.py +72 -0
  66. pgdbm-0.1.0/examples/saas-app/app/db/tenant.py +308 -0
  67. pgdbm-0.1.0/examples/saas-app/app/main.py +122 -0
  68. pgdbm-0.1.0/examples/saas-app/app/middleware/__init__.py +1 -0
  69. pgdbm-0.1.0/examples/saas-app/app/middleware/tenant.py +66 -0
  70. pgdbm-0.1.0/examples/saas-app/app/models/__init__.py +1 -0
  71. pgdbm-0.1.0/examples/saas-app/app/models/project.py +120 -0
  72. pgdbm-0.1.0/examples/saas-app/app/models/tenant.py +103 -0
  73. pgdbm-0.1.0/examples/saas-app/app/models/user.py +46 -0
  74. pgdbm-0.1.0/examples/saas-app/migrations/001_unified_schema.sql +226 -0
  75. pgdbm-0.1.0/examples/saas-app/requirements.txt +16 -0
  76. pgdbm-0.1.0/examples/saas-app/tests/__init__.py +1 -0
  77. pgdbm-0.1.0/examples/saas-app/tests/conftest.py +130 -0
  78. pgdbm-0.1.0/examples/saas-app/tests/test_auth.py +115 -0
  79. pgdbm-0.1.0/examples/saas-app/tests/test_projects.py +160 -0
  80. pgdbm-0.1.0/examples/saas-app/tests/test_tenant.py +99 -0
  81. pgdbm-0.1.0/examples/todo-app/README.md +140 -0
  82. pgdbm-0.1.0/examples/todo-app/app/__init__.py +1 -0
  83. pgdbm-0.1.0/examples/todo-app/app/api/__init__.py +1 -0
  84. pgdbm-0.1.0/examples/todo-app/app/api/health.py +26 -0
  85. pgdbm-0.1.0/examples/todo-app/app/api/todos.py +100 -0
  86. pgdbm-0.1.0/examples/todo-app/app/config.py +64 -0
  87. pgdbm-0.1.0/examples/todo-app/app/db.py +256 -0
  88. pgdbm-0.1.0/examples/todo-app/app/main.py +72 -0
  89. pgdbm-0.1.0/examples/todo-app/app/models.py +67 -0
  90. pgdbm-0.1.0/examples/todo-app/migrations/001_initial_schema.sql +37 -0
  91. pgdbm-0.1.0/examples/todo-app/requirements.txt +13 -0
  92. pgdbm-0.1.0/examples/todo-app/tests/__init__.py +1 -0
  93. pgdbm-0.1.0/examples/todo-app/tests/conftest.py +77 -0
  94. pgdbm-0.1.0/examples/todo-app/tests/test_api.py +178 -0
  95. pgdbm-0.1.0/examples/todo-app/tests/test_db.py +163 -0
  96. pgdbm-0.1.0/pyproject.toml +167 -0
  97. pgdbm-0.1.0/src/pgdbm/__init__.py +71 -0
  98. pgdbm-0.1.0/src/pgdbm/__version__.py +9 -0
  99. pgdbm-0.1.0/src/pgdbm/core.py +757 -0
  100. pgdbm-0.1.0/src/pgdbm/errors.py +140 -0
  101. pgdbm-0.1.0/src/pgdbm/fixtures/__init__.py +14 -0
  102. pgdbm-0.1.0/src/pgdbm/fixtures/conftest.py +289 -0
  103. pgdbm-0.1.0/src/pgdbm/migrations.py +560 -0
  104. pgdbm-0.1.0/src/pgdbm/monitoring.py +390 -0
  105. pgdbm-0.1.0/src/pgdbm/py.typed +0 -0
  106. pgdbm-0.1.0/src/pgdbm/testing.py +415 -0
  107. pgdbm-0.1.0/tests/conftest.py +83 -0
  108. pgdbm-0.1.0/tests/integration/test_basic_usage.py +456 -0
  109. pgdbm-0.1.0/tests/integration/test_migrations.py +419 -0
  110. pgdbm-0.1.0/tests/integration/test_monitoring.py +369 -0
  111. pgdbm-0.1.0/tests/integration/test_multi_tenancy.py +421 -0
  112. pgdbm-0.1.0/tests/integration/test_testing_utilities.py +417 -0
  113. pgdbm-0.1.0/tests/test_core.py +292 -0
  114. pgdbm-0.1.0/tests/test_migrations_unit.py +294 -0
  115. pgdbm-0.1.0/tests/test_security.py +267 -0
  116. pgdbm-0.1.0/tests/test_shared_pool.py +354 -0
  117. pgdbm-0.1.0/uv.lock +1253 -0
@@ -0,0 +1,27 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(python:*)",
5
+ "Bash(ls:*)",
6
+ "Bash(grep:*)",
7
+ "Bash(find:*)",
8
+ "Bash(source:*)",
9
+ "Bash(psql:*)",
10
+ "Bash(timeout:*)",
11
+ "Bash(pre-commit run:*)",
12
+ "Bash(ruff check:*)",
13
+ "Bash(mypy:*)",
14
+ "Bash(uv run mypy:*)",
15
+ "Bash(uv run pre-commit run:*)",
16
+ "Bash(git add:*)",
17
+ "Bash(git reset:*)",
18
+ "Bash(uv run ruff:*)",
19
+ "Bash(uv run isort:*)",
20
+ "Bash(uv run bandit:*)",
21
+ "Bash(uv run pytest:*)",
22
+ "Bash(git commit:*)",
23
+ "Bash(rm:*)"
24
+ ],
25
+ "deny": []
26
+ }
27
+ }
@@ -0,0 +1,60 @@
1
+ # Auto detect text files and perform LF normalization
2
+ * text=auto
3
+
4
+ # Python files
5
+ *.py text
6
+ *.pyw text
7
+ *.pyx text
8
+ *.pyi text
9
+
10
+ # Documentation
11
+ *.md text
12
+ *.rst text
13
+ *.txt text
14
+ LICENSE text
15
+ AUTHORS text
16
+ CHANGELOG text
17
+ CONTRIBUTING text
18
+ README text
19
+
20
+ # Config files
21
+ *.json text
22
+ *.yaml text
23
+ *.yml text
24
+ *.toml text
25
+ *.ini text
26
+ *.cfg text
27
+ .gitignore text
28
+ .gitattributes text
29
+
30
+ # Shell scripts
31
+ *.sh text eol=lf
32
+ *.bash text eol=lf
33
+
34
+ # Windows scripts
35
+ *.bat text eol=crlf
36
+ *.cmd text eol=crlf
37
+ *.ps1 text eol=crlf
38
+
39
+ # Binary files
40
+ *.db binary
41
+ *.sqlite binary
42
+ *.sqlite3 binary
43
+ *.pyc binary
44
+ *.pyo binary
45
+ *.pyd binary
46
+ *.so binary
47
+ *.dylib binary
48
+ *.dll binary
49
+ *.exe binary
50
+ *.zip binary
51
+ *.tar binary
52
+ *.gz binary
53
+ *.bz2 binary
54
+ *.7z binary
55
+ *.png binary
56
+ *.jpg binary
57
+ *.jpeg binary
58
+ *.gif binary
59
+ *.ico binary
60
+ *.pdf binary
pgdbm-0.1.0/.gitignore ADDED
@@ -0,0 +1,50 @@
1
+ # Environment variables
2
+ .env*
3
+
4
+ # Python
5
+ __pycache__/
6
+ *.py[cod]
7
+ *$py.class
8
+ *.so
9
+ .Python
10
+ build/
11
+ develop-eggs/
12
+ dist/
13
+ downloads/
14
+ eggs/
15
+ .eggs/
16
+ lib/
17
+ lib64/
18
+ parts/
19
+ sdist/
20
+ var/
21
+ wheels/
22
+ *.egg-info/
23
+ .installed.cfg
24
+ *.egg
25
+ .pytest_cache/
26
+ .coverage
27
+ htmlcov/
28
+ .tox/
29
+ .venv/
30
+ venv/
31
+
32
+ # Emacs
33
+ *~
34
+ \#*\#
35
+ /.emacs.desktop
36
+ /.emacs.desktop.lock
37
+ .emacs-bu/
38
+ *.elc
39
+ auto-save-list
40
+ tramp
41
+ .\#*
42
+ .dir-locals.el
43
+ .projectile
44
+
45
+ # OS
46
+ .DS_Store
47
+ Thumbs.db
48
+
49
+ Makefile
50
+ tmp
@@ -0,0 +1,52 @@
1
+ # See https://pre-commit.com for more information
2
+ # See https://pre-commit.com/hooks.html for more hooks
3
+ repos:
4
+ - repo: https://github.com/pre-commit/pre-commit-hooks
5
+ rev: v5.0.0
6
+ hooks:
7
+ - id: trailing-whitespace
8
+ - id: end-of-file-fixer
9
+ - id: check-yaml
10
+ - id: check-added-large-files
11
+ - id: check-json
12
+ - id: check-toml
13
+ - id: check-merge-conflict
14
+ - id: debug-statements
15
+ - id: detect-private-key
16
+ - id: mixed-line-ending
17
+ args: ['--fix=lf']
18
+ - id: name-tests-test
19
+ args: ['--pytest-test-first']
20
+
21
+ - repo: https://github.com/psf/black
22
+ rev: 25.1.0
23
+ hooks:
24
+ - id: black
25
+ language_version: python3
26
+ args: ['--config=pyproject.toml']
27
+
28
+ - repo: https://github.com/pycqa/isort
29
+ rev: 6.0.1
30
+ hooks:
31
+ - id: isort
32
+ args: ['--settings-path=pyproject.toml']
33
+
34
+ - repo: https://github.com/charliermarsh/ruff-pre-commit
35
+ rev: v0.12.5
36
+ hooks:
37
+ - id: ruff
38
+ args: ['--fix', '--exit-non-zero-on-fix']
39
+
40
+ - repo: https://github.com/pre-commit/mirrors-mypy
41
+ rev: v1.17.0
42
+ hooks:
43
+ - id: mypy
44
+ additional_dependencies: [asyncpg-stubs, pydantic, pytest, pytest-asyncio]
45
+ args: ['--config-file=pyproject.toml', 'src/']
46
+ files: '^src/'
47
+ pass_filenames: false
48
+
49
+
50
+ ci:
51
+ autoupdate_schedule: weekly
52
+ skip: [mypy] # mypy requires installed dependencies
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,52 @@
1
+ # Changelog
2
+
3
+ All notable changes to pgdbm will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Added
11
+ - TLS/SSL support in `DatabaseConfig` with `ssl_enabled`, `ssl_mode`, CA/cert/key options
12
+ - Server-side timeouts in `DatabaseConfig` (`statement_timeout_ms`, `idle_in_transaction_session_timeout_ms`, `lock_timeout_ms`)
13
+ - Advisory locking in migrations to serialize runners per `module_name`
14
+ - Migration version extraction from filenames
15
+ - Supports numeric prefix (001_), Flyway style (V1__), and timestamp patterns
16
+ - Automatic version property on Migration model
17
+ - Better ordering and conflict prevention
18
+
19
+ ### Changed
20
+ - Replace generic exceptions with custom error types throughout codebase
21
+ - ConfigurationError, PoolError, QueryError, MigrationError, etc.
22
+ - Enhanced error messages with troubleshooting tips
23
+ - Better debugging experience
24
+ - `execute_and_return_id` now correctly detects existing RETURNING clauses to avoid duplication
25
+ - **BREAKING**: Minimum Python version raised to 3.9
26
+ - Python 3.8 reached EOL in October 2024
27
+ - Allows use of modern type annotations and features
28
+
29
+ ## [0.1.0] - 2025-01-26
30
+
31
+ ### Added
32
+ - Initial public release
33
+ - Core async database management with connection pooling
34
+ - Schema-based multi-tenancy support
35
+ - Built-in migration system
36
+ - Comprehensive testing utilities
37
+ - Connection monitoring and debugging tools
38
+ - Shared connection pool support for microservices
39
+ - Full type hints and py.typed support
40
+ - Pytest fixtures for easy testing
41
+ - Production-ready patterns out of the box
42
+
43
+ ### Features
44
+ - **AsyncDatabaseManager**: Main database interface with connection pooling
45
+ - **DatabaseConfig**: Pydantic-based configuration management
46
+ - **AsyncMigrationManager**: Database migration tracking and execution
47
+ - **MonitoredAsyncDatabaseManager**: Performance monitoring capabilities
48
+ - **Testing utilities**: Automatic test database creation and cleanup
49
+ - **Schema isolation**: Multi-tenant support with `{{tables.name}}` templating
50
+
51
+ [Unreleased]: https://github.com/juanreyero/pgdbm/compare/v0.1.0...HEAD
52
+ [0.1.0]: https://github.com/juanreyero/pgdbm/releases/tag/v0.1.0
pgdbm-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Juan Reyero
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
pgdbm-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,288 @@
1
+ Metadata-Version: 2.4
2
+ Name: pgdbm
3
+ Version: 0.1.0
4
+ Summary: Production-ready async PostgreSQL utilities with connection pooling, migrations, and testing support
5
+ Project-URL: Homepage, https://juanreyero.com/open/pgdbm
6
+ Project-URL: Documentation, https://github.com/juanre/pgdbm
7
+ Project-URL: Repository, https://github.com/juanre/pgdbm
8
+ Project-URL: Issues, https://github.com/juanre/pgdbm/issues
9
+ Project-URL: Changelog, https://github.com/juanre/pgdbm/blob/main/CHANGELOG.md
10
+ Author-email: Juan Reyero <juan@juanreyero.com>
11
+ Maintainer-email: Juan Reyero <juan@juanreyero.com>
12
+ License: MIT
13
+ License-File: LICENSE
14
+ Keywords: async,asyncio,asyncpg,database,migrations,postgresql,testing
15
+ Classifier: Development Status :: 4 - Beta
16
+ Classifier: Framework :: AsyncIO
17
+ Classifier: Intended Audience :: Developers
18
+ Classifier: License :: OSI Approved :: MIT License
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3.9
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Topic :: Database
26
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
27
+ Classifier: Typing :: Typed
28
+ Requires-Python: >=3.9
29
+ Requires-Dist: asyncpg>=0.28.0
30
+ Requires-Dist: pydantic>=2.0.0
31
+ Description-Content-Type: text/markdown
32
+
33
+ # pgdbm
34
+
35
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
36
+ [![Python](https://img.shields.io/pypi/pyversions/pgdbm.svg)](https://pypi.org/project/pgdbm/)
37
+ [![PyPI](https://img.shields.io/pypi/v/pgdbm.svg)](https://pypi.org/project/pgdbm/)
38
+
39
+ A PostgreSQL library for Python that provides high-level async database operations with built-in migration management, connection pooling, and testing utilities. It offers:
40
+
41
+ - **Connection pooling** with proper resource management
42
+ - **Schema migrations** that are version-controlled and automated
43
+ - **Testing utilities** that provide isolated test databases
44
+ - **Module isolation** when multiple services share a database
45
+ - **Monitoring** for slow queries and connection issues
46
+
47
+ ## Key Features
48
+
49
+ - **🚀 High Performance** - Built on asyncpg, the fastest PostgreSQL driver for Python
50
+ - **📦 Migration System** - Version-controlled schema migrations with automatic ordering
51
+ - **🧪 Testing Support** - Fixtures and utilities for database testing
52
+ - **🔧 Module Isolation** - Prevent table conflicts when modules share databases
53
+ - **📊 Monitoring** - Track slow queries and connection pool metrics
54
+ - **🔒 Type Safe** - Full type hints and Pydantic integration
55
+
56
+ ### Design intent: dual ownership
57
+
58
+ pgdbm is designed so a module can either:
59
+ - **Own its database** when run independently (it creates a pool and runs its own migrations), or
60
+ - **Use a database owned by another** component via a shared pool while still running its own migrations into a schema namespace.
61
+
62
+ This keeps modules portable: the same code can run as a standalone service or as part of a larger app.
63
+
64
+ ## Installation
65
+
66
+ ```bash
67
+ # Install using uv (recommended)
68
+ uv add pgdbm
69
+
70
+ # Or using pip
71
+ pip install pgdbm
72
+ ```
73
+
74
+ ## Quick Start
75
+
76
+ ### 1. Create a migration file
77
+
78
+ ```sql
79
+ -- migrations/001_initial.sql
80
+ CREATE TABLE IF NOT EXISTS {{tables.users}} (
81
+ id SERIAL PRIMARY KEY,
82
+ email VARCHAR(255) UNIQUE NOT NULL,
83
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
84
+ );
85
+ ```
86
+
87
+ ### 2. Use pgdbm
88
+
89
+ ```python
90
+ from pgdbm import AsyncDatabaseManager, DatabaseConfig, AsyncMigrationManager
91
+
92
+ # Configure and connect
93
+ config = DatabaseConfig(
94
+ host="localhost",
95
+ database="myapp",
96
+ user="postgres",
97
+ password="secret"
98
+ )
99
+
100
+ db = AsyncDatabaseManager(config)
101
+ await db.connect()
102
+
103
+ # Apply migrations
104
+ migrations = AsyncMigrationManager(db, migrations_path="./migrations")
105
+ await migrations.apply_pending()
106
+
107
+ # Use your database
108
+ user_id = await db.execute_and_return_id(
109
+ "INSERT INTO {{tables.users}} (email) VALUES ($1)",
110
+ "user@example.com"
111
+ )
112
+
113
+ # Clean up
114
+ await db.disconnect()
115
+ ```
116
+
117
+ Standalone vs shared-pool usage:
118
+
119
+ ```python
120
+ # Standalone (owns the DB):
121
+ config = DatabaseConfig(connection_string="postgresql://localhost/app", schema="users")
122
+ db = AsyncDatabaseManager(config)
123
+ await db.connect()
124
+ await AsyncMigrationManager(db, "./migrations", module_name="users").apply_pending()
125
+
126
+ # Shared pool (uses external DB):
127
+ shared = await AsyncDatabaseManager.create_shared_pool(DatabaseConfig(connection_string="postgresql://localhost/app"))
128
+ db = AsyncDatabaseManager(pool=shared, schema="users") # Module still runs its own migrations
129
+ await AsyncMigrationManager(db, "./migrations", module_name="users").apply_pending()
130
+ ```
131
+
132
+ ## Core Patterns
133
+
134
+ ### 1. Migration Management
135
+
136
+ pgdbm includes a built-in migration system:
137
+
138
+ ```python
139
+ # Apply all pending migrations
140
+ migrations = AsyncMigrationManager(db, migrations_path="./migrations")
141
+ result = await migrations.apply_pending()
142
+
143
+ # Check what was applied
144
+ for migration in result['applied']:
145
+ print(f"Applied {migration['filename']} in {migration['execution_time_ms']}ms")
146
+ ```
147
+
148
+ Migrations are automatically ordered by version number extracted from filenames.
149
+
150
+ ### 2. Module Isolation
151
+
152
+ When multiple modules share a database, use schemas to prevent table conflicts:
153
+
154
+ ```python
155
+ # Each module can get its own schema
156
+ user_db = AsyncDatabaseManager(
157
+ config=DatabaseConfig(database="app", schema="user_module")
158
+ )
159
+ blog_db = AsyncDatabaseManager(
160
+ config=DatabaseConfig(database="app", schema="blog_module")
161
+ )
162
+
163
+ # Both can have a "users" table without conflict:
164
+ # - user_module.users
165
+ # - blog_module.users
166
+ ```
167
+
168
+ The `{{tables.tablename}}` syntax in queries automatically expands to the correct schema-qualified name.
169
+
170
+ ### 3. Connection Pool Sharing
171
+
172
+ For applications with multiple services sharing a database:
173
+
174
+ ```python
175
+ # Create shared pool
176
+ shared_pool = await AsyncDatabaseManager.create_shared_pool(config)
177
+
178
+ # Each service gets its own schema but shares connections
179
+ user_db = AsyncDatabaseManager(pool=shared_pool, schema="users")
180
+ billing_db = AsyncDatabaseManager(pool=shared_pool, schema="billing")
181
+ ```
182
+
183
+ ### 4. Testing Support
184
+
185
+ Built-in fixtures for database tests:
186
+
187
+ ```python
188
+ # conftest.py
189
+ from pgdbm.fixtures.conftest import *
190
+
191
+ # test_users.py
192
+ async def test_create_user(test_db):
193
+ # Automatic test database with cleanup
194
+ await test_db.execute("""
195
+ CREATE TABLE users (id SERIAL PRIMARY KEY, email TEXT)
196
+ """)
197
+
198
+ user_id = await test_db.execute_and_return_id(
199
+ "INSERT INTO users (email) VALUES ($1)",
200
+ "test@example.com"
201
+ )
202
+ assert user_id == 1
203
+ ```
204
+
205
+ ### 5. Monitoring
206
+
207
+ Track database performance:
208
+
209
+ ```python
210
+ from pgdbm import MonitoredAsyncDatabaseManager
211
+
212
+ db = MonitoredAsyncDatabaseManager(
213
+ config=config,
214
+ slow_query_threshold_ms=100 # Log queries over 100ms
215
+ )
216
+
217
+ # Get metrics
218
+ metrics = await db.get_query_metrics()
219
+ slow_queries = await db.get_slow_queries(limit=10)
220
+ ```
221
+
222
+ ### 6. Production TLS and Timeouts
223
+
224
+ Enable TLS with certificate verification and enforce server-side timeouts:
225
+
226
+ ```python
227
+ from pgdbm import AsyncDatabaseManager, DatabaseConfig
228
+
229
+ config = DatabaseConfig(
230
+ connection_string="postgresql://db.example.com/app",
231
+ ssl_enabled=True,
232
+ ssl_mode="verify-full", # 'require' | 'verify-ca' | 'verify-full'
233
+ ssl_ca_file="/etc/ssl/certs/ca.pem",
234
+ # Optional mutual TLS:
235
+ # ssl_cert_file="/etc/ssl/certs/client.crt",
236
+ # ssl_key_file="/etc/ssl/private/client.key",
237
+
238
+ # Sensible timeouts (ms)
239
+ statement_timeout_ms=60_000,
240
+ idle_in_transaction_session_timeout_ms=60_000,
241
+ lock_timeout_ms=5_000,
242
+ )
243
+
244
+ db = AsyncDatabaseManager(config)
245
+ await db.connect()
246
+ ```
247
+
248
+ Notes:
249
+ - Use `verify-full` for strict hostname and certificate validation in production.
250
+ - Timeouts are applied via `server_settings`; you can override or disable by passing None.
251
+
252
+ ## Examples
253
+
254
+ The `examples/` directory contains applications:
255
+
256
+ - **todo-app/** - REST API with migrations, testing, and error handling
257
+ - **saas-app/** - Multi-tenant SaaS application
258
+ - **microservices/** - Multiple services sharing a connection pool
259
+
260
+ ## Documentation
261
+
262
+ - [Quickstart Guide](docs/quickstart.md) - Get started
263
+ - [Patterns Guide](docs/patterns.md) - Deployment patterns, schema isolation, and framework integration
264
+ - [Migration Guide](docs/migrations.md) - Schema versioning and {{tables.}} syntax
265
+ - [API Reference](docs/api-reference.md) - Complete API documentation
266
+ - [Testing Guide](docs/testing.md) - Testing best practices
267
+
268
+ ## Contributing
269
+
270
+ Short version:
271
+
272
+ - Requirements: Python 3.9+, PostgreSQL 12+, uv (or pip)
273
+ - Setup:
274
+ - uv: `uv sync`
275
+ - pip: `pip install -e ".[dev]"`
276
+ - hooks: `pre-commit install`
277
+ - Run tests: `pytest`
278
+ - Lint/type-check: `pre-commit run --all-files`
279
+
280
+ Notes:
281
+
282
+ - Integration tests use ephemeral databases; you can override with env vars like `TEST_DB_HOST`, `TEST_DB_PORT`, `TEST_DB_USER`, `TEST_DB_PASSWORD`.
283
+ - Keep PRs small and focused, include tests/docs for user-visible changes.
284
+ - Style is enforced via Black/Isort/Ruff/Mypy; run pre-commit locally before pushing.
285
+
286
+ ## License
287
+
288
+ MIT License - see [LICENSE](LICENSE) for details.