def __call__(self, *args): from trytond.cache import Cache from trytond.transaction import Transaction from trytond.rpc import RPC if self._name in self._object.__rpc__: rpc = self._object.__rpc__[self._name] elif self._name in getattr(self._object, '_buttons', {}): rpc = RPC(readonly=False, instantiate=0) else: raise TypeError('%s is not callable' % self._name) with Transaction().start(self._config.database_name, self._config.user, readonly=rpc.readonly) as transaction: Cache.clean(self._config.database_name) args, kwargs, transaction.context, transaction.timestamp = \ rpc.convert(self._object, *args) meth = getattr(self._object, self._name) if not hasattr(meth, 'im_self') or meth.im_self: result = rpc.result(meth(*args, **kwargs)) else: assert rpc.instantiate == 0 inst = args.pop(0) if hasattr(inst, self._name): result = rpc.result(meth(inst, *args, **kwargs)) else: result = [rpc.result(meth(i, *args, **kwargs)) for i in inst] if not rpc.readonly: transaction.commit() Cache.resets(self._config.database_name) return result
def commit(self): try: if self._datamanagers: for datamanager in self._datamanagers: datamanager.tpc_begin(self) for datamanager in self._datamanagers: datamanager.commit(self) for datamanager in self._datamanagers: datamanager.tpc_vote(self) self.connection.commit() except: self.rollback() raise else: try: for datamanager in self._datamanagers: datamanager.tpc_finish(self) except: logger.critical( 'A datamanager raised an exception in' ' tpc_finish, the data might be inconsistant', exc_info=True) if not self._nocache: from trytond.cache import Cache Cache.resets(self.database.name)
def wrapper(request, pool, *args, **kwargs): DatabaseOperationalError = backend.get('DatabaseOperationalError') readonly_ = readonly # can not modify non local if readonly_ is None: if request.method in {'POST', 'PUT', 'DELETE', 'PATCH'}: readonly_ = False else: readonly_ = True for count in range(config.getint('database', 'retry'), -1, -1): with Transaction().start( pool.database_name, 0, readonly=readonly_ ) as transaction: try: Cache.clean(pool.database_name) result = func(request, pool, *args, **kwargs) return result except DatabaseOperationalError: if count and not readonly_: transaction.rollback() continue logger.error('%s', request, exc_info=True) raise except Exception: logger.error('%s', request, exc_info=True) raise # Need to commit to unlock SQLite database transaction.commit() Cache.resets(pool.database_name)
def commit(self): try: if self._datamanagers: for datamanager in self._datamanagers: datamanager.tpc_begin(self) for datamanager in self._datamanagers: datamanager.commit(self) for datamanager in self._datamanagers: datamanager.tpc_vote(self) # ABD: Some datamanager may returns transactions which should # be committed just before the main transaction for sub_transaction in self._sub_transactions: # Does not handle TPC or recursive transaction commit # This just commits the sub transactions to avoid any crashes # which could occur otherwise. sub_transaction.connection.commit() self.connection.commit() except: self.rollback() raise else: try: for datamanager in self._datamanagers: datamanager.tpc_finish(self) except: logger.critical( 'A datamanager raised an exception in' ' tpc_finish, the data might be inconsistant', exc_info=True) if not self._nocache: from trytond.cache import Cache Cache.resets(self.database.name)
def _load_modules(): global res TableHandler = backend.get('TableHandler') cursor = Transaction().cursor # Migration from 3.6: remove double module old_table = 'ir_module_module' new_table = 'ir_module' if TableHandler.table_exist(cursor, old_table): TableHandler.table_rename(cursor, old_table, new_table) if update: cursor.execute( *ir_module.select(ir_module.name, where=ir_module.state.in_(('installed', 'to install', 'to upgrade', 'to remove')))) else: cursor.execute( *ir_module.select(ir_module.name, where=ir_module.state.in_(('installed', 'to upgrade', 'to remove')))) module_list = [name for (name, ) in cursor.fetchall()] if update: module_list += update graph = create_graph(module_list)[0] try: load_module_graph(graph, pool, update, lang) except Exception: cursor.rollback() raise if update: cursor.execute(*ir_module.select( ir_module.name, where=(ir_module.state == 'to remove'))) fetchall = cursor.fetchall() if fetchall: for (mod_name, ) in fetchall: # TODO check if ressource not updated by the user cursor.execute(*ir_model_data.select( ir_model_data.model, ir_model_data.db_id, where=(ir_model_data.module == mod_name), order_by=ir_model_data.id.desc)) for rmod, rid in cursor.fetchall(): Model = pool.get(rmod) Model.delete([Model(rid)]) cursor.commit() cursor.execute( *ir_module.update([ir_module.state], ['uninstalled'], where=(ir_module.state == 'to remove'))) cursor.commit() res = False Module = pool.get('ir.module') Module.update_list() cursor.commit() Cache.resets(database_name)
def _dispatch(request, pool, *args, **kwargs): DatabaseOperationalError = backend.get('DatabaseOperationalError') obj, method = get_object_method(request, pool) if method in obj.__rpc__: rpc = obj.__rpc__[method] else: raise UserError('Calling method %s on %s is not allowed' % (method, obj)) log_message = '%s.%s(*%s, **%s) from %s@%s/%s' log_args = (obj, method, args, kwargs, request.authorization.username, request.remote_addr, request.path) logger.info(log_message, *log_args) user = request.user_id for count in range(config.getint('database', 'retry'), -1, -1): with Transaction().start(pool.database_name, user, readonly=rpc.readonly) as transaction: Cache.clean(pool.database_name) try: c_args, c_kwargs, transaction.context, transaction.timestamp \ = rpc.convert(obj, *args, **kwargs) meth = getattr(obj, method) if (rpc.instantiate is None or not is_instance_method(obj, method)): result = rpc.result(meth(*c_args, **c_kwargs)) else: assert rpc.instantiate == 0 inst = c_args.pop(0) if hasattr(inst, method): result = rpc.result(meth(inst, *c_args, **c_kwargs)) else: result = [rpc.result(meth(i, *c_args, **c_kwargs)) for i in inst] except DatabaseOperationalError: if count and not rpc.readonly: transaction.rollback() continue logger.error(log_message, *log_args, exc_info=True) raise except (ConcurrencyException, UserError, UserWarning): logger.debug(log_message, *log_args, exc_info=True) raise except Exception: logger.error(log_message, *log_args, exc_info=True) raise # Need to commit to unlock SQLite database transaction.commit() Cache.resets(pool.database_name) if request.authorization.type == 'session': try: with Transaction().start(pool.database_name, 0) as transaction: Session = pool.get('ir.session') Session.reset(request.authorization.get('session')) except DatabaseOperationalError: logger.debug('Reset session failed', exc_info=True) logger.debug('Result: %s', result) return result
def rollback(self): for cache in self.cache.itervalues(): cache.clear() for datamanager in self._datamanagers: datamanager.tpc_abort(self) self.connection.rollback() if not self._nocache: from trytond.cache import Cache Cache.resets(self.database.name)
def finish(self): WebDAVServer.DAVRequestHandler.finish(self) if not Transaction().connection: return dbname = Transaction().database.name Transaction().__exit__(None, None, None) if dbname: with Transaction().start(dbname, 0): Cache.resets(dbname)
def _load_modules(): global res TableHandler = backend.get('TableHandler') cursor = Transaction().cursor # Migration from 3.6: remove double module old_table = 'ir_module_module' new_table = 'ir_module' if TableHandler.table_exist(cursor, old_table): TableHandler.table_rename(cursor, old_table, new_table) if update: cursor.execute(*ir_module.select(ir_module.name, where=ir_module.state.in_(('installed', 'to install', 'to upgrade', 'to remove')))) else: cursor.execute(*ir_module.select(ir_module.name, where=ir_module.state.in_(('installed', 'to upgrade', 'to remove')))) module_list = [name for (name,) in cursor.fetchall()] if update: module_list += update graph = create_graph(module_list)[0] try: load_module_graph(graph, pool, update, lang) except Exception: cursor.rollback() raise if update: cursor.execute(*ir_module.select(ir_module.name, where=(ir_module.state == 'to remove'))) fetchall = cursor.fetchall() if fetchall: for (mod_name,) in fetchall: # TODO check if ressource not updated by the user cursor.execute(*ir_model_data.select(ir_model_data.model, ir_model_data.db_id, where=(ir_model_data.module == mod_name), order_by=ir_model_data.id.desc)) for rmod, rid in cursor.fetchall(): Model = pool.get(rmod) Model.delete([Model(rid)]) cursor.commit() cursor.execute(*ir_module.update([ir_module.state], ['uninstalled'], where=(ir_module.state == 'to remove'))) cursor.commit() res = False Module = pool.get('ir.module') Module.update_list() cursor.commit() Cache.resets(database_name)
def dispatch_request(self): """ Does the request dispatching. Matches the URL and returns the return value of the view or error handler. This does not have to be a response object. """ DatabaseOperationalError = backend.get('DatabaseOperationalError') req = _request_ctx_stack.top.request if req.routing_exception is not None: self.raise_routing_exception(req) rule = req.url_rule # if we provide automatic options for this URL and the # request came with the OPTIONS method, reply automatically if getattr(rule, 'provide_automatic_options', False) \ and req.method == 'OPTIONS': return self.make_default_options_response() with Transaction().start(self.database_name, 0): Cache.clean(self.database_name) Cache.resets(self.database_name) with Transaction().start(self.database_name, 0, readonly=True): Website = Pool().get('nereid.website') website = Website.get_from_host(req.host) user, company = website.application_user.id, website.company.id for count in range(int(config.get('database', 'retry')), -1, -1): with Transaction().start( self.database_name, user, context={'company': company}, readonly=rule.is_readonly) as txn: try: transaction_start.send(self) rv = self._dispatch_request(req) txn.cursor.commit() except DatabaseOperationalError: # Strict transaction handling may cause this. # Rollback and Retry the whole transaction if within # max retries, or raise exception and quit. txn.cursor.rollback() if count: continue raise except Exception: # Rollback and raise any other exception txn.cursor.rollback() raise else: return rv finally: transaction_stop.send(self)
def finish(self): WebDAVServer.DAVRequestHandler.finish(self) global CACHE CACHE = LocalDict() if not Transaction().cursor: return dbname = Transaction().cursor.database_name Transaction().stop() if dbname: Cache.resets(dbname)
def finish(self): WebDAVServer.DAVRequestHandler.finish(self) global CACHE CACHE = LocalDict() if not Transaction().cursor: return dbname = Transaction().cursor.database_name Transaction().stop() if dbname: with Transaction().start(dbname, 0): Cache.resets(dbname)
def func(): with Transaction().start(dbname, user_id, context=CONTEXT) as transaction: # No password is needed, because we are working directly with the # API, bypassing any networking stuff. # don't forget to install the party's module before this test. party_obj = pool.get('party.party') new_party = party_obj.create([{'name': 'test_transactions'}])[0] new_party_id = new_party.id transaction.cursor.commit() print new_party_id # Reset the global cache for multi-instance Cache.resets(dbname)
def login(request, database_name, user, password): Database = backend.get('Database') DatabaseOperationalError = backend.get('DatabaseOperationalError') try: Database(database_name).connect() except DatabaseOperationalError: logger.error('fail to connect to %s', database_name, exc_info=True) return False session = security.login(database_name, user, password) with Transaction().start(database_name, 0): Cache.clean(database_name) Cache.resets(database_name) msg = 'successful login' if session else 'bad login or password' logger.info('%s \'%s\' from %s using %s on database \'%s\'', msg, user, request.remote_addr, request.scheme, database_name) return session
def __init__(self, database_name=None, user='******', database_type=None, language='en_US', password='', config_file=None): super(TrytondConfig, self).__init__() from trytond.config import CONFIG CONFIG.update_etc(config_file) CONFIG.set_timezone() if database_type is not None: CONFIG['db_type'] = database_type from trytond.pool import Pool from trytond import backend from trytond.protocols.dispatcher import create from trytond.cache import Cache from trytond.transaction import Transaction self.database_type = CONFIG['db_type'] if database_name is None: if self.database_type == 'sqlite': database_name = ':memory:' else: database_name = 'test_%s' % int(time.time()) self.database_name = database_name self._user = user self.config_file = config_file Pool.start() with Transaction().start(None, 0) as transaction: cursor = transaction.cursor databases = backend.get('Database').list(cursor) if database_name not in databases: create(database_name, CONFIG['admin_passwd'], language, password) database_list = Pool.database_list() self.pool = Pool(database_name) if database_name not in database_list: self.pool.init() with Transaction().start(self.database_name, 0) as transaction: Cache.clean(database_name) User = self.pool.get('res.user') transaction.context = self.context self.user = User.search([ ('login', '=', user), ], limit=1)[0].id with transaction.set_user(self.user): self._context = User.get_preferences(context_only=True) Cache.resets(database_name)
def wrapper(*args, **kwargs): _db = Tdb._db _readonly = True if readonly is not None: _readonly = readonly elif 'request' in kwargs: _readonly = not (kwargs['request'].method in ('PUT', 'POST', 'DELETE', 'PATCH')) _user = user or 0 _context = {} _retry = Tdb._retry or 0 _is_open = (Transaction().cursor) if not _is_open: with Transaction().start(_db, 0): Cache.clean(_db) _context.update(default_context()) else: # Transaction().new_cursor(readonly=_readonly) pass _context.update(context or {}) # _context.update({'company': Tdb._company}) for count in range(_retry, -1, -1): with NoTransaction() if _is_open else Transaction().start( _db, _user, readonly=_readonly, context=_context): cursor = Transaction().cursor if withhold: cursor.cursor.withhold = True try: result = func(*args, **kwargs) if not _readonly: cursor.commit() except DatabaseOperationalError: cursor.rollback() if count and not _readonly: continue raise except Exception: cursor.rollback() raise Cache.resets(_db) return result
def __init__(self, database=None, user='******', config_file=None): super(TrytondConfig, self).__init__() if not database: database = os.environ.get('TRYTOND_DATABASE_URI') else: os.environ['TRYTOND_DATABASE_URI'] = database if not config_file: config_file = os.environ.get('TRYTOND_CONFIG') from trytond.config import config config.update_etc(config_file) from trytond.pool import Pool from trytond.cache import Cache from trytond.transaction import Transaction self.database = database database_name = None if database: uri = urlparse.urlparse(database) database_name = uri.path.strip('/') if not database_name: database_name = os.environ['DB_NAME'] self.database_name = database_name self._user = user self.config_file = config_file Pool.start() self.pool = Pool(database_name) self.pool.init() with Transaction().start(self.database_name, 0) as transaction: Cache.clean(database_name) User = self.pool.get('res.user') transaction.context = self.context self.user = User.search([ ('login', '=', user), ], limit=1)[0].id with transaction.set_user(self.user): self._context = User.get_preferences(context_only=True) Cache.resets(database_name)
def _dispatch(request, pool, *args, **kwargs): DatabaseOperationalError = backend.get('DatabaseOperationalError') obj, method = get_object_method(request, pool) if method in obj.__rpc__: rpc = obj.__rpc__[method] else: raise UserError('Calling method %s on %s is not allowed' % (method, obj)) log_message = '%s.%s(*%s, **%s) from %s@%s/%s' log_args = (obj, method, args, kwargs, request.authorization.username, request.remote_addr, request.path) logger.info(log_message, *log_args) user = request.user_id session = None if request.authorization.type == 'session': session = request.authorization.get('session') for count in range(config.getint('database', 'retry'), -1, -1): with Transaction().start(pool.database_name, user, readonly=rpc.readonly, context={'session': session}) as transaction: Cache.clean(pool.database_name) try: PerfLog().on_enter(user, session, request.method, args, kwargs) except: perf_logger.exception('on_enter failed') try: c_args, c_kwargs, transaction.context, transaction.timestamp \ = rpc.convert(obj, *args, **kwargs) meth = getattr(obj, method) try: wrapped_meth = profile(meth) except: perf_logger.exception('profile failed') else: meth = wrapped_meth if (rpc.instantiate is None or not is_instance_method(obj, method)): result = rpc.result(meth(*c_args, **c_kwargs)) else: assert rpc.instantiate == 0 inst = c_args.pop(0) if hasattr(inst, method): result = rpc.result(meth(inst, *c_args, **c_kwargs)) else: result = [rpc.result(meth(i, *c_args, **c_kwargs)) for i in inst] except DatabaseOperationalError: if count and not rpc.readonly: transaction.rollback() continue logger.error(log_message, *log_args, exc_info=True) raise except (ConcurrencyException, UserError, UserWarning): logger.debug(log_message, *log_args, exc_info=True) raise except Exception: logger.error(log_message, *log_args, exc_info=True) raise # Need to commit to unlock SQLite database transaction.commit() Cache.resets(pool.database_name) if request.authorization.type == 'session': try: with Transaction().start(pool.database_name, 0) as transaction: Session = pool.get('ir.session') Session.reset(request.authorization.get('session')) except DatabaseOperationalError: logger.debug('Reset session failed', exc_info=True) logger.debug('Result: %s', result) try: PerfLog().on_leave(result) except: perf_logger.exception('on_leave failed') return result
def load_modules(database_name, pool, update=False, lang=None): res = True if not Transaction().cursor: contextmanager = Transaction().start(database_name, 0) else: contextmanager = contextlib.nested(Transaction().new_cursor(), Transaction().set_user(0), Transaction().reset_context()) with contextmanager: cursor = Transaction().cursor if update: # Migration from 2.2: workflow module removed cursor.execute('DELETE FROM ir_module_module ' 'WHERE name = %s', ('workflow',)) if 'all' in CONFIG['init']: cursor.execute("SELECT name FROM ir_module_module " "WHERE name != \'test\'") else: cursor.execute("SELECT name FROM ir_module_module " "WHERE state IN ('installed', 'to install', " "'to upgrade', 'to remove')") else: cursor.execute("SELECT name FROM ir_module_module " "WHERE state IN ('installed', 'to upgrade', 'to remove')") module_list = [name for (name,) in cursor.fetchall()] if update: for module in CONFIG['init'].keys(): if CONFIG['init'][module]: module_list.append(module) for module in CONFIG['update'].keys(): if CONFIG['update'][module]: module_list.append(module) graph = create_graph(module_list)[0] try: load_module_graph(graph, pool, lang) except Exception: cursor.rollback() raise if update: cursor.execute("SELECT name FROM ir_module_module " "WHERE state IN ('to remove')") fetchall = cursor.fetchall() if fetchall: for (mod_name,) in fetchall: #TODO check if ressource not updated by the user cursor.execute('SELECT model, db_id FROM ir_model_data ' 'WHERE module = %s ' 'ORDER BY id DESC', (mod_name,)) for rmod, rid in cursor.fetchall(): Model = pool.get(rmod) Model.delete([Model(rid)]) cursor.commit() cursor.execute("UPDATE ir_module_module SET state = %s " "WHERE state IN ('to remove')", ('uninstalled',)) cursor.commit() res = False Module = pool.get('ir.module.module') Module.update_list() cursor.commit() Cache.resets(database_name) return res
def dispatch_request(self): """ Does the request dispatching. Matches the URL and returns the return value of the view or error handler. This does not have to be a response object. """ DatabaseOperationalError = backend.get('DatabaseOperationalError') req = _request_ctx_stack.top.request if req.routing_exception is not None: self.raise_routing_exception(req) rule = req.url_rule # if we provide automatic options for this URL and the # request came with the OPTIONS method, reply automatically if getattr(rule, 'provide_automatic_options', False) \ and req.method == 'OPTIONS': return self.make_default_options_response() with Transaction().start(self.database_name, 0): Cache.clean(self.database_name) Cache.resets(self.database_name) with Transaction().start(self.database_name, 0, readonly=True): user = current_website.application_user.id website_context = current_website.get_context() website_context.update({ 'company': current_website.company.id, }) language = current_locale.language.code # pop locale if specified in the view_args req.view_args.pop('locale', None) active_id = req.view_args.pop('active_id', None) for count in range(int(config.get('database', 'retry')), -1, -1): with Transaction().start( self.database_name, user, context=website_context, readonly=rule.is_readonly) as txn: try: transaction_start.send(self) rv = self._dispatch_request( req, language=language, active_id=active_id ) txn.commit() transaction_commit.send(self) except DatabaseOperationalError: # Strict transaction handling may cause this. # Rollback and Retry the whole transaction if within # max retries, or raise exception and quit. txn.rollback() if count: continue raise except Exception: # Rollback and raise any other exception txn.rollback() raise else: return rv finally: transaction_stop.send(self)
error={ 'type': 'UserError', 'message': exc.message, 'description': exc.description, 'code': exc.code, }), 500 current_app.logger.error(traceback.format_exc()) except Exception, exc: cursor.rollback() result = jsonify(error=unicode(exc)), 500 current_app.logger.error(traceback.format_exc()) else: if not (readonly or current_app.testing): cursor.commit() Cache.resets(database) return result return wrapper ar_to_dict = lambda ar: {'id': ar.id, 'rec_name': ar.rec_name} @restful.route('/login', methods=['POST']) def login(database): """ POST: Login and return user id and session """ result = security.login(database, request.form['login'], request.form['password'])
result = jsonify(error={ 'type': 'UserError', 'message': exc.message, 'description': exc.description, 'code': exc.code, }), 500 current_app.logger.error(traceback.format_exc()) except Exception, exc: cursor.rollback() result = jsonify(error=unicode(exc)), 500 current_app.logger.error(traceback.format_exc()) else: if not (readonly or current_app.testing): cursor.commit() Cache.resets(database) return result return wrapper ar_to_dict = lambda ar: {'id': ar.id, 'rec_name': ar.rec_name} @restful.route('/login', methods=['POST']) def login(database): """ POST: Login and return user id and session """ result = security.login( database, request.form['login'], request.form['password'] )
def dispatch(host, port, protocol, database_name, user, session, object_type, object_name, method, *args, **kargs): if object_type == 'common': if method == 'login': try: database = Database(database_name).connect() cursor = database.cursor() cursor.close() except Exception: return False res = security.login(database_name, user, session) Cache.clean(database_name) logger = logging.getLogger('dispatcher') msg = res and 'successful login' or 'bad login or password' logger.info('%s \'%s\' from %s:%d using %s on database \'%s\'' % \ (msg, user, host, port, protocol, database_name)) Cache.resets(database_name) return res or False elif method == 'logout': name = security.logout(database_name, user, session) logger = logging.getLogger('dispatcher') logger.info('logout \'%s\' from %s:%d ' \ 'using %s on database \'%s\'' % (name, host, port, protocol, database_name)) return True elif method == 'version': return VERSION elif method == 'timezone_get': return CONFIG['timezone'] elif method == 'list_lang': return [ ('bg_BG', 'Български'), ('ca_ES', 'Català'), ('cs_CZ', 'Čeština'), ('de_DE', 'Deutsch'), ('en_US', 'English'), ('es_AR', 'Español (Argentina)'), ('es_ES', 'Español (España)'), ('es_CO', 'Español (Colombia)'), ('fr_FR', 'Français'), ('nl_NL', 'Nederlands'), ('ru_RU', 'Russian'), ] elif method == 'db_exist': try: database = Database(*args, **kargs).connect() cursor = database.cursor() cursor.close(close=True) return True except Exception: return False elif method == 'list': if CONFIG['prevent_dblist']: raise Exception('AccessDenied') database = Database().connect() try: cursor = database.cursor() try: res = database.list(cursor) finally: cursor.close(close=True) except Exception: res = [] return res elif method == 'create': return create(*args, **kargs) elif method == 'restore': return restore(*args, **kargs) elif method == 'drop': return drop(*args, **kargs) elif method == 'dump': return dump(*args, **kargs) return elif object_type == 'system': database = Database(database_name).connect() database_list = Pool.database_list() pool = Pool(database_name) if not database_name in database_list: pool.init() if method == 'listMethods': res = [] for type in ('model', 'wizard', 'report'): for object_name, obj in pool.iterobject(type=type): for method in obj._rpc: res.append(type + '.' + object_name + '.' + method) return res elif method == 'methodSignature': return 'signatures not supported' elif method == 'methodHelp': res = [] args_list = args[0].split('.') object_type = args_list[0] object_name = '.'.join(args_list[1:-1]) method = args_list[-1] obj = pool.get(object_name, type=object_type) return pydoc.getdoc(getattr(obj, method)) user = security.check(database_name, user, session) Cache.clean(database_name) database_list = Pool.database_list() pool = Pool(database_name) if not database_name in database_list: with Transaction().start(database_name, user, readonly=True) as transaction: pool.init() obj = pool.get(object_name, type=object_type) if method in obj._rpc: readonly = not obj._rpc[method] elif method in getattr(obj, '_buttons', {}): readonly = False else: raise UserError('Calling method %s on %s %s is not allowed!' % (method, object_type, object_name)) for count in range(int(CONFIG['retry']), -1, -1): with Transaction().start(database_name, user, readonly=readonly) as transaction: try: args_without_context = list(args) if 'context' in kargs: context = kargs.pop('context') else: context = args_without_context.pop() if '_timestamp' in context: transaction.timestamp = context['_timestamp'] del context['_timestamp'] transaction.context = context res = getattr(obj, method)(*args_without_context, **kargs) if not readonly: transaction.cursor.commit() except DatabaseOperationalError, exception: transaction.cursor.rollback() if count and not readonly: continue raise except Exception, exception: if CONFIG['verbose'] and not isinstance(exception, ( NotLogged, ConcurrencyException, UserError, UserWarning)): tb_s = ''.join(traceback.format_exception(*sys.exc_info())) logger = logging.getLogger('dispatcher') logger.error('Exception calling method %s on ' '%s %s from %s@%s:%d/%s:\n' % (method, object_type, object_name, user, host, port, database_name) + tb_s) transaction.cursor.rollback() raise
def dispatch(host, port, protocol, database_name, user, session, object_type, object_name, method, *args, **kwargs): Database = backend.get('Database') DatabaseOperationalError = backend.get('DatabaseOperationalError') if object_type == 'common': if method == 'login': try: database = Database(database_name).connect() cursor = database.cursor() cursor.close() except Exception: return False res = security.login(database_name, user, session) with Transaction().start(database_name, 0): Cache.clean(database_name) Cache.resets(database_name) msg = res and 'successful login' or 'bad login or password' logger.info('%s \'%s\' from %s:%d using %s on database \'%s\'', msg, user, host, port, protocol, database_name) return res or False elif method == 'logout': name = security.logout(database_name, user, session) logger.info('logout \'%s\' from %s:%d ' 'using %s on database \'%s\'', name, host, port, protocol, database_name) return True elif method == 'version': return __version__ elif method == 'list_lang': return [ ('bg_BG', 'Български'), ('ca_ES', 'Català'), ('cs_CZ', 'Čeština'), ('de_DE', 'Deutsch'), ('en_US', 'English'), ('es_AR', 'Español (Argentina)'), ('es_EC', 'Español (Ecuador)'), ('es_ES', 'Español (España)'), ('es_CO', 'Español (Colombia)'), ('fr_FR', 'Français'), ('lt_LT', 'Lietuvių'), ('nl_NL', 'Nederlands'), ('ru_RU', 'Russian'), ('sl_SI', 'Slovenščina'), ] elif method == 'db_exist': try: database = Database(*args, **kwargs).connect() cursor = database.cursor() cursor.close(close=True) return True except Exception: return False elif method == 'list': if not config.getboolean('database', 'list'): raise Exception('AccessDenied') with Transaction().start(None, 0, close=True) as transaction: return transaction.database.list(transaction.cursor) elif method == 'create': return create(*args, **kwargs) elif method == 'restore': return restore(*args, **kwargs) elif method == 'drop': return drop(*args, **kwargs) elif method == 'dump': return dump(*args, **kwargs) return elif object_type == 'system': database = Database(database_name).connect() database_list = Pool.database_list() pool = Pool(database_name) if database_name not in database_list: pool.init() if method == 'listMethods': res = [] for type in ('model', 'wizard', 'report'): for object_name, obj in pool.iterobject(type=type): for method in obj.__rpc__: res.append(type + '.' + object_name + '.' + method) return res elif method == 'methodSignature': return 'signatures not supported' elif method == 'methodHelp': res = [] args_list = args[0].split('.') object_type = args_list[0] object_name = '.'.join(args_list[1:-1]) method = args_list[-1] obj = pool.get(object_name, type=object_type) return pydoc.getdoc(getattr(obj, method)) for count in range(config.getint('database', 'retry'), -1, -1): try: user = security.check(database_name, user, session) except DatabaseOperationalError: if count: continue raise break database_list = Pool.database_list() pool = Pool(database_name) if database_name not in database_list: with Transaction().start(database_name, user, readonly=True) as transaction: pool.init() obj = pool.get(object_name, type=object_type) if method in obj.__rpc__: rpc = obj.__rpc__[method] else: raise UserError('Calling method %s on %s %s is not allowed!' % (method, object_type, object_name)) log_message = '%s.%s.%s(*%s, **%s) from %s@%s:%d/%s' log_args = (object_type, object_name, method, args, kwargs, user, host, port, database_name) logger.info(log_message, *log_args) for count in range(config.getint('database', 'retry'), -1, -1): with Transaction().start(database_name, user, readonly=rpc.readonly) as transaction: Cache.clean(database_name) try: c_args, c_kwargs, transaction.context, transaction.timestamp \ = rpc.convert(obj, *args, **kwargs) meth = getattr(obj, method) if (rpc.instantiate is None or not is_instance_method(obj, method)): result = rpc.result(meth(*c_args, **c_kwargs)) else: assert rpc.instantiate == 0 inst = c_args.pop(0) if hasattr(inst, method): result = rpc.result(meth(inst, *c_args, **c_kwargs)) else: result = [rpc.result(meth(i, *c_args, **c_kwargs)) for i in inst] if not rpc.readonly: transaction.cursor.commit() except DatabaseOperationalError: transaction.cursor.rollback() if count and not rpc.readonly: continue raise except (NotLogged, ConcurrencyException, UserError, UserWarning): logger.debug(log_message, *log_args, exc_info=True) transaction.cursor.rollback() raise except Exception: logger.error(log_message, *log_args, exc_info=True) transaction.cursor.rollback() raise Cache.resets(database_name) with Transaction().start(database_name, 0) as transaction: pool = Pool(database_name) Session = pool.get('ir.session') try: Session.reset(session) except DatabaseOperationalError: logger.debug('Reset session failed', exc_info=True) # Silently fail when reseting session transaction.cursor.rollback() else: transaction.cursor.commit() logger.debug('Result: %s', result) return result
def dispatch(host, port, protocol, database_name, user, session, object_type, object_name, method, *args, **kwargs): Database = backend.get('Database') DatabaseOperationalError = backend.get('DatabaseOperationalError') if object_type == 'common': if method == 'login': try: database = Database(database_name).connect() cursor = database.cursor() cursor.close() except Exception: return False res = security.login(database_name, user, session) with Transaction().start(database_name, 0): Cache.clean(database_name) Cache.resets(database_name) msg = res and 'successful login' or 'bad login or password' logger.info('%s \'%s\' from %s:%d using %s on database \'%s\'', msg, user, host, port, protocol, database_name) return res or False elif method == 'logout': name = security.logout(database_name, user, session) logger.info('logout \'%s\' from %s:%d ' 'using %s on database \'%s\'', name, host, port, protocol, database_name) return True elif method == 'version': return __version__ elif method == 'list_lang': return [ ('bg_BG', 'Български'), ('ca_ES', 'Català'), ('cs_CZ', 'Čeština'), ('de_DE', 'Deutsch'), ('en_US', 'English'), ('es_AR', 'Español (Argentina)'), ('es_EC', 'Español (Ecuador)'), ('es_ES', 'Español (España)'), ('es_CO', 'Español (Colombia)'), ('es_MX', 'Español (México)'), ('fr_FR', 'Français'), ('hu_HU', 'Magyar'), ('it_IT', 'Italiano'), ('lt_LT', 'Lietuvių'), ('nl_NL', 'Nederlands'), ('pt_BR', 'Português (Brasil)'), ('ru_RU', 'Russian'), ('sl_SI', 'Slovenščina'), ] elif method == 'db_exist': try: database = Database(*args, **kwargs).connect() cursor = database.cursor() cursor.close(close=True) return True except Exception: return False elif method == 'list': if not config.getboolean('database', 'list'): raise Exception('AccessDenied') with Transaction().start(None, 0, close=True) as transaction: return transaction.database.list(transaction.cursor) elif method == 'create': return create(*args, **kwargs) elif method == 'restore': return restore(*args, **kwargs) elif method == 'drop': return drop(*args, **kwargs) elif method == 'dump': return dump(*args, **kwargs) return elif object_type == 'system': database = Database(database_name).connect() database_list = Pool.database_list() pool = Pool(database_name) if database_name not in database_list: pool.init() if method == 'listMethods': res = [] for type in ('model', 'wizard', 'report'): for object_name, obj in pool.iterobject(type=type): for method in obj.__rpc__: res.append(type + '.' + object_name + '.' + method) return res elif method == 'methodSignature': return 'signatures not supported' elif method == 'methodHelp': res = [] args_list = args[0].split('.') object_type = args_list[0] object_name = '.'.join(args_list[1:-1]) method = args_list[-1] obj = pool.get(object_name, type=object_type) return pydoc.getdoc(getattr(obj, method)) for count in range(config.getint('database', 'retry'), -1, -1): try: user = security.check(database_name, user, session) except DatabaseOperationalError: if count: continue raise break database_list = Pool.database_list() pool = Pool(database_name) if database_name not in database_list: with Transaction().start(database_name, user, readonly=True) as transaction: pool.init() obj = pool.get(object_name, type=object_type) if method in obj.__rpc__: rpc = obj.__rpc__[method] else: raise UserError('Calling method %s on %s %s is not allowed!' % (method, object_type, object_name)) log_message = '%s.%s.%s(*%s, **%s) from %s@%s:%d/%s' log_args = (object_type, object_name, method, args, kwargs, user, host, port, database_name) logger.info(log_message, *log_args) for count in range(config.getint('database', 'retry'), -1, -1): with Transaction().start(database_name, user, readonly=rpc.readonly) as transaction: Cache.clean(database_name) try: c_args, c_kwargs, transaction.context, transaction.timestamp \ = rpc.convert(obj, *args, **kwargs) meth = getattr(obj, method) if (rpc.instantiate is None or not is_instance_method(obj, method)): result = rpc.result(meth(*c_args, **c_kwargs)) else: assert rpc.instantiate == 0 inst = c_args.pop(0) if hasattr(inst, method): result = rpc.result(meth(inst, *c_args, **c_kwargs)) else: result = [rpc.result(meth(i, *c_args, **c_kwargs)) for i in inst] if not rpc.readonly: transaction.cursor.commit() except DatabaseOperationalError: transaction.cursor.rollback() if count and not rpc.readonly: continue raise except (NotLogged, ConcurrencyException, UserError, UserWarning): logger.debug(log_message, *log_args, exc_info=True) transaction.cursor.rollback() raise except Exception: logger.error(log_message, *log_args, exc_info=True) transaction.cursor.rollback() raise Cache.resets(database_name) with Transaction().start(database_name, 0) as transaction: pool = Pool(database_name) Session = pool.get('ir.session') try: Session.reset(session) except DatabaseOperationalError: logger.debug('Reset session failed', exc_info=True) # Silently fail when reseting session transaction.cursor.rollback() else: transaction.cursor.commit() logger.debug('Result: %s', result) return result
UserWarning)): tb_s = ''.join(traceback.format_exception(*sys.exc_info())) logger = logging.getLogger('dispatcher') logger.error('Exception calling method %s on ' '%s %s from %s@%s:%d/%s:\n' % (method, object_type, object_name, user, host, port, database_name) + tb_s) transaction.cursor.rollback() raise if not (object_name == 'res.request' and method == 'request_get'): with Transaction().start(database_name, 0) as transaction: pool = Pool(database_name) session_obj = pool.get('ir.session') session_obj.reset(session) transaction.cursor.commit() Cache.resets(database_name) return res def create(database_name, password, lang, admin_password): ''' Create a database :param database_name: the database name :param password: the server password :param lang: the default language for the database :param admin_password: the admin password :return: True if succeed ''' security.check_super(password) res = False
def dispatch_request(self): """ Does the request dispatching. Matches the URL and returns the return value of the view or error handler. This does not have to be a response object. """ DatabaseOperationalError = backend.get('DatabaseOperationalError') req = _request_ctx_stack.top.request if req.routing_exception is not None: self.raise_routing_exception(req) rule = req.url_rule # if we provide automatic options for this URL and the # request came with the OPTIONS method, reply automatically if getattr(rule, 'provide_automatic_options', False) \ and req.method == 'OPTIONS': return self.make_default_options_response() with Transaction().start(self.database_name, 0): Cache.clean(self.database_name) Cache.resets(self.database_name) with Transaction().start(self.database_name, 0, readonly=True): user = current_website.application_user.id website_context = current_website.get_context() website_context.update({ 'company': current_website.company.id, }) language = current_locale.language.code # pop locale if specified in the view_args req.view_args.pop('locale', None) active_id = req.view_args.pop('active_id', None) for count in range(int(config.get('database', 'retry')), -1, -1): with Transaction().start(self.database_name, user, context=website_context, readonly=rule.is_readonly) as txn: try: transaction_start.send(self) rv = self._dispatch_request(req, language=language, active_id=active_id) txn.commit() transaction_commit.send(self) except DatabaseOperationalError: # Strict transaction handling may cause this. # Rollback and Retry the whole transaction if within # max retries, or raise exception and quit. txn.rollback() if count: continue raise except Exception: # Rollback and raise any other exception txn.rollback() raise else: return rv finally: transaction_stop.send(self)
def __init__(self, database_uri=None, user='******', language='en_US', admin_password='', super_pwd=None, config_file=None): OrigConfigModule.Config.__init__(self) # FixMe: straighten this mess out if config_file is None: config_file = os.environ.get('TRYTOND_CONFIG') assert config_file and os.path.isfile(config_file), \ "Set the environment variable TRYTOND_CONFIG to the path of TRYTOND CONFIG" if not database_uri: database_uri = os.environ.get('TRYTOND_DATABASE_URI') else: os.environ['TRYTOND_DATABASE_URI'] = database_uri assert os.path.isfile(config_file), \ "set os.environ.get('TRYTOND_CONFIG') to be the Tryton config file" from trytond.config import config config.update_etc(config_file) from trytond.pool import Pool from trytond import backend from trytond.protocols.dispatcher import create from trytond.cache import Cache from trytond.transaction import Transaction self.database = database_uri database_name = None if database_uri: uri = urlparse.urlparse(database_uri) database_name = uri.path.strip('/') if not database_name: assert 'DB_NAME' in os.environ, \ "Set os.environ['DB_NAME'] to be the database name" database_name = os.environ['DB_NAME'] self.database_name = database_name self._user = user self.config_file = config_file Pool.start() if False: # new in 3.4 self.pool = Pool(database_name) self.pool.init() else: # 3.2 code created the database if it did not exist with Transaction().start(None, 0) as transaction: cursor = transaction.cursor databases = backend.get('Database').list(cursor) if database_name not in databases: # trytond/protocols/dispatcher.py ''' Create a database :param database_name: the database name :param password: the server password :param lang: the default language for the database :param admin_password: the admin password :return: True if succeed ''' if not super_pwd: sys.stderr.write( "WARN: No super_pwd to create db %s\n" % (database_name,)) #! This is NOT the postgres server password #! This calls security.check_super(password) #! which is set in the conf file, [session]super_pwd #! using crypt to generate it from from the command line #! We default it to admin which may also be the #! of the user 'admin': admin_password super_pwd = 'admin' assert admin_password, "ERROR: No admin_password to create db " + database_name sys.stderr.write( "create %s %s %s %s\n" % (database_name, super_pwd, language, admin_password,)) create(database_name, super_pwd, language, admin_password) database_list = Pool.database_list() self.pool = Pool(database_name) if database_name not in database_list: self.pool.init() with Transaction().start(self.database_name, 0) as transaction: Cache.clean(database_name) User = self.pool.get('res.user') transaction.context = self.context self.user = User.search([ ('login', '=', user), ], limit=1)[0].id with transaction.set_user(self.user): self._context = User.get_preferences(context_only=True) Cache.resets(database_name)
def _load_modules(): global res TableHandler = backend.get("TableHandler") transaction = Transaction() with transaction.connection.cursor() as cursor: # Migration from 3.6: remove double module old_table = "ir_module_module" new_table = "ir_module" if TableHandler.table_exist(old_table): TableHandler.table_rename(old_table, new_table) if update: migrate_modules(cursor) cursor.execute( *ir_module.select( ir_module.name, where=ir_module.state.in_(("installed", "to install", "to upgrade", "to remove")), ) ) else: cursor.execute( *ir_module.select( ir_module.name, where=ir_module.state.in_(("installed", "to upgrade", "to remove")) ) ) module_list = [name for (name,) in cursor.fetchall()] if update: module_list += update graph = create_graph(module_list)[0] load_module_graph(graph, pool, update, lang) if update: cursor.execute(*ir_module.select(ir_module.name, where=(ir_module.state == "to remove"))) fetchall = cursor.fetchall() if fetchall: for (mod_name,) in fetchall: # TODO check if ressource not updated by the user cursor.execute( *ir_model_data.select( ir_model_data.model, ir_model_data.db_id, where=(ir_model_data.module == mod_name), order_by=ir_model_data.id.desc, ) ) for rmod, rid in cursor.fetchall(): Model = pool.get(rmod) Model.delete([Model(rid)]) Transaction().connection.commit() cursor.execute( *ir_module.update([ir_module.state], ["uninstalled"], where=(ir_module.state == "to remove")) ) Transaction().connection.commit() res = False Module = pool.get("ir.module") Module.update_list() # Need to commit to unlock SQLite database transaction.commit() Cache.resets(database_name)
def _load_modules(): global res TableHandler = backend.get('TableHandler') transaction = Transaction() with transaction.connection.cursor() as cursor: # Migration from 3.6: remove double module old_table = 'ir_module_module' new_table = 'ir_module' if TableHandler.table_exist(old_table): TableHandler.table_rename(old_table, new_table) # Migration from 4.0: rename installed to activated cursor.execute( *ir_module.select(ir_module.name, where=ir_module.state.in_(('installed', 'uninstalled')))) if cursor.fetchone(): cursor.execute( *ir_module.update([ir_module.state], ['activated'], where=ir_module.state == 'installed')) cursor.execute( *ir_module.update([ir_module.state], ['not activated'], where=ir_module.state == 'uninstalled')) if update: cursor.execute(*ir_module.select(ir_module.name, where=ir_module.state.in_(( 'activated', 'to activate', 'to upgrade', 'to remove')))) else: cursor.execute(*ir_module.select(ir_module.name, where=ir_module.state.in_(( 'activated', 'to upgrade', 'to remove')))) module_list = [name for (name, ) in cursor.fetchall()] if update: module_list += update graph = create_graph(module_list)[0] load_module_graph(graph, pool, update, lang) if update: cursor.execute(*ir_module.select( ir_module.name, where=(ir_module.state == 'to remove'))) fetchall = cursor.fetchall() if fetchall: for (mod_name, ) in fetchall: # TODO check if ressource not updated by the user cursor.execute(*ir_model_data.select( ir_model_data.model, ir_model_data.db_id, where=(ir_model_data.module == mod_name), order_by=ir_model_data.id.desc)) for rmod, rid in cursor.fetchall(): Model = pool.get(rmod) Model.delete([Model(rid)]) Transaction().connection.commit() cursor.execute( *ir_module.update([ir_module.state], ['not activated'], where=( ir_module.state == 'to remove'))) Transaction().connection.commit() res = False Module = pool.get('ir.module') Module.update_list() # Need to commit to unlock SQLite database transaction.commit() Cache.resets(database_name)
print module #print dir(module) user_obj = pool.get('res.user') user = user_obj.search([('login', '=', 'admin')], limit=1)[0] user_id = user.id with Transaction().start(dbname, user_id) as transaction: # No password is needed, because we are working directly with the # API, bypassing any networking stuff. # don't forget to install the party's module before this test. try: party_obj = pool.get('party.party') except: ir_module = pool.get('ir.module.module') print '*******************', sorted(dir(ir_module)) ir_module.update_list() party = ir_module.search([('name', '=', 'country')]) #print [mod.name for mod in modules ] ir_module.install(party) pool.init(update=['country']) print sorted(dir(party)) party_obj = pool.get('party.party') new_party = party_obj.create([{'name': 'New party'}])[0] new_party_id = new_party.id transaction.cursor.commit() print new_party_id # Reset the global cache for multi-instance Cache.resets(dbname)