Skip to content

Commit

Permalink
Adding some error handling abilities
Browse files Browse the repository at this point in the history
  • Loading branch information
adamkerz committed Apr 4, 2019
1 parent a96171e commit 78498a3
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 18 deletions.
31 changes: 22 additions & 9 deletions pie.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Enables a user to execute predefined tasks that may accept parameters and options from the command line without any other required packages.
Great for bootstrapping a development environment, and then interacting with it.
"""
__VERSION__='0.2.5'
__VERSION__='0.2.6'


import inspect
Expand All @@ -26,7 +26,7 @@

# function for input (also so that we can mock it tests)
INPUT_FN=input if PY3 else raw_input
# function to execute a command - must emulate the subprocess call method
# function to execute a command - must emulate the subprocess call method and return an error code on failure
CMD_FN=subprocess.call


Expand Down Expand Up @@ -213,6 +213,13 @@ class CmdContextManager(object):
"""
context=[]


class CmdError(Exception):
def __init__(self,errorcode,cmd):
self.errorcode=errorcode
self.cmd=cmd


@classmethod
def enter(cls,ctx):
cls.context.append(ctx)
Expand All @@ -222,7 +229,9 @@ def enter(cls,ctx):
def cmd(cls,c,i=None):
if i is None: i=len(cls.context)
if i>0: return cls.context[i-1].cmd(c)
return CMD_FN(c,shell=True)
errorcode=CMD_FN(c,shell=True)
if errorcode!=0:
raise cls.CmdError(errorcode,c)

@classmethod
def exit(cls):
Expand Down Expand Up @@ -520,30 +529,34 @@ def main(args):
# pick up the specific case of not being able to find a pie_tasks module/package
# handle different attributes and messages in py2 vs py3
if isinstance(e,ImportError) and (getattr(e,'message','')=='No module named pie_tasks' or getattr(e,'msg','')=="No module named 'pie_tasks'"):
print('pie_tasks could not be found.')
print('pie_tasks could not be found.',file=sys.stderr)
else:
print('An error occurred when importing pie_tasks:\n'+traceback.format_exc())
print('An error occurred when importing pie_tasks:\n'+traceback.format_exc(),file=sys.stderr)
return 1

else:
# otherwise, we need to activate and run pie again, within the venv
if pv.exists():
return pv.run_pie(args)
else:
print('{} not found. You can create it with the -R argument.'.format(pv.PIE_VENV))
print('{} not found. You can create it with the -R argument.'.format(pv.PIE_VENV),file=sys.stderr)
return 1

# try to execute each arg
for a in parsed_args:
try:
a.execute()
except CmdContextManager.CmdError as e:
print('Error when executing command "{}". Errorcode = {}'.format(e.cmd,e.errorcode),file=sys.stderr)
return e.errorcode
except TaskCall.TaskNotFound as e:
print('Task {} could not be found.'.format(e.name))
break
print('Task {} could not be found.'.format(e.name),file=sys.stderr)
return 1
return 0

else:
Help().execute()

return 1


if __name__=='__main__':
Expand Down
2 changes: 1 addition & 1 deletion pie_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

@task
def setup():
createVenvs()
createVenv()
updatePackages()


Expand Down
18 changes: 18 additions & 0 deletions tests/data/error_handling/pie_tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from pie import *


@task
def cmd_no_failure():
cmd('python -c "print(\'alpha\')"')


@task
def cmd_failure_non_existent():
cmd('non_existent')
cmd('python -c "print(\'beta\')"')


@task
def cmd_failure_error_code():
cmd('python -c "import sys; sys.exit(3)"')
cmd('python -c "print(\'gamma\')"')
5 changes: 3 additions & 2 deletions tests/test_calling_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

@pytest.mark.parametrize('pie_tasks_path',['missing_task'],indirect=['pie_tasks_path'])
def test_missing_task(pie,capsys,pie_tasks_path):
pie.main(['missing'])
r=pie.main(['missing'])
out,err=capsys.readouterr()
assert out.startswith('Task missing could not be found.')
assert err.startswith('Task missing could not be found.')
assert r==1
26 changes: 26 additions & 0 deletions tests/test_error_handling.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import os

import pytest


@pytest.mark.parametrize('pie_tasks_path',['error_handling'],indirect=['pie_tasks_path'])
def test_cmd_no_failure(pie,capfd,pie_tasks_path):
pie.main(['cmd_no_failure'])
out,err=capfd.readouterr()
out=out.replace(os.linesep,'\n')
assert out=='alpha\n'

@pytest.mark.parametrize('pie_tasks_path',['error_handling'],indirect=['pie_tasks_path'])
def test_cmd_failure_non_existent(pie,capfd,pie_tasks_path):
errorcode=pie.main(['cmd_failure_non_existent'])
out,err=capfd.readouterr()
assert not out.endswith('beta\n')
assert errorcode==1

@pytest.mark.parametrize('pie_tasks_path',['error_handling'],indirect=['pie_tasks_path'])
def test_cmd_failure_error_code(pie,capfd,pie_tasks_path):
errorcode=pie.main(['cmd_failure_error_code'])
out,err=capfd.readouterr()
assert not out.endswith('gamma\n')
assert errorcode==3

10 changes: 6 additions & 4 deletions tests/test_importing_pie_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,18 @@ def test_help(pie,capsys,pie_tasks_path):

@pytest.mark.parametrize('pie_tasks_path',['no_pie_tasks'],indirect=['pie_tasks_path'])
def test_list_no_pie_tasks(pie,capsys,pie_tasks_path):
pie.main(['-l'])
r=pie.main(['-l'])
out,err=capsys.readouterr()
assert out.startswith('pie_tasks could not be found.')
assert err.startswith('pie_tasks could not be found.')
assert r==1


@pytest.mark.parametrize('pie_tasks_path',['error_importing_pie_tasks'],indirect=['pie_tasks_path'])
def test_list_error_importing_pie_tasks(pie,capsys,pie_tasks_path):
pie.main(['-l'])
r=pie.main(['-l'])
out,err=capsys.readouterr()
assert out.startswith('An error occurred when importing pie_tasks:')
assert err.startswith('An error occurred when importing pie_tasks:')
assert r==1


@pytest.mark.parametrize('pie_tasks_path',['package_tasks','module_tasks'],indirect=['pie_tasks_path'])
Expand Down
5 changes: 3 additions & 2 deletions tests/test_pie_requirements.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@

@pytest.mark.parametrize('pie_tasks_path',['pie_requirements'],indirect=['pie_tasks_path'])
def test_no_venv(pie,capsys,pie_tasks_path):
pie.main(['test'])
r=pie.main(['test'])
out,err=capsys.readouterr()
assert out.startswith('.venv-pie not found. You can create it with the -R argument.')
assert err.startswith('.venv-pie not found. You can create it with the -R argument.')
assert r==1


@pytest.mark.parametrize('pie_tasks_path',['pie_requirements'],indirect=['pie_tasks_path'])
Expand Down

0 comments on commit 78498a3

Please sign in to comment.