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 __setup__(cls): super(User, cls).__setup__() cls.__rpc__.update({ 'get_preferences': RPC(check_access=False), 'set_preferences': RPC( readonly=False, check_access=False, fresh_session=True), 'get_preferences_fields_view': RPC(check_access=False), }) table = cls.__table__() cls._sql_constraints += [ ('login_key', Unique(table, table.login), 'You can not have two users with the same login!') ] cls._buttons.update({ 'reset_password': { 'invisible': ~Eval('email', True) | (not _has_password), }, }) cls._preferences_fields = [ 'name', 'password', 'email', 'signature', 'menu', 'pyson_menu', 'actions', 'status_bar', 'warnings', 'applications', ] cls._context_fields = [ 'language', 'language_direction', 'groups', ] cls._order.insert(0, ('name', 'ASC'))
def __setup__(cls): super(ShipmentOut, cls).__setup__() # There can be cases when people might want to use a different # shipment carrier at any state except `done`. cls.carrier.states = STATES cls._error_messages.update({ 'mailclass_missing': 'Select a mailclass to ship using Endicia [USPS].', 'error_label': 'Error in generating label "%s"', 'tracking_number_already_present': 'Tracking Number is already present for this shipment.', 'invalid_state': 'Labels can only be generated when the ' 'shipment is in Packed or Done states only', 'wrong_carrier': 'Carrier for selected shipment is not Endicia', }) cls.__rpc__.update({ 'make_endicia_labels': RPC(readonly=False, instantiate=0), 'get_endicia_shipping_cost': RPC(readonly=False, instantiate=0), })
def test_check_access(self): "Test check_access" rpc_no_access = RPC(check_access=False) self.assertEqual(rpc_no_access.convert(None, {}), ([], {}, {}, None)) rpc_with_access = RPC(check_access=True) self.assertEqual(rpc_with_access.convert(None, {}), ([], {}, { '_check_access': True }, None))
def __setup__(cls): super(PatientPrescriptionOrder, cls).__setup__() cls._buttons.update({ 'generate_prescription': { 'invisible': Equal(Eval('state'), 'validated'), }, 'create_prescription': { 'invisible': Or(Equal(Eval('state'), 'done'), Equal(Eval('state'), 'validated')) }, }) ''' Allow calling the set_signature method via RPC ''' cls.__rpc__.update({ 'set_signature': RPC(readonly=False), })
def __setup__(cls): super(Invoice, cls).__setup__() cls._buttons.update({ 'pay_using_payment_transaction': { 'invisible': Or( Eval('state') != 'posted', Eval('type') == 'in', ), 'readonly': ~Eval('groups', []).contains( Id('account', 'group_account')), }, }) cls.__rpc__.update({ 'capture_and_pay_using_transaction': RPC( readonly=False, instantiate=0 ), })
def __setup__(cls): super(LabTest, cls).__setup__() cls._buttons.update({ 'generate_document': { 'invisible': Not(Equal(Eval('state'), 'draft')), }, 'set_to_draft': { 'invisible': Not(Equal(Eval('state'), 'done')), }, 'sign_document': { 'invisible': Not(Equal(Eval('state'), 'done')), }, }) ''' Allow calling the set_signature method via RPC ''' cls.__rpc__.update({ 'set_signature': RPC(readonly=False), })
def test_instantiate_unique(self): "Test instantiate unique" rpc = RPC(instantiate=0, unique=True) obj = Mock() rpc.convert(obj, [1, 2], {}) obj.browse.assert_called_once_with([1, 2]) obj.reset_mock() with self.assertRaises(ValueError): rpc.convert(obj, [1, 1], {})
def __setup__(cls): super(Module, cls).__setup__() table = cls.__table__() cls._sql_constraints = [ ('name_uniq', Unique(table, table.name), 'The name of the module must be unique!'), ] cls._order.insert(0, ('name', 'ASC')) cls.__rpc__.update({ 'on_write': RPC(instantiate=0), }) cls._error_messages.update({ 'delete_state': ('You can not remove a module that is activated ' 'or will be activated'), 'missing_dep': 'Missing dependencies %s for module "%s"', 'deactivate_dep': ('Some activated modules depend on the ones ' 'you are trying to deactivate:'), }) cls._buttons.update({ 'activate': { 'invisible': Eval('state') != 'not activated', 'depends': ['state'], }, 'activate_cancel': { 'invisible': Eval('state') != 'to activate', 'depends': ['state'], }, 'deactivate': { 'invisible': Eval('state') != 'activated', 'depends': ['state'], }, 'deactivate_cancel': { 'invisible': Eval('state') != 'to remove', 'depends': ['state'], }, 'upgrade': { 'invisible': Eval('state') != 'activated', 'depends': ['state'], }, 'upgrade_cancel': { 'invisible': Eval('state') != 'to upgrade', 'depends': ['state'], }, })
def __setup__(cls): super(Service, cls).__setup__() cls.__rpc__['getTechnicalService'] = RPC(check_access=False, readonly=False) cls._error_messages.update({ 'modify_invoice': ('You can not modify service "%s".'), 'delete_cancel': ('You can not delete service "%s".'), }) cls._transitions |= set(( ('pending', 'review'), ('review', 'ready'), ('review', 'without'), ('review', 'warranty'), ('ready', 'delivered'), ('without', 'delivered'), ('warranty', 'delivered'), )) cls._buttons.update({ 'review': { 'invisible': Eval('state') != ('pending') }, 'ready': { 'invisible': Eval('state').in_(['pending', 'ready', 'without', 'delivered']) }, 'without': { 'invisible': Eval('state').in_(['pending', 'ready', 'without', 'delivered']) }, 'warranty': { 'invisible': ~Eval('garanty', True) | (Eval('state').in_( ['pending', 'ready', 'without', 'delivered'])) }, 'delivered': { 'invisible': Eval('state').in_(['review', 'pending', 'delivered']) }, })
def __setup__(cls): super(Payment, cls).__setup__() cls._order.insert(0, ('date', 'DESC')) cls._transitions |= set(( ('draft', 'approved'), ('approved', 'processing'), ('processing', 'succeeded'), ('processing', 'failed'), ('approved', 'draft'), ('succeeded', 'failed'), ('failed', 'succeeded'), )) cls._buttons.update({ 'draft': { 'invisible': Eval('state') != 'approved', 'icon': 'tryton-back', 'depends': ['state'], }, 'approve': { 'invisible': Eval('state') != 'draft', 'icon': 'tryton-forward', 'depends': ['state'], }, 'succeed': { 'invisible': ~Eval('state').in_(['processing', 'failed']), 'icon': 'tryton-ok', 'depends': ['state'], }, 'fail': { 'invisible': ~Eval('state').in_(['processing', 'succeeded']), 'icon': 'tryton-cancel', 'depends': ['state'], }, }) cls.__rpc__.update({ 'approve': RPC(readonly=False, instantiate=0, fresh_session=True), })
def __setup__(cls): super(Module, cls).__setup__() cls._sql_constraints = [ ('name_uniq', 'unique (name)', 'The name of the module must be unique!'), ] cls._order.insert(0, ('name', 'ASC')) cls.__rpc__.update({ 'on_write': RPC(instantiate=0), }) cls._error_messages.update({ 'delete_state': ('You can not remove a module that is installed ' 'or will be installed'), 'missing_dep': 'Missing dependencies %s for module "%s"', 'uninstall_dep': ('The modules you are trying to uninstall ' 'depends on installed modules:'), }) cls._buttons.update({ 'install': { 'invisible': Eval('state') != 'uninstalled', }, 'install_cancel': { 'invisible': Eval('state') != 'to install', }, 'uninstall': { 'invisible': Eval('state') != 'installed', }, 'uninstall_cancel': { 'invisible': Eval('state') != 'to remove', }, 'upgrade': { 'invisible': Eval('state') != 'installed', }, 'upgrade_cancel': { 'invisible': Eval('state') != 'to upgrade', }, })
def __setup__(cls): super(Statement, cls).__setup__() cls._order[0] = ('id', 'DESC') cls._transitions |= set(( ('draft', 'validated'), ('draft', 'cancelled'), ('validated', 'posted'), ('validated', 'cancelled'), ('cancelled', 'draft'), )) cls._buttons.update({ 'draft': { 'invisible': Eval('state') != 'cancelled', 'depends': ['state'], }, 'validate_statement': { 'invisible': Eval('state') != 'draft', 'depends': ['state'], }, 'post': { 'invisible': Eval('state') != 'validated', 'depends': ['state'], }, 'cancel': { 'invisible': ~Eval('state').in_(['draft', 'validated']), 'depends': ['state'], }, 'reconcile': { 'invisible': Eval('state').in_(['draft', 'cancelled']), 'readonly': ~Eval('to_reconcile'), 'depends': ['state', 'to_reconcile'], }, }) cls.__rpc__.update({ 'post': RPC( readonly=False, instantiate=0, fresh_session=True), })
def __setup__(cls): super(Module, cls).__setup__() table = cls.__table__() cls._sql_constraints = [ ('name_uniq', Unique(table, table.name), 'The name of the module must be unique!'), ] cls._order.insert(0, ('name', 'ASC')) cls.__rpc__.update({ 'on_write': RPC(instantiate=0), }) cls._buttons.update({ 'activate': { 'invisible': Eval('state') != 'not activated', 'depends': ['state'], }, 'activate_cancel': { 'invisible': Eval('state') != 'to activate', 'depends': ['state'], }, 'deactivate': { 'invisible': Eval('state') != 'activated', 'depends': ['state'], }, 'deactivate_cancel': { 'invisible': Eval('state') != 'to remove', 'depends': ['state'], }, 'upgrade': { 'invisible': Eval('state') != 'activated', 'depends': ['state'], }, 'upgrade_cancel': { 'invisible': Eval('state') != 'to upgrade', 'depends': ['state'], }, })
def __call__(self, *args, **kwargs): from trytond.rpc import RPC from trytond.tools import is_instance_method from trytond.transaction import Transaction from trytond.worker import run_task 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: args, kwargs, transaction.context, transaction.timestamp = \ rpc.convert(self._object, *args, **kwargs) meth = getattr(self._object, self._name) if (rpc.instantiate is None or not is_instance_method(self._object, self._name)): 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 ] transaction.commit() while transaction.tasks: task_id = transaction.tasks.pop() run_task(self._config.database_name, task_id) return result
def __setup__(cls): super(ViewTreeState, cls).__setup__() cls.__rpc__.update({ 'set': RPC(readonly=False, check_access=False), 'get': RPC(check_access=False), })
def __setup__(cls): super(ViewTreeWidth, cls).__setup__() cls.__rpc__.update({ 'set_width': RPC(readonly=False), })
def __setup__(cls): super(DictSchemaMixin, cls).__setup__() cls.__rpc__.update({ 'get_keys': RPC(instantiate=0), })
def __setup__(cls): super(Icon, cls).__setup__() cls.__rpc__.update({ 'list_icons': RPC(), })
def __setup__(cls): super().__setup__() cls.__rpc__.update( update=RPC(instantiate=0, readonly=False))
def __setup__(cls): super(Invoice, cls).__setup__() cls.__rpc__.update({ 'render': RPC(instantiate=0), })
def test_simple(self): "Test simple" rpc = RPC(check_access=False) self.assertEqual(rpc.convert(None, 'foo', {}), (['foo'], {}, {}, None))
def __setup__(cls): super(Report, cls).__setup__() cls.__rpc__ = { 'execute': RPC(), }
def __setup__(cls): super(ModelView, cls).__setup__() cls.__rpc__['fields_view_get'] = RPC() cls.__rpc__['view_toolbar_get'] = RPC() cls.__rpc__['on_change'] = RPC(instantiate=0) cls.__rpc__['on_change_with'] = RPC(instantiate=0) cls._buttons = {} fields_ = {} callables = {} for name in dir(cls): if name.startswith('__'): continue attr = getattr(cls, name) if isinstance(attr, fields.Field): fields_[name] = attr elif callable(attr): callables[name] = attr methods = { 'depends': collections.defaultdict(set), 'depend_methods': collections.defaultdict(set), 'change': collections.defaultdict(set), } cls.__change_buttons = methods['change'] def get_callable_attributes(name, method): for parent_cls in cls.__mro__: parent_meth = getattr(parent_cls, name, None) if not parent_meth: continue for attr in ['depends', 'depend_methods', 'change']: parent_value = getattr(parent_meth, attr, None) if parent_value: methods[attr][name] |= parent_value for name, method in callables.items(): get_callable_attributes(name, method) def setup_field(field_name, field, attribute): if attribute == 'selection_change_with': if isinstance(getattr(field, 'selection', None), str): function_name = field.selection else: return else: function_name = '%s_%s' % (attribute, field_name) if not getattr(cls, function_name, None): return function = getattr(cls, function_name, None) setattr( field, attribute, getattr(field, attribute) | methods['depends'][function_name]) meth_names = list(methods['depend_methods'][function_name]) meth_done = set() while meth_names: meth_name = meth_names.pop() assert callable(getattr(cls, meth_name)), \ "%s.%s not callable" % (cls, meth_name) setattr( field, attribute, getattr(field, attribute) | methods['depends'][meth_name]) meth_names += list(methods['depend_methods'][meth_name] - meth_done) meth_done.add(meth_name) if (attribute == 'on_change' and not getattr(function, 'on_change', None)): # Decorate on_change to always return self setattr(cls, function_name, on_change(function)) for name, field in fields_.items(): for attribute in [ 'on_change', 'on_change_with', 'autocomplete', 'selection_change_with', ]: setup_field(name, field, attribute)
def __post_setup__(cls): super(ModelView, cls).__post_setup__() methods = { '_done': set(), 'depends': collections.defaultdict(set), 'depend_methods': collections.defaultdict(set), 'change': collections.defaultdict(set), } cls.__change_buttons = methods['change'] def set_methods(name): if name in methods['_done']: return methods['_done'].add(name) for parent_cls in cls.__mro__: parent_meth = getattr(parent_cls, name, None) if not parent_meth: continue for attr in ['depends', 'depend_methods', 'change']: if isinstance(parent_meth, property): parent_value = getattr(parent_meth.fget, attr, set()) parent_value |= getattr(parent_meth.fset, attr, set()) else: parent_value = getattr(parent_meth, attr, set()) if parent_value: methods[attr][name] |= parent_value def setup_field(field_name, field, attribute): if attribute == 'selection_change_with': if isinstance(getattr(field, 'selection', None), str): function_name = field.selection else: return else: function_name = '%s_%s' % (attribute, field_name) function = getattr(cls, function_name, None) if not function: return set_methods(function_name) setattr(field, attribute, methods['depends'][function_name]) meth_names = list(methods['depend_methods'][function_name]) meth_done = set() while meth_names: meth_name = meth_names.pop() method = getattr(cls, meth_name) assert callable(method) or isinstance(method, property), \ "%s.%s not callable or property" % (cls, meth_name) set_methods(meth_name) setattr( field, attribute, getattr(field, attribute) | methods['depends'][meth_name]) meth_names += list(methods['depend_methods'][meth_name] - meth_done) meth_done.add(meth_name) if (attribute == 'on_change' and not getattr(function, 'on_change', None)): # Decorate on_change to always return self setattr(cls, function_name, on_change(function)) for name, field in cls._fields.items(): for attribute in [ 'on_change', 'on_change_with', 'autocomplete', 'selection_change_with', ]: setup_field(name, field, attribute) # Update __rpc__ for field_name, field in cls._fields.items(): field.set_rpc(cls) for button in cls._buttons: if not is_instance_method(cls, button): cls.__rpc__.setdefault(button, RPC(readonly=False, instantiate=0)) else: cls.__rpc__.setdefault( button, RPC(instantiate=0, result=on_change_result)) meth_names = set() meth_done = set() for parent_cls in cls.__mro__: parent_meth = getattr(parent_cls, button, None) if not parent_meth: continue cls.__change_buttons[button] |= getattr( parent_meth, 'change', set()) meth_names |= getattr(parent_meth, 'change_methods', set()) while meth_names: meth_name = meth_names.pop() method = getattr(cls, meth_name) assert callable(method) or isinstance(method, property), \ "%s.%s not callable or property" % (cls, meth_name) set_methods(meth_name) cls.__change_buttons[button] |= methods['depends'][meth_name] meth_names |= (methods['depend_methods'][meth_name] - meth_done) meth_done.add(meth_name) set_methods('on_change_notify') cls._on_change_notify_depends = methods['depends']['on_change_notify'] meth_names = list(methods['depend_methods']['on_change_notify']) meth_done = set() while meth_names: meth_name = meth_names.pop() method = getattr(cls, meth_name) assert callable(method) or isinstance(method, property), \ "%s.%s not callable or property" % (cls, meth_name) set_methods(meth_name) cls._on_change_notify_depends |= methods['depends'][meth_name] meth_names += list(methods['depend_methods'][meth_name] - meth_done) meth_done.add(meth_name)
def __setup__(cls): super(Currency, cls).__setup__() cls._order.insert(0, ('code', 'ASC')) cls.__rpc__.update({ 'compute': RPC(instantiate=slice(0, 3, 2)), })
def test_timestamp(self): "Test context timestamp" rpc = RPC(check_access=False) self.assertEqual(rpc.convert(None, {'_timestamp': 'test'}), ([], {}, {}, 'test'))
def __setup__(cls): super(ViewSearch, cls).__setup__() cls.__rpc__.update({ 'get_search': RPC(), })
def __setup__(cls): super().__setup__() cls.__rpc__.update({ 'renew': RPC(readonly=False), })
def dispatch(host, port, protocol, database_name, user, session, object_type, object_name, method, *args, **kwargs): 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'), ('lt_LT', 'Lietuvių'), ('nl_NL', 'Nederlands'), ('ru_RU', 'Russian'), ] 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 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, **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 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) if hasattr(obj, '_buttons'): for button in obj._buttons: res.append(type + '.' + object_name + '.' + button) 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(int(CONFIG['retry']), -1, -1): try: user = security.check(database_name, user, session) except DatabaseOperationalError: if count: continue raise break 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__: rpc = obj.__rpc__[method] elif method in getattr(obj, '_buttons', {}): rpc = RPC(readonly=False, instantiate=0) 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=rpc.readonly) as transaction: try: args, kwargs, transaction.context, transaction.timestamp = \ rpc.convert(obj, *args, **kwargs) meth = getattr(obj, method) 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, method): result = rpc.result(meth(inst, *args, **kwargs)) else: result = [rpc.result(meth(i, *args, **kwargs)) for i in inst] if not rpc.readonly: transaction.cursor.commit() except DatabaseOperationalError, exception: transaction.cursor.rollback() if count and not rpc.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 __setup__(cls): super(Icon, cls).__setup__() cls._order.insert(0, ('sequence', 'ASC')) cls.__rpc__.update({ 'list_icons': RPC(), })
def __setup__(cls): super(DebugModelInstance, cls).__setup__() cls._order.insert(0, ('name', 'ASC')) cls.__rpc__.update({'refresh': RPC(readonly=False)}) cls._buttons.update({'open_initial': {}})