diff --git a/lark/__init__.py b/lark/__init__.py new file mode 100644 index 0000000..2ae2839 --- /dev/null +++ b/lark/__init__.py @@ -0,0 +1 @@ +pass diff --git a/lark/cli/__init__.py b/lark/cli/__init__.py new file mode 100644 index 0000000..81d934e --- /dev/null +++ b/lark/cli/__init__.py @@ -0,0 +1,118 @@ +import argparse +import copy +import dataclasses +import os.path +import xdg + +import lark.cli.model +from lark import metadata + +# TODO: This stuff goes in an eventual config module/class. +SQLITE_FILENAME = 'metadata.db' +data_path = os.path.join(xdg.XDG_DATA_HOME, 'lark') + +# TODO: This is pretty clunky, maybe it can be redesigned? +ALIASES = { + 'verbs': { + 'list': ['list', 'ls'], + 'add': ['add', 'a'], + 'modify': ['modify', 'mod'], + 'remove': ['remove', 'rm', 'delete', 'del'], + 'test': ['test'], + }, + 'objects': { + 'platform': ['platform', 'platforms'], + }, + } + +parser = argparse.ArgumentParser('Lark') +parser.add_argument('verb') +parser.add_argument('object') + +parser.add_argument('parameters', nargs=argparse.REMAINDER) + +args = parser.parse_args() + +metadata.configure(os.path.join(data_path, SQLITE_FILENAME)) + +def cli_init(): + if args.verb in ALIASES['verbs']['list']: + verb_list() + + elif args.verb in ALIASES['verbs']['add']: + verb_add() + + elif args.verb in ALIASES['verbs']['modify']: + verb_modify() + + elif args.verb in ALIASES['verbs']['remove']: + verb_remove() + + elif args.verb in ALIASES['verbs']['test']: + verb_test() + + else: + print('Verb %s was not recognized.' % args.verb) + +# TODO: Probably make a verbs submodule. +def verb_list(): + + if args.object in ALIASES['objects']['platform']: + filters = {} + + with metadata.get_db_session() as session: + print(metadata.search(session, metadata.Platform, **filters)) + + else: + error_unsupported_object() + +def verb_add(): + + if args.object in ALIASES['objects']['platform']: + parameters = parse_parameters(args.parameters) + # TODO: Ask for confirmation. + # TODO: Data editor + + new_platform = metadata.Platform(**parameters) + with metadata.get_db_session() as session: + session.add(new_platform) + print('Added platform %s.' % new_platform.shortcode) + + else: + error_unsupported_object() + +def verb_modify(): + if args.object in ALIASES['objects']['platform']: + parameters = parse_parameters(args.parameters) + + with metadata.get_db_session() as session: + platforms = metadata.search(session, metadata.Platform, **parameters) + platform_to_modify = lark.cli.model.prompt_select_from_list( + platforms, 'Select a platform to modify.') + + lark.cli.model.editor(platform_to_modify) + +def verb_remove(): + if args.object in ALIASES['objects']['platform']: + parameters = parse_parameters(args.parameters) + + with metadata.get_db_session() as session: + platforms = metadata.search(session, metadata.Platform, **parameters) + for platform in platforms: + print('Removing %s.' % platform.fullname) + session.delete(platform) + +def verb_test(): + pass + +# TODO: Probably make an errors submodule. +def error_unsupported_object(): + print('Verb %s does not support object %s.' % (args.verb, args.object)) + +def parse_parameters(parameters_list): + parameters = {} + for parameter_string in parameters_list: + key, value = parameter_string.split('=') + parameters[key] = value + + return parameters diff --git a/lark/cli/model.py b/lark/cli/model.py new file mode 100644 index 0000000..f750e22 --- /dev/null +++ b/lark/cli/model.py @@ -0,0 +1,59 @@ +''' +model.py + +Methods for interacting with Lark's database models. +''' + +import lark.metadata +# TODO: This is a big fucking mess. Don't roll your own library, use prompt-toolkit or something. +IGNORED_CLASS_KEYS = ['id', '_sa_instance_state'] +def editor(data_object): + + data_dict = {} + for key, value in data_object.__dict__.items(): + if key in IGNORED_CLASS_KEYS: + pass + else: + data_dict[key] = {'nullable': data_object.__table__.columns.get(key).nullable, + 'auto': False, + 'unique': data_object.__table__.columns.get(key).nullable, + 'value': value} + + if key == 'uuid': + if value is None: + data_dict[key]['auto'] = True + data_dict[key]['value'] = lark.metadata._uuidgen() + + while True: + editable_list = [] + for key, properties in data_dict.items(): + editable_list.append('%s: %s' % (key, properties['value'])) + + user_input = prompt_select_from_list(editable_list, 'Select a value to edit:', ['abort']) + + if user_input == 'abort': + break + +def prompt_select_from_list(choices, prompt, commands=[]): + if len(choices) == 1: + return choices[0] + + index = 0 + user_choice = None + for choice in choices: + print('%s: %s' % (index, choice)) + index += 1 + + print(prompt) + while user_choice is None: + user_input = input('[0-%s]: ' % (len(choices)-1)) + if user_input.isdigit() and int(user_input) >= 0 and int(user_input) <= len(choices)-1: + user_choice = choices[int(user_input)] + + elif str(user_input) in commands: + user_choice = user_input + + else: + print('%s is neither a choice nor a command.' % user_input) + + return user_choice diff --git a/lark/metadata.py b/lark/metadata.py index 1dd7bc3..76f07eb 100644 --- a/lark/metadata.py +++ b/lark/metadata.py @@ -46,9 +46,14 @@ class Release(_SQLBase): release_group = sqlalchemy.orm.relationship('ReleaseGroup', back_populates='releases') def __repr__(self): + if self.release_group is None: + release_group_name = '[Orphan]' + else: + release_group_name = self.release_group.name + 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.id, self.uuid, self.sha1sum, release_group_name, self.region, self.version, self.disambiguation)) class ReleaseGroup(_SQLBase): @@ -61,7 +66,7 @@ class ReleaseGroup(_SQLBase): 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') + releases = sqlalchemy.orm.relationship('Release', back_populates='release_group') def __repr__(self): return 'Release Group: id: %s, uuid: %s, name: %s, platform:%s' % (self.id, self.uuid, diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..a2cdd25 --- /dev/null +++ b/setup.py @@ -0,0 +1,15 @@ +import setuptools + +setuptools.setup( + name='lark', + version='0.1', + py_modules=['lark'], + install_requires=[ + 'click', + 'sqlalchemy', + 'xdg',], + entry_points=''' + [console_scripts] + lark=lark.cli:cli_init + ''', +)