[IMP] *: use file_path and file_open

Replace all the calls to get_resource_path to the better file_path or
directly use file_open when not needed

Doing both a get_resource_path and file_open means checking twice that
the file exists.
Doing a simple path concatenation before a file_open is safe.
If given to another method (e.g. etree.parse), calling file_path is
the prefered method.

Note that get_resource_path used to return False when the file does
not exists while file_path/file_open raises a FileNotFoundException

closes odoo/odoo#135607

Related: odoo/upgrade#5187
Related: odoo/enterprise#47475
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
This commit is contained in:
Martin Trigaux
2023-10-06 14:33:43 +00:00
parent 9e253bbe63
commit 22ab49e343
60 changed files with 222 additions and 244 deletions
-14
View File
@@ -1,6 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.modules.module import get_module_resource
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
from contextlib import contextmanager
@@ -88,19 +87,6 @@ class AccountEdiTestCommon(AccountTestInvoicingCommon):
def edi_cron(self):
self.env['account.edi.document'].sudo().search([('state', 'in', ('to_send', 'to_cancel'))])._process_documents_web_services(with_commit=False)
def create_invoice_from_file(self, module_name, subfolder, filename):
file_path = get_module_resource(module_name, subfolder, filename)
file = open(file_path, 'rb').read()
attachment = self.env['ir.attachment'].create({
'name': filename,
'datas': base64.encodebytes(file),
'res_model': 'account.move',
})
journal_id = self.company_data['default_journal_sale']
action_vals = journal_id.with_context(default_move_type='in_invoice').create_document_from_attachment(attachment.ids)
return self.env['account.move'].browse(action_vals['res_id'])
def assert_generated_file_equal(self, invoice, expected_values, applied_xpath=None):
invoice.action_post()
invoice.edi_document_ids._process_documents_web_services(with_commit=False) # synchronous are called in post, but there's no CRON in tests for asynchronous
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from odoo.tests.common import TransactionCase, tagged
from odoo.tools.misc import file_open
from unittest import skipIf
import os
@@ -17,7 +18,7 @@ class TestCaseIndexation(TransactionCase):
@skipIf(PDFResourceManager is None, "pdfminer not installed")
def test_attachment_pdf_indexation(self):
with open(os.path.join(directory, 'files', 'test_content.pdf'), 'rb') as file:
with file_open(os.path.join(directory, 'files', 'test_content.pdf'), 'rb') as file:
pdf = file.read()
text = self.env['ir.attachment']._index(pdf, 'application/pdf')
self.assertEqual(text, 'TestContent!!\x0c', 'the index content should be correct')
@@ -3,7 +3,6 @@
import base64
import json
import os
import tempfile
from io import BytesIO
from zipfile import ZipFile
@@ -1,9 +1,8 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.tests import common
from odoo.addons.hr.tests.common import TestHrCommon
from odoo.modules.module import get_module_resource
from odoo.tools.misc import file_open
class TestRecruitmentProcess(TestHrCommon):
@@ -36,7 +35,7 @@ class TestRecruitmentProcess(TestHrCommon):
# An applicant is interested in the job position. So he sends a resume by email.
# In Order to test process of Recruitment so giving HR officer's rights
with open(get_module_resource('hr_recruitment', 'tests', 'resume.eml'), 'rb') as request_file:
with file_open('hr_recruitment/tests/resume.eml', 'rb') as request_file:
request_message = request_file.read()
self.env['mail.thread'].with_user(self.res_users_hr_recruitment_officer).message_process(
'hr.applicant', request_message, custom_values={"job_id": self.job_developer.id})
-1
View File
@@ -9,7 +9,6 @@ from threading import Thread
import time
import urllib3
from odoo.modules.module import get_resource_path
from odoo.addons.hw_drivers.main import iot_devices, manager
from odoo.addons.hw_drivers.tools import helpers
-1
View File
@@ -9,7 +9,6 @@ import subprocess
import time
from odoo import http, tools
from odoo.modules.module import get_resource_path
from odoo.addons.hw_drivers.event_manager import event_manager
from odoo.addons.hw_drivers.main import iot_devices, manager
@@ -18,6 +18,7 @@ from odoo.addons.hw_drivers.driver import Driver
from odoo.addons.hw_drivers.event_manager import event_manager
from odoo.addons.hw_drivers.main import iot_devices
from odoo.addons.hw_drivers.tools import helpers
from odoo.tools.misc import file_open
path = os.path.realpath(os.path.join(os.path.dirname(__file__), '../../views'))
loader = jinja2.FileSystemLoader(path)
@@ -203,7 +204,7 @@ class DisplayController(http.Controller):
cust_js = None
interfaces = ni.interfaces()
with open(os.path.join(os.path.dirname(__file__), "../../static/src/js/worker.js")) as js:
with file_open("hw_drivers/static/src/js/worker.js") as js:
cust_js = js.read()
display_ifaces = []
@@ -11,7 +11,6 @@ import os
from PIL import Image, ImageOps
import re
import subprocess
import tempfile
from uuid import getnode as get_mac
from odoo import http
+2 -2
View File
@@ -23,7 +23,7 @@ import secrets
from odoo import _, http, service
from odoo.tools.func import lazy_property
from odoo.modules.module import get_resource_path
from odoo.tools.misc import file_path
_logger = logging.getLogger(__name__)
@@ -368,7 +368,7 @@ def load_iot_handlers():
And execute these python drivers and interfaces
"""
for directory in ['interfaces', 'drivers']:
path = get_resource_path('hw_drivers', 'iot_handlers', directory)
path = file_path(f'hw_drivers/iot_handlers/{directory}')
filesList = list_file_by_os(path)
for file in filesList:
spec = util.spec_from_file_location(file, str(Path(path).joinpath(file)))
@@ -14,11 +14,11 @@ import threading
from odoo import http, service
from odoo.http import Response
from odoo.modules.module import get_resource_path
from odoo.addons.hw_drivers.connection_manager import connection_manager
from odoo.addons.hw_drivers.main import iot_devices
from odoo.addons.hw_drivers.tools import helpers
from odoo.addons.web.controllers.home import Home
from odoo.tools.misc import file_path
_logger = logging.getLogger(__name__)
@@ -112,8 +112,8 @@ class IoTboxHomepage(Home):
@http.route('/list_handlers', type='http', auth='none', website=True)
def list_handlers(self):
drivers_list = helpers.list_file_by_os(get_resource_path('hw_drivers', 'iot_handlers', 'drivers'))
interfaces_list = helpers.list_file_by_os(get_resource_path('hw_drivers', 'iot_handlers', 'interfaces'))
drivers_list = helpers.list_file_by_os(file_path('hw_drivers/iot_handlers/drivers'))
interfaces_list = helpers.list_file_by_os(file_path('hw_drivers/iot_handlers/interfaces'))
return handler_list_template.render({
'title': "Odoo's IoT Box - Handlers list",
'breadcrumb': 'Handlers list',
@@ -167,7 +167,7 @@ class IoTboxHomepage(Home):
else:
persistent = ""
subprocess.check_call([get_resource_path('point_of_sale', 'tools/posbox/configuration/connect_to_wifi.sh'), essid, password, persistent])
subprocess.check_call([file_path('point_of_sale/tools/posbox/configuration/connect_to_wifi.sh'), essid, password, persistent])
server = helpers.get_odoo_server_url()
res_payload = {
'message': 'Connecting to ' + essid,
@@ -198,7 +198,7 @@ class IoTboxHomepage(Home):
@http.route('/handlers_clear', type='http', auth='none', cors='*', csrf=False)
def clear_handlers_list(self):
for directory in ['drivers', 'interfaces']:
for file in list(Path(get_resource_path('hw_drivers', 'iot_handlers', directory)).glob('*')):
for file in list(Path(file_path(f'hw_drivers/iot_handlers/{directory}')).glob('*')):
if file.name != '__pycache__':
helpers.unlink_file(str(file.relative_to(*file.parts[:3])))
return "<meta http-equiv='refresh' content='0; url=http://" + helpers.get_ip() + ":8069/list_handlers'>"
@@ -216,7 +216,7 @@ class IoTboxHomepage(Home):
url = helpers.get_odoo_server_url()
token = helpers.get_token()
if iotname and platform.system() == 'Linux':
subprocess.check_call([get_resource_path('point_of_sale', 'tools/posbox/configuration/rename_iot.sh'), iotname])
subprocess.check_call([file_path('point_of_sale/tools/posbox/configuration/rename_iot.sh'), iotname])
helpers.odoo_restart(5)
return 'http://' + helpers.get_ip() + ':8069'
@@ -238,7 +238,7 @@ class IoTboxHomepage(Home):
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])
subprocess.check_call([file_path('point_of_sale/tools/posbox/configuration/connect_to_server_wifi.sh'), url, iotname, token, essid, password, persistent])
return url
# Set server address
@@ -3,11 +3,11 @@ import base64
from freezegun import freeze_time
from collections import Counter
from os.path import join as opj
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
from odoo import fields
from odoo.tools import misc
from odoo.modules.module import get_resource_path, get_module_resource
from lxml import etree
@@ -117,8 +117,8 @@ class TestUBLCommon(AccountTestInvoicingCommon):
def _update_invoice_from_file(self, module_name, subfolder, filename, invoice):
""" Create an attachment from a file and post it on the invoice
"""
file_path = get_module_resource(module_name, subfolder, filename)
with misc.file_open(file_path, 'rb') as file:
file_path = opj(module_name, subfolder, filename)
with misc.file_open(file_path, 'rb', filter_ext=('.xml',)) as file:
attachment = self.env['ir.attachment'].create({
'name': filename,
'datas': base64.encodebytes(file.read()),
@@ -234,8 +234,7 @@ class TestUBLCommon(AccountTestInvoicingCommon):
xml_content = base64.b64decode(attachment.with_context(bin_size=False).datas)
xml_etree = self.get_xml_tree_from_string(xml_content)
expected_file_full_path = get_resource_path(self.test_module, 'tests/test_files', expected_file_path)
self.assertTrue(expected_file_full_path, "expected file not found")
expected_file_full_path = misc.file_path(f'{self.test_module}/tests/test_files/{expected_file_path}')
expected_etree = etree.parse(expected_file_full_path).getroot()
modified_etree = self.with_applied_xpath(
@@ -4,7 +4,6 @@ from odoo import Command, fields
from odoo.addons.l10n_account_edi_ubl_cii_tests.tests.common import TestUBLCommon
from odoo.addons.account.tests.test_account_move_send import TestAccountMoveSendCommon
from odoo.exceptions import UserError
from odoo.modules.module import get_resource_path
from odoo.tests import tagged
from odoo.tools import file_open
@@ -179,9 +178,8 @@ class TestUBLDK(TestUBLCommon, TestAccountMoveSendCommon):
#########
def import_bill_xml_file_in_purchase_journal(self, file_path):
full_file_path = get_resource_path(self.test_module, 'tests/test_files', file_path)
self.assertTrue(full_file_path, f'File not found: {file_path}')
with file_open(full_file_path, 'rb') as file:
file_path = f"{self.test_module}/tests/test_files/{file_path}"
with file_open(file_path, 'rb') as file:
xml_attachment = self.env['ir.attachment'].create({
'mimetype': 'application/xml',
'name': 'test_invoice.xml',
@@ -3,7 +3,7 @@ from hashlib import sha256
from base64 import b64encode
from lxml import etree
from odoo import models, fields
from odoo.modules.module import get_module_resource
from odoo.tools.misc import file_path
import re
TAX_EXEMPTION_CODES = ['VATEX-SA-29', 'VATEX-SA-29-7', 'VATEX-SA-30']
@@ -57,7 +57,7 @@ class AccountEdiXmlUBL21Zatca(models.AbstractModel):
def _transform_and_canonicalize_xml(content):
""" Transform XML content to remove certain elements and signatures using an XSL template """
invoice_xsl = etree.parse(get_module_resource('l10n_sa_edi', 'data', 'pre-hash_invoice.xsl'))
invoice_xsl = etree.parse(file_path('l10n_sa_edi/data/pre-hash_invoice.xsl'))
transform = etree.XSLT(invoice_xsl)
return _canonicalize_xml(transform(content))
+3 -3
View File
@@ -6,7 +6,7 @@ from datetime import datetime
from base64 import b64encode, b64decode
from odoo import models, fields, service, _, api
from odoo.exceptions import UserError
from odoo.modules.module import get_module_resource
from odoo.tools.misc import file_open
from requests.exceptions import HTTPError, RequestException
from cryptography import x509
from cryptography.x509 import ObjectIdentifier, load_der_x509_certificate
@@ -288,8 +288,8 @@ class AccountJournal(models.Model):
'simplified/invoice.xml', 'simplified/credit.xml', 'simplified/debit.xml',
], {}
for file in file_names:
fpath = get_module_resource('l10n_sa_edi', 'tests/compliance', file)
with open(fpath, 'rb') as ip:
fpath = f'l10n_sa_edi/tests/compliance/{file}'
with file_open(fpath, 'rb', filter_ext=('.xml',)) as ip:
compliance_files[file] = ip.read().decode()
return compliance_files
@@ -5,7 +5,7 @@ import base64
from odoo import api, fields, models
from odoo.modules.module import get_module_resource
from odoo.tools.misc import file_open
class LunchProductCategory(models.Model):
@@ -16,8 +16,7 @@ class LunchProductCategory(models.Model):
@api.model
def _default_image(self):
image_path = get_module_resource('lunch', 'static/img', 'lunch.png')
return base64.b64encode(open(image_path, 'rb').read())
return base64.b64encode(file_open('lunch/static/img/lunch.png', 'rb').read())
name = fields.Char('Product Category', required=True, translate=True)
company_id = fields.Many2one('res.company')
+3 -4
View File
@@ -7,10 +7,9 @@ from lxml import etree
from odoo import api, fields, models, tools, _
from odoo.exceptions import UserError
from odoo.modules import get_module_resource
from odoo.modules.module import get_resource_from_path, get_resource_path
from odoo.modules.module import get_resource_from_path
from odoo.tools.convert import xml_import
from odoo.tools.misc import file_open
from odoo.tools.misc import file_path
from odoo.tools.translate import TranslationImporter, get_po_paths
@@ -79,7 +78,7 @@ class TemplateResetMixin(models.AbstractModel):
for template in self.filtered('template_fs'):
external_id = template.get_external_id().get(template.id)
module, xml_id = external_id.split('.')
fullpath = get_resource_path(*template.template_fs.split('/'))
fullpath = file_path(template.template_fs)
if fullpath:
for field_name, field in template._fields.items():
if field.translate is True:
+5 -5
View File
@@ -5,7 +5,6 @@ from unittest.mock import patch
from odoo.addons.mail.tests.common import MailCommon
from odoo.exceptions import AccessError, ValidationError, UserError
from odoo.modules.module import get_module_resource
from odoo.tests import Form, tagged, users
from odoo.tools import convert_file
@@ -174,13 +173,14 @@ class TestMailTemplate(MailCommon):
@tagged('mail_template')
class TestMailTemplateReset(MailCommon):
def _load(self, module, *args):
def _load(self, module, filepath):
# pylint: disable=no-value-for-parameter
convert_file(self.env, module='mail',
filename=get_module_resource(module, *args),
filename=filepath,
idref={}, mode='init', noupdate=False, kind='test')
def test_mail_template_reset(self):
self._load('mail', 'tests', 'test_mail_template.xml')
self._load('mail', 'tests/test_mail_template.xml')
mail_template = self.env.ref('mail.mail_template_test').with_context(lang=self.env.user.lang)
@@ -212,7 +212,7 @@ class TestMailTemplateReset(MailCommon):
def test_mail_template_reset_translation(self):
""" Test if a translated value can be reset correctly when its translation exists/doesn't exist in the po file of the directory """
self._load('mail', 'tests', 'test_mail_template.xml')
self._load('mail', 'tests/test_mail_template.xml')
self.env['res.lang']._activate_lang('en_UK')
self.env['res.lang']._activate_lang('fr_FR')
+3 -2
View File
@@ -4,13 +4,14 @@
import io
import uuid
import base64
from os.path import join as opj
from PIL import Image
from typing import Optional, List, Dict
from werkzeug.urls import url_quote
from odoo.exceptions import UserError
from odoo.tools import image_to_base64
from odoo import api, fields, models, modules, _, service
from odoo import api, fields, models, _, service
from odoo.tools import file_open, split_every
@@ -123,7 +124,7 @@ class PosConfig(models.Model):
for pos_config_id in pos_config_ids:
for image_name in ['landing_01.jpg', 'landing_02.jpg', 'landing_03.jpg']:
image_path = modules.get_module_resource("pos_self_order", "static/img", image_name)
image_path = opj("pos_self_order/static/img", image_name)
attachment = self.env['ir.attachment'].create({
'name': image_name,
'datas': base64.b64encode(file_open(image_path, "rb").read()),
-1
View File
@@ -4,7 +4,6 @@ from datetime import timedelta
from odoo import fields
from odoo.addons.stock.tests.common2 import TestStockCommon
from odoo import tools
from odoo.modules.module import get_module_resource
class PurchaseTestCommon(TestStockCommon):
+7 -6
View File
@@ -5,7 +5,7 @@ import uuid
from odoo import api, fields, models
from odoo.addons.rating.models import rating_data
from odoo.modules.module import get_resource_path
from odoo.tools.misc import file_open
class Rating(models.Model):
@@ -96,12 +96,13 @@ class Rating(models.Model):
self.rating_image_url = False
self.rating_image = False
for rating in self:
image_path = f'rating/static/src/img/{rating._get_rating_image_filename()}'
rating.rating_image_url = f'/{image_path}'
try:
image_path = get_resource_path('rating', 'static/src/img', rating._get_rating_image_filename())
rating.rating_image_url = '/rating/static/src/img/%s' % rating._get_rating_image_filename()
rating.rating_image = base64.b64encode(open(image_path, 'rb').read()) if image_path else False
except (IOError, OSError):
pass
rating.rating_image = base64.b64encode(
file_open(image_path, 'rb', filter_ext=('.png',)).read())
except (IOError, OSError, FileNotFoundError):
rating.rating_image = False
@api.depends('rating')
def _compute_rating_text(self):
@@ -3,7 +3,6 @@
import base64
from odoo import _, api, Command, models
from odoo.modules.module import get_resource_path
from odoo.tools import file_open
@@ -39,8 +38,7 @@ class OnboardingStep(models.Model):
# take any existing product or create one
product = self.env['product.product'].search([], limit=1)
if not product:
default_image_path = get_resource_path('product', 'static/img', 'product_product_13-image.jpg')
with file_open(default_image_path, 'rb') as default_image_stream:
with file_open('product/static/img/product_product_13-image.jpg', 'rb') as default_image_stream:
product = self.env['product.product'].create({
'name': _('Sample Product'),
'active': False,
@@ -2,8 +2,7 @@
import base64
from odoo.tests.common import TransactionCase
from odoo.modules.module import get_module_resource
from odoo.tools.misc import file_open
class TestProductConfiguratorCommon(TransactionCase):
@@ -78,8 +77,8 @@ class TestProductConfiguratorCommon(TransactionCase):
cls.product_product_custo_desk.product_variant_ids[3].active = False
# Setup a first optional product
img_path = get_module_resource('product', 'static', 'img', 'product_product_11-image.png')
img_content = base64.b64encode(open(img_path, "rb").read())
img_path = 'product/static/img/product_product_11-image.png'
img_content = base64.b64encode(file_open(img_path, "rb").read())
cls.product_product_conf_chair = cls.env['product.template'].create({
'name': 'Conference Chair (TEST)',
'image_1920': img_content,
+4 -4
View File
@@ -7,7 +7,6 @@ from odoo.addons.mail.tests.common import mail_new_test_user
from odoo.exceptions import AccessError
from odoo.tests import tagged
from odoo.tools import mute_logger, convert_file
from odoo.modules.module import get_module_resource
@tagged('post_install', '-at_install')
@@ -113,13 +112,14 @@ class TestSmsTemplateAccessRights(TransactionCase):
@tagged('post_install', '-at_install')
class TestSMSTemplateReset(TransactionCase):
def _load(self, module, *args):
def _load(self, module, filepath):
# pylint: disable=no-value-for-parameter
convert_file(self.env, module='sms',
filename=get_module_resource(module, *args),
filename=filepath,
idref={}, mode='init', noupdate=False, kind='test')
def test_sms_template_reset(self):
self._load('sms', 'tests', 'test_sms_template.xml')
self._load('sms', 'tests/test_sms_template.xml')
sms_template = self.env.ref('sms.sms_template_test').with_context(lang=self.env.user.lang)
@@ -7,8 +7,8 @@ import pprint
import unittest
from odoo.tests.common import TransactionCase, can_import, RecordCapturer
from odoo.modules.module import get_module_resource
from odoo.tools import mute_logger, pycompat
from odoo.tools.misc import file_open
from odoo.addons.base_import.models.base_import import ImportValidationError
from odoo.addons.test_base_import.models.test_base_import import model as base_import_model
@@ -358,8 +358,7 @@ class TestPreview(TransactionCase):
@unittest.skipUnless(can_import('xlrd'), "XLRD module not available")
def test_xls_success(self):
xls_file_path = get_module_resource('test_base_import', 'data', 'test.xls')
file_content = open(xls_file_path, 'rb').read()
file_content = file_open('test_base_import/data/test.xls', 'rb').read()
import_wizard = self.env['base_import.import'].create({
'res_model': base_import_model('preview'),
'file': file_content,
@@ -382,8 +381,7 @@ class TestPreview(TransactionCase):
@unittest.skipUnless(can_import('xlrd.xlsx'), "XLRD/XLSX not available")
def test_xlsx_success(self):
xlsx_file_path = get_module_resource('test_base_import', 'data', 'test.xlsx')
file_content = open(xlsx_file_path, 'rb').read()
file_content = file_open('test_base_import/data/test.xlsx', 'rb').read()
import_wizard = self.env['base_import.import'].create({
'res_model': base_import_model('preview'),
'file': file_content,
@@ -406,8 +404,7 @@ class TestPreview(TransactionCase):
@unittest.skipUnless(can_import('odf'), "ODFPY not available")
def test_ods_success(self):
ods_file_path = get_module_resource('test_base_import', 'data', 'test.ods')
file_content = open(ods_file_path, 'rb').read()
file_content = file_open('test_base_import/data/test.ods', 'rb').read()
import_wizard = self.env['base_import.import'].create({
'res_model': base_import_model('preview'),
'file': file_content,
+4 -5
View File
@@ -6,19 +6,18 @@ import re
from odoo import tools
from odoo.addons.base.tests.common import TransactionCaseWithUserDemo
from odoo.modules.module import get_module_resource
class TestQweb(TransactionCaseWithUserDemo):
def _load(self, module, *args):
def _load(self, module, filepath):
tools.convert_file(
self.env, 'test_website',
get_module_resource(module, *args),
self.env, module,
filepath,
{}, 'init', False, 'test'
)
def test_qweb_cdn(self):
self._load('test_website', 'tests', 'template_qweb_test.xml')
self._load('test_website', 'tests/template_qweb_test.xml')
website = self.env.ref('website.default_website')
website.write({
+4 -6
View File
@@ -18,7 +18,6 @@ import odoo.modules.registry
from odoo import http, _
from odoo.exceptions import AccessError, UserError
from odoo.http import request, Response
from odoo.modules import get_resource_path
from odoo.tools import file_open, file_path, replace_exceptions
from odoo.tools.mimetypes import guess_mimetype
from odoo.tools.image import image_guess_size_from_field_name
@@ -214,12 +213,11 @@ class Binary(http.Controller):
def company_logo(self, dbname=None, **kw):
imgname = 'logo'
imgext = '.png'
placeholder = functools.partial(get_resource_path, 'web', 'static', 'img')
dbname = request.db
uid = (request.session.uid if dbname else None) or odoo.SUPERUSER_ID
if not dbname:
response = http.Stream.from_path(placeholder(imgname + imgext)).get_response()
response = http.Stream.from_path(file_path('web/static/img/logo.png')).get_response()
else:
try:
# create an empty registry
@@ -255,9 +253,9 @@ class Binary(http.Controller):
response_class=Response,
)
else:
response = http.Stream.from_path(placeholder('nologo.png')).get_response()
response = http.Stream.from_path(file_path('web/static/img/nologo.png')).get_response()
except Exception:
response = http.Stream.from_path(placeholder(imgname + imgext)).get_response()
response = http.Stream.from_path(file_path(f'web/static/img/{imgname}{imgext}')).get_response()
return response
@@ -273,7 +271,7 @@ class Binary(http.Controller):
"""
supported_exts = ('.ttf', '.otf', '.woff', '.woff2')
fonts = []
fonts_directory = file_path(os.path.join('web', 'static', 'fonts', 'sign'))
fonts_directory = file_path('web/static/fonts/sign')
if fontname:
font_path = os.path.join(fonts_directory, fontname)
with file_open(font_path, 'rb', filter_ext=supported_exts) as font_file:
+3 -3
View File
@@ -13,10 +13,10 @@ import werkzeug.wsgi
import odoo
import odoo.modules.registry
from odoo import http
from odoo.modules import get_manifest, get_resource_path
from odoo.modules import get_manifest
from odoo.http import request
from odoo.tools import lazy
from odoo.tools.misc import file_open
from odoo.tools.misc import file_open, file_path
from .utils import _local_web_translations
@@ -80,7 +80,7 @@ class WebClient(http.Controller):
for addon_name in mods:
manifest = get_manifest(addon_name)
if manifest and manifest['bootstrap']:
f_name = get_resource_path(addon_name, 'i18n', f'{lang}.po')
f_name = file_path(f'{addon_name}/i18n/{lang}.po')
if not f_name:
continue
translations_per_module[addon_name] = {'messages': _local_web_translations(f_name)}
+2 -2
View File
@@ -5,8 +5,8 @@ from markupsafe import Markup
from odoo import api, fields, models, tools
from odoo.addons.base.models.ir_qweb_fields import nl2br
from odoo.modules import get_resource_path
from odoo.tools import html2plaintext, is_html_empty
from odoo.tools.misc import file_path
try:
import sass as libsass
@@ -289,7 +289,7 @@ class BaseDocumentLayout(models.TransientModel):
precision = 8
output_style = 'expanded'
bootstrap_path = get_resource_path('web', 'static', 'lib', 'bootstrap', 'scss')
bootstrap_path = file_path('web/static/lib/bootstrap/scss')
try:
return libsass.compile(
+8 -4
View File
@@ -2,7 +2,10 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import re
from contextlib import suppress
import odoo.tests
from odoo.tools.misc import file_open
RE_ONLY = re.compile(r'QUnit\.(only|debug)\(')
@@ -45,11 +48,12 @@ class WebSuite(odoo.tests.HttpCase):
for asset in assets:
filename = asset['filename']
if not filename or not filename.endswith('.js'):
if not filename.endswith('.js'):
continue
with open(filename, 'rb') as fp:
if RE_ONLY.search(fp.read().decode('utf-8')):
self.fail("`QUnit.only()` or `QUnit.debug()` used in file %r" % asset['url'])
with suppress(FileNotFoundError):
with file_open(filename, 'rb', filter_ext=('.js',)) as fp:
if RE_ONLY.search(fp.read().decode('utf-8')):
self.fail("`QUnit.only()` or `QUnit.debug()` used in file %r" % asset['url'])
@odoo.tests.tagged('post_install', '-at_install')
+7 -6
View File
@@ -14,14 +14,14 @@ from lxml import etree
from base64 import b64decode, b64encode
from datetime import datetime
from math import floor
from os.path import join as opj
from odoo.http import request, Response
from odoo import http, tools, _, SUPERUSER_ID
from odoo.addons.http_routing.models.ir_http import slug, unslug
from odoo.addons.web_editor.tools import get_video_url_data
from odoo.exceptions import UserError, MissingError, ValidationError
from odoo.modules.module import get_resource_path
from odoo.tools import file_open
from odoo.tools.misc import file_open
from odoo.tools.mimetypes import guess_mimetype
from odoo.tools.image import image_data_uri, binary_to_image
from odoo.addons.base.models.assetsbundle import AssetsBundle
@@ -569,11 +569,12 @@ class Web_Editor(http.Controller):
return '%s?access_token=%s' % (attachment.image_src, attachment.access_token)
def _get_shape_svg(self, module, *segments):
shape_path = get_resource_path(module, 'static', *segments)
if not shape_path:
shape_path = opj(module, 'static', *segments)
try:
with file_open(shape_path, 'r', filter_ext=('.svg',)) as file:
return file.read()
except FileNotFoundError:
raise werkzeug.exceptions.NotFound()
with tools.file_open(shape_path, 'r', filter_ext=('.svg',)) as file:
return file.read()
def _update_svg_colors(self, options, svg):
user_colors = []
+4 -11
View File
@@ -29,7 +29,7 @@ from odoo import _, api, models, fields
from odoo.exceptions import UserError, ValidationError
from odoo.tools import ustr, posix_to_ldml, pycompat
from odoo.tools import html_escape as escape
from odoo.tools.misc import get_lang, babel_locale_parse
from odoo.tools.misc import file_open, get_lang, babel_locale_parse
REMOTE_CONNECTION_TIMEOUT = 2.5
@@ -479,20 +479,13 @@ class Image(models.AbstractModel):
def load_local_url(self, url):
match = self.local_url_re.match(urls.url_parse(url).path)
rest = match.group('rest')
for sep in os.sep, os.altsep:
if sep and sep != '/':
rest.replace(sep, '/')
path = odoo.modules.get_module_resource(
match.group('module'), 'static', *(rest.split('/')))
if not path:
return None
path = os.path.join(
match.group('module'), 'static', rest)
try:
with open(path, 'rb') as f:
with file_open(path, 'rb') as f:
# force complete image load to ensure it's valid image data
image = I.open(f)
image.load()
+3 -5
View File
@@ -23,7 +23,7 @@ from odoo.addons.portal.controllers.portal import pager
from odoo.addons.iap.tools import iap_tools
from odoo.exceptions import AccessError, MissingError, UserError, ValidationError
from odoo.http import request
from odoo.modules.module import get_resource_path, get_manifest
from odoo.modules.module import get_manifest
from odoo.osv.expression import AND, OR, FALSE_DOMAIN, get_unaccent_wrapper
from odoo.tools.translate import _, xml_translate
from odoo.tools import escape_psql, pycompat
@@ -98,8 +98,7 @@ class Website(models.Model):
return self.env.ref('base.main_company').social_tiktok
def _default_logo(self):
image_path = get_resource_path('website', 'static/src/img', 'website_logo.svg')
with tools.file_open(image_path, 'rb') as f:
with tools.file_open('website/static/src/img/website_logo.svg', 'rb') as f:
return base64.b64encode(f.read())
logo = fields.Binary('Website Logo', default=_default_logo, help="Display this logo on the website.")
@@ -134,8 +133,7 @@ class Website(models.Model):
robots_txt = fields.Html('Robots.txt', translate=False, groups='website.group_website_designer', sanitize=False)
def _default_favicon(self):
img_path = get_resource_path('web', 'static/img/favicon.ico')
with tools.file_open(img_path, 'rb') as f:
with tools.file_open('web/static/img/favicon.ico', 'rb') as f:
return base64.b64encode(f.read())
favicon = fields.Binary(string="Website Favicon", help="This field holds the image used to display a favicon on the website.", default=_default_favicon)
@@ -5,7 +5,6 @@ import re
from odoo import api, fields, models, tools, _
from odoo.exceptions import ValidationError
from odoo.modules.module import get_resource_path
class WebsiteConfiguratorFeature(models.Model):
@@ -34,11 +33,11 @@ class WebsiteConfiguratorFeature(models.Model):
@staticmethod
def _process_svg(theme, colors, image_mapping):
svg = None
preview_svg = get_resource_path(theme, 'static', 'description', theme + '.svg')
if not preview_svg:
try:
with tools.file_open(f'{theme}/static/description/{theme}.svg', 'r') as file:
svg = file.read()
except FileNotFoundError:
return False
with tools.file_open(preview_svg, 'r') as file:
svg = file.read()
default_colors = {
'color1': '#3AADAA',
@@ -7,7 +7,6 @@ from pytz import timezone, utc
from odoo import api, fields, models, _
from odoo.addons.http_routing.models.ir_http import slug
from odoo.addons.resource.models.utils import float_to_time
from odoo.modules.module import get_resource_path
from odoo.tools import is_html_empty
from odoo.tools.translate import html_translate
@@ -116,7 +115,7 @@ class Sponsor(models.Model):
elif sponsor.partner_id.image_256:
sponsor.website_image_url = self.env['website'].image_url(sponsor.partner_id, 'image_256', size=256)
else:
sponsor.website_image_url = get_resource_path('website_event_exhibitor', 'static/src/img', 'event_sponsor_default_%d.png' % (sponsor.id % 1))
sponsor.website_image_url = 'website_event_exhibitor/static/src/img/event_sponsor_default_0.jpeg'
def _synchronize_with_partner(self, fname):
""" Synchronize with partner if not set. Setting a value does not write
@@ -7,8 +7,8 @@ import pytz
from odoo import http
from odoo.addons.http_routing.models.ir_http import url_for
from odoo.http import request
from odoo.modules.module import get_module_resource
from odoo.tools import ustr
from odoo.tools.misc import file_open
from odoo.tools.translate import _
@@ -47,8 +47,7 @@ class TrackManifest(http.Controller):
def service_worker(self):
""" Returns a ServiceWorker javascript file scoped for website_event
"""
sw_file = get_module_resource('website_event_track', 'static/src/js/service_worker.js')
with open(sw_file, 'r') as fp:
with file_open('website_event_track/static/src/js/service_worker.js', 'r') as fp:
body = fp.read()
js_cdn_url = 'undefined'
if request.website.cdn_activated:
+3 -3
View File
@@ -4,8 +4,9 @@ import base64
from odoo.addons.base.tests.common import HttpCaseWithUserDemo, HttpCaseWithUserPortal
from odoo.fields import Command
from odoo.modules.module import get_module_resource
from odoo.tests import tagged
from odoo.tools.misc import file_open
@tagged('post_install', '-at_install')
class TestUi(HttpCaseWithUserDemo, HttpCaseWithUserPortal):
@@ -125,8 +126,7 @@ class TestUi(HttpCaseWithUserDemo, HttpCaseWithUserPortal):
})
self.product_product_4_product_template.attribute_line_ids[0].write({'value_ids': [(4, product_attribute_value_7.id)]})
img_path = get_module_resource('product', 'static', 'img', 'product_product_11-image.png')
img_content = base64.b64encode(open(img_path, "rb").read())
img_content = base64.b64encode(file_open('product/static/img/product_product_11-image.png', "rb").read())
self.product_product_11_product_template = self.env['product.template'].create({
'name': 'Conference Chair (TEST)',
'website_sequence': 9999, # laule
@@ -5,9 +5,9 @@ import base64
from dateutil.relativedelta import relativedelta
from odoo import tests
from odoo.fields import Datetime
from odoo.modules.module import get_module_resource
from odoo.tools import mute_logger
from odoo.addons.base.tests.common import HttpCaseWithUserDemo, HttpCaseWithUserPortal
from odoo.tools.misc import file_open
class TestUICommon(HttpCaseWithUserDemo, HttpCaseWithUserPortal):
@@ -15,10 +15,8 @@ class TestUICommon(HttpCaseWithUserDemo, HttpCaseWithUserPortal):
def setUp(self):
super(TestUICommon, self).setUp()
# Load pdf and img contents
pdf_path = get_module_resource('website_slides', 'static', 'src', 'img', 'presentation.pdf')
pdf_content = base64.b64encode(open(pdf_path, "rb").read())
img_path = get_module_resource('website_slides', 'static', 'src', 'img', 'slide_demo_gardening_1.jpg')
img_content = base64.b64encode(open(img_path, "rb").read())
pdf_content = base64.b64encode(file_open('website_slides/static/src/img/presentation.pdf', "rb").read())
img_content = base64.b64encode(file_open('website_slides/static/src/img/slide_demo_gardening_1.jpg', "rb").read())
self.channel = self.env['slide.channel'].create({
'name': 'Basics of Gardening - Test',
+5 -6
View File
@@ -28,12 +28,11 @@ from rjsmin import jsmin as rjsmin
from odoo import release, SUPERUSER_ID, _
from odoo.http import request
from odoo.modules.module import get_resource_path
from odoo.tools import (func, misc, transpile_javascript,
is_odoo_module, SourceMapGenerator, profiler,
apply_inheritance_specs)
from odoo.tools.constants import SCRIPT_EXTENSIONS, STYLE_EXTENSIONS
from odoo.tools.misc import file_open, html_escape as escape
from odoo.tools.misc import file_open, file_path
from odoo.tools.pycompat import to_text
_logger = logging.getLogger(__name__)
@@ -186,8 +185,8 @@ class AssetsBundle(object):
self.env.cr.execute(f"""DELETE FROM {attachments._table} WHERE id IN (
SELECT id FROM {attachments._table} WHERE id in %s FOR NO KEY UPDATE SKIP LOCKED
)""", [tuple(attachments.ids)])
for file_path in to_delete:
attachments._file_delete(file_path)
for fpath in to_delete:
attachments._file_delete(fpath)
def clean_attachments(self, extension):
""" Takes care of deleting any outdated ir.attachment records associated to a bundle before
@@ -719,7 +718,7 @@ class AssetsBundle(object):
except IOError:
rtlcss = 'rtlcss'
cmd = [rtlcss, '-c', get_resource_path("base", "data/rtlcss.json"), '-']
cmd = [rtlcss, '-c', file_path("base/data/rtlcss.json"), '-']
try:
rtlcss = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
@@ -1091,7 +1090,7 @@ class SassStylesheetAsset(PreprocessedCSS):
class ScssStylesheetAsset(PreprocessedCSS):
@property
def bootstrap_path(self):
return get_resource_path('web', 'static', 'lib', 'bootstrap', 'scss')
return file_path('web/static/lib/bootstrap/scss')
precision = 8
output_style = 'expanded'
-1
View File
@@ -31,7 +31,6 @@ from odoo.modules.registry import Registry
from odoo.service import security
from odoo.tools import get_lang, submap
from odoo.tools.translate import code_translations
from odoo.modules.module import get_resource_path, get_module_path
_logger = logging.getLogger(__name__)
+5 -8
View File
@@ -9,7 +9,6 @@ import io
import logging
import os
import shutil
import tempfile
import threading
import zipfile
@@ -32,7 +31,7 @@ from odoo.tools.parse_version import parse_version
from odoo.tools.misc import topological_sort, get_flag
from odoo.tools.translate import TranslationImporter, get_po_paths
from odoo.http import request
from odoo.modules import get_module_path, get_module_resource
from odoo.modules import get_module_path
_logger = logging.getLogger(__name__)
@@ -162,10 +161,8 @@ class Module(models.Model):
if not module.name:
module.description_html = False
continue
module_path = modules.get_module_path(module.name, display_warning=False) # avoid to log warning for fake community module
if module_path:
path = modules.check_resource_path(module_path, 'static/description/index.html')
if module_path and path:
path = os.path.join(module.name, '/static/description/index.html')
try:
with tools.file_open(path, 'rb') as desc_file:
doc = desc_file.read()
if doc.startswith(XML_DECLARATION):
@@ -191,7 +188,7 @@ class Module(models.Model):
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:
except FileNotFoundError:
overrides = {
'embed_stylesheet': False,
'doctitle_xform': False,
@@ -246,7 +243,7 @@ class Module(models.Model):
module.icon_image = ''
if module.icon:
path_parts = module.icon.split('/')
path = modules.get_module_resource(path_parts[1], *path_parts[2:])
path = os.path.join(path_parts[1], *path_parts[2:])
elif module.id:
path = modules.module.get_module_icon_path(module)
else:
+10 -10
View File
@@ -3,13 +3,13 @@
import base64
from collections import defaultdict
from os.path import join as opj
import operator
import re
from odoo import api, fields, models, tools, _
from odoo.exceptions import ValidationError
from odoo.http import request
from odoo.modules import get_module_resource
from odoo.osv import expression
MENU_ITEM_SEPARATOR = "/"
@@ -56,16 +56,16 @@ class IrUiMenu(models.Model):
else:
return self.name
def read_image(self, path):
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.encodebytes(icon_file.read())
return icon_image
icon_path = opj(path_info[0], path_info[1])
try:
with tools.file_open(icon_path, 'rb', filter_ext=('.png',)) as icon_file:
return base64.encodebytes(icon_file.read())
except FileNotFoundError:
return False
@api.constrains('parent_id')
def _check_parent_id(self):
@@ -179,10 +179,10 @@ class IrUiMenu(models.Model):
`web_icon` can either be:
- an image icon [module, path]
- a built icon [icon_class, icon_color, background_color]
and it only has to call `read_image` if it's an image.
and it only has to call `_read_image` if it's an image.
"""
if web_icon and len(web_icon.split(',')) == 2:
return self.read_image(web_icon)
return self._read_image(web_icon)
def unlink(self):
# Detach children and promote them to top-level, because it would be unwise to
+20 -17
View File
@@ -21,12 +21,13 @@ import odoo
from odoo import api, fields, models, tools, _
from odoo.exceptions import ValidationError, AccessError, UserError
from odoo.http import request
from odoo.modules.module import get_resource_from_path, get_resource_path
from odoo.modules.module import get_resource_from_path
from odoo.tools import config, ConstantMapping, get_diff, pycompat, apply_inheritance_specs, locate_node, str2bool
from odoo.tools.convert import _fix_multiple_roots
from odoo.tools import safe_eval, lazy, lazy_property, frozendict
from odoo.tools.view_validation import valid_view, get_domain_value_names, get_expression_field_names, get_dict_asts
from odoo.tools.convert import _fix_multiple_roots
from odoo.tools.misc import file_path
from odoo.tools.translate import xml_translate, TRANSLATED_ATTRS
from odoo.tools.view_validation import valid_view, get_domain_value_names, get_expression_field_names, get_dict_asts
from odoo.models import check_method_name
from odoo.osv.expression import expression
@@ -234,22 +235,24 @@ actual arch.
if read_file and view.arch_fs and (view.xml_id or view.key):
xml_id = view.xml_id or view.key
# It is safe to split on / herebelow because arch_fs is explicitely stored with '/'
fullpath = get_resource_path(*view.arch_fs.split('/'))
if fullpath:
arch_fs = get_view_arch_from_file(fullpath, xml_id)
# replace %(xml_id)s, %(xml_id)d, %%(xml_id)s, %%(xml_id)d by the res_id
if arch_fs:
arch_fs = resolve_external_ids(arch_fs, xml_id).replace('%%', '%')
translation_dictionary = field_arch_db.get_translation_dictionary(
view.with_env(env_en).arch_db, {lang: view.with_env(env_lang).arch_db}
)
arch_fs = field_arch_db.translate(
lambda term: translation_dictionary[term][lang],
arch_fs
)
else:
try:
fullpath = file_path(view.arch_fs)
except FileNotFoundError:
_logger.warning("View %s: Full path [%s] cannot be found.", xml_id, view.arch_fs)
arch_fs = False
continue
arch_fs = get_view_arch_from_file(fullpath, xml_id)
# replace %(xml_id)s, %(xml_id)d, %%(xml_id)s, %%(xml_id)d by the res_id
if arch_fs:
arch_fs = resolve_external_ids(arch_fs, xml_id).replace('%%', '%')
translation_dictionary = field_arch_db.get_translation_dictionary(
view.with_env(env_en).arch_db, {lang: view.with_env(env_lang).arch_db}
)
arch_fs = field_arch_db.translate(
lambda term: translation_dictionary[term][lang],
arch_fs
)
view.arch = pycompat.to_text(arch_fs or view.arch_db)
def _inverse_arch(self):
+2 -3
View File
@@ -3,7 +3,7 @@
from odoo.tests.common import TransactionCase
from odoo.tools import pdf
from odoo.modules.module import get_module_resource
from odoo.tools.misc import file_open
import io
@@ -12,8 +12,7 @@ class TestPdf(TransactionCase):
def setUp(self):
super().setUp()
file_path = get_module_resource('base', 'tests', 'minimal.pdf')
self.file = open(file_path, 'rb').read()
self.file = file_open('base/tests/minimal.pdf', 'rb').read()
self.minimal_reader_buffer = io.BytesIO(self.file)
self.minimal_pdf_reader = pdf.OdooPdfFileReader(self.minimal_reader_buffer)
-1
View File
@@ -12,7 +12,6 @@ from lxml.builder import E
from copy import deepcopy
from textwrap import dedent
from odoo.modules import get_module_resource
from odoo.tests.common import TransactionCase
from odoo.addons.base.models.ir_qweb import QWebException, render
from odoo.tools import misc, mute_logger
@@ -18,12 +18,12 @@ from odoo.addons import __path__ as ADDONS_PATH
from odoo.addons.base.models.assetsbundle import AssetsBundle
from odoo.addons.base.models.ir_asset import AssetPaths
from odoo.addons.base.models.ir_attachment import IrAttachment
from odoo.modules.module import get_resource_path, get_manifest
from odoo.modules.module import get_manifest
from odoo.tests import HttpCase, tagged
from odoo.tests.common import TransactionCase
from odoo.addons.base.models.ir_qweb import QWebException
from odoo.tools import mute_logger, func
from odoo.tools.misc import file_path
GETMTINE = os.path.getmtime
@@ -241,7 +241,7 @@ class TestJavascriptAssetsBundle(FileTouchable):
last_modified0 = bundle0.get_checksum('js')
version0 = bundle0.get_version('js')
path = get_resource_path('test_assetsbundle', 'static', 'src', 'js', 'test_jsfile1.js')
path = file_path('test_assetsbundle/static/src/js/test_jsfile1.js')
bundle1 = self._get_asset(self.jsbundle_name, debug_assets=True)
with self._touch(path):
@@ -504,7 +504,7 @@ class TestJavascriptAssetsBundle(FileTouchable):
# 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')
path = file_path('test_assetsbundle/static/src/css/test_cssfile1.css')
ltr_bundle1 = self._get_asset(self.cssbundle_name, debug_assets=True)
with self._touch(path):
@@ -768,7 +768,7 @@ class TestAssetsBundleWithIRAMock(FileTouchable):
self._bundle(self._get_asset(), False, False, '(Second access, no change)')
# Touch the file and compile a third time
path = get_resource_path('test_assetsbundle', 'static', 'src', 'scss', 'test_file1.scss')
path = file_path('test_assetsbundle/static/src/scss/test_file1.scss')
t = time.time() + 5
asset = self._get_asset()
with self._touch(path, t):
@@ -8,9 +8,9 @@ from lxml import etree as ET
from lxml.builder import E
import odoo
from odoo.modules.module import get_resource_path
from odoo.tests import common
from odoo.tools.convert import convert_file, xml_import, _eval_xml
from odoo.tools.misc import file_path
Field = E.field
Value = E.value
@@ -237,7 +237,7 @@ class TestEvalXML(common.TransactionCase):
self.assertEqual(record.name, 'bar')
# Reset the value to the one from the XML data file,
# with a lang passed in the environment.
filepath = get_resource_path('test_convert', 'data/test_translated_field/test_model_data.xml')
filepath = file_path('test_convert/data/test_translated_field/test_model_data.xml')
doc = ET.parse(filepath)
obj = xml_import(env_fr, 'test_convert', {}, mode='init', xml_filename=filepath)
obj.parse(doc.getroot())
@@ -7,6 +7,7 @@ import re
from odoo.tests import common
from odoo.tools import html_escape as e
from odoo.tools.misc import file_open
directory = os.path.dirname(__file__)
@@ -216,7 +217,7 @@ class TestBinaryExport(TestBasicExport):
def test_image(self):
converter = self.env['ir.qweb.field.image']
with open(os.path.join(directory, 'test_vectors', 'image'), 'rb') as f:
with file_open(os.path.join(directory, 'test_vectors', 'image'), 'rb') as f:
content = f.read()
encoded_content = base64.b64encode(content)
@@ -225,13 +226,13 @@ class TestBinaryExport(TestBasicExport):
self.assertEqual(
value, u'<img src="data:image/jpeg;base64,%s">' % encoded_content.decode('ascii'))
with open(os.path.join(directory, 'test_vectors', 'pdf'), 'rb') as f:
with file_open(os.path.join(directory, 'test_vectors', 'pdf'), 'rb') as f:
content = f.read()
with self.assertRaises(ValueError):
converter.value_to_html(base64.b64encode(content), {})
with open(os.path.join(directory, 'test_vectors', 'pptx'), 'rb') as f:
with file_open(os.path.join(directory, 'test_vectors', 'pptx'), 'rb') as f:
content = f.read()
with self.assertRaises(ValueError):
+2 -2
View File
@@ -6,8 +6,8 @@ import re
import subprocess
from unittest import skipIf
from odoo import tools
from odoo.modules.module import get_resource_path
from odoo.tests import tagged
from odoo.tools.misc import file_path
from . import lint_case
@@ -32,7 +32,7 @@ class TestESLint(lint_case.LintCase):
if not re.match('.*/libs?/.*', p) # don't check libraries
if not re.match('.*/o_spreadsheet/o_spreadsheet.js', p) # don't check generated code
]
eslintrc_path = get_resource_path('test_lint', 'tests', 'eslintrc')
eslintrc_path = file_path('test_lint/tests/eslintrc')
_logger.info('Testing %s js files', len(files_to_check))
# https://eslint.org/docs/user-guide/command-line-interface
+2 -2
View File
@@ -6,7 +6,7 @@ import itertools
import os
from . import lint_case
from odoo.tools.misc import file_open
class L10nChecker(lint_case.NodeVisitor):
def matches_tagged(self, node):
@@ -44,7 +44,7 @@ class L10nLinter(lint_case.LintCase):
checker = L10nChecker()
rs = []
for path in self.iter_module_files('**/l10n_*/tests/*.py'):
with open(path, 'rb') as f:
with file_open(path, 'rb') as f:
t = ast.parse(f.read(), path)
rs.extend(zip(itertools.repeat(os.path.relpath(path)), checker.visit(t)))
@@ -2,11 +2,12 @@
import logging
from ast import literal_eval
from os.path import join as opj
from odoo.modules import get_modules
from odoo.modules.module import _DEFAULT_MANIFEST, module_manifest, get_module_path, get_module_resource
from odoo.modules.module import _DEFAULT_MANIFEST, module_manifest, get_module_path
from odoo.tests import BaseCase
from odoo.tools import file_open
from odoo.tools.misc import file_open, file_path
_logger = logging.getLogger(__name__)
@@ -105,8 +106,9 @@ class ManifestLinter(BaseCase):
module)
else:
path_parts = value.split('/')
path = get_module_resource(path_parts[1], *path_parts[2:])
if not path:
try:
file_path(opj(*path_parts[1:]))
except FileNotFoundError:
_logger.warning(
"Icon value specified in manifest of module %s wasn't found in given path."
" Please specify a correct value or remove this key from the manifest.",
@@ -3,7 +3,7 @@ import itertools
import os
from . import lint_case
from odoo.tools.misc import file_open
class OnchangeChecker(lint_case.NodeVisitor):
def matches_onchange(self, node):
@@ -37,7 +37,7 @@ class TestOnchangeDomains(lint_case.LintCase):
checker = OnchangeChecker()
rs = []
for path in self.iter_module_files('*.py'):
with open(path, 'rb') as f:
with file_open(path, 'rb') as f:
t = ast.parse(f.read(), path)
rs.extend(zip(itertools.repeat(os.path.relpath(path)), checker.visit(t)))
+5 -3
View File
@@ -3,9 +3,10 @@
from collections import Counter
from odoo.modules import get_modules, get_resource_path
from odoo.modules import get_modules
from odoo.tests.common import TransactionCase
from odoo.tools.translate import TranslationFileReader
from odoo.tools.misc import file_path
class PotLinter(TransactionCase):
@@ -21,8 +22,9 @@ class PotLinter(TransactionCase):
# retrieve all modules, and their corresponding POT file
for module in get_modules():
filename = get_resource_path(module, 'i18n', module + '.pot')
if not filename:
try:
filename = file_path(f'{module}/i18n/{module}.pot')
except FileNotFoundError:
continue
counts = Counter(map(format, TranslationFileReader(filename)))
duplicates = [key for key, count in counts.items() if count > 1]
@@ -2,10 +2,11 @@
import os.path
from odoo.tests.common import BaseCase
from odoo.tools.misc import file_open
from odoo.tools.mimetypes import guess_mimetype
def contents(extension):
with open(os.path.join(
with file_open(os.path.join(
os.path.dirname(__file__),
'testfiles',
'case.{}'.format(extension)
+3 -2
View File
@@ -25,8 +25,9 @@ def initialize(cr):
and ir_model_data entries.
"""
f = odoo.modules.get_module_resource('base', 'data', 'base_data.sql')
if not f:
try:
f = odoo.tools.misc.file_path('base/data/base_data.sql')
except FileNotFoundError:
m = "File not found: 'base.sql' (provided by module 'base')."
_logger.critical(m)
raise IOError(m)
+11 -4
View File
@@ -11,10 +11,10 @@ import os
import re
from os.path import join as opj
from odoo.modules.module import get_resource_path
import odoo.release as release
import odoo.upgrade
from odoo.tools.parse_version import parse_version
from odoo.tools.misc import file_path
_logger = logging.getLogger(__name__)
@@ -47,7 +47,7 @@ VERSION_RE = re.compile(
def load_script(path, module_name):
full_path = get_resource_path(*path.split(os.path.sep)) if not os.path.isabs(path) else path
full_path = file_path(path) if not os.path.isabs(path) else path
spec = importlib.util.spec_from_file_location(module_name, full_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
@@ -122,14 +122,21 @@ class MigrationManager(object):
if _verify_upgrade_version(path, version)
}
def check_path(path):
try:
return file_path(path)
except FileNotFoundError:
return False
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')),
'module_upgrades': get_scripts(get_resource_path(pkg.name, 'upgrades')),
'module': get_scripts(check_path(pkg.name + '/migrations')),
'module_upgrades': get_scripts(check_path(pkg.name + '/upgrades')),
}
scripts = defaultdict(list)
+10 -9
View File
@@ -243,17 +243,18 @@ def get_resource_from_path(path):
return None
def get_module_icon(module):
iconpath = ['static', 'description', 'icon.png']
if get_module_resource(module, *iconpath):
return ('/' + module + '/') + '/'.join(iconpath)
return '/base/' + '/'.join(iconpath)
fpath = f"{module}/static/description/icon.png"
try:
file_path(fpath)
return "/" + fpath
except FileNotFoundError:
return "/base/static/description/icon.png"
def get_module_icon_path(module):
iconpath = ['static', 'description', 'icon.png']
path = get_module_resource(module.name, *iconpath)
if not path:
path = get_module_resource('base', *iconpath)
return path
try:
return file_path(f"{module}/static/description/icon.png")
except FileNotFoundError:
return file_path("base/static/description/icon.png")
def module_manifest(path):
"""Returns path to module manifest if one can be found under `path`, else `None`."""
+4 -2
View File
@@ -1,6 +1,8 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from contextlib import suppress
import odoo
import logging
@@ -17,8 +19,8 @@ def get_installed_modules(cursor):
def get_neutralization_queries(modules):
# neutralization for each module
for module in modules:
filename = odoo.modules.get_module_resource(module, 'data/neutralize.sql')
if filename:
filename = f'{module}/data/neutralize.sql'
with suppress(FileNotFoundError):
with odoo.tools.misc.file_open(filename) as file:
yield file.read().strip()
+4 -3
View File
@@ -28,7 +28,7 @@ except ImportError:
import odoo
from . import pycompat
from .config import config
from .misc import file_open, unquote, ustr, SKIPPED_ELEMENT_TYPES
from .misc import file_open, file_path, SKIPPED_ELEMENT_TYPES
from .translate import _
from odoo import SUPERUSER_ID, api
from odoo.exceptions import ValidationError
@@ -155,9 +155,10 @@ def _eval_xml(self, node, env):
# after that, only text content makes sense
data = pycompat.to_text(data)
if t == 'file':
from ..modules import module
path = data.strip()
if not module.get_module_resource(self.module, path):
try:
file_path(os.path.join(self.module, path))
except FileNotFoundError:
raise IOError("No such file or directory: '%s' in %s" % (
path, self.module))
return '%s,%s' % (self.module, path)
+2 -3
View File
@@ -428,10 +428,9 @@ def scan_languages():
:returns: a list of (lang_code, lang_name) pairs
:rtype: [(str, unicode)]
"""
csvpath = odoo.modules.module.get_resource_path('base', 'data', 'res.lang.csv')
try:
# read (code, name) from languages in base/data/res.lang.csv
with open(csvpath, 'rb') as csvfile:
with file_open('base/data/res.lang.csv', 'rb') as csvfile:
reader = pycompat.csv_reader(csvfile, delimiter=',', quotechar='"')
fields = next(reader)
code_index = fields.index("code")
@@ -441,7 +440,7 @@ def scan_languages():
for row in reader
]
except Exception:
_logger.error("Could not read %s", csvpath)
_logger.error("Could not read res.lang.csv")
result = []
return sorted(result or [('en_US', u'English')], key=itemgetter(1))
+10 -6
View File
@@ -17,6 +17,7 @@ import tarfile
import threading
import warnings
from collections import defaultdict, namedtuple
from contextlib import suppress
from datetime import datetime
from os.path import join
@@ -27,9 +28,8 @@ from psycopg2.extras import Json
import odoo
from odoo.exceptions import UserError
from odoo.modules.module import get_resource_path
from . import config, pycompat
from .misc import file_open, get_iso_codes, SKIPPED_ELEMENT_TYPES
from .misc import file_open, file_path, get_iso_codes, SKIPPED_ELEMENT_TYPES
_logger = logging.getLogger(__name__)
@@ -1146,7 +1146,7 @@ class TranslationModuleReader:
if not module:
return
extra_comments = extra_comments or []
src_file = open(fabsolutepath, 'rb')
src_file = file_open(fabsolutepath, 'rb')
options = {}
if extract_method == 'python':
options['encoding'] = 'UTF-8'
@@ -1239,7 +1239,8 @@ class TranslationImporter:
the language must be present and activated in the database
:param xmlids: if given, only translations for records with xmlid in xmlids will be loaded
"""
with file_open(filepath, mode='rb') as fileobj:
with suppress(FileNotFoundError), file_open(filepath, mode='rb') as fileobj:
_logger.info('loading base translation file %s for language %s', filepath, lang)
fileformat = os.path.splitext(filepath)[-1][1:].lower()
self.load(fileobj, fileformat, lang, xmlids=xmlids)
@@ -1484,12 +1485,15 @@ def get_po_paths(module_name: str, lang: str):
else:
langs = [lang_base, lang]
return [
po_paths = [
path
for lang_ in langs
for dir_ in ('i18n', 'i18n_extra')
if (path := get_resource_path(module_name, dir_, lang_ + '.po'))
if (path := join(module_name, dir_, lang_ + '.po'))
]
for path in po_paths:
with suppress(FileNotFoundError):
yield file_path(path)
class CodeTranslations: