dm-dbcore
A SQLAlchemy database connection wrapper with metadata caching, multi-database support (PostgreSQL, MySQL, SQLite), and custom type adapters.
Features
- Singleton connection management - One database connection per application
- Metadata caching - Automatic SQLAlchemy metadata caching for faster startup
- Multi-database support - Works with PostgreSQL, MySQL, and SQLite
- Custom type adapters - NumPy arrays, PostgreSQL geometric types (Point, Polygon, Circle)
- MySQL utilities - Read credentials from
.my.cnffiles - Automatic staleness detection - Cache invalidation when schema changes
- Context managers - Safe transactional operations with
session_scope()
Installation
From PyPI
pip install dm-dbcore
With database-specific drivers
# PostgreSQL
pip install dm-dbcore[postgresql]
# MySQL
pip install dm-dbcore[mysql]
# NumPy support
pip install dm-dbcore[numpy]
# Astronomy support (PostgreSQL geometric types with cornish)
pip install dm-dbcore[astronomy]
# All extras
pip install dm-dbcore[postgresql,mysql,numpy,astronomy]
From source
git clone https://github.com/demitri/dm-dbcore.git
cd dm-dbcore
pip install -e .
Quick Start
Basic Usage
from dm_dbcore import DatabaseConnection, session_scope
from sqlalchemy import text
# Create connection (first time only, required on first call)
db = DatabaseConnection(
database_connection_string='postgresql+psycopg://user:pass@localhost/mydb',
cache_name='myapp_cache.pkl' # Optional: enables metadata caching
)
# Subsequent calls return the same instance (no parameters needed)
db = DatabaseConnection()
# Use the connection with a transactional scope
with session_scope(db) as session:
result = session.execute(text("SELECT * FROM users"))
for row in result:
print(row)
Database Types
from dm_dbcore import DatabaseConnection, DBTYPE_POSTGRESQL, DBTYPE_MYSQL, DBTYPE_SQLITE
# PostgreSQL
db = DatabaseConnection('postgresql+psycopg://user:pass@localhost/mydb')
# MySQL
db = DatabaseConnection('mysql://user:pass@localhost/mydb')
# SQLite
db = DatabaseConnection('sqlite:///path/to/database.db')
# Check database type
print(db.database_type) # 'postgresql', 'mysql', or 'sqlite'
Using SQLAlchemy ORM Models
from dm_dbcore import DatabaseConnection, session_scope
from sqlalchemy.orm import declarative_base
from sqlalchemy import Column, Integer, String
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(50))
email = Column(String(100))
# Create connection with metadata
db = DatabaseConnection('postgresql+psycopg://user:pass@localhost/mydb')
# Bind models to the connection's metadata
Base.metadata.bind = db.engine
# Query using ORM
with session_scope(db) as session:
users = session.query(User).filter(User.name.like('John%')).all()
for user in users:
print(f"{user.name}: {user.email}")
Metadata Caching
Metadata caching dramatically improves application startup time by storing SQLAlchemy's table reflection data:
# Enable caching by providing a cache filename
db = DatabaseConnection(
database_connection_string='postgresql+psycopg://localhost/mydb',
cache_name='myapp_metadata.pkl'
)
# Cache is automatically stored in ~/.sqlalchemy_cache/
# Cache is invalidated automatically when schema changes are detected
PostgreSQL: Uses information_schema.columns to compute schema hash (no manual setup required)
MySQL: Uses information_schema.TABLES to compute schema hash (no manual setup required)
SQLite: Cache is always considered stale (no automatic detection)
Advanced Features
Custom Context Manager
from dm_dbcore import DatabaseConnection
from contextlib import contextmanager
db = DatabaseConnection('postgresql+psycopg://localhost/mydb')
@contextmanager
def my_session():
session = db.Session()
try:
yield session
session.commit()
except Exception:
session.rollback()
raise
finally:
session.close()
# Use your custom context manager
with my_session() as session:
# Your database operations
pass
NumPy Array Support (PostgreSQL/SQLite)
When you install with NumPy support, you can store/retrieve NumPy arrays:
from dm_dbcore import DatabaseConnection
import numpy as np
db = DatabaseConnection('postgresql+psycopg://localhost/mydb')
# NumPy adapters are automatically loaded for PostgreSQL
# Arrays are automatically converted to/from database format
MySQL Utilities
Read database credentials from .my.cnf files:
from dm_dbcore.mysql import read_password_from_my_cnf, read_connection_options_from_my_cnf
# Read password for specific host/user
password = read_password_from_my_cnf(host='localhost', user='myuser')
# Read all connection options from .my.cnf
options = read_connection_options_from_my_cnf(section='client')
# Returns: {'host': '...', 'user': '...', 'password': '...', 'database': '...', 'port': ...}
PostgreSQL Geometric Types
Standard Geometric Types
from sqlalchemy import Column
from sqlalchemy.dialects.postgresql import base as pg
from dm_dbcore.adapters import PGPoint, PGPolygon
# Register types with SQLAlchemy
pg.ischema_names['point'] = PGPoint
pg.ischema_names['polygon'] = PGPolygon
# Use in your models
class Location(Base):
__tablename__ = 'locations'
id = Column(Integer, primary_key=True)
coordinates = Column(PGPoint) # Stores (x, y) tuples
boundary = Column(PGPolygon) # Stores list of (x, y) tuples
Astronomy-Specific Geometric Types
Requires cornish library: pip install dm-dbcore[astronomy]
from sqlalchemy import Column
from sqlalchemy.dialects.postgresql import base as pg
from dm_dbcore.adapters import PGASTCircle, PGASTPolygon
# Register astronomy types
pg.ischema_names['circle'] = PGASTCircle
pg.ischema_names['polygon'] = PGASTPolygon
# Use with astronomical coordinate systems
class AstronomicalObject(Base):
__tablename__ = 'objects'
id = Column(Integer, primary_key=True)
search_region = Column(PGASTCircle) # Uses cornish.ASTCircle
footprint = Column(PGASTPolygon) # Uses cornish.ASTPolygon
Module Organization
dm_dbcore/
├── DatabaseConnection # Main connection class
├── MetadataCache # Metadata caching
├── session_scope # Context manager
├── DBTYPE_* # Database type constants
├── adapters/ # Custom type adapters
│ ├── postgresql/ # PostgreSQL adapters
│ │ ├── PGPoint # PostgreSQL Point type
│ │ ├── PGPolygon # PostgreSQL Polygon type
│ │ ├── PGASTCircle # Astronomy Circle (requires cornish)
│ │ ├── PGASTPolygon # Astronomy Polygon (requires cornish)
│ │ ├── PGCitext # PostgreSQL citext type
│ │ └── numpy_postgresql # NumPy array adapters for PostgreSQL
│ └── sqlite/ # SQLite adapters
│ └── numpy_sqlite # NumPy array adapters for SQLite
└── mysql/ # MySQL utilities
├── read_password_from_my_cnf
└── read_connection_options_from_my_cnf
Import Examples
# Core functionality
from dm_dbcore import DatabaseConnection, session_scope
from dm_dbcore import DBTYPE_POSTGRESQL, DBTYPE_MYSQL, DBTYPE_SQLITE
# PostgreSQL geometric types
from dm_dbcore.adapters import PGPoint, PGPolygon
# Astronomy types (requires cornish)
from dm_dbcore.adapters import PGASTCircle, PGASTPolygon
# MySQL utilities
from dm_dbcore.mysql import read_password_from_my_cnf
from dm_dbcore.mysql import read_connection_options_from_my_cnf
API Reference
DatabaseConnection
DatabaseConnection(database_connection_string, cache_name=None)
Singleton class for managing database connections.
Parameters:
database_connection_string(str, required on first call): SQLAlchemy connection stringcache_name(str, optional): Filename for metadata cache (enables caching)
Attributes:
engine: SQLAlchemy Engine objectSession: SQLAlchemy Session factory (scoped)metadata: SQLAlchemy MetaData objectdatabase_type: One ofDBTYPE_POSTGRESQL,DBTYPE_MYSQL,DBTYPE_SQLITE
session_scope
session_scope(db)
Context manager for transactional database operations.
Parameters:
db: DatabaseConnection instance
Usage:
with session_scope(db) as session:
# Your database operations
pass # Automatic commit on success, rollback on exception
MetadataCache
MetadataCache(dbc, filename, path=None)
Manages SQLAlchemy metadata caching.
Methods:
read(): Load metadata from cachewrite(metadata): Save metadata to cachecacheIsStale(): Check if cache needs refresh
MySQL Utilities
read_password_from_my_cnf(host=None, user=None, section=None, mycnf_path='~/.my.cnf')
Read password from MySQL configuration file.
Parameters:
host(str, optional): Hostname to match (case-sensitive)user(str, optional): Username to matchsection(str, optional): Option group to check (defaults to 'client')mycnf_path(str): Path to .my.cnf file
Returns: Password string or None
read_connection_options_from_my_cnf(section=None, mycnf_path='~/.my.cnf')
Read all connection options from MySQL configuration file.
Parameters:
section(str, optional): Option group to check (defaults to 'client')mycnf_path(str): Path to .my.cnf file
Returns: Dictionary with keys: host, user, password, database, port
Requirements
- Python 3.8+
- SQLAlchemy 2.0+
- Database drivers:
- PostgreSQL:
psycopg[binary] - MySQL:
pymysqlormysqlclient - SQLite: Built into Python
- PostgreSQL:
- Optional dependencies:
numpy- NumPy array supportcornish- Astronomy-specific geometric types
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT License - see LICENSE file for details.
Author
Demitri Muna
Links
Metadata
Release files for dm-dbcore 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| dm_dbcore-0.1.0.tar.gz | 24.3 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dm_dbcore-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 49.7 kB
Release files / dm_dbcore-0.1.0.tar.gz
| Download URL | dm_dbcore-0.1.0.tar.gz |
|---|---|
| Size | 24.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
448582771070f7e40d25adc715506b6f9c9462da61da4b0a67df0fa37b61ccb7
|
|
BLAKE2b-256 checksum How to use checksums |
68d13f03f9f64824d23ff2053c98ec24ae144a7b5b944ab6cc0510f402cd8d6c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|
Release files / dm_dbcore-0.1.0-py3-none-any.whl
| Download URL | dm_dbcore-0.1.0-py3-none-any.whl |
|---|---|
| Size | 25.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8e5c6f28720cb9987c5674bc7d742aaa05585ebb77e338b4682a4d12a4d9427e
|
|
BLAKE2b-256 checksum How to use checksums |
db259edb4b06490b48a598c86794ced0e5a038e8a0d943b447bf6b56821914fa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|
Security for dm-dbcore 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.