server/utils.py
changeset 0 b97547f5f1fa
child 1134 f885df228fc0
equal deleted inserted replaced
-1:000000000000 0:b97547f5f1fa
       
     1 """Some utilities for the CubicWeb server.
       
     2 
       
     3 :organization: Logilab
       
     4 :copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
       
     5 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
       
     6 """
       
     7 __docformat__ = "restructuredtext en"
       
     8 
       
     9 import sys
       
    10 import string
       
    11 from threading import Timer, Thread
       
    12 from getpass import getpass
       
    13 from random import choice
       
    14 
       
    15 try:
       
    16     from crypt import crypt
       
    17 except ImportError:
       
    18     # crypt is not available (eg windows)
       
    19     from cubicweb.md5crypt import crypt
       
    20 
       
    21 
       
    22 def getsalt(chars=string.letters + string.digits):
       
    23     """generate a random 2-character 'salt'"""
       
    24     return choice(chars) + choice(chars)
       
    25 
       
    26 
       
    27 def crypt_password(passwd, salt=None):
       
    28     """return the encrypted password using the given salt or a generated one
       
    29     """
       
    30     if passwd is None:
       
    31         return None
       
    32     if salt is None:
       
    33         salt = getsalt()
       
    34     return crypt(passwd, salt)
       
    35 
       
    36 
       
    37 def cartesian_product(seqin):
       
    38     """returns a generator which returns the cartesian product of `seqin`
       
    39 
       
    40     for more details, see :
       
    41     http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/302478
       
    42     """
       
    43     def rloop(seqin, comb):
       
    44         """recursive looping function"""
       
    45         if seqin:                   # any more sequences to process?
       
    46             for item in seqin[0]:
       
    47                 newcomb = comb + [item]     # add next item to current combination
       
    48                 # call rloop w/ remaining seqs, newcomb
       
    49                 for item in rloop(seqin[1:], newcomb):   
       
    50                     yield item          # seqs and newcomb
       
    51         else:                           # processing last sequence
       
    52             yield comb                  # comb finished, add to list
       
    53     return rloop(seqin, [])
       
    54 
       
    55 
       
    56 def cleanup_solutions(rqlst, solutions):
       
    57     for sol in solutions:
       
    58         for vname in sol.keys():
       
    59             if not (vname in rqlst.defined_vars or vname in rqlst.aliases):
       
    60                 del sol[vname]
       
    61 
       
    62 
       
    63 DEFAULT_MSG = 'we need a manager connection on the repository \
       
    64 (the server doesn\'t have to run, even should better not)'
       
    65 
       
    66 def manager_userpasswd(user=None, passwd=None, msg=DEFAULT_MSG, confirm=False):
       
    67     if not user:
       
    68         print msg
       
    69         while not user:
       
    70             user = raw_input('login: ')
       
    71         passwd = getpass('password: ')
       
    72         if confirm:
       
    73             while True:
       
    74                 passwd2 = getpass('confirm password: ')
       
    75                 if passwd == passwd2:
       
    76                     break
       
    77                 print 'password doesn\'t match'
       
    78                 passwd = getpass('password: ')
       
    79         user = unicode(user, sys.stdin.encoding)
       
    80     elif not passwd:
       
    81         assert not confirm
       
    82         passwd = getpass('password for %s: ' % user)
       
    83     # XXX decode password using stdin encoding then encode it using appl'encoding
       
    84     return user, passwd
       
    85 
       
    86 
       
    87 class LoopTask(object):
       
    88     """threaded task restarting itself once executed"""
       
    89     def __init__(self, interval, func):
       
    90         self.interval = interval
       
    91         def auto_restart_func(self=self, func=func):
       
    92             try:
       
    93                 func()
       
    94             finally:
       
    95                 self.start()
       
    96         self.func = auto_restart_func
       
    97         self.name = func.__name__
       
    98         
       
    99     def start(self):
       
   100         self._t = Timer(self.interval, self.func)
       
   101         self._t.start()
       
   102 
       
   103     def cancel(self):
       
   104         self._t.cancel()
       
   105 
       
   106     def join(self):
       
   107         self._t.join()
       
   108 
       
   109 
       
   110 class RepoThread(Thread):
       
   111     """subclass of thread so it auto remove itself from a given list once
       
   112     executed
       
   113     """
       
   114     def __init__(self, target, running_threads):
       
   115         def auto_remove_func(self=self, func=target):
       
   116             try:
       
   117                 func()
       
   118             finally:
       
   119                 self.running_threads.remove(self)
       
   120         Thread.__init__(self, target=target)
       
   121         self.running_threads = running_threads
       
   122         self._name = target.__name__
       
   123         
       
   124     def start(self):
       
   125         self.running_threads.append(self)
       
   126         Thread.start(self)
       
   127 
       
   128     @property
       
   129     def name(self):
       
   130         return '%s(%s)' % (self._name, Thread.getName(self))
       
   131 
       
   132 
       
   133 from logilab.common.deprecation import class_moved
       
   134 from cubicweb.server import pool
       
   135 Operation = class_moved(pool.Operation)
       
   136 PreCommitOperation = class_moved(pool.PreCommitOperation)
       
   137 LateOperation = class_moved(pool.LateOperation)
       
   138 SingleLastOperation = class_moved(pool.SingleLastOperation)