Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
adamkerz committed Apr 4, 2019
2 parents b9a6590 + 78498a3 commit 63602d5
Show file tree
Hide file tree
Showing 10 changed files with 118 additions and 27 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
29 changes: 29 additions & 0 deletions pie_unix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""
Extension module for PIE that provides unix specific shortcuts.
"""
__VERSION__='0.0.1'

import pie


def cmd(c,use_sudo=False):
sudo(c) if use_sudo else pie.cmd(c)

def sudo(c):
pie.cmd('sudo {}'.format(c))


def set_permissions(p,mode=None,owner=None,group=None,use_sudo=False):
if mode: cmd('chmod {:04o} {}'.format(mode,p),use_sudo)
if owner: cmd('chown {} {}'.format(owner,p),use_sudo)
if group: cmd('chgrp {} {}'.format(group,p),use_sudo)


def mkdir(p,mode=None,owner=None,group=None,use_sudo=False):
cmd('mkdir {}'.format(p),use_sudo)
set_permissions(p,mode,owner,group,use_sudo)

def put_file(src,dest,mode=None,owner=None,group=None,use_sudo=False):
cmd('cp {} {}'.format(src,dest),use_sudo)
set_permissions(dest,mode,owner,group,use_sudo)

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\')"')
4 changes: 4 additions & 0 deletions tests/data/parameters/pie_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,7 @@ def options_parameter_default_value(v='foo'):
@task([OptionsParameter('v',use_default=True)])
def options_parameter_default_value_use_default(v='foo'):
print(v)

@task([OptionsParameter('a'),OptionsParameter('b',use_default=True),])
def options_parameter_multiple_parameters_use_default(a,b='foo'):
print(b)
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
15 changes: 6 additions & 9 deletions tests/test_parameters.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@
import pytest


@pytest.mark.parametrize('pie_tasks_path',['parameters'],indirect=['pie_tasks_path'])
def test_listing_tasks(pie,capsys,pie_tasks_path):
pie.main(['-l'])
out,err=capsys.readouterr()
tasks=set([t.strip(' ') for t in out.strip('\n').split('\n')])
expected=set(['no_function_call_decorator','function_call_decorator','one_parameter','options_parameter','parameter_default_value','options_parameter_default_value','options_parameter_default_value_use_default'])
assert tasks==expected


@pytest.mark.parametrize('pie_tasks_path',['parameters'],indirect=['pie_tasks_path'])
def test_parameter_suggests_default(pie,capsys,pie_tasks_path,pie_mock_input):
pie_mock_input.set_return('')
Expand Down Expand Up @@ -70,3 +61,9 @@ def test_options_parameter_uses_default(pie,capsys,pie_tasks_path,pie_input_forb
pie.main(['options_parameter_default_value_use_default'])
out,err=capsys.readouterr()
assert out=='foo\n'

@pytest.mark.parametrize('pie_tasks_path',['parameters'],indirect=['pie_tasks_path'])
def test_options_parameter_multiple_parameters_uses_default(pie,capsys,pie_tasks_path,pie_input_forbidden):
pie.main(['options_parameter_multiple_parameters_use_default(bar)'])
out,err=capsys.readouterr()
assert out=='foo\n'
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 63602d5

Please sign in to comment.