Skip to content
Snippets Groups Projects
Commit 048c7fef authored by william's avatar william
Browse files

[IMP] base: _check_with_xsd from ir.attachment

Search the xsd files from in the database.
To enable this option, the Environment should be passed to the optional
`env` parameter. Both the XSD root and the XSD imported by the root and
the recusrively imported files will be searched in the database.

X-original-commit: 06a35f2e
parent a0f45bab
No related branches found
No related tags found
No related merge requests found
# -*- coding: utf-8 -*-
from . import test_methods
from . import test_lxml
from . import test_form_impl
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.tests import common
from odoo.tools.xml_utils import _check_with_xsd
import base64
from lxml.etree import XMLSchemaError
class TestLXML(common.TransactionCase):
def test_lxml_import_from_filestore(self):
resolver_schema_int = b"""
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:etype="http://codespeak.net/lxml/test/external">
<xsd:import namespace="http://codespeak.net/lxml/test/external" schemaLocation="imported_schema.xsd"/>
<xsd:element name="a" type="etype:AType"/>
</xsd:schema>
"""
incomplete_schema_int = b"""
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:etype="http://codespeak.net/lxml/test/external">
<xsd:import namespace="http://codespeak.net/lxml/test/external" schemaLocation="non_existing_schema.xsd"/>
<xsd:element name="a" type="etype:AType"/>
</xsd:schema>
"""
imported_schema = b"""
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://codespeak.net/lxml/test/external">
<xsd:complexType name="AType">
<xsd:sequence><xsd:element name="b" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/></xsd:sequence>
</xsd:complexType>
</xsd:schema>
"""
self.env['ir.attachment'].create([{
'datas': base64.b64encode(resolver_schema_int),
'name': 'resolver_schema_int.xsd'
}, {
'datas': base64.b64encode(incomplete_schema_int),
'name': 'incomplete_schema_int.xsd'
}, {
'datas': base64.b64encode(imported_schema),
'name': 'imported_schema.xsd'
}])
_check_with_xsd("<a><b></b></a>", 'resolver_schema_int.xsd', self.env)
with self.assertRaises(XMLSchemaError):
_check_with_xsd("<a><b></b></a>", 'incomplete_schema_int.xsd', self.env)
with self.assertRaises(FileNotFoundError):
_check_with_xsd("<a><b></b></a>", 'non_existing_schema.xsd', self.env)
# -*- coding: utf-8 -*-
import base64
from io import BytesIO
from lxml import etree
from odoo.tools.misc import file_open
from odoo.exceptions import UserError
class odoo_resolver(etree.Resolver):
"""Odoo specific file resolver that can be added to the XML Parser.
It will search filenames in the ir.attachments
"""
def __init__(self, env):
super().__init__()
self.env = env
def resolve(self, url, id, context):
"""Search url in ``ir.attachment`` and return the resolved content."""
attachment = self.env['ir.attachment'].search([('name', '=', url)])
if attachment:
return self.resolve_string(base64.b64decode(attachment.datas), context)
def check_with_xsd(tree_or_str, stream):
raise UserError("Method 'check_with_xsd' deprecated ")
def _check_with_xsd(tree_or_str, stream, env=None):
"""Check an XML against an XSD schema.
def _check_with_xsd(tree_or_str, stream):
This will raise a UserError if the XML file is not valid according to the
XSD file.
:param tree_or_str (etree, str): representation of the tree to be checked
:param stream (io.IOBase, str): the byte stream used to build the XSD schema.
If env is given, it can also be the name of an attachment in the filestore
:param env (odoo.api.Environment): If it is given, it enables resolving the
imports of the schema in the filestore with ir.attachments.
"""
if not isinstance(tree_or_str, etree._Element):
tree_or_str = etree.fromstring(tree_or_str)
xml_schema_doc = etree.parse(stream)
xsd_schema = etree.XMLSchema(xml_schema_doc)
parser = etree.XMLParser()
if env:
parser.resolvers.add(odoo_resolver(env))
if isinstance(stream, str) and stream.endswith('.xsd'):
attachment = env['ir.attachment'].search([('name', '=', stream)])
if not attachment:
raise FileNotFoundError()
stream = BytesIO(base64.b64decode(attachment.datas))
xsd_schema = etree.XMLSchema(etree.parse(stream, parser=parser))
try:
xsd_schema.assertValid(tree_or_str)
except etree.DocumentInvalid as xml_errors:
#import UserError only here to avoid circular import statements with tools.func being imported in exceptions.py
from odoo.exceptions import UserError
raise UserError('\n'.join(str(e) for e in xml_errors.error_log))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment