def _get_asset_content(self, xmlid, options): options = dict(self.env.context) options.update(options, inherit_branding=False, inherit_branding_auto=False, edit_translations=False, translatable=False, rendering_bundle=True) env = self.env(context=options) # TODO: This helper can be used by any template that wants to embedd the backend. # It is currently necessary because the ir.ui.view bundle inheritance does not # match the module dependency graph. def get_modules_order(): if request: from odoo.addons.web.controllers.main import module_boot return json.dumps(module_boot()) return '[]' template = env['ir.qweb'].render(xmlid, {"get_modules_order": get_modules_order}) files = [] remains = [] for el in html.fragments_fromstring(template): if isinstance(el, basestring): remains.append(el) elif isinstance(el, html.HtmlElement): href = el.get('href', '') src = el.get('src', '') atype = el.get('type') media = el.get('media') can_aggregate = not urlparse(href).netloc and not href.startswith('/web/content') if el.tag == 'style' or (el.tag == 'link' and el.get('rel') == 'stylesheet' and can_aggregate): if href.endswith('.sass'): atype = 'text/sass' elif href.endswith('.less'): atype = 'text/less' if atype not in ('text/less', 'text/sass'): atype = 'text/css' path = filter(None, href.split('/')) filename = get_resource_path(*path) files.append({'atype': atype, 'url': href, 'filename': filename, 'content': el.text, 'media': media}) elif el.tag == 'script': atype = 'text/javascript' if src: path = filter(None, src.split('/')) filename = get_resource_path(*path) else: filename = None files.append({'atype': atype, 'url': src, 'filename': filename, 'content': el.text, 'media': media}) else: remains.append(html.tostring(el)) else: try: remains.append(html.tostring(el)) except Exception: # notYETimplementederror raise NotImplementedError return (files, remains)
def _get_asset_content(self, xmlid, options): options = dict(options, inherit_branding=False, inherit_branding_auto=False, edit_translations=False, translatable=False, rendering_bundle=True) options['website_id'] = self.env.context.get('website_id') IrQweb = self.env['ir.qweb'].with_context(options) def can_aggregate(url): return not urls.url_parse(url).scheme and not urls.url_parse(url).netloc and not url.startswith('/web/content') # TODO: This helper can be used by any template that wants to embedd the backend. # It is currently necessary because the ir.ui.view bundle inheritance does not # match the module dependency graph. def get_modules_order(): if request: from odoo.addons.web.controllers.main import module_boot return json.dumps(module_boot()) return '[]' template = IrQweb.render(xmlid, {"get_modules_order": get_modules_order}) files = [] remains = [] for el in html.fragments_fromstring(template): if isinstance(el, html.HtmlElement): href = el.get('href', '') src = el.get('src', '') atype = el.get('type') media = el.get('media') if can_aggregate(href) and (el.tag == 'style' or (el.tag == 'link' and el.get('rel') == 'stylesheet')): if href.endswith('.sass'): atype = 'text/sass' elif href.endswith('.scss'): atype = 'text/scss' elif href.endswith('.less'): atype = 'text/less' if atype not in ('text/less', 'text/scss', 'text/sass'): atype = 'text/css' path = [segment for segment in href.split('/') if segment] filename = get_resource_path(*path) if path else None files.append({'atype': atype, 'url': href, 'filename': filename, 'content': el.text, 'media': media}) elif can_aggregate(src) and el.tag == 'script': atype = 'text/javascript' path = [segment for segment in src.split('/') if segment] filename = get_resource_path(*path) if path else None files.append({'atype': atype, 'url': src, 'filename': filename, 'content': el.text, 'media': media}) else: remains.append((el.tag, OrderedDict(el.attrib), el.text)) else: # the other cases are ignored pass return (files, remains)
def compile_css(self, cmd, source, atype): """Sanitizes @import rules, remove duplicates @import rules, then compile""" imports = [] def handle_compile_error(e, source): error = self.get_preprocessor_error(e, source=source) _logger.warning(error) self.css_errors.append(error) return '' def sanitize(matchobj): ref = matchobj.group(2) line = '@import "%s"%s' % (ref, matchobj.group(3)) if '.' not in ref and line not in imports and not ref.startswith(('.', '/', '~')): imports.append(line) return line if atype == ScssStylesheetAsset: msg = "Local import '%s' is forbidden for security reasons. Please remove all @import \"your_file.scss\" imports in your custom sass files. In Odoo you have to import all sass files in the assets, and not through the @import statement." % ref else: msg = "Local import '%s' is forbidden for security reasons. Please remove all @import \"your_file.less\" imports in your custom less files. In Odoo you have to import all less files in the assets, and not through the @import statement." % ref _logger.warning(msg) self.css_errors.append(msg) return '' source = re.sub(self.rx_preprocess_imports, sanitize, source) if atype == ScssStylesheetAsset: try: path_to_bs = get_resource_path('web', 'static', 'lib', 'bootstrap', 'scss') path_to_bs_components = get_resource_path('web', 'static', 'lib', 'bootstrap', 'scss', 'bootstrap') result = sass.compile( string=source.encode('utf-8'), include_paths=[path_to_bs, path_to_bs_components], output_style='expanded', precision=8, ) compiled = result.strip() except sass.CompileError as e: return handle_compile_error(e, source=source) else: try: compiler = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE) except Exception: msg = "Could not execute command %r" % cmd[0] _logger.error(msg) self.css_errors.append(msg) return '' result = compiler.communicate(input=source.encode('utf-8')) if compiler.returncode: cmd_output = ''.join(misc.ustr(result)) if not cmd_output: cmd_output = "Process exited with return code %d\n" % compiler.returncode return handle_compile_error(cmd_output, source=source) compiled = result[0].strip().decode('utf8') return compiled
def test_01_debug_mode_assets(self): """ Checks that the ir.attachments records created for compiled less assets in debug mode are correctly invalidated. """ # Compile for the first time self._bundle(self._get_asset(), True, False) # Compile a second time, without changes self._bundle(self._get_asset(), False, False) # Touch the file and compile a third time path = get_resource_path('test_assetsbundle', 'static', 'src', 'less', 'test_lessfile1.less') t = time.time() + 5 asset = self._get_asset() _touch(path, asset, t=t) self._bundle(asset, True, True) # Because we are in the same transaction since the beginning of the test, the first asset # created and the second one have the same write_date, but the file's last modified date # has really been modified. If we do not update the write_date to a posterior date, we are # not able to reproduce the case where we compile this bundle again without changing # anything. self.cr.execute("update ir_attachment set write_date=clock_timestamp() + interval '10 seconds' where id = (select max(id) from ir_attachment)") # Compile a fourth time, without changes self._bundle(self._get_asset(), False, False)
def _binary_ir_attachment_redirect_content(cls, record, default_mimetype='application/octet-stream'): # mainly used for theme images attachemnts status = content = filename = filehash = None mimetype = getattr(record, 'mimetype', False) if record.type == 'url' and record.url: # if url in in the form /somehint server locally url_match = re.match("^/(\w+)/(.+)$", record.url) if url_match: module = url_match.group(1) module_path = get_module_path(module) module_resource_path = get_resource_path(module, url_match.group(2)) if module_path and module_resource_path: module_path = os.path.join(os.path.normpath(module_path), '') # join ensures the path ends with '/' module_resource_path = os.path.normpath(module_resource_path) if module_resource_path.startswith(module_path): with open(module_resource_path, 'rb') as f: content = base64.b64encode(f.read()) status = 200 filename = os.path.basename(module_resource_path) mimetype = guess_mimetype(base64.b64decode(content), default=default_mimetype) filehash = '"%s"' % hashlib.md5(pycompat.to_text(content).encode('utf-8')).hexdigest() else: status = 301 content = record.url return status, content, filename, mimetype, filehash
def load_drivers(self): subprocess.check_call("sudo mount -o remount,rw /", shell=True) subprocess.check_call("sudo mount -o remount,rw /root_bypass_ramdisks", shell=True) mac = subprocess.check_output("/sbin/ifconfig eth0 |grep -Eo ..\(\:..\){5}", shell=True).decode('utf-8').split('\n')[0] #response = requests.get(url, auth=(username, db_uuid.split('\n')[0]), stream=True) server = get_odoo_server_url() if server: urllib3.disable_warnings() pm = urllib3.PoolManager(cert_reqs='CERT_NONE') resp = False server = server + '/iot/get_drivers' try: resp = pm.request('POST', server, fields={'mac': mac}) except Exception as e: _logger.error('Could not reach configured server') _logger.error('A error encountered : %s ' % e) if resp and resp.data: zip_file = zipfile.ZipFile(io.BytesIO(resp.data)) zip_file.extractall(get_resource_path('hw_drivers', 'drivers')) subprocess.check_call("sudo service odoo restart", shell=True) subprocess.check_call("sudo mount -o remount,ro /", shell=True) subprocess.check_call("sudo mount -o remount,ro /root_bypass_ramdisks", shell=True) return "<meta http-equiv='refresh' content='20; url=http://" + get_ip() + ":8069/list_drivers'>"
def _compute_rating_image(self): for rating in self: try: image_path = get_resource_path('rating', 'static/src/img', 'rating_%s.png' % (int(rating.rating),)) rating.rating_image = base64.b64encode(open(image_path, 'rb').read()) except (IOError, OSError): rating.rating_image = False
def test_account_bank_statement_def(self): """ In order to test Bank Statement feature of account I create a bank statement line and confirm it and check it's move created """ tools.convert_file(self.cr, 'account', get_resource_path('account', 'test', 'account_minimal_test.xml'), {}, 'init', False, 'test', self.registry._assertion_report) # Select the period and journal for the bank statement journal = self.env['account.bank.statement'].with_context({ 'lang': u'en_US', 'tz': False, 'active_model': 'ir.ui.menu', 'journal_type': 'bank', 'date': time.strftime("%Y/%m/%d") })._default_journal() self.assertTrue(journal, 'Journal has not been selected') # Create a bank statement with Opening and Closing balance 0 account_statement = self.env['account.bank.statement'].create({ 'balance_end_real': 0.0, 'balance_start': 0.0, 'date': time.strftime("%Y-%m-%d"), 'company_id': self.ref('base.main_company'), 'journal_id': journal.id, }) # Create Account bank statement line account_bank_statement_line = self.env['account.bank.statement.line'].create({ 'amount': 1000, 'date': time.strftime('%Y-%m-%d'), 'partner_id': self.ref('base.res_partner_4'), 'name': 'EXT001', 'statement_id': account_statement.id, }) # Create a Account for bank statement line process account = self.env['account.account'].create({ 'name': 'toto', 'code': 'bidule', 'user_type_id': self.ref('account.data_account_type_fixed_assets'), }) # Process the bank statement line account_statement.line_ids.process_reconciliation(new_aml_dicts=[{ 'credit': 1000, 'debit': 0, 'name': 'toto', 'account_id': account.id, }]) # Modify the bank statement and set the Closing Balance 1000. account_statement.write({'balance_end_real': 1000.00}) # Confirm the bank statement using Confirm button account_statement.button_confirm_bank() # Check bank statement state should be confirm self.assertEquals(account_statement.state, 'confirm')
def step_by_step_configure(self, token, iotname, essid, password, persistent=False): if token: url = token.split('|')[0] token = token.split('|')[1] else: url = '' subprocess.check_call([get_resource_path('point_of_sale', 'tools/posbox/configuration/connect_to_server_wifi.sh'), url, iotname, token, essid, password, persistent]) return url
def list_drivers(self): drivers_list = [] for driver in os.listdir(get_resource_path('hw_drivers', 'drivers')): if driver != '__pycache__': drivers_list.append(driver) return driver_list_template.render({ 'title': "Odoo's IoT Box - Drivers list", 'breadcrumb': 'Drivers list', 'drivers_list': drivers_list, })
def _get_files(self): def get_scripts(path): if not path: return {} return { version: glob.glob1(opj(path, version), '*.py') for version in os.listdir(path) if os.path.isdir(opj(path, version)) } for pkg in self.graph: if not (hasattr(pkg, 'update') or pkg.state == 'to upgrade' or getattr(pkg, 'load_state', None) == 'to upgrade'): continue self.migrations[pkg.name] = { 'module': get_scripts(get_resource_path(pkg.name, 'migrations')), 'maintenance': get_scripts(get_resource_path('base', 'maintenance', 'migrations', pkg.name)), }
def get_command(self): try: if os.name == 'nt': lessc = misc.find_in_path('lessc.cmd') else: lessc = misc.find_in_path('lessc') except IOError: lessc = 'lessc' lesspath = get_resource_path('web', 'static', 'lib', 'bootstrap', 'less') return [lessc, '-', '--no-js', '--no-color', '--include-path=%s' % lesspath]
def connect_box(self, token): """ This route is called when we want that a IoT Box will be connected to a Odoo DB token is a base 64 encoded string and have 2 argument separate by | 1 - url of odoo DB 2 - token. This token will be compared to the token of Odoo. He have 1 hour lifetime """ server = get_odoo_server_url() image = get_resource_path('hw_drivers', 'static/img', 'False.jpg') if server == '': token = b64decode(token).decode('utf-8') url, token = token.split('|') try: subprocess.check_call([get_resource_path('point_of_sale', 'tools/posbox/configuration/connect_to_server.sh'), url, '', token, 'noreboot']) m.send_alldevices() image = get_resource_path('hw_drivers', 'static/img', 'True.jpg') except subprocess.CalledProcessError as e: _logger.error('A error encountered : %s ' % e.output) if os.path.isfile(image): with open(image, 'rb') as f: return f.read()
def stat(self): if not (self.inline or self._filename or self._ir_attach): path = (segment for segment in self.url.split('/') if segment) self._filename = get_resource_path(*path) if self._filename: return try: # Test url against ir.attachments attach = self.bundle.env['ir.attachment'].sudo().get_serve_attachment(self.url) self._ir_attach = attach[0] except Exception: raise AssetNotFound("Could not find %s" % self.name)
def load_drivers(self): """ This method loads local files: 'odoo/addons/hw_drivers/drivers' And execute these python drivers """ path = get_resource_path('hw_drivers', 'drivers') driversList = os.listdir(path) for driver in driversList: path_file = os.path.join(path, driver) spec = util.spec_from_file_location(driver, path_file) if spec: module = util.module_from_spec(spec) spec.loader.exec_module(module)
def stat(self): if not (self.inline or self._filename or self._ir_attach): path = filter(None, self.url.split('/')) self._filename = get_resource_path(*path) if self._filename: return try: # Test url against ir.attachments fields = ['__last_update', 'datas', 'mimetype'] domain = [('type', '=', 'binary'), ('url', '=', self.url)] attach = self.bundle.env['ir.attachment'].sudo().search_read(domain, fields) self._ir_attach = attach[0] except Exception: raise AssetNotFound("Could not find %s" % self.name)
def test_product_margin(self): ''' In order to test the product_margin module ''' # load account_minimal_test.xml file for chart of account in configuration tools.convert_file( self.cr, 'product_margin', get_resource_path('account', 'test', 'account_minimal_test.xml'), {}, 'init', False, 'test', self.registry._assertion_report) supplier = self.env['res.partner'].create({'name': 'Supplier'}) customer = self.env['res.partner'].create({'name': 'Customer'}) ipad = self.env.ref("product.product_product_4") # Create supplier invoice and customer invoice to test product margin. # Define supplier invoices self.create_account_invoice('in_invoice', supplier, ipad, 10.0, 300.00) self.create_account_invoice('in_invoice', supplier, ipad, 4.0, 450.00) # Define Customer Invoices self.create_account_invoice('out_invoice', customer, ipad, 20.0, 750.00) self.create_account_invoice('out_invoice', customer, ipad, 10.0, 550.00) result = ipad._compute_product_margin_fields_values() # Sale turnover ( Quantity * Price Subtotal / Quantity) sale_turnover = ((20.0 * 750.00) + (10.0 * 550.00)) # Expected sale (Total quantity * Sale price) sale_expected = (750.00 * 30.0) # Purchase total cost (Quantity * Unit price) purchase_total_cost = ((10.0 * 300.00) + (4.0 * 450.00)) # Purchase normal cost ( Total quantity * Cost price) purchase_normal_cost = (14.0 * 500.00) total_margin = sale_turnover - purchase_total_cost expected_margin = sale_expected - purchase_normal_cost # Check total margin self.assertEqual(result[ipad.id]['total_margin'], total_margin, "Wrong Total Margin.") # Check expected margin self.assertEqual(result[ipad.id]['expected_margin'], expected_margin, "Wrong Expected Margin.")
def _get_asset_content(self, bundle, options, nodeAttrs=None): options = dict(options, inherit_branding=False, inherit_branding_auto=False, edit_translations=False, translatable=False, rendering_bundle=True) options['website_id'] = self.env.context.get('website_id') asset_paths = self.env['ir.asset']._get_asset_paths(bundle=bundle, css=True, js=True) files = [] remains = [] for path, *_ in asset_paths: ext = path.split('.')[-1] is_js = ext in SCRIPT_EXTENSIONS is_css = ext in STYLE_EXTENSIONS if not is_js and not is_css: continue mimetype = 'text/javascript' if is_js else 'text/%s' % ext if can_aggregate(path): segments = [segment for segment in path.split('/') if segment] files.append({ 'atype': mimetype, 'url': path, 'filename': get_resource_path(*segments) if segments else None, 'content': '', 'media': nodeAttrs and nodeAttrs.get('media'), }) else: if is_js: tag = 'script' attributes = { "type": mimetype, "src": path, } else: tag = 'link' attributes = { "type": mimetype, "rel": "stylesheet", "href": path, 'media': nodeAttrs and nodeAttrs.get('media'), } remains.append((tag, attributes, '')) return (files, remains)
def test_eslint(self): """ Test that there are no eslint errors in javascript files """ files_to_check = [ p for p in self.iter_module_files('**/static/**/*.js') if not re.match('.*/libs?/.*', p) # don't check libraries ] eslintrc_path = get_resource_path('test_lint', 'tests', 'eslintrc') _logger.info('Testing %s js files', len(files_to_check)) # https://eslint.org/docs/user-guide/command-line-interface cmd = [eslint, '--no-eslintrc', '-c', eslintrc_path] + files_to_check process = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=False) self.assertEqual(process.returncode, 0, msg=process.stdout.decode())
def setUpClass(cls): super().setUpClass() cls.doc_type_unknown = cls.env.ref('edi.document_type_unknown') # Locate test file directory corresponding to the class (which # may be a derived class in a different module). module_file = sys.modules[cls.__module__].__file__ module = get_resource_from_path(module_file)[0] path = get_resource_path(module, 'tests', 'files') if path: cls.files = pathlib.Path(path) # Delete any document types corresponding to non-existent # models, to avoid failures in edi.document.type.autocreate() EdiDocumentType = cls.env['edi.document.type'] EdiDocumentType.search( []).filtered(lambda x: x.model_id.model not in cls.env).unlink()
def print_inventory_commands(self): if not request.env.user.has_group('stock.group_stock_user'): return request.not_found() barcode_pdfs = [] # get fixed command barcodes file_path = get_resource_path('stock_barcode', 'static/img', 'barcodes_actions.pdf') commands_file = open(file_path, 'rb') barcode_pdfs.append(commands_file.read()) commands_file.close() # make sure we use the selected company if possible allowed_company_ids = self._get_allowed_company_ids() # same domain conditions for picking types and locations domain = [('active', '=', 'True'), ('barcode', '!=', ''), ('company_id', 'in', allowed_company_ids)] # get picking types barcodes picking_type_ids = request.env['stock.picking.type'].search(domain) picking_report = request.env.ref( 'stock.action_report_picking_type_label', raise_if_not_found=True) picking_types_pdf, _ = picking_report._render_qweb_pdf( picking_type_ids.ids) if picking_types_pdf: barcode_pdfs.append(picking_types_pdf) # get locations barcodes if request.env.user.has_group('stock.group_stock_multi_locations'): locations_ids = request.env['stock.location'].search(domain) locations_report = request.env.ref( 'stock.action_report_location_barcode', raise_if_not_found=True) locations_pdf, _ = locations_report._render_qweb_pdf( locations_ids.ids) if locations_pdf: barcode_pdfs.append(locations_pdf) merged_pdf = pdf.merge_pdf(barcode_pdfs) pdfhttpheaders = [('Content-Type', 'application/pdf'), ('Content-Length', len(merged_pdf))] return request.make_response(merged_pdf, headers=pdfhttpheaders)
def background_shape(self, module, filename, **kwargs): """ Returns a color-customized background-shape. """ shape_path = get_resource_path(module, 'static', 'shapes', filename) if shape_path: svg = open(shape_path, 'r').read() else: # Fallback to attachments for future migrations attachment = request.env['ir.attachment'].search( [('url', '=like', request.httprequest.path)], limit=1) if not attachment: raise werkzeug.exceptions.NotFound() svg = b64decode(attachment.datas).decode('utf-8') user_colors = [] for key, color in kwargs.items(): match = re.match('^c([12345])$', key) if match: user_colors.append([tools.html_escape(color), match.group(1)]) default_palette = { '1': '#3AADAA', '2': '#7C6576', '3': '#F6F6F6', '4': '#FFFFFF', '5': '#383E45', } color_mapping = { default_palette[palette_number]: color for color, palette_number in user_colors } # create a case-insensitive regex to match all the colors to replace, eg: '(?i)(#3AADAA)|(#7C6576)' regex = '(?i)%s' % '|'.join('(%s)' % color for color in color_mapping.keys()) def subber(match): key = match.group().upper() return color_mapping[key] if key in color_mapping else key svg = re.sub(regex, subber, svg) return request.make_response(svg, [ ('Content-type', 'image/svg+xml'), ('Cache-control', 'max-age=%s' % http.STATIC_CACHE_LONG), ])
def connect_to_server(self, token, iotname): credential = token.split('|') url = credential[0] token = credential[1] if len(credential) > 2: # IoT Box send token with db_uuid and enterprise_code only since V13 db_uuid = credential[2] enterprise_code = credential[3] helpers.add_credential(db_uuid, enterprise_code) reboot = 'reboot' subprocess.check_call([ get_resource_path( 'point_of_sale', 'tools/posbox/configuration/connect_to_server.sh'), url, iotname, token, reboot ]) return 'http://' + helpers.get_ip() + ':8069'
def get_asset_content(self, url, url_info=None, custom_attachments=None): """ Fetch the content of an asset (scss / js) file. That content is either the one of the related file on the disk or the one of the corresponding custom ir.attachment record. Params: url (str): the URL of the asset (scss / js) file/ir.attachment url_info (dict, optional): the related url info (see get_asset_info) (allows to optimize some code which already have the info and do not want this function to re-get it) custom_attachments (ir.attachment(), optional): the related custom ir.attachment records the function might need to search into (allows to optimize some code which already have that info and do not want this function to re-get it) Returns: utf-8 encoded content of the asset (scss / js) """ if url_info is None: url_info = self.get_asset_info(url) if url_info["customized"]: # If the file is already customized, the content is found in the # corresponding attachment attachment = None if custom_attachments is None: attachment = self._get_custom_attachment(url) else: attachment = custom_attachments.filtered(lambda r: r.url == url) return attachment and base64.b64decode(attachment.datas) or False # If the file is not yet customized, the content is found by reading # the local scss file module = url_info["module"] module_path = get_module_path(module) module_resource_path = get_resource_path(module, url_info["resource_path"]) if module_path and module_resource_path: module_path = os.path.join(os.path.normpath(module_path), '') # join ensures the path ends with '/' module_resource_path = os.path.normpath(module_resource_path) if module_resource_path.startswith(module_path): with open(module_resource_path, "rb") as f: return f.read()
def load_iot_handlers(): """ This method loads local files: 'odoo/addons/hw_drivers/iot_handlers/drivers' and 'odoo/addons/hw_drivers/iot_handlers/interfaces' And execute these python drivers and interfaces """ for directory in ['interfaces', 'drivers']: path = get_resource_path('hw_drivers', 'iot_handlers', directory) filesList = os.listdir(path) for file in filesList: path_file = os.path.join(path, file) spec = util.spec_from_file_location(file, path_file) if spec: module = util.module_from_spec(spec) spec.loader.exec_module(module) http.addons_manifest = {} http.root = http.Root()
def load_drivers(self): """ This method loads local files: 'odoo/addons/hw_drivers/drivers' And execute these python drivers """ helpers.download_drivers() path = get_resource_path('hw_drivers', 'drivers') driversList = os.listdir(path) self.devices = {} for driver in driversList: path_file = os.path.join(path, driver) spec = util.spec_from_file_location(driver, path_file) if spec: module = util.module_from_spec(spec) spec.loader.exec_module(module) http.addons_manifest = {} http.root = http.Root()
def test_17_css_bundle_date_invalidation(self): """ Checks that both css bundles are invalidated when one of its assets' modification date is changed """ # Assets access for en_US language ltr_bundle0 = self._get_asset(self.cssbundle_xmlid) ltr_bundle0.css() ltr_last_modified0 = ltr_bundle0.last_modified ltr_version0 = ltr_bundle0.version # Assets access for ar_SY language rtl_bundle0 = self._get_asset(self.cssbundle_xmlid, env=self.env(context={'lang': 'ar_SY'})) rtl_bundle0.css() rtl_last_modified0 = rtl_bundle0.last_modified rtl_version0 = rtl_bundle0.version # Touch test_cssfile1.css # Note: No lang specific context given while calling _get_asset so it will load assets for en_US path = get_resource_path('test_assetsbundle', 'static', 'src', 'css', 'test_cssfile1.css') ltr_bundle1 = self._get_asset(self.cssbundle_xmlid) with self._touch(path): ltr_bundle1.css() ltr_last_modified1 = ltr_bundle1.last_modified ltr_version1 = ltr_bundle1.version ltr_ira1 = self._any_ira_for_bundle('css') self.assertNotEquals(ltr_last_modified0, ltr_last_modified1) self.assertNotEquals(ltr_version0, ltr_version1) rtl_bundle1 = self._get_asset(self.cssbundle_xmlid, env=self.env(context={'lang': 'ar_SY'})) rtl_bundle1.css() rtl_last_modified1 = rtl_bundle1.last_modified rtl_version1 = rtl_bundle1.version rtl_ira1 = self._any_ira_for_bundle('css', lang='ar_SY') self.assertNotEquals(rtl_last_modified0, rtl_last_modified1) self.assertNotEquals(rtl_version0, rtl_version1) # Checks rtl and ltr bundles are different self.assertNotEquals(ltr_ira1.id, rtl_ira1.id) # check if the previous attachment is correctly cleaned css_bundles = self.env['ir.attachment'].search([ ('url', '=like', '/web/content/%-%/{0}%.{1}'.format(self.cssbundle_xmlid, 'css')) ]) self.assertEquals(len(css_bundles), 2)
def test_17_css_bundle_date_invalidation(self): """ Checks that both css bundles are invalidated when one of its assets' modification date is changed """ # Assets access for en_US language ltr_bundle0 = self._get_asset(self.cssbundle_xmlid) ltr_bundle0.css() ltr_last_modified0 = ltr_bundle0.last_modified ltr_version0 = ltr_bundle0.version # Assets access for ar_SY language rtl_bundle0 = self._get_asset(self.cssbundle_xmlid, env=self.env(context={'lang': 'ar_SY'})) rtl_bundle0.css() rtl_last_modified0 = rtl_bundle0.last_modified rtl_version0 = rtl_bundle0.version # Touch test_cssfile1.css # Note: No lang specific context given while calling _get_asset so it will load assets for en_US path = get_resource_path('test_assetsbundle', 'static', 'src', 'css', 'test_cssfile1.css') ltr_bundle1 = self._get_asset(self.cssbundle_xmlid) _touch(path, ltr_bundle1) ltr_bundle1.css() ltr_last_modified1 = ltr_bundle1.last_modified ltr_version1 = ltr_bundle1.version ltr_ira1 = self._any_ira_for_bundle('css') self.assertNotEquals(ltr_last_modified0, ltr_last_modified1) self.assertNotEquals(ltr_version0, ltr_version1) rtl_bundle1 = self._get_asset(self.cssbundle_xmlid, env=self.env(context={'lang': 'ar_SY'})) rtl_bundle1.css() rtl_last_modified1 = rtl_bundle1.last_modified rtl_version1 = rtl_bundle1.version rtl_ira1 = self._any_ira_for_bundle('css', lang='ar_SY') self.assertNotEquals(rtl_last_modified0, rtl_last_modified1) self.assertNotEquals(rtl_version0, rtl_version1) # Checks rtl and ltr bundles are different self.assertNotEquals(ltr_ira1.id, rtl_ira1.id) # check if the previous attachment is correctly cleaned css_bundles = self.env['ir.attachment'].search([ ('url', '=like', '/web/content/%-%/{0}%.{1}'.format(self.cssbundle_xmlid, 'css')) ]) self.assertEquals(len(css_bundles), 2)
def connect_to_wifi(self, essid, password, persistent=False): if persistent: persistent = "1" else: persistent = "" subprocess.check_call([get_resource_path('point_of_sale', 'tools/posbox/configuration/connect_to_wifi.sh'), essid, password, persistent]) server = get_odoo_server_url() res_payload = { 'message': 'Connecting to ' + essid, } if server: res_payload['server'] = { 'url': server, 'message': 'Redirect to Odoo Server' } return json.dumps(res_payload)
def step_by_step_configure(self, token, iotname, essid, password, persistent=False): if token: url = token.split('|')[0] token = token.split('|')[1] else: url = '' subprocess.check_call([ get_resource_path( 'point_of_sale', 'tools/posbox/configuration/connect_to_server_wifi.sh'), url, iotname, token, essid, password, persistent ]) return url
def schema_gantt(arch, **kwargs): global _gantt_validator if _gantt_validator is None: with misc.file_open( os.path.join('web_gantt_view', 'views', 'gantt.rng')) as f: # gantt.rng needs to include common.rng from the `base/rng/` directory. The idea # here is to set the base url of lxml lib in order to load relative file from the # `base/rng` directory. base_url = os.path.join(get_resource_path('base', 'rng'), '') _gantt_validator = etree.RelaxNG(etree.parse(f, base_url=base_url)) if _gantt_validator.validate(arch): return True for error in _gantt_validator.error_log: _logger.error(ustr(error)) return False
def _import_hs_codes(self): if not xlrd: # pragma: no cover raise exceptions.UserError(_("xlrd library not found.")) code_obj = self.env["hs.code"] path = os.path.join(get_resource_path("l10n_es_intrastat_report"), "data", "NC_20.xls") workbook = xlrd.open_workbook(path) sheet = workbook.sheet_by_index(0) vals_list = [] parents = [] prev_level = "" for nrow in range(1, sheet.nrows): code = sheet.cell_value(nrow, 1).replace(" ", "") description = sheet.cell_value(nrow, 5).lstrip("-") level = sheet.cell_value(nrow, 4) temp = prev_level while temp > level and parents: del parents[-1] temp = temp[:-1] if len(code) < 8 and description != description.upper(): parents.append(description) prev_level = level if len(code) != 8: # bypass parent lines continue vals = { "local_code": code, "description": " /".join(parents + [description]), } iu = sheet.cell_value(nrow, 6) if iu and iu != "-": # specific unit if iu in UOM_MAPPING: iu_unit_id = self.env.ref("intrastat_product.%s" % UOM_MAPPING[iu]).id else: iu_unit_id = self._get_intrastat_unit(iu) if iu_unit_id: vals["intrastat_unit_id"] = iu_unit_id else: raise exceptions.UserError(_("Unit not found: '%s'") % iu) if not code_obj.search([("local_code", "=", code)]): vals_list.append(vals) if vals_list: code_obj.create(vals_list)
def setUpClass(cls): super().setUpClass() cls.certificate_path = get_resource_path( "l10n_es_aeat", "tests", "cert", "entidadspj_act.p12", ) cls.certificate_password = b"794613" with open(cls.certificate_path, "rb") as certificate: content = certificate.read() cls.sii_cert = cls.env["l10n.es.aeat.certificate"].create({ "name": "Test Certificate", "folder": "Test folder", "file": base64.b64encode(content), })
def _compute_rating_image(self): # Due to some new widgets, we may have ratings different from 0/1/5/10 (e.g. slide.channel review) # Let us have some custom rounding while finding a better solution for images. for rating in self: rating_for_img = 0 if rating.rating >= 8: rating_for_img = 10 elif rating.rating > 3: rating_for_img = 5 elif rating.rating >= 1: rating_for_img = 1 try: image_path = get_resource_path( 'rating', 'static/src/img', 'rating_%s.png' % rating_for_img) rating.rating_image = base64.b64encode( open(image_path, 'rb').read()) except (IOError, OSError): rating.rating_image = False
def setUpClass(cls): super().setUpClass() module = "account_invoice_inter_company" convert_file( cls.cr, module, get_resource_path(module, "tests", "inter_company_invoice.xml"), None, 'init', False, 'test', cls.registry._assertion_report, ) cls.module = __name__.split('addons.')[1].split('.')[0] cls.account_obj = cls.env['account.account'] cls.invoice_obj = cls.env['account.invoice'] cls.company_a = cls.env.ref(cls.module + ".company_a") cls.invoice_company_a = cls.env.ref(cls.module + '.customer_invoice_company_a') cls.user_company_a = cls.env.ref(cls.module + '.user_company_a') cls.user_company_b = cls.env.ref(cls.module + '.user_company_b') cls.user_child_company_b = cls.env.ref(cls.module + '.child_partner_company_b') cls.invoice_line_a = cls.invoice_company_a.invoice_line_ids[0] cls.product_a = cls.invoice_line_a.product_id cls.invoice_line_b = cls.env["account.invoice.line"].create({ "invoice_id": cls.invoice_company_a.id, "product_id": cls.product_a.id, "name": "Test second line", "account_id": cls.env.ref(cls.module + ".a_sale_company_a").id, "price_unit": 20, }) cls.chart = cls.env['account.chart.template'].search([], limit=1) if not cls.chart: raise ValidationError( # translation to avoid pylint warnings _("No Chart of Account Template has been defined !"))
def test_product_margin(self): ''' In order to test the product_margin module ''' # load account_minimal_test.xml file for chart of account in configuration tools.convert_file(self.cr, 'product_margin', get_resource_path('account', 'test', 'account_minimal_test.xml'), {}, 'init', False, 'test', self.registry._assertion_report) supplier = self.env['res.partner'].create({'name': 'Supplier', 'supplier': True}) customer = self.env['res.partner'].create({'name': 'Customer', 'customer': True}) ipad = self.env.ref("product.product_product_4") # Create supplier invoice and customer invoice to test product margin. # Define supplier invoices self.create_account_invoice('in_invoice', supplier, ipad, 10.0, 300.00) self.create_account_invoice('in_invoice', supplier, ipad, 4.0, 450.00) # Define Customer Invoices self.create_account_invoice('out_invoice', customer, ipad, 20.0, 750.00) self.create_account_invoice('out_invoice', customer, ipad, 10.0, 550.00) result = ipad._compute_product_margin_fields_values() # Sale turnover ( Quantity * Price Subtotal / Quantity) sale_turnover = ((20.0 * 750.00) + (10.0 * 550.00)) # Expected sale (Total quantity * Sale price) sale_expected = (750.00 * 30.0) # Purchase total cost (Quantity * Unit price) purchase_total_cost = ((10.0 * 300.00) + (4.0 * 450.00)) # Purchase normal cost ( Total quantity * Cost price) purchase_normal_cost = (14.0 * 500.00) total_margin = sale_turnover - purchase_total_cost expected_margin = sale_expected - purchase_normal_cost # Check total margin self.assertEqual(result[ipad.id]['total_margin'], total_margin, "Wrong Total Margin.") # Check expected margin self.assertEqual(result[ipad.id]['expected_margin'], expected_margin, "Wrong Expected Margin.")
def _get_asset_content(self, bundle, nodeAttrs=None, defer_load=False, lazy_load=False): asset_paths = self.env['ir.asset']._get_asset_paths(bundle=bundle, css=True, js=True) files = [] remains = [] for path, *_ in asset_paths: ext = path.split('.')[-1] is_js = ext in SCRIPT_EXTENSIONS is_css = ext in STYLE_EXTENSIONS if not is_js and not is_css: continue mimetype = 'text/javascript' if is_js else 'text/%s' % ext if can_aggregate(path): segments = [segment for segment in path.split('/') if segment] files.append({ 'atype': mimetype, 'url': path, 'filename': get_resource_path(*segments) if segments else None, 'content': '', 'media': nodeAttrs and nodeAttrs.get('media'), }) else: if is_js: tag = 'script' attributes = { "type": mimetype, } attributes["data-src" if lazy_load else "src"] = path if defer_load or lazy_load: attributes["defer"] = "defer" else: tag = 'link' attributes = { "type": mimetype, "rel": "stylesheet", "href": path, 'media': nodeAttrs and nodeAttrs.get('media'), } remains.append((tag, attributes, '')) return (files, remains)
def _compute_validation_state(self): dmfa_schema_file_path = get_resource_path( 'l10n_be_hr_payroll', 'data', 'DmfAOriginal_20191.xsd', ) xsd_root = etree.parse(dmfa_schema_file_path) schema = etree.XMLSchema(xsd_root) for dmfa in self: if not dmfa.dmfa_xml: dmfa.validation_state = 'normal' dmfa.error_message = False else: xml_root = etree.fromstring(base64.b64decode(dmfa.dmfa_xml)) try: schema.assertValid(xml_root) dmfa.validation_state = 'done' except etree.DocumentInvalid as err: dmfa.validation_state = 'invalid' dmfa.error_message = str(err)
def test_03_date_invalidation(self): """ Checks that a bundle is invalidated when one of its assets' modification date is changed. """ bundle0 = self._get_asset(self.jsbundle_xmlid) bundle0.js() last_modified0 = bundle0.last_modified version0 = bundle0.version path = get_resource_path('test_assetsbundle', 'static', 'src', 'js', 'test_jsfile1.js') bundle1 = self._get_asset(self.jsbundle_xmlid) _touch(path, bundle1) bundle1.js() last_modified1 = bundle1.last_modified version1 = bundle1.version self.assertNotEquals(last_modified0, last_modified1) self.assertNotEquals(version0, version1) # check if the previous attachment is correctly cleaned self.assertEquals(len(self._any_ira_for_bundle('js')), 1)
def setUpClass(cls): super().setUpClass() # Reset system default printer cls.printer_default = cls.env.ref('print.default_printer') cls.printer_default.queue = None cls.printer_default.set_system_default() # Locate test file directory corresponding to the class (which # may be a derived class in a different module). module_file = sys.modules[cls.__module__].__file__ module = get_resource_from_path(module_file)[0] path = get_resource_path(module, 'tests', 'files') if path: cls.files = pathlib.Path(path) cls.safety = "print.default_test_print" # Enable default print safety for tests config.misc["print"] = {"default_test_print": 1}
def download_iot_handlers(auto=True): """ Get the drivers from the configured Odoo server """ server = get_odoo_server_url() if server: urllib3.disable_warnings() pm = urllib3.PoolManager(cert_reqs='CERT_NONE') server = server + '/iot/get_handlers' try: resp = pm.request('POST', server, fields={'mac': get_mac_address(), 'auto': auto}) if resp.data: subprocess.check_call(["sudo", "mount", "-o", "remount,rw", "/"]) zip_file = zipfile.ZipFile(io.BytesIO(resp.data)) zip_file.extractall(get_resource_path('hw_drivers', 'iot_handlers')) subprocess.check_call(["sudo", "mount", "-o", "remount,ro", "/"]) subprocess.check_call(["sudo", "mount", "-o", "remount,rw", "/root_bypass_ramdisks/etc/cups"]) except Exception as e: _logger.error('Could not reach configured server') _logger.error('A error encountered : %s ' % e)
def test_08_json_load(self): json_resource = get_resource_path( 'l10n_nl_kvk', 'examples', 'kvk_69599084.json', ) json_file = open(json_resource, 'rb').read() res_data = json.loads(json_file.decode()) self.assertTrue(res_data) api_version = res_data['apiVersion'] self.assertTrue(api_version) self.assertEqual(api_version, '2.0') data_items_list = res_data['data']['items'] self.assertTrue(data_items_list) self.assertEqual(len(data_items_list), 2) for kvk_item in data_items_list: self.assertEqual(kvk_item['kvkNumber'], '69599084')
def test_03_json_load(self): json_resource = get_resource_path( 'l10n_nl_openkvk', 'examples', 'openkvk_56048785.json', ) json_file = open(json_resource, 'rb').read() res_data = json.loads(json_file.decode()) self.assertTrue(res_data) dossiernummer_list = res_data['dossiernummer'] self.assertTrue(dossiernummer_list) self.assertEqual(len(dossiernummer_list), 2) for kvk_item in dossiernummer_list: self.assertEqual(kvk_item['text'], '56048785') self.assertEqual(kvk_item['dossiernummer'], '56048785') self.assertEqual(kvk_item['handelsnaam'], 'Onestein B.V.') self.assertTrue('id') self.assertTrue('link')
def _compare_sii_dict(self, json_file, inv_type, lines, extra_vals=None, module=None): """Helper method for creating an invoice according arguments, and comparing the expected SII dict with . """ module = module or "l10n_es_aeat_sii_oca" vals = { "name": "TEST001", "partner_id": self.partner.id, "invoice_date": "2020-01-01", "move_type": inv_type, "invoice_line_ids": [], } for line in lines: vals["invoice_line_ids"].append(( 0, 0, { "product_id": self.product.id, "account_id": self.account_expense.id, "name": "Test line", "price_unit": line["price_unit"], "quantity": 1, "tax_ids": [(6, 0, line["taxes"].ids)], }, )) if extra_vals: vals.update(extra_vals) invoice = self.env["account.move"].create(vals) result_dict = invoice._get_sii_invoice_dict() path = get_resource_path(module, "tests", json_file) if not path: raise Exception("Incorrect JSON file: %s" % json_file) with open(path, "r") as f: expected_dict = json.loads(f.read()) self.assertEqual(expected_dict, result_dict) return invoice
def test_png_logo_upload(self): with open( "%s/static/img/icons/icon-512x512.png" % get_resource_path("web_pwa_oca"), "rb") as fi: icon_to_send = base64.b64encode(fi.read()) # Set PWA icon in settings self.res_config_settings_obj.pwa_icon = icon_to_send self.res_config_settings_obj.set_values() # Call the manifest controller manifest_data = self.url_open("/web_pwa_oca/manifest.webmanifest") manifest_content_str = manifest_data.content.decode("utf-8") manifest_content = json.loads(manifest_content_str) expected_vals = { "src": "/web_pwa_oca/icon512x512.png", "sizes": "512x512", "type": "image/png", } self.assertTrue(expected_vals in manifest_content["icons"])
def test_10_paginated_css_date_invalidation(self): """ Checks that a bundle is invalidated when one of its assets' modification date is changed. """ bundle0 = self._get_asset(self.cssbundle_xmlid, env=self.env(context={'max_css_rules': 1})) bundle0.css() last_modified0 = bundle0.last_modified version0 = bundle0.version path = get_resource_path('test_assetsbundle', 'static', 'src', 'css', 'test_cssfile1.css') bundle1 = self._get_asset(self.cssbundle_xmlid, env=self.env(context={'max_css_rules': 1})) _touch(path, bundle1) bundle1.css() last_modified1 = bundle1.last_modified version1 = bundle1.version self.assertNotEquals(last_modified0, last_modified1) self.assertNotEquals(version0, version1) # check if the previous attachment is correctly cleaned self.assertEquals(len(self._any_ira_for_bundle('css')), 3)
def setUpClass(cls): super(TestAccountInvoiceInterCompany, cls).setUpClass() module = "account_invoice_inter_company" convert_file( cls.cr, module, get_resource_path(module, "tests", "inter_company_invoice.xml"), None, 'init', False, 'test', cls.registry._assertion_report, ) cls.account_obj = cls.env['account.account'] cls.invoice_obj = cls.env['account.invoice'] cls.invoice_company_a = cls.env.ref( 'account_invoice_inter_company.customer_invoice_company_a') cls.user_company_a = cls.env.ref( 'account_invoice_inter_company.user_company_a') cls.user_company_b = cls.env.ref( 'account_invoice_inter_company.user_company_b') cls.chart = cls.env['account.chart.template'].search([], limit=1) if not cls.chart: raise ValidationError( # translation to avoid pylint warnings _("No Chart of Account Template has been defined !"))
def _get_default_favicon(self, original=False): img_path = get_resource_path('web', 'static/src/img/favicon.ico') with tools.file_open(img_path, 'rb') as f: if original: return base64.b64encode(f.read()) # Modify the source image to change the color of the 'O'. # This could seem overkill to modify the pixels 1 by 1, but # Pillow doesn't provide an easy way to do it, and this # is acceptable for a 16x16 image. color = (randrange(32, 224, 24), randrange(32, 224, 24), randrange(32, 224, 24)) original = Image.open(f) new_image = Image.new('RGBA', original.size) for y in range(original.size[1]): for x in range(original.size[0]): pixel = original.getpixel((x, y)) if pixel[0] == 0 and pixel[1] == 0 and pixel[2] == 0: new_image.putpixel((x, y), (0, 0, 0, 0)) else: new_image.putpixel((x, y), (color[0], color[1], color[2], pixel[3])) stream = io.BytesIO() new_image.save(stream, format="ICO") return base64.b64encode(stream.getvalue())
def download_drivers(self, mac, auto): # Check mac is of one of the IoT Boxes box = request.env['iot.box'].sudo().search([('identifier', '=', mac)], limit=1) if not box or (auto == 'True' and not box.drivers_auto_update): return '' zip_list = [] for module in modules.get_modules(): for file in modules.get_module_filetree(module, 'drivers').keys(): if file.startswith('.') or file.startswith('_'): continue # zip it zip_list.append( (modules.get_resource_path(module, 'drivers', file), file)) file_like_object = io.BytesIO() zipfile_ob = zipfile.ZipFile(file_like_object, 'w') for zip in zip_list: zipfile_ob.write(zip[0], zip[1]) # In order to remove the absolute path zipfile_ob.close() return file_like_object.getvalue()
def _default_favicon(self): img_path = get_resource_path('web', 'static/src/img/favicon.ico') with tools.file_open(img_path, 'rb') as f: return base64.b64encode(f.read())
def binary_content(cls, xmlid=None, model='ir.attachment', id=None, field='datas', unique=False, filename=None, filename_field='datas_fname', download=False, mimetype=None, default_mimetype='application/octet-stream', env=None): """ Get file, attachment or downloadable content If the ``xmlid`` and ``id`` parameter is omitted, fetches the default value for the binary field (via ``default_get``), otherwise fetches the field for that precise record. :param str xmlid: xmlid of the record :param str model: name of the model to fetch the binary from :param int id: id of the record from which to fetch the binary :param str field: binary field :param bool unique: add a max-age for the cache control :param str filename: choose a filename :param str filename_field: if not create an filename with model-id-field :param bool download: apply headers to download the file :param str mimetype: mintype of the field (for headers) :param str default_mimetype: default mintype if no mintype found :param Environment env: by default use request.env :returns: (status, headers, content) """ env = env or request.env # get object and content obj = None if xmlid: obj = env.ref(xmlid, False) elif id and model in env.registry: obj = env[model].browse(int(id)) # obj exists if not obj or not obj.exists() or field not in obj: return (404, [], None) # check read access try: last_update = obj['__last_update'] except AccessError: return (403, [], None) status, headers, content = None, [], None # attachment by url check module_resource_path = None if model == 'ir.attachment' and obj.type == 'url' and obj.url: url_match = re.match("^/(\w+)/(.+)$", obj.url) if url_match: module = url_match.group(1) module_path = get_module_path(module) module_resource_path = get_resource_path(module, url_match.group(2)) if module_path and module_resource_path: module_path = os.path.join(os.path.normpath(module_path), '') # join ensures the path ends with '/' module_resource_path = os.path.normpath(module_resource_path) if module_resource_path.startswith(module_path): with open(module_resource_path, 'rb') as f: content = base64.b64encode(f.read()) last_update = pycompat.text_type(os.path.getmtime(module_resource_path)) if not module_resource_path: module_resource_path = obj.url if not content: status = 301 content = module_resource_path else: content = obj[field] or '' # filename if not filename: if filename_field in obj: filename = obj[filename_field] elif module_resource_path: filename = os.path.basename(module_resource_path) else: filename = "%s-%s-%s" % (obj._name, obj.id, field) # mimetype mimetype = 'mimetype' in obj and obj.mimetype or False if not mimetype: if filename: mimetype = mimetypes.guess_type(filename)[0] if not mimetype and getattr(env[model]._fields[field], 'attachment', False): # for binary fields, fetch the ir_attachement for mimetype check attach_mimetype = env['ir.attachment'].search_read(domain=[('res_model', '=', model), ('res_id', '=', id), ('res_field', '=', field)], fields=['mimetype'], limit=1) mimetype = attach_mimetype and attach_mimetype[0]['mimetype'] if not mimetype: mimetype = guess_mimetype(base64.b64decode(content), default=default_mimetype) headers += [('Content-Type', mimetype), ('X-Content-Type-Options', 'nosniff')] # cache etag = bool(request) and request.httprequest.headers.get('If-None-Match') retag = '"%s"' % hashlib.md5(last_update.encode('utf-8')).hexdigest() status = status or (304 if etag == retag else 200) headers.append(('ETag', retag)) headers.append(('Cache-Control', 'max-age=%s' % (STATIC_CACHE if unique else 0))) # content-disposition default name if download: headers.append(('Content-Disposition', cls.content_disposition(filename))) return (status, headers, content)
def bootstrap_components_path(self): return get_resource_path('web', 'static', 'lib', 'bootstrap', 'scss', 'bootstrap')
def clear_drivers_list(self): os.system(get_resource_path('point_of_sale', 'tools/posbox/configuration/clear_drivers_list.sh')) return "<meta http-equiv='refresh' content='0; url=http://" + get_ip() + ":8069/list_drivers'>"
def root(self): """Return root directory of repository""" default = get_resource_path('runbot', 'static') return self.env['ir.config_parameter'].sudo().get_param('runbot.root', default)
def get_assets_editor_resources(self, key, get_views=True, get_less=True, bundles=False, bundles_restriction=[]): # Related views must be fetched if the user wants the views and/or the style views = request.env["ir.ui.view"].get_related_views(key, bundles=bundles) views = views.read(['name', 'id', 'key', 'xml_id', 'arch', 'active', 'inherit_id']) less_files_data_by_bundle = [] # Load less only if asked by the user if get_less: # Compile regex outside of the loop # This will used to exclude library less files from the result excluded_url_matcher = re.compile("^(.+/lib/.+)|(.+import_bootstrap.less)$") # Load already customized less files attachments custom_attachments = request.env["ir.attachment"].search([("url", "=like", self._make_custom_less_file_url("%%.%%", "%%"))]) # First check the t-call-assets used in the related views url_infos = dict() for v in views: for asset_call_node in etree.fromstring(v["arch"]).xpath("//t[@t-call-assets]"): if asset_call_node.get("t-css") == "false": continue asset_name = asset_call_node.get("t-call-assets") # Loop through bundle files to search for LESS file info less_files_data = [] for file_info in request.env["ir.qweb"]._get_asset_content(asset_name, {})[0]: if file_info["atype"] != "text/less": continue url = file_info["url"] # Exclude library files (see regex above) if excluded_url_matcher.match(url): continue # Check if the file is customized and get bundle/path info less_file_data = self._match_less_file_url(url) if not less_file_data: continue # Save info (arch will be fetched later) url_infos[url] = less_file_data less_files_data.append(url) # Less data is returned sorted by bundle, with the bundles names and xmlids if len(less_files_data): less_files_data_by_bundle.append([dict(xmlid=asset_name, name=request.env.ref(asset_name).name), less_files_data]) # Filter bundles/files: # - A file which appears in multiple bundles only appears in the first one (the first in the DOM) # - Only keep bundles with files which appears in the asked bundles and only keep those files for i in range(0, len(less_files_data_by_bundle)): bundle_1 = less_files_data_by_bundle[i] for j in range(0, len(less_files_data_by_bundle)): bundle_2 = less_files_data_by_bundle[j] # In unwanted bundles, keep only the files which are in wanted bundles too (less_helpers) if bundle_1[0]["xmlid"] not in bundles_restriction and bundle_2[0]["xmlid"] in bundles_restriction: bundle_1[1] = [item_1 for item_1 in bundle_1[1] if item_1 in bundle_2[1]] for i in range(0, len(less_files_data_by_bundle)): bundle_1 = less_files_data_by_bundle[i] for j in range(i+1, len(less_files_data_by_bundle)): bundle_2 = less_files_data_by_bundle[j] # In every bundle, keep only the files which were not found in previous bundles bundle_2[1] = [item_2 for item_2 in bundle_2[1] if item_2 not in bundle_1[1]] # Only keep bundles which still have files and that were requested less_files_data_by_bundle = [ data for data in less_files_data_by_bundle if (len(data[1]) > 0 and (not bundles_restriction or data[0]["xmlid"] in bundles_restriction)) ] # Fetch the arch of each kept file, in each bundle for bundle_data in less_files_data_by_bundle: for i in range(0, len(bundle_data[1])): url = bundle_data[1][i] url_info = url_infos[url] content = None if url_info["customized"]: # If the file is already customized, the content is found in the corresponding attachment content = base64.b64decode(custom_attachments.filtered(lambda a: a.url == url).datas) else: # If the file is not yet customized, the content is found by reading the local less file module = url_info["module"] module_path = get_module_path(module) module_resource_path = get_resource_path(module, url_info["resource_path"]) if module_path and module_resource_path: module_path = os.path.join(os.path.normpath(module_path), '') # join ensures the path ends with '/' module_resource_path = os.path.normpath(module_resource_path) if module_resource_path.startswith(module_path): with open(module_resource_path, "rb") as f: content = f.read() bundle_data[1][i] = dict( url = "/%s/%s" % (url_info["module"], url_info["resource_path"]), arch = content, customized = url_info["customized"], ) return dict( views = get_views and views or [], less = get_less and less_files_data_by_bundle or [], )
def connect_to_server(self, token, iotname): url = token.split('|')[0] token = token.split('|')[1] reboot = 'reboot' subprocess.check_call([get_resource_path('point_of_sale', 'tools/posbox/configuration/connect_to_server.sh'), url, iotname, token, reboot]) return 'http://' + get_ip() + ':8069'