diff --git a/app/__pycache__/database.cpython-312.pyc b/app/__pycache__/database.cpython-312.pyc new file mode 100644 index 0000000..89b25ba Binary files /dev/null and b/app/__pycache__/database.cpython-312.pyc differ diff --git a/app/__pycache__/utils.cpython-312.pyc b/app/__pycache__/utils.cpython-312.pyc new file mode 100644 index 0000000..b6b2101 Binary files /dev/null and b/app/__pycache__/utils.cpython-312.pyc differ diff --git a/app/app.py b/app/app.py new file mode 100755 index 0000000..31b029b --- /dev/null +++ b/app/app.py @@ -0,0 +1,60 @@ +import os +import typer + +from pathlib import Path +from database import Shelf +from utils import die + + + +app = typer.Typer() +project_subcommand = typer.Typer() +app.add_typer(project_subcommand, name='project') + +entries: dict = { + 'dirs': [], + 'projects': [], + 'config': {} +} + + + +@project_subcommand.command('add') +def project_add(path: Path, name: str = None, runner: str = None, editor: str = 'code', multi: bool = False): + + global entries + + if multi: + die('Cannot specify name for a dir', 2) if name else None + + for dir in os.listdir(path): + entries['dirs'].append(create_entry(path/dir, name, runner, editor)) + + else: + entries['projects'].append(create_entry(path, name, runner, editor)) + + with Shelf('spyglass') as shelf: + shelf.update(entries) + + + +def create_entry(path: Path, name: str, runner: str, editor: str): + if not name: + name = os.path.dirname(path) + + if not runner: + runner = None + + if not editor: + editor = None + + return {name: {'path': str(path.resolve()), 'runner': str(path/runner) if runner else None, 'editor': editor}} + + + +def main(): + app() + + +if __name__ == '__main__': + main() diff --git a/app/database.py b/app/database.py new file mode 100755 index 0000000..47dc28a --- /dev/null +++ b/app/database.py @@ -0,0 +1,52 @@ +import os +import shelve as shelf +import platform +from pathlib import Path +from utils import die + + +class Shelf: + def __init__(self, filename: str): + self.file: Path = None + self.db = None + + os_type: str = platform.system() + + if os_type == 'Linux': + self.file = os.environ.get('HOME') + '/.local/share/' + filename + elif os_type == 'Windows': + self.file = os.environ.get('APPDATA') + filename + else: + die('OS not supported', 2) + + + def __enter__(self): + # Open the shelf and load data into self.db + self.db = shelf.open(self.file, writeback=True) + return self + + def __exit__(self, exc_type, exc_value, traceback): + # Save any updates to the shelf + if self.db is not None: + self.db.sync() + self.db.close() + + def update(self, entries: dict): + db_values = self.db.values() + + if db_values: + dirs, projects, _ = db_values + new_dirs, new_projects, _ = entries.values() + + for dir in new_dirs: + if dir not in dirs: + self.db['dirs'].append(dir) + + for project in new_projects: + if project not in projects: + self.db['projects'].append(project) + else: + for k, v in entries.items(): + self.db[k] = v + + diff --git a/app/utils.py b/app/utils.py new file mode 100644 index 0000000..e3ac1ed --- /dev/null +++ b/app/utils.py @@ -0,0 +1,5 @@ + +def die(msg: str, code: str): + print(msg) + exit(code) + diff --git a/requirements.txt b/requirements.txt index 0e56538..466178a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,4 @@ typer[all] -pyYAML +attrs >= 23.2.0 +shelve2 >= 1.0 +pyYAML >= 6.0.1 diff --git a/spyglass.py b/spyglass.py deleted file mode 100755 index 93ccabe..0000000 --- a/spyglass.py +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/python - -import os -import yaml -import platform -from pathlib import Path -# from rich import print - -import typer - - -app = typer.Typer() -project_subcommand = typer.Typer() -app.add_typer(project_subcommand, name='project') - -entries: list = [] - - -@project_subcommand.command('add') -def project_add(path: Path, name: str = None, runner: str = None, editor: str = 'code', multi: bool = False): - - global entries - - if multi: - if name: - print('\n[bold red]Cannot name multiple projects the same.\n') - exit(69) - - for dir in os.listdir(path): - print(dir) - entries.append(assamble_entry(path/dir, name, runner, editor)) - else: - entries.append(assamble_entry(path, name, runner, editor)) - - for project in entries: - store_project(project) - - - - - -def get_database_path(): - database: str = None - os_type: str = platform.system() - - if os_type == 'Linux': - database = os.environ.get('HOME') + '/.local/share/spyglass-db.yaml' - elif os_type == 'Windows': - database = os.environ.get('APPDATA') + 'spyglass-db.yaml' - else: - print('OS not supported') - exit(69) - - return database - - - -def store_project(project: dict): - database: str = get_database_path() - - if not os.path.exists(database): - with open(database, 'w') as f: - f.write('projects:') - data = None - with open(database, 'r') as f: - data = yaml.safe_load(f) - - project_list: list = [proj for proj in data['projects'] if os.path.isdir(proj)] - - print(project_list) - - if project not in project_list: - project_list.append(project) - else: - print('Project already exists') - - with open(database, 'w') as f: - yaml.safe_dump(data, f) - - -def assamble_entry(path: Path, name: str, runner: str, editor: str): - if not name: - name = os.path.dirname(path) - - if not runner: - runner = 'None' - - if not editor: - editor = 'code' - - return {name: {'path': str(path), 'runner': str(path/runner), 'editor': editor}} - - - -def main(): - app() - - -if __name__ == '__main__': - main()