Hello community,

here is the log from the commit of package python-logilab-common for 
openSUSE:Factory checked in at 2012-02-24 06:53:44
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-logilab-common (Old)
 and      /work/SRC/openSUSE:Factory/.python-logilab-common.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-logilab-common", Maintainer is "[email protected]"

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-logilab-common/python-logilab-common.changes  
    2011-09-23 12:42:56.000000000 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-logilab-common.new/python-logilab-common.changes
 2012-02-24 06:53:50.000000000 +0100
@@ -1,0 +2,9 @@
+Sat Feb 18 16:32:08 UTC 2012 - [email protected]
+
+- Update to version 0.57.1
+  * daemon: change $HOME after dropping privileges (closes #81297)
+  * compat: method_type for py3k use instance of the class to
+  * have a real instance method (closes: #79268)
+ 
+
+-------------------------------------------------------------------

Old:
----
  logilab-common-0.56.2.tar.gz

New:
----
  logilab-common-0.57.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-logilab-common.spec ++++++
--- /var/tmp/diff_new_pack.EbZpLM/_old  2012-02-24 06:53:52.000000000 +0100
+++ /var/tmp/diff_new_pack.EbZpLM/_new  2012-02-24 06:53:52.000000000 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-logilab-common
 #
-# Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany.
+# Copyright (c) 2012 SUSE LINUX Products GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -16,9 +16,8 @@
 #
 
 
-
 Name:           python-logilab-common
-Version:        0.56.2
+Version:        0.57.1
 Release:        0
 Url:            http://www.logilab.org/projects/common/
 Summary:        Python lowlevel functionality shared by logilab projects

++++++ logilab-common-0.56.2.tar.gz -> logilab-common-0.57.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logilab-common-0.56.2/ChangeLog 
new/logilab-common-0.57.1/ChangeLog
--- old/logilab-common-0.56.2/ChangeLog 2011-09-08 16:43:22.000000000 +0200
+++ new/logilab-common-0.57.1/ChangeLog 2011-10-28 12:00:09.000000000 +0200
@@ -1,6 +1,29 @@
 ChangeLog for logilab.common
 ============================
 
+2011-10-28  --  0.57.1
+    * daemon: change $HOME after dropping privileges (closes #81297)
+
+    * compat: method_type for py3k use instance of the class to have a
+      real instance method (closes: #79268)
+
+
+
+2011-10-12  --  0.57.0
+    * only install unittest2 when python version < 2.7 (closes: #76068)
+
+    * daemon: make pidfile world-readable (closes #75968)
+
+    * daemon: remove unused(?) DaemonMixin class
+
+    * update compat module for callable() and method_type()
+
+    * decorators: fix monkeypatch py3k compat (closes #75290)
+
+    * decorators: provide a @cachedproperty decorator
+
+
+
 2011-09-08  --  0.56.2
     * daemon: call initgroups/setgid before setuid (closes #74173)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logilab-common-0.56.2/PKG-INFO 
new/logilab-common-0.57.1/PKG-INFO
--- old/logilab-common-0.56.2/PKG-INFO  2011-09-08 18:14:09.000000000 +0200
+++ new/logilab-common-0.57.1/PKG-INFO  2011-10-28 12:00:19.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.0
 Name: logilab-common
-Version: 0.56.2
+Version: 0.57.1
 Summary: collection of low-level Python packages and modules used by Logilab 
projects
 Home-page: http://www.logilab.org/project/logilab-common
 Author: Logilab
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logilab-common-0.56.2/__pkginfo__.py 
new/logilab-common-0.57.1/__pkginfo__.py
--- old/logilab-common-0.56.2/__pkginfo__.py    2011-09-08 16:43:22.000000000 
+0200
+++ new/logilab-common-0.57.1/__pkginfo__.py    2011-10-28 12:00:09.000000000 
+0200
@@ -17,13 +17,14 @@
 # with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
 """logilab.common packaging information"""
 __docformat__ = "restructuredtext en"
+import sys
 
 distname = 'logilab-common'
 modname = 'common'
 subpackage_of = 'logilab'
 subpackage_master = True
 
-numversion = (0, 56, 2)
+numversion = (0, 57, 1)
 version = '.'.join([str(num) for num in numversion])
 
 license = 'LGPL' # 2.1 or later
@@ -39,4 +40,6 @@
 scripts = [join('bin', 'pytest')]
 include_dirs = [join('test', 'data')]
 
-install_requires = ['unittest2 >= 0.5.1']
+if sys.version_info < (2, 7):
+    install_requires = ['unittest2 >= 0.5.1']
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logilab-common-0.56.2/bin/pytest 
new/logilab-common-0.57.1/bin/pytest
--- old/logilab-common-0.56.2/bin/pytest        2008-03-05 18:08:25.000000000 
+0100
+++ new/logilab-common-0.57.1/bin/pytest        2011-09-08 18:14:28.000000000 
+0200
@@ -1,4 +1,4 @@
-#!/usr/bin/python -u
+#!/usr/bin/python -uWdefault
 
 from logilab.common.pytest import run
 run()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logilab-common-0.56.2/compat.py 
new/logilab-common-0.57.1/compat.py
--- old/logilab-common-0.56.2/compat.py 2011-04-26 09:44:21.000000000 +0200
+++ new/logilab-common-0.57.1/compat.py 2011-10-28 12:00:10.000000000 +0200
@@ -20,7 +20,7 @@
 2.5, making them available in for earlier versions of python.
 
 See another compatibility snippets from other projects:
-    
+
     :mod:`lib2to3.fixes`
     :mod:`coverage.backward`
     :mod:`unittest2.compatibility`
@@ -32,6 +32,7 @@
 
 import os
 import sys
+import types
 from warnings import warn
 
 import __builtin__ as builtins # 2to3 will tranform '__builtin__' to 'builtins'
@@ -50,14 +51,23 @@
     def str_encode(string, encoding):
         return str(string)
 
-# XXX shouldn't we remove this and just let 2to3 do his job ?
+# XXX callable built-in seems back in all python versions
 try:
-    callable = callable
-except NameError:# callable removed from py3k
-    import collections
+    callable = builtins.callable
+except AttributeError:
+    from collections import Callable
     def callable(something):
-        return isinstance(something, collections.Callable)
-    del collections
+        return isinstance(something, Callable)
+    del Callable
+
+# See also http://bugs.python.org/issue11776
+if sys.version_info[0] == 3:
+    def method_type(callable, instance, klass):
+        # api change. klass is no more considered
+        return types.MethodType(callable, instance)
+else:
+    # alias types otherwise
+    method_type = types.MethodType
 
 if sys.version_info < (3, 0):
     raw_input = raw_input
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logilab-common-0.56.2/daemon.py 
new/logilab-common-0.57.1/daemon.py
--- old/logilab-common-0.56.2/daemon.py 2011-09-08 16:43:22.000000000 +0200
+++ new/logilab-common-0.57.1/daemon.py 2011-10-28 12:00:10.000000000 +0200
@@ -15,7 +15,7 @@
 #
 # You should have received a copy of the GNU Lesser General Public License 
along
 # with logilab-common.  If not, see <http://www.gnu.org/licenses/>.
-"""A daemonize function (for Unices) and daemon mix-in class"""
+"""A daemonize function (for Unices)"""
 
 __docformat__ = "restructuredtext en"
 
@@ -46,6 +46,7 @@
             raise OSError(err, os.strerror(err), 'initgroups')
     os.setgid(passwd.pw_gid)
     os.setuid(passwd.pw_uid)
+    os.putenv('HOME', passwd.pw_dir)
 
 
 def daemonize(pidfile=None, uid=None, umask=077):
@@ -92,109 +93,8 @@
         f = file(pidfile, 'w')
         f.write(str(os.getpid()))
         f.close()
+        os.chmod(pidfile, 0644)
     # change process uid
     if uid:
         setugid(uid)
     return None
-
-
-class DaemonMixIn:
-    """Mixin to make a daemon from watchers/queriers.
-    """
-
-    def __init__(self, configmod) :
-        self.delay = configmod.DELAY
-        self.name = str(self.__class__).split('.')[-1]
-        self._pid_file = os.path.join('/tmp', '%s.pid'%self.name)
-        if os.path.exists(self._pid_file):
-            raise Exception('''Another instance of %s must be running.
-If it i not the case, remove the file %s''' % (self.name, self._pid_file))
-        self._alive = 1
-        self._sleeping = 0
-        self.config = configmod
-
-    def _daemonize(self):
-        if not self.config.NODETACH:
-            if daemonize(self._pid_file) is None:
-                # put signal handler
-                signal.signal(signal.SIGTERM, self.signal_handler)
-                signal.signal(signal.SIGHUP, self.signal_handler)
-            else:
-                return -1
-
-    def run(self):
-        """ optionally go in daemon mode and
-        do what concrete class has to do and pauses for delay between runs
-        If self.delay is negative, do a pause before starting
-        """
-        if self._daemonize() == -1:
-            return
-        if self.delay < 0:
-            self.delay = -self.delay
-            time.sleep(self.delay)
-        while True:
-            try:
-                self._run()
-            except Exception, ex:
-                # display for info, sleep, and hope the problem will be solved
-                # later.
-                self.config.exception('Internal error: %s', ex)
-            if not self._alive:
-                break
-            try:
-                self._sleeping = 1
-                time.sleep(self.delay)
-                self._sleeping = 0
-            except SystemExit:
-                break
-        self.config.info('%s instance exited', self.name)
-        # remove pid file
-        os.remove(self._pid_file)
-
-    def signal_handler(self, sig_num, stack_frame):
-        if sig_num == signal.SIGTERM:
-            if self._sleeping:
-                # we are sleeping so we can exit without fear
-                self.config.debug('exit on SIGTERM')
-                sys.exit(0)
-            else:
-                self.config.debug('exit on SIGTERM (on next turn)')
-                self._alive = 0
-        elif sig_num == signal.SIGHUP:
-            self.config.info('reloading configuration on SIGHUP')
-            reload(self.config)
-
-    def _run(self):
-        """should be overridden in the mixed class"""
-        raise NotImplementedError()
-
-
-import logging
-from logilab.common.logging_ext import set_log_methods
-set_log_methods(DaemonMixIn, logging.getLogger('lgc.daemon'))
-
-## command line utilities 
######################################################
-
-L_OPTIONS = ["help", "log=", "delay=", 'no-detach']
-S_OPTIONS = 'hl:d:n'
-
-def print_help(modconfig):
-    print """  --help or -h
-    displays this message
-  --log <log_level>
-    log treshold (7 record everything, 0 record only emergency.)
-    Defaults to %s
-  --delay <delay>
-    the number of seconds between two runs.
-    Defaults to %s""" % (modconfig.LOG_TRESHOLD, modconfig.DELAY)
-
-def handle_option(modconfig, opt_name, opt_value, help_meth):
-    if opt_name in ('-h', '--help'):
-        help_meth()
-        sys.exit(0)
-    elif opt_name in ('-l', '--log'):
-        modconfig.LOG_TRESHOLD = int(opt_value)
-    elif opt_name in ('-d', '--delay'):
-        modconfig.DELAY = int(opt_value)
-    elif opt_name in ('-n', '--no-detach'):
-        modconfig.NODETACH = 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logilab-common-0.56.2/decorators.py 
new/logilab-common-0.57.1/decorators.py
--- old/logilab-common-0.56.2/decorators.py     2011-09-08 16:43:22.000000000 
+0200
+++ new/logilab-common-0.57.1/decorators.py     2011-10-28 12:00:10.000000000 
+0200
@@ -18,10 +18,11 @@
 """ A few useful function/method decorators. """
 __docformat__ = "restructuredtext en"
 
-import types
-import sys, re
+import sys
 from time import clock, time
 
+from logilab.common.compat import callable, method_type
+
 # XXX rewrite so we can use the decorator syntax when keyarg has to be 
specified
 
 def _is_generator_function(callableobj):
@@ -116,6 +117,45 @@
     else:
         return decorator(callableobj)
 
+
+class cachedproperty(object):
+    """ Provides a cached property equivalent to the stacking of
+    @cached and @property, but more efficient.
+
+    After first usage, the <property_name> becomes part of the object's
+    __dict__. Doing:
+
+      del obj.<property_name> empties the cache.
+
+    Idea taken from the pyramid_ framework and the mercurial_ project.
+
+    .. _pyramid: http://pypi.python.org/pypi/pyramid
+    .. _mercurial: http://pypi.python.org/pypi/Mercurial
+    """
+    __slots__ = ('wrapped',)
+
+    def __init__(self, wrapped):
+        try:
+            wrapped.__name__
+        except AttributeError:
+            raise TypeError('%s must have a __name__ attribute' %
+                            wrapped)
+        self.wrapped = wrapped
+
+    @property
+    def __doc__(self):
+        doc = getattr(self.wrapped, '__doc__', None)
+        return ('<wrapped by the cachedproperty decorator>%s'
+                % ('\n%s' % doc if doc else ''))
+
+    def __get__(self, inst, objtype=None):
+        if inst is None:
+            return self
+        val = self.wrapped(inst)
+        setattr(inst, self.wrapped.__name__, val)
+        return val
+
+
 def get_cache_impl(obj, funcname):
     cls = obj.__class__
     member = getattr(cls, funcname)
@@ -175,8 +215,8 @@
         self.func = func
     def __get__(self, instance, objtype):
         if instance is None:
-            return types.MethodType(self.func, objtype, objtype.__class__)
-        return types.MethodType(self.func, instance, objtype)
+            return method_type(self.func, objtype, objtype.__class__)
+        return method_type(self.func, instance, objtype)
     def __set__(self, instance, value):
         raise AttributeError("can't set attribute")
 
@@ -233,8 +273,8 @@
             raise AttributeError('%s has no __name__ attribute: '
                                  'you should provide an explicit `methodname`'
                                  % func)
-        if callable(func):
-            setattr(klass, name, types.MethodType(func, None, klass))
+        if callable(func) and sys.version_info < (3, 0):
+            setattr(klass, name, method_type(func, None, klass))
         else:
             # likely a property
             # this is quite borderline but usage already in the wild ...
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logilab-common-0.56.2/deprecation.py 
new/logilab-common-0.57.1/deprecation.py
--- old/logilab-common-0.56.2/deprecation.py    2011-04-26 09:44:21.000000000 
+0200
+++ new/logilab-common-0.57.1/deprecation.py    2011-10-28 11:59:58.000000000 
+0200
@@ -71,7 +71,7 @@
             old_name, new_class.__module__, new_class.__name__)
     return class_renamed(old_name, new_class, message)
 
-def deprecated(reason=None, stacklevel=2):
+def deprecated(reason=None, stacklevel=2, name=None, doc=None):
     """Decorator that raises a DeprecationWarning to print a message
     when the decorated function is called.
     """
@@ -83,10 +83,10 @@
             warn(message, DeprecationWarning, stacklevel=stacklevel)
             return func(*args, **kwargs)
         try:
-            wrapped.__name__ = func.__name__
+            wrapped.__name__ = name or func.__name__
         except TypeError: # readonly attribute in 2.3
             pass
-        wrapped.__doc__ = func.__doc__
+        wrapped.__doc__ = doc or func.__doc__
         return wrapped
     return deprecated_decorator
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/logilab-common-0.56.2/test/unittest_decorators.py 
new/logilab-common-0.57.1/test/unittest_decorators.py
--- old/logilab-common-0.56.2/test/unittest_decorators.py       2011-09-08 
16:43:22.000000000 +0200
+++ new/logilab-common-0.57.1/test/unittest_decorators.py       2011-10-28 
11:59:58.000000000 +0200
@@ -20,7 +20,8 @@
 import types
 
 from logilab.common.testlib import TestCase, unittest_main
-from logilab.common.decorators import monkeypatch, cached, clear_cache, 
copy_cache
+from logilab.common.decorators import (monkeypatch, cached, clear_cache,
+                                       copy_cache, cachedproperty)
 
 class DecoratorsTC(TestCase):
 
@@ -161,5 +162,40 @@
         copy_cache(foo2, 'foo', foo)
         self.assertEqual(foo2._foo, {(1,): None})
 
+
+    def test_cachedproperty(self):
+        class Foo(object):
+            x = 0
+            @cachedproperty
+            def bar(self):
+                self.__class__.x += 1
+                return self.__class__.x
+            @cachedproperty
+            def quux(self):
+                """ some prop """
+                return 42
+
+        foo = Foo()
+        self.assertEqual(Foo.x, 0)
+        self.failIf('bar' in foo.__dict__)
+        self.assertEqual(foo.bar, 1)
+        self.failUnless('bar' in foo.__dict__)
+        self.assertEqual(foo.bar, 1)
+        self.assertEqual(foo.quux, 42)
+        self.assertEqual(Foo.bar.__doc__,
+                         '<wrapped by the cachedproperty decorator>')
+        self.assertEqual(Foo.quux.__doc__,
+                         '<wrapped by the cachedproperty decorator>\n some 
prop ')
+
+        foo2 = Foo()
+        self.assertEqual(foo2.bar, 2)
+        # make sure foo.foo is cached
+        self.assertEqual(foo.bar, 1)
+
+        class Kallable(object):
+            def __call__(self):
+                return 42
+        self.assertRaises(TypeError, cachedproperty, Kallable())
+
 if __name__ == '__main__':
     unittest_main()

-- 
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to