|
|
|
@ -5,8 +5,6 @@ Everything needed to interact with the metadata database; namely SQL ORM objects
|
|
|
|
generator for the actual database, and a handful of convenience functions.
|
|
|
|
generator for the actual database, and a handful of convenience functions.
|
|
|
|
'''
|
|
|
|
'''
|
|
|
|
import contextlib
|
|
|
|
import contextlib
|
|
|
|
import collections
|
|
|
|
|
|
|
|
import hashlib
|
|
|
|
|
|
|
|
import uuid
|
|
|
|
import uuid
|
|
|
|
|
|
|
|
|
|
|
|
import sqlalchemy
|
|
|
|
import sqlalchemy
|
|
|
|
@ -17,9 +15,13 @@ import sqlalchemy.orm
|
|
|
|
HASH_CHUNK_SIZE = 10485760 # 10mb
|
|
|
|
HASH_CHUNK_SIZE = 10485760 # 10mb
|
|
|
|
_db_session_maker = sqlalchemy.orm.sessionmaker()
|
|
|
|
_db_session_maker = sqlalchemy.orm.sessionmaker()
|
|
|
|
_engine = None
|
|
|
|
_engine = None
|
|
|
|
|
|
|
|
_configured = False
|
|
|
|
|
|
|
|
|
|
|
|
# TODO: Support DAT credit, DAT filenames, and checking DAT completeness.
|
|
|
|
# TODO: Support DAT credit, DAT filenames, and checking DAT completeness.
|
|
|
|
DatData = collections.namedtuple('DatData', 'UUID, name, website, version, image_list')
|
|
|
|
#DatData = collections.namedtuple('DatData', 'UUID, name, website, version, image_list')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class MetadataDBSessionException(Exception):
|
|
|
|
|
|
|
|
'''This exception is raised when something goes wrong with a database session.'''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _uuidgen():
|
|
|
|
def _uuidgen():
|
|
|
|
@ -29,7 +31,6 @@ _SQLBase = sqlalchemy.ext.declarative.declarative_base()
|
|
|
|
|
|
|
|
|
|
|
|
class Release(_SQLBase):
|
|
|
|
class Release(_SQLBase):
|
|
|
|
'''SQLAlchemy ORM class for ROM image metadata.'''
|
|
|
|
'''SQLAlchemy ORM class for ROM image metadata.'''
|
|
|
|
# TODO: Split filenames into more meaningful metadata.
|
|
|
|
|
|
|
|
__tablename__ = 'images'
|
|
|
|
__tablename__ = 'images'
|
|
|
|
id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.Sequence('image_id_sequence'),
|
|
|
|
id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.Sequence('image_id_sequence'),
|
|
|
|
primary_key=True)
|
|
|
|
primary_key=True)
|
|
|
|
@ -94,6 +95,7 @@ def configure(db_path):
|
|
|
|
|
|
|
|
|
|
|
|
_SQLBase.metadata.create_all(_engine)
|
|
|
|
_SQLBase.metadata.create_all(_engine)
|
|
|
|
_db_session_maker.configure(bind=_engine)
|
|
|
|
_db_session_maker.configure(bind=_engine)
|
|
|
|
|
|
|
|
_configured = True
|
|
|
|
|
|
|
|
|
|
|
|
# TODO: Passing the session object is a little clunky. Maybe there's a way to infer it somehow?
|
|
|
|
# TODO: Passing the session object is a little clunky. Maybe there's a way to infer it somehow?
|
|
|
|
def search(session, table_object, **constraints):
|
|
|
|
def search(session, table_object, **constraints):
|
|
|
|
@ -120,7 +122,10 @@ def search(session, table_object, **constraints):
|
|
|
|
@contextlib.contextmanager
|
|
|
|
@contextlib.contextmanager
|
|
|
|
def get_db_session():
|
|
|
|
def get_db_session():
|
|
|
|
'''Get a SQLAlchemy database session with a proper context object. '''
|
|
|
|
'''Get a SQLAlchemy database session with a proper context object. '''
|
|
|
|
# TODO: Raise an exception if _db_session_maker() isn't configured.
|
|
|
|
# TODO: There's probably a more reliable way of knowing whether the database was configured.
|
|
|
|
|
|
|
|
if not _configured:
|
|
|
|
|
|
|
|
raise MetadataDBSessionException('Tried to get session without configuring a database.')
|
|
|
|
|
|
|
|
|
|
|
|
session = _db_session_maker()
|
|
|
|
session = _db_session_maker()
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
yield session
|
|
|
|
yield session
|
|
|
|
|