[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:
@@ -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})
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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,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')
|
||||
|
||||
@@ -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()),
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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 = []
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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__)
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)))
|
||||
|
||||
|
||||
@@ -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
@@ -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,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
@@ -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`."""
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user