Refactor backend and add registry build workflow
Build and publish Docker image / build-and-publish (push) Successful in 2m45s
Build and publish Docker image / build-and-publish (push) Successful in 2m45s
This commit is contained in:
commit
c177d7981d
43 files changed
+18124
No files matched your search
@@ -0,0 +1,85 @@
|
||||
import logging
|
||||
import psycopg2
|
||||
import sqlite3
|
||||
|
||||
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class PostgresCursorWrapper:
|
||||
def __init__(self, cursor):
|
||||
self.cursor = cursor
|
||||
|
||||
def execute(self, query, args=None):
|
||||
# Convert SQLite ? placeholders to Postgres %s
|
||||
if query:
|
||||
# Replace ? with %s
|
||||
pg_query = query.replace('?', '%s')
|
||||
|
||||
# Handle BLOB to BYTEA differences if necessary
|
||||
# (psycopg2 usually handles bytes objects correctly as BYTEA)
|
||||
else:
|
||||
pg_query = query
|
||||
|
||||
try:
|
||||
return self.cursor.execute(pg_query, args)
|
||||
except Exception as e:
|
||||
logger.error(f"SQL Error: {e} | Query: {pg_query} | Args: {args}")
|
||||
raise e
|
||||
|
||||
def fetchall(self):
|
||||
return self.cursor.fetchall()
|
||||
|
||||
def fetchone(self):
|
||||
return self.cursor.fetchone()
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.cursor, name)
|
||||
|
||||
class PostgresConnectionWrapper:
|
||||
def __init__(self, conn):
|
||||
self.conn = conn
|
||||
# Enable autocommit or manage it manually?
|
||||
# sqlite3 connection in app.py context manager does not seem to set autocommit,
|
||||
# but the context manager does commit() or rollback().
|
||||
|
||||
def cursor(self):
|
||||
# Use RealDictCursor to mimic sqlite3.Row (dictionary access)
|
||||
return PostgresCursorWrapper(self.conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor))
|
||||
|
||||
def commit(self):
|
||||
return self.conn.commit()
|
||||
|
||||
def rollback(self):
|
||||
return self.conn.rollback()
|
||||
|
||||
def close(self):
|
||||
return self.conn.close()
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.conn, name)
|
||||
|
||||
def get_db_connection(database_url):
|
||||
"""
|
||||
Factory function to return a connection object.
|
||||
Supports 'sqlite://' (or just file path) and 'postgresql://'.
|
||||
"""
|
||||
if database_url.startswith('postgres://') or database_url.startswith('postgresql://'):
|
||||
try:
|
||||
conn = psycopg2.connect(database_url)
|
||||
return PostgresConnectionWrapper(conn)
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to connect to Postgres: {e}")
|
||||
raise e
|
||||
else:
|
||||
# Fallback to SQLite
|
||||
# If it starts with sqlite:///, strip it
|
||||
if database_url.startswith('sqlite:///'):
|
||||
db_path = database_url.replace('sqlite:///', '')
|
||||
else:
|
||||
db_path = database_url
|
||||
|
||||
conn = sqlite3.connect(db_path)
|
||||
conn.row_factory = sqlite3.Row
|
||||
return conn
|
||||
Reference in new issue
Block a user