def load_information_from_description_file(module, mod_path=None): """ :param module: The name of the module (sale, purchase, ...) :param mod_path: Physical path of module, if not providedThe name of the module (sale, purchase, ...) """ if not mod_path: mod_path = get_module_path(module, downloaded=True) manifest_file = module_manifest(mod_path) if manifest_file: # default values for descriptor info = { 'application': False, 'author': 'FlectraHQ', 'auto_install': False, 'category': 'Uncategorized', 'depends': [], 'description': '', 'icon': get_module_icon(module), 'installable': True, 'license': 'LGPL-3', 'post_load': None, 'version': '1.0', 'web': False, 'website': 'https://www.flectrahq.com', 'sequence': 100, 'summary': '', } info.update( pycompat.izip( 'depends data demo test init_xml update_xml demo_xml'.split(), iter(list, None))) f = tools.file_open(manifest_file, mode='rb') try: info.update(ast.literal_eval(pycompat.to_native(f.read()))) finally: f.close() if not info.get('description'): readme_path = [ opj(mod_path, x) for x in README if os.path.isfile(opj(mod_path, x)) ] if readme_path: readme_text = tools.file_open(readme_path[0]).read() info['description'] = readme_text if 'active' in info: # 'active' has been renamed 'auto_install' info['auto_install'] = info['active'] info['version'] = adapt_version(info['version']) return info _logger.debug('module %s: no manifest file found %s', module, MANIFEST_NAMES) return {}
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 add a colored bar on the bottom # 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) height = original.size[1] width = original.size[0] bar_size = 1 for y in range(height): for x in range(width): pixel = original.getpixel((x, y)) if height - bar_size <= y + 1 <= height: new_image.putpixel((x, y), (color[0], color[1], color[2], 255)) else: new_image.putpixel( (x, y), (pixel[0], pixel[1], pixel[2], pixel[3])) stream = io.BytesIO() new_image.save(stream, format="ICO") return base64.b64encode(stream.getvalue())
def test_js_translations(self): """ Test that there are no translation of JS template strings or underscore calls misused as translation markers """ counter = 0 failures = 0 for js_file in self.iter_module_files('*.js'): # lodash has string methods and occurrences of `_('text')` in its comments if js_file.endswith('/lodash.js'): continue counter += 1 with tools.file_open(js_file, 'r') as f: js_txt = f.read() error_list = self.check_text(js_txt) for line_number, template_string in error_list: failures += 1 mod, relative_path, _ = get_resource_from_path(js_file) if template_string: prefix = "Translation of a template string" suffix = template_string else: prefix = "underscore.js used as translation function" suffix = "_t and _lt are the JS translation functions" _logger.error("%s found in `%s/%s` at line %s: %s", prefix, mod, relative_path, line_number, suffix) _logger.info('%s files tested', counter) if failures > 0: self.fail("%s invalid template strings found in js files." % failures)
def _get_desc(self): for module in self: path = modules.get_module_resource( module.name, 'static/description/index.html') if path: with tools.file_open(path, 'rb') as desc_file: doc = desc_file.read() html = lxml.html.document_fromstring(doc) for element, attribute, link, pos in html.iterlinks(): if element.get('src') and not '//' in element.get( 'src') and not 'static/' in element.get('src'): element.set( 'src', "/%s/static/description/%s" % (module.name, element.get('src'))) module.description_html = tools.html_sanitize( lxml.html.tostring(html)) else: overrides = { 'embed_stylesheet': False, 'doctitle_xform': False, 'output_encoding': 'unicode', 'xml_declaration': False, 'file_insertion_enabled': False, } output = publish_string(source=module.description or '', settings_overrides=overrides, writer=MyWriter()) module.description_html = tools.html_sanitize(output)
def read_image(self, path): if not path: return False path_info = path.split(',') icon_path = get_module_resource(path_info[0], path_info[1]) icon_image = False if icon_path: with tools.file_open(icon_path, 'rb') as icon_file: icon_image = base64.encodestring(icon_file.read()) return icon_image
def _get_icon_image(self): for module in self: module.icon_image = '' if module.icon: path_parts = module.icon.split('/') path = modules.get_module_resource(path_parts[1], *path_parts[2:]) else: path = modules.module.get_module_icon(module.name) if path: with tools.file_open(path, 'rb') as image_file: module.icon_image = base64.b64encode(image_file.read())
def relaxng(view_type): """ Return a validator for the given view type, or None. """ if view_type not in _relaxng_cache: with tools.file_open(os.path.join('base', 'rng', '%s_view.rng' % view_type)) as frng: try: relaxng_doc = etree.parse(frng) _relaxng_cache[view_type] = etree.RelaxNG(relaxng_doc) except Exception: _logger.exception('Failed to load RelaxNG XML schema for views validation') _relaxng_cache[view_type] = None return _relaxng_cache[view_type]
def load_script(path, module_name): fp, fname = tools.file_open(path, pathinfo=True) fp2 = None if not isinstance(fp, file): # pylint: disable=file-builtin # imp.load_source need a real file object, so we create # one from the file-like object we get from file_open fp2 = os.tmpfile() fp2.write(fp.read()) fp2.seek(0) try: return imp.load_source(module_name, fname, fp2 or fp) finally: if fp: fp.close() if fp2: fp2.close()
def _get_image(self): if self._logo_image: return self._logo_image try: im = urllib2.urlopen(_url.encode("UTF-8")) if im.headers.maintype != 'image': raise TypeError(im.headers.maintype) except Exception as e: path = os.path.join('report_aeroo','config_pixmaps', 'module_banner_1.png') image_file = file_data = file_open(path,'rb') try: file_data = image_file.read() self._logo_image = b64encode(file_data) return self._logo_image finally: image_file.close() else: self._logo_image = b64encode(im.read()) return self._logo_image
def check(self): icp = self.env['ir.config_parameter'] icp.set_param('aeroo.docs_enabled', str(self.enabled)) icp.set_param('aeroo.docs_host', self.host) icp.set_param('aeroo.docs_port', self.port) icp.set_param('aeroo.docs_auth_type', self.auth_type or 'simple') icp.set_param('aeroo.docs_username', self.username) icp.set_param('aeroo.docs_password', self.password) error_details = '' state = 'done' if self.enabled: try: fp = file_open('report_aeroo/test_temp.odt', mode='rb') file_data = fp.read() docs_client = DOCSConnection(self.host, self.port, username=self.username, password=self.password) token = docs_client.upload(file_data) data = docs_client.convert(identifier=token, out_mime='pdf') except Exception as e: error_details = str(e) state = 'error' if state=='error': msg = _('Failure! Connection to DOCS service was not established ' + 'or convertion to PDF unsuccessful!') elif state=='done' and not self.enabled: msg = _('Connection to Aeroo DOCS disabled!') else: msg = _('Success! Connection to the DOCS service was successfully '+ 'established and PDF convertion is working.') self.msg = msg self.error_details = error_details self.state = state mod_obj = self.env['ir.model.data'] act_obj = self.env['ir.actions.act_window'] result = mod_obj.get_object_reference('report_aeroo', 'action_docs_config_wizard') act_id = result and result[1] or False result = act_obj.search([('id','=',act_id)]).read()[0] result['res_id'] = self.id return result
def test_js_translations(self): """ Test that there are no translation of JS template strings """ counter = 0 failures = 0 for js_file in self.iter_module_files('*.js'): counter += 1 with tools.file_open(js_file, 'r') as f: js_txt = f.read() error_list = self.check_text(js_txt) for line_number, template_string in error_list: failures += 1 mod, relative_path, _ = get_resource_from_path(js_file) _logger.error( "Translation of a template string found in `%s/%s` at line %s: %s", mod, relative_path, line_number, template_string) _logger.info('%s files tested', counter) if failures > 0: self.fail("%s invalid template strings found in js files." % failures)
def _read_template(self): self.ensure_one() fp = None data = None try: fp = file_open(self.report_file, mode='rb') data = fp.read() except IOError as e: if e.errno == 13: # Permission denied on the template file raise UserError(_(e.strerror), e.filename) else: _logger.exception("Error in '_read_template' method", exc_info=True) except Exception as e: _logger.exception("Error in '_read_template' method", exc_info=True) fp = False data = False finally: if fp is not None: fp.close() return data
def export_icon_to_png( self, icon, color='#000', size=100, alpha=255, font='/web/static/lib/fontawesome/fonts/fontawesome-webfont.ttf'): """ This method converts an unicode character to an image (using Font Awesome font by default) and is used only for mass mailing because custom fonts are not supported in mail. :param icon : decimal encoding of unicode character :param color : RGB code of the color :param size : Pixels in integer :param alpha : transparency of the image from 0 to 255 :param font : font path :returns PNG image converted from given font """ # Make sure we have at least size=1 size = max(1, min(size, 512)) # Initialize font with tools.file_open(font.lstrip('/'), 'rb') as f: font_obj = ImageFont.truetype(f, size) # if received character is not a number, keep old behaviour (icon is character) icon = chr(int(icon)) if icon.isdigit() else icon # Determine the dimensions of the icon image = Image.new("RGBA", (size, size), color=(0, 0, 0, 0)) draw = ImageDraw.Draw(image) boxw, boxh = draw.textsize(icon, font=font_obj) draw.text((0, 0), icon, font=font_obj) left, top, right, bottom = image.getbbox() # Create an alpha mask imagemask = Image.new("L", (boxw, boxh), 0) drawmask = ImageDraw.Draw(imagemask) drawmask.text((-left, -top), icon, font=font_obj, fill=alpha) # Create a solid color image and apply the mask if color.startswith('rgba'): color = color.replace('rgba', 'rgb') color = ','.join(color.split(',')[:-1]) + ')' iconimage = Image.new("RGBA", (boxw, boxh), color) iconimage.putalpha(imagemask) # Create output image outimage = Image.new("RGBA", (boxw, size), (0, 0, 0, 0)) outimage.paste(iconimage, (left, top)) # output image output = io.BytesIO() outimage.save(output, format="PNG") response = werkzeug.wrappers.Response() response.mimetype = 'image/png' response.data = output.getvalue() response.headers['Cache-Control'] = 'public, max-age=604800' response.headers['Access-Control-Allow-Origin'] = '*' response.headers['Access-Control-Allow-Methods'] = 'GET, POST' response.headers['Connection'] = 'close' response.headers['Date'] = time.strftime("%a, %d-%b-%Y %T GMT", time.gmtime()) response.headers['Expires'] = time.strftime( "%a, %d-%b-%Y %T GMT", time.gmtime(time.time() + 604800 * 60)) return response
def load_information_from_description_file(module, mod_path=None): """ :param module: The name of the module (sale, purchase, ...) :param mod_path: Physical path of module, if not providedThe name of the module (sale, purchase, ...) """ if not mod_path: mod_path = get_module_path(module, downloaded=True) manifest_file = module_manifest(mod_path) if manifest_file: # default values for descriptor info = { 'application': False, 'author': 'FlectraHQ, Odoo S.A.', 'auto_install': False, 'category': 'Uncategorized', 'depends': [], 'description': '', 'icon': get_module_icon(module), 'installable': True, 'license': 'LGPL-3', 'post_load': None, 'version': '1.0', 'web': False, 'sequence': 100, 'summary': '', 'website': '', } info.update( zip('depends data demo test init_xml update_xml demo_xml'.split(), iter(list, None))) f = tools.file_open(manifest_file, mode='rb') try: info.update(ast.literal_eval(pycompat.to_text(f.read()))) finally: f.close() if not info.get('description'): readme_path = [ opj(mod_path, x) for x in README if os.path.isfile(opj(mod_path, x)) ] if readme_path: with tools.file_open(readme_path[0]) as fd: info['description'] = fd.read() # auto_install is set to `False` if disabled, and a set of # auto_install dependencies otherwise. That way, we can set # auto_install: [] to always auto_install a module regardless of its # dependencies auto_install = info.get('auto_install', info.get('active', False)) if isinstance(auto_install, collections.abc.Iterable): info['auto_install'] = set(auto_install) non_dependencies = info['auto_install'].difference(info['depends']) assert not non_dependencies,\ "auto_install triggers must be dependencies, found " \ "non-dependencies [%s] for module %s" % ( ', '.join(non_dependencies), module ) elif auto_install: info['auto_install'] = set(info['depends']) else: info['auto_install'] = False info['version'] = adapt_version(info['version']) return info _logger.debug('module %s: no manifest file found %s', module, MANIFEST_NAMES) return {}
def _get_test_file_content(cls, filename): """ Get the content of a test file inside this module """ path = 'l10n_it_edi/tests/expected_xmls/' + filename with tools.file_open(path, mode='rb') as test_file: return test_file.read()
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 _default_logo(self): image_path = get_resource_path('website', 'static/src/img', 'website_logo.png') with tools.file_open(image_path, 'rb') as f: return base64.b64encode(f.read())
def shape(self, module, filename, **kwargs): """ Returns a color-customized svg (background shape or illustration). """ svg = None if module == 'illustration': attachment = request.env['ir.attachment'].sudo().search( [('url', '=like', request.httprequest.path), ('public', '=', True)], limit=1) if not attachment: raise werkzeug.exceptions.NotFound() svg = b64decode(attachment.datas).decode('utf-8') else: shape_path = get_resource_path(module, 'static', 'shapes', filename) if not shape_path: raise werkzeug.exceptions.NotFound() with tools.file_open(shape_path, 'r') as file: svg = file.read() user_colors = [] for key, value in kwargs.items(): colorMatch = re.match('^c([1-5])$', key) if colorMatch: # Check that color is hex or rgb(a) to prevent arbitrary injection if not re.match( r'(?i)^#[0-9A-F]{6,8}$|^rgba?\(\d{1,3},\d{1,3},\d{1,3}(?:,[0-9.]{1,4})?\)$', value.replace(' ', '')): raise werkzeug.exceptions.BadRequest() user_colors.append( [tools.html_escape(value), colorMatch.group(1)]) elif key == 'flip': if value == 'x': svg = svg.replace('<svg ', '<svg style="transform: scaleX(-1);" ') elif value == 'y': svg = svg.replace('<svg ', '<svg style="transform: scaleY(-1)" ') elif value == 'xy': svg = svg.replace('<svg ', '<svg style="transform: scale(-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 load_templates(self, **kwargs): base_url = request.httprequest.base_url templates = [ 'im_livechat/static/src/legacy/public_livechat.xml', ] return [tools.file_open(tmpl, 'rb').read() for tmpl in templates]