From 53069d8212a5e87802ca9535191e8cb056d9a787 Mon Sep 17 00:00:00 2001 From: kennyballou Date: Sat, 9 Mar 2013 18:22:33 -0700 Subject: Use uppercase properties for dictionary value After using pylint I noticed I should have Xnt also use this for the override properties dictionary [http://www.python.org/dev/peps/pep-0008/#constants] --- docs/source/buildfile.rst | 6 +++--- xnt/commands/target.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/source/buildfile.rst b/docs/source/buildfile.rst index cec8e30..8200fff 100644 --- a/docs/source/buildfile.rst +++ b/docs/source/buildfile.rst @@ -134,16 +134,16 @@ Build Properties As mentioned in :ref:`xntPropertiesParameters`, Xnt can accept parameters from the command line and pass them into the build file. Xnt doesn't necessarily -expect the dictionary (named `properties`) to exist; but if you ever intend to +expect the dictionary (named `PROPERTIES`) to exist; but if you ever intend to use it, it will have to be defined one way or another (either to an empty dictionary or actually hold values). For example, to define an empty -`properties` dictionary, one could write their build file as such:: +`PROPERTIES` dictionary, one could write their build file as such:: #!/usr/bin/env python from xnt import target - properties = {} + PROPERTIES = {} @target def foo(): diff --git a/xnt/commands/target.py b/xnt/commands/target.py index 0520c74..dbf46fe 100644 --- a/xnt/commands/target.py +++ b/xnt/commands/target.py @@ -58,13 +58,13 @@ class TargetCommand(Command): def __get_properties(): """Return the properties dictionary of the build module""" try: - return getattr(self.build, "properties") + return getattr(self.build, "PROPERTIES") except AttributeError: return None try: if props and len(props) > 0: setattr(self.build, - "properties", + "PROPERTIES", process_params(props, __get_properties())) target = getattr(self.build, target_name) error_code = target() -- cgit v1.2.1 From 532f5d98c15f091a270e68450112e91ad085f6bf Mon Sep 17 00:00:00 2001 From: kennyballou Date: Sat, 9 Mar 2013 18:33:32 -0700 Subject: Refactor/ Move Program flow to use `argparse` --- pylint.conf | 2 +- xnt/basecommand.py | 32 --------- xnt/cmdoptions.py | 31 --------- xnt/commands/__init__.py | 41 ------------ xnt/commands/help.py | 42 ------------ xnt/commands/listtargets.py | 56 ---------------- xnt/commands/target.py | 78 ---------------------- xnt/commands/version.py | 34 ---------- xnt/tasks.py | 6 +- xnt/tests/xenantargparsertests.py | 132 ++++++++++++++++++++++++++++++++++++++ xnt/version.py | 2 +- xnt/xenant.py | 126 ++++++++++++++++++++++++++++-------- 12 files changed, 235 insertions(+), 347 deletions(-) delete mode 100644 xnt/basecommand.py delete mode 100644 xnt/cmdoptions.py delete mode 100644 xnt/commands/__init__.py delete mode 100644 xnt/commands/help.py delete mode 100644 xnt/commands/listtargets.py delete mode 100644 xnt/commands/target.py delete mode 100644 xnt/commands/version.py create mode 100644 xnt/tests/xenantargparsertests.py diff --git a/pylint.conf b/pylint.conf index 5282466..a56e0a5 100644 --- a/pylint.conf +++ b/pylint.conf @@ -249,7 +249,7 @@ max-attributes=7 min-public-methods=1 # Maximum number of public methods for a class (see R0904). -max-public-methods=50 +max-public-methods=55 [EXCEPTIONS] diff --git a/xnt/basecommand.py b/xnt/basecommand.py deleted file mode 100644 index 6433918..0000000 --- a/xnt/basecommand.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env python -"""Basecommand class for xnt commands""" - -# Xnt -- A Wrapper Build Tool -# Copyright (C) 2012 Kenny Ballou - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -class Command(object): - """Base Command Class Definition""" - name = None - usage = None - hidden = False - need_build = False - - def __init__(self): - pass - - def run(self, arguments=None): - """Invoke the Command""" - pass diff --git a/xnt/cmdoptions.py b/xnt/cmdoptions.py deleted file mode 100644 index 529f060..0000000 --- a/xnt/cmdoptions.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python -"""Xenant Options Defintion - -All available options for Xenant (and there actions) -""" - -# Xnt -- A Wrapper Build Tool -# Copyright (C) 2012 Kenny Ballou - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -import logging - -def __flip_verbose_flag(): - """Turn on logging for xnt (and submodules)""" - logging.getLogger("xnt").setLevel(logging.INFO) - -OPTIONS = { - "-v": __flip_verbose_flag, -} diff --git a/xnt/commands/__init__.py b/xnt/commands/__init__.py deleted file mode 100644 index 583558b..0000000 --- a/xnt/commands/__init__.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env python -"""Commands Module""" - -# Xnt -- A Wrapper Build Tool -# Copyright (C) 2012 Kenny Ballou - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -from xnt.commands.help import HelpCommand -from xnt.commands.listtargets import ListTargetsCommand -from xnt.commands.version import VersionCommand -from xnt.commands.target import TargetCommand - -COMMANDS = { - HelpCommand.name: HelpCommand, - ListTargetsCommand.name: ListTargetsCommand, - VersionCommand.name: VersionCommand, - TargetCommand.name: TargetCommand, -} - -def get_summaries(ignore_hidden=True): - """Return a list of summaries about each command""" - items = [] - - for name, command_class in COMMANDS.items(): - if ignore_hidden and command_class.hidden: - continue - items.append((name, command_class.summary)) - - return sorted(items) diff --git a/xnt/commands/help.py b/xnt/commands/help.py deleted file mode 100644 index 79584be..0000000 --- a/xnt/commands/help.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env python -"""Xnt Help Command""" - -# Xnt -- A Wrapper Build Tool -# Copyright (C) 2012 Kenny Ballou - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -from xnt.basecommand import Command -from xnt.status_codes import SUCCESS - -class HelpCommand(Command): - """Help Command""" - name = 'help' - usage = """""" - summary = 'Print Usage Summary' - needs_build = False - - def run(self, arguments=None): - """Invoke Help""" - from xnt.commands import get_summaries - from xnt import __version__, __license__ - commands = get_summaries() - print(__version__) - print(__license__) - print("Available Commands:") - for name, summary in commands: - print(name) - print("\t" + summary) - - return SUCCESS diff --git a/xnt/commands/listtargets.py b/xnt/commands/listtargets.py deleted file mode 100644 index 2885905..0000000 --- a/xnt/commands/listtargets.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python -"""List Targets Xnt Command""" - -# Xnt -- A Wrapper Build Tool -# Copyright (C) 2012 Kenny Ballou - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -from xnt.basecommand import Command -from xnt.status_codes import SUCCESS, ERROR -import logging - -LOGGER = logging.getLogger(__name__) - -class ListTargetsCommand(Command): - """List Targets Command""" - name = 'list-targets' - usage = """""" - summary = "Prints targets in build file" - needs_build = True - - def __init__(self, build): - """Initialization""" - Command.__init__(self) - self.build = build - - def run(self, arguments=None): - """Invoke ListTargets""" - LOGGER.debug("build is null? %s", self.build == None) - try: - for attr in dir(self.build): - LOGGER.debug("Attribute %s:", attr) - try: - func = getattr(self.build, attr) - if func.decorator == "target": - print(attr + ":") - if func.__doc__: - print(func.__doc__) - print("\n") - except AttributeError: - pass - except AttributeError as ex: - LOGGER.error(ex) - return ERROR - return SUCCESS diff --git a/xnt/commands/target.py b/xnt/commands/target.py deleted file mode 100644 index 0520c74..0000000 --- a/xnt/commands/target.py +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env python -"""(Generic) Target Xnt Command for invoking build targets""" - -# Xnt -- A Wrapper Build Tool -# Copyright (C) 2012 Kenny Ballou - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -from xnt.basecommand import Command -from xnt.status_codes import SUCCESS, ERROR, UNKNOWN_ERROR -import logging - -LOGGER = logging.getLogger("xnt") - -class TargetCommand(Command): - """Target Command""" - name = '' - usage = """""" - summary = "Invokes target(s) in build.py" - needs_build = True - - def __init__(self, build): - """Initialization""" - Command.__init__(self) - self.build = build - - def run(self, targets=None, props=None): #pylint: disable-msg=W0221 - """Invoke Target Command""" - if targets: - for target in targets: - error_code = self.call_target(target, props) - if error_code: - return error_code - return SUCCESS - else: - return self.call_target("default", props) - - def call_target(self, target_name, props): - """Invoke build target""" - def process_params(params, buildproperties=None): - """Parse the passed properties and append to build properties""" - properties = buildproperties if buildproperties is not None else {} - for param in params: - name, value = param[2:].split("=") - properties[name] = value - return properties - def __get_properties(): - """Return the properties dictionary of the build module""" - try: - return getattr(self.build, "properties") - except AttributeError: - return None - try: - if props and len(props) > 0: - setattr(self.build, - "properties", - process_params(props, __get_properties())) - target = getattr(self.build, target_name) - error_code = target() - return error_code if error_code else 0 - except AttributeError: - LOGGER.warning("There was no target: %s", target_name) - return ERROR - except Exception as ex: - LOGGER.error(ex) - return UNKNOWN_ERROR - diff --git a/xnt/commands/version.py b/xnt/commands/version.py deleted file mode 100644 index 9c2e302..0000000 --- a/xnt/commands/version.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python -"""Version Xnt Command""" - -# Xnt -- A Wrapper Build Tool -# Copyright (C) 2012 Kenny Ballou - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -from xnt.basecommand import Command -from xnt.status_codes import SUCCESS - -class VersionCommand(Command): - """Version Command""" - name = 'version' - usage = """""" - summary = "Print Version of Xnt" - needs_build = False - - def run(self, arguments=None): - """Invoke Version""" - from xnt import __version__ - print(__version__) - return SUCCESS diff --git a/xnt/tasks.py b/xnt/tasks.py index 7a3e79d..679701c 100644 --- a/xnt/tasks.py +++ b/xnt/tasks.py @@ -127,12 +127,10 @@ def xntcall(path, targets=None, props=None): param: targets - list of targets to execute param: props - dictionary of properties to pass to the build module """ - import xnt.xenant - from xnt.commands.target import TargetCommand + from xnt.xenant import invoke_build, load_build cwd = os.getcwd() - command = TargetCommand(xnt.xenant.load_build(path)) os.chdir(path) - error_code = command.run(targets=targets, props=props) + error_code = invoke_build(load_build(path), targets=targets, props=props) os.chdir(cwd) return error_code diff --git a/xnt/tests/xenantargparsertests.py b/xnt/tests/xenantargparsertests.py new file mode 100644 index 0000000..3a22b33 --- /dev/null +++ b/xnt/tests/xenantargparsertests.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python +"""Xenant Arg Parser Tests""" + +# Xnt -- A Wrapper Build Tool +# Copyright (C) 2012 Kenny Ballou + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import xnt.xenant +import unittest + +#pylint: disable-msg=C0103 +class XenantArgParserTests(unittest.TestCase): + """Test Cases for Xenant Args Parsing""" + + def test_nil_args(self): + """Test the empty case (no arguements)""" + args_in = [] + args = xnt.xenant.parse_args(args_in) + self.assertIsNotNone(args) + self.assertFalse(args["verbose"]) + self.assertFalse(args["list-targets"]) + self.assertIsNone(args["properties"]) + self.assertIsNotNone(args["targets"]) + self.assertEqual(len(args["targets"]), 0) + + def test_single_target(self): + """Test the single target case""" + args_in = ["my_target"] + args = xnt.xenant.parse_args(args_in) + self.assertIsNotNone(args) + self.assertFalse(args["verbose"]) + self.assertFalse(args["list-targets"]) + self.assertIsNone(args["properties"]) + self.assertIsNotNone(args["targets"]) + self.assertEqual(len(args["targets"]), 1) + + def test_verbose(self): + """Test verbose flag""" + args_in = ["-v"] + args = xnt.xenant.parse_args(args_in) + self.assertIsNotNone(args) + self.assertTrue(args["verbose"]) + self.assertFalse(args["list-targets"]) + self.assertIsNone(args["properties"]) + self.assertIsNotNone(args["targets"]) + self.assertEqual(len(args["targets"]), 0) + + def test_list_targets_short(self): + """Test list targets flag, short hand""" + args_in = ["-l"] + args = xnt.xenant.parse_args(args_in) + self.assertIsNotNone(args) + self.assertFalse(args["verbose"]) + self.assertTrue(args["list-targets"]) + self.assertIsNone(args["properties"]) + self.assertIsNotNone(args["targets"]) + self.assertEqual(len(args["targets"]), 0) + + def test_list_targets_long(self): + """Test list targets flag, long hand""" + args_in = ["--list-targets"] + args = xnt.xenant.parse_args(args_in) + self.assertIsNotNone(args) + self.assertFalse(args["verbose"]) + self.assertTrue(args["list-targets"]) + self.assertIsNone(args["properties"]) + self.assertIsNotNone(args["targets"]) + self.assertEqual(len(args["targets"]), 0) + + def test_single_verbose(self): + """Test the verbose single case""" + args_in = ["-v", "my_verbose_target"] + args = xnt.xenant.parse_args(args_in) + self.assertIsNotNone(args) + self.assertTrue(args["verbose"]) + self.assertFalse(args["list-targets"]) + self.assertIsNone(args["properties"]) + self.assertIsNotNone(args["targets"]) + self.assertEqual(len(args["targets"]), 1) + + def test_multi_target(self): + """Test the verbose single case""" + args_in = ["my_first_target", "my_second_target"] + args = xnt.xenant.parse_args(args_in) + self.assertIsNotNone(args) + self.assertFalse(args["verbose"]) + self.assertFalse(args["list-targets"]) + self.assertIsNone(args["properties"]) + self.assertIsNotNone(args["targets"]) + self.assertEqual(len(args["targets"]), 2) + + def test_properties_no_target(self): + """Test property parsing""" + args_in = ["-Dmyvar=myvalue"] + args = xnt.xenant.parse_args(args_in) + self.assertIsNotNone(args) + self.assertFalse(args["verbose"]) + self.assertFalse(args["list-targets"]) + self.assertIsNotNone(args["properties"]) + self.assertEqual(len(args["properties"]), 1) + self.assertEqual(args["properties"][0], "myvar=myvalue") + self.assertIsNotNone(args["targets"]) + self.assertEqual(len(args["targets"]), 0) + + def test_more_properties(self): + """Test property parsing""" + args_in = ["-Dmyvar=myvalue", "-Dmyothervar=myothervalue"] + args = xnt.xenant.parse_args(args_in) + self.assertIsNotNone(args) + self.assertFalse(args["verbose"]) + self.assertFalse(args["list-targets"]) + self.assertIsNotNone(args["properties"]) + self.assertEqual(len(args["properties"]), 2) + self.assertEqual(args["properties"][0], "myvar=myvalue") + self.assertEqual(args["properties"][1], "myothervar=myothervalue") + self.assertIsNotNone(args["targets"]) + self.assertEqual(len(args["targets"]), 0) + +if __name__ == "__main__": + unittest.main() diff --git a/xnt/version.py b/xnt/version.py index 3562358..77cf994 100644 --- a/xnt/version.py +++ b/xnt/version.py @@ -17,5 +17,5 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -__version_info__ = (0, 5, 2) +__version_info__ = (0, 5, 3) __version__ = '.'.join(list(str(i) for i in __version_info__ if True)) diff --git a/xnt/xenant.py b/xnt/xenant.py index e67ef7c..9e5a3df 100644 --- a/xnt/xenant.py +++ b/xnt/xenant.py @@ -21,9 +21,9 @@ import os import sys import time import logging -from xnt.cmdoptions import OPTIONS -from xnt.commands import COMMANDS -from xnt.commands.target import TargetCommand +import argparse +from xnt import __version__ +from xnt.status_codes import SUCCESS, ERROR, UNKNOWN_ERROR logging.basicConfig(format="%(asctime)s:%(levelname)s:%(message)s") LOGGER = logging.Logger(name=__name__) @@ -32,30 +32,15 @@ LOGGER.addHandler(logging.StreamHandler()) def main(): """Xnt Entry Point""" start_time = time.time() - params = list(p for p in sys.argv[1:] if p.startswith('-D')) - flags = list(o for o in sys.argv[1:] - if o.startswith('-') and o not in params) - cmds = list(c for c in sys.argv[1:] - if c not in flags and c not in params) - #Loop flags and apply them - for flag in flags: - if flag in OPTIONS: - OPTIONS[flag]() - else: - LOGGER.debug("%s is not a vaild option", flag) - #run things - cmd_found = False - for cmd in cmds: - if cmd in COMMANDS: - cmd_found = True - if COMMANDS[cmd].needs_build: - command = COMMANDS[cmd](load_build()) - else: - command = COMMANDS[cmd]() - error_code = command.run() - if cmd_found == False: - command = TargetCommand(load_build()) - error_code = command.run(targets=cmds, props=params) + args = parse_args(sys.argv[1:]) + if args["verbose"]: + LOGGER.setLevel(logging.DEBUG) + if args["list-targets"]: + error_code = list_targets(load_build()) + else: + error_code = invoke_build(load_build(), + args["targets"], + args["properties"]) elapsed_time = time.time() - start_time LOGGER.info("Execution time: %.3f", elapsed_time) if error_code != 0: @@ -91,5 +76,92 @@ def load_build(path=""): del sys.modules["build"] os.chdir(cwd) +def invoke_build(build, targets=None, props=None): + """Invoke Build with `targets` passing `props`""" + def call_target(target_name, props): + """Call target on build module""" + def process_params(params, existing_props=None): + """Parse and separate properties and append to build module""" + properties = existing_props if existing_props is not None else {} + for param in params: + name, value = param.split("=") + properties[name] = value + return properties + def __get_properties(): + """Return the properties dictionary of the build module""" + try: + return getattr(build, "PROPERTIES") + except AttributeError: + LOGGER.warning("Build file specifies no properties") + return None + try: + if props and len(props) > 0: + setattr(build, + "PROPERTIES", + process_params(props, __get_properties())) + target = getattr(build, target_name) + error_code = target() + return error_code if error_code else 0 + except AttributeError: + LOGGER.error("There was no target: %s", target_name) + return ERROR + except Exception as ex: + LOGGER.critical(ex) + return UNKNOWN_ERROR + if targets and len(targets) > 0: + for target in targets: + error_code = call_target(target, props) + if error_code: + return error_code + return SUCCESS + else: + return call_target("default", props) + +def list_targets(build): + """List targets (and doctstrings) of the provided build module""" + try: + for attr in dir(build): + try: + func = getattr(build, attr) + if func.decorator == "target": + print(attr + ":") + if func.__doc__: + print(func.__doc__) + print("") + except AttributeError: + pass + except AttributeError as ex: + LOGGER.error(ex) + return ERROR + return SUCCESS + +def parse_args(args_in): + """Parse and group arguments""" + parser = argparse.ArgumentParser(prog="Xnt") + parser.add_argument("-v", "--verbose", + help="Enable verbose output", + action="store_true", + dest="verbose") + parser.add_argument( + "--version", + action="version", + version=__version__, + help="Print Xnt Version and quit") + parser.add_argument("-l", "--list-targets", + action="store_true", + dest="list-targets", + help="Print build targets") + # Properties Group + params_group = parser.add_argument_group("Properties") + params_group.add_argument( + "-D", dest="properties", action="append", + help="Property values to be passed to the build module") + target_group = parser.add_argument_group("Targets") + + # Targets Group + target_group.add_argument("targets", nargs=argparse.REMAINDER, + help="Name(s) of targets to invoke") + return vars(parser.parse_args(args_in)) + if __name__ == "__main__": main() -- cgit v1.2.1 From 2467c3a3bdefd1d06f02afc1a6b9ac5bf272ca0e Mon Sep 17 00:00:00 2001 From: kennyballou Date: Sat, 9 Mar 2013 18:37:54 -0700 Subject: Update documentation to reflect option changes --- docs/source/xenant.rst | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/source/xenant.rst b/docs/source/xenant.rst index e9456fa..156883f 100644 --- a/docs/source/xenant.rst +++ b/docs/source/xenant.rst @@ -47,27 +47,27 @@ Xnt has a number of other commands that can be invoked besides those defined in the current directory's `build.py` file. One will need a build file to run. The others, however, do not. -* ``help`` prints a summary message, including information about the version of - Xnt, license, and usage. +* ``-h`` or ``--help`` prints a summary message, including information about + the version of Xnt, license, and usage. Usage:: - $ xnt help + $ xnt --help -* ``list-targets`` does exactly what the name should suggest: it prints a list - of the targets found in the current directory's `build.py` script, along with - any docstrings that may be defined with them. +* ``-l`` or ``--list-targets`` does exactly what the name should suggest: it + prints a list of the targets found in the current directory's `build.py` + script, along with any docstrings that may be defined with them. Usage:: - $ xnt list-targets + $ xnt --list-targets -* ``version`` prints Xnt's installed version. +* ``--version`` prints Xnt's installed version. Usage:: - $ xnt version + $ xnt --version .. _xntOptions: @@ -82,7 +82,7 @@ Usage:: Where options can be any and all of the following (unless otherwise specified): -* ``-v``: add verbose output to the execution of Xnt +* ``-v`` or ``--verbose``: add verbose output to the execution of Xnt .. _xntPropertiesParameters: -- cgit v1.2.1 From 793bdd9d0fd2403e665ea2e117fb72096cec091b Mon Sep 17 00:00:00 2001 From: kennyballou Date: Sat, 9 Mar 2013 20:22:42 -0700 Subject: Add build-file specification option --- pylint.conf | 2 +- xnt/tasks.py | 6 ++++-- xnt/tests/xenantargparsertests.py | 26 ++++++++++++++++++++++++++ xnt/xenant.py | 27 ++++++++++++++++++++------- 4 files changed, 51 insertions(+), 10 deletions(-) diff --git a/pylint.conf b/pylint.conf index a56e0a5..aa74eda 100644 --- a/pylint.conf +++ b/pylint.conf @@ -249,7 +249,7 @@ max-attributes=7 min-public-methods=1 # Maximum number of public methods for a class (see R0904). -max-public-methods=55 +max-public-methods=60 [EXCEPTIONS] diff --git a/xnt/tasks.py b/xnt/tasks.py index 679701c..02cde24 100644 --- a/xnt/tasks.py +++ b/xnt/tasks.py @@ -120,7 +120,7 @@ def log(msg="", lvl=logging.INFO): """Log message using tasks global logger""" LOGGER.log(lvl, msg) -def xntcall(path, targets=None, props=None): +def xntcall(buildfile, targets=None, props=None): """Invoke xnt on another build file in a different directory param: path - to the build file (including build file) @@ -128,9 +128,11 @@ def xntcall(path, targets=None, props=None): param: props - dictionary of properties to pass to the build module """ from xnt.xenant import invoke_build, load_build + build = load_build(buildfile) + path = os.path.dirname(buildfile) cwd = os.getcwd() os.chdir(path) - error_code = invoke_build(load_build(path), targets=targets, props=props) + error_code = invoke_build(build, targets=targets, props=props) os.chdir(cwd) return error_code diff --git a/xnt/tests/xenantargparsertests.py b/xnt/tests/xenantargparsertests.py index 3a22b33..04c8d1c 100644 --- a/xnt/tests/xenantargparsertests.py +++ b/xnt/tests/xenantargparsertests.py @@ -128,5 +128,31 @@ class XenantArgParserTests(unittest.TestCase): self.assertIsNotNone(args["targets"]) self.assertEqual(len(args["targets"]), 0) + def test_build_file_spec_short(self): + """Test build file option""" + args_in = ["-b", "mybuildfile.py"] + args = xnt.xenant.parse_args(args_in) + self.assertIsNotNone(args) + self.assertFalse(args["verbose"]) + self.assertFalse(args["list-targets"]) + self.assertIsNotNone(args["build-file"]) + self.assertEqual(args["build-file"], "mybuildfile.py") + self.assertIsNone(args["properties"]) + self.assertIsNotNone(args["targets"]) + self.assertEqual(len(args["targets"]), 0) + + def test_build_file_spec_long(self): + """Test build file option""" + args_in = ["--build-file", "mybuildfile.py"] + args = xnt.xenant.parse_args(args_in) + self.assertIsNotNone(args) + self.assertFalse(args["verbose"]) + self.assertFalse(args["list-targets"]) + self.assertIsNotNone(args["build-file"]) + self.assertEqual(args["build-file"], "mybuildfile.py") + self.assertIsNone(args["properties"]) + self.assertIsNotNone(args["targets"]) + self.assertEqual(len(args["targets"]), 0) + if __name__ == "__main__": unittest.main() diff --git a/xnt/xenant.py b/xnt/xenant.py index 9e5a3df..5e8dc66 100644 --- a/xnt/xenant.py +++ b/xnt/xenant.py @@ -33,12 +33,15 @@ def main(): """Xnt Entry Point""" start_time = time.time() args = parse_args(sys.argv[1:]) + build_file = "./build.py" if args["verbose"]: LOGGER.setLevel(logging.DEBUG) + if args["build-file"]: + build_file = args["build-file"] if args["list-targets"]: - error_code = list_targets(load_build()) + error_code = list_targets(load_build(build_file)) else: - error_code = invoke_build(load_build(), + error_code = invoke_build(load_build(build_file), args["targets"], args["properties"]) elapsed_time = time.time() - start_time @@ -47,15 +50,20 @@ def main(): LOGGER.info("Failure") from xnt.tasks import rm rm("build.pyc", - "__pycache__") + "__pycache__", + build_file + "c", + os.path.join(os.path.dirname(build_file), "__pycache__")) if error_code != 0: sys.exit(error_code) -def load_build(path=""): +def load_build(buildfile="./build.py"): """Load build file Load the build.py and return the resulting import """ + path = os.path.dirname(buildfile) + build = os.path.basename(buildfile) + buildmodule = os.path.splitext(build)[0] if not path: path = os.getcwd() else: @@ -63,17 +71,17 @@ def load_build(path=""): sys.path.append(path) cwd = os.getcwd() os.chdir(path) - if not os.path.exists("build.py"): + if not os.path.exists(build): LOGGER.error("There was no build file") sys.exit(1) try: - return __import__("build", fromlist=[]) + return __import__(buildmodule, fromlist=[]) except ImportError: LOGGER.error("HOW?!") return None finally: sys.path.remove(path) - del sys.modules["build"] + del sys.modules[buildmodule] os.chdir(cwd) def invoke_build(build, targets=None, props=None): @@ -147,6 +155,11 @@ def parse_args(args_in): action="version", version=__version__, help="Print Xnt Version and quit") + parser.add_argument( + "-b", "--build-file", + dest="build-file", + help="""Specify a build file if different than defaut or in different + path""") parser.add_argument("-l", "--list-targets", action="store_true", dest="list-targets", -- cgit v1.2.1 From bef742210b3f620b6e805a77a5320b79ab78b985 Mon Sep 17 00:00:00 2001 From: kennyballou Date: Sat, 9 Mar 2013 20:28:43 -0700 Subject: Update documentation about build files --- README.rst | 3 +++ docs/source/taskreference.rst | 5 ++--- docs/source/xenant.rst | 3 +++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index a9b66f2..f501df3 100644 --- a/README.rst +++ b/README.rst @@ -226,6 +226,9 @@ Where ``[options]`` are one of the following: * ``-v``: verbose, turn on logging +* ``-b BUILDFILE`` or ``--build-file BUILDFILE``: Specify build file + for Xnt to load + And where ``[target]+`` are any target(s) method in your ``build.py`` file or: diff --git a/docs/source/taskreference.rst b/docs/source/taskreference.rst index a65f00e..3a36d21 100644 --- a/docs/source/taskreference.rst +++ b/docs/source/taskreference.rst @@ -89,15 +89,14 @@ Miscellaneous Tasks change; I'm not sure how I feel about that yet.] .. _xnt.tasks.xntcall: -.. function:: xntcall(path, targets=None, props=None) +.. function:: xntcall(buildfile, targets=None, props=None) Invoke the *target(s)* of a build file in a different *path*. *target* is the name of the target to invoke (similar to *target* of a regular invocation. - *path* is the relative or full path to where the "sub" *build.py* file can - be found. + *buildfile* is the path (relative or full) and build file to use Compile Tasks ============= diff --git a/docs/source/xenant.rst b/docs/source/xenant.rst index 156883f..f5907bb 100644 --- a/docs/source/xenant.rst +++ b/docs/source/xenant.rst @@ -84,6 +84,9 @@ Where options can be any and all of the following (unless otherwise specified): * ``-v`` or ``--verbose``: add verbose output to the execution of Xnt +* ``-b BUILDFILE`` or ``--build-file BUILDFILE``: specifiy to Xnt the build + module to load + .. _xntPropertiesParameters: Properties and Parameter Passing -- cgit v1.2.1 From dc48af934f5f5db12faddf9fd9419635d1e80368 Mon Sep 17 00:00:00 2001 From: kennyballou Date: Sat, 9 Mar 2013 18:37:54 -0700 Subject: Update documentation to reflect option changes --- README.rst | 11 ++++++----- docs/source/xenant.rst | 20 ++++++++++---------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/README.rst b/README.rst index a9b66f2..b76b82d 100644 --- a/README.rst +++ b/README.rst @@ -224,7 +224,7 @@ Command Usage: Where ``[options]`` are one of the following: -* ``-v``: verbose, turn on logging +* ``-v`` or ``--verbose``: verbose, turn on logging And where ``[target]+`` are any target(s) method in your ``build.py`` file or: @@ -235,13 +235,14 @@ file or: Other Commands -------------- -* ``list-targets``: Xnt will print all targets marked by the - ``@target`` decorator and possibly their docstrings if they are +* ``-l`` or ``--list-targets``: Xnt will print all targets marked by + the ``@target`` decorator and possibly their docstrings if they are defined -* ``version``: Print the current version of Xnt and quit +* ``--version``: Print the current version of Xnt and quit -* ``help``: Print summary information about Xnt and command usage +* ``-h`` or ``--help``: Print summary information about Xnt and + command usage For more information about Xnt and the build in functions, see the `Package Documentation`_. diff --git a/docs/source/xenant.rst b/docs/source/xenant.rst index e9456fa..156883f 100644 --- a/docs/source/xenant.rst +++ b/docs/source/xenant.rst @@ -47,27 +47,27 @@ Xnt has a number of other commands that can be invoked besides those defined in the current directory's `build.py` file. One will need a build file to run. The others, however, do not. -* ``help`` prints a summary message, including information about the version of - Xnt, license, and usage. +* ``-h`` or ``--help`` prints a summary message, including information about + the version of Xnt, license, and usage. Usage:: - $ xnt help + $ xnt --help -* ``list-targets`` does exactly what the name should suggest: it prints a list - of the targets found in the current directory's `build.py` script, along with - any docstrings that may be defined with them. +* ``-l`` or ``--list-targets`` does exactly what the name should suggest: it + prints a list of the targets found in the current directory's `build.py` + script, along with any docstrings that may be defined with them. Usage:: - $ xnt list-targets + $ xnt --list-targets -* ``version`` prints Xnt's installed version. +* ``--version`` prints Xnt's installed version. Usage:: - $ xnt version + $ xnt --version .. _xntOptions: @@ -82,7 +82,7 @@ Usage:: Where options can be any and all of the following (unless otherwise specified): -* ``-v``: add verbose output to the execution of Xnt +* ``-v`` or ``--verbose``: add verbose output to the execution of Xnt .. _xntPropertiesParameters: -- cgit v1.2.1