Cleaned up and retabulated metadata.py.

metadata-restructure
Emily Frost 4 years ago
parent 21ec564616
commit 2a95a93844
Signed by: Emily
GPG Key ID: AA5D42849F1CBDC9

@ -16,126 +16,124 @@ HASH_CHUNK_SIZE = 10485760 # 10mb
_db_session_maker = sqlalchemy.orm.sessionmaker() _db_session_maker = sqlalchemy.orm.sessionmaker()
_engine = None _engine = None
_configured = False _configured = False
_SQLBase = sqlalchemy.ext.declarative.declarative_base()
# TODO: Support DAT credit, DAT filenames, and checking DAT completeness.
#DatData = collections.namedtuple('DatData', 'UUID, name, website, version, image_list')
class MetadataDBSessionException(Exception): class MetadataDBSessionException(Exception):
'''This exception is raised when something goes wrong with a database session.''' '''This exception is raised when something goes wrong with a database session.'''
def _uuidgen(): def _uuidgen():
return str(uuid.uuid4()) return str(uuid.uuid4())
_SQLBase = sqlalchemy.ext.declarative.declarative_base() class Platform(_SQLBase):
'''SQLAlchemy ORM class for platform metadata.'''
__tablename__ = 'platforms'
id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.Sequence('platform_id_sequence'),
primary_key=True)
uuid = sqlalchemy.Column(sqlalchemy.String, nullable=False, default=_uuidgen)
fullname = sqlalchemy.Column(sqlalchemy.String, nullable=False)
shortcode = sqlalchemy.Column(sqlalchemy.String, unique=True, nullable=False)
class Release(_SQLBase): release_groups = sqlalchemy.orm.relationship('ReleaseGroup', order_by=ReleaseGroup.id,
'''SQLAlchemy ORM class for ROM image metadata.''' back_populates='platform')
__tablename__ = 'images'
id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.Sequence('image_id_sequence'),
primary_key=True)
uuid = sqlalchemy.Column(sqlalchemy.String, nullable=False, default=_uuidgen)
sha1sum = sqlalchemy.Column(sqlalchemy.String, unique=True, nullable=False)
format = sqlalchemy.Column(sqlalchemy.String, nullable=False)
region = sqlalchemy.Column(sqlalchemy.String)
version = sqlalchemy.Column(sqlalchemy.String, nullable=False)
disambiguation = sqlalchemy.Column(sqlalchemy.String)
release_group_id = sqlalchemy.Column(sqlalchemy.Integer,
sqlalchemy.ForeignKey('release_groups.id'))
release_group = sqlalchemy.orm.relationship('ReleaseGroup', back_populates='releases')
def __repr__(self):
return ('ROM Image: id: %s, uuid: %s, sha1sum: %s, release-group: %s, region: %s, '
'version: %s, disambiguation: %s' % (
self.id, self.uuid, self.sha1sum, self.release_group.name, self.region,
self.version, self.disambiguation))
class ReleaseGroup(_SQLBase): def __repr__(self):
'''SQLAlchemy ORM class for release group metadata.''' return 'Platform: id: %s, uuid: %s, fullname: %s, shortcode: %s' % (self.id, self.uuid,
__tablename__ = 'release_groups' self.fullname, self.shortcode)
id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.Sequence('image_id_sequence'),
primary_key=True)
uuid = sqlalchemy.Column(sqlalchemy.String, nullable=False, default=_uuidgen)
name = sqlalchemy.Column(sqlalchemy.String, unique=True, nullable=False)
platform_id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey('platforms.id'))
platform = sqlalchemy.orm.relationship('Platform', back_populates='release_groups')
images = sqlalchemy.orm.relationship('Release', back_populates='release_group')
def __repr__(self): class ReleaseGroup(_SQLBase):
return 'Release Group: id: %s, uuid: %s, name: %s, platform:%s' % (self.id, self.uuid, '''SQLAlchemy ORM class for release group metadata.'''
self.name, self.platform.fullname) __tablename__ = 'release_groups'
id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.Sequence('image_id_sequence'),
primary_key=True)
uuid = sqlalchemy.Column(sqlalchemy.String, nullable=False, default=_uuidgen)
name = sqlalchemy.Column(sqlalchemy.String, unique=True, nullable=False)
platform_id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey('platforms.id'))
platform = sqlalchemy.orm.relationship('Platform', back_populates='release_groups')
images = sqlalchemy.orm.relationship('Release', back_populates='release_group')
class Platform(_SQLBase): def __repr__(self):
'''SQLAlchemy ORM class for platform metadata.''' return 'Release Group: id: %s, uuid: %s, name: %s, platform:%s' % (self.id, self.uuid,
__tablename__ = 'platforms' self.name, self.platform.fullname)
id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.Sequence('platform_id_sequence'),
primary_key=True)
uuid = sqlalchemy.Column(sqlalchemy.String, nullable=False, default=_uuidgen)
fullname = sqlalchemy.Column(sqlalchemy.String, nullable=False)
shortcode = sqlalchemy.Column(sqlalchemy.String, unique=True, nullable=False)
release_groups = sqlalchemy.orm.relationship('ReleaseGroup', order_by=ReleaseGroup.id,
back_populates='platform')
def __repr__(self): class Release(_SQLBase):
return 'Platform: id: %s, uuid: %s, fullname: %s, shortcode: %s' % (self.id, self.uuid, '''SQLAlchemy ORM class for ROM image metadata.'''
self.fullname, self.shortcode) __tablename__ = 'images'
id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.Sequence('image_id_sequence'),
primary_key=True)
uuid = sqlalchemy.Column(sqlalchemy.String, nullable=False, default=_uuidgen)
sha1sum = sqlalchemy.Column(sqlalchemy.String, unique=True, nullable=False)
format = sqlalchemy.Column(sqlalchemy.String, nullable=False)
region = sqlalchemy.Column(sqlalchemy.String)
version = sqlalchemy.Column(sqlalchemy.String, nullable=False)
disambiguation = sqlalchemy.Column(sqlalchemy.String)
release_group_id = sqlalchemy.Column(sqlalchemy.Integer,
sqlalchemy.ForeignKey('release_groups.id'))
release_group = sqlalchemy.orm.relationship('ReleaseGroup', back_populates='releases')
def __repr__(self):
return ('ROM Image: id: %s, uuid: %s, sha1sum: %s, release-group: %s, region: %s, '
'version: %s, disambiguation: %s' % (
self.id, self.uuid, self.sha1sum, self.release_group.name, self.region,
self.version, self.disambiguation))
def configure(db_path): def configure(db_path):
''' '''
Configure and initialize the database for the entire module. Configure and initialize the database for the entire module.
Currently, only SQLite is supported. Currently, only SQLite is supported.
db_path: Path for the SQLite database db_path: Path for the SQLite database
''' '''
_engine = sqlalchemy.create_engine('sqlite:///%s' % db_path) _engine = sqlalchemy.create_engine('sqlite:///%s' % 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 _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):
''' '''
Search the database for entries matching the given constraints. Search the database for entries matching the given constraints.
session: SQLAlchemy session, presumably from get_db_session session: SQLAlchemy session, presumably from get_db_session
table_object: SQLAlchemy ORM table object, defined in the file above table_object: SQLAlchemy ORM table object, defined in the file above
constraints: key-value pairs to match against specific fields in the database constraints: key-value pairs to match against specific fields in the database
Note: Currently, only the query.ilike method is supported. This is intended to Note: Currently, only the query.ilike method is supported. This is intended to
eventually support the entire range of available filters. eventually support the entire range of available filters.
''' '''
query = session.query(table_object) query = session.query(table_object)
for key, value in constraints.items(): for key, value in constraints.items():
query = query.filter(getattr(table_object, key).ilike('%%%s%%' % value)) query = query.filter(getattr(table_object, key).ilike('%%%s%%' % value))
item_list = [] item_list = []
for item in query: for item in query:
item_list.append(item) item_list.append(item)
return item_list return item_list
@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: There's probably a more reliable way of knowing whether the database was configured. # TODO: There's probably a more reliable way of knowing whether the database was configured.
if not _configured: if not _configured:
raise MetadataDBSessionException('Tried to get session without configuring a database.') raise MetadataDBSessionException('Tried to get session without configuring a database.')
session = _db_session_maker() session = _db_session_maker()
try: try:
yield session yield session
except: except:
# TODO: Decide which exceptions to handle/eat here and which ones belong in UI. # TODO: Decide which exceptions to handle/eat here and which ones belong in UI.
# This one is okay to put off until you start really building UI. # This one is okay to put off until you start really building UI.
session.rollback() session.rollback()
raise raise
else: else:
session.commit() session.commit()
finally: finally:
session.close() session.close()

@ -33,7 +33,6 @@ A container for all languages and versions of a release. For example, the Star F
* releases * releases
- A list containing all releases in this release group. - A list containing all releases in this release group.
## Release ## Release
A single release of a game. For example: Star Fox 64 (U) v1.2 A single release of a game. For example: Star Fox 64 (U) v1.2

Loading…
Cancel
Save