server/utils.py
changeset 0 b97547f5f1fa
child 1134 f885df228fc0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/utils.py	Wed Nov 05 15:52:50 2008 +0100
@@ -0,0 +1,138 @@
+"""Some utilities for the CubicWeb server.
+
+:organization: Logilab
+:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
+__docformat__ = "restructuredtext en"
+
+import sys
+import string
+from threading import Timer, Thread
+from getpass import getpass
+from random import choice
+
+try:
+    from crypt import crypt
+except ImportError:
+    # crypt is not available (eg windows)
+    from cubicweb.md5crypt import crypt
+
+
+def getsalt(chars=string.letters + string.digits):
+    """generate a random 2-character 'salt'"""
+    return choice(chars) + choice(chars)
+
+
+def crypt_password(passwd, salt=None):
+    """return the encrypted password using the given salt or a generated one
+    """
+    if passwd is None:
+        return None
+    if salt is None:
+        salt = getsalt()
+    return crypt(passwd, salt)
+
+
+def cartesian_product(seqin):
+    """returns a generator which returns the cartesian product of `seqin`
+
+    for more details, see :
+    http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/302478
+    """
+    def rloop(seqin, comb):
+        """recursive looping function"""
+        if seqin:                   # any more sequences to process?
+            for item in seqin[0]:
+                newcomb = comb + [item]     # add next item to current combination
+                # call rloop w/ remaining seqs, newcomb
+                for item in rloop(seqin[1:], newcomb):   
+                    yield item          # seqs and newcomb
+        else:                           # processing last sequence
+            yield comb                  # comb finished, add to list
+    return rloop(seqin, [])
+
+
+def cleanup_solutions(rqlst, solutions):
+    for sol in solutions:
+        for vname in sol.keys():
+            if not (vname in rqlst.defined_vars or vname in rqlst.aliases):
+                del sol[vname]
+
+
+DEFAULT_MSG = 'we need a manager connection on the repository \
+(the server doesn\'t have to run, even should better not)'
+
+def manager_userpasswd(user=None, passwd=None, msg=DEFAULT_MSG, confirm=False):
+    if not user:
+        print msg
+        while not user:
+            user = raw_input('login: ')
+        passwd = getpass('password: ')
+        if confirm:
+            while True:
+                passwd2 = getpass('confirm password: ')
+                if passwd == passwd2:
+                    break
+                print 'password doesn\'t match'
+                passwd = getpass('password: ')
+        user = unicode(user, sys.stdin.encoding)
+    elif not passwd:
+        assert not confirm
+        passwd = getpass('password for %s: ' % user)
+    # XXX decode password using stdin encoding then encode it using appl'encoding
+    return user, passwd
+
+
+class LoopTask(object):
+    """threaded task restarting itself once executed"""
+    def __init__(self, interval, func):
+        self.interval = interval
+        def auto_restart_func(self=self, func=func):
+            try:
+                func()
+            finally:
+                self.start()
+        self.func = auto_restart_func
+        self.name = func.__name__
+        
+    def start(self):
+        self._t = Timer(self.interval, self.func)
+        self._t.start()
+
+    def cancel(self):
+        self._t.cancel()
+
+    def join(self):
+        self._t.join()
+
+
+class RepoThread(Thread):
+    """subclass of thread so it auto remove itself from a given list once
+    executed
+    """
+    def __init__(self, target, running_threads):
+        def auto_remove_func(self=self, func=target):
+            try:
+                func()
+            finally:
+                self.running_threads.remove(self)
+        Thread.__init__(self, target=target)
+        self.running_threads = running_threads
+        self._name = target.__name__
+        
+    def start(self):
+        self.running_threads.append(self)
+        Thread.start(self)
+
+    @property
+    def name(self):
+        return '%s(%s)' % (self._name, Thread.getName(self))
+
+
+from logilab.common.deprecation import class_moved
+from cubicweb.server import pool
+Operation = class_moved(pool.Operation)
+PreCommitOperation = class_moved(pool.PreCommitOperation)
+LateOperation = class_moved(pool.LateOperation)
+SingleLastOperation = class_moved(pool.SingleLastOperation)