From 4177db3d468dec0d363071f16e52da25b52be95b Mon Sep 17 00:00:00 2001 From: Sylvain Th?nault Date: Mon, 29 Apr 2013 15:59:45 +0200 Subject: [modutils] fix typo causing name error in python3 / bad message in python2. Closes #136037 --- ChangeLog | 5 +++++ modutils.py | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9e8337e..8ee6eac 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,11 @@ ChangeLog for logilab.common ============================ +-- + * modutils: fix typo causing name error in python3 / bad message in python2 + (#136037) + + 2013-04-16 -- 0.59.1 * graph: added pruning of the recursive search tree for detecting cycles in graphs (closes #2469) diff --git a/modutils.py b/modutils.py index 2cae005..c792847 100644 --- a/modutils.py +++ b/modutils.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved. +# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr # # This file is part of logilab-common. @@ -570,7 +570,7 @@ def _search_zip(modpath, pic): if importer.find_module(modpath[0]): if not importer.find_module('/'.join(modpath)): raise ImportError('No module named %s in %s/%s' % ( - '.'.join(modpath[1:]), file, modpath)) + '.'.join(modpath[1:]), filepath, modpath)) return ZIPFILE, abspath(filepath) + '/' + '/'.join(modpath), filepath raise ImportError('No module named %s' % '.'.join(modpath)) -- cgit v1.2.1 From f8e39f91ad757f79cd4f83d481fabf627699f78f Mon Sep 17 00:00:00 2001 From: Sylvain Th?nault Date: Mon, 29 Apr 2013 15:58:38 +0200 Subject: [registry] type.__new__ first arg is the metaclass, not the class --- registry.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/registry.py b/registry.py index 0dc7a21..7721d76 100644 --- a/registry.py +++ b/registry.py @@ -933,9 +933,9 @@ def wrap_predicates(decorator): predicate.__call__ = decorator(predicate.__call__) class PredicateMetaClass(type): - def __new__(cls, *args, **kwargs): + def __new__(mcs, *args, **kwargs): # use __new__ so subclasses doesn't have to call Predicate.__init__ - inst = type.__new__(cls, *args, **kwargs) + inst = type.__new__(mcs, *args, **kwargs) proxy = weakref.proxy(inst, lambda p: _PREDICATES.pop(id(p))) _PREDICATES[id(proxy)] = proxy return inst -- cgit v1.2.1 From 259fac24fdc0b990678be0748528b8b302e2058e Mon Sep 17 00:00:00 2001 From: Sylvain Th?nault Date: Tue, 7 May 2013 14:42:37 +0200 Subject: [modutils test] enhance some test names --- test/unittest_modutils.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/test/unittest_modutils.py b/test/unittest_modutils.py index 3e9a74a..dfbcf14 100644 --- a/test/unittest_modutils.py +++ b/test/unittest_modutils.py @@ -1,4 +1,4 @@ -# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved. +# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr # # This file is part of logilab-common. @@ -143,16 +143,16 @@ class file_from_modpath_tc(ModutilsTestCase): corresponding file, giving priority to source file over precompiled file if it exists""" - def test_knownValues_file_from_modpath_1(self): + def test_site_packages(self): self.assertEqual(path.realpath(modutils.file_from_modpath(['logilab', 'common', 'modutils'])), path.realpath(modutils.__file__.replace('.pyc', '.py'))) - def test_knownValues_file_from_modpath_2(self): + def test_std_lib(self): from os import path self.assertEqual(path.realpath(modutils.file_from_modpath(['os', 'path']).replace('.pyc', '.py')), path.realpath(path.__file__.replace('.pyc', '.py'))) - def test_knownValues_file_from_modpath_3(self): + def test_xmlplus(self): try: # don't fail if pyxml isn't installed from xml.dom import ext @@ -162,13 +162,15 @@ class file_from_modpath_tc(ModutilsTestCase): self.assertEqual(path.realpath(modutils.file_from_modpath(['xml', 'dom', 'ext']).replace('.pyc', '.py')), path.realpath(ext.__file__.replace('.pyc', '.py'))) - def test_knownValues_file_from_modpath_4(self): + def test_builtin(self): self.assertEqual(modutils.file_from_modpath(['sys']), None) - def test_raise_file_from_modpath_Exception(self): + + def test_unexisting(self): self.assertRaises(ImportError, modutils.file_from_modpath, ['turlututu']) + class get_source_file_tc(ModutilsTestCase): def test(self): -- cgit v1.2.1 From ef345bf9d8664d5addfd0ef627b1f6d569f311fb Mon Sep 17 00:00:00 2001 From: Sylvain Th?nault Date: Tue, 7 May 2013 14:46:28 +0200 Subject: [modutils]?fix python3.3 crash on file_from_modpath. Closes #137244 --- ChangeLog | 9 +++++++-- modutils.py | 11 ++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8ee6eac..b0c893e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,8 +2,13 @@ ChangeLog for logilab.common ============================ -- - * modutils: fix typo causing name error in python3 / bad message in python2 - (#136037) + * modutils: + + * fix typo causing name error in python3 / bad message in python2 + (#136037) + + * fix python3.3 crash in file_from_modpath due to implementation + change of imp.find_module wrt builtin modules (#137244) 2013-04-16 -- 0.59.1 diff --git a/modutils.py b/modutils.py index c792847..05f0602 100644 --- a/modutils.py +++ b/modutils.py @@ -606,6 +606,15 @@ def _module_file(modpath, path=None): checkeggs = False imported = [] while modpath: + # take care to changes in find_module implementation wrt builtin modules + # + # Python 2.6.6 (r266:84292, Sep 11 2012, 08:34:23) + # >>> imp.find_module('posix') + # (None, 'posix', ('', '', 6)) + # + # Python 3.3.1 (default, Apr 26 2013, 12:08:46) + # >>> imp.find_module('posix') + # (None, None, ('', '', 6)) try: _, mp_filename, mp_desc = find_module(modpath[0], path) except ImportError: @@ -613,7 +622,7 @@ def _module_file(modpath, path=None): return _search_zip(modpath, pic)[:2] raise else: - if checkeggs: + if checkeggs and mp_filename: fullabspath = [abspath(x) for x in _path] try: pathindex = fullabspath.index(dirname(abspath(mp_filename))) -- cgit v1.2.1 From 1e207fd9fa6d8c6c56e7706a781652fb8b6ad109 Mon Sep 17 00:00:00 2001 From: Sylvain Th?nault Date: Mon, 17 Jun 2013 17:10:04 +0200 Subject: [modutils]?setuptools pkg_resources support. Closes #8796 NO I won't write a test. Setup is to painful to reproduce for automatic test (require virtualenv, setuptools, python setup.py develop, etc). See description on the ticket. --- modutils.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/modutils.py b/modutils.py index 05f0602..834b5d3 100644 --- a/modutils.py +++ b/modutils.py @@ -574,6 +574,11 @@ def _search_zip(modpath, pic): return ZIPFILE, abspath(filepath) + '/' + '/'.join(modpath), filepath raise ImportError('No module named %s' % '.'.join(modpath)) +try: + import pkg_resources +except ImportError: + pkg_resources = None + def _module_file(modpath, path=None): """get a module type / file path @@ -604,6 +609,12 @@ def _module_file(modpath, path=None): checkeggs = True except AttributeError: checkeggs = False + # pkg_resources support (aka setuptools namespace packages) + if pkg_resources is not None and modpath[0] in pkg_resources._namespace_packages and len(modpath) > 1: + # setuptools has added into sys.modules a module object with proper + # __path__, get back information from there + module = sys.modules[modpath.pop(0)] + path = module.__path__ imported = [] while modpath: # take care to changes in find_module implementation wrt builtin modules -- cgit v1.2.1 From fb8c4ee84abfc8f73ede8460cf718b90fb2b8ef9 Mon Sep 17 00:00:00 2001 From: Sylvain Th?nault Date: Mon, 17 Jun 2013 18:03:04 +0200 Subject: [modutils] add pkgutil.extend_path support. Closes #8796 --- modutils.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/modutils.py b/modutils.py index 834b5d3..9d0bb49 100644 --- a/modutils.py +++ b/modutils.py @@ -617,6 +617,7 @@ def _module_file(modpath, path=None): path = module.__path__ imported = [] while modpath: + modname = modpath[0] # take care to changes in find_module implementation wrt builtin modules # # Python 2.6.6 (r266:84292, Sep 11 2012, 08:34:23) @@ -627,7 +628,7 @@ def _module_file(modpath, path=None): # >>> imp.find_module('posix') # (None, None, ('', '', 6)) try: - _, mp_filename, mp_desc = find_module(modpath[0], path) + _, mp_filename, mp_desc = find_module(modname, path) except ImportError: if checkeggs: return _search_zip(modpath, pic)[:2] @@ -653,7 +654,16 @@ def _module_file(modpath, path=None): if mtype != PKG_DIRECTORY: raise ImportError('No module %s in %s' % ('.'.join(modpath), '.'.join(imported))) - path = [mp_filename] + # XXX guess if package is using pkgutil.extend_path by looking for + # those keywords in the first four Kbytes + data = open(join(mp_filename, '__init__.py')).read(4096) + if 'pkgutil' in data and 'extend_path' in data: + # extend_path is called, search sys.path for module/packages of this name + # see pkgutil.extend_path documentation + path = [join(p, modname) for p in sys.path + if isdir(join(p, modname))] + else: + path = [mp_filename] return mtype, mp_filename def _is_python_file(filename): -- cgit v1.2.1 From 081bd4dae7a4c725984d7ffcc5f8de58f8a92fe3 Mon Sep 17 00:00:00 2001 From: R?mi Cardona Date: Mon, 10 Jun 2013 17:45:48 +0200 Subject: Update version number in spec file --- python-logilab-common.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python-logilab-common.spec b/python-logilab-common.spec index d960177..0544013 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.59.0 +Version: 0.59.1 Release: logilab.1%{?dist} Summary: Common libraries for Logilab projects -- cgit v1.2.1 From 84ba539413f84d320a4a59db95d38361b054383e Mon Sep 17 00:00:00 2001 From: Mike Mueller Date: Fri, 28 Jun 2013 14:15:02 +0200 Subject: Fixed: Install fails on Windows with Python 3.3. Calling subprocess with `shell=True` works. --- setup.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index cc54251..8f27b3b 100644 --- a/setup.py +++ b/setup.py @@ -140,8 +140,10 @@ class MyBuildPy(build_py): if sys.version_info >= (3, 0): # process manually python file in include_dirs (test data) from subprocess import check_call - print('running 2to3 on', dest) # brackets are NOT optional here for py3k compat - check_call(['2to3', '-wn', dest]) + # brackets are NOT optional here for py3k compat + print('running 2to3 on', dest) + # Needs `shell=True` to run on Windows. + check_call(['2to3', '-wn', dest], shell=True) def install(**kwargs): -- cgit v1.2.1 From c7a5df7f9cb4ad06174655185b319d91ea4f84f2 Mon Sep 17 00:00:00 2001 From: Julien Cristau Date: Mon, 22 Jul 2013 08:51:35 +0200 Subject: testlib: fix for python 3.3 unittest.TestCase no longer has a assertSameElements method. Use assertCountEqual instead of assertSameElements/assertItemsEqual. Closes #144526 --- test/unittest_cache.py | 12 ++++++------ testlib.py | 13 ++++++++----- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/test/unittest_cache.py b/test/unittest_cache.py index 9b02b39..459f172 100644 --- a/test/unittest_cache.py +++ b/test/unittest_cache.py @@ -33,7 +33,7 @@ class CacheTestCase(TestCase): self.assertEqual(len(self.cache._usage), 1) self.assertEqual(self.cache._usage[-1], 1, '1 is not the most recently used key') - self.assertItemsEqual(self.cache._usage, + self.assertCountEqual(self.cache._usage, self.cache.keys(), "usage list and data keys are different") @@ -47,7 +47,7 @@ class CacheTestCase(TestCase): "lenght of usage list is not 2") self.assertEqual(self.cache._usage[-1], 2, '1 is not the most recently used key') - self.assertItemsEqual(self.cache._usage, + self.assertCountEqual(self.cache._usage, self.cache.keys())# usage list and data keys are different def test_setitem3(self): @@ -57,7 +57,7 @@ class CacheTestCase(TestCase): self.assertEqual(self.cache[1], 'bar', "1 : 'bar' is not in cache.data") self.assertEqual(len(self.cache._usage), 1, "lenght of usage list is not 1") self.assertEqual(self.cache._usage[-1], 1, '1 is not the most recently used key') - self.assertItemsEqual(self.cache._usage, + self.assertCountEqual(self.cache._usage, self.cache.keys())# usage list and data keys are different def test_recycling1(self): @@ -74,7 +74,7 @@ class CacheTestCase(TestCase): 'key 1 has not been suppressed from the cache LRU list') self.assertEqual(len(self.cache._usage), 5, "lenght of usage list is not 5") self.assertEqual(self.cache._usage[-1], 6, '6 is not the most recently used key') - self.assertItemsEqual(self.cache._usage, + self.assertCountEqual(self.cache._usage, self.cache.keys())# usage list and data keys are different def test_recycling2(self): @@ -86,7 +86,7 @@ class CacheTestCase(TestCase): a = self.cache[1] self.assertEqual(a, 'foo') self.assertEqual(self.cache._usage[-1], 1, '1 is not the most recently used key') - self.assertItemsEqual(self.cache._usage, + self.assertCountEqual(self.cache._usage, self.cache.keys())# usage list and data keys are different def test_delitem(self): @@ -97,7 +97,7 @@ class CacheTestCase(TestCase): del self.cache['foo'] self.assertTrue('foo' not in self.cache.keys(), "Element 'foo' was not removed cache dictionnary") self.assertTrue('foo' not in self.cache._usage, "Element 'foo' was not removed usage list") - self.assertItemsEqual(self.cache._usage, + self.assertCountEqual(self.cache._usage, self.cache.keys())# usage list and data keys are different diff --git a/testlib.py b/testlib.py index 0517032..27326b8 100644 --- a/testlib.py +++ b/testlib.py @@ -721,7 +721,7 @@ succeeded test into", osp.join(os.getcwd(), FILE_RESTART) base = '' self.fail(base + '\n'.join(msgs)) - @deprecated('Please use assertItemsEqual instead.') + @deprecated('Please use assertCountEqual instead.') def assertUnorderedIterableEquals(self, got, expected, msg=None): """compares two iterable and shows difference between both @@ -1183,10 +1183,13 @@ succeeded test into", osp.join(os.getcwd(), FILE_RESTART) assertRaises = failUnlessRaises - if not hasattr(unittest.TestCase, 'assertItemsEqual'): - # python 3.2 has deprecated assertSameElements and is missing - # assertItemsEqual - assertItemsEqual = unittest.TestCase.assertSameElements + if sys.version_info >= (3,2): + assertItemsEqual = unittest.TestCase.assertCountEqual + else: + assertCountEqual = unittest.TestCase.assertItemsEqual + +TestCase.assertItemsEqual = deprecated('assertItemsEqual is deprecated, use assertCountEqual')( + TestCase.assertItemsEqual) import doctest -- cgit v1.2.1 From 701a93ce71b855d86e26bde0075e27479f1164e2 Mon Sep 17 00:00:00 2001 From: Julien Cristau Date: Thu, 20 Jun 2013 14:27:38 +0200 Subject: graph: use codecs.open. Closes #155138 Makes python3 happier (can't write utf8 data to a file opened without an encoding) --- graph.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/graph.py b/graph.py index 5cae530..94a71b6 100644 --- a/graph.py +++ b/graph.py @@ -28,7 +28,7 @@ import os.path as osp import os import sys import tempfile -from logilab.common.compat import str_encode +import codecs def escape(value): """Make usable in a dot file.""" @@ -106,8 +106,8 @@ class DotBackend: ppng, outputfile = tempfile.mkstemp(".png", name) os.close(pdot) os.close(ppng) - pdot = open(dot_sourcepath, 'w') - pdot.write(str_encode(self.source, 'utf8')) + pdot = codecs.open(dot_sourcepath, 'w', encoding='utf8') + pdot.write(self.source) pdot.close() if target != 'dot': if sys.platform == 'win32': -- cgit v1.2.1 From 07f9b4ac057f646c5232781d01fc34765c1c04c2 Mon Sep 17 00:00:00 2001 From: Sylvain Th?nault Date: Fri, 26 Jul 2013 10:25:50 +0200 Subject: update Changelog --- ChangeLog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index b0c893e..7dac422 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,11 @@ ChangeLog for logilab.common * fix python3.3 crash in file_from_modpath due to implementation change of imp.find_module wrt builtin modules (#137244) + * testlib: use assertCountEqual instead of assertSameElements/assertItemsEqual + (deprecated), fixing crash with python 3.3 (#144526) + + * graph: use codecs.open avoid crash when writing utf-8 data under python3 + (#155138) 2013-04-16 -- 0.59.1 * graph: added pruning of the recursive search tree for detecting cycles in -- cgit v1.2.1