From d4117776b4eaaa1b0e1d0cae20b1def8625e37b0 Mon Sep 17 00:00:00 2001 From: kennyballou Date: Thu, 31 Jan 2013 19:17:54 -0700 Subject: Start of rewrite of xenant's entry --- xnt/basecommand.py | 31 +++++++++++++++++ xnt/commands/__init__.py | 43 ++++++++++++++++++++++++ xnt/commands/help.py | 37 ++++++++++++++++++++ xnt/commands/listtargets.py | 49 +++++++++++++++++++++++++++ xnt/commands/target.py | 67 ++++++++++++++++++++++++++++++++++++ xnt/commands/version.py | 30 +++++++++++++++++ xnt/runner.py | 47 ++++++++++++++++++++++++++ xnt/xenant.py | 82 +-------------------------------------------- 8 files changed, 305 insertions(+), 81 deletions(-) create mode 100644 xnt/basecommand.py create mode 100644 xnt/commands/__init__.py create mode 100644 xnt/commands/help.py create mode 100644 xnt/commands/listtargets.py create mode 100644 xnt/commands/target.py create mode 100644 xnt/commands/version.py create mode 100644 xnt/runner.py diff --git a/xnt/basecommand.py b/xnt/basecommand.py new file mode 100644 index 0000000..0cd772c --- /dev/null +++ b/xnt/basecommand.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python + +# 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 os +import sys + +class Command(object): + name = None + usage = None + hidden = False + + def __init__(self): + pass + + def run(arguments=[]): + pass diff --git a/xnt/commands/__init__.py b/xnt/commands/__init__.py new file mode 100644 index 0000000..473d61a --- /dev/null +++ b/xnt/commands/__init__.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python + +# 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, +} + +SUCCESS = 0 +ERROR = 1 +UNKNOWN_ERROR = 2 + +def get_summaries(ignore_hidden=True): + 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 new file mode 100644 index 0000000..ea84551 --- /dev/null +++ b/xnt/commands/help.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +# 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.basecommands import Command, SUCCESS + +class HelpCommand(Command): + name = 'help' + usage = """""" + summary = 'Print Usage Summary' + + def run(self, arguments=[]): + from xnt.commands import get_summaries + from xnt import __version__, __license__ + commands = get_summaries() + print(__version__) + print(__license__) + print("\n") + for name, summary in commands: + print(name) + print("\t" + summary) + + return SUCCESS diff --git a/xnt/commands/listtargets.py b/xnt/commands/listtargets.py new file mode 100644 index 0000000..f5d48c3 --- /dev/null +++ b/xnt/commands/listtargets.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +# 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, SUCCESS, ERROR +from xnt.xenant import loadBuild +import logging + +logger = logging.getLogger("xnt") + +class ListTargetsCommand(Command): + name = 'list-targets' + usege = """""" + summary = "Prints targets in build file" + + def run(self, arguments=[]): + build = loadBuild + try: + for f in dir(build): + try: + fa = getattr(build, f) + if fa.decorator == "target": + print(f + ":") + if fa.__doc__: + print(fa.__doc__) + print("\n") + except AttributeError: + pass + except Exception as ex: + logger.error(ex) + return ERROR + return SUCCESS + except Exception as ex: + logger.error(ex) + return ERROR diff --git a/xnt/commands/target.py b/xnt/commands/target.py new file mode 100644 index 0000000..e06b58a --- /dev/null +++ b/xnt/commands/target.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python + +# 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, SUCCESS, ERROR, UNKNOWN_ERROR +from xnt.xenant import loadBuild +import logging + +logger = logging.getLogger("xnt") + +class TargetCommand(Command): + name = '' + usage = """""" + summary = "Invokes target(s) in build.py" + + def run(self, targets=[], props=[]): + if targets: + for t in targets: + ec = self.callTarget(t, props) + if ec: + return ec + return SUCCESS + else: + return self.callTarget("default", props) + + def callTarget(self, targetName, props): + build = loadBuild() + def processParams(params, buildProperties={}): + properties = buildProperties if buildProperties is not None else {} + for p in params: + name, value = p[2:].split("=") + properties[name] = value + return properties + def __getProperties(): + try: + return getattr(build, "properties") + except AttributeError: + return None + try: + if len(props) > 0: + setattr(build, + "properties", + processParams(props, __getProperties())) + target = getattr(build, targetName) + ec = target() + return ec if ec else 0 + except AttributeError: + logger.warning("There was no target: %s", targetName) + return ERROR + except Exception as ex: + logger.error(ex) + return UNKNOWN_ERROR + diff --git a/xnt/commands/version.py b/xnt/commands/version.py new file mode 100644 index 0000000..09bd239 --- /dev/null +++ b/xnt/commands/version.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python + +# 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.basecommands import Command, SUCCESS + +class VersionCommand(Command): + name = 'version' + usage = """""" + summary = "Print Version of Xnt" + + def run(arguments=[]): + from xnt import __version__ + print(__version__) + + return SUCCESS diff --git a/xnt/runner.py b/xnt/runner.py new file mode 100644 index 0000000..6960356 --- /dev/null +++ b/xnt/runner.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python + +# 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 os +import sys +import logger + +logging.basicConfig(format="%(asctime)s:%(levelname)s:%(message)s") +logger = logging.Logger(name=__name__) +logger.addHandler(logging.StreamHandler()) + +def main(): + 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) + commands = list(c for c in sys.argv[1:] + if c not in opts and c not in params) + #run things + elapsed_time = time.time() - start_time + logger.info("Execution time: %.3f", elapsed_time) + logger.info("Success" if ec == 0 else "Failure") + from xnt.tasks import rm + rm("build.pyc", + "__pycache__") + if ec != 0: + sys.exit(ec) + +if __name__ == "__main__": + ec = main() + if ec: + sys.exit(ec) diff --git a/xnt/xenant.py b/xnt/xenant.py index b9f40ab..453c4a2 100644 --- a/xnt/xenant.py +++ b/xnt/xenant.py @@ -21,34 +21,15 @@ import sys import time import logging -logging.basicConfig(format="%(asctime)s:%(levelname)s:%(message)s") -logger = logging.Logger(name=__name__) -logger.addHandler(logging.StreamHandler()) - -def usageAction(): - print(usage()); - sys.exit(0) - -def versionAction(): - print(version()) - sys.exit(0) def verboseAction(): logging.getLogger("xnt").setLevel(logging.INFO) actions = { - "--usage": usageAction, - "--version": versionAction, "-v" : verboseAction, } def main(): - start_time = time.time() - params = list(p for p in sys.argv[1:] if p.startswith('-D')) - opts = list(o for o in sys.argv[1:] - if o.startswith('-') and o not in params) - targets = list(a for a in sys.argv[1:] - if a not in opts and a not in params) for opt in opts: if opt in actions: actions[opt]() @@ -64,38 +45,6 @@ def main(): exit_codes.append(invoke(t)) else: exit_codes.append(invoke("default")) - from xnt.tasks import rm - rm("build.pyc", - "__pycache__") - elapsed_time = time.time() - start_time - logger.info("Execution time: %.3f", elapsed_time) - ec = sum(exit_codes) - logger.info("Success" if ec == 0 else "Failure") - if ec != 0: - sys.exit(ec) - -def invokeBuild(build, targetName, props=[]): - def __getProperties(): - try: - return getattr(build, "properties") - except AttributeError: - return None - - if targetName == "list-targets": - return printTargets(build) - try: - if len(props) > 0: - setattr(build, "properties", __processParams(props, - __getProperties())) - target = getattr(build, targetName) - ec = target() - return ec if ec else 0 - except AttributeError: - logger.warning("There was no target: %s", targetName) - return -2 - except Exception as e: - logger.error(e) - return -3 def usage(): import xnt @@ -116,29 +65,7 @@ def usage(): + endl return usageText -def version(): - import xnt - return xnt.__version__ - -def printTargets(build): - print(version()) - print("\n") - try: - for f in dir(build): - try: - fa = getattr(build, f) - if fa.decorator == "target": - print(f + ":") - if fa.__doc__: - print(fa.__doc__) - print("\n") - except AttributeError: - pass - except Exception as e: - logger.error(e) - return 1 - -def __loadBuild(path=""): +def loadBuild(path=""): if not path: path = os.getcwd() else: @@ -159,12 +86,5 @@ def __loadBuild(path=""): del sys.modules["build"] os.chdir(cwd) -def __processParams(params, buildProperties={}): - properties = buildProperties if buildProperties is not None else {} - for p in params: - name, value = p[2:].split("=") - properties[name] = value - return properties - if __name__ == "__main__": main() -- cgit v1.2.1 From 7ab6083f53f180ff49b2739a2fb1d3b6269a4a56 Mon Sep 17 00:00:00 2001 From: kennyballou Date: Fri, 1 Feb 2013 18:52:53 -0700 Subject: Refactor, Fix, and Further hack Xenant's rewrite My first hack toward this (major) refactor had a number of mistakes that were (hopefully) corrected. I intend to now write tests for these (may require a bit more refactoring...). But there is also probably a lot more that needs to be done for this. --- setup.py | 6 +++--- xnt/__init__.py | 2 +- xnt/cmdoptions.py | 26 ++++++++++++++++++++++++++ xnt/commands/__init__.py | 6 ------ xnt/commands/help.py | 3 ++- xnt/commands/listtargets.py | 12 ++++++------ xnt/commands/target.py | 9 +++++---- xnt/commands/version.py | 3 ++- xnt/runner.py | 26 +++++++++++++++++++++++--- xnt/status_codes.py | 21 +++++++++++++++++++++ xnt/xenant.py | 1 + 11 files changed, 90 insertions(+), 25 deletions(-) create mode 100644 xnt/cmdoptions.py create mode 100644 xnt/status_codes.py diff --git a/setup.py b/setup.py index c81da5c..c283570 100644 --- a/setup.py +++ b/setup.py @@ -25,21 +25,21 @@ def read(fname): setup( name="Xnt", - version="0.4.1", + version="0.5.0dev1", author="Kenny Ballou", author_email="kennethmgballou@gmail.com", url="https://bitbucket.org/devnulltao/xnt", description=("High-Level build script for doing more complex build tasks"), packages=find_packages(), test_suite="xnt.tests", - scripts=["xnt/xenant.py",], + scripts=["xnt/runner.py",], package_data={ }, long_description=read("README"), platforms=["Linux", "Windows",], entry_points={ 'console_scripts': [ - 'xnt = xnt.xenant:main', + 'xnt = xnt.runner:main', ], }, install_requires=['distribute',], diff --git a/xnt/__init__.py b/xnt/__init__.py index 810a83c..9d9f2a3 100644 --- a/xnt/__init__.py +++ b/xnt/__init__.py @@ -16,7 +16,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -__version__ = "Xnt 0.4.1" +__version__ = "Xnt 0.5.0dev1" __license__ = """ Xnt -- A Wrapper Build Tool Copyright (C) 2012 Kenny Ballou diff --git a/xnt/cmdoptions.py b/xnt/cmdoptions.py new file mode 100644 index 0000000..9f3c944 --- /dev/null +++ b/xnt/cmdoptions.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python + +# 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 flipVerboseFlag(): + logging.getLogger("xnt").setLevel(logging.INFO) + +options = { + "-v": flipVerboseFlag, +} diff --git a/xnt/commands/__init__.py b/xnt/commands/__init__.py index 473d61a..d50ab3a 100644 --- a/xnt/commands/__init__.py +++ b/xnt/commands/__init__.py @@ -19,19 +19,13 @@ 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, } -SUCCESS = 0 -ERROR = 1 -UNKNOWN_ERROR = 2 - def get_summaries(ignore_hidden=True): items = [] diff --git a/xnt/commands/help.py b/xnt/commands/help.py index ea84551..88fd01a 100644 --- a/xnt/commands/help.py +++ b/xnt/commands/help.py @@ -16,7 +16,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from xnt.basecommands import Command, SUCCESS +from xnt.basecommand import Command +from xnt.status_codes import SUCCESS class HelpCommand(Command): name = 'help' diff --git a/xnt/commands/listtargets.py b/xnt/commands/listtargets.py index f5d48c3..5dddb92 100644 --- a/xnt/commands/listtargets.py +++ b/xnt/commands/listtargets.py @@ -16,11 +16,12 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from xnt.basecommand import Command, SUCCESS, ERROR +from xnt.basecommand import Command +from xnt.status_codes import SUCCESS, ERROR from xnt.xenant import loadBuild import logging -logger = logging.getLogger("xnt") +logger = logging.getLogger(__name__) class ListTargetsCommand(Command): name = 'list-targets' @@ -28,9 +29,11 @@ class ListTargetsCommand(Command): summary = "Prints targets in build file" def run(self, arguments=[]): - build = loadBuild + build = loadBuild() + logger.debug("build is null? %s", build == None) try: for f in dir(build): + logger.debug("Attribute %s:", f) try: fa = getattr(build, f) if fa.decorator == "target": @@ -44,6 +47,3 @@ class ListTargetsCommand(Command): logger.error(ex) return ERROR return SUCCESS - except Exception as ex: - logger.error(ex) - return ERROR diff --git a/xnt/commands/target.py b/xnt/commands/target.py index e06b58a..b1f3d2b 100644 --- a/xnt/commands/target.py +++ b/xnt/commands/target.py @@ -16,7 +16,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from xnt.basecommand import Command, SUCCESS, ERROR, UNKNOWN_ERROR +from xnt.basecommand import Command +from xnt.status_codes import SUCCESS, ERROR, UNKNOWN_ERROR from xnt.xenant import loadBuild import logging @@ -55,9 +56,9 @@ class TargetCommand(Command): setattr(build, "properties", processParams(props, __getProperties())) - target = getattr(build, targetName) - ec = target() - return ec if ec else 0 + target = getattr(build, targetName) + ec = target() + return ec if ec else 0 except AttributeError: logger.warning("There was no target: %s", targetName) return ERROR diff --git a/xnt/commands/version.py b/xnt/commands/version.py index 09bd239..34853c4 100644 --- a/xnt/commands/version.py +++ b/xnt/commands/version.py @@ -16,7 +16,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from xnt.basecommands import Command, SUCCESS +from xnt.basecommand import Command +from xnt.status_codes import SUCCESS class VersionCommand(Command): name = 'version' diff --git a/xnt/runner.py b/xnt/runner.py index 6960356..55f7ea3 100644 --- a/xnt/runner.py +++ b/xnt/runner.py @@ -18,7 +18,11 @@ import os import sys -import logger +import time +import logging +from xnt.cmdoptions import options +from xnt.commands import commands +from xnt.commands.target import TargetCommand logging.basicConfig(format="%(asctime)s:%(levelname)s:%(message)s") logger = logging.Logger(name=__name__) @@ -29,9 +33,25 @@ def main(): 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) - commands = list(c for c in sys.argv[1:] - if c not in opts and c 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 + command = commands[cmd]() + ec = command.run() + logger.debug("cmd_found = %s", cmd_found) + if cmd_found == False: + command = TargetCommand() + ec = command.run(targets=cmds, props=params) elapsed_time = time.time() - start_time logger.info("Execution time: %.3f", elapsed_time) logger.info("Success" if ec == 0 else "Failure") diff --git a/xnt/status_codes.py b/xnt/status_codes.py new file mode 100644 index 0000000..3549a14 --- /dev/null +++ b/xnt/status_codes.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python + +# 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 . + +SUCCESS = 0 +ERROR = 1 +UNKNOWN_ERROR = 2 diff --git a/xnt/xenant.py b/xnt/xenant.py index 453c4a2..783f99f 100644 --- a/xnt/xenant.py +++ b/xnt/xenant.py @@ -21,6 +21,7 @@ import sys import time import logging +logger = logging.getLogger(__name__) def verboseAction(): logging.getLogger("xnt").setLevel(logging.INFO) -- cgit v1.2.1 From 80150a10208479b0a7c1daf747fbc700fff6d2ac Mon Sep 17 00:00:00 2001 From: kennyballou Date: Thu, 14 Feb 2013 10:57:03 -0700 Subject: Remove Debug Log Emit and Needless Success Message --- xnt/runner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xnt/runner.py b/xnt/runner.py index 55f7ea3..3d78f7a 100644 --- a/xnt/runner.py +++ b/xnt/runner.py @@ -48,13 +48,13 @@ def main(): cmd_found = True command = commands[cmd]() ec = command.run() - logger.debug("cmd_found = %s", cmd_found) if cmd_found == False: command = TargetCommand() ec = command.run(targets=cmds, props=params) elapsed_time = time.time() - start_time logger.info("Execution time: %.3f", elapsed_time) - logger.info("Success" if ec == 0 else "Failure") + if ec != 0: + logger.info("Failure") from xnt.tasks import rm rm("build.pyc", "__pycache__") -- cgit v1.2.1 From 164fda0ca69a001a84b52577e837be502c010de1 Mon Sep 17 00:00:00 2001 From: kennyballou Date: Thu, 14 Feb 2013 11:42:25 -0700 Subject: Remove Usage Method --- xnt/xenant.py | 46 ---------------------------------------------- 1 file changed, 46 deletions(-) diff --git a/xnt/xenant.py b/xnt/xenant.py index 783f99f..e2f24d5 100644 --- a/xnt/xenant.py +++ b/xnt/xenant.py @@ -23,49 +23,6 @@ import logging logger = logging.getLogger(__name__) -def verboseAction(): - logging.getLogger("xnt").setLevel(logging.INFO) - -actions = { - "-v" : verboseAction, -} - -def main(): - for opt in opts: - if opt in actions: - actions[opt]() - else: - logger.debug("%s is not a valid option", opt) - exit_codes = [] - def invoke(target): - return invokeBuild(__loadBuild(), - target, - params) - if targets: - for t in targets: - exit_codes.append(invoke(t)) - else: - exit_codes.append(invoke("default")) - -def usage(): - import xnt - endl = os.linesep - usageText = \ - xnt.__version__ + endl + \ - xnt.__license__ + endl + \ - "Usage:\txnt [options] [target]" + endl + \ - "Where [target] is a target in your ``build.py`` file" + endl + \ - " And [options] is one of the falling:" + endl + \ - "\t-v: print verbose information about Xnt's running" + endl + \ - "\t--usage: Print this message" + endl + \ - "In addition to targets defined by your ``build.py`` file" + endl + \ - "\t``list-targets`` can be used in place of [targets] to" + endl + \ - "\t\tlist targets and docstrings defined in your ``build.py`` file" + \ - endl + \ - "\tIf no [target] is provided, Xnt will try the target: ``default``" \ - + endl - return usageText - def loadBuild(path=""): if not path: path = os.getcwd() @@ -86,6 +43,3 @@ def loadBuild(path=""): sys.path.remove(path) del sys.modules["build"] os.chdir(cwd) - -if __name__ == "__main__": - main() -- cgit v1.2.1 From 956f60a6b72e530597c41a3938a2ccdb5abdd90a Mon Sep 17 00:00:00 2001 From: kennyballou Date: Thu, 14 Feb 2013 13:16:23 -0700 Subject: Add Target Command to Commands List This makes for a better summary when running `xnt help`. Further, if someone tries to run this as a command, it will result in the Command attempting to run the ``default`` target --- xnt/commands/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xnt/commands/__init__.py b/xnt/commands/__init__.py index d50ab3a..8d51cec 100644 --- a/xnt/commands/__init__.py +++ b/xnt/commands/__init__.py @@ -19,11 +19,13 @@ 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): -- cgit v1.2.1 From 86249dfc82e273fb947b653303d03eacafd9d16b Mon Sep 17 00:00:00 2001 From: kennyballou Date: Thu, 14 Feb 2013 13:20:37 -0700 Subject: Fix variable name spelling mistake --- xnt/commands/listtargets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xnt/commands/listtargets.py b/xnt/commands/listtargets.py index 5dddb92..f86ec2a 100644 --- a/xnt/commands/listtargets.py +++ b/xnt/commands/listtargets.py @@ -25,7 +25,7 @@ logger = logging.getLogger(__name__) class ListTargetsCommand(Command): name = 'list-targets' - usege = """""" + usage = """""" summary = "Prints targets in build file" def run(self, arguments=[]): -- cgit v1.2.1 From fe375100833c625c3076a010ef572cf30eb18c7e Mon Sep 17 00:00:00 2001 From: kennyballou Date: Thu, 14 Feb 2013 13:39:35 -0700 Subject: Refactor build module loading Add field to commands to flag the build module to be loaded. Refactor commands to use dependency injection for the build module (this should allow for some testing of the commands). --- xnt/basecommand.py | 1 + xnt/commands/help.py | 1 + xnt/commands/listtargets.py | 12 +++++++----- xnt/commands/target.py | 12 +++++++----- xnt/commands/version.py | 1 + xnt/runner.py | 28 ++++++++++++++++++++++++++-- 6 files changed, 43 insertions(+), 12 deletions(-) diff --git a/xnt/basecommand.py b/xnt/basecommand.py index 0cd772c..83bdf0a 100644 --- a/xnt/basecommand.py +++ b/xnt/basecommand.py @@ -23,6 +23,7 @@ class Command(object): name = None usage = None hidden = False + need_build = False def __init__(self): pass diff --git a/xnt/commands/help.py b/xnt/commands/help.py index 88fd01a..746ad78 100644 --- a/xnt/commands/help.py +++ b/xnt/commands/help.py @@ -23,6 +23,7 @@ class HelpCommand(Command): name = 'help' usage = """""" summary = 'Print Usage Summary' + needs_build = False def run(self, arguments=[]): from xnt.commands import get_summaries diff --git a/xnt/commands/listtargets.py b/xnt/commands/listtargets.py index f86ec2a..4ecc645 100644 --- a/xnt/commands/listtargets.py +++ b/xnt/commands/listtargets.py @@ -18,7 +18,6 @@ from xnt.basecommand import Command from xnt.status_codes import SUCCESS, ERROR -from xnt.xenant import loadBuild import logging logger = logging.getLogger(__name__) @@ -27,15 +26,18 @@ class ListTargetsCommand(Command): name = 'list-targets' usage = """""" summary = "Prints targets in build file" + needs_build = True + + def __init__(self, build): + self.build = build def run(self, arguments=[]): - build = loadBuild() - logger.debug("build is null? %s", build == None) + logger.debug("build is null? %s", self.build == None) try: - for f in dir(build): + for f in dir(self.build): logger.debug("Attribute %s:", f) try: - fa = getattr(build, f) + fa = getattr(self.build, f) if fa.decorator == "target": print(f + ":") if fa.__doc__: diff --git a/xnt/commands/target.py b/xnt/commands/target.py index b1f3d2b..ad43dd0 100644 --- a/xnt/commands/target.py +++ b/xnt/commands/target.py @@ -18,7 +18,6 @@ from xnt.basecommand import Command from xnt.status_codes import SUCCESS, ERROR, UNKNOWN_ERROR -from xnt.xenant import loadBuild import logging logger = logging.getLogger("xnt") @@ -27,6 +26,10 @@ class TargetCommand(Command): name = '' usage = """""" summary = "Invokes target(s) in build.py" + needs_build = True + + def __init__(self, build): + self.build = build def run(self, targets=[], props=[]): if targets: @@ -39,7 +42,6 @@ class TargetCommand(Command): return self.callTarget("default", props) def callTarget(self, targetName, props): - build = loadBuild() def processParams(params, buildProperties={}): properties = buildProperties if buildProperties is not None else {} for p in params: @@ -48,15 +50,15 @@ class TargetCommand(Command): return properties def __getProperties(): try: - return getattr(build, "properties") + return getattr(self.build, "properties") except AttributeError: return None try: if len(props) > 0: - setattr(build, + setattr(self.build, "properties", processParams(props, __getProperties())) - target = getattr(build, targetName) + target = getattr(self.build, targetName) ec = target() return ec if ec else 0 except AttributeError: diff --git a/xnt/commands/version.py b/xnt/commands/version.py index 34853c4..350a739 100644 --- a/xnt/commands/version.py +++ b/xnt/commands/version.py @@ -23,6 +23,7 @@ class VersionCommand(Command): name = 'version' usage = """""" summary = "Print Version of Xnt" + needs_build = False def run(arguments=[]): from xnt import __version__ diff --git a/xnt/runner.py b/xnt/runner.py index 3d78f7a..b0cf15e 100644 --- a/xnt/runner.py +++ b/xnt/runner.py @@ -46,10 +46,13 @@ def main(): for cmd in cmds: if cmd in commands: cmd_found = True - command = commands[cmd]() + if commands[cmd].needs_build: + command = commands[cmd](loadBuild()) + else: + command = commands[cmd]() ec = command.run() if cmd_found == False: - command = TargetCommand() + command = TargetCommand(loadBuild()) ec = command.run(targets=cmds, props=params) elapsed_time = time.time() - start_time logger.info("Execution time: %.3f", elapsed_time) @@ -61,6 +64,27 @@ def main(): if ec != 0: sys.exit(ec) +def loadBuild(path=""): + if not path: + path = os.getcwd() + else: + path = os.path.abspath(path) + sys.path.append(path) + cwd = os.getcwd() + os.chdir(path) + if not os.path.exists("build.py"): + logger.error("There was no build file") + sys.exit(1) + try: + return __import__("build", fromlist=[]) + except ImportError: + logger.error("HOW?!") + return None + finally: + sys.path.remove(path) + del sys.modules["build"] + os.chdir(cwd) + if __name__ == "__main__": ec = main() if ec: -- cgit v1.2.1 From 037397787ceb3b2def0e9e06787b11fafac7fdf0 Mon Sep 17 00:00:00 2001 From: kennyballou Date: Thu, 14 Feb 2013 13:44:39 -0700 Subject: Rename runner back to xenant --- setup.py | 4 +-- xnt/runner.py | 91 ----------------------------------------------------------- xnt/xenant.py | 48 ++++++++++++++++++++++++++++++- 3 files changed, 49 insertions(+), 94 deletions(-) delete mode 100644 xnt/runner.py diff --git a/setup.py b/setup.py index c283570..2554ad3 100644 --- a/setup.py +++ b/setup.py @@ -32,14 +32,14 @@ setup( description=("High-Level build script for doing more complex build tasks"), packages=find_packages(), test_suite="xnt.tests", - scripts=["xnt/runner.py",], + scripts=["xnt/xenant.py",], package_data={ }, long_description=read("README"), platforms=["Linux", "Windows",], entry_points={ 'console_scripts': [ - 'xnt = xnt.runner:main', + 'xnt = xnt.xenant:main', ], }, install_requires=['distribute',], diff --git a/xnt/runner.py b/xnt/runner.py deleted file mode 100644 index b0cf15e..0000000 --- a/xnt/runner.py +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env python - -# 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 os -import sys -import time -import logging -from xnt.cmdoptions import options -from xnt.commands import commands -from xnt.commands.target import TargetCommand - -logging.basicConfig(format="%(asctime)s:%(levelname)s:%(message)s") -logger = logging.Logger(name=__name__) -logger.addHandler(logging.StreamHandler()) - -def main(): - 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](loadBuild()) - else: - command = commands[cmd]() - ec = command.run() - if cmd_found == False: - command = TargetCommand(loadBuild()) - ec = command.run(targets=cmds, props=params) - elapsed_time = time.time() - start_time - logger.info("Execution time: %.3f", elapsed_time) - if ec != 0: - logger.info("Failure") - from xnt.tasks import rm - rm("build.pyc", - "__pycache__") - if ec != 0: - sys.exit(ec) - -def loadBuild(path=""): - if not path: - path = os.getcwd() - else: - path = os.path.abspath(path) - sys.path.append(path) - cwd = os.getcwd() - os.chdir(path) - if not os.path.exists("build.py"): - logger.error("There was no build file") - sys.exit(1) - try: - return __import__("build", fromlist=[]) - except ImportError: - logger.error("HOW?!") - return None - finally: - sys.path.remove(path) - del sys.modules["build"] - os.chdir(cwd) - -if __name__ == "__main__": - ec = main() - if ec: - sys.exit(ec) diff --git a/xnt/xenant.py b/xnt/xenant.py index e2f24d5..b0cf15e 100644 --- a/xnt/xenant.py +++ b/xnt/xenant.py @@ -20,8 +20,49 @@ import os import sys import time import logging +from xnt.cmdoptions import options +from xnt.commands import commands +from xnt.commands.target import TargetCommand -logger = logging.getLogger(__name__) +logging.basicConfig(format="%(asctime)s:%(levelname)s:%(message)s") +logger = logging.Logger(name=__name__) +logger.addHandler(logging.StreamHandler()) + +def main(): + 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](loadBuild()) + else: + command = commands[cmd]() + ec = command.run() + if cmd_found == False: + command = TargetCommand(loadBuild()) + ec = command.run(targets=cmds, props=params) + elapsed_time = time.time() - start_time + logger.info("Execution time: %.3f", elapsed_time) + if ec != 0: + logger.info("Failure") + from xnt.tasks import rm + rm("build.pyc", + "__pycache__") + if ec != 0: + sys.exit(ec) def loadBuild(path=""): if not path: @@ -43,3 +84,8 @@ def loadBuild(path=""): sys.path.remove(path) del sys.modules["build"] os.chdir(cwd) + +if __name__ == "__main__": + ec = main() + if ec: + sys.exit(ec) -- cgit v1.2.1 From af38cbce8f3d1e27442f3ec47c5cc62d16c0f918 Mon Sep 17 00:00:00 2001 From: kennyballou Date: Thu, 14 Feb 2013 13:46:29 -0700 Subject: Remove xenant tests These will be replaced by tests on the individual commands --- xnt/tests/xenanttests.py | 41 ----------------------------------------- 1 file changed, 41 deletions(-) delete mode 100644 xnt/tests/xenanttests.py diff --git a/xnt/tests/xenanttests.py b/xnt/tests/xenanttests.py deleted file mode 100644 index 043b40d..0000000 --- a/xnt/tests/xenanttests.py +++ /dev/null @@ -1,41 +0,0 @@ - -#!/usr/bin/env python - -# 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 sys -import os -import shutil -import xnt -import xnt.tasks -import xnt.xenant as xenant -import unittest - - -class XenantTests(unittest.TestCase): - def setUp(self): - os.mkdir("temp") - - def tearDown(self): - shutil.rmtree("temp") - - def test_version(self): - actual = xenant.version() - self.assertEqual(xnt.__version__, xenant.version()) - -if __name__ == "__main__": - unittest.main() -- cgit v1.2.1 From 61394de034014ec1ec35091922fe54daf13b4811 Mon Sep 17 00:00:00 2001 From: kennyballou Date: Thu, 14 Feb 2013 15:14:41 -0700 Subject: Replace newline character --- xnt/commands/help.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xnt/commands/help.py b/xnt/commands/help.py index 746ad78..35ec9bb 100644 --- a/xnt/commands/help.py +++ b/xnt/commands/help.py @@ -31,7 +31,7 @@ class HelpCommand(Command): commands = get_summaries() print(__version__) print(__license__) - print("\n") + print("Available Commands:") for name, summary in commands: print(name) print("\t" + summary) -- cgit v1.2.1 From 6e77b7ed20a768f695648adb24d1497c56ec21f9 Mon Sep 17 00:00:00 2001 From: kennyballou Date: Thu, 14 Feb 2013 15:27:17 -0700 Subject: Update Documentation regarding usage --- README | 17 ++++++++++++----- docs/source/xenant.rst | 32 +++++++++++++++++++------------- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/README b/README index 296014b..4b91b3a 100644 --- a/README +++ b/README @@ -197,15 +197,22 @@ Where ``[options]`` are one of the following: * ``--version``: print version and quit -And where ``[target]`` is any target method in your ``build.py`` file -or: +And where ``[target]+`` are any target(s) method in your ``build.py`` +file or: * Nothing; if no target is specified, Xnt will attempt to invoke the ``default`` target -* ``list-targets``: if this 'special' target is provided, Xnt will - print all targets marked by the ``@target`` decorator and possibly - their docstrings if they are defined +Other Commands +-------------- + +* ``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 + +* ``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 5bd6235..e9456fa 100644 --- a/docs/source/xenant.rst +++ b/docs/source/xenant.rst @@ -38,16 +38,22 @@ example:: Will execute `target1` through `targetN` in order of listing. -.. _specialTargets: +.. _otherCommands: -Special Targets ---------------- +Othes Commands +-------------- + +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. -"Special" targets (for lack of a better name) are targets that do not exist in -the build script, but rather are a part of Xnt. +Usage:: + + $ xnt help -Thus far, I have only defined one "special" target, ``list-targets`` (I don't -think this name is going to change again ...). * ``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 @@ -57,6 +63,12 @@ Usage:: $ xnt list-targets +* ``version`` prints Xnt's installed version. + +Usage:: + + $ xnt version + .. _xntOptions: Options @@ -72,12 +84,6 @@ Where options can be any and all of the following (unless otherwise specified): * ``-v``: add verbose output to the execution of Xnt -* ``--version``: Print the version of Xnt and exit - -* ``--usage``: Print version, license, usage information and quit. [I've - debatted between putting this as a special target and leaving it as an - option.. not sure which is better...] - .. _xntPropertiesParameters: Properties and Parameter Passing -- cgit v1.2.1 From bca77f0a1a2c325978a5292b142d063037d68a4c Mon Sep 17 00:00:00 2001 From: kennyballou Date: Thu, 21 Feb 2013 08:10:54 -0700 Subject: Add Change Notes --- README | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README b/README index 4b91b3a..53a58e1 100644 --- a/README +++ b/README @@ -9,6 +9,15 @@ A wrapper build tool Release Notes ============= +0.5.0: +----------- + +* Rewrite Command Parsing + * This change does incur some interface change. Namely, + ``--version`` is now ``version``, ``--usage`` is now ``help`` + * All other commands and switches are the same + * See `Package Documentation`_ for more information + 0.4.1:2012-01-25 ---------------- -- cgit v1.2.1 From b430fb92b9f02ba0f2b7407e9e3452475bd7991a Mon Sep 17 00:00:00 2001 From: kennyballou Date: Thu, 21 Feb 2013 10:29:07 -0700 Subject: Update return values section --- docs/source/buildfile.rst | 44 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/docs/source/buildfile.rst b/docs/source/buildfile.rst index 58e226a..b57cbe0 100644 --- a/docs/source/buildfile.rst +++ b/docs/source/buildfile.rst @@ -73,10 +73,32 @@ Return Values ============= The targets you define can return an error code (or '0' for success) however -you see fit. Doing this will give you a status message at the end of the -invocation of Xnt that will inform you if the target ran successfully or not -given your criteria (or will just say it succeeded if you don't specify a -return value at all). For example:: +you see fit. Xnt will emit 'Failure' if the status code is *not* zero and will +otherwise remain silent if the code is zero. Further, the status code returned +by your target will be returned as the exit code of Xnt when finished +executing. + +*Notice*, this allows Xnt to fail fast when attempting to execute multiple +targets. That is, if you specify more than one target, Xnt will stop at the +first failure. + +If you don't define a return value for a target, Xnt will assume success and +return '0'. + +Examples +-------- + +Not defining the return value:: + + @target + def foo(): + pass + +Will result in (no success message; other output may be shown):: + + ... + +Returning success (no success message; other output may be shown):: @target def foo(): @@ -85,9 +107,19 @@ return value at all). For example:: Will result in:: ... - Success -Most tasks have been updated to return error codes as well to that you can +Returning failure (not 0):: + + @target + def foo(): + return 1 + +Will result in:: + + ... + Failure + +Most tasks have been updated to return error codes as well so that you can return what it returns. If you find any tasks that can be updated to behave this way, please create an issue for it. -- cgit v1.2.1 From 44ef20c131021c7bcb83079d0e56321b6f9c17b4 Mon Sep 17 00:00:00 2001 From: kennyballou Date: Thu, 21 Feb 2013 10:29:20 -0700 Subject: Update Section Reference --- docs/source/buildfile.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/buildfile.rst b/docs/source/buildfile.rst index b57cbe0..6d1d31f 100644 --- a/docs/source/buildfile.rst +++ b/docs/source/buildfile.rst @@ -60,7 +60,7 @@ Next, we will look at a new target:: This is a standard definition of a Python function with a decorator. First, the ``target`` decorator marks the function definition as a target (to -be used by the ``list-targets`` command, see :ref:`specialTargets`). Next, we +be used by the ``list-targets`` command, see :ref:`otherCommands`). Next, we define the function; this function name *is* the name of the target. That is, the name given to the function will be name given to the command to invoke this target. Further, we have the docstring; (this is also used by the -- cgit v1.2.1