summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkennyballou <kballou@onyx.boisestate.edu>2013-10-03 20:15:49 -0600
committerkennyballou <kballou@onyx.boisestate.edu>2013-10-03 20:15:49 -0600
commit9f37b86453e70502f943abc1dc6532a590dac9f7 (patch)
tree4087df829156742f52f46a59fb1b86ba0321102d
parenteb280ea3bd908d9f33a881f2b46cd17671975848 (diff)
parent9fee0807a3ffbdd85df612caab99f060a5f4d006 (diff)
downloadxnt-9f37b86453e70502f943abc1dc6532a590dac9f7.tar.gz
xnt-9f37b86453e70502f943abc1dc6532a590dac9f7.tar.xz
Merge branch 'add_target_run_check' into develop
-rw-r--r--docs/source/buildfile.rst49
-rw-r--r--xnt/__init__.py25
2 files changed, 66 insertions, 8 deletions
diff --git a/docs/source/buildfile.rst b/docs/source/buildfile.rst
index 8200fff..2786a32 100644
--- a/docs/source/buildfile.rst
+++ b/docs/source/buildfile.rst
@@ -73,6 +73,55 @@ call ``mkdir`` of the ``xnt`` (internally of the ``xnt.tasks``) module. This
function, if not obvious by the name, creates a directory named 'build' (see
:doc:`taskreference`).
+Target Decorator
+================
+
+The ``target`` decorator is just a standard Python decorating function with a
+few exceptions. Namely, a new default behaviour is being introduced: a target
+will _not_ execute more than once in a single invocation of ``xnt``. However,
+if you so require a target to execute more than once, the option is provided.
+For example::
+
+ import xnt
+
+ @xnt.target
+ def init():
+ #executes initalization
+
+ @xnt.target
+ def build():
+ init() # depends on init
+ # compiles project
+
+ @xnt.target
+ def package():
+ init() # explicitly depends on init
+ build() # depends on build
+ # packages project together
+
+The ``target`` decorators new default behaviour will not run the ``init``
+target more than once if the ``package`` target was invoked. However, let's say
+we introduce another target, ``clean`` for example, and define it as::
+
+ @xnt.target(always_run=True)
+ def clean():
+ # clean project state
+
+To further illustrate this new optional argument, let us define another
+target, ``test`` that will call ``clean`` twice::
+
+ @xnt.target
+ def test():
+ clean()
+ package()
+ # Run tests
+ clean()
+
+When we run our ``test`` target, we notice we want to start from a fresh, clean
+state and we want to finish on a fresh, clean state. With the new default, this
+wouldn't be possible, but with this new optional argument, ``always_run`` it
+still is.
+
Return Values
=============
diff --git a/xnt/__init__.py b/xnt/__init__.py
index 61de895..507041f 100644
--- a/xnt/__init__.py
+++ b/xnt/__init__.py
@@ -55,15 +55,24 @@ from xnt.tasks import setup
from xnt.tasks import which
from xnt.tasks import in_path
-def target(target_fn):
+def target(*args, **kwargs):
"""Decorator function for marking a method in
build file as a "target" method, or a method meant
to be invoked from Xnt
"""
- def wrap():
- """Inner wrapper function for decorator"""
- print(target_fn.__name__ + ":")
- return target_fn()
- wrap.decorator = "target"
- wrap.__doc__ = target_fn.__doc__
- return wrap
+ def w_target(target_fn):
+ """target wrapping function"""
+ has_run = [False,]
+ def wrap():
+ """Inner wrapper function for decorator"""
+ if not has_run[0] or kwargs.get('always_run', False):
+ has_run[0] = True
+ print(target_fn.__name__ + ":")
+ return target_fn()
+ return None
+ wrap.decorator = "target"
+ wrap.__doc__ = target_fn.__doc__
+ return wrap
+ if len(args) == 1 and callable(args[0]):
+ return w_target(args[0])
+ return w_target