From 2ff29b2be1397683d3331581992fa77d50af7925 Mon Sep 17 00:00:00 2001 From: kennyballou Date: Sat, 28 Sep 2013 13:17:16 -0600 Subject: Add target run check * Add `has_run` check to targets to ensure targets only execute once per build --- xnt/__init__.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/xnt/__init__.py b/xnt/__init__.py index 61de895..767c2b7 100644 --- a/xnt/__init__.py +++ b/xnt/__init__.py @@ -60,10 +60,13 @@ def target(target_fn): build file as a "target" method, or a method meant to be invoked from Xnt """ + has_run = [False,] def wrap(): """Inner wrapper function for decorator""" - print(target_fn.__name__ + ":") - return target_fn() + if not has_run[0]: + has_run[0] = True + print(target_fn.__name__ + ":") + return target_fn() wrap.decorator = "target" wrap.__doc__ = target_fn.__doc__ return wrap -- cgit v1.2.1 From d5076eb03c18e8915b4667b5c8198b0ac404d069 Mon Sep 17 00:00:00 2001 From: kennyballou Date: Thu, 3 Oct 2013 16:17:36 -0600 Subject: Add optional argument for target decorator To maintain backwards compatibility in decorator behaviour, add the optional parameter `always_run` to override the `has_run` check --- xnt/__init__.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/xnt/__init__.py b/xnt/__init__.py index 767c2b7..507041f 100644 --- a/xnt/__init__.py +++ b/xnt/__init__.py @@ -55,18 +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 """ - has_run = [False,] - def wrap(): - """Inner wrapper function for decorator""" - if not has_run[0]: - has_run[0] = True - 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 -- cgit v1.2.1 From 9fee0807a3ffbdd85df612caab99f060a5f4d006 Mon Sep 17 00:00:00 2001 From: kennyballou Date: Thu, 3 Oct 2013 20:11:01 -0600 Subject: Update documentation * document new target decorator behaviour --- docs/source/buildfile.rst | 49 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) 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 ============= -- cgit v1.2.1