Internal Partenamut library for PostgreSQL access using Psycopg 3
Project description
aa-psycopg
Internal Partenamut library for PostgreSQL access using Psycopg 3.
Provides a simple and efficient interface for interacting with PostgreSQL using:
- A direct connection (
PostgreSQLConnection) - A connection pool (
PostgreSQLPool)
Supports query execution (SELECT, INSERT, UPDATE, DELETE), transactions, schema caching, and query runtime statistics.
Installation
If you want to install only psycopg functionality (see: Usage of Psycopg for Direct Connection or Pooling)
pip install aa-psycopg
If you also want to install features for validating query configuration with pydantic (see Usage of QueryConfig for Query Management)
pip install aa-psycopg[pydantic]
Requirements
- Python 3.11+
- psycopg 3
- psycopg_pool
Features
- Easy-to-use wrapper for psycopg3.
- Connection pooling via psycopg_pool.
- Method for chunked/streamed query execution (
read_in_chunks) to avoid loading large datasets into memory. - Automatic query runtime tracking.
- Safe connection string handling (masks passwords in logs).
- Schema caching for executed queries.
API overview
ping(retries=0, timeout=60, query_name="ping") -> bool
Test database connectivity.read(query, params=None, query_name=None) -> list[dict]
Execute a SELECT query. Setquery_nameto track query runtime statistics.read_in_chunks(query, params=None, chunk_size=500000, query_name=None) -> Generator[list[dict]]
Execute a SELECT query and yield results in batches (streaming mode).write(query, params=None, returning=False, query_name=None) -> list[dict] | None
Execute INSERT/UPDATE/DELETE (optionally returning results). Setquery_nameto track query runtime statistics.execute_transaction(queries_params, query_name=None)
Run multiple queries inside a transaction. Setquery_nameto track query runtime statistics.get_stats() -> dict
Retrieve runtime stats (execution time & call count perquery_name).get_schema(query) -> list[psycopg.Column]
Get schema for a previously executed query.
Usage of Psycopg for Direct Connection or Pooling
Direct Connection
import logging
import json
from aa_psycopg.connection import PostgreSQLConnection
# Configure logging (can adjust level or handlers as needed)
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)
with PostgreSQLConnection(
user="myuser",
password="mypassword",
host="localhost",
port=5432,
db="mydatabase"
) as client:
# Check if database is alive
client.ping()
# Fetch results
results = client.read("SELECT * FROM my_table", query_name="fetch_all")
logger.info("Fetched results: %s", results[:5])
# Stream rows in chunks (efficient for very large result sets)
for i, chunk in client.read_in_chunks(
"SELECT * FROM big_table",
chunk_size=5000, # how many rows to fetch per chunk
query_name="stream_big_table",
):
logger.info("Fetched results of chunk %s: %s", i + 1, chunk[:5])
# Write data
client.write(
"INSERT INTO my_table (name) VALUES (%(name)s)",
params={"name": "example"},
query_name="insert_row"
)
logger.info("Inserted row into my_table")
# Transaction
client.execute_transaction([
("INSERT INTO my_table (name) VALUES (%(name)s)", {"name": "row1"}),
("INSERT INTO my_table (name) VALUES (%(name)s)", {"name": "row2"}),
], query_name="bulk_insert")
logger.info("Executed bulk insert transaction")
# Query stats
stats = client.get_stats()
logger.info("Query stats: %s", json.dumps(stats, indent=4))
Connection Pool
import logging
import json
from aa_psycopg.pool import PostgreSQLPool
# Configure logging (can be redirected to CloudWatch or file)
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)
with PostgreSQLPool(
user="myuser",
password="mypassword",
host="localhost",
port=5432,
db="mydatabase",
min_size=0, # pool starts with 0 connections, only creating connection with first query
max_size=1 # pool will not exceed 1 connection
) as client:
# Check connectivity
client.ping()
# Fetch results
results = client.read("SELECT * FROM users WHERE active = true", query_name="active_users")
logger.info("Fetched results: %s", results[:5])
# Stream results in chunks (efficient for very large result sets)
for i, chunk in client.read_in_chunks(
"SELECT * FROM big_table",
chunk_size=5000, # how many rows to fetch per chunk
query_name="stream_big_table",
):
logger.info("Fetched results of chunk %s: %s", i + 1, chunk[:5])
# Insert with RETURNING
new_ids = client.write(
"INSERT INTO users (name) VALUES (%(name)s) RETURNING id",
params={"name": "Alice"},
returning=True,
query_name="insert_user"
)
logger.info("Inserted new user IDs: %s", new_ids)
# Bulk transaction
client.execute_transaction([
("UPDATE users SET active=false WHERE id=%(id)s", {"id": 1}),
("DELETE FROM users WHERE active=false", None),
], query_name="cleanup")
logger.info("Executed cleanup transaction")
# Stats (dump as JSON)
stats = client.get_stats()
logger.info("Query stats: %s", json.dumps(stats, indent=4))
Usage of QueryConfig for Query Management
QueryConfig is a Pydantic-based configuration class that allows you to manage SQL queries
and their parameters from either a .sql file or a raw query string.
It can also load configurations from YAML files for easier organization.
Installation of optional dependency
QueryConfig is optional. To enable it, install the extra dependencies:
uv pip install aa-psycopg[pydantic]
This will pull in pydantic.
Basic Usage
Load from a .sql file
from pathlib import Path
from aa_psycopg.query_config import QueryConfig
cfg = QueryConfig(path_query=Path("queries/get_users.sql"), params={"user_id": 123})
print(cfg.query) # Contents of the SQL file
print(cfg.params) # {"user_id": 123}
Load directly from a raw query string
from aa_psycopg.query_config import QueryConfig
cfg = QueryConfig(query="SELECT * FROM users WHERE id = %(user_id)s", params={"user_id": 123})
print(cfg.query) # The query string
Loading from YAML
You can define a query configuration in a .yaml file:
# query_config.yaml
path_query: queries/get_users.sql
params:
user_id: 123
OR
# query_config.yaml
query: |
SELECT * FROM users
WHERE id = %(user_id)s
params:
user_id: 123
Load it using from_yaml:
from aa_psycopg.query_config import QueryConfig
cfg = QueryConfig.from_yaml("query_config.yaml")
print(cfg.query) # SQL contents from the file
print(cfg.params) # {"user_id": 123}
Validation
- You must provide exactly one of
queryorpath_query. - If a
.sqlfile is given, it must exist and have a.sqlextension. - All parameters defined in the SQL (using
%(param)sstyle) must match the keys inparams. If they don’t, aValueErroris raised with details. --> """
# Example query with a parameter mismatch (SQL expects "id", params gives "user_id")
from aa_psycopg.query_config import QueryConfig
try:
cfg = QueryConfig(
query="SELECT * FROM users WHERE id = %(id)s",
params={"user_id": 123}, # This will cause a validation error
)
except ValueError as e:
print("Validation failed, mismatch detected!")
print(e)
Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Please make sure to update tests as appropriate.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aa_psycopg-0.1.8.tar.gz.
File metadata
- Download URL: aa_psycopg-0.1.8.tar.gz
- Upload date:
- Size: 13.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.6.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bd191fe8b44852ecf587a083c3eddd019ac67fd547ab8ca6216d57260347cb7a
|
|
| MD5 |
fb36fb163c56811990f79993849484af
|
|
| BLAKE2b-256 |
3c1f48925982e3f923608e020b4716df4bfda69b23212a7840877da153cc6821
|
File details
Details for the file aa_psycopg-0.1.8-py3-none-any.whl.
File metadata
- Download URL: aa_psycopg-0.1.8-py3-none-any.whl
- Upload date:
- Size: 13.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.6.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2d9529287bab4d8aae0277ee78efcce8807aa57a7ee9d07875cc1ad343813dc5
|
|
| MD5 |
8302e2ed99ce66ccc1d89fc43d96446c
|
|
| BLAKE2b-256 |
382d8dc0817e753ff0f7763293114bf257580a42b1a8711afe3e1a235cfcb2a5
|