summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSylvain Thénault <sylvain.thenault@logilab.fr>2014-07-30 16:34:22 +0200
committerSylvain Thénault <sylvain.thenault@logilab.fr>2014-07-30 16:34:22 +0200
commit175b1d482177b3cf76bb07768419c3a9a8850c7b (patch)
tree1063258fa76ca121c739df2bf0af2062102bc947
parent3a055f094934977806c2c22ff440cebdd7f5df62 (diff)
parentcf1a3bbc247e7bf26519190fb176a746f2fa067a (diff)
downloadlogilab-common-175b1d482177b3cf76bb07768419c3a9a8850c7b.tar.gz
default was stable
-rw-r--r--ChangeLog13
-rw-r--r--__pkginfo__.py4
-rw-r--r--configuration.py29
-rw-r--r--dbf.py1
-rw-r--r--debian/changelog6
-rw-r--r--fileutils.py1
-rw-r--r--graph.py2
-rw-r--r--modutils.py3
-rw-r--r--pytest.py27
-rw-r--r--python-logilab-common.spec2
-rw-r--r--shellutils.py6
-rw-r--r--test/data/module.py1
-rw-r--r--test/unittest_configuration.py45
-rw-r--r--test/unittest_table.py1
-rw-r--r--test/unittest_tree.py1
-rw-r--r--test/unittest_ureports_html.py1
-rw-r--r--test/unittest_ureports_text.py1
-rw-r--r--test/utils.py1
-rw-r--r--testlib.py10
19 files changed, 101 insertions, 54 deletions
diff --git a/ChangeLog b/ChangeLog
index 1948de6..5406478 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/dbf.py b/dbf.py
index 8def2d2..3396383 100644
--- a/dbf.py
+++ b/dbf.py
@@ -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
diff --git a/graph.py b/graph.py
index d62e8c0..9a77495 100644
--- a/graph.py
+++ b/graph.py
@@ -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):
diff --git a/pytest.py b/pytest.py
index 2d6ccf9..8767938 100644
--- a/pytest.py
+++ b/pytest.py
@@ -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 *
diff --git a/testlib.py b/testlib.py
index 817149c..683c7ac 100644
--- a/testlib.py
+++ b/testlib.py
@@ -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)