Răsfoiți Sursa

add running of python code and testing it

Oz N Tiram 9 ani în urmă
părinte
comite
9362dcf300
4 a modificat fișierele cu 53 adăugiri și 19 ștergeri
  1. 5 1
      README.rst
  2. 29 13
      frank/frank.py
  3. 3 0
      test/dummy_code.py
  4. 16 5
      test/test_frank.py

+ 5 - 1
README.rst

@@ -32,7 +32,7 @@ Frank understands the following file format::
 
 
     run_function_python:
     run_function_python:
       python:
       python:
-       - foo.bar:callable_function
+       - foo.bar:callable_object
 
 
 
 
 The `commands` is a mandatory list of commnads to excute after each push.
 The `commands` is a mandatory list of commnads to excute after each push.
@@ -74,3 +74,7 @@ This example demonstrates running multiple commands after the keyword `shell`.
 You can also specify any keyword that the function `subprocess.Popen` accepts.
 You can also specify any keyword that the function `subprocess.Popen` accepts.
 For example you can specify envirnment variables or the working directroy, as 
 For example you can specify envirnment variables or the working directroy, as 
 in the example with the keyword `cwd`. 
 in the example with the keyword `cwd`. 
+
+Example 2:
+----------
+TODO: demonstrate running of python code

+ 29 - 13
frank/frank.py

@@ -3,29 +3,28 @@ Frank can be configured using the following yaml::
 	.frank.yml
 	.frank.yml
 
 
 	commads:
 	commads:
-	 - build
 	 - test
 	 - test
-	 - publish
 	 - deploy
 	 - deploy
+	 - publish
 
 
+	newtag:
+	 - python:
+	   - frank.actions:detect_new_tag
 
 
 	deploy:
 	deploy:
 	 - cmd 
 	 - cmd 
 	 - runif:
 	 - runif:
 	   - test
 	   - test
 	   - newtag
 	   - newtag
-	 
-	newtag:
-	 - python:
-	   - frank.actions:detect_new_tag
-
-	publish:
+	
+        publish:
 	  - shell:
 	  - shell:
-		- cd docs; make html
+           - cd docs; make html
 	  - python:
 	  - python:
-		- frank.actions:recursive_copy 
+	   - frank.actions:recursive_copy 
 
 
-The sections commands is a simple list of command you would like to define. 
+The sections commands is a simple list of command you would 
+like to define. 
 This section is optional. It's main purpose is for you to decalre 
 This section is optional. It's main purpose is for you to decalre 
 which commands frank should execute upon recieving a load.
 which commands frank should execute upon recieving a load.
 
 
@@ -118,8 +117,9 @@ from flask import Flask, request, abort
 import conf
 import conf
 from shell import Shell
 from shell import Shell
 from collections import OrderedDict, namedtuple
 from collections import OrderedDict, namedtuple
+import importlib
 
 
-PythonCode = namedtupe('PythonCode', path, args, kwargs, code)
+PythonCode = namedtuple('PythonCode', ['path', 'args', 'kwargs', 'code'])
 
 
 def override_run(self, command, **kwargs):
 def override_run(self, command, **kwargs):
     """
     """
@@ -208,6 +208,7 @@ def report_failure(results):
 
 
 def run_action(axn):
 def run_action(axn):
     results = []
     results = []
+    # run shell or python callable object without arguments
     if isinstance(axn, list):
     if isinstance(axn, list):
 
 
         if axn[0] == 'shell':
         if axn[0] == 'shell':
@@ -221,11 +222,12 @@ def run_action(axn):
         if axn[0] == 'python':
         if axn[0] == 'python':
             for func in axn[1:]:
             for func in axn[1:]:
                 mod, f = func.split(':')
                 mod, f = func.split(':')
-                mod = importlib.import(mod)
+                mod = importlib.import_module(mod)
                 f = getattr(mod, f)
                 f = getattr(mod, f)
                 res = f()
                 res = f()
                 results.append(PythonCode(func, None, None, res))
                 results.append(PythonCode(func, None, None, res))
 
 
+    # run shell or python callable object arguments
     elif isinstance(axn, OrderedDict):
     elif isinstance(axn, OrderedDict):
 
 
         if 'shell' in axn:
         if 'shell' in axn:
@@ -237,6 +239,20 @@ def run_action(axn):
             sh.run(cmd, **kwargs)
             sh.run(cmd, **kwargs)
             results.append(sh)
             results.append(sh)
 
 
+        if 'python' in axn:
+            callables = axn['python']
+            for func in callables:
+                mod, f = func.split(':')
+                mod = importlib.import_module(mod)
+                try:
+                    f = getattr(mod, f)
+                    res = f()
+                except AttributeError as E:
+                    res = E
+                
+                results.append(PythonCode(func, None, None, res))
+                    
+
     return results
     return results
 
 
 
 

+ 3 - 0
test/dummy_code.py

@@ -0,0 +1,3 @@
+
+def do_something():
+    return True

+ 16 - 5
test/test_frank.py

@@ -123,15 +123,26 @@ def test_run_action_shell_with_kwargs():
     assert len(results) == 1
     assert len(results) == 1
     assert isinstance(results[0].exception, OSError)
     assert isinstance(results[0].exception, OSError)
     axn = OrderedDict([('shell', OrderedDict([('cwd', '/tmp'),
     axn = OrderedDict([('shell', OrderedDict([('cwd', '/tmp'),
-                      ('cmd', 'touch /nosuchdir/foo')]))])
+        ('cmd', 'touch /nosuchdir/foo')]))])
     results = run_action(axn)
     results = run_action(axn)
-    assert len(r)esults) == 1
+    assert len(results) == 1
     assert results[0].code == 1
     assert results[0].code == 1
     # missing arguments to touch
     # missing arguments to touch
     axn = OrderedDict([('shell', OrderedDict([('cwd', '/tmp'),
     axn = OrderedDict([('shell', OrderedDict([('cwd', '/tmp'),
-                      ('cmd', 'touch')]))])
+        ('cmd', 'touch')]))])
     assert len(results) == 1
     assert len(results) == 1
     assert results[0].code == 1
     assert results[0].code == 1
     assert ['touch: missing file operand',
     assert ['touch: missing file operand',
-            "Try `touch --help' for more information."] == 
-                results[0].errors()
+            "Try 'touch --help' for more information."] == \
+                 results[0].errors()
+
+def test_run_python_code():
+    od = ordered_load("""
+    run_function_python:
+      python:
+        - dummy_code:do_something
+        - dummy_code:do_something_else
+    """)
+    results = run_action(od['run_function_python'])
+    assert len(results) == 2
+    assert isinstance(results[-1].code, AttributeError)