diff options
author | Sylvain Thénault <sylvain.thenault@logilab.fr> | 2014-07-30 16:34:22 +0200 |
---|---|---|
committer | Sylvain Thénault <sylvain.thenault@logilab.fr> | 2014-07-30 16:34:22 +0200 |
commit | 175b1d482177b3cf76bb07768419c3a9a8850c7b (patch) | |
tree | 1063258fa76ca121c739df2bf0af2062102bc947 | |
parent | 3a055f094934977806c2c22ff440cebdd7f5df62 (diff) | |
parent | cf1a3bbc247e7bf26519190fb176a746f2fa067a (diff) | |
download | logilab-common-175b1d482177b3cf76bb07768419c3a9a8850c7b.tar.gz |
default was stable
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | __pkginfo__.py | 4 | ||||
-rw-r--r-- | configuration.py | 29 | ||||
-rw-r--r-- | dbf.py | 1 | ||||
-rw-r--r-- | debian/changelog | 6 | ||||
-rw-r--r-- | fileutils.py | 1 | ||||
-rw-r--r-- | graph.py | 2 | ||||
-rw-r--r-- | modutils.py | 3 | ||||
-rw-r--r-- | pytest.py | 27 | ||||
-rw-r--r-- | python-logilab-common.spec | 2 | ||||
-rw-r--r-- | shellutils.py | 6 | ||||
-rw-r--r-- | test/data/module.py | 1 | ||||
-rw-r--r-- | test/unittest_configuration.py | 45 | ||||
-rw-r--r-- | test/unittest_table.py | 1 | ||||
-rw-r--r-- | test/unittest_tree.py | 1 | ||||
-rw-r--r-- | test/unittest_ureports_html.py | 1 | ||||
-rw-r--r-- | test/unittest_ureports_text.py | 1 | ||||
-rw-r--r-- | test/utils.py | 1 | ||||
-rw-r--r-- | testlib.py | 10 |
19 files changed, 101 insertions, 54 deletions
@@ -1,6 +1,17 @@ ChangeLog for logilab.common ============================ +-- + * shellutils: restore py 2.5 compat by removing usage of class decorator + * pytest: drop broken --coverage option + * testlib: support for skipping whole test class and conditional skip, don't + run setUp for skipped tests + * configuration: load options in config file order (#185648) + +2014-03-07 -- 0.62.0 + * modutils: cleanup_sys_modules returns the list of cleaned modules + + 2014-02-11 -- 0.61.0 * pdf_ext: removed, it had no known users (CVE-2014-1838) @@ -20,7 +31,7 @@ ChangeLog for logilab.common * ensure file is closed, may cause pb depending on the interpreter, eg pypy) (#180876) - + * fix support for `extend_path` based nested namespace packages ; Report and patch by John Johnson (#177651) diff --git a/__pkginfo__.py b/__pkginfo__.py index d3be555..e1a4022 100644 --- a/__pkginfo__.py +++ b/__pkginfo__.py @@ -1,4 +1,4 @@ -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. +# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved. # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr # # This file is part of logilab-common. @@ -25,7 +25,7 @@ modname = 'common' subpackage_of = 'logilab' subpackage_master = True -numversion = (0, 61, 0) +numversion = (0, 62, 0) version = '.'.join([str(num) for num in numversion]) license = 'LGPL' # 2.1 or later diff --git a/configuration.py b/configuration.py index fa93a05..0b03e90 100644 --- a/configuration.py +++ b/configuration.py @@ -96,7 +96,15 @@ Quick start: simplest usage multiple=4,5,6 number=3 - >>> + + Note : starting with Python 2.7 ConfigParser is able to take into + account the order of occurrences of the options into a file (by + using an OrderedDict). If you have two options changing some common + state, like a 'disable-all-stuff' and a 'enable-some-stuff-a', their + order of appearance will be significant : the last specified in the + file wins. For earlier version of python and logilab.common newer + than 0.61 the behaviour is unspecified. + """ __docformat__ = "restructuredtext en" @@ -109,8 +117,7 @@ import sys import re from os.path import exists, expanduser from copy import copy -from ConfigParser import ConfigParser, NoOptionError, NoSectionError, \ - DuplicateSectionError +from ConfigParser import ConfigParser, NoOptionError, NoSectionError from warnings import warn from logilab.common.compat import callable, raw_input, str_encode as _encode @@ -394,7 +401,7 @@ def ini_format(stream, options, encoding): format_section = ini_format_section def rest_format_section(stream, section, options, encoding=None, doc=None): - """format an options section using the INI format""" + """format an options section using as ReST formatted output""" encoding = _get_encoding(encoding, stream) if section: print >> stream, '%s\n%s' % (section, "'"*len(section)) @@ -655,13 +662,13 @@ class OptionsManagerMixIn(object): options provider) """ parser = self.cfgfile_parser - for provider in self.options_providers: - for section, option, optdict in provider.all_options(): - try: - value = parser.get(section, option) - provider.set_option(option, value, optdict=optdict) - except (NoSectionError, NoOptionError), ex: - continue + for section in parser.sections(): + for option, value in parser.items(section): + try: + self.global_set_option(option, value) + except (KeyError, OptionError): + # TODO handle here undeclared options appearing in the config file + continue def load_configuration(self, **kwargs): """override configuration according to given parameters @@ -36,7 +36,6 @@ import os, os.path import sys import csv import tempfile -import ConfigParser class Dbase: def __init__(self): diff --git a/debian/changelog b/debian/changelog index 49b1834..f1cb5c6 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +logilab-common (0.62.0-1) unstable; urgency=low + + * new upstream release + + -- Aurelien Campeas <aurelien.campeas@logilab.fr> Thu, 03 Jul 2014 14:31:32 +0200 + logilab-common (0.61.0-1) unstable; urgency=low * new upstream release diff --git a/fileutils.py b/fileutils.py index 4ac9270..7a028b1 100644 --- a/fileutils.py +++ b/fileutils.py @@ -32,7 +32,6 @@ from os.path import isabs, isdir, islink, split, exists, normpath, join from os.path import abspath from os import sep, mkdir, remove, listdir, stat, chmod, walk from stat import ST_MODE, S_IWRITE -from cStringIO import StringIO from logilab.common import STD_BLACKLIST as BASE_BLACKLIST, IGNORED_EXTENSIONS from logilab.common.shellutils import find @@ -63,7 +63,7 @@ class DotBackend: assert charset.lower() in ('utf-8', 'iso-8859-1', 'latin1'), \ 'unsupported charset %s' % charset self.emit('charset="%s"' % charset) - for param in additionnal_param.iteritems(): + for param in sorted(additionnal_param.iteritems()): self.emit('='.join(param)) def get_source(self): diff --git a/modutils.py b/modutils.py index 2756841..d0cccf3 100644 --- a/modutils.py +++ b/modutils.py @@ -455,13 +455,16 @@ def get_source_file(filename, include_no_ext=False): def cleanup_sys_modules(directories): """remove submodules of `directories` from `sys.modules`""" + cleaned = [] for modname, module in sys.modules.items(): modfile = getattr(module, '__file__', None) if modfile: for directory in directories: if modfile.startswith(directory): + cleaned.append(modname) del sys.modules[modname] break + return cleaned def is_python_source(filename): @@ -105,9 +105,6 @@ pytest path/to/mytests.py -m '(not long and database) or regr' pytest one (will run both test_thisone and test_thatone) pytest path/to/mytests.py -s not (will skip test_notthisone) - -pytest --coverage test_foo.py - (only if logilab.devtools is available) """ ENABLE_DBC = False @@ -604,7 +601,7 @@ def make_parser(): action="callback", help="Verbose output") parser.add_option('-i', '--pdb', callback=rebuild_and_store, dest="pdb", action="callback", - help="Enable test failure inspection (conflicts with --coverage)") + help="Enable test failure inspection") parser.add_option('-x', '--exitfirst', callback=rebuild_and_store, dest="exitfirst", default=False, action="callback", help="Exit on first failure " @@ -631,14 +628,6 @@ def make_parser(): parser.add_option('-m', '--match', default=None, dest='tags_pattern', help="only execute test whose tag match the current pattern") - try: - from logilab.devtools.lib.coverage import Coverage - parser.add_option('--coverage', dest="coverage", default=False, - action="store_true", - help="run tests with pycoverage (conflicts with --pdb)") - except ImportError: - pass - if DJANGO_FOUND: parser.add_option('-J', '--django', dest='django', default=False, action="store_true", @@ -652,8 +641,6 @@ def parseargs(parser): """ # parse the command line options, args = parser.parse_args() - if options.pdb and getattr(options, 'coverage', False): - parser.error("'pdb' and 'coverage' options are exclusive") filenames = [arg for arg in args if arg.endswith('.py')] if filenames: if len(filenames) > 1: @@ -683,16 +670,9 @@ def run(): options, explicitfile = parseargs(parser) # mock a new command line sys.argv[1:] = parser.newargs - covermode = getattr(options, 'coverage', None) cvg = None if not '' in sys.path: sys.path.insert(0, '') - if covermode: - # control_import_coverage(rootdir) - from logilab.devtools.lib.coverage import Coverage - cvg = Coverage([rootdir]) - cvg.erase() - cvg.start() if DJANGO_FOUND and options.django: tester = DjangoTester(cvg, options) else: @@ -719,12 +699,7 @@ def run(): import traceback traceback.print_exc() finally: - if covermode: - cvg.stop() - cvg.save() tester.show_report() - if covermode: - print 'coverage information stored, use it with pycoverage -ra' sys.exit(tester.errcode) class SkipAwareTestProgram(unittest.TestProgram): diff --git a/python-logilab-common.spec b/python-logilab-common.spec index f63e49c..a5944fc 100644 --- a/python-logilab-common.spec +++ b/python-logilab-common.spec @@ -10,7 +10,7 @@ %{!?_python_sitelib: %define _python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")} Name: %{python}-logilab-common -Version: 0.61.0 +Version: 0.62.0 Release: logilab.1%{?dist} Summary: Common libraries for Logilab projects diff --git a/shellutils.py b/shellutils.py index 28c2b42..69ee1e4 100644 --- a/shellutils.py +++ b/shellutils.py @@ -1,4 +1,4 @@ -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. +# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved. # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr # # This file is part of logilab-common. @@ -226,7 +226,7 @@ def unzip(archive, destdir): outfile.write(zfobj.read(name)) outfile.close() -@deprecated('Use subprocess.Popen instead') + class Execute: """This is a deadlock safe version of popen2 (no stdin), that returns an object with errorlevel, out and err. @@ -237,6 +237,8 @@ class Execute: self.out, self.err = cmd.communicate() self.status = os.WEXITSTATUS(cmd.returncode) +Execute = deprecated('Use subprocess.Popen instead')(Execute) + def acquire_lock(lock_file, max_try=10, delay=10, max_delay=3600): """Acquire a lock represented by a file on the file system diff --git a/test/data/module.py b/test/data/module.py index 9b85430..4e1abce 100644 --- a/test/data/module.py +++ b/test/data/module.py @@ -2,7 +2,6 @@ """test module for astng """ -__revision__ = '$Id: module.py,v 1.9 2003-11-24 13:40:26 syt Exp $' from logilab.common import modutils, Execute as spawn from logilab.common.astutils import * diff --git a/test/unittest_configuration.py b/test/unittest_configuration.py index a8e3c0f..edcb5db 100644 --- a/test/unittest_configuration.py +++ b/test/unittest_configuration.py @@ -1,4 +1,4 @@ -# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. +# copyright 2003-2014 LOGILAB S.A. (Paris, FRANCE), all rights reserved. # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr # # This file is part of logilab-common. @@ -25,7 +25,7 @@ from sys import version_info from logilab.common.testlib import TestCase, unittest_main from logilab.common.optik_ext import OptionValueError -from logilab.common.configuration import Configuration, \ +from logilab.common.configuration import Configuration, OptionError, \ OptionsManagerMixIn, OptionsProviderMixIn, Method, read_old_config, \ merge_options @@ -47,6 +47,8 @@ OPTIONS = [('dothis', {'type':'yn', 'action': 'store', 'default': True, 'metavar ('diffgroup', {'type':'string', 'default':'pouet', 'metavar': '<key=val>', 'group': 'agroup'}), + ('reset-value', {'type': 'string', 'metavar': '<string>', 'short': 'r', + 'dest':'value'}), ] @@ -149,6 +151,38 @@ diffgroup=zou finally: os.remove(file) + def test_option_order(self): + """ Check that options are taken into account in the command line order + and not in the order they are defined in the Configuration object. + """ + file = tempfile.mktemp() + stream = open(file, 'w') + try: + stream.write("""[Test] +reset-value=toto +value=tata +""") + stream.close() + self.cfg.load_file_configuration(file) + finally: + os.remove(file) + self.assertEqual(self.cfg['value'], 'tata') + + def test_unsupported_options(self): + file = tempfile.mktemp() + stream = open(file, 'w') + try: + stream.write("""[Test] +whatever=toto +value=tata +""") + stream.close() + self.cfg.load_file_configuration(file) + finally: + os.remove(file) + self.assertEqual(self.cfg['value'], 'tata') + self.assertRaises(OptionError, self.cfg.__getitem__, 'whatever') + def test_generate_config(self): stream = StringIO() self.cfg.generate_config(stream) @@ -170,6 +204,8 @@ multiple-choice=yo,ye named=key:val +#reset-value= + [AGROUP] @@ -197,6 +233,8 @@ multiple-choice=yo,ye named=key:val +reset-value=' ' + [AGROUP] @@ -251,6 +289,7 @@ Options: --choice=<yo|ye> --multiple-choice=<yo|ye> --named=<key=val> + -r <string>, --reset-value=<string> Agroup: --diffgroup=<key=val> @@ -309,6 +348,8 @@ multiple-choice=yo,ye named=key:val +reset-value=' ' + [AGROUP] diff --git a/test/unittest_table.py b/test/unittest_table.py index d2db8b7..7c58d69 100644 --- a/test/unittest_table.py +++ b/test/unittest_table.py @@ -19,7 +19,6 @@ Unittests for table management """ -__revision__ = '$Id: unittest_table.py,v 1.13 2006-04-09 22:30:53 nico Exp $' import sys import os diff --git a/test/unittest_tree.py b/test/unittest_tree.py index 8e7f4bd..fb8e303 100644 --- a/test/unittest_tree.py +++ b/test/unittest_tree.py @@ -19,7 +19,6 @@ unit tests for module logilab.common.tree squeleton generated by /home/syt/bin/py2tests on Jan 20 at 10:43:25 """ -__revision__ = "$Id: unittest_tree.py,v 1.9 2005-09-07 23:44:02 nico Exp $" from logilab.common.testlib import TestCase, unittest_main from logilab.common.tree import * diff --git a/test/unittest_ureports_html.py b/test/unittest_ureports_html.py index c849c4f..2298eec 100644 --- a/test/unittest_ureports_html.py +++ b/test/unittest_ureports_html.py @@ -18,7 +18,6 @@ '''unit tests for ureports.html_writer ''' -__revision__ = "$Id: unittest_ureports_html.py,v 1.3 2005-05-27 12:27:08 syt Exp $" from utils import WriterTC from logilab.common.testlib import TestCase, unittest_main diff --git a/test/unittest_ureports_text.py b/test/unittest_ureports_text.py index 25a2194..dd39dd8 100644 --- a/test/unittest_ureports_text.py +++ b/test/unittest_ureports_text.py @@ -18,7 +18,6 @@ '''unit tests for ureports.text_writer ''' -__revision__ = "$Id: unittest_ureports_text.py,v 1.4 2005-05-27 12:27:08 syt Exp $" from utils import WriterTC from logilab.common.testlib import TestCase, unittest_main diff --git a/test/utils.py b/test/utils.py index 957d7eb..f54c179 100644 --- a/test/utils.py +++ b/test/utils.py @@ -18,7 +18,6 @@ '''unit tests utilities for ureports ''' -__revision__ = "$Id: utils.py,v 1.3 2005-05-27 12:27:08 syt Exp $" from cStringIO import StringIO from logilab.common.ureports.nodes import * @@ -579,6 +579,16 @@ class TestCase(unittest.TestCase): # if result.cvg: # result.cvg.start() testMethod = self._get_test_method() + if (getattr(self.__class__, "__unittest_skip__", False) or + getattr(testMethod, "__unittest_skip__", False)): + # If the class or method was skipped. + try: + skip_why = (getattr(self.__class__, '__unittest_skip_why__', '') + or getattr(testMethod, '__unittest_skip_why__', '')) + self._addSkip(result, skip_why) + finally: + result.stopTest(self) + return if runcondition and not runcondition(testMethod): return # test is skipped result.startTest(self) |