def load_test(module_name, idref, mode): cr.commit() try: _load_data(cr, module_name, idref, mode, 'test') return True except Exception: _test_logger.exception( 'module %s: an exception occurred in a test', module_name) return False finally: if tools.config.options['test_commit']: cr.commit() else: cr.rollback() # avoid keeping stale xml_id, etc. in cache actpy.registry(cr.dbname).clear_caches()
def __getattr__(self, name): cr = self._cursor if cr is None: from actpy import registry cr = self._cursor = registry(self.dbname).cursor() for _ in range(self._depth): cr.__enter__() return getattr(cr, name)
def environment(): """ Return an environment with a new cursor for the current database; the cursor is committed and closed after the context block. """ reg = registry(common.get_db_name()) with reg.cursor() as cr: yield api.Environment(cr, SUPERUSER_ID, {}) cr.commit()
def execute(db, uid, obj, method, *args, **kw): threading.currentThread().dbname = db with actpy.registry(db).cursor() as cr: check_method_name(method) res = execute_cr(cr, uid, obj, method, *args, **kw) if res is None: _logger.info('The method %s of the object %s can not return `None` !', method, obj) return res
def check_session(session): with actpy.registry(session.db).cursor() as cr: self = actpy.api.Environment(cr, session.uid, {})['res.users'].browse(session.uid) if actpy.tools.misc.consteq(self._compute_session_token(session.sid), session.session_token): return True self._invalidate_session_cache() return False
def receive(self, req): """ End-point to receive mail from an external SMTP server. """ dbs = req.jsonrequest.get('databases') for db in dbs: message = base64.b64decode(dbs[db]) try: db_registry = registry(db) with db_registry.cursor() as cr: env = api.Environment(cr, SUPERUSER_ID, {}) env['mail.thread'].message_process(None, message) except psycopg2.Error: pass return True
def setUp(self): # check that the registry is properly reset registry = actpy.registry() fnames = set(registry[self.MODEL]._fields) @self.addCleanup def check_registry(): assert set(registry[self.MODEL]._fields) == fnames super(TestCustomFields, self).setUp() # use a test cursor instead of a real cursor self.registry.enter_test_mode() self.addCleanup(self.registry.leave_test_mode) # do not reload the registry after removing a field self.env = self.env(context={'_force_unlink': True})
def oauth2callback(self, **kw): """ This route/function is called by Google when user Accept/Refuse the consent of Google """ state = json.loads(kw['state']) dbname = state.get('d') service = state.get('s') url_return = state.get('f') with registry(dbname).cursor() as cr: if kw.get('code'): request.env(cr, request.session.uid)['google.%s' % service].set_all_tokens( kw['code']) return redirect(url_return) elif kw.get('error'): return redirect("%s%s%s" % (url_return, "?error=", kw['error'])) else: return redirect("%s%s" % (url_return, "?error=Unknown_error"))
def run_scheduler(self, use_new_cursor=False, company_id=False): """ Call the scheduler in order to check the running procurements (super method), to check the minimum stock rules and the availability of moves. This function is intended to be run for all the companies at the same time, so we run functions as SUPERUSER to avoid intercompanies and access rights issues. """ try: if use_new_cursor: cr = registry(self._cr.dbname).cursor() self = self.with_env(self.env(cr=cr)) # TDE FIXME self._run_scheduler_tasks(use_new_cursor=use_new_cursor, company_id=company_id) finally: if use_new_cursor: try: self._cr.close() except Exception: pass return {}
def shell(self, dbname): local_vars = { 'openerp': actpy, 'actpy': actpy, } with actpy.api.Environment.manage(): if dbname: registry = actpy.registry(dbname) with registry.cursor() as cr: uid = actpy.SUPERUSER_ID ctx = actpy.api.Environment(cr, uid, {})['res.users'].context_get() env = actpy.api.Environment(cr, uid, ctx) local_vars['env'] = env local_vars['self'] = env.user self.console(local_vars) cr.rollback() else: self.console(local_vars)
def dispatch(method, params): (db, uid, passwd ) = params[0:3] # set uid tracker - cleaned up at the WSGI # dispatching phase in actpy.service.wsgi_server.application threading.current_thread().uid = uid params = params[3:] if method == 'obj_list': raise NameError("obj_list has been discontinued via RPC as of 6.0, please query ir.model directly!") if method not in ['execute', 'execute_kw']: raise NameError("Method not available %s" % method) security.check(db,uid,passwd) registry = actpy.registry(db).check_signaling() fn = globals()[method] with registry.manage_changes(): res = fn(db, uid, *params) return res
def setUp(self): self.registry = actpy.registry(get_db_name()) #: current transaction's cursor self.cr = self.cursor() self.uid = actpy.SUPERUSER_ID #: :class:`~actpy.api.Environment` for the current test case self.env = api.Environment(self.cr, self.uid, {}) @self.addCleanup def reset(): # rollback and close the cursor, and reset the environments self.registry.clear_caches() self.registry.reset_changes() self.env.reset() self.cr.rollback() self.cr.close() self.patch(type(self.env['res.partner']), '_get_gravatar_image', lambda *a: False)
def _login(cls, db, login, password): user_id = super(Users, cls)._login(db, login, password) if user_id: return user_id with registry(db).cursor() as cr: cr.execute("SELECT id FROM res_users WHERE lower(login)=%s", (login, )) res = cr.fetchone() if res: return False env = api.Environment(cr, SUPERUSER_ID, {}) Ldap = env['res.company.ldap'] for conf in Ldap.get_ldap_dicts(): entry = Ldap.authenticate(conf, login, password) if entry: user_id = Ldap.get_or_create_user(conf, login, entry) if user_id: break return user_id
def poll(self, dbname, channels, last, options=None, timeout=TIMEOUT): if options is None: options = {} # Dont hang ctrl-c for a poll request, we need to bypass private # attribute access because we dont know before starting the thread that # it will handle a longpolling request if not actpy.evented: current = threading.current_thread() current._Thread__daemonic = True # PY2 current._daemonic = True # PY3 # rename the thread to avoid tests waiting for a longpolling current.setName("actpy.longpolling.request.%s" % current.ident) registry = actpy.registry(dbname) # immediatly returns if past notifications exist with registry.cursor() as cr: env = api.Environment(cr, SUPERUSER_ID, {}) notifications = env['bus.bus'].poll(channels, last, options) # immediatly returns in peek mode if options.get('peek'): return dict(notifications=notifications, channels=channels) # or wait for future ones if not notifications: if not self.started: # Lazy start of events listener self.start() event = self.Event() for channel in channels: self.channels.setdefault(hashable(channel), []).append(event) try: event.wait(timeout=timeout) with registry.cursor() as cr: env = api.Environment(cr, SUPERUSER_ID, {}) notifications = env['bus.bus'].poll(channels, last, options, force_status=True) except Exception: # timeout pass return notifications
def _refresh_google_token_json( self, refresh_token, service): # exchange_AUTHORIZATION vs Token (service = calendar) get_param = self.env['ir.config_parameter'].sudo().get_param client_id = get_param('google_%s_client_id' % (service, ), default=False) client_secret = get_param('google_%s_client_secret' % (service, ), default=False) if not client_id or not client_secret: raise UserError( _("The account for the Google service '%s' is not configured") % service) headers = {"content-type": "application/x-www-form-urlencoded"} data = { 'refresh_token': refresh_token, 'client_id': client_id, 'client_secret': client_secret, 'grant_type': 'refresh_token', } try: dummy, response, dummy = self._do_request(GOOGLE_TOKEN_ENDPOINT, params=data, headers=headers, type='POST', preuri='') return response except requests.HTTPError as error: if error.response.status_code == 400: # invalid grant with registry(request.session.db).cursor() as cur: self.env(cur)['res.users'].browse(self.env.uid).write( {'google_%s_rtoken' % service: False}) error_key = error.response.json().get("error", "nc") _logger.exception("Bad google request : %s !", error_key) error_msg = _( "Something went wrong during your token generation. Maybe your Authorization Code is invalid or already expired [%s]" ) % error_key raise self.env['res.config.settings'].get_config_warning(error_msg)
def log_xml(self, xml_string, func): self.ensure_one() if self.debug_logging: db_name = self._cr.dbname # Use a new cursor to avoid rollback that could be caused by an upper method try: db_registry = registry(db_name) with db_registry.cursor() as cr: env = api.Environment(cr, SUPERUSER_ID, {}) IrLogging = env['ir.logging'] IrLogging.sudo().create({'name': 'delivery.carrier', 'type': 'server', 'dbname': db_name, 'level': 'DEBUG', 'message': xml_string, 'path': self.delivery_type, 'func': func, 'line': 1}) except psycopg2.Error: pass
def _auth_method_calendar(cls): token = request.params['token'] dbname = request.params['db'] registry = actpy.registry(dbname) error_message = False with registry.cursor() as cr: env = Environment(cr, SUPERUSER_ID, {}) attendee = env['calendar.attendee'].sudo().search( [('access_token', '=', token)], limit=1) if not attendee: error_message = """Invalid Invitation Token.""" elif request.session.uid and request.session.login != 'anonymous': # if valid session but user is not match user = env['res.users'].sudo().browse(request.session.uid) if attendee.partner_id != user.partner_id: error_message = """Invitation cannot be forwarded via email. This event/meeting belongs to %s and you are logged in as %s. Please ask organizer to add you.""" % ( attendee.email, user.email) if error_message: raise BadRequest(error_message) return True
def send_notifications(): db_registry = registry(dbname) with api.Environment.manage(), db_registry.cursor() as cr: env = api.Environment(cr, SUPERUSER_ID, _context) env['mail.mail'].browse(email_ids).send()
def _process_jobs(cls, db_name): """ Try to process all cron jobs. This selects in database all the jobs that should be processed. It then tries to lock each of them and, if it succeeds, run the cron job (if it doesn't succeed, it means the job was already locked to be taken care of by another thread) and return. :raise BadVersion: if the version is different from the worker's :raise BadModuleState: if modules are to install/upgrade/remove """ db = actpy.sql_db.db_connect(db_name) threading.current_thread().dbname = db_name try: with db.cursor() as cr: # Make sure the database has the same version as the code of # base and that no module must be installed/upgraded/removed cr.execute( "SELECT latest_version FROM ir_module_module WHERE name=%s", ['base']) (version, ) = cr.fetchone() cr.execute( "SELECT COUNT(*) FROM ir_module_module WHERE state LIKE %s", ['to %']) (changes, ) = cr.fetchone() if version is None: raise BadModuleState() elif version != BASE_VERSION: raise BadVersion() # Careful to compare timestamps with 'UTC' - everything is UTC as of v6.1. cr.execute("""SELECT * FROM ir_cron WHERE numbercall != 0 AND active AND nextcall <= (now() at time zone 'UTC') ORDER BY priority""") jobs = cr.dictfetchall() if changes: if not jobs: raise BadModuleState() # nextcall is never updated if the cron is not executed, # it is used as a sentinel value to check whether cron jobs # have been locked for a long time (stuck) parse = fields.Datetime.from_string oldest = min([parse(job['nextcall']) for job in jobs]) if datetime.now() - oldest > MAX_FAIL_TIME: actpy.modules.reset_modules_state(db_name) else: raise BadModuleState() for job in jobs: lock_cr = db.cursor() try: # Try to grab an exclusive lock on the job row from within the task transaction # Restrict to the same conditions as for the search since the job may have already # been run by an other thread when cron is running in multi thread lock_cr.execute("""SELECT * FROM ir_cron WHERE numbercall != 0 AND active AND nextcall <= (now() at time zone 'UTC') AND id=%s FOR UPDATE NOWAIT""", (job['id'], ), log_exceptions=False) locked_job = lock_cr.fetchone() if not locked_job: _logger.debug( "Job `%s` already executed by another process/thread. skipping it", job['cron_name']) continue # Got the lock on the job row, run its code _logger.info('Starting job `%s`.', job['cron_name']) job_cr = db.cursor() try: registry = actpy.registry(db_name) registry[cls._name]._process_job(job_cr, job, lock_cr) except Exception: _logger.exception( 'Unexpected exception while processing cron job %r', job) finally: job_cr.close() except psycopg2.OperationalError as e: if e.pgcode == '55P03': # Class 55: Object not in prerequisite state; 55P03: lock_not_available _logger.debug( 'Another process/thread is already busy executing job `%s`, skipping it.', job['cron_name']) continue else: # Unexpected OperationalError raise finally: # we're exiting due to an exception while acquiring the lock lock_cr.close() finally: if hasattr(threading.current_thread(), 'dbname'): del threading.current_thread().dbname
def _procure_orderpoint_confirm(self, use_new_cursor=False, company_id=False): """ Create procurements based on orderpoints. :param bool use_new_cursor: if set, use a dedicated cursor and auto-commit after processing 1000 orderpoints. This is appropriate for batch jobs only. """ if company_id and self.env.user.company_id.id != company_id: # To ensure that the company_id is taken into account for # all the processes triggered by this method # i.e. If a PO is generated by the run of the procurements the # sequence to use is the one for the specified company not the # one of the user's company self = self.with_context(company_id=company_id, force_company=company_id) OrderPoint = self.env['stock.warehouse.orderpoint'] domain = self._get_orderpoint_domain(company_id=company_id) orderpoints_noprefetch = OrderPoint.with_context( prefetch_fields=False).search( domain, order=self._procurement_from_orderpoint_get_order()).ids while orderpoints_noprefetch: if use_new_cursor: cr = registry(self._cr.dbname).cursor() self = self.with_env(self.env(cr=cr)) OrderPoint = self.env['stock.warehouse.orderpoint'] orderpoints = OrderPoint.browse(orderpoints_noprefetch[:1000]) orderpoints_noprefetch = orderpoints_noprefetch[1000:] # Calculate groups that can be executed together location_data = defaultdict(lambda: dict( products=self.env['product.product'], orderpoints=self.env['stock.warehouse.orderpoint'], groups=list())) for orderpoint in orderpoints: key = self._procurement_from_orderpoint_get_grouping_key( [orderpoint.id]) location_data[key]['products'] += orderpoint.product_id location_data[key]['orderpoints'] += orderpoint location_data[key][ 'groups'] = self._procurement_from_orderpoint_get_groups( [orderpoint.id]) for location_id, location_data in location_data.items(): location_orderpoints = location_data['orderpoints'] product_context = dict( self._context, location=location_orderpoints[0].location_id.id) substract_quantity = location_orderpoints._quantity_in_progress( ) for group in location_data['groups']: if group.get('from_date'): product_context['from_date'] = group[ 'from_date'].strftime( DEFAULT_SERVER_DATETIME_FORMAT) if group['to_date']: product_context['to_date'] = group['to_date'].strftime( DEFAULT_SERVER_DATETIME_FORMAT) product_quantity = location_data['products'].with_context( product_context)._product_available() for orderpoint in location_orderpoints: try: op_product_virtual = product_quantity[ orderpoint.product_id.id]['virtual_available'] if op_product_virtual is None: continue if float_compare(op_product_virtual, orderpoint.product_min_qty, precision_rounding=orderpoint. product_uom.rounding) <= 0: qty = max(orderpoint.product_min_qty, orderpoint.product_max_qty ) - op_product_virtual remainder = orderpoint.qty_multiple > 0 and qty % orderpoint.qty_multiple or 0.0 if float_compare(remainder, 0.0, precision_rounding=orderpoint. product_uom.rounding) > 0: qty += orderpoint.qty_multiple - remainder if float_compare(qty, 0.0, precision_rounding=orderpoint. product_uom.rounding) < 0: continue qty -= substract_quantity[orderpoint.id] qty_rounded = float_round( qty, precision_rounding=orderpoint.product_uom. rounding) if qty_rounded > 0: values = orderpoint._prepare_procurement_values( qty_rounded, **group['procurement_values']) try: with self._cr.savepoint(): self.env['procurement.group'].run( orderpoint.product_id, qty_rounded, orderpoint.product_uom, orderpoint.location_id, orderpoint.name, orderpoint.name, values) except UserError as error: self.env[ 'procurement.rule']._log_next_activity( orderpoint.product_id, error.name) self._procurement_from_orderpoint_post_process( [orderpoint.id]) if use_new_cursor: cr.commit() except OperationalError: if use_new_cursor: orderpoints_noprefetch += [orderpoint.id] cr.rollback() continue else: raise try: if use_new_cursor: cr.commit() except OperationalError: if use_new_cursor: cr.rollback() continue else: raise if use_new_cursor: cr.commit() cr.close() return {}
def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules=None, report=None): """Migrates+Updates or Installs all module nodes from ``graph`` :param graph: graph of module nodes to load :param status: deprecated parameter, unused, left to avoid changing signature in 8.0 :param perform_checks: whether module descriptors should be checked for validity (prints warnings for same cases) :param skip_modules: optional list of module names (packages) which have previously been loaded and can be skipped :return: list of modules that were installed or updated """ def load_test(module_name, idref, mode): cr.commit() try: _load_data(cr, module_name, idref, mode, 'test') return True except Exception: _test_logger.exception( 'module %s: an exception occurred in a test', module_name) return False finally: if tools.config.options['test_commit']: cr.commit() else: cr.rollback() # avoid keeping stale xml_id, etc. in cache actpy.registry(cr.dbname).clear_caches() def _get_files_of_kind(kind): if kind == 'demo': kind = ['demo_xml', 'demo'] elif kind == 'data': kind = ['init_xml', 'update_xml', 'data'] if isinstance(kind, str): kind = [kind] files = [] for k in kind: for f in package.data[k]: files.append(f) if k.endswith('_xml') and not (k == 'init_xml' and not f.endswith('.xml')): # init_xml, update_xml and demo_xml are deprecated except # for the case of init_xml with yaml, csv and sql files as # we can't specify noupdate for those file. correct_key = 'demo' if k.count('demo') else 'data' _logger.warning( "module %s: key '%s' is deprecated in favor of '%s' for file '%s'.", package.name, k, correct_key, f) return files def _load_data(cr, module_name, idref, mode, kind): """ kind: data, demo, test, init_xml, update_xml, demo_xml. noupdate is False, unless it is demo data or it is csv data in init mode. """ try: if kind in ('demo', 'test'): threading.currentThread().testing = True for filename in _get_files_of_kind(kind): _logger.info("loading %s/%s", module_name, filename) noupdate = False if kind in ('demo', 'demo_xml') or (filename.endswith('.csv') and kind in ('init', 'init_xml')): noupdate = True tools.convert_file(cr, module_name, filename, idref, mode, noupdate, kind, report) finally: if kind in ('demo', 'test'): threading.currentThread().testing = False processed_modules = [] loaded_modules = [] registry = actpy.registry(cr.dbname) migrations = actpy.modules.migration.MigrationManager(cr, graph) module_count = len(graph) _logger.info('loading %d modules...', module_count) registry.clear_caches() # register, instantiate and initialize models for each modules t0 = time.time() t0_sql = actpy.sql_db.sql_counter for index, package in enumerate(graph, 1): module_name = package.name module_id = package.id if skip_modules and module_name in skip_modules: continue _logger.debug('loading module %s (%d/%d)', module_name, index, module_count) migrations.migrate_module(package, 'pre') load_openerp_module(package.name) new_install = package.state == 'to install' if new_install: py_module = sys.modules['actpy.addons.%s' % (module_name, )] pre_init = package.info.get('pre_init_hook') if pre_init: getattr(py_module, pre_init)(cr) model_names = registry.load(cr, package) loaded_modules.append(package.name) if hasattr(package, 'init') or hasattr( package, 'update') or package.state in ('to install', 'to upgrade'): registry.setup_models(cr) registry.init_models(cr, model_names, {'module': package.name}) cr.commit() idref = {} mode = 'update' if hasattr(package, 'init') or package.state == 'to install': mode = 'init' if hasattr(package, 'init') or hasattr( package, 'update') or package.state in ('to install', 'to upgrade'): env = api.Environment(cr, SUPERUSER_ID, {}) # Can't put this line out of the loop: ir.module.module will be # registered by init_models() above. module = env['ir.module.module'].browse(module_id) if perform_checks: module._check() if package.state == 'to upgrade': # upgrading the module information module.write(module.get_values_from_terp(package.data)) _load_data(cr, module_name, idref, mode, kind='data') has_demo = hasattr(package, 'demo') or (package.dbdemo and package.state != 'installed') if has_demo: _load_data(cr, module_name, idref, mode, kind='demo') cr.execute('update ir_module_module set demo=%s where id=%s', (True, module_id)) module.invalidate_cache(['demo']) migrations.migrate_module(package, 'post') # Update translations for all installed languages overwrite = actpy.tools.config["overwrite_existing_translations"] module.with_context(overwrite=overwrite)._update_translations() if package.name is not None: registry._init_modules.add(package.name) if new_install: post_init = package.info.get('post_init_hook') if post_init: getattr(py_module, post_init)(cr, registry) # validate all the views at a whole env['ir.ui.view']._validate_module_views(module_name) if has_demo: # launch tests only in demo mode, allowing tests to use demo data. if tools.config.options['test_enable']: # Yamel test report.record_result(load_test(module_name, idref, mode)) # Python tests env['ir.http']._clear_routing_map( ) # force routing map to be rebuilt report.record_result( actpy.modules.module.run_unit_tests( module_name, cr.dbname)) # tests may have reset the environment env = api.Environment(cr, SUPERUSER_ID, {}) module = env['ir.module.module'].browse(module_id) processed_modules.append(package.name) ver = adapt_version(package.data['version']) # Set new modules and dependencies module.write({'state': 'installed', 'latest_version': ver}) package.load_state = package.state package.load_version = package.installed_version package.state = 'installed' for kind in ('init', 'demo', 'update'): if hasattr(package, kind): delattr(package, kind) if package.name is not None: registry._init_modules.add(package.name) cr.commit() _logger.log(25, "%s modules loaded in %.2fs, %s queries", len(graph), time.time() - t0, actpy.sql_db.sql_counter - t0_sql) registry.clear_caches() cr.commit() return loaded_modules, processed_modules
def load_modules(db, force_demo=False, status=None, update_module=False): initialize_sys_path() force = [] if force_demo: force.append('demo') cr = db.cursor() try: if not actpy.modules.db.is_initialized(cr): _logger.info("init db") actpy.modules.db.initialize(cr) update_module = True # process auto-installed modules tools.config["init"]["all"] = 1 tools.config['update']['all'] = 1 if not tools.config['without_demo']: tools.config["demo"]['all'] = 1 # This is a brand new registry, just created in # actpy.modules.registry.Registry.new(). registry = actpy.registry(cr.dbname) if 'base' in tools.config['update'] or 'all' in tools.config['update']: cr.execute( "update ir_module_module set state=%s where name=%s and state=%s", ('to upgrade', 'base', 'installed')) # STEP 1: LOAD BASE (must be done before module dependencies can be computed for later steps) graph = actpy.modules.graph.Graph() graph.add_module(cr, 'base', force) if not graph: _logger.critical( 'module base cannot be loaded! (hint: verify addons-path)') raise ImportError( 'Module `base` cannot be loaded! (hint: verify addons-path)') # processed_modules: for cleanup step after install # loaded_modules: to avoid double loading report = registry._assertion_report loaded_modules, processed_modules = load_module_graph( cr, graph, status, perform_checks=update_module, report=report) load_lang = tools.config.pop('load_language') if load_lang or update_module: # some base models are used below, so make sure they are set up registry.setup_models(cr) if load_lang: for lang in load_lang.split(','): tools.load_language(cr, lang) # STEP 2: Mark other modules to be loaded/updated if update_module: env = api.Environment(cr, SUPERUSER_ID, {}) Module = env['ir.module.module'] _logger.info('updating modules list') Module.update_list() _check_module_names( cr, itertools.chain(tools.config['init'], tools.config['update'])) module_names = [k for k, v in tools.config['init'].items() if v] if module_names: modules = Module.search([('state', '=', 'uninstalled'), ('name', 'in', module_names)]) if modules: modules.button_install() module_names = [k for k, v in tools.config['update'].items() if v] if module_names: modules = Module.search([('state', '=', 'installed'), ('name', 'in', module_names)]) if modules: modules.button_upgrade() cr.execute("update ir_module_module set state=%s where name=%s", ('installed', 'base')) Module.invalidate_cache(['state']) # STEP 3: Load marked modules (skipping base which was done in STEP 1) # IMPORTANT: this is done in two parts, first loading all installed or # partially installed modules (i.e. installed/to upgrade), to # offer a consistent system to the second part: installing # newly selected modules. # We include the modules 'to remove' in the first step, because # they are part of the "currently installed" modules. They will # be dropped in STEP 6 later, before restarting the loading # process. # IMPORTANT 2: We have to loop here until all relevant modules have been # processed, because in some rare cases the dependencies have # changed, and modules that depend on an uninstalled module # will not be processed on the first pass. # It's especially useful for migrations. previously_processed = -1 while previously_processed < len(processed_modules): previously_processed = len(processed_modules) processed_modules += load_marked_modules( cr, graph, ['installed', 'to upgrade', 'to remove'], force, status, report, loaded_modules, update_module) if update_module: processed_modules += load_marked_modules( cr, graph, ['to install'], force, status, report, loaded_modules, update_module) registry.loaded = True registry.setup_models(cr) # STEP 3.5: execute migration end-scripts migrations = actpy.modules.migration.MigrationManager(cr, graph) for package in graph: migrations.migrate_module(package, 'end') # STEP 4: Finish and cleanup installations if processed_modules: env = api.Environment(cr, SUPERUSER_ID, {}) cr.execute( """select model,name from ir_model where id NOT IN (select distinct model_id from ir_model_access)""" ) for (model, name) in cr.fetchall(): if model in registry and not registry[ model]._abstract and not registry[model]._transient: _logger.warning( 'The model %s has no access rules, consider adding one. E.g. access_%s,access_%s,model_%s,,1,0,0,0', model, model.replace('.', '_'), model.replace('.', '_'), model.replace('.', '_')) # Temporary warning while we remove access rights on osv_memory objects, as they have # been replaced by owner-only access rights cr.execute( """select distinct mod.model, mod.name from ir_model_access acc, ir_model mod where acc.model_id = mod.id""" ) for (model, name) in cr.fetchall(): if model in registry and registry[model]._transient: _logger.warning( 'The transient model %s (%s) should not have explicit access rules!', model, name) cr.execute("SELECT model from ir_model") for (model, ) in cr.fetchall(): if model in registry: env[model]._check_removed_columns(log=True) elif _logger.isEnabledFor( logging.INFO): # more an info that a warning... _logger.warning( "Model %s is declared but cannot be loaded! (Perhaps a module was partially removed or renamed)", model) # Cleanup orphan records env['ir.model.data']._process_end(processed_modules) for kind in ('init', 'demo', 'update'): tools.config[kind] = {} cr.commit() # STEP 5: Uninstall modules to remove if update_module: # Remove records referenced from ir_model_data for modules to be # removed (and removed the references from ir_model_data). cr.execute("SELECT name, id FROM ir_module_module WHERE state=%s", ('to remove', )) modules_to_remove = dict(cr.fetchall()) if modules_to_remove: env = api.Environment(cr, SUPERUSER_ID, {}) pkgs = reversed( [p for p in graph if p.name in modules_to_remove]) for pkg in pkgs: uninstall_hook = pkg.info.get('uninstall_hook') if uninstall_hook: py_module = sys.modules['actpy.addons.%s' % (pkg.name, )] getattr(py_module, uninstall_hook)(cr, registry) Module = env['ir.module.module'] Module.browse(modules_to_remove.values()).module_uninstall() # Recursive reload, should only happen once, because there should be no # modules to remove next time cr.commit() _logger.info( 'Reloading registry once more after uninstalling modules') api.Environment.reset() registry = actpy.modules.registry.Registry.new( cr.dbname, force_demo, status, update_module) registry.check_tables_exist(cr) cr.commit() return registry # STEP 6: verify custom views on every model if update_module: env = api.Environment(cr, SUPERUSER_ID, {}) View = env['ir.ui.view'] for model in registry: try: View._validate_custom_views(model) except Exception as e: _logger.warning('invalid custom view(s) for model %s: %s', model, tools.ustr(e)) if report.failures: _logger.error('At least one test failed when loading the modules.') else: _logger.info('Modules loaded.') # STEP 8: call _register_hook on every model env = api.Environment(cr, SUPERUSER_ID, {}) for model in env.values(): model._register_hook() # STEP 9: save installed/updated modules for post-install tests registry.updated_modules += processed_modules cr.commit() finally: cr.close()
def compute_session_token(session): with actpy.registry(session.db).cursor() as cr: self = actpy.api.Environment(cr, session.uid, {})['res.users'].browse(session.uid) return self._compute_session_token(session.sid)
def check(db, uid, passwd): res_users = actpy.registry(db)['res.users'] return res_users.check(db, uid, passwd)
def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=None, reply_to=False, attachments=None, message_id=None, references=None, openobject_id=False, debug=False, subtype='plain', headers=None, smtp_server=None, smtp_port=None, ssl=False, smtp_user=None, smtp_password=None, cr=None, uid=None): """Low-level function for sending an email (deprecated). :deprecate: since OpenERP 6.1, please use ir.mail_server.send_email() instead. :param email_from: A string used to fill the `From` header, if falsy, config['email_from'] is used instead. Also used for the `Reply-To` header if `reply_to` is not provided :param email_to: a sequence of addresses to send the mail to. """ # If not cr, get cr from current thread database local_cr = None if not cr: db_name = getattr(threading.currentThread(), 'dbname', None) if db_name: local_cr = cr = actpy.registry(db_name).cursor() else: raise Exception( "No database cursor found, please pass one explicitly") # Send Email try: mail_server_pool = actpy.registry(cr.dbname)['ir.mail_server'] res = False # Pack Message into MIME Object email_msg = mail_server_pool.build_email(email_from, email_to, subject, body, email_cc, email_bcc, reply_to, attachments, message_id, references, openobject_id, subtype, headers=headers) res = mail_server_pool.send_email( cr, uid or 1, email_msg, mail_server_id=None, smtp_server=smtp_server, smtp_port=smtp_port, smtp_user=smtp_user, smtp_password=smtp_password, smtp_encryption=('ssl' if ssl else None), smtp_debug=debug) except Exception: _logger.exception("tools.email_send failed to deliver email") return False finally: if local_cr: cr.close() return res
def setUpClass(cls): cls.registry = actpy.registry(get_db_name()) cls.cr = cls.registry.cursor() cls.uid = actpy.SUPERUSER_ID cls.env = api.Environment(cls.cr, cls.uid, {})
def migrate(cr, version): registry = actpy.registry(cr.dbname) from actpy.addons.account.models.chart_template import migrate_set_tags_and_taxes_updatable migrate_set_tags_and_taxes_updatable(cr, registry, 'l10n_ch')
def login(db, login, password): res_users = actpy.registry(db)['res.users'] return res_users._login(db, login, password)
def migrate(cr, version): registry = actpy.registry(cr.dbname) from actpy.addons.account.models.chart_template import migrate_tags_on_taxes migrate_tags_on_taxes(cr, registry)
def registry(): return actpy.registry(common.get_db_name())