<commit_before># -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

#
# OSV: Objects Services
#

import orm
import logging
import netsvc
import pooler
import copy
from psycopg2 import IntegrityError, errorcodes
from tools.func import wraps
from tools.translate import translate

module_list = []
module_class_list = {}
class_pool = {}

class except_osv(Exception):
    def __init__(self, name, value, exc_type='warning'):
        self.name = name
        self.exc_type = exc_type
        self.value = value
        self.args = (exc_type, name)

class object_proxy(netsvc.Service):
    def __init__(self):
        self.logger = logging.getLogger('web-services')
        netsvc.Service.__init__(self, 'object_proxy', audience='')
        self.exportMethod(self.exec_workflow)
        self.exportMethod(self.execute)
        self.exportMethod(self.set_debug)
        self.exportMethod(self.obj_list)

    def check(f):
        @wraps(f)
        def wrapper(self, dbname, *args, **kwargs):
            """ Wraps around OSV functions and normalises a few exceptions
            """

            def tr(src, ttype):
                # We try to do the same as the _(), but without the frame
                # inspection, since we aready are wrapping an osv function
                # trans_obj = self.get('ir.translation') cannot work yet :(
                ctx = {}
                if not kwargs:
                    if args and isinstance(args[-1], dict):
                        ctx = args[-1]
                elif isinstance(kwargs, dict):
                    ctx = kwargs.get('context', {})

                uid = 1
                if args and isinstance(args[0], (long, int)):
                    uid = args[0]

                lang = ctx and ctx.get('lang')
                if not (lang or hasattr(src, '__call__')):
                    return src

                # We open a *new* cursor here, one reason is that failed SQL
                # queries (as in IntegrityError) will invalidate the current one.
                cr = False

                if hasattr(src, '__call__'):
                    # callable. We need to find the right parameters to call
                    # the  orm._sql_message(self, cr, uid, ids, context) function,
                    # or we skip..
                    # our signature is f(osv_pool, dbname [,uid, obj, method, args])
                    try:
                        if args and len(args) > 1:
                            obj = self.get(args[1])
                            if len(args) > 3 and isinstance(args[3], (long, int, list)):
                                ids = args[3]
                            else:
                                ids = []
                        cr = pooler.get_db_only(dbname).cursor()
                        return src(obj, cr, uid, ids, context=(ctx or {}))
                    except Exception:
                        pass
                    finally:
                        if cr: cr.close()

                    return False # so that the original SQL error will
                                 # be returned, it is the best we have.

                try:
                    cr = pooler.get_db_only(dbname).cursor()
                    res = translate(cr, name=False, source_type=ttype,
                                    lang=lang, source=src)
                    if res:
                        return res
                    else:
                        return src
                finally:
                    if cr: cr.close()

            def _(src):
                return tr(src, 'code')

            try:
                if not pooler.get_pool(dbname)._ready:
                    raise except_osv('Database not ready', 'Currently, this database is not fully loaded and can not be used.')
                return f(self, dbname, *args, **kwargs)
            except orm.except_orm, inst:
                if inst.name == 'AccessError':
                    self.logger.debug("AccessError", exc_info=True)
                self.abortResponse(1, inst.name, 'warning', inst.value)
            except except_osv, inst:
                self.abortResponse(1, inst.name, inst.exc_type, inst.value)
            except IntegrityError, inst:
                osv_pool = pooler.get_pool(dbname)
                for key in osv_pool._sql_error.keys():
                    if key in inst[0]:
                        self.abortResponse(1, _('Constraint Error'), 'warning',
                                        tr(osv_pool._sql_error[key], 'sql_constraint') or inst[0])
                if inst.pgcode in (errorcodes.NOT_NULL_VIOLATION, errorcodes.FOREIGN_KEY_VIOLATION, errorcodes.RESTRICT_VIOLATION):
                    msg = inst.pgerror + '\n'
                    msg += _('The operation cannot be completed, probably due to the following:\n' \
                          '- deletion: you may be trying to delete a record while other records still reference it\n' \
                          '- creation/update: a mandatory field is not correctly set' )
                    self.logger.debug("IntegrityError", exc_info=False)
                    try:
                        if '"public".' in inst.pgerror:
                            context = inst.pgerror.split('"public".')[1]
                            model_name = table = context.split('"')[1]
                            model = table.replace("_",".")
                            model_obj = osv_pool.get(model)
                            if model_obj:
                                model_name = model_obj._description or model_obj._name
                            msg += _('\n\n[object with reference: %s - %s]') % (model_name, model)
                    except Exception:
                        pass
                    self.abortResponse(1, _('Integrity Error'), 'warning', msg)
                else:
                    self.abortResponse(1, _('Integrity Error'), 'warning', inst[0])
            except Exception:
                self.logger.exception("Uncaught exception")
                raise

        return wrapper

    def execute_cr(self, cr, uid, obj, method, *args, **kw):
        object = pooler.get_pool(cr.dbname).get(obj)
        if not object:
            raise except_osv('Object Error', 'Object %s doesn\'t exist' % str(obj))
        try:
            return getattr(object, method)(cr, uid, *args, **kw)
        except TypeError:
            try:
                import inspect
                fn = getattr(object, method)
                __fn_name = method
                __fn_file = inspect.getfile(fn)
                tb_s = "Function %s from file %s" %( __fn_name, __fn_file)
            except Exception:
                tb_s = "Object: %s Function: %s\n" % (object, getattr(object, method))
            self.logger.exception(tb_s)
            raise

    @check
    def execute(self, db, uid, obj, method, *args, **kw):
        cr = pooler.get_db(db).cursor()
        try:
            try:
                if method.startswith('_'):
                    raise except_osv('Access Denied', 'Private methods (such as %s) cannot be called remotely.' % (method,))
                res = self.execute_cr(cr, uid, obj, method, *args, **kw)
                if res is None:
                    self.logger.warning('Method %s.%s can not return a None value (crash in XML-RPC)' % (obj, method))
                cr.commit()
            except Exception:
                cr.rollback()
                raise
        finally:
            cr.close()
        return res

    def exec_workflow_cr(self, cr, uid, obj, method, *args):
        wf_service = netsvc.LocalService("workflow")
        return wf_service.trg_validate(uid, obj, args[0], method, cr)

    @check
    def exec_workflow(self, db, uid, obj, method, *args):
        cr = pooler.get_db(db).cursor()
        try:
            try:
                res = self.exec_workflow_cr(cr, uid, obj, method, *args)
                cr.commit()
            except Exception:
                cr.rollback()
                raise
        finally:
            cr.close()
        return res

    def set_debug(self, db, obj, do_debug=True):
        object = pooler.get_pool(db).get(obj)
        if not object:
            raise except_osv('Object Error', 'Object %s doesn\'t exist' % str(obj))
        try:
            object._debug = do_debug
            return True
        except Exception:
            raise

    def obj_list(self):
        return []

object_proxy()

class osv_pool(object):
    def __init__(self):
        self._ready = False
        self.obj_pool = {}
        self.module_object_list = {}
        self.created = []
        self._sql_error = {}
        self._store_function = {}
        self._init = True
        self._init_parent = {}
        self.logger = logging.getLogger("pool")

    def init_set(self, cr, mode):
        different = mode != self._init
        if different:
            if mode:
                self._init_parent = {}
            if not mode:
                for o in self._init_parent:
                    self.get(o)._parent_store_compute(cr)
            self._init = mode

        self._ready = True
        return different

    def obj_list(self):
        return self.obj_pool.keys()

    # adds a new object instance to the object pool.
    # if it already existed, the instance is replaced
    def add(self, name, obj_inst):
        assert isinstance(name, basestring)
        if name in self.obj_pool:
            del self.obj_pool[name]
        self.obj_pool[name] = obj_inst

        module = str(obj_inst.__class__)[6:]
        module = module[:len(module)-1]
        module = module.split('.')[0][2:]
        self.module_object_list.setdefault(module, []).append(obj_inst)

    # Return None if object does not exist
    def get(self, name):
        if not name:
            return None
        assert isinstance(name, basestring), repr(name)
        obj = self.obj_pool.get(name, None)
        if not obj:
            self.logger.warning("Object %s not found by pooler!", name)
        return obj

    #TODO: pass a list of modules to load
    def instanciate(self, module, cr):
        res = []
        class_list = module_class_list.get(module, [])
        for klass in class_list:
            res.append(klass.createInstance(self, module, cr))
        return res

class osv_base(object):
    def __init__(self, pool, cr):
        pool.add(self._name, self)
        self.pool = pool
        super(osv_base, self).__init__(cr)

    def __new__(cls):
        module = str(cls)[6:]
        module = module[:len(module)-1]
        module = module.split('.')[0][2:]
        if not hasattr(cls, '_module'):
            cls._module = module
        module_class_list.setdefault(cls._module, []).append(cls)
        class_pool[cls._name] = cls
        if module not in module_list:
            module_list.append(cls._module)
        return None

class osv_memory(osv_base, orm.orm_memory):
    #
    # Goal: try to apply inheritancy at the instanciation level and
    #       put objects in the pool var
    #
    def createInstance(cls, pool, module, cr):
        parent_names = getattr(cls, '_inherit', None)
        if parent_names:
            if isinstance(parent_names, (str, unicode)):
                name = cls._name or parent_names
                parent_names = [parent_names]
            else:
                name = cls._name
            if not name:
                raise TypeError('_name is mandatory in case of multiple inheritance')

            for parent_name in ((type(parent_names)==list) and parent_names or [parent_names]):
                parent_class = pool.get(parent_name).__class__
                assert pool.get(parent_name), "parent class %s does not exist in module %s !" % (parent_name, module)
                nattr = {}
                for s in ('_columns', '_defaults', '_virtuals'):
                    new = copy.copy(getattr(pool.get(parent_name), s))
                    if hasattr(new, 'update'):
                        new.update(cls.__dict__.get(s, {}))
                    else:
                        new.extend(cls.__dict__.get(s, []))
                    nattr[s] = new
                cls = type(name, (cls, parent_class), nattr)

        obj = object.__new__(cls)
        obj.__init__(pool, cr)
        return obj
    createInstance = classmethod(createInstance)

class osv(osv_base, orm.orm):
    #
    # Goal: try to apply inheritancy at the instanciation level and
    #       put objects in the pool var
    #
    def createInstance(cls, pool, module, cr):
        parent_names = getattr(cls, '_inherit', None)
        if parent_names:
            if isinstance(parent_names, (str, unicode)):
                name = cls._name or parent_names
                parent_names = [parent_names]
            else:
                name = cls._name
            if not name:
                raise TypeError('_name is mandatory in case of multiple inheritance')

            for parent_name in ((type(parent_names)==list) and parent_names or [parent_names]):
                parent_class = pool.get(parent_name).__class__
                assert pool.get(parent_name), "parent class %s does not exist in module %s !" % (parent_name, module)
                nattr = {}
                for s in ('_columns', '_defaults', '_inherits', '_constraints', '_sql_constraints', '_virtuals', '_column_stats'):
                    new = copy.copy(getattr(pool.get(parent_name), s))
                    if hasattr(new, 'update'):
                        new.update(cls.__dict__.get(s, {}))
                    else:
                        if s=='_constraints':
                            for c in cls.__dict__.get(s, []):
                                exist = False
                                for c2 in range(len(new)):
                                     #For _constraints, we should check field and methods as well
                                     if new[c2][2]==c[2] and new[c2][0]==c[0]:
                                        new[c2] = c
                                        exist = True
                                        break
                                if not exist:
                                    new.append(c)
                        else:
                            new.extend(cls.__dict__.get(s, []))
                    nattr[s] = new
                cls = type(name, (cls, parent_class), nattr)
        obj = object.__new__(cls)
        obj.__init__(pool, cr)
        return obj
    createInstance = classmethod(createInstance)

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

<commit_msg>OSV: override inherited constraints, when fn name equals [Bug 700451]<commit_after># -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

#
# OSV: Objects Services
#

import orm
import logging
import netsvc
import pooler
import copy
from psycopg2 import IntegrityError, errorcodes
from tools.func import wraps
from tools.translate import translate

module_list = []
module_class_list = {}
class_pool = {}

class except_osv(Exception):
    def __init__(self, name, value, exc_type='warning'):
        self.name = name
        self.exc_type = exc_type
        self.value = value
        self.args = (exc_type, name)

class object_proxy(netsvc.Service):
    def __init__(self):
        self.logger = logging.getLogger('web-services')
        netsvc.Service.__init__(self, 'object_proxy', audience='')
        self.exportMethod(self.exec_workflow)
        self.exportMethod(self.execute)
        self.exportMethod(self.set_debug)
        self.exportMethod(self.obj_list)

    def check(f):
        @wraps(f)
        def wrapper(self, dbname, *args, **kwargs):
            """ Wraps around OSV functions and normalises a few exceptions
            """

            def tr(src, ttype):
                # We try to do the same as the _(), but without the frame
                # inspection, since we aready are wrapping an osv function
                # trans_obj = self.get('ir.translation') cannot work yet :(
                ctx = {}
                if not kwargs:
                    if args and isinstance(args[-1], dict):
                        ctx = args[-1]
                elif isinstance(kwargs, dict):
                    ctx = kwargs.get('context', {})

                uid = 1
                if args and isinstance(args[0], (long, int)):
                    uid = args[0]

                lang = ctx and ctx.get('lang')
                if not (lang or hasattr(src, '__call__')):
                    return src

                # We open a *new* cursor here, one reason is that failed SQL
                # queries (as in IntegrityError) will invalidate the current one.
                cr = False

                if hasattr(src, '__call__'):
                    # callable. We need to find the right parameters to call
                    # the  orm._sql_message(self, cr, uid, ids, context) function,
                    # or we skip..
                    # our signature is f(osv_pool, dbname [,uid, obj, method, args])
                    try:
                        if args and len(args) > 1:
                            obj = self.get(args[1])
                            if len(args) > 3 and isinstance(args[3], (long, int, list)):
                                ids = args[3]
                            else:
                                ids = []
                        cr = pooler.get_db_only(dbname).cursor()
                        return src(obj, cr, uid, ids, context=(ctx or {}))
                    except Exception:
                        pass
                    finally:
                        if cr: cr.close()

                    return False # so that the original SQL error will
                                 # be returned, it is the best we have.

                try:
                    cr = pooler.get_db_only(dbname).cursor()
                    res = translate(cr, name=False, source_type=ttype,
                                    lang=lang, source=src)
                    if res:
                        return res
                    else:
                        return src
                finally:
                    if cr: cr.close()

            def _(src):
                return tr(src, 'code')

            try:
                if not pooler.get_pool(dbname)._ready:
                    raise except_osv('Database not ready', 'Currently, this database is not fully loaded and can not be used.')
                return f(self, dbname, *args, **kwargs)
            except orm.except_orm, inst:
                if inst.name == 'AccessError':
                    self.logger.debug("AccessError", exc_info=True)
                self.abortResponse(1, inst.name, 'warning', inst.value)
            except except_osv, inst:
                self.abortResponse(1, inst.name, inst.exc_type, inst.value)
            except IntegrityError, inst:
                osv_pool = pooler.get_pool(dbname)
                for key in osv_pool._sql_error.keys():
                    if key in inst[0]:
                        self.abortResponse(1, _('Constraint Error'), 'warning',
                                        tr(osv_pool._sql_error[key], 'sql_constraint') or inst[0])
                if inst.pgcode in (errorcodes.NOT_NULL_VIOLATION, errorcodes.FOREIGN_KEY_VIOLATION, errorcodes.RESTRICT_VIOLATION):
                    msg = inst.pgerror + '\n'
                    msg += _('The operation cannot be completed, probably due to the following:\n' \
                          '- deletion: you may be trying to delete a record while other records still reference it\n' \
                          '- creation/update: a mandatory field is not correctly set' )
                    self.logger.debug("IntegrityError", exc_info=False)
                    try:
                        if '"public".' in inst.pgerror:
                            context = inst.pgerror.split('"public".')[1]
                            model_name = table = context.split('"')[1]
                            model = table.replace("_",".")
                            model_obj = osv_pool.get(model)
                            if model_obj:
                                model_name = model_obj._description or model_obj._name
                            msg += _('\n\n[object with reference: %s - %s]') % (model_name, model)
                    except Exception:
                        pass
                    self.abortResponse(1, _('Integrity Error'), 'warning', msg)
                else:
                    self.abortResponse(1, _('Integrity Error'), 'warning', inst[0])
            except Exception:
                self.logger.exception("Uncaught exception")
                raise

        return wrapper

    def execute_cr(self, cr, uid, obj, method, *args, **kw):
        object = pooler.get_pool(cr.dbname).get(obj)
        if not object:
            raise except_osv('Object Error', 'Object %s doesn\'t exist' % str(obj))
        try:
            return getattr(object, method)(cr, uid, *args, **kw)
        except TypeError:
            try:
                import inspect
                fn = getattr(object, method)
                __fn_name = method
                __fn_file = inspect.getfile(fn)
                tb_s = "Function %s from file %s" %( __fn_name, __fn_file)
            except Exception:
                tb_s = "Object: %s Function: %s\n" % (object, getattr(object, method))
            self.logger.exception(tb_s)
            raise

    @check
    def execute(self, db, uid, obj, method, *args, **kw):
        cr = pooler.get_db(db).cursor()
        try:
            try:
                if method.startswith('_'):
                    raise except_osv('Access Denied', 'Private methods (such as %s) cannot be called remotely.' % (method,))
                res = self.execute_cr(cr, uid, obj, method, *args, **kw)
                if res is None:
                    self.logger.warning('Method %s.%s can not return a None value (crash in XML-RPC)' % (obj, method))
                cr.commit()
            except Exception:
                cr.rollback()
                raise
        finally:
            cr.close()
        return res

    def exec_workflow_cr(self, cr, uid, obj, method, *args):
        wf_service = netsvc.LocalService("workflow")
        return wf_service.trg_validate(uid, obj, args[0], method, cr)

    @check
    def exec_workflow(self, db, uid, obj, method, *args):
        cr = pooler.get_db(db).cursor()
        try:
            try:
                res = self.exec_workflow_cr(cr, uid, obj, method, *args)
                cr.commit()
            except Exception:
                cr.rollback()
                raise
        finally:
            cr.close()
        return res

    def set_debug(self, db, obj, do_debug=True):
        object = pooler.get_pool(db).get(obj)
        if not object:
            raise except_osv('Object Error', 'Object %s doesn\'t exist' % str(obj))
        try:
            object._debug = do_debug
            return True
        except Exception:
            raise

    def obj_list(self):
        return []

object_proxy()

class osv_pool(object):
    def __init__(self):
        self._ready = False
        self.obj_pool = {}
        self.module_object_list = {}
        self.created = []
        self._sql_error = {}
        self._store_function = {}
        self._init = True
        self._init_parent = {}
        self.logger = logging.getLogger("pool")

    def init_set(self, cr, mode):
        different = mode != self._init
        if different:
            if mode:
                self._init_parent = {}
            if not mode:
                for o in self._init_parent:
                    self.get(o)._parent_store_compute(cr)
            self._init = mode

        self._ready = True
        return different

    def obj_list(self):
        return self.obj_pool.keys()

    # adds a new object instance to the object pool.
    # if it already existed, the instance is replaced
    def add(self, name, obj_inst):
        assert isinstance(name, basestring)
        if name in self.obj_pool:
            del self.obj_pool[name]
        self.obj_pool[name] = obj_inst

        module = str(obj_inst.__class__)[6:]
        module = module[:len(module)-1]
        module = module.split('.')[0][2:]
        self.module_object_list.setdefault(module, []).append(obj_inst)

    # Return None if object does not exist
    def get(self, name):
        if not name:
            return None
        assert isinstance(name, basestring), repr(name)
        obj = self.obj_pool.get(name, None)
        if not obj:
            self.logger.warning("Object %s not found by pooler!", name)
        return obj

    #TODO: pass a list of modules to load
    def instanciate(self, module, cr):
        res = []
        class_list = module_class_list.get(module, [])
        for klass in class_list:
            res.append(klass.createInstance(self, module, cr))
        return res

class osv_base(object):
    def __init__(self, pool, cr):
        pool.add(self._name, self)
        self.pool = pool
        super(osv_base, self).__init__(cr)

    def __new__(cls):
        module = str(cls)[6:]
        module = module[:len(module)-1]
        module = module.split('.')[0][2:]
        if not hasattr(cls, '_module'):
            cls._module = module
        module_class_list.setdefault(cls._module, []).append(cls)
        class_pool[cls._name] = cls
        if module not in module_list:
            module_list.append(cls._module)
        return None

class osv_memory(osv_base, orm.orm_memory):
    #
    # Goal: try to apply inheritancy at the instanciation level and
    #       put objects in the pool var
    #
    def createInstance(cls, pool, module, cr):
        parent_names = getattr(cls, '_inherit', None)
        if parent_names:
            if isinstance(parent_names, (str, unicode)):
                name = cls._name or parent_names
                parent_names = [parent_names]
            else:
                name = cls._name
            if not name:
                raise TypeError('_name is mandatory in case of multiple inheritance')

            for parent_name in ((type(parent_names)==list) and parent_names or [parent_names]):
                parent_class = pool.get(parent_name).__class__
                assert pool.get(parent_name), "parent class %s does not exist in module %s !" % (parent_name, module)
                nattr = {}
                for s in ('_columns', '_defaults', '_virtuals'):
                    new = copy.copy(getattr(pool.get(parent_name), s))
                    if hasattr(new, 'update'):
                        new.update(cls.__dict__.get(s, {}))
                    else:
                        new.extend(cls.__dict__.get(s, []))
                    nattr[s] = new
                cls = type(name, (cls, parent_class), nattr)

        obj = object.__new__(cls)
        obj.__init__(pool, cr)
        return obj
    createInstance = classmethod(createInstance)

class osv(osv_base, orm.orm):
    #
    # Goal: try to apply inheritancy at the instanciation level and
    #       put objects in the pool var
    #
    def createInstance(cls, pool, module, cr):
        parent_names = getattr(cls, '_inherit', None)
        if parent_names:
            if isinstance(parent_names, (str, unicode)):
                name = cls._name or parent_names
                parent_names = [parent_names]
            else:
                name = cls._name
            if not name:
                raise TypeError('_name is mandatory in case of multiple inheritance')

            for parent_name in ((type(parent_names)==list) and parent_names or [parent_names]):
                parent_class = pool.get(parent_name).__class__
                assert pool.get(parent_name), "parent class %s does not exist in module %s !" % (parent_name, module)
                nattr = {}
                for s in ('_columns', '_defaults', '_inherits', '_constraints', '_sql_constraints', '_virtuals', '_column_stats'):
                    new = copy.copy(getattr(pool.get(parent_name), s))
                    if hasattr(new, 'update'):
                        new.update(cls.__dict__.get(s, {}))
                    else:
                        if s=='_constraints':
                            for c in cls.__dict__.get(s, []):
                                exist = False
                                for c2 in range(len(new)):
                                     #For _constraints, we should check field and methods as well
                                     if new[c2][2]==c[2] and (new[c2][0] == c[0] \
                                            or getattr(new[c2][0],'__name__', True) == \
                                                getattr(c[0],'__name__', False)):
                                        # If new class defines a constraint with
                                        # same function name, we let it override
                                        # the old one.
                                        new[c2] = c
                                        exist = True
                                        break
                                if not exist:
                                    new.append(c)
                        else:
                            new.extend(cls.__dict__.get(s, []))
                    nattr[s] = new
                cls = type(name, (cls, parent_class), nattr)
        obj = object.__new__(cls)
        obj.__init__(pool, cr)
        return obj
    createInstance = classmethod(createInstance)

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

<|endoftext|>


<commit_before>#
# Copyright (c) 2014, Arista Networks, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#   Redistributions of source code must retain the above copyright notice,
#   this list of conditions and the following disclaimer.
#
#   Redistributions in binary form must reproduce the above copyright
#   notice, this list of conditions and the following disclaimer in the
#   documentation and/or other materials provided with the distribution.
#
#   Neither the name of Arista Networks nor the names of its
#   contributors may be used to endorse or promote products derived from
#   this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
import collections

from pyeapi.utils import load_module

class Node(object):

    def __init__(self, connection):
        self._connection = connection

    @property
    def connection(self):
        return self._connection

    def __str__(self):
        return 'Node(uri=%s)' % self.connection.uri

    def __repr__(self):
        return 'Node(%s)' % repr(self.connection)

    def config(self, commands):
        """Convenience method that sends commands to config mode
        """
        if isinstance(commands, basestring):
            commands = [commands]

        if not isinstance(commands, collections.Iterable):
            raise TypeError('commands must be an iterable object')

        # push the configure command onto the command stack
        commands.insert(0, 'configure')
        response = self.enable(commands)

        # pop the configure command output off the stack
        response.pop(0)

        return response

    def enable(self, commands, serialization='json'):
        """Convenience method that sends commands to enable mode
        """
        if isinstance(commands, basestring):
            commands = [commands]

        if not isinstance(commands, collections.Iterable):
            raise TypeError('commands must be an iterable object')

        response = self._connection.execute(commands, serialization)
        return response['result']

    def resource(self, name):
        """Loads the resource identified by name
        """
        module = load_module('pyeapi.resources.%s' % name)
        return module.instance(self)

    def get_config(self, config='running-config', params=None):
        """Convenience method that returns the running-config as a dict
        """
        command = 'show %s' % config
        if params:
            command += ' %s' % params
        result = self.enable(command, 'text')
        return str(result[0]['output']).strip()

<commit_msg>finishes the refactor from resources to api<commit_after>#
# Copyright (c) 2014, Arista Networks, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#   Redistributions of source code must retain the above copyright notice,
#   this list of conditions and the following disclaimer.
#
#   Redistributions in binary form must reproduce the above copyright
#   notice, this list of conditions and the following disclaimer in the
#   documentation and/or other materials provided with the distribution.
#
#   Neither the name of Arista Networks nor the names of its
#   contributors may be used to endorse or promote products derived from
#   this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
import collections

from pyeapi.utils import load_module

class Node(object):

    def __init__(self, connection):
        self._connection = connection

    @property
    def connection(self):
        return self._connection

    def __str__(self):
        return 'Node(uri=%s)' % self.connection.uri

    def __repr__(self):
        return 'Node(%s)' % repr(self.connection)

    def config(self, commands):
        """Convenience method that sends commands to config mode
        """
        if isinstance(commands, basestring):
            commands = [commands]

        if not isinstance(commands, collections.Iterable):
            raise TypeError('commands must be an iterable object')

        # push the configure command onto the command stack
        commands.insert(0, 'configure')
        response = self.enable(commands)

        # pop the configure command output off the stack
        response.pop(0)

        return response

    def enable(self, commands, serialization='json'):
        """Convenience method that sends commands to enable mode
        """
        if isinstance(commands, basestring):
            commands = [commands]

        if not isinstance(commands, collections.Iterable):
            raise TypeError('commands must be an iterable object')

        response = self._connection.execute(commands, serialization)
        return response['result']

    def api(self, name, namespace='pyeapi.api'):
        """Loads the resource identified by name
        """
        module = load_module('{}.{}'.format(namespace, name))
        return module.instance(self)

    def get_config(self, config='running-config', params=None):
        """Convenience method that returns the running-config as a dict
        """
        command = 'show %s' % config
        if params:
            command += ' %s' % params
        result = self.enable(command, 'text')
        return str(result[0]['output']).strip()

<|endoftext|>


<commit_before># -*- encoding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
#    $Id$
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

#
# OSV: Objects Services
#

import orm
import netsvc
import pooler
import copy
import sys

from psycopg2 import IntegrityError
from netsvc import Logger, LOG_ERROR
from tools.misc import UpdateableDict

module_list = []
module_class_list = {}
class_pool = {}

class except_osv(Exception):
    def __init__(self, name, value, exc_type='warning'):
        self.name = name
        self.exc_type = exc_type
        self.value = value
        self.args = (exc_type, name)

class osv_pool(netsvc.Service):

    def __init__(self):
        self.obj_pool = {}
        self.module_object_list = {}
        self.created = []
        self._sql_error = {}
        self._store_function = {}
        self._init = True
        self._init_parent = {}
        netsvc.Service.__init__(self, 'object_proxy', audience='')
        self.joinGroup('web-services')
        self.exportMethod(self.exportedMethods)
        self.exportMethod(self.obj_list)
        self.exportMethod(self.exec_workflow)
        self.exportMethod(self.execute)
        self.exportMethod(self.execute_cr)

    def init_set(self, cr, mode):
        if mode <> self._init:
            if mode:
                self._init_parent = {}
            if not mode:
                for o in self._init_parent:
                    self.get(o)._parent_store_compute(cr)
            self._init = mode
            return True
        return False

    def execute_cr(self, cr, uid, obj, method, *args, **kw):
        try:
            object = pooler.get_pool(cr.dbname).get(obj)
            if not object:
                self.abortResponse(1, 'Object Error', 'warning',
                'Object %s doesn\'t exist' % str(obj))
            return getattr(object, method)(cr, uid, *args, **kw)
        except orm.except_orm, inst:
            self.abortResponse(1, inst.name, 'warning', inst.value)
        except except_osv, inst:
            self.abortResponse(1, inst.name, inst.exc_type, inst.value)
        except IntegrityError, inst:
            for key in self._sql_error.keys():
                if key in inst[0]:
                    self.abortResponse(1, 'Constraint Error', 'warning', self._sql_error[key])
            self.abortResponse(1, 'Integrity Error', 'warning', inst[0])
        except Exception, e:
            import traceback
            tb_s = reduce(lambda x, y: x+y, traceback.format_exception( sys.exc_type, sys.exc_value, sys.exc_traceback))
            logger = Logger()
            for idx, s in enumerate(tb_s.split('\n')):
                logger.notifyChannel("web-services", LOG_ERROR, '[%2d]: %s' % (idx, s,))
            raise

    def execute(self, db, uid, obj, method, *args, **kw):
        db, pool = pooler.get_db_and_pool(db)
        cr = db.cursor()
        try:
            try:
                res = pool.execute_cr(cr, uid, obj, method, *args, **kw)
                cr.commit()
            except Exception:
                cr.rollback()
                raise
        finally:
            cr.close()
        return res

    def exec_workflow_cr(self, cr, uid, obj, method, *args):
        wf_service = netsvc.LocalService("workflow")
        return wf_service.trg_validate(uid, obj, args[0], method, cr)

    def exec_workflow(self, db, uid, obj, method, *args):
        cr = pooler.get_db(db).cursor()
        try:
            try:
                res = self.exec_workflow_cr(cr, uid, obj, method, *args)
                cr.commit()
            except orm.except_orm, inst:
                cr.rollback()
                self.abortResponse(1, inst.name, 'warning', inst.value)
            except except_osv, inst:
                cr.rollback()
                self.abortResponse(1, inst.name, inst[0], inst.value)
        finally:
            cr.close()
        return res

    def obj_list(self):
        return self.obj_pool.keys()

    # adds a new object instance to the object pool.
    # if it already existed, the instance is replaced
    def add(self, name, obj_inst):
        if name in self.obj_pool:
            del self.obj_pool[name]
        self.obj_pool[name] = obj_inst

        module = str(obj_inst.__class__)[6:]
        module = module[:len(module)-1]
        module = module.split('.')[0][2:]
        self.module_object_list.setdefault(module, []).append(obj_inst)

    # Return False if object does not exist
    def get(self, name):
        obj = self.obj_pool.get(name, None)
        return obj

    #TODO: pass a list of modules to load
    def instanciate(self, module, cr):
        res = []
        class_list = module_class_list.get(module, [])
        for klass in class_list:
            res.append(klass.createInstance(self, module, cr))
        return res

class osv_memory(orm.orm_memory):
    #__metaclass__ = inheritor
    def __new__(cls):
        module = str(cls)[6:]
        module = module[:len(module)-1]
        module = module.split('.')[0][2:]
        if not hasattr(cls, '_module'):
            cls._module = module
        module_class_list.setdefault(cls._module, []).append(cls)
        class_pool[cls._name] = cls
        if module not in module_list:
            module_list.append(cls._module)
        return None

    #
    # Goal: try to apply inheritancy at the instanciation level and
    #       put objects in the pool var
    #
    def createInstance(cls, pool, module, cr):
        name = hasattr(cls, '_name') and cls._name or cls._inherit
        parent_name = hasattr(cls, '_inherit') and cls._inherit
        if parent_name:
            print 'Inherit not supported in osv_memory object !'
        obj = object.__new__(cls)
        obj.__init__(pool, cr)
        return obj
    createInstance = classmethod(createInstance)

    def __init__(self, pool, cr):
        pool.add(self._name, self)
        self.pool = pool
        orm.orm_memory.__init__(self, cr)

class osv(orm.orm):
    #__metaclass__ = inheritor
    def __new__(cls):
        module = str(cls)[6:]
        module = module[:len(module)-1]
        module = module.split('.')[0][2:]
        if not hasattr(cls, '_module'):
            cls._module = module
        module_class_list.setdefault(cls._module, []).append(cls)
        class_pool[cls._name] = cls
        if module not in module_list:
            module_list.append(cls._module)
        return None

    #
    # Goal: try to apply inheritancy at the instanciation level and
    #       put objects in the pool var
    #
    def createInstance(cls, pool, module, cr):
        parent_name = hasattr(cls, '_inherit') and cls._inherit
        if parent_name:
            parent_class = pool.get(parent_name).__class__
            assert pool.get(parent_name), "parent class %s does not exist in module %s !" % (parent_name, module)
            nattr = {}
            for s in ('_columns', '_defaults', '_inherits', '_constraints', '_sql_constraints'):
                new = copy.copy(getattr(pool.get(parent_name), s))
                if hasattr(new, 'update'):
                    new.update(cls.__dict__.get(s, {}))
                else:
                    if s=='_constraints':
                        for c in cls.__dict__.get(s, []):
                            exist = False
                            for c2 in range(len(new)):
                                if new[c2][2]==c[2]:
                                    new[c2] = c
                                    exist = True
                                    break
                            if not exist:
                                new.append(c)
                    else:
                        new.extend(cls.__dict__.get(s, []))
                nattr[s] = new
            name = hasattr(cls, '_name') and cls._name or cls._inherit
            cls = type(name, (cls, parent_class), nattr)
        obj = object.__new__(cls)
        obj.__init__(pool, cr)
        return obj
    createInstance = classmethod(createInstance)

    def __init__(self, pool, cr):
        pool.add(self._name, self)
        self.pool = pool
        orm.orm.__init__(self, cr)

class Cacheable(object):

    _cache = UpdateableDict()

    def add(self, key, value):
        self._cache[key] = value

    def invalidate(self, key):
        del self._cache[key]

    def get(self, key):
        try:
            w = self._cache[key]
            return w
        except KeyError:
            return None

    def clear(self):
        self._cache.clear()
        self._items = []

def filter_dict(d, fields):
    res = {}
    for f in fields + ['id']:
        if f in d:
            res[f] = d[f]
    return res

class cacheable_osv(osv, Cacheable):

    _relevant = ['lang']

    def __init__(self):
        super(cacheable_osv, self).__init__()

    def read(self, cr, user, ids, fields=None, context=None, load='_classic_read'):
        if not fields:
            fields = []
        if not context:
            context = {}
        fields = fields or self._columns.keys()
        ctx = [context.get(x, False) for x in self._relevant]
        result, tofetch = [], []
        for id in ids:
            res = self.get(self._name, id, ctx)
            if not res:
                tofetch.append(id)
            else:
                result.append(filter_dict(res, fields))

        # gen the list of "local" (ie not inherited) fields which are classic or many2one
        nfields = filter(lambda x: x[1]._classic_write, self._columns.items())
        # gen the list of inherited fields
        inherits = map(lambda x: (x[0], x[1][2]), self._inherit_fields.items())
        # complete the field list with the inherited fields which are classic or many2one
        nfields += filter(lambda x: x[1]._classic_write, inherits)
        nfields = [x[0] for x in nfields]

        res = super(cacheable_osv, self).read(cr, user, tofetch, nfields, context, load)
        for r in res:
            self.add((self._name, r['id'], ctx), r)
            result.append(filter_dict(r, fields))

        # Appel de fonction si necessaire
        tofetch = []
        for f in fields:
            if f not in nfields:
                tofetch.append(f)
        for f in tofetch:
            fvals = self._columns[f].get(cr, self, ids, f, user, context=context)
            for r in result:
                r[f] = fvals[r['id']]

        # TODO: tri par self._order !!
        return result

    def invalidate(self, key):
        del self._cache[key[0]][key[1]]

    def write(self, cr, user, ids, values, context=None):
        if not context:
            context = {}
        for id in ids:
            self.invalidate((self._name, id))
        return super(cacheable_osv, self).write(cr, user, ids, values, context)

    def unlink(self, cr, user, ids):
        self.clear()
        return super(cacheable_osv, self).unlink(cr, user, ids)

#cacheable_osv = osv

#class FakePool(object):
#   def __init__(self, module):
#       self.preferred_module = module

#   def get(self, name):
#       localpool = module_objects_dict.get(self.preferred_module, {'dict': {}})['dict']
#       if name in localpool:
#           obj = localpool[name]
#       else:
#           obj = pooler.get_pool(cr.dbname).get(name)
#       return obj

#       fake_pool = self
#       class fake_class(obj.__class__):
#           def __init__(self):
#               super(fake_class, self).__init__()
#               self.pool = fake_pool

#       return fake_class()

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

<commit_msg>[IMP] Update the logging of the error in the osv module<commit_after># -*- encoding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
#    $Id$
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

#
# OSV: Objects Services
#

import orm
import netsvc
import pooler
import copy
import sys

from psycopg2 import IntegrityError
from netsvc import Logger, LOG_ERROR
from tools.misc import UpdateableDict

module_list = []
module_class_list = {}
class_pool = {}

class except_osv(Exception):
    def __init__(self, name, value, exc_type='warning'):
        self.name = name
        self.exc_type = exc_type
        self.value = value
        self.args = (exc_type, name)

class osv_pool(netsvc.Service):

    def __init__(self):
        self.obj_pool = {}
        self.module_object_list = {}
        self.created = []
        self._sql_error = {}
        self._store_function = {}
        self._init = True
        self._init_parent = {}
        netsvc.Service.__init__(self, 'object_proxy', audience='')
        self.joinGroup('web-services')
        self.exportMethod(self.exportedMethods)
        self.exportMethod(self.obj_list)
        self.exportMethod(self.exec_workflow)
        self.exportMethod(self.execute)
        self.exportMethod(self.execute_cr)

    def init_set(self, cr, mode):
        if mode <> self._init:
            if mode:
                self._init_parent = {}
            if not mode:
                for o in self._init_parent:
                    self.get(o)._parent_store_compute(cr)
            self._init = mode
            return True
        return False

    def execute_cr(self, cr, uid, obj, method, *args, **kw):
        try:
            object = pooler.get_pool(cr.dbname).get(obj)
            if not object:
                self.abortResponse(1, 'Object Error', 'warning',
                'Object %s doesn\'t exist' % str(obj))
            return getattr(object, method)(cr, uid, *args, **kw)
        except orm.except_orm, inst:
            self.abortResponse(1, inst.name, 'warning', inst.value)
        except except_osv, inst:
            self.abortResponse(1, inst.name, inst.exc_type, inst.value)
        except IntegrityError, inst:
            for key in self._sql_error.keys():
                if key in inst[0]:
                    self.abortResponse(1, 'Constraint Error', 'warning', self._sql_error[key])
            self.abortResponse(1, 'Integrity Error', 'warning', inst[0])
        except Exception, e:
            import traceback
            tb_s = reduce(lambda x, y: x+y, traceback.format_exception( sys.exc_type, sys.exc_value, sys.exc_traceback))
            logger = Logger()
            logger.notifyChannel('web-services', LOG_ERROR, tb_s)
            raise

    def execute(self, db, uid, obj, method, *args, **kw):
        db, pool = pooler.get_db_and_pool(db)
        cr = db.cursor()
        try:
            try:
                res = pool.execute_cr(cr, uid, obj, method, *args, **kw)
                cr.commit()
            except Exception:
                cr.rollback()
                raise
        finally:
            cr.close()
        return res

    def exec_workflow_cr(self, cr, uid, obj, method, *args):
        wf_service = netsvc.LocalService("workflow")
        return wf_service.trg_validate(uid, obj, args[0], method, cr)

    def exec_workflow(self, db, uid, obj, method, *args):
        cr = pooler.get_db(db).cursor()
        try:
            try:
                res = self.exec_workflow_cr(cr, uid, obj, method, *args)
                cr.commit()
            except orm.except_orm, inst:
                cr.rollback()
                self.abortResponse(1, inst.name, 'warning', inst.value)
            except except_osv, inst:
                cr.rollback()
                self.abortResponse(1, inst.name, inst[0], inst.value)
        finally:
            cr.close()
        return res

    def obj_list(self):
        return self.obj_pool.keys()

    # adds a new object instance to the object pool.
    # if it already existed, the instance is replaced
    def add(self, name, obj_inst):
        if name in self.obj_pool:
            del self.obj_pool[name]
        self.obj_pool[name] = obj_inst

        module = str(obj_inst.__class__)[6:]
        module = module[:len(module)-1]
        module = module.split('.')[0][2:]
        self.module_object_list.setdefault(module, []).append(obj_inst)

    # Return False if object does not exist
    def get(self, name):
        obj = self.obj_pool.get(name, None)
        return obj

    #TODO: pass a list of modules to load
    def instanciate(self, module, cr):
        res = []
        class_list = module_class_list.get(module, [])
        for klass in class_list:
            res.append(klass.createInstance(self, module, cr))
        return res

class osv_memory(orm.orm_memory):
    #__metaclass__ = inheritor
    def __new__(cls):
        module = str(cls)[6:]
        module = module[:len(module)-1]
        module = module.split('.')[0][2:]
        if not hasattr(cls, '_module'):
            cls._module = module
        module_class_list.setdefault(cls._module, []).append(cls)
        class_pool[cls._name] = cls
        if module not in module_list:
            module_list.append(cls._module)
        return None

    #
    # Goal: try to apply inheritancy at the instanciation level and
    #       put objects in the pool var
    #
    def createInstance(cls, pool, module, cr):
        name = hasattr(cls, '_name') and cls._name or cls._inherit
        parent_name = hasattr(cls, '_inherit') and cls._inherit
        if parent_name:
            print 'Inherit not supported in osv_memory object !'
        obj = object.__new__(cls)
        obj.__init__(pool, cr)
        return obj
    createInstance = classmethod(createInstance)

    def __init__(self, pool, cr):
        pool.add(self._name, self)
        self.pool = pool
        orm.orm_memory.__init__(self, cr)

class osv(orm.orm):
    #__metaclass__ = inheritor
    def __new__(cls):
        module = str(cls)[6:]
        module = module[:len(module)-1]
        module = module.split('.')[0][2:]
        if not hasattr(cls, '_module'):
            cls._module = module
        module_class_list.setdefault(cls._module, []).append(cls)
        class_pool[cls._name] = cls
        if module not in module_list:
            module_list.append(cls._module)
        return None

    #
    # Goal: try to apply inheritancy at the instanciation level and
    #       put objects in the pool var
    #
    def createInstance(cls, pool, module, cr):
        parent_name = hasattr(cls, '_inherit') and cls._inherit
        if parent_name:
            parent_class = pool.get(parent_name).__class__
            assert pool.get(parent_name), "parent class %s does not exist in module %s !" % (parent_name, module)
            nattr = {}
            for s in ('_columns', '_defaults', '_inherits', '_constraints', '_sql_constraints'):
                new = copy.copy(getattr(pool.get(parent_name), s))
                if hasattr(new, 'update'):
                    new.update(cls.__dict__.get(s, {}))
                else:
                    if s=='_constraints':
                        for c in cls.__dict__.get(s, []):
                            exist = False
                            for c2 in range(len(new)):
                                if new[c2][2]==c[2]:
                                    new[c2] = c
                                    exist = True
                                    break
                            if not exist:
                                new.append(c)
                    else:
                        new.extend(cls.__dict__.get(s, []))
                nattr[s] = new
            name = hasattr(cls, '_name') and cls._name or cls._inherit
            cls = type(name, (cls, parent_class), nattr)
        obj = object.__new__(cls)
        obj.__init__(pool, cr)
        return obj
    createInstance = classmethod(createInstance)

    def __init__(self, pool, cr):
        pool.add(self._name, self)
        self.pool = pool
        orm.orm.__init__(self, cr)

class Cacheable(object):

    _cache = UpdateableDict()

    def add(self, key, value):
        self._cache[key] = value

    def invalidate(self, key):
        del self._cache[key]

    def get(self, key):
        try:
            w = self._cache[key]
            return w
        except KeyError:
            return None

    def clear(self):
        self._cache.clear()
        self._items = []

def filter_dict(d, fields):
    res = {}
    for f in fields + ['id']:
        if f in d:
            res[f] = d[f]
    return res

class cacheable_osv(osv, Cacheable):

    _relevant = ['lang']

    def __init__(self):
        super(cacheable_osv, self).__init__()

    def read(self, cr, user, ids, fields=None, context=None, load='_classic_read'):
        if not fields:
            fields = []
        if not context:
            context = {}
        fields = fields or self._columns.keys()
        ctx = [context.get(x, False) for x in self._relevant]
        result, tofetch = [], []
        for id in ids:
            res = self.get(self._name, id, ctx)
            if not res:
                tofetch.append(id)
            else:
                result.append(filter_dict(res, fields))

        # gen the list of "local" (ie not inherited) fields which are classic or many2one
        nfields = filter(lambda x: x[1]._classic_write, self._columns.items())
        # gen the list of inherited fields
        inherits = map(lambda x: (x[0], x[1][2]), self._inherit_fields.items())
        # complete the field list with the inherited fields which are classic or many2one
        nfields += filter(lambda x: x[1]._classic_write, inherits)
        nfields = [x[0] for x in nfields]

        res = super(cacheable_osv, self).read(cr, user, tofetch, nfields, context, load)
        for r in res:
            self.add((self._name, r['id'], ctx), r)
            result.append(filter_dict(r, fields))

        # Appel de fonction si necessaire
        tofetch = []
        for f in fields:
            if f not in nfields:
                tofetch.append(f)
        for f in tofetch:
            fvals = self._columns[f].get(cr, self, ids, f, user, context=context)
            for r in result:
                r[f] = fvals[r['id']]

        # TODO: tri par self._order !!
        return result

    def invalidate(self, key):
        del self._cache[key[0]][key[1]]

    def write(self, cr, user, ids, values, context=None):
        if not context:
            context = {}
        for id in ids:
            self.invalidate((self._name, id))
        return super(cacheable_osv, self).write(cr, user, ids, values, context)

    def unlink(self, cr, user, ids):
        self.clear()
        return super(cacheable_osv, self).unlink(cr, user, ids)

#cacheable_osv = osv

#class FakePool(object):
#   def __init__(self, module):
#       self.preferred_module = module

#   def get(self, name):
#       localpool = module_objects_dict.get(self.preferred_module, {'dict': {}})['dict']
#       if name in localpool:
#           obj = localpool[name]
#       else:
#           obj = pooler.get_pool(cr.dbname).get(name)
#       return obj

#       fake_pool = self
#       class fake_class(obj.__class__):
#           def __init__(self):
#               super(fake_class, self).__init__()
#               self.pool = fake_pool

#       return fake_class()

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

<|endoftext|>


<commit_before>import requests
import json
import time
import logging
from requests.exceptions import SSLError, Timeout

from .exceptions import (FBException, FBHTTPException, FBJSONException,
    FBConnectionException)

BASE_GRAPH_URL = "https://graph.facebook.com"
BASE_FQL_URL = "https://graph.facebook.com/fql?"
BATCH_QUERY_LIMIT = 50
TIMEOUT = 60.0
REQUESTS_CONFIG = {'max_retries': 2}

log = logging.getLogger(__name__)

def GetRequestFactory(relative_url, **params):
    ''' Returns a properly formed GET request dictionary. '''

    params['method'] = 'GET'
    params['relative_url'] = relative_url

    return params

def _issue_request(method, relative_url, **kwargs):
    """
    Generic method for making requests to the Graph API and deserializing
    the response. Here we aggregate all general error-handling & exception
    catching/raising.

    Returns: deserialized JSON as native Python data structures.
    """
    url = BASE_GRAPH_URL + ('/%s' % relative_url)
    if 'timeout' not in kwargs:
        kwargs['timeout'] = TIMEOUT

    try:
        r = requests.request(method, url, config=REQUESTS_CONFIG, **kwargs)
    except (SSLError, Timeout) as e:
        raise FBConnectionException(e.message)

    if r.status_code != requests.codes.ok:
        raise FBHTTPException(r.status_code, r.text)

    try:
        data = json.loads(r.text)
    except ValueError as e:
        log.warn("Error decoding JSON: {0}. JSON={1}".format(e.message, r.text))
        raise FBJSONException("%s (%s)" % (e.message, r.text))

    return data

#TODO: PUT, DELETE request factories

class FBGraph(object):
    def __init__(self, access_token='', timeout=TIMEOUT):

        self._access_token = access_token
        self._response_fmt = 'json'
        self._timeout = timeout

    def get(self, relative_url, params=None):
        """
        Query facebook's graph api at relative_url with
        query string parameters params, where params is a python dict.
        """
        data = {}
        params = params or {}
        params['access_token'] = self._access_token

        data = _issue_request('get', relative_url, params=params,
            timeout=self._timeout)

        return data

    def post(self, relative_url, payload=None):
        """
        Publish to the graph.
        Returns a deserialized python object, see
        `Graph API<https://developers.facebook.com/docs/reference/api/>`_

        Note: this method requires a valid access token to work.

        Example 1::
           data = fbg.post('me/feed', {'message': 'Hello, Facebook World!'})
           print data
           # {u'id': u'537208670_111222333444555666777'}

        Example 2::

           new_pic = open('my_pic.png', 'rb')
           data = fbg.post('me/photos', {
              'source': new_pic,
              'message': 'Hey, I\'m posting a picture on Facebook!'})
           print data
           # {u'id': u'123456789012', u'post_id': u'537208670_123456789012'}
        """
        if not isinstance(payload, dict):
            raise FBException('Must specify payload as dict.')

        files = {}
        for k in payload.keys():
            if isinstance(payload[k], file):
                files[k] = payload[k]
                del payload[k]

        payload = payload or {}
        payload['access_token'] = self._access_token

        data = _issue_request('post', relative_url, data=payload, files=files,
            timeout=self._timeout)

        return data

    def batch(self, batch):
        """
        Query's facebook's graph api in batches. batch is a list of dicts,
        where each dict is of the form::

           {'method': 'GET', 'relative_url': 'someurl', ...}.

        There are optional params available, see:
        https://developers.facebook.com/docs/reference/api/batch/

        Returns a list of completely deserialized python data structures for
        each batch response, of the form:
            [
                {
                    "headers": [{ ... }],
                    "code": 200,
                    "body": { ... }
                },
                ...
            ]

        If there was an error in an individual response, the "body" will
        contain the deserialized Facebook error response.
        See: https://developers.facebook.com/docs/reference/api/batch/
        """
        data = []
        payload = {
            'batch': json.dumps(batch),
            'access_token': self._access_token
        }

        data = _issue_request('post', '', data=payload, timeout=self._timeout)

        # deserialize the body of each batch response, need to make sure it
        # is deserializable, thanks to this bug:
        # https://developers.facebook.com/bugs/295201867209494
        for d in data:
            if isinstance(d, dict) and 'body' in d:
                try:
                    d['body'] = json.loads(d['body'])
                except Exception as e:
                    log.warn("Error decoding JSON in batched request: {0}".format(e.message))
                    d['body'] = {'data': []} # default in case deserialization fails
                    pass

        return data

class FBQuery(object):
    def __init__(self, access_token, timeout=TIMEOUT):
        self._access_token = access_token
        # currrently only support json response format
        self._response_fmt = 'json'
        self._timeout = timeout

    def query(self, fql_str):
        params = {
            'q': fql_str,
            'access_token' : self._access_token,
            'format': self._response_fmt
        }

        start_time = time.time()

        data = _issue_request('get', 'fql', params=params,
            timeout=self._timeout)

        stop_time = time.time()
        duration = stop_time - start_time
        data['query_time'] = duration

        return data
<commit_msg>disable ssl verification by default.<commit_after>import requests
import json
import time
import logging
from requests.exceptions import SSLError, Timeout

from .exceptions import (FBException, FBHTTPException, FBJSONException,
    FBConnectionException)

BASE_GRAPH_URL = "https://graph.facebook.com"
BASE_FQL_URL = "https://graph.facebook.com/fql?"
BATCH_QUERY_LIMIT = 50
TIMEOUT = 60.0
REQUESTS_CONFIG = {'max_retries': 2}
VERIFY_SSL = False

log = logging.getLogger(__name__)

def GetRequestFactory(relative_url, **params):
    ''' Returns a properly formed GET request dictionary. '''

    params['method'] = 'GET'
    params['relative_url'] = relative_url

    return params

def _issue_request(method, relative_url, **kwargs):
    """
    Generic method for making requests to the Graph API and deserializing
    the response. Here we aggregate all general error-handling & exception
    catching/raising.

    Returns: deserialized JSON as native Python data structures.
    """
    url = BASE_GRAPH_URL + ('/%s' % relative_url)
    kwargs['timeout'] = kwargs.get('timeout', TIMEOUT)
    kwargs['verify'] = kwargs.get('verify', VERIFY_SSL)

    try:
        r = requests.request(method, url, config=REQUESTS_CONFIG, **kwargs)
    except (SSLError, Timeout) as e:
        raise FBConnectionException(e.message)

    if r.status_code != requests.codes.ok:
        raise FBHTTPException(r.status_code, r.text)

    try:
        data = json.loads(r.text)
    except ValueError as e:
        log.warn("Error decoding JSON: {0}. JSON={1}".format(e.message, r.text))
        raise FBJSONException("%s (%s)" % (e.message, r.text))

    return data

#TODO: PUT, DELETE request factories

class FBGraph(object):
    def __init__(self, access_token='', timeout=TIMEOUT):

        self._access_token = access_token
        self._response_fmt = 'json'
        self._timeout = timeout

    def get(self, relative_url, params=None):
        """
        Query facebook's graph api at relative_url with
        query string parameters params, where params is a python dict.
        """
        params = params or {}
        params['access_token'] = self._access_token

        data = _issue_request('get', relative_url, params=params,
            timeout=self._timeout)

        return data

    def post(self, relative_url, payload=None):
        """
        Publish to the graph.
        Returns a deserialized python object, see
        `Graph API<https://developers.facebook.com/docs/reference/api/>`_

        Note: this method requires a valid access token to work.

        Example 1::
           data = fbg.post('me/feed', {'message': 'Hello, Facebook World!'})
           print data
           # {u'id': u'537208670_111222333444555666777'}

        Example 2::

           new_pic = open('my_pic.png', 'rb')
           data = fbg.post('me/photos', {
              'source': new_pic,
              'message': 'Hey, I\'m posting a picture on Facebook!'})
           print data
           # {u'id': u'123456789012', u'post_id': u'537208670_123456789012'}
        """
        if not isinstance(payload, dict):
            raise FBException('Must specify payload as dict.')

        files = {}
        for k in payload.keys():
            if isinstance(payload[k], file):
                files[k] = payload[k]
                del payload[k]

        payload = payload or {}
        payload['access_token'] = self._access_token

        data = _issue_request('post', relative_url, data=payload, files=files,
            timeout=self._timeout)

        return data

    def batch(self, batch):
        """
        Query's facebook's graph api in batches. batch is a list of dicts,
        where each dict is of the form::

           {'method': 'GET', 'relative_url': 'someurl', ...}.

        There are optional params available, see:
        https://developers.facebook.com/docs/reference/api/batch/

        Returns a list of completely deserialized python data structures for
        each batch response, of the form:
            [
                {
                    "headers": [{ ... }],
                    "code": 200,
                    "body": { ... }
                },
                ...
            ]

        If there was an error in an individual response, the "body" will
        contain the deserialized Facebook error response.
        See: https://developers.facebook.com/docs/reference/api/batch/
        """
        payload = {
            'batch': json.dumps(batch),
            'access_token': self._access_token
        }

        data = _issue_request('post', '', data=payload, timeout=self._timeout)

        # deserialize the body of each batch response, need to make sure it
        # is deserializable, thanks to this bug:
        # https://developers.facebook.com/bugs/295201867209494
        for d in data:
            if isinstance(d, dict) and 'body' in d:
                try:
                    d['body'] = json.loads(d['body'])
                except Exception as e:
                    log.warn("Error decoding JSON in batched request: {0}".format(e.message))
                    d['body'] = {'data': []} # default in case deserialization fails
                    pass

        return data

class FBQuery(object):
    def __init__(self, access_token, timeout=TIMEOUT):
        self._access_token = access_token
        # currrently only support json response format
        self._response_fmt = 'json'
        self._timeout = timeout

    def query(self, fql_str):
        params = {
            'q': fql_str,
            'access_token' : self._access_token,
            'format': self._response_fmt
        }

        start_time = time.time()

        data = _issue_request('get', 'fql', params=params,
            timeout=self._timeout)

        stop_time = time.time()
        duration = stop_time - start_time
        data['query_time'] = duration

        return data
<|endoftext|>


<commit_before>"""Fabric file to setup a cluster so that fab_[cassandra|dse] can be used on it

Creates ~/.cstar_perf/cluster_config.json
Creates ~/fab directory on each node

This is currently only used by cstar_docker, but should remain useful
for other deployment types in the future.
"""

from fabric import api as fab
from fabric.tasks import execute as fab_execute
from StringIO import StringIO
import json
import re
import operator

fab.env.use_ssh_config = True
fab.env.connection_attempts = 10

def setup_hosts_file(hosts):
    """Setup /etc/hosts

    hosts is a dictionary of hostname -> ip address
    """
    with fab.settings(user='root'):
        for host, ip in hosts.items():
            fab.run("echo '{ip} {host}' >> /etc/hosts".format(ip=ip, host=host), quiet=True)

def setup_fab_dir(jdk_roots=['/usr/lib/jvm']):
    fab.run('rm -rf ~/fab && mkdir ~/fab')

    java_homes = []
    version_re = re.compile("^(openjdk|java) version \"(.*)\"$", re.MULTILINE)
    # Find available JDKs:
    for root in jdk_roots:
        homes = fab.run("find {root} -maxdepth 1 -mindepth 1 -type d".format(root=root), quiet=True).strip().split()
        for home in homes:
            # Find java binary and test that it runs:
            if fab.run('test -f {home}/bin/java && test -f {home}/bin/javac'.format(home=home), quiet=True).return_code == 0:
                version_out = fab.run("{home}/bin/java -version".format(home=home), quiet=True).replace("\r\n","\n")
                m = version_re.match(version_out)
                if m:
                    version = m.group(2)
                    java_homes.append((home, version))
    java_homes.sort(key=operator.itemgetter(1), reverse=True)
    assert len(java_homes) > 0, "Did not find any available JDKs"

    # Symlink JDKs in ~/fab/jvms
    fab.run("mkdir -p ~/fab/jvms")
    for home, version in java_homes:
        fab.run("ln -s {home} ~/fab/jvms/{version}".format(home=home, version=version))
    fab.run("ln -s {home} ~/fab/java".format(home=java_homes[0][0]))

    # Symlink ant
    assert fab.run("test -d /usr/share/ant", quiet=True).return_code == 0, "Did not find ant installed"
    fab.run("ln -s /usr/share/ant ~/fab/ant")

    # Checkout trunk cassandra-stress
    fab.run("mkdir -p ~/fab/stress")

    if fab.run("test -d ~/.docker_cassandra.git", quiet=True).return_code == 0:
        # Docker base image checks out cassandra for us, we can just copy that:
        fab.run("git -C ~/.docker_cassandra.git clean -fdx")
        fab.run("cp -a ~/.docker_cassandra.git/.git ~/fab/cassandra.git")
        fab.run("cp -a ~/.docker_cassandra.git ~/fab/stress/trunk")
    else:
        fab.run("git -C ~/fab/stress clone http://github.com/apache/cassandra.git trunk")
        fab.run("cp -a ~/fab/stress/trunk/.git ~/fab/cassandra.git")

    fab.run("git -C ~/fab/stress/trunk pull origin")
    fab.run("cd ~/fab/stress/trunk && JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF8 JAVA_HOME=~/fab/java ~/fab/ant/bin/ant clean jar")
    fab.run("ln -s ~/fab/stress/trunk ~/fab/stress/default")

def copy_fab_dir(from_node):
    fab.run("rm -rf ~/fab ~/.m2")
    fab.run("rsync -a {from_node}:fab ~/".format(from_node=from_node))
    fab.run("rsync -a {from_node}:.m2 ~/".format(from_node=from_node))

def install_cstar_perf_tool(existing_checkout=False):
    if not existing_checkout:
        fab.run("mkdir -p ~/git")
        fab.run("git -C ~/git clone http://github.com/datastax/cstar_perf.git")
    with fab.settings(user='root'):
        fab.run("pip install -e /home/cstar/git/cstar_perf/tool")

    # Add all the git remotes and fetch:
    fab.run('fab -f ~/git/cstar_perf/tool/cstar_perf/tool/fab_cassandra.py add_git_remotes')
    fab.run('git -C ~/fab/cassandra.git fetch --all')

def install_cstar_perf_frontend(existing_checkout=False):
    """Install the frontend

    This method assumes that Cassandra is already installed and running on the frontend node
    """
    if not existing_checkout:
        fab.run("mkdir -p ~/git")
        fab.run("git -C ~/git clone http://github.com/datastax/cstar_perf.git")
    with fab.settings(user='root'):
        fab.run("pip install -e /home/cstar/git/cstar_perf/frontend")

def copy_cluster_config(config):
    config = json.dumps(config, sort_keys=True, indent=4, separators=(',', ': '))
    config_file = StringIO(config)
    fab.run('mkdir -p ~/.cstar_perf')
    fab.put(config_file, '~/.cstar_perf/cluster_config.json')

<commit_msg>Fix git remotes<commit_after>"""Fabric file to setup a cluster so that fab_[cassandra|dse] can be used on it

Creates ~/.cstar_perf/cluster_config.json
Creates ~/fab directory on each node

This is currently only used by cstar_docker, but should remain useful
for other deployment types in the future.
"""

from fabric import api as fab
from fabric.tasks import execute as fab_execute
from StringIO import StringIO
import json
import re
import operator

fab.env.use_ssh_config = True
fab.env.connection_attempts = 10

def setup_hosts_file(hosts):
    """Setup /etc/hosts

    hosts is a dictionary of hostname -> ip address
    """
    with fab.settings(user='root'):
        for host, ip in hosts.items():
            fab.run("echo '{ip} {host}' >> /etc/hosts".format(ip=ip, host=host), quiet=True)

def setup_fab_dir(jdk_roots=['/usr/lib/jvm']):
    fab.run('rm -rf ~/fab && mkdir ~/fab')

    java_homes = []
    version_re = re.compile("^(openjdk|java) version \"(.*)\"$", re.MULTILINE)
    # Find available JDKs:
    for root in jdk_roots:
        homes = fab.run("find {root} -maxdepth 1 -mindepth 1 -type d".format(root=root), quiet=True).strip().split()
        for home in homes:
            # Find java binary and test that it runs:
            if fab.run('test -f {home}/bin/java && test -f {home}/bin/javac'.format(home=home), quiet=True).return_code == 0:
                version_out = fab.run("{home}/bin/java -version".format(home=home), quiet=True).replace("\r\n","\n")
                m = version_re.match(version_out)
                if m:
                    version = m.group(2)
                    java_homes.append((home, version))
    java_homes.sort(key=operator.itemgetter(1), reverse=True)
    assert len(java_homes) > 0, "Did not find any available JDKs"

    # Symlink JDKs in ~/fab/jvms
    fab.run("mkdir -p ~/fab/jvms")
    for home, version in java_homes:
        fab.run("ln -s {home} ~/fab/jvms/{version}".format(home=home, version=version))
    fab.run("ln -s {home} ~/fab/java".format(home=java_homes[0][0]))

    # Symlink ant
    assert fab.run("test -d /usr/share/ant", quiet=True).return_code == 0, "Did not find ant installed"
    fab.run("ln -s /usr/share/ant ~/fab/ant")

    # Checkout trunk cassandra-stress
    fab.run("mkdir -p ~/fab/stress")

    if fab.run("test -d ~/.docker_cassandra.git", quiet=True).return_code == 0:
        # Docker base image checks out cassandra for us, we can just copy that:
        fab.run("git -C ~/.docker_cassandra.git clean -fdx")
        fab.run("cp -a ~/.docker_cassandra.git/.git ~/fab/cassandra.git")
        fab.run("cp -a ~/.docker_cassandra.git ~/fab/stress/trunk")
    else:
        fab.run("git -C ~/fab/stress clone http://github.com/apache/cassandra.git trunk")
        fab.run("cp -a ~/fab/stress/trunk/.git ~/fab/cassandra.git")

    fab.run("git -C ~/fab/stress/trunk pull origin")
    fab.run("cd ~/fab/stress/trunk && JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF8 JAVA_HOME=~/fab/java ~/fab/ant/bin/ant clean jar")
    fab.run("ln -s ~/fab/stress/trunk ~/fab/stress/default")

def copy_fab_dir(from_node):
    fab.run("rm -rf ~/fab ~/.m2")
    fab.run("rsync -a {from_node}:fab ~/".format(from_node=from_node))
    fab.run("rsync -a {from_node}:.m2 ~/".format(from_node=from_node))

def install_cstar_perf_tool(existing_checkout=False):
    if not existing_checkout:
        fab.run("mkdir -p ~/git")
        fab.run("git -C ~/git clone http://github.com/datastax/cstar_perf.git")
    with fab.settings(user='root'):
        fab.run("pip install -e /home/cstar/git/cstar_perf/tool")

    # Add all the git remotes and fetch:
    fab.run('fab -f ~/git/cstar_perf/tool/cstar_perf/tool/fab_cassandra.py -H {hosts} add_git_remotes'.format(
        hosts=",".join([fab.env.hosts] if isinstance(fab.env.hosts, basestring) else fab.env.hosts)))
    fab.run('git -C ~/fab/cassandra.git fetch --all')

def install_cstar_perf_frontend(existing_checkout=False):
    """Install the frontend

    This method assumes that Cassandra is already installed and running on the frontend node
    """
    if not existing_checkout:
        fab.run("mkdir -p ~/git")
        fab.run("git -C ~/git clone http://github.com/datastax/cstar_perf.git")
    with fab.settings(user='root'):
        fab.run("pip install -e /home/cstar/git/cstar_perf/frontend")

def copy_cluster_config(config):
    config = json.dumps(config, sort_keys=True, indent=4, separators=(',', ': '))
    config_file = StringIO(config)
    fab.run('mkdir -p ~/.cstar_perf')
    fab.put(config_file, '~/.cstar_perf/cluster_config.json')

<|endoftext|>


<commit_before>""" The pygame time module
"""

class Clock(object):

   def __init__(self):
      pass

   def tick(self, fps):
      pass
<commit_msg>Docstrings for pygame.time.<commit_after>""" pygame module for monitoring time
"""

class Clock(object):
    """ Clock() -> Clock
    create an object to help track time
    """

    def __init__(self):
        pass

    def tick(self, framerate=0):
        """ tick(framerate=0) -> milliseconds
        update the clock
        """
        #{ "tick", clock_tick, METH_VARARGS, DOC_CLOCKTICK },

    def get_fps(self):
        """ get_fps() -> float
        compute the clock framerate
        """
        #{ "get_fps", (PyCFunction) clock_get_fps,

    def get_time(self):
        """ get_time() -> milliseconds
        time used in the previous tick
        """
        #{ "get_time", (PyCFunction) clock_get_time, METH_NOARGS,
        #DOC_CLOCKGETTIME },

    def get_rawtime(self):
        """ get_rawtime() -> milliseconds
        actual time used in the previous tick
        """
        #{ "get_rawtime", (PyCFunction) clock_get_rawtime, METH_NOARGS,
        #DOC_CLOCKGETRAWTIME },

    def tick_busy_loop(self):
        """ tick_busy_loop(framerate=0) -> milliseconds
        update the clock
        """
        #{ "tick_busy_loop", clock_tick_busy_loop, METH_VARARGS,
        #DOC_CLOCKTICKBUSYLOOP },

def get_ticks():
    """ get_ticks() -> milliseconds
    get the time in milliseconds
    """

def set_timer(eventid, milliseconds):
    """set_timer(eventid, milliseconds) -> None
    repeatedly create an event on the event queue"
    """

def wait(milliseconds):
    """ wait(milliseconds) -> time
    pause the program for an amount of time
    """

def delay(milliseconds):
    """ delay(milliseconds) -> time
    pause the program for an amount of time
    """
<|endoftext|>