From 6662f94e6f224bcef426323d80f69306b7b294e9 Mon Sep 17 00:00:00 2001 From: technocake Date: Thu, 11 Jul 2019 02:12:38 +0200 Subject: [PATCH] cleanup --- README.md | 7 ++++--- bin/goto | 7 +++---- bin/project | 28 +++++++++++++++------------- goto/gotomagic/git.py | 15 ++------------- goto/gotomagic/magic.py | 23 ++++++++++++++++++----- goto/gotomagic/text/text.py | 6 ++++++ goto/gotomagic/utils.py | 18 ++++++++++++++++++ goto/settings.py | 3 +++ goto/tests/test_end_to_end.sh | 9 +++++---- goto/tests/test_gotomagic.py | 20 +++++++++++++------- goto/the_real_goto.py | 32 +++++++++++++++++++++----------- requirements.txt | 1 + requirements_dev.txt | 1 + setup.py | 1 + tox.ini | 2 ++ 15 files changed, 113 insertions(+), 60 deletions(-) create mode 100644 goto/settings.py diff --git a/README.md b/README.md index de252e9..044efd0 100644 --- a/README.md +++ b/README.md @@ -37,9 +37,9 @@ Do the same as above, but **open git bash as Administrator** #### Linux - User Site install On linux, the recommended way to install goto is by `pip install --user magicgoto` -This requires that you have your User site bin in your path. -Usually this is `~/.local/bin`. So adding `PATH="${HOME}/.local/bin:$PATH"` to -your rcfile should do the trick in most cases. +> This requires that you have your User site bin in your path. +> Usually this is `~/.local/bin`. So adding `PATH="${HOME}/.local/bin:$PATH"` to +> your rcfile should do the trick in most cases. ### Commands @@ -125,6 +125,7 @@ You tell Goto with the command: + #### How does Goto know which shortcuts there are in the project? Define them once, and use them a thousand times. By this command: diff --git a/bin/goto b/bin/goto index 98c98e6..7a1855b 100755 --- a/bin/goto +++ b/bin/goto @@ -7,7 +7,7 @@ function _goto_main { - local PROJECT PROJECTFILE URI + local PROJECT URI # If goto is run in sourced mode, contiune. # Else: print warning. NO EXIT statement. @@ -22,7 +22,6 @@ function _goto_main { PROJECT=$(cat "${GOTOPATH}/active-project") - PROJECTFILE="${GOTOPATH}/projects/${PROJECT}.json" # Catching deactivated state # TODO: make a better way to print to stderr @@ -59,7 +58,7 @@ function _goto_main { && ! "$1" =~ ^(list|help|add|rm|mv|rename|update|copy|subl|vscode|intelij|idea|show|cd|open)$ \ && ! "$1" =~ ^"--" \ && ! "$1" =~ ^"-" \ - ]]; then + ]]; then # if run like: goto URI=$(goto show "$1") @@ -79,7 +78,7 @@ function _goto_main { # General case if [ -n "$(command -v the_real_goto.py)" ]; then - the_real_goto.py "$PROJECTFILE" "$@" + the_real_goto.py "$PROJECT" "$@" else echo "Error the_real_goto.py not found" >&2 return 1 diff --git a/bin/project b/bin/project index 4e78ef1..71ced18 100755 --- a/bin/project +++ b/bin/project @@ -2,8 +2,6 @@ . _gotoutils # load common utility functions load_gotopath -STATEDIR="$GOTOPATH" - _usage() { echo "Usage: project [add ] | [list]" @@ -16,14 +14,18 @@ _usage() { } _addproject() { - touch "$STATEDIR/projects/$1" + local PROJECT_FOLDER="$GOTOPATH/projects/$1" + if [[ ! -d $PROJECT_FOLDER ]]; then + mkdir "$PROJECT_FOLDER" + else + echo "Project $1 already exists" + fi } _rmproject() { if prompt "Are you sure you want to delete project $1? [y|n]: "; then - rm "$STATEDIR/projects/$1" - rm "$STATEDIR/projects/$1.json" - echo "Removed project $2" + rm -rf "$GOTOPATH/projects/$1" + echo "Removed project $1" else echo echo "Aborting delete of project $1" @@ -31,16 +33,16 @@ _rmproject() { } _listprojects() { - ls "$STATEDIR/projects" | grep -v .json + ls "$GOTOPATH/projects/" } _deactivate_project() { - echo "" > "$STATEDIR/active-project" + echo "" > "$GOTOPATH/active-project" } _changeproject() { - if [ -f "$STATEDIR/projects/$1" ]; then - echo "$1" > "$STATEDIR/active-project" + if [ -d "$GOTOPATH/projects/$1" ]; then + echo "$1" > "$GOTOPATH/active-project" echo "active project is now: $1" else echo "Warning - tried to change to a non existing project." @@ -52,7 +54,7 @@ _changeproject() { } _showactiveproject() { - cat "$STATEDIR/active-project" + cat "$GOTOPATH/active-project" } # --------------------------- @@ -90,9 +92,9 @@ if [ "$1" = "rm" ] then if [ "$2" = "" ] ; then _usage + exit 1 else - _rmproject "$2" "$3" - # TODO if active project == removed what to do? _changeproject "$2" + _rmproject "$2" _deactivate_project exit 0 fi diff --git a/goto/gotomagic/git.py b/goto/gotomagic/git.py index 55e55b5..d2771bf 100644 --- a/goto/gotomagic/git.py +++ b/goto/gotomagic/git.py @@ -3,11 +3,7 @@ import sys import git from .magic import GotoMagic - - -# HACK HACK -GOTOPATH = os.environ.get('GOTOPATH', os.path.expanduser('~/.goto')) - +from . import utils class GitMagic(): @@ -25,13 +21,7 @@ class GitMagic(): def __init__(self, project): """ Loads json from jfile """ - shared_file = os.path.join( - GOTOPATH, 'projects', 'shared', project, '{}.json'.format(project) - ) - - shared_folder = os.path.dirname(shared_file) - if not os.path.exists(shared_folder): - os.makedirs(shared_folder) + utils.create_project_folder(project, 'shared') if not is_git_repo(shared_folder): self.repo = git.Repo.init(shared_folder) @@ -55,7 +45,6 @@ def share(self): gotohub.pull('master') gotohub.push('master') - def save(self): """ Saves the magic to jsonfile jfile """ self.magic.save() diff --git a/goto/gotomagic/magic.py b/goto/gotomagic/magic.py index 33ad003..aad174f 100644 --- a/goto/gotomagic/magic.py +++ b/goto/gotomagic/magic.py @@ -2,6 +2,10 @@ """ Magic is stored here. """ +from __future__ import absolute_import, unicode_literals +from builtins import dict, str # redefine dict and str to be py3-like in py2. +# http://johnbachman.net/building-a-python-23-compatible-unicode-sandwich.html + import json import codecs import os @@ -9,6 +13,8 @@ from . import text from .text import print_text from .text import GotoWarning +from .. import settings +from . import utils class GotoMagic(): @@ -21,10 +27,15 @@ class GotoMagic(): tl-dr: saving magic as json. """ - def __init__(self, jfile): + def __init__(self, project, degree='private', GOTOPATH=None): """ Loads json from jfile """ - self.jfile = jfile - self.magic = load_magic(jfile) + if GOTOPATH is None: + GOTOPATH = settings.GOTOPATH + self.project = project + utils.create_project_folder(project, degree, GOTOPATH) + self.jfile = os.path.join( + GOTOPATH, 'projects', project, degree, "{}.json".format(project)) + self.magic = load_magic(self.jfile) def reload(self): """ reload the magic """ @@ -195,10 +206,12 @@ def save_magic(jfile, magic): "saves the magic shortcuts as json into a file" with codecs.open(jfile, 'w+', encoding='utf-8') as f: try: - data = json.dumps(magic, sort_keys=True, indent=4, ensure_ascii=False) + data = str(json.dumps(magic, sort_keys=True, indent=4, ensure_ascii=False)) f.write(data) except Exception as e: print_text( text.error.messages["magic_could_not_be_saved"], - message=e.message + message=str(e) ) + # TODO: handle more elegantly + exit(1) diff --git a/goto/gotomagic/text/text.py b/goto/gotomagic/text/text.py index fc2d595..6846a34 100644 --- a/goto/gotomagic/text/text.py +++ b/goto/gotomagic/text/text.py @@ -20,6 +20,9 @@ def message(self): "Missing error message with name: {}".format(self.name)) return text.format(**self.kwargs) + def __str__(self): + return self.message + class GotoWarning: def __init__(self, name, **kwargs): @@ -36,6 +39,9 @@ def message(self): "Missing warning message with name: {}".format(self.name)) return text.format(**self.kwargs) + def __str__(self): + return self.message + def print_text(text, **kwargs): print(text.format(**kwargs)) diff --git a/goto/gotomagic/utils.py b/goto/gotomagic/utils.py index e2e6b18..7f0834c 100644 --- a/goto/gotomagic/utils.py +++ b/goto/gotomagic/utils.py @@ -1,6 +1,7 @@ import os import sys from ..gotomagic.text import GotoWarning +from .. import settings def detect_platform(): @@ -23,6 +24,23 @@ def is_file(raw_uri): return os.path.exists(candidate) +def create_project_folder(project, degree='private', GOTOPATH=None): + ''' + Creates project folder in goto state folders, + if not already existing. + + degree can be either private, public or shared + + ''' + if GOTOPATH is None: + GOTOPATH = settings.GOTOPATH + + project_folder = os.path.join(GOTOPATH, 'projects', project, degree) + + if not os.path.exists(project_folder): + os.makedirs(project_folder) + + def detect_unescaped_ampersand_url(): ''' Detects if user has entered a url with ampersand, diff --git a/goto/settings.py b/goto/settings.py new file mode 100644 index 0000000..17ee1bd --- /dev/null +++ b/goto/settings.py @@ -0,0 +1,3 @@ +import os +# HACK HACK +GOTOPATH = os.environ.get('GOTOPATH', os.path.expanduser('~/.goto')) \ No newline at end of file diff --git a/goto/tests/test_end_to_end.sh b/goto/tests/test_end_to_end.sh index a6ee2e2..296132f 100755 --- a/goto/tests/test_end_to_end.sh +++ b/goto/tests/test_end_to_end.sh @@ -22,7 +22,8 @@ function set_up { echo "setting up tests" create_goto_folders "$GOTOPATH" touch "$OUTPUTFILE" - PROJECTFILE="$GOTOPATH/projects/$TESTPROJECT.json" + PROJECTFOLDER="$GOTOPATH/projects/$TESTPROJECT" + PROJECTFILE="$PROJECTFOLDER/private/$TESTPROJECT.json" } @@ -179,8 +180,8 @@ function test_04_switch_to_nonexistent_project { function test_05_add_project { _cmd_should_succeed "project add $TESTPROJECT" - if [ ! -f "${GOTOPATH}/projects/${TESTPROJECT}" ]; then - _fail_test "project file not created" + if [ ! -d "$PROJECTFOLDER" ]; then + _fail_test "project folder not created" fi _cmd_should_succeed "goto list" } @@ -239,7 +240,7 @@ function test_07_goto { _projectfile_should_contain "$magicword" } -function TODO_test_08_goto_add_æøå { +function test_08_goto_add_æøå { existing_magicword="test_æøå" nonexisting_magicword="IDoNotExist" uri="http://example.com/æøå" diff --git a/goto/tests/test_gotomagic.py b/goto/tests/test_gotomagic.py index b4f0380..128f0b2 100644 --- a/goto/tests/test_gotomagic.py +++ b/goto/tests/test_gotomagic.py @@ -1,15 +1,23 @@ -from unittest import TestCase +from unittest import TestCase, skip import os +import shutil from ..gotomagic.magic import GotoMagic -tmpgotofile = 'testgotofile.json' + +TMPGOTOPATH = '/tmp/.goto-unit-tests' +project = '__testgoto__' +tmpgotofile = os.path.join(TMPGOTOPATH, 'projects', project, 'private', '%s.json' % project) # noqa + + +# now, these tests would run on the real GOTOPATH. +# Find a way to point gotopath away first. class TestMagic(TestCase): def setUp(self): """ Sets up goto magic to use tmp file """ - self.magic = GotoMagic(tmpgotofile) + self.magic = GotoMagic(project, degree='private', GOTOPATH=TMPGOTOPATH) def test_adding_shortcut(self): """ Adding shortcuts through the gotomagic module""" @@ -22,10 +30,8 @@ def test_adding_shortcut(self): def tearDown(self): """ Empty testgotofile after each test """ - if os.path.exists(tmpgotofile): + if os.path.exists(TMPGOTOPATH): # Displaying contents of testfile with open(tmpgotofile) as f: print(f.read()) - os.remove(tmpgotofile) - - + shutil.rmtree(TMPGOTOPATH) diff --git a/goto/the_real_goto.py b/goto/the_real_goto.py index 7618a00..3127656 100755 --- a/goto/the_real_goto.py +++ b/goto/the_real_goto.py @@ -2,11 +2,14 @@ # code: utf-8 'Goto - the magic project that takes you where you need to be, now.' from __future__ import absolute_import, unicode_literals +from builtins import dict, str # redefine dict and str to be py3-like in py2. +# http://johnbachman.net/building-a-python-23-compatible-unicode-sandwich.html import os import sys import codecs +from .settings import GOTOPATH from .gotomagic import text from .gotomagic.magic import GotoMagic from .gotomagic.utils import healthcheck @@ -22,18 +25,11 @@ def main(): - err = healthcheck() - if err: - print(err.message) - exit(2) + exit_if_unhealthy() + exit_with_usage_if_needed() - if len(sys.argv) < 3: - output, _ = commands.usage() - print(output) - exit(0) - - jfile = sys.argv[1] - magic = GotoMagic(jfile) + project = sys.argv[1] + magic = GotoMagic(project) command = sys.argv[2] args = sys.argv[3:] @@ -46,6 +42,20 @@ def main(): exit(0) +def exit_if_unhealthy(): + err = healthcheck() + if err: + print(err.message) + exit(2) + + +def exit_with_usage_if_needed(): + if len(sys.argv) < 3: + output, _ = commands.usage() + print(output) + exit(0) + + def run_command(magic, command, args): if command in ['help', '-h', '/?', '--help']: return commands.usage() diff --git a/requirements.txt b/requirements.txt index 345455e..6e69511 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ pyperclip gitpython +future diff --git a/requirements_dev.txt b/requirements_dev.txt index 5ce75ce..4411b85 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -1,3 +1,4 @@ tox pyperclip gitpython +future diff --git a/setup.py b/setup.py index aef6f53..a45041d 100644 --- a/setup.py +++ b/setup.py @@ -26,6 +26,7 @@ install_requires=[ 'pyperclip', 'gitpython', + 'future', ], scripts=[ 'bin/goto', diff --git a/tox.ini b/tox.ini index f8c4a07..dc2a844 100644 --- a/tox.ini +++ b/tox.ini @@ -4,6 +4,8 @@ envlist = py27,py37 [testenv] deps= pytest + -rrequirements_dev.txt + commands = # NOTE: you can run any command line tool here - not just tests #python -m unittest