diff options
author | Hans Ulrich Niedermann <hun@n-dimensional.de> | 2008-07-26 11:26:15 +0200 |
---|---|---|
committer | Hans Ulrich Niedermann <hun@n-dimensional.de> | 2008-07-26 11:26:15 +0200 |
commit | 7a90533a806fd76e89795fff427473e7264662f7 (patch) | |
tree | 7bcf5c2f4455887a9786bdb60708126ef936329b | |
parent | 37ee99e8e72e2b8c50bec80f9b2bacc8dde04df7 (diff) | |
download | nbb-releases.tar.gz nbb-releases.tar.xz nbb-releases.zip |
nbb 0.2releases
* Switch to release tags including the package name
* Make automake's "nbb make" depend on configure etc.
Squashed commit of the following:
commit 9c4a035b71c7648b006b91a52e86edb2baea5138
Author: Hans Ulrich Niedermann <hun@n-dimensional.de>
Date: Sat Jul 26 10:36:31 2008 +0200
New version tag syntax: "make tag VER=1.2"
commit fefebc702664a683ceeafa800b0fe75178d63037
Author: Hans Ulrich Niedermann <hun@n-dimensional.de>
Date: Sat Jul 26 10:30:02 2008 +0200
Switch to release tags including the package name
This will reduce tag confusion when we fork into a
different project.
A tag like nbb-1.2 or foo-tools-1.2 is much more useful
than v1.2.
commit 330c382390ffbe3c361a763d5cee6febe1b30f5e
Author: Hans Ulrich Niedermann <hun@n-dimensional.de>
Date: Tue Jul 22 12:08:41 2008 +0200
Remove obsolete .htaccess file
commit b1d5fc06e235a45561bf53b4bfd07856cec4ea81
Author: Hans Ulrich Niedermann <hun@n-dimensional.de>
Date: Thu Jul 24 15:03:14 2008 +0200
Make automake's "make" command depend on configure
commit 958e81655ad143dfd54b099637db60db42f77fb0
Author: Hans Ulrich Niedermann <hun@n-dimensional.de>
Date: Thu Jul 24 15:00:33 2008 +0200
Adjust testcases for absolute builddirs
When configure is called as /path/to/configure instead of
../path/to/configure, the ".git/" test directories are reported
by "git init" using absolute pathnames, not must ".git/".
commit 72dac191283299c66356dc895eb6ba19982b16ab
Author: Hans Ulrich Niedermann <hun@n-dimensional.de>
Date: Thu Jul 24 14:59:19 2008 +0200
Fix typo in automake/distcheck test case
commit 7ca2e00188d8668b6b1f4116559ddae4e3cbb35c
Author: Hans Ulrich Niedermann <hun@n-dimensional.de>
Date: Thu Jul 24 13:32:49 2008 +0200
Open 0.1.x section in NEWS
commit e05a138e9e3099455fa23799550949512188b3c9
Author: Hans Ulrich Niedermann <hun@n-dimensional.de>
Date: Tue Jul 22 08:40:31 2008 +0200
Add license review to TODO
commit e2fd1f2e101486859899049147df7993c8042df7
Author: Hans Ulrich Niedermann <hun@n-dimensional.de>
Date: Sat Jul 19 00:25:12 2008 +0200
Ensure cmp/mv/rm rules are correct and silent
Make sure the "if cmp ... mv .. rm" in make rules are
correct and useful, and the cmp is silent.
commit b6e7a354ed1ab53aebdb775a800156629744a065
Author: Hans Ulrich Niedermann <hun@n-dimensional.de>
Date: Wed Jul 16 21:03:36 2008 +0200
Reflect code progress in TODO file, add plans
commit 9559ceb5def8ec5d2e5674e7bf25b484877b3e60
Author: Hans Ulrich Niedermann <hun@n-dimensional.de>
Date: Wed Jul 16 06:12:30 2008 +0200
Fix some issues found by pylint/pychecker
Includes real issues like wrong argument numbers and missing
ancestor __init__() calls, whitespace and comment cleanups.
Cannot "fix" everything because of a good amount of the warnings
raised by pylint/pychecker are false alarms.
commit c73487455e8d9a283fcb328eab8573c4c5bc73c7
Author: Hans Ulrich Niedermann <hun@n-dimensional.de>
Date: Wed Jul 16 06:11:57 2008 +0200
Add pylint and pychecker checks as "lint" target
-rw-r--r-- | Makefile.am | 17 | ||||
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | TODO | 75 | ||||
-rwxr-xr-x | build-helpers/package-version | 3 | ||||
-rw-r--r-- | doc/.htaccess | 15 | ||||
-rw-r--r-- | src/Makefile-files | 15 | ||||
-rw-r--r-- | src/nbb.in | 12 | ||||
-rw-r--r-- | src/nbblib/__init__.py | 6 | ||||
-rw-r--r-- | src/nbblib/bs.py | 60 | ||||
-rw-r--r-- | src/nbblib/commands.py | 3 | ||||
-rw-r--r-- | src/nbblib/main.py | 29 | ||||
-rw-r--r-- | src/nbblib/nbbcommands.py | 43 | ||||
-rw-r--r-- | src/nbblib/plugins.py | 45 | ||||
-rw-r--r-- | src/nbblib/progutils.py | 35 | ||||
-rw-r--r-- | src/nbblib/vcs.py | 23 | ||||
-rw-r--r-- | test/Makefile.am | 4 | ||||
-rw-r--r-- | test/local.at | 8 | ||||
-rw-r--r-- | test/nbb-automake.at | 2 | ||||
-rw-r--r-- | test/nbb-config.at | 4 | ||||
-rw-r--r-- | test/nbb-detect.at | 12 |
20 files changed, 245 insertions, 170 deletions
diff --git a/Makefile.am b/Makefile.am index 191238c..9b76bb5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -47,6 +47,7 @@ endif # Requires git 1.5 to work properly. if HAVE_GIT +# Usage: $ make tag VER=1.2 tag: test -d "$(top_srcdir)/.git" @cd "$(top_srcdir)" && $(GIT) status;: @@ -56,15 +57,15 @@ tag: @cd "$(top_srcdir)" && if $(GIT) diff-index --cached --quiet HEAD; then :; else \ echo "Uncommitted cached changes detected."; \ exit 2; fi - @if test "x$(TAG)" = "x"; then \ - echo "TAG not defined. Try 'make tag TAG=2.11' or something similar."; \ + @if test "x$(VER)" = "x"; then \ + echo "VER not defined. Try 'make tag VER=2.11' or something similar."; \ exit 3; \ fi - @test "x$$(echo "$(TAG)" | $(SED) 's/^[0-9]\{1,\}\.[0-9]\{1,\}//')" = "x" || { \ - echo "TAG=$(TAG) is not in numerical 'x.y' format."; \ + @test "x$$(echo "$(VER)" | $(SED) 's/^[0-9]\{1,\}\.[0-9]\{1,\}//')" = "x" || { \ + echo "VER=$(VER) is not in numerical 'x.y' format."; \ exit 4; } - @test "x$$($(SED) '1q' '$(top_srcdir)/NEWS')" = "x$(PACKAGE_TARNAME) $(TAG)" || { \ - echo "NEWS does not start with entry for '$(PACKAGE_TARNAME) $(TAG)'"; \ + @test "x$$($(SED) '1q' '$(top_srcdir)/NEWS')" = "x$(PACKAGE_TARNAME) $(VER)" || { \ + echo "NEWS does not start with entry for '$(PACKAGE_TARNAME) $(VER)'"; \ exit 5; } @$(SED) -n '1p; 2,/^$(PACKAGE_TARNAME) / p' '$(top_srcdir)/NEWS' \ | $(SED) '$$ { /^$(PACKAGE_TARNAME) / d }' | $(SED) '$$ { /^$$/d }' \ @@ -72,10 +73,10 @@ tag: @echo "=======================================================================" @cat TAG-MESSAGE @echo "=======================================================================" - @echo "Do you really want to tag this as release 'v$(TAG)'? Enter to continue, Ctrl-C to abort." + @echo "Do you really want to tag this as release '$(PACKAGE_TARNAME)-$(VER)'? Enter to continue, Ctrl-C to abort." @read msgfile="$$PWD/TAG-MESSAGE"; \ - cd "$(top_srcdir)" && $(GIT) tag -s -F "$$msgfile" "v$(TAG)"; \ + cd "$(top_srcdir)" && $(GIT) tag -s -F "$$msgfile" "$(PACKAGE_TARNAME)-$(VER)"; \ rm -f "$$msgfile" endif @@ -1,2 +1,6 @@ +nbb 0.2 + * Switch to release tags including the package name + * Make automake's "nbb make" depend on configure etc. + nbb 0.1 * Initial public standalone version of nbb. @@ -2,56 +2,70 @@ Release Plans: ======================================================================== -nbb-0.1 + +Items starting with "*" have been finished, while those marked with "-" +still need to be done. + + +nbb-0.1 (done) * Start new git repo (get rid of ndim-git-utils history). * Clean up git tags. -nbb-0.5 - * Write docs: man page equivalent, README, NEWS, HACKING. -nbb-1.0 - * Make public release. +nbb-0.2 + * Make sure the "if cmp ... mv .. rm" in make rules are correct and useful, + and the cmp is silent. + * Make automake's "nbb make" depend on configure etc. + * Switch to release tags including the package name -======================================================================== -TODO (some time): -======================================================================== - * Separate generic plugin/command/etc. stuff and nbb specific - code into separate modules. - * Switch plugins.Foo.validate() functions to different protocol: +nbb-0.3 + - License review. Every source file needs a license. Trace back origin + of all code. + - Useful logging infrastructure, and --debug etc user interface. + - Store config in ${srcdir}/.nbb.conf instead of 'git config'. + More portable. bzr does not have a config interface, for example. + + +nbb-0.9 or earlier + - Switch plugins.Foo.validate() functions to different protocol: Either return or raise an exception. - * Use different exceptions for plugins signalling detection failure + - Use different exceptions for plugins signalling detection failure to detect() and detect() to signal "no matching plugin detected" to detect()'s caller. - * BS support: cmake, scons, ... - * VCS support: SVN, darcs, hg, ... - * Out-of-source builds for systems which require in-source-tree builds: + - BS support: cmake, scons, python setuptools ... + - VCS support: SVN, darcs, hg, ... + - Out-of-source builds for systems which require in-source-tree builds: "cp -rl foo.src foo.build"? - * General removal of redundancy in Python code. - * Useful logging infrastructure, and --debug etc user interface. - * Make sure the "if cmp ... mv .. rm" in make rules are correct and useful. - * More declarative syntax elements in the Python code. - * Use declarations for command line parsing, and help text generation. + - General removal of redundancy in Python code. + - More declarative syntax elements in the Python code. + - Use declarations for command line parsing, and help text generation. Use optparse stuff for both global params and extra optparse stuff for each command? - * Add global --nick or similar option to determine the branch + - Add global --nick or similar option to determine the branch name to use for composing the pathes. - * Store config in ${srcdir}/.nbb.conf instead of 'git config'? - More portable. bzr does not have a config interface, for example. - * Model different "stages" of e.g. automake builds as distinct objects, + - Model different "stages" of e.g. automake builds as distinct objects, including proper dependency detectors, and stuff? OK, we're not going to duplicate scons here. - * Bash syntax completion - * Man page or something similar. Generate from help texts? - * Command aliases: + - Bash syntax completion, ideally autogenerated + - Docs: + - Write docs: README, NEWS, HACKING. + - Man page or something similar. Generate from help texts? + - Command aliases: make -> build (for automake, or similar mapping) - * Make automake's make depend on configure etc. - * Test sh command like run command. + - Test sh command like run command. + + +nbb-1.0 + - Make public release. + ======================================================================== -DONE: +DONE (some time in the past) ======================================================================== + * Separate generic plugin/command/etc. stuff and nbb specific + code into separate modules. * Implement sh and run commands. * supports execution of user commands in source, build, install dirs * Do not move command objects to plugin detection framework (bad idea!) @@ -80,6 +94,7 @@ DONE: gained with git-amb, especially the command interdependencies. (Nothing to do! :) + ======================================================================== End of TODO file. ======================================================================== diff --git a/build-helpers/package-version b/build-helpers/package-version index 61a3018..f81bcd4 100755 --- a/build-helpers/package-version +++ b/build-helpers/package-version @@ -21,7 +21,8 @@ if test -f "$top_srcdir/$version_stamp"; then # dist source tree cat "$top_srcdir/$version_stamp" | ${TR-tr} -d '\012' elif test -d "$GIT_DIR"; then # git source tree git_describe=`${GIT-git} describe 2>/dev/null || echo devel` - echo "$git_describe" | ${SED-sed} 's/^v//;s/-/./;s/-g/-/' | ${TR-tr} -d '\012' + # change tags like "foo-conf-1.2" to "1.2" + echo "$git_describe" | ${SED-sed} 's/^\([A-Za-z0-9_-]\{1,\}\)-\([0-9]\)/\2/;s/-/./;s/-g/-/' | ${TR-tr} -d '\012' else # ??? echo "devel" | ${TR-tr} -d '\012' fi diff --git a/doc/.htaccess b/doc/.htaccess deleted file mode 100644 index 5558f6e..0000000 --- a/doc/.htaccess +++ /dev/null @@ -1,15 +0,0 @@ -AddDescription "MIT LICENSE" LICENSE.MIT -AddDescription "GNU GENERAL PUBLIC LICENSE" LICENSE.GPL -AddDescription "General description of ndim-git-utils" README -AddDescription "Common code to several scripts" git-ndim-sh -AddDescription "The git-amb(1) man page" git-amb.txt -AddDescription "The git-amb script" git-amb -AddDescription "The git-rebase-subtree(1) man page" git-rebase-subtree.txt -AddDescription "The git-rebase-subtree script" git-rebase-subtree -AddDescription "The git-buildmsg(1) man page" git-buildmsg.txt -AddDescription "The git-buildmsg script" git-buildmsg -AddDescription "ndim's git cheatsheet" ndim-git-cheatsheet.txt -AddDescription "source tarball distribution" ndim-git-utils-*.tar.bz2 -ReadmeName FOOTER.html -HeaderName HEADER.html -IndexIgnore FOOTER.html HEADER.html .. diff --git a/src/Makefile-files b/src/Makefile-files index ba4cb50..490ff31 100644 --- a/src/Makefile-files +++ b/src/Makefile-files @@ -14,6 +14,17 @@ nbblib_PYTHON += src/nbblib/plugins.py nbblib_PYTHON += src/nbblib/progutils.py nbblib_PYTHON += src/nbblib/vcs.py +lint: lint-local + +lint-local: lint-local-pylint +lint-local: lint-local-pychecker + +lint-local-pylint: + cd src && pylint --zope=y --acquired-members=name,plugins nbb nbblib + +lint-local-pychecker: + cd src && pychecker --limit=500 $$(for f in nbblib/*.py; do echo nbblib.$$(basename "$$f" .py); done) + # Put all python source files, whether changed or verbatim, # into builddir, such that we can run tests in builddir. ALL_LOCAL += all-local-nbblib @@ -54,7 +65,7 @@ all-local-nbblib-pydoc: all-local-nbblib if test "$$rebuild" = "yes"; then \ echo $(PYDOC) -w "$${mod}"; \ ( cd src && $(PYDOC) -w "$${mod}" ); \ - if test -f "$$htmlfile" && cmp "src/$${mod}.html" "$$htmlfile"; \ + if test -f "$$htmlfile" && cmp "src/$${mod}.html" "$$htmlfile" > /dev/null; \ then rm -f "src/$${mod}.html"; \ else echo "INFO: Updating pydoc/$${mod}.html"; \ mv -f "src/$${mod}.html" "$$htmlfile"; fi; \ @@ -88,7 +99,7 @@ src/nbb: src/nbb.in $(nodist_nbblib_PYTHON) $(nbblib_PYTHON) Makefile $(GREP) '@[a-zA-Z0-9_]\{1,\}@' src/nbb.new; \ exit 1; \ fi - @if test -f src/nbb && cmp src/nbb.new src/nbb; \ + @if test -f src/nbb && cmp src/nbb.new src/nbb > /dev/null; \ then rm -f src/nbb.new; \ else mv -f src/nbb.new src/nbb; echo "INFO: Updating src/nbb"; fi @chmod +x src/nbb @@ -10,7 +10,7 @@ import sys import os PACKAGE_VERSION = "@PACKAGE_VERSION@" -if sys.version_info < (2,4): +if sys.version_info < (2, 4): print "Fatal: This program requires Python 2.4 or later." sys.exit(3) @@ -18,6 +18,7 @@ import logging # since python 2.3 def logmain(argv): + """set up logging module""" # funcName: Since python 2.5 # format="%(filename)s:%(lineno)d:%(funcName)s:" logformat = "%(levelname)s: %(message)s" @@ -28,7 +29,7 @@ def logmain(argv): del argv[i] loglevel = logging.DEBUG elif argv[i] in ('--info', ): - del argv[i] + del argv[i] loglevel = logging.INFO else: i += 1 @@ -43,6 +44,7 @@ def logmain(argv): def nbbmain(argv): + """nbb main program""" logmain(argv) pkgpythondir = "@pkgpythondir@" lib_found = False @@ -58,15 +60,15 @@ def nbbmain(argv): sys.path = path try: import nbblib - logging.debug("nbb.PACKAGE_VERSION %s, nbblib.PACKAGE_VERSION %s", + logging.debug("PACKAGE_VERSION from nbb: %s, from nbblib: %s", PACKAGE_VERSION, nbblib.PACKAGE_VERSION) assert(nbblib.PACKAGE_VERSION == PACKAGE_VERSION) lib_found = True break - except AssertionError, e: + except AssertionError: logging.debug("Assertion error", exc_info=True) sys.path = orig_path - except ImportError, e: + except ImportError: logging.debug("Import error", exc_info=True) sys.path = orig_path if not lib_found: diff --git a/src/nbblib/__init__.py b/src/nbblib/__init__.py index 2e2118a..e29a3b8 100644 --- a/src/nbblib/__init__.py +++ b/src/nbblib/__init__.py @@ -1,3 +1,9 @@ +"""Convenience package for nbb + +How exactly to cleanly import the modules in the future is still unclear, +so we'll just keep it as is for now. +""" + import nbblib.bs as bs import nbblib.commands as commands import nbblib.nbbcommands as nbbcommands diff --git a/src/nbblib/bs.py b/src/nbblib/bs.py index f9215a2..44e901a 100644 --- a/src/nbblib/bs.py +++ b/src/nbblib/bs.py @@ -1,6 +1,6 @@ -######################################################################## -# Buildsystem Source Tree plugins -######################################################################## +"""\ +Buildsystem Source Tree plugins +""" import os @@ -54,7 +54,8 @@ class BSSourceTree(plugins.GenericDetectPlugin): return super(BSSourceTree, cls).detect(context, vcs_tree) - def get_tree_root(self): return self._get_tree_root() + def get_tree_root(self): + return self._get_tree_root() tree_root = property(get_tree_root) @@ -64,15 +65,24 @@ class BSSourceTree(plugins.GenericDetectPlugin): # Abstract methods @plugins.abstractmethod - def _get_tree_root(self): pass + def _get_tree_root(self): + pass + @plugins.abstractmethod - def init(self): pass + def init(self): + pass + @plugins.abstractmethod - def configure(self): pass + def configure(self): + pass + @plugins.abstractmethod - def build(self): pass + def build(self): + pass + @plugins.abstractmethod - def install(self): pass + def install(self): + pass class AutomakeSourceTree(BSSourceTree): @@ -84,10 +94,10 @@ class AutomakeSourceTree(BSSourceTree): srcdir = vcs_tree.tree_root self.config = vcs_tree.config flag = False - for f in [ os.path.join(srcdir, 'configure.ac'), - os.path.join(srcdir, 'configure.in'), - ]: - if os.path.exists(f): + for fname in [ os.path.join(srcdir, 'configure.ac'), + os.path.join(srcdir, 'configure.in'), + ]: + if os.path.exists(fname): flag = True break if not flag: @@ -106,20 +116,25 @@ class AutomakeSourceTree(BSSourceTree): if not os.path.exists(os.path.join(self.config.srcdir, 'configure')): self.init() builddir = self.config.builddir - if not os.path.exists(builddir): os.makedirs(builddir) + if not os.path.exists(builddir): + os.makedirs(builddir) os.chdir(builddir) progutils.prog_run(["%s/configure" % self.config.srcdir, "--prefix=%s" % self.config.installdir, "--enable-maintainer-mode", ], self.context) - def build(self): + def make(self, *make_args): """'make'""" builddir = self.config.builddir if not os.path.exists(os.path.join(builddir, 'config.status')): self.configure() os.chdir(builddir) - progutils.prog_run(["make", ], self.context) + progutils.prog_run(["make"] + list(make_args), self.context) + + def build(self): + """'make'""" + self.make() def install(self): """'make install'""" @@ -140,9 +155,9 @@ class SconsSourceTree(BSSourceTree): srcdir = vcs_tree.tree_root self.config = vcs_tree.config flag = False - for f in [ os.path.join(srcdir, 'SConstruct'), - ]: - if os.path.exists(f): + for fname in [ os.path.join(srcdir, 'SConstruct'), + ]: + if os.path.exists(fname): flag = True break if not flag: @@ -152,8 +167,11 @@ class SconsSourceTree(BSSourceTree): def _get_tree_root(self): return self.__tree_root - def init(self): pass - def configure(self): pass + def init(self): + pass + + def configure(self): + pass def build(self): progutils.prog_run(["scons"], diff --git a/src/nbblib/commands.py b/src/nbblib/commands.py index 2c7cfdf..2a02a83 100644 --- a/src/nbblib/commands.py +++ b/src/nbblib/commands.py @@ -104,11 +104,12 @@ class Command(object): return True def __str__(self): - return "Command(%s, %s)" % (self.cmd_name, self.cmdargs) + return "Command(%s, %s)" % (self.name, self.cmdargs) __all__.append('Commander') class Commander(object): + """Represent cmdline command (parse args, find and run the command)""" def __init__(self, context, cmd, *cmdargs): self.context = context diff --git a/src/nbblib/main.py b/src/nbblib/main.py index fe4b304..524936f 100644 --- a/src/nbblib/main.py +++ b/src/nbblib/main.py @@ -7,13 +7,13 @@ nbb (ndim's branch builder) %(PACKAGE_VERSION)s Build, install given branch of source code into a branch specific place Copyright (C) 2007, 2008 Hans Ulrich Niedermann <hun@n-dimensional.de> -TBA: License conditions +TODO: License conditions Usage: %(prog)s [general options] <command> [command specific options] Features: * supports git branches - * supports bzr branches (requires useful branch nick, TBD: bzr config ?) + * supports bzr branches (requires useful branch nick, TODO: bzr config ?) * does out-of-source-tree builds (in-source-tree-builds unsupported) * direct support for automake/autoconf based build systems @@ -40,7 +40,7 @@ Command line interface (implemeted): $ %(prog)s [general options] run [--builddir] <command> [<param>...] $ %(prog)s [general options] run --installdir <command> [<param>...] -TBD: Command line interface: +TODO: Command line interface: Run cleanup commands: $ %(prog)s [general options] purge [command specific options] @@ -49,7 +49,7 @@ TBD: Command line interface: --installdir-only $ %(prog)s [general options] purge-all # either this $ %(prog)s [general options] purge --all # or that - TBD: 'make clean', 'make distclean' and similar stuff? + TODO: 'make clean', 'make distclean' and similar stuff? Global options: @@ -76,19 +76,23 @@ from nbblib import progutils def print_version(context): + """print nbb version""" print "%(prog)s (ndim's branch builder) %(PACKAGE_VERSION)s" % context def print_help(context): + """print general nbb help text""" print __doc__ % context, class PropertySetAgainError(Exception): + """To be raised in case of setting a property for the second time""" def __str__(self): return "Property cannot be set more than once" class InvalidPropertyValue(Exception): + """To be raised when the value assigned to a property is invalid""" def __init__(self, value): super(InvalidPropertyValue, self).__init__() self.value = value @@ -97,6 +101,7 @@ class InvalidPropertyValue(Exception): class Property(object): + """Context property base class for command line context""" def __init__(self, *args, **kwargs): assert(len(args) == 0) if 'default' in kwargs: @@ -123,7 +128,8 @@ class Property(object): setattr(instance, self.name, self.convert(value)) def __str__(self): if hasattr(self, 'default'): - return '<property %s defaulting to %s>' % (self.__class__.__name, self.default) + return '<property %s defaulting to %s>' \ + % (self.__class__.__name__, self.default) else: return '<property %s>' % (self.__class__.__name__) def isvalid(self, value): @@ -187,10 +193,9 @@ class Context(object): def __str__(self): kk = [x for x in dir(self) if (x.find('__') < 0) and (x.find('--') < 0)] kk.sort() - lll = ( (k, getattr(self,k)) for k in kk ) - return "%s(%s)" % (self.__class__.__name__, - ", ".join(("%s=%s" % (a,repr(c)) - for a,c in lll))) + lll = ( (k, getattr(self, k)) for k in kk ) + it = ( "%s=%s" % (a, repr(c)) for a, c in lll ) + return "%s(%s)" % (self.__class__.__name__, ", ".join(it)) def main(argv): @@ -205,7 +210,7 @@ def main(argv): "%(prog)s requires some arguments" % context) i = 1 - while i<len(argv): + while i < len(argv): if argv[i][0] != '-': break elif argv[i] in ('-h', '--help'): @@ -218,13 +223,13 @@ def main(argv): context.dry_run = True elif argv[i] in ('-b', '--build-system'): i = i + 1 - assert(i<len(argv)) + assert(i < len(argv)) context.bs = argv[i] elif argv[i][:15] == '--build-system=': context.bs = argv[i][6:] elif argv[i] in ('-v', '--vcs'): i = i + 1 - assert(i<len(argv)) + assert(i < len(argv)) context.vcs = argv[i] elif argv[i][:6] == '--vcs=': context.vcs = argv[i][6:] diff --git a/src/nbblib/nbbcommands.py b/src/nbblib/nbbcommands.py index 3b57fa9..79025de 100644 --- a/src/nbblib/nbbcommands.py +++ b/src/nbblib/nbbcommands.py @@ -3,25 +3,27 @@ nbblib.nbbcommands - implementation of nbb commands Copyright (C) 2008 Hans Ulrich Niedermann <hun@n-dimensional.de> """ -import sys import os import logging -import nbblib.package as package import nbblib.progutils as progutils import nbblib.vcs as vcs import nbblib.bs as bs -from nbblib.commands import * + + +from nbblib.commands import Command, CommandLineError def adjust_doc(doc): """Remove common whitespace at beginning of doc string lines""" - if not doc: return doc + if not doc: + return doc i = 0 - for i in range(len(doc)): + while i < len(doc): if doc[i] not in " \t": break + i += 1 prefix = doc[:i] rest_doc = doc[i:] almost_doc = rest_doc.replace("\n%s" % prefix, "\n") @@ -42,24 +44,26 @@ class HelpCommand(Command): usage = '[<command>]' def validate_args(self, *args, **kwargs): + """Accept zero args or one arg, a command name""" if len(args) == 1 and args[0] not in Command.plugins.keys(): raise CommandLineError("'%s' is an invalid command name" % args[0]) elif len(args) > 1: raise CommandLineError("'%s' command only takes one optional parameter" % self.name) def _print_command_list(self): + """Print list of commands (no help arg given)""" print "List of commands:" keys = Command.plugins.keys() if not keys: raise Exception("No commands found. Please lart the developer.") keys.sort() keys2 = Command.plugins.keys() - keys2.sort(lambda a,b: cmp(len(b),len(a))) - print "keys ", keys - print "keys2", keys2 + keys2.sort(lambda a, b: cmp(len(b), len(a))) + print "keys ", keys + print "keys2", keys2 fmt = "\t%%-%ds\t%%s" % len(keys2[0]) for k in keys: - print fmt % (k, Command.plugins[k].summary) + print fmt % (k, Command.plugins[k].summary) def _print_command_help(self, cmd): """print help for command cmd""" @@ -75,6 +79,7 @@ class HelpCommand(Command): print adjust_doc(c.__doc__) def run(self): + """Branch to the real commands""" if len(self.args) == 0: self._print_command_list() elif len(self.args) == 1: @@ -88,6 +93,7 @@ class InternalConfigCommand(Command): summary = 'print internal program configuration' validate_args = Command.validate_args_none def run(self): + """Just print info, do nothing else""" print "Source tree types:", ", ".join(vcs.VCSourceTree.plugins.keys()) print "Build system types:", ", ".join(bs.BSSourceTree.plugins.keys()) print "Commands:", ", ".join(Command.plugins.keys()) @@ -110,8 +116,8 @@ class SourceClassCommand(Command): logging.debug("bs_sourcetree %s", self.bs_sourcetree) cfg = self.vcs_sourcetree.config - for x in ('srcdir', 'builddir', 'installdir'): - logging.info("CONFIG %s %s", x, getattr(cfg, x)) + for dir_kind in ('srcdir', 'builddir', 'installdir'): + logging.info("CONFIG %s %s", dir_kind, getattr(cfg, dir_kind)) class DetectCommand(Command): @@ -204,9 +210,12 @@ class MakeCommand(SourceClassCommand): summary = 'run make in builddir' validate_args = Command.validate_args_any def run(self): - os.chdir(self.bs_sourcetree.config.builddir) - progutils.prog_run(["make"] + list(self.args), - self.context) + if hasattr(self.bs_sourcetree, 'make'): + self.bs_sourcetree.make(*self.args) + else: + os.chdir(self.bs_sourcetree.config.builddir) + progutils.prog_run(["make"] + list(self.args), + self.context) class GeneralRunCommand(SourceClassCommand): @@ -250,10 +259,10 @@ class GeneralShellCommand(GeneralRunCommand): def get_shell_prompt(self): return r",--[Ctrl-d or 'exit' to quit this %s shell for branch '%s']--\n| <%s %s> %s\n\`--[\u@\h \W]\$ " \ % (self.context.prog, self.vcs_sourcetree.branch_name, - self.context.prog, self.name, self.get_run_in_dir(), ) + self.context.prog, self.name, self.rundir, ) def run(self): self.chdir() - # FIXME: Allow using $SHELL or similar. + # TODO: Allow using $SHELL or similar. progutils.prog_run(['sh'] + list(self.args), self.context, env_update = {'PS1': self.get_shell_prompt()}) @@ -306,7 +315,7 @@ class ConfigCommand(SourceClassCommand): print getattr(self.vcs_sourcetree.config, self.args[0]) else: assert(False) - elif len(self.args) == 2: + elif len(self.args) == 2 and self.args[0] in git_set_items: if self.args[0] == 'builddir': self.vcs_sourcetree.config.builddir = self.args[1] elif self.args[0] == 'installdir': diff --git a/src/nbblib/plugins.py b/src/nbblib/plugins.py index a21e2d4..d4b753a 100644 --- a/src/nbblib/plugins.py +++ b/src/nbblib/plugins.py @@ -55,13 +55,16 @@ class MyPluginB(MyPluginType): if not other_detection_successful: raise self.no_match_exception() -Ideas: - * Get rid of references to 'context', and handle that in derived classes. - Bad idea, as any serious plugin using program will have the plugins - operating in some kind of context. """ +# TODO: Check plugin instances for defined members. +# 1. class AbstractMember(...): __get__, __set__ +# 2. class ConcreteMember(...): __get__, __set__ +# 3. plugin registration checks presence of AbstractMember instances, +# and fails if one is found + + import logging import functools import inspect @@ -107,6 +110,7 @@ __all__.append('AmbigousPluginDetection') class AmbigousPluginDetection(Exception): """Raised when more than one registered plugin matches the given args""" def __init__(self, matches, cls, context, *args, **kwargs): + super(AmbigousPluginDetection, self).__init__() self.matches = matches self.cls = cls self.context = context @@ -130,10 +134,11 @@ class AbstractMethodsInConcreteClass(Exception): implemented if this class is not abstract itself. """ def __init__(self, cls, methods): + super(AbstractMethodsInConcreteClass, self).__init__() self.cls = cls self.methods = methods def __str__(self): - methods = " ".join((k for k,v in self.methods)) + methods = " ".join((key for key, value in self.methods)) return "Class %s.%s must implement the %s abstract methods." \ % (self.cls.__module__, self.cls.__name__, @@ -144,10 +149,11 @@ __all__.append('AbstractMethodError') class AbstractMethodError(Exception): """Raised when an abstract method is called""" def __init__(self, name, module): + super(AbstractMethodError, self).__init__() self.name = name self.module = module def __str__(self): - # FIXME: Class name? + # FIXME: How to print class name alongside module and method name? return "Abstract method %s called someplace in %s" \ % (repr(self.name), repr(self.module)) @@ -167,12 +173,12 @@ def abstractmethod(fun): before the actual program is run! """ @functools.wraps(fun) - def f(self, *args, **kwargs): + def wrapper(self, *args, **kwargs): # fun(self, *args, **kwargs) raise AbstractMethodError(name=fun.__name__, module=fun.__module__) - f.abstract_method = True - return f + wrapper.abstract_method = True + return wrapper # Internal type __all__.append('PluginDict') @@ -216,26 +222,27 @@ class GenericPluginMeta(type): You can add abstract subclasses of Plugin by giving them a __name__ = None, define an @abstractmethod method in that abstract subclass, and much more. """ - def __init__(cls, name, bases, attrs): - logging.debug("META_INIT %s %s %s %s", cls, name, bases, attrs) - if not hasattr(cls, 'plugins'): + def __init__(mcs, name, bases, attrs): + super(GenericPluginMeta, mcs).__init__() + logging.debug("META_INIT %s %s %s %s", mcs, name, bases, attrs) + if not hasattr(mcs, 'plugins'): # This branch only executes when processing the mount point itself. # So, since this is a new plugin type, not an implementation, this # class shouldn't be registered as a plugin. Instead, it sets up a # list where plugins can be registered later. - cls.plugins = PluginDict() - elif cls.name is not None: + mcs.plugins = PluginDict() + elif mcs.name is not None: # This must be a plugin implementation, which should be registered. # Simply appending it to the list is all that's needed to keep # track of it later. def abstract_method_filter(member): return hasattr(member, '__call__') \ and hasattr(member, 'abstract_method') - ams = inspect.getmembers(cls, abstract_method_filter) + ams = inspect.getmembers(mcs, abstract_method_filter) if ams: - raise AbstractMethodsInConcreteClass(cls, ams) - logging.debug("Registering %s with %s as %s", cls, cls.plugins, cls.name) - cls.plugins[cls.name] = cls + raise AbstractMethodsInConcreteClass(mcs, ams) + logging.debug("Registering %s with %s as %s", mcs, mcs.plugins, mcs.name) + mcs.plugins[mcs.name] = mcs else: # This must be an abstract subclass of plugins. pass @@ -310,7 +317,7 @@ class GenericDetectPlugin(object): logging.debug("KLASS %s validated", klass) matches[key] = t except PluginNoMatch: - pass + pass # ignore non-matching plugins logging.debug("Matches: %s", matches) if len(matches) > 1: raise cls.ambigous_match_exception(matches, diff --git a/src/nbblib/progutils.py b/src/nbblib/progutils.py index 0486d99..c4c632c 100644 --- a/src/nbblib/progutils.py +++ b/src/nbblib/progutils.py @@ -1,6 +1,6 @@ -######################################################################## -# Utility functions -######################################################################## +"""\ +Utility functions for running external programs +""" import os @@ -12,25 +12,26 @@ __all__ = ['prog_stdout', 'prog_retstd', 'ProgramRunError', 'prog_run'] def prog_stdout(call_list): """Run program and return stdout (similar to shell backticks)""" - p = subprocess.Popen(call_list, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - stdout, stderr = p.communicate(input=None) + proc = subprocess.Popen(call_list, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + stdout, stderr = proc.communicate(input=None) return stdout.strip() def prog_retstd(call_list): """Run program and return stdout (similar to shell backticks)""" - p = subprocess.Popen(call_list, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - stdout, stderr = p.communicate(input=None) - return (p.returncode, stdout.strip(), stderr.strip()) + proc = subprocess.Popen(call_list, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + stdout, stderr = proc.communicate(input=None) + return (proc.returncode, stdout.strip(), stderr.strip()) class ProgramRunError(Exception): """A program run returns a retcode != 0""" def __init__(self, call_list, retcode, cwd=None): + super(ProgramRunError, self).__init__() self.call_list = call_list self.retcode = retcode if cwd: @@ -54,9 +55,9 @@ def prog_run(call_list, context=None, env=None, env_update=None): env = os.environ.copy() if env_update: env.update(env_update) - p = subprocess.Popen(call_list, env=env) - stdout, stderr = p.communicate(input=None) - if p.returncode != 0: - raise ProgramRunError(call_list, p.returncode, os.getcwd()) - return p.returncode + proc = subprocess.Popen(call_list, env=env) + stdout, stderr = proc.communicate(input=None) + if proc.returncode != 0: + raise ProgramRunError(call_list, proc.returncode, os.getcwd()) + return proc.returncode diff --git a/src/nbblib/vcs.py b/src/nbblib/vcs.py index a78663f..336f9c9 100644 --- a/src/nbblib/vcs.py +++ b/src/nbblib/vcs.py @@ -1,3 +1,8 @@ +"""\ +VCS Source Tree plugin system +""" + + import os import logging import urlparse @@ -32,10 +37,6 @@ class AbstractConfig(object): installdir = property(get_installdir) -######################################################################## -# VCS Source Tree plugin system -######################################################################## - class NotAVCSourceTree(plugins.PluginNoMatch): def __init__(self, srcdir): super(NotAVCSourceTree, self).__init__() @@ -151,7 +152,7 @@ class GitSourceTree(VCSourceTree): def _get_branch_name(self): bname = progutils.prog_stdout(["git", "symbolic-ref", "HEAD"]) - refs,heads,branch = bname.split('/') + refs, heads, branch = bname.split('/') assert(refs=='refs' and heads=='heads') return branch @@ -162,14 +163,16 @@ class GitConfig(AbstractConfig): def __init__(self, *args, **kwargs): super(GitConfig, self).__init__(*args, **kwargs) - def _itemname(self, item): return '.'.join((package.GIT_CONFIG_PREFIX, item, )) + def _itemname(self, item): + return '.'.join((package.GIT_CONFIG_PREFIX, item, )) + def _myreldir(self, rdir): return os.path.join(self._srcdir, rdir, self._nick) def get_builddir(self): ret, stdout, stderr = progutils.prog_retstd(['git', 'config', self._itemname('builddir')]) assert(stderr == "") - if ret == 0 and stdout: + if ret == 0 and stdout: return self._myreldir(stdout) else: return super(GitConfig, self).get_builddir() @@ -183,7 +186,7 @@ class GitConfig(AbstractConfig): def get_installdir(self): ret, stdout, stderr = progutils.prog_retstd(['git', 'config', self._itemname('installdir')]) assert(stderr == "") - if ret == 0 and stdout: + if ret == 0 and stdout: return self._myreldir(stdout) else: return super(GitConfig, self).get_installdir() @@ -205,7 +208,7 @@ class BzrSourceTree(VCSourceTree): import bzrlib.errors import bzrlib.workingtree try: - wt,b = bzrlib.workingtree.WorkingTree.open_containing(srcdir) + wt, b = bzrlib.workingtree.WorkingTree.open_containing(srcdir) except bzrlib.errors.NotBranchError: logging.debug("Not a bzr branch: %s", repr(srcdir)) raise self.no_match_exception(srcdir) @@ -223,7 +226,7 @@ class BzrSourceTree(VCSourceTree): #print "wt.branch.basis_tree:", wt.branch.basis_tree() def _get_tree_root(self): - proto,host,path,some,thing = urlparse.urlsplit(self.wt.branch.base) + proto, host, path, some, thing = urlparse.urlsplit(self.wt.branch.base) assert(proto == "file" and host == "") assert(some == "" and thing == "") return os.path.abspath(path) diff --git a/test/Makefile.am b/test/Makefile.am index acb26d8..3a87f6b 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -87,7 +87,7 @@ $(srcdir)/testsuite.at: $(TESTCASES) Makefile.in done; \ } > testsuite.at.new @if test -f $(srcdir)/testsuite.at \ - && cmp testsuite.at.new $(srcdir)/testsuite.at; \ + && cmp testsuite.at.new $(srcdir)/testsuite.at > /dev/null; \ then rm -f testsuite.at.new; \ else echo "INFO: Updating $(srcdir)/testsuite.at"; \ mv -f testsuite.at.new $(srcdir)/testsuite.at; fi @@ -99,7 +99,7 @@ $(srcdir)/$(TESTSUITE): testsuite.at local.at package.m4 $(TESTCASES) AUTOM4TE="$(AUTOM4TE)"; \ if test "x$${AUTOM4TE}" = "x"; then AUTOM4TE="autom4te"; fi; \ $${AUTOM4TE} --language=autotest -I '$(srcdir)' -o $(TESTSUITE).tmp $(srcdir)/testsuite.at - @if test -f $(srcdir)/$(TESTSUITE) && cmp $(TESTSUITE).tmp $(srcdir)/$(TESTSUITE); \ + @if test -f $(srcdir)/$(TESTSUITE) && cmp $(TESTSUITE).tmp $(srcdir)/$(TESTSUITE) > /dev/null; \ then rm -f $(TESTSUITE).tmp; \ else echo "INFO: Updating $(srcdir)/$(TESTSUITE)"; \ mv -f $(TESTSUITE).tmp $(srcdir)/$(TESTSUITE); fi diff --git a/test/local.at b/test/local.at index 0226c15..27e14de 100644 --- a/test/local.at +++ b/test/local.at @@ -36,10 +36,16 @@ $(if test "${NBB_SCRIPT-nbb}" = "nbb"; then echo "nbb"; else echo $PYTHON $NBB_S ])dnl +dnl AT_GIT_INIT_OUTPUT_CANONICAL +m4_define([AT_GIT_INIT_OUTPUT_CANONICAL], [dnl +sed 's|^Initialized empty Git repository in @<:@a-zA-Z0-9/\._-@:>@\{1,\}.git/$|Initialized empty Git repository in .git/|' dnl +])dnl + + dnl AT_WRAP_GIT([stuff-to-do-with-git-repo])dnl m4_define([AT_WRAP_GIT], [dnl AT_CHECK([mkdir test.dir && cd test.dir]) -AT_CHECK([cd test.dir && git init], [0], +AT_CHECK([cd test.dir && git init | AT_GIT_INIT_OUTPUT_CANONICAL], [0], [Initialized empty Git repository in .git/ ])dnl $1 diff --git a/test/nbb-automake.at b/test/nbb-automake.at index bf9218d..a6596ff 100644 --- a/test/nbb-automake.at +++ b/test/nbb-automake.at @@ -44,7 +44,7 @@ dnl =================================================================== AT_SETUP([nbb automake: make distcheck]) AT_KEYWORDS([nbb automake make distcheck]) -AT_WRAP_GIT_AM([dl +AT_WRAP_GIT_AM([dnl AT_CHECK([cd test.dir && AT_NBB configure], [0], [ignore], [ignore]) AT_CHECK([cd test.dir && AT_NBB make distcheck], [0], [ignore], [ignore]) ]) diff --git a/test/nbb-config.at b/test/nbb-config.at index 34608c9..cc44e44 100644 --- a/test/nbb-config.at +++ b/test/nbb-config.at @@ -8,7 +8,7 @@ dnl =================================================================== AT_SETUP([nbb config: git defaults]) AT_KEYWORDS([nbb git config]) AT_CHECK([mkdir test.git && cd test.git]) -AT_CHECK([cd test.git && git init], [0], +AT_CHECK([cd test.git && git init | AT_GIT_INIT_OUTPUT_CANONICAL], [0], [Initialized empty Git repository in .git/ ]) AT_DATA([test.git/configure.ac], [dnl @@ -29,7 +29,7 @@ dnl =================================================================== AT_SETUP([nbb config: git set/get]) AT_KEYWORDS([nbb git config]) AT_CHECK([mkdir test.git && cd test.git]) -AT_CHECK([cd test.git && git init], [0], +AT_CHECK([cd test.git && git init | AT_GIT_INIT_OUTPUT_CANONICAL], [0], [Initialized empty Git repository in .git/ ]) AT_DATA([test.git/configure.ac], [dnl diff --git a/test/nbb-detect.at b/test/nbb-detect.at index d5458f4..aa2bf59 100644 --- a/test/nbb-detect.at +++ b/test/nbb-detect.at @@ -18,7 +18,7 @@ dnl =================================================================== AT_SETUP([nbb detect-vcs: git detection ]) AT_KEYWORDS([nbb detect vcs git]) AT_CHECK([mkdir test.git && cd test.git]) -AT_CHECK([cd test.git && git init], [0], +AT_CHECK([cd test.git && git init | AT_GIT_INIT_OUTPUT_CANONICAL], [0], [Initialized empty Git repository in .git/ ]) AT_CHECK([echo "VCS: git $PWD/test.git" > expout @@ -43,7 +43,7 @@ AT_SETUP([nbb detect-vcs: bzr AND git ambigous repository]) AT_KEYWORDS([nbb detect vcs bzr git]) AT_CHECK([mkdir test.bzrgit && cd test.bzrgit]) AT_CHECK([cd test.bzrgit && bzr init && bzr nick testnick]) -AT_CHECK([cd test.bzrgit && git init], [0], +AT_CHECK([cd test.bzrgit && git init | AT_GIT_INIT_OUTPUT_CANONICAL], [0], [Initialized empty Git repository in .git/ ]) AT_CHECK([echo "ERROR: Ambigous VCS types detected for '$PWD/test.bzrgit': @@ -59,7 +59,7 @@ dnl =================================================================== AT_SETUP([nbb detect-bs: automake detection ]) AT_KEYWORDS([nbb detect bs automake]) AT_CHECK([mkdir test.git && cd test.git]) -AT_CHECK([cd test.git && git init], [0], +AT_CHECK([cd test.git && git init | AT_GIT_INIT_OUTPUT_CANONICAL], [0], [Initialized empty Git repository in .git/ ]) AT_DATA([test.git/configure.ac], [dnl @@ -76,7 +76,7 @@ dnl =================================================================== AT_SETUP([nbb detect-bs: scons detection]) AT_KEYWORDS([nbb detect bs scons]) AT_CHECK([mkdir test.git && cd test.git]) -AT_CHECK([cd test.git && git init], [0], +AT_CHECK([cd test.git && git init | AT_GIT_INIT_OUTPUT_CANONICAL], [0], [Initialized empty Git repository in .git/ ]) AT_DATA([test.git/SConstruct], [dnl @@ -92,7 +92,7 @@ dnl =================================================================== AT_SETUP([nbb detect-bs: automake AND scons detection ]) AT_KEYWORDS([nbb detect bs scons automake]) AT_CHECK([mkdir test.git && cd test.git]) -AT_CHECK([cd test.git && git init], [0], +AT_CHECK([cd test.git && git init | AT_GIT_INIT_OUTPUT_CANONICAL], [0], [Initialized empty Git repository in .git/ ]) AT_DATA([test.git/configure.ac], [dnl @@ -114,7 +114,7 @@ dnl =================================================================== AT_SETUP([nbb detect-bs: no BS detection]) AT_KEYWORDS([nbb detect bs]) AT_CHECK([mkdir test.git && cd test.git]) -AT_CHECK([cd test.git && git init], [0], +AT_CHECK([cd test.git && git init | AT_GIT_INIT_OUTPUT_CANONICAL], [0], [Initialized empty Git repository in .git/ ]) AT_CHECK([echo "ERROR: Unknown BS source tree type: '$PWD/test.git'" > experr |