Code refactoring for tests
- Rename XMLSchemaTestCase to XsdValidatorTestCase - Add casepath() helper - Modify TestResources: derive from TestCase and use casepath() - Split test_package.py into 3 modules (added test_etree.py and test_memory.py) - Update .tox with new environments 'package' and 'memory' - Replace test_package with test_etree into test_all.py script - Modify XsdValidatorTestCase.check_schema() to use xs prefix for XSD namespace and no namespace as targetNamespace for a fast reuse of common and user sample cases
This commit is contained in:
parent
81849f2368
commit
6994da5173
|
@ -6,7 +6,8 @@
|
|||
*.json
|
||||
.idea/
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage*
|
||||
!.coveragerc
|
||||
.ipynb_checkpoints/
|
||||
doc/_*/
|
||||
dist/
|
||||
|
|
|
@ -62,7 +62,7 @@ author = 'Davide Brunato'
|
|||
# The short X.Y version.
|
||||
version = '1.0'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '1.0.13'
|
||||
release = '1.0.14'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
|
4
setup.py
4
setup.py
|
@ -38,8 +38,8 @@ class InstallCommand(install):
|
|||
|
||||
setup(
|
||||
name='xmlschema',
|
||||
version='1.0.13',
|
||||
install_requires=['elementpath~=1.1.7'],
|
||||
version='1.0.14',
|
||||
install_requires=['elementpath~=1.1.8'],
|
||||
packages=['xmlschema'],
|
||||
include_package_data=True,
|
||||
cmdclass={
|
||||
|
|
19
tox.ini
19
tox.ini
|
@ -4,7 +4,7 @@
|
|||
# and then run "tox" from this directory.
|
||||
|
||||
[tox]
|
||||
envlist = py27, py35, py36, py37, py38, docs, flake8, coverage
|
||||
envlist = package, py27, py35, py36, py37, py38, memory, docs, flake8, coverage
|
||||
skip_missing_interpreters = true
|
||||
toxworkdir = {homedir}/.tox/xmlschema
|
||||
|
||||
|
@ -12,24 +12,21 @@ toxworkdir = {homedir}/.tox/xmlschema
|
|||
deps =
|
||||
lxml
|
||||
elementpath~=1.1.7
|
||||
py37: memory_profiler
|
||||
py27: pathlib2
|
||||
memory: memory_profiler
|
||||
docs: Sphinx
|
||||
docs: sphinx_rtd_theme
|
||||
flake8: flake8
|
||||
coverage: coverage
|
||||
coverage: memory_profiler
|
||||
commands = python xmlschema/tests/test_all.py {posargs}
|
||||
whitelist_externals = make
|
||||
|
||||
[testenv:py27]
|
||||
deps =
|
||||
lxml
|
||||
elementpath~=1.1.7
|
||||
pathlib2
|
||||
commands = python xmlschema/tests/test_all.py {posargs}
|
||||
[testenv:package]
|
||||
commands = python xmlschema/tests/test_package.py
|
||||
|
||||
[testenv:py38]
|
||||
deps = elementpath~=1.1.7
|
||||
commands = python xmlschema/tests/test_all.py {posargs}
|
||||
[testenv:memory]
|
||||
commands = python xmlschema/tests/test_memory.py
|
||||
|
||||
[testenv:docs]
|
||||
commands =
|
||||
|
|
|
@ -26,7 +26,7 @@ from .validators import (
|
|||
XMLSchemaBase, XMLSchema, XMLSchema10
|
||||
)
|
||||
|
||||
__version__ = '1.0.13'
|
||||
__version__ = '1.0.14'
|
||||
__author__ = "Davide Brunato"
|
||||
__contact__ = "brunato@sissa.it"
|
||||
__copyright__ = "Copyright 2016-2019, SISSA"
|
||||
|
|
|
@ -45,29 +45,37 @@ def has_network_access(*locations):
|
|||
|
||||
SKIP_REMOTE_TESTS = not has_network_access('http://www.sissa.it', 'http://www.w3.org/', 'http://dublincore.org/')
|
||||
PROTECTED_PREFIX_PATTERN = re.compile(r'ns\d:')
|
||||
TEST_CASES_DIR = os.path.join(os.path.dirname(__file__), 'test_cases/')
|
||||
SCHEMA_TEMPLATE = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" version="{0}">
|
||||
{1}
|
||||
</xs:schema>"""
|
||||
|
||||
|
||||
def casepath(relative_path):
|
||||
"""
|
||||
Returns the absolute path from a relative path specified from the `xmlschema/tests/test_cases/` dir.
|
||||
"""
|
||||
return os.path.join(TEST_CASES_DIR, relative_path)
|
||||
|
||||
|
||||
def print_test_header():
|
||||
"""Print an header thar displays Python version and platform used for test session."""
|
||||
header1 = "Test %r" % xmlschema
|
||||
header2 = "with Python {} on platform {}".format(platform.python_version(), platform.platform())
|
||||
print('{0}\n{1}\n{2}\n{0}'.format("*" * max(len(header1), len(header2)), header1, header2))
|
||||
|
||||
|
||||
class XMLSchemaTestCase(unittest.TestCase):
|
||||
class XsdValidatorTestCase(unittest.TestCase):
|
||||
"""
|
||||
XMLSchema TestCase class.
|
||||
TestCase class for XSD validators.
|
||||
"""
|
||||
@classmethod
|
||||
def casepath(cls, relative_path):
|
||||
return casepath(relative_path)
|
||||
|
||||
Setup tests common environment. The tests parts have to use empty prefix for
|
||||
XSD namespace names and 'ns' prefix for XMLSchema test namespace names.
|
||||
"""
|
||||
test_cases_dir = os.path.join(os.path.dirname(__file__), 'test_cases/')
|
||||
etree_register_namespace(prefix='', uri=XSD_NAMESPACE)
|
||||
etree_register_namespace(prefix='xs', uri=XSD_NAMESPACE)
|
||||
etree_register_namespace(prefix='ns', uri="ns")
|
||||
SCHEMA_TEMPLATE = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<schema xmlns:ns="ns" xmlns="http://www.w3.org/2001/XMLSchema"
|
||||
targetNamespace="ns" elementFormDefault="unqualified" version="{0}">
|
||||
{1}
|
||||
</schema>"""
|
||||
|
||||
schema_class = XMLSchema
|
||||
|
||||
|
@ -83,36 +91,27 @@ class XMLSchemaTestCase(unittest.TestCase):
|
|||
'ns': 'ns',
|
||||
}
|
||||
|
||||
cls.vh_dir = cls.casepath('examples/vehicles')
|
||||
cls.vh_xsd_file = cls.casepath('examples/vehicles/vehicles.xsd')
|
||||
cls.vh_xml_file = cls.casepath('examples/vehicles/vehicles.xml')
|
||||
cls.vh_json_file = cls.casepath('examples/vehicles/vehicles.json')
|
||||
cls.vh_dir = casepath('examples/vehicles')
|
||||
cls.vh_xsd_file = casepath('examples/vehicles/vehicles.xsd')
|
||||
cls.vh_xml_file = casepath('examples/vehicles/vehicles.xml')
|
||||
cls.vh_json_file = casepath('examples/vehicles/vehicles.json')
|
||||
cls.vh_schema = cls.schema_class(cls.vh_xsd_file)
|
||||
cls.vh_namespaces = fetch_namespaces(cls.vh_xml_file)
|
||||
|
||||
cls.col_dir = cls.casepath('examples/collection')
|
||||
cls.col_xsd_file = cls.casepath('examples/collection/collection.xsd')
|
||||
cls.col_xml_file = cls.casepath('examples/collection/collection.xml')
|
||||
cls.col_json_file = cls.casepath('examples/collection/collection.json')
|
||||
cls.col_dir = casepath('examples/collection')
|
||||
cls.col_xsd_file = casepath('examples/collection/collection.xsd')
|
||||
cls.col_xml_file = casepath('examples/collection/collection.xml')
|
||||
cls.col_json_file = casepath('examples/collection/collection.json')
|
||||
cls.col_schema = cls.schema_class(cls.col_xsd_file)
|
||||
cls.col_namespaces = fetch_namespaces(cls.col_xml_file)
|
||||
|
||||
cls.st_xsd_file = cls.casepath('features/decoder/simple-types.xsd')
|
||||
cls.st_xsd_file = casepath('features/decoder/simple-types.xsd')
|
||||
cls.st_schema = cls.schema_class(cls.st_xsd_file)
|
||||
|
||||
cls.models_xsd_file = cls.casepath('features/models/models.xsd')
|
||||
cls.models_xsd_file = casepath('features/models/models.xsd')
|
||||
cls.models_schema = cls.schema_class(cls.models_xsd_file)
|
||||
|
||||
@classmethod
|
||||
def casepath(cls, path):
|
||||
"""
|
||||
Returns the absolute path of a test case file.
|
||||
|
||||
:param path: the relative path of the case file from base dir ``xmlschema/tests/test_cases/``.
|
||||
"""
|
||||
return os.path.join(cls.test_cases_dir, path)
|
||||
|
||||
def retrieve_schema_source(self, source):
|
||||
def get_schema_source(self, source):
|
||||
"""
|
||||
Returns a schema source that can be used to create an XMLSchema instance.
|
||||
|
||||
|
@ -129,9 +128,7 @@ class XMLSchemaTestCase(unittest.TestCase):
|
|||
raise XMLSchemaValueError("% is not an XSD global definition/declaration." % source)
|
||||
|
||||
root = etree_element('schema', attrib={
|
||||
'xmlns:ns': "ns",
|
||||
'xmlns': "http://www.w3.org/2001/XMLSchema",
|
||||
'targetNamespace': "ns",
|
||||
'xmlns:xs': "http://www.w3.org/2001/XMLSchema",
|
||||
'elementFormDefault': "qualified",
|
||||
'version': self.schema_class.XSD_VERSION,
|
||||
})
|
||||
|
@ -140,19 +137,11 @@ class XMLSchemaTestCase(unittest.TestCase):
|
|||
else:
|
||||
source = source.strip()
|
||||
if not source.startswith('<'):
|
||||
return self.casepath(source)
|
||||
return casepath(source)
|
||||
elif source.startswith('<?xml ') or source.startswith('<xs:schema '):
|
||||
return source
|
||||
else:
|
||||
return self.SCHEMA_TEMPLATE.format(self.schema_class.XSD_VERSION, source)
|
||||
|
||||
def get_schema(self, source):
|
||||
return self.schema_class(self.retrieve_schema_source(source))
|
||||
|
||||
def get_element(self, name, **attrib):
|
||||
source = '<element name="{}" {}/>'.format(
|
||||
name, ' '.join('%s="%s"' % (k, v) for k, v in attrib.items())
|
||||
)
|
||||
schema = self.schema_class(self.retrieve_schema_source(source))
|
||||
return schema.elements[name]
|
||||
return SCHEMA_TEMPLATE.format(self.schema_class.XSD_VERSION, source)
|
||||
|
||||
def check_etree_elements(self, elem, other):
|
||||
"""Checks if two ElementTree elements are equal."""
|
||||
|
@ -168,6 +157,16 @@ class XMLSchemaTestCase(unittest.TestCase):
|
|||
msg = "Protected prefix {!r} found:\n {}".format(match.group(0), s)
|
||||
self.assertIsNone(match, msg)
|
||||
|
||||
def get_schema(self, source):
|
||||
return self.schema_class(self.get_schema_source(source))
|
||||
|
||||
def get_element(self, name, **attrib):
|
||||
source = '<xs:element name="{}" {}/>'.format(
|
||||
name, ' '.join('%s="%s"' % (k, v) for k, v in attrib.items())
|
||||
)
|
||||
schema = self.schema_class(self.get_schema_source(source))
|
||||
return schema.elements[name]
|
||||
|
||||
def check_errors(self, path, expected):
|
||||
"""
|
||||
Checks schema or validation errors, checking information completeness of the
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
# @author Davide Brunato <brunato@sissa.it>
|
||||
#
|
||||
if __name__ == '__main__':
|
||||
from xmlschema.tests import print_test_header
|
||||
from xmlschema.tests.test_etree import *
|
||||
from xmlschema.tests.test_helpers import *
|
||||
from xmlschema.tests.test_meta import *
|
||||
from xmlschema.tests.test_regex import *
|
||||
|
@ -18,8 +20,6 @@ if __name__ == '__main__':
|
|||
from xmlschema.tests.test_models import *
|
||||
from xmlschema.tests.test_schemas import *
|
||||
from xmlschema.tests.test_validators import *
|
||||
from xmlschema.tests.test_package import *
|
||||
from xmlschema.tests import print_test_header
|
||||
|
||||
print_test_header()
|
||||
unittest.main()
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c), 2018-2019, SISSA (International School for Advanced Studies).
|
||||
# All rights reserved.
|
||||
# This file is distributed under the terms of the MIT License.
|
||||
# See the file 'LICENSE' in the root directory of the present
|
||||
# distribution, or http://opensource.org/licenses/MIT.
|
||||
#
|
||||
# @author Davide Brunato <brunato@sissa.it>
|
||||
#
|
||||
import unittest
|
||||
import os
|
||||
import importlib
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
|
||||
@unittest.skipIf(sys.version_info < (3,), "In Python 2 ElementTree is not overwritten by cElementTree")
|
||||
class TestElementTree(unittest.TestCase):
|
||||
|
||||
def test_element_string_serialization(self):
|
||||
ElementTree = importlib.import_module('xml.etree.ElementTree')
|
||||
xmlschema_etree = importlib.import_module('xmlschema.etree')
|
||||
|
||||
elem = ElementTree.Element('element')
|
||||
self.assertEqual(xmlschema_etree.etree_tostring(elem), '<element />')
|
||||
elem = xmlschema_etree.ElementTree.Element('element')
|
||||
self.assertEqual(xmlschema_etree.etree_tostring(elem), '<element />')
|
||||
elem = xmlschema_etree.PyElementTree.Element('element')
|
||||
self.assertEqual(xmlschema_etree.etree_tostring(elem), '<element />')
|
||||
|
||||
def test_import_element_tree_before(self):
|
||||
ElementTree = importlib.import_module('xml.etree.ElementTree')
|
||||
xmlschema_etree = importlib.import_module('xmlschema.etree')
|
||||
|
||||
self.assertIsNot(ElementTree.Element, ElementTree._Element_Py, msg="cElementTree not available!")
|
||||
elem = xmlschema_etree.PyElementTree.Element('element')
|
||||
self.assertEqual(xmlschema_etree.etree_tostring(elem), '<element />')
|
||||
self.assertIs(importlib.import_module('xml.etree.ElementTree'), ElementTree)
|
||||
self.assertIs(xmlschema_etree.ElementTree, ElementTree)
|
||||
|
||||
def test_import_element_tree_after(self):
|
||||
xmlschema_etree = importlib.import_module('xmlschema.etree')
|
||||
ElementTree = importlib.import_module('xml.etree.ElementTree')
|
||||
|
||||
self.assertIsNot(ElementTree.Element, ElementTree._Element_Py, msg="cElementTree not available!")
|
||||
elem = xmlschema_etree.PyElementTree.Element('element')
|
||||
self.assertEqual(xmlschema_etree.etree_tostring(elem), '<element />')
|
||||
self.assertIs(importlib.import_module('xml.etree.ElementTree'), ElementTree)
|
||||
self.assertIs(xmlschema_etree.ElementTree, ElementTree)
|
||||
|
||||
def test_element_tree_import_script(self):
|
||||
test_dir = os.path.dirname(__file__) or '.'
|
||||
|
||||
cmd = [os.path.join(test_dir, 'check_etree_import.py')]
|
||||
process = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
output = process.stdout.decode('utf-8')
|
||||
self.assertTrue("\nTest OK:" in output, msg="Wrong import of ElementTree after xmlschema")
|
||||
|
||||
cmd.append('--before')
|
||||
process = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
output = process.stdout.decode('utf-8')
|
||||
self.assertTrue("\nTest OK:" in output, msg="Wrong import of ElementTree before xmlschema")
|
||||
|
||||
def test_safe_xml_parser(self):
|
||||
test_dir = os.path.dirname(__file__) or '.'
|
||||
xmlschema_etree = importlib.import_module('xmlschema.etree')
|
||||
parser = xmlschema_etree.SafeXMLParser(target=xmlschema_etree.PyElementTree.TreeBuilder())
|
||||
PyElementTree = xmlschema_etree.PyElementTree
|
||||
|
||||
xml_file = os.path.join(test_dir, 'test_cases/resources/with_entity.xml')
|
||||
elem = xmlschema_etree.ElementTree.parse(xml_file).getroot()
|
||||
self.assertEqual(elem.text, 'abc')
|
||||
self.assertRaises(
|
||||
PyElementTree.ParseError, xmlschema_etree.ElementTree.parse, xml_file, parser=parser
|
||||
)
|
||||
|
||||
xml_file = os.path.join(test_dir, 'test_cases/resources/unused_external_entity.xml')
|
||||
elem = xmlschema_etree.ElementTree.parse(xml_file).getroot()
|
||||
self.assertEqual(elem.text, 'abc')
|
||||
self.assertRaises(
|
||||
PyElementTree.ParseError, xmlschema_etree.ElementTree.parse, xml_file, parser=parser
|
||||
)
|
||||
|
||||
xml_file = os.path.join(test_dir, 'test_cases/resources/external_entity.xml')
|
||||
self.assertRaises(xmlschema_etree.ParseError, xmlschema_etree.ElementTree.parse, xml_file)
|
||||
self.assertRaises(
|
||||
PyElementTree.ParseError, xmlschema_etree.ElementTree.parse, xml_file, parser=parser
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from xmlschema.tests import print_test_header
|
||||
|
||||
print_test_header()
|
||||
unittest.main()
|
|
@ -22,10 +22,9 @@ from xmlschema.helpers import get_xsd_annotation, iter_xsd_components, get_names
|
|||
local_name, qname_to_prefixed, has_xsd_components, get_xsd_component, \
|
||||
get_xml_bool_attribute, get_xsd_derivation_attribute
|
||||
from xmlschema.qnames import XSI_TYPE, XSD_SCHEMA, XSD_ELEMENT, XSD_SIMPLE_TYPE, XSD_ANNOTATION
|
||||
from xmlschema.tests import XMLSchemaTestCase
|
||||
|
||||
|
||||
class TestHelpers(XMLSchemaTestCase):
|
||||
class TestHelpers(unittest.TestCase):
|
||||
|
||||
def test_get_namespace_function(self):
|
||||
self.assertEqual(get_namespace(XSD_SIMPLE_TYPE), XSD_NAMESPACE)
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c), 2018-2019, SISSA (International School for Advanced Studies).
|
||||
# All rights reserved.
|
||||
# This file is distributed under the terms of the MIT License.
|
||||
# See the file 'LICENSE' in the root directory of the present
|
||||
# distribution, or http://opensource.org/licenses/MIT.
|
||||
#
|
||||
# @author Davide Brunato <brunato@sissa.it>
|
||||
#
|
||||
import unittest
|
||||
import os
|
||||
import decimal
|
||||
import subprocess
|
||||
|
||||
|
||||
class TestMemoryUsage(unittest.TestCase):
|
||||
|
||||
@staticmethod
|
||||
def check_memory_profile(output):
|
||||
"""Check the output of a memory memory profile run on a function."""
|
||||
mem_usage = []
|
||||
func_num = 0
|
||||
for line in output.split('\n'):
|
||||
parts = line.split()
|
||||
if 'def' in parts:
|
||||
func_num += 1
|
||||
if not parts or not parts[0].isdigit() or len(parts) == 1 \
|
||||
or not parts[1].replace('.', '').isdigit():
|
||||
continue
|
||||
mem_usage.append(decimal.Decimal(parts[1]))
|
||||
|
||||
if func_num > 1:
|
||||
raise ValueError("Cannot the a memory profile output of more than one function!")
|
||||
return max(v - mem_usage[0] for v in mem_usage[1:])
|
||||
|
||||
@unittest.skip
|
||||
def test_package_memory_usage(self):
|
||||
test_dir = os.path.dirname(__file__) or '.'
|
||||
cmd = [os.path.join(test_dir, 'check_memory.py'), '1']
|
||||
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||
package_mem = self.check_memory_profile(output)
|
||||
self.assertLess(package_mem, 20)
|
||||
|
||||
def test_element_tree_memory_usage(self):
|
||||
test_dir = os.path.dirname(__file__) or '.'
|
||||
xsd10_schema_file = os.path.join(
|
||||
os.path.dirname(os.path.abspath(test_dir)), 'validators/schemas/XSD_1.0/XMLSchema.xsd'
|
||||
)
|
||||
|
||||
cmd = [os.path.join(test_dir, 'check_memory.py'), '2', xsd10_schema_file]
|
||||
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||
parse_mem = self.check_memory_profile(output)
|
||||
|
||||
cmd = [os.path.join(test_dir, 'check_memory.py'), '3', xsd10_schema_file]
|
||||
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||
iterparse_mem = self.check_memory_profile(output)
|
||||
|
||||
cmd = [os.path.join(test_dir, 'check_memory.py'), '4', xsd10_schema_file]
|
||||
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||
lazy_iterparse_mem = self.check_memory_profile(output)
|
||||
|
||||
self.assertLess(parse_mem, 2)
|
||||
self.assertLessEqual(lazy_iterparse_mem, parse_mem / 2)
|
||||
self.assertLessEqual(lazy_iterparse_mem, iterparse_mem)
|
||||
|
||||
def test_decode_memory_usage(self):
|
||||
test_dir = os.path.dirname(__file__) or '.'
|
||||
xsd10_schema_file = os.path.join(
|
||||
os.path.dirname(os.path.abspath(test_dir)), 'validators/schemas/XSD_1.0/XMLSchema.xsd'
|
||||
)
|
||||
|
||||
cmd = [os.path.join(test_dir, 'check_memory.py'), '5', xsd10_schema_file]
|
||||
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||
decode_mem = self.check_memory_profile(output)
|
||||
|
||||
cmd = [os.path.join(test_dir, 'check_memory.py'), '6', xsd10_schema_file]
|
||||
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||
lazy_decode_mem = self.check_memory_profile(output)
|
||||
|
||||
self.assertLess(decode_mem, 2)
|
||||
self.assertLessEqual(lazy_decode_mem, decode_mem / decimal.Decimal(1.4))
|
||||
|
||||
def test_validate_memory_usage(self):
|
||||
test_dir = os.path.dirname(__file__) or '.'
|
||||
xsd10_schema_file = os.path.join(
|
||||
os.path.dirname(os.path.abspath(test_dir)), 'validators/schemas/XSD_1.0/XMLSchema.xsd'
|
||||
)
|
||||
|
||||
cmd = [os.path.join(test_dir, 'check_memory.py'), '7', xsd10_schema_file]
|
||||
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||
validate_mem = self.check_memory_profile(output)
|
||||
|
||||
cmd = [os.path.join(test_dir, 'check_memory.py'), '8', xsd10_schema_file]
|
||||
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||
lazy_validate_mem = self.check_memory_profile(output)
|
||||
|
||||
self.assertLess(validate_mem, 2)
|
||||
self.assertLessEqual(lazy_validate_mem, validate_mem / 2)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from xmlschema.tests import print_test_header
|
||||
|
||||
print_test_header()
|
||||
unittest.main()
|
|
@ -15,10 +15,10 @@ This module runs tests concerning model groups validation.
|
|||
import unittest
|
||||
|
||||
from xmlschema.validators import ModelVisitor
|
||||
from xmlschema.tests import XMLSchemaTestCase
|
||||
from xmlschema.tests import casepath, XsdValidatorTestCase
|
||||
|
||||
|
||||
class TestModelValidation(XMLSchemaTestCase):
|
||||
class TestModelValidation(XsdValidatorTestCase):
|
||||
|
||||
# --- Test helper functions ---
|
||||
|
||||
|
@ -468,7 +468,7 @@ class TestModelValidation(XMLSchemaTestCase):
|
|||
#
|
||||
# Tests on issues
|
||||
def test_issue_086(self):
|
||||
issue_086_xsd = self.casepath('issues/issue_086/issue_086.xsd')
|
||||
issue_086_xsd = casepath('issues/issue_086/issue_086.xsd')
|
||||
schema = self.schema_class(issue_086_xsd)
|
||||
group = schema.types['Foo'].content_type
|
||||
|
||||
|
|
|
@ -17,177 +17,8 @@ import os
|
|||
import re
|
||||
import importlib
|
||||
import platform
|
||||
import sys
|
||||
import decimal
|
||||
import subprocess
|
||||
|
||||
try:
|
||||
import memory_profiler
|
||||
except ImportError:
|
||||
memory_profiler = None
|
||||
|
||||
|
||||
@unittest.skipIf(sys.version_info < (3,), "In Python 2 ElementTree is not overwritten by cElementTree")
|
||||
class TestElementTree(unittest.TestCase):
|
||||
|
||||
def test_element_string_serialization(self):
|
||||
ElementTree = importlib.import_module('xml.etree.ElementTree')
|
||||
xmlschema_etree = importlib.import_module('xmlschema.etree')
|
||||
|
||||
elem = ElementTree.Element('element')
|
||||
self.assertEqual(xmlschema_etree.etree_tostring(elem), '<element />')
|
||||
elem = xmlschema_etree.ElementTree.Element('element')
|
||||
self.assertEqual(xmlschema_etree.etree_tostring(elem), '<element />')
|
||||
elem = xmlschema_etree.PyElementTree.Element('element')
|
||||
self.assertEqual(xmlschema_etree.etree_tostring(elem), '<element />')
|
||||
|
||||
def test_import_element_tree_before(self):
|
||||
ElementTree = importlib.import_module('xml.etree.ElementTree')
|
||||
xmlschema_etree = importlib.import_module('xmlschema.etree')
|
||||
|
||||
self.assertIsNot(ElementTree.Element, ElementTree._Element_Py, msg="cElementTree not available!")
|
||||
elem = xmlschema_etree.PyElementTree.Element('element')
|
||||
self.assertEqual(xmlschema_etree.etree_tostring(elem), '<element />')
|
||||
self.assertIs(importlib.import_module('xml.etree.ElementTree'), ElementTree)
|
||||
self.assertIs(xmlschema_etree.ElementTree, ElementTree)
|
||||
|
||||
def test_import_element_tree_after(self):
|
||||
xmlschema_etree = importlib.import_module('xmlschema.etree')
|
||||
ElementTree = importlib.import_module('xml.etree.ElementTree')
|
||||
|
||||
self.assertIsNot(ElementTree.Element, ElementTree._Element_Py, msg="cElementTree not available!")
|
||||
elem = xmlschema_etree.PyElementTree.Element('element')
|
||||
self.assertEqual(xmlschema_etree.etree_tostring(elem), '<element />')
|
||||
self.assertIs(importlib.import_module('xml.etree.ElementTree'), ElementTree)
|
||||
self.assertIs(xmlschema_etree.ElementTree, ElementTree)
|
||||
|
||||
def test_element_tree_import_script(self):
|
||||
test_dir = os.path.dirname(__file__) or '.'
|
||||
|
||||
cmd = [os.path.join(test_dir, 'check_etree_import.py')]
|
||||
process = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
output = process.stdout.decode('utf-8')
|
||||
self.assertTrue("\nTest OK:" in output, msg="Wrong import of ElementTree after xmlschema")
|
||||
|
||||
cmd.append('--before')
|
||||
process = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
output = process.stdout.decode('utf-8')
|
||||
self.assertTrue("\nTest OK:" in output, msg="Wrong import of ElementTree before xmlschema")
|
||||
|
||||
def test_safe_xml_parser(self):
|
||||
test_dir = os.path.dirname(__file__) or '.'
|
||||
xmlschema_etree = importlib.import_module('xmlschema.etree')
|
||||
parser = xmlschema_etree.SafeXMLParser(target=xmlschema_etree.PyElementTree.TreeBuilder())
|
||||
PyElementTree = xmlschema_etree.PyElementTree
|
||||
|
||||
xml_file = os.path.join(test_dir, 'test_cases/resources/with_entity.xml')
|
||||
elem = xmlschema_etree.ElementTree.parse(xml_file).getroot()
|
||||
self.assertEqual(elem.text, 'abc')
|
||||
self.assertRaises(
|
||||
PyElementTree.ParseError, xmlschema_etree.ElementTree.parse, xml_file, parser=parser
|
||||
)
|
||||
|
||||
xml_file = os.path.join(test_dir, 'test_cases/resources/unused_external_entity.xml')
|
||||
elem = xmlschema_etree.ElementTree.parse(xml_file).getroot()
|
||||
self.assertEqual(elem.text, 'abc')
|
||||
self.assertRaises(
|
||||
PyElementTree.ParseError, xmlschema_etree.ElementTree.parse, xml_file, parser=parser
|
||||
)
|
||||
|
||||
xml_file = os.path.join(test_dir, 'test_cases/resources/external_entity.xml')
|
||||
self.assertRaises(xmlschema_etree.ParseError, xmlschema_etree.ElementTree.parse, xml_file)
|
||||
self.assertRaises(
|
||||
PyElementTree.ParseError, xmlschema_etree.ElementTree.parse, xml_file, parser=parser
|
||||
)
|
||||
|
||||
|
||||
@unittest.skipIf(memory_profiler is None or sys.version_info[:2] != (3, 7), "Test only with Python 3.7")
|
||||
class TestMemoryUsage(unittest.TestCase):
|
||||
|
||||
@staticmethod
|
||||
def check_memory_profile(output):
|
||||
"""Check the output of a memory memory profile run on a function."""
|
||||
mem_usage = []
|
||||
func_num = 0
|
||||
for line in output.split('\n'):
|
||||
parts = line.split()
|
||||
if 'def' in parts:
|
||||
func_num += 1
|
||||
if not parts or not parts[0].isdigit() or len(parts) == 1 \
|
||||
or not parts[1].replace('.', '').isdigit():
|
||||
continue
|
||||
mem_usage.append(decimal.Decimal(parts[1]))
|
||||
|
||||
if func_num > 1:
|
||||
raise ValueError("Cannot the a memory profile output of more than one function!")
|
||||
return max(v - mem_usage[0] for v in mem_usage[1:])
|
||||
|
||||
@unittest.skip
|
||||
def test_package_memory_usage(self):
|
||||
test_dir = os.path.dirname(__file__) or '.'
|
||||
cmd = [os.path.join(test_dir, 'check_memory.py'), '1']
|
||||
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||
package_mem = self.check_memory_profile(output)
|
||||
self.assertLess(package_mem, 20)
|
||||
|
||||
def test_element_tree_memory_usage(self):
|
||||
test_dir = os.path.dirname(__file__) or '.'
|
||||
xsd10_schema_file = os.path.join(
|
||||
os.path.dirname(os.path.abspath(test_dir)), 'validators/schemas/XSD_1.0/XMLSchema.xsd'
|
||||
)
|
||||
|
||||
cmd = [os.path.join(test_dir, 'check_memory.py'), '2', xsd10_schema_file]
|
||||
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||
parse_mem = self.check_memory_profile(output)
|
||||
|
||||
cmd = [os.path.join(test_dir, 'check_memory.py'), '3', xsd10_schema_file]
|
||||
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||
iterparse_mem = self.check_memory_profile(output)
|
||||
|
||||
cmd = [os.path.join(test_dir, 'check_memory.py'), '4', xsd10_schema_file]
|
||||
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||
lazy_iterparse_mem = self.check_memory_profile(output)
|
||||
|
||||
self.assertLess(parse_mem, 2)
|
||||
self.assertLessEqual(lazy_iterparse_mem, parse_mem / 2)
|
||||
self.assertLessEqual(lazy_iterparse_mem, iterparse_mem)
|
||||
|
||||
def test_decode_memory_usage(self):
|
||||
test_dir = os.path.dirname(__file__) or '.'
|
||||
xsd10_schema_file = os.path.join(
|
||||
os.path.dirname(os.path.abspath(test_dir)), 'validators/schemas/XSD_1.0/XMLSchema.xsd'
|
||||
)
|
||||
|
||||
cmd = [os.path.join(test_dir, 'check_memory.py'), '5', xsd10_schema_file]
|
||||
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||
decode_mem = self.check_memory_profile(output)
|
||||
|
||||
cmd = [os.path.join(test_dir, 'check_memory.py'), '6', xsd10_schema_file]
|
||||
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||
lazy_decode_mem = self.check_memory_profile(output)
|
||||
|
||||
self.assertLess(decode_mem, 2)
|
||||
self.assertLessEqual(lazy_decode_mem, decode_mem / decimal.Decimal(1.5))
|
||||
|
||||
def test_validate_memory_usage(self):
|
||||
test_dir = os.path.dirname(__file__) or '.'
|
||||
xsd10_schema_file = os.path.join(
|
||||
os.path.dirname(os.path.abspath(test_dir)), 'validators/schemas/XSD_1.0/XMLSchema.xsd'
|
||||
)
|
||||
|
||||
cmd = [os.path.join(test_dir, 'check_memory.py'), '7', xsd10_schema_file]
|
||||
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||
validate_mem = self.check_memory_profile(output)
|
||||
|
||||
cmd = [os.path.join(test_dir, 'check_memory.py'), '8', xsd10_schema_file]
|
||||
output = subprocess.check_output(cmd, universal_newlines=True)
|
||||
lazy_validate_mem = self.check_memory_profile(output)
|
||||
|
||||
self.assertLess(validate_mem, 2)
|
||||
self.assertLessEqual(lazy_validate_mem, validate_mem / 2)
|
||||
|
||||
|
||||
@unittest.skipIf(platform.system() == 'Windows', "Skip packaging test on Windows platform.")
|
||||
class TestPackaging(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -14,7 +14,6 @@ This module runs tests concerning resources.
|
|||
"""
|
||||
import unittest
|
||||
import os
|
||||
import platform
|
||||
|
||||
try:
|
||||
from pathlib import PureWindowsPath, PurePath
|
||||
|
@ -25,9 +24,10 @@ from xmlschema import (
|
|||
fetch_namespaces, fetch_resource, normalize_url, fetch_schema, fetch_schema_locations,
|
||||
load_xml_resource, XMLResource, XMLSchemaURLError
|
||||
)
|
||||
from xmlschema.tests import XMLSchemaTestCase, SKIP_REMOTE_TESTS
|
||||
from xmlschema.tests import casepath
|
||||
from xmlschema.compat import urlopen, urlsplit, uses_relative, StringIO
|
||||
from xmlschema.etree import ElementTree, PyElementTree, lxml_etree, is_etree_element, etree_element, py_etree_element
|
||||
from xmlschema.etree import ElementTree, PyElementTree, lxml_etree, is_etree_element, \
|
||||
etree_element, py_etree_element
|
||||
|
||||
|
||||
def is_windows_path(path):
|
||||
|
@ -39,7 +39,17 @@ def add_leading_slash(path):
|
|||
return '/' + path if path and path[0] not in ('/', '\\') else path
|
||||
|
||||
|
||||
class TestResources(XMLSchemaTestCase):
|
||||
class TestResources(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.vh_dir = casepath('examples/vehicles')
|
||||
cls.vh_xsd_file = casepath('examples/vehicles/vehicles.xsd')
|
||||
cls.vh_xml_file = casepath('examples/vehicles/vehicles.xml')
|
||||
|
||||
cls.col_dir = casepath('examples/collection')
|
||||
cls.col_xsd_file = casepath('examples/collection/collection.xsd')
|
||||
cls.col_xml_file = casepath('examples/collection/collection.xml')
|
||||
|
||||
def check_url(self, url, expected):
|
||||
url_parts = urlsplit(url)
|
||||
|
@ -108,13 +118,13 @@ class TestResources(XMLSchemaTestCase):
|
|||
self.assertEqual(normalize_url('dir2/schema.xsd', '////root/dir1'), 'file:///root/dir1/dir2/schema.xsd')
|
||||
|
||||
def test_fetch_resource(self):
|
||||
wrong_path = self.casepath('resources/dummy_file.txt')
|
||||
wrong_path = casepath('resources/dummy_file.txt')
|
||||
self.assertRaises(XMLSchemaURLError, fetch_resource, wrong_path)
|
||||
right_path = self.casepath('resources/dummy file.txt')
|
||||
right_path = casepath('resources/dummy file.txt')
|
||||
self.assertTrue(fetch_resource(right_path).endswith('dummy file.txt'))
|
||||
|
||||
def test_fetch_namespaces(self):
|
||||
self.assertFalse(fetch_namespaces(self.casepath('resources/malformed.xml')))
|
||||
self.assertFalse(fetch_namespaces(casepath('resources/malformed.xml')))
|
||||
|
||||
def test_fetch_schema_locations(self):
|
||||
locations = fetch_schema_locations(self.col_xml_file)
|
||||
|
@ -282,15 +292,15 @@ class TestResources(XMLSchemaTestCase):
|
|||
resource = XMLResource(self.vh_xml_file, defuse='always')
|
||||
self.assertIsInstance(resource.root, py_etree_element)
|
||||
|
||||
xml_file = self.casepath('resources/with_entity.xml')
|
||||
xml_file = casepath('resources/with_entity.xml')
|
||||
self.assertIsInstance(XMLResource(xml_file), XMLResource)
|
||||
self.assertRaises(PyElementTree.ParseError, XMLResource, xml_file, defuse='always')
|
||||
|
||||
xml_file = self.casepath('resources/unused_external_entity.xml')
|
||||
xml_file = casepath('resources/unused_external_entity.xml')
|
||||
self.assertIsInstance(XMLResource(xml_file), XMLResource)
|
||||
self.assertRaises(PyElementTree.ParseError, XMLResource, xml_file, defuse='always')
|
||||
|
||||
xml_file = self.casepath('resources/external_entity.xml')
|
||||
xml_file = casepath('resources/external_entity.xml')
|
||||
self.assertIsInstance(XMLResource(xml_file), XMLResource)
|
||||
self.assertRaises(PyElementTree.ParseError, XMLResource, xml_file, defuse='always')
|
||||
|
||||
|
@ -367,22 +377,6 @@ class TestResources(XMLSchemaTestCase):
|
|||
self.assertEqual(len(locations), 2)
|
||||
self.check_url(locations[0][1], os.path.join(self.col_dir, 'other.xsd'))
|
||||
|
||||
@unittest.skipIf(SKIP_REMOTE_TESTS or platform.system() == 'Windows',
|
||||
"Remote networks are not accessible or avoid SSL verification error on Windows.")
|
||||
def test_remote_schemas_loading(self):
|
||||
col_schema = self.schema_class("https://raw.githubusercontent.com/brunato/xmlschema/master/"
|
||||
"xmlschema/tests/test_cases/examples/collection/collection.xsd")
|
||||
self.assertTrue(isinstance(col_schema, self.schema_class))
|
||||
vh_schema = self.schema_class("https://raw.githubusercontent.com/brunato/xmlschema/master/"
|
||||
"xmlschema/tests/test_cases/examples/vehicles/vehicles.xsd")
|
||||
self.assertTrue(isinstance(vh_schema, self.schema_class))
|
||||
|
||||
def test_schema_defuse(self):
|
||||
vh_schema = self.schema_class(self.vh_xsd_file, defuse='always')
|
||||
self.assertIsInstance(vh_schema.root, etree_element)
|
||||
for schema in vh_schema.maps.iter_schemas():
|
||||
self.assertIsInstance(schema.root, etree_element)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from xmlschema.tests import print_test_header
|
||||
|
|
|
@ -17,6 +17,7 @@ import unittest
|
|||
import pdb
|
||||
import os
|
||||
import pickle
|
||||
import platform
|
||||
import time
|
||||
import warnings
|
||||
|
||||
|
@ -26,12 +27,12 @@ from xmlschema import XMLSchemaBase, XMLSchemaParseError, XMLSchemaModelError, \
|
|||
from xmlschema.compat import PY3, unicode_type
|
||||
from xmlschema.etree import lxml_etree, etree_element, py_etree_element
|
||||
from xmlschema.qnames import XSD_LIST, XSD_UNION, XSD_ELEMENT, XSI_TYPE
|
||||
from xmlschema.tests import tests_factory, SchemaObserver, XMLSchemaTestCase
|
||||
from xmlschema.tests import SKIP_REMOTE_TESTS, tests_factory, SchemaObserver, XsdValidatorTestCase
|
||||
from xmlschema.validators import XsdValidator, XMLSchema11
|
||||
from xmlschema.xpath import ElementPathContext
|
||||
|
||||
|
||||
class TestXMLSchema10(XMLSchemaTestCase):
|
||||
class TestXMLSchema10(XsdValidatorTestCase):
|
||||
|
||||
def check_schema(self, source, expected=None, **kwargs):
|
||||
"""
|
||||
|
@ -43,9 +44,9 @@ class TestXMLSchema10(XMLSchemaTestCase):
|
|||
a substring test if it's not `None` (maybe a string). Then returns the schema instance.
|
||||
"""
|
||||
if isinstance(expected, type) and issubclass(expected, Exception):
|
||||
self.assertRaises(expected, self.schema_class, self.retrieve_schema_source(source), **kwargs)
|
||||
self.assertRaises(expected, self.schema_class, self.get_schema_source(source), **kwargs)
|
||||
else:
|
||||
schema = self.schema_class(self.retrieve_schema_source(source), **kwargs)
|
||||
schema = self.schema_class(self.get_schema_source(source), **kwargs)
|
||||
if callable(expected):
|
||||
self.assertTrue(expected(schema))
|
||||
return schema
|
||||
|
@ -53,16 +54,16 @@ class TestXMLSchema10(XMLSchemaTestCase):
|
|||
def check_complex_restriction(self, base, restriction, expected=None, **kwargs):
|
||||
content = 'complex' if self.content_pattern.search(base) else 'simple'
|
||||
source = """
|
||||
<complexType name="targetType">
|
||||
<xs:complexType name="targetType">
|
||||
{0}
|
||||
</complexType>
|
||||
<complexType name="restrictedType">
|
||||
<{1}Content>
|
||||
<restriction base="ns:targetType">
|
||||
</xs:complexType>
|
||||
<xs:complexType name="restrictedType">
|
||||
<xs:{1}Content>
|
||||
<xs:restriction base="targetType">
|
||||
{2}
|
||||
</restriction>
|
||||
</{1}Content>
|
||||
</complexType>
|
||||
</xs:restriction>
|
||||
</xs:{1}Content>
|
||||
</xs:complexType>
|
||||
""".format(base.strip(), content, restriction.strip())
|
||||
self.check_schema(source, expected, **kwargs)
|
||||
|
||||
|
@ -91,14 +92,14 @@ class TestXMLSchema10(XMLSchemaTestCase):
|
|||
def test_simple_types(self):
|
||||
# Issue #54: set list or union schema element.
|
||||
xs = self.check_schema("""
|
||||
<simpleType name="test_list">
|
||||
<annotation/>
|
||||
<list itemType="string"/>
|
||||
</simpleType>
|
||||
<simpleType name="test_union">
|
||||
<annotation/>
|
||||
<union memberTypes="string integer boolean"/>
|
||||
</simpleType>
|
||||
<xs:simpleType name="test_list">
|
||||
<xs:annotation/>
|
||||
<xs:list itemType="xs:string"/>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="test_union">
|
||||
<xs:annotation/>
|
||||
<xs:union memberTypes="xs:string xs:integer xs:boolean"/>
|
||||
</xs:simpleType>
|
||||
""")
|
||||
xs.types['test_list'].elem = xs.root[0] # elem.tag == 'simpleType'
|
||||
self.assertEqual(xs.types['test_list'].elem.tag, XSD_LIST)
|
||||
|
@ -110,12 +111,14 @@ class TestXMLSchema10(XMLSchemaTestCase):
|
|||
with warnings.catch_warnings(record=True) as context:
|
||||
warnings.simplefilter("always")
|
||||
self.check_schema("""
|
||||
<include schemaLocation="example.xsd" />
|
||||
<import schemaLocation="example.xsd" />
|
||||
<redefine schemaLocation="example.xsd"/>
|
||||
<import namespace="http://missing.example.test/" />
|
||||
<import/>
|
||||
""")
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="ns">
|
||||
<xs:include schemaLocation="example.xsd" />
|
||||
<xs:import schemaLocation="example.xsd" />
|
||||
<xs:redefine schemaLocation="example.xsd"/>
|
||||
<xs:import namespace="http://missing.example.test/" />
|
||||
<xs:import/>
|
||||
</xs:schema>
|
||||
""")
|
||||
self.assertEqual(len(context), 3, "Wrong number of include/import warnings")
|
||||
self.assertEqual(context[0].category, XMLSchemaIncludeWarning)
|
||||
self.assertEqual(context[1].category, XMLSchemaIncludeWarning)
|
||||
|
@ -127,293 +130,333 @@ class TestXMLSchema10(XMLSchemaTestCase):
|
|||
def test_wrong_references(self):
|
||||
# Wrong namespace for element type's reference
|
||||
self.check_schema("""
|
||||
<element name="dimension" type="dimensionType"/>
|
||||
<simpleType name="dimensionType">
|
||||
<restriction base="short"/>
|
||||
</simpleType>
|
||||
""", XMLSchemaParseError)
|
||||
<xs:element name="dimension" type="xs:dimensionType"/>
|
||||
<xs:simpleType name="dimensionType">
|
||||
<xs:restriction base="xs:short"/>
|
||||
</xs:simpleType>
|
||||
""", XMLSchemaParseError)
|
||||
|
||||
def test_restriction_has_annotation(self):
|
||||
# Wrong namespace for element type's reference
|
||||
schema = self.check_schema("""
|
||||
<simpleType name='Magic'>
|
||||
<annotation>
|
||||
<documentation> stuff </documentation>
|
||||
</annotation>
|
||||
<restriction base='string'>
|
||||
<enumeration value='A'/>
|
||||
</restriction>
|
||||
</simpleType>""")
|
||||
<xs:simpleType name='Magic'>
|
||||
<xs:annotation>
|
||||
<xs:documentation> stuff </xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:restriction base='xs:string'>
|
||||
<xs:enumeration value='A'/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>""")
|
||||
self.assertIsNotNone(schema.types["Magic"].annotation)
|
||||
|
||||
def test_facets(self):
|
||||
# Issue #55 and a near error (derivation from xs:integer)
|
||||
self.check_schema("""
|
||||
<simpleType name="dtype">
|
||||
<restriction base="decimal">
|
||||
<fractionDigits value="3" />
|
||||
<totalDigits value="20" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
<simpleType name="ntype">
|
||||
<restriction base="ns:dtype">
|
||||
<totalDigits value="3" />
|
||||
<fractionDigits value="1" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
""")
|
||||
<xs:simpleType name="dtype">
|
||||
<xs:restriction base="xs:decimal">
|
||||
<xs:fractionDigits value="3" />
|
||||
<xs:totalDigits value="20" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="ntype">
|
||||
<xs:restriction base="dtype">
|
||||
<xs:totalDigits value="3" />
|
||||
<xs:fractionDigits value="1" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
""")
|
||||
self.check_schema("""
|
||||
<simpleType name="dtype">
|
||||
<restriction base="integer">
|
||||
<fractionDigits value="3" /> <!-- <<< value must be 0 -->
|
||||
<totalDigits value="20" />
|
||||
</restriction>
|
||||
</simpleType>
|
||||
""", xmlschema.XMLSchemaParseError)
|
||||
<xs:simpleType name="dtype">
|
||||
<xs:restriction base="xs:integer">
|
||||
<xs:fractionDigits value="3" /> <!-- <<< value must be 0 -->
|
||||
<xs:totalDigits value="20" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
""", xmlschema.XMLSchemaParseError)
|
||||
|
||||
# Issue #56
|
||||
self.check_schema("""
|
||||
<simpleType name="mlengthparent">
|
||||
<restriction base="string">
|
||||
<maxLength value="200"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
<simpleType name="mlengthchild">
|
||||
<restriction base="ns:mlengthparent">
|
||||
<maxLength value="20"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
""")
|
||||
<xs:simpleType name="mlengthparent">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:maxLength value="200"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="mlengthchild">
|
||||
<xs:restriction base="mlengthparent">
|
||||
<xs:maxLength value="20"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
""")
|
||||
|
||||
def test_element_restrictions(self):
|
||||
base = """
|
||||
<sequence>
|
||||
<element name="A" maxOccurs="7"/>
|
||||
<element name="B" type="string"/>
|
||||
<element name="C" fixed="5"/>
|
||||
</sequence>
|
||||
<xs:sequence>
|
||||
<xs:element name="A" maxOccurs="7"/>
|
||||
<xs:element name="B" type="xs:string"/>
|
||||
<xs:element name="C" fixed="5"/>
|
||||
</xs:sequence>
|
||||
"""
|
||||
self.check_complex_restriction(
|
||||
base, restriction="""
|
||||
<sequence>
|
||||
<element name="A" maxOccurs="6"/>
|
||||
<element name="B" type="NCName"/>
|
||||
<element name="C" fixed="5"/>
|
||||
</sequence>
|
||||
""")
|
||||
|
||||
<xs:sequence>
|
||||
<xs:element name="A" maxOccurs="6"/>
|
||||
<xs:element name="B" type="xs:NCName"/>
|
||||
<xs:element name="C" fixed="5"/>
|
||||
</xs:sequence>
|
||||
"""
|
||||
)
|
||||
self.check_complex_restriction(
|
||||
base, restriction="""
|
||||
<sequence>
|
||||
<element name="A" maxOccurs="8"/> <!-- <<< More occurrences -->
|
||||
<element name="B" type="NCName"/>
|
||||
<element name="C" fixed="5"/>
|
||||
</sequence>
|
||||
""", expected=XMLSchemaParseError)
|
||||
|
||||
<xs:sequence>
|
||||
<xs:element name="A" maxOccurs="8"/> <!-- <<< More occurrences -->
|
||||
<xs:element name="B" type="xs:NCName"/>
|
||||
<xs:element name="C" fixed="5"/>
|
||||
</xs:sequence>
|
||||
""", expected=XMLSchemaParseError
|
||||
)
|
||||
self.check_complex_restriction(
|
||||
base, restriction="""
|
||||
<sequence>
|
||||
<element name="A" maxOccurs="6"/>
|
||||
<element name="B" type="float"/> <!-- <<< Not a derived type -->
|
||||
<element name="C" fixed="5"/>
|
||||
</sequence>
|
||||
""", expected=XMLSchemaParseError)
|
||||
|
||||
<xs:sequence>
|
||||
<xs:element name="A" maxOccurs="6"/>
|
||||
<xs:element name="B" type="float"/> <!-- <<< Not a derived type -->
|
||||
<xs:element name="C" fixed="5"/>
|
||||
</xs:sequence>
|
||||
""", expected=XMLSchemaParseError
|
||||
)
|
||||
self.check_complex_restriction(
|
||||
base, restriction="""
|
||||
<sequence>
|
||||
<element name="A" maxOccurs="6"/>
|
||||
<element name="B" type="NCName"/>
|
||||
<element name="C" fixed="3"/> <!-- <<< Different fixed value -->
|
||||
</sequence>
|
||||
""", expected=XMLSchemaParseError)
|
||||
|
||||
<xs:sequence>
|
||||
<xs:element name="A" maxOccurs="6"/>
|
||||
<xs:element name="B" type="xs:NCName"/>
|
||||
<xs:element name="C" fixed="3"/> <!-- <<< Different fixed value -->
|
||||
</xs:sequence>
|
||||
""", expected=XMLSchemaParseError
|
||||
)
|
||||
self.check_complex_restriction(
|
||||
base, restriction="""
|
||||
<sequence>
|
||||
<element name="A" maxOccurs="6" nillable="true"/> <!-- <<< nillable is True -->
|
||||
<element name="B" type="NCName"/>
|
||||
<element name="C" fixed="5"/>
|
||||
</sequence>
|
||||
""", expected=XMLSchemaParseError)
|
||||
<xs:sequence>
|
||||
<xs:element name="A" maxOccurs="6" nillable="true"/> <!-- <<< nillable is True -->
|
||||
<xs:element name="B" type="xs:NCName"/>
|
||||
<xs:element name="C" fixed="5"/>
|
||||
</xs:sequence>
|
||||
""", expected=XMLSchemaParseError
|
||||
)
|
||||
|
||||
def test_sequence_group_restriction(self):
|
||||
# Meaningless sequence group
|
||||
base = """
|
||||
<sequence>
|
||||
<sequence>
|
||||
<element name="A"/>
|
||||
<element name="B"/>
|
||||
</sequence>
|
||||
</sequence>
|
||||
<xs:sequence>
|
||||
<xs:sequence>
|
||||
<xs:element name="A"/>
|
||||
<xs:element name="B"/>
|
||||
</xs:sequence>
|
||||
</xs:sequence>
|
||||
"""
|
||||
self.check_complex_restriction(
|
||||
base, '<sequence><element name="A"/><element name="B"/></sequence>'
|
||||
base, restriction="""
|
||||
<xs:sequence>
|
||||
<xs:element name="A"/>
|
||||
<xs:element name="B"/>
|
||||
</xs:sequence>
|
||||
"""
|
||||
)
|
||||
self.check_complex_restriction(
|
||||
base, '<sequence><element name="A"/><element name="C"/></sequence>', XMLSchemaParseError
|
||||
base, restriction="""
|
||||
<xs:sequence>
|
||||
<xs:element name="A"/>
|
||||
<xs:element name="C"/>
|
||||
</xs:sequence>
|
||||
""", expected=XMLSchemaParseError
|
||||
)
|
||||
|
||||
base = """
|
||||
<sequence>
|
||||
<element name="A"/>
|
||||
<element name="B" minOccurs="0"/>
|
||||
</sequence>
|
||||
<xs:sequence>
|
||||
<xs:element name="A"/>
|
||||
<xs:element name="B" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
"""
|
||||
self.check_complex_restriction(base, '<sequence><element name="A"/></sequence>')
|
||||
self.check_complex_restriction(base, '<sequence><element name="B"/></sequence>', XMLSchemaParseError)
|
||||
self.check_complex_restriction(base, '<sequence><element name="C"/></sequence>', XMLSchemaParseError)
|
||||
self.check_complex_restriction(base, '<xs:sequence><xs:element name="A"/></xs:sequence>')
|
||||
self.check_complex_restriction(
|
||||
base, '<sequence><element name="A"/><element name="B"/></sequence>'
|
||||
base, '<xs:sequence><xs:element name="B"/></xs:sequence>', XMLSchemaParseError
|
||||
)
|
||||
self.check_complex_restriction(
|
||||
base, '<sequence><element name="A"/><element name="C"/></sequence>', XMLSchemaParseError
|
||||
base, '<xs:sequence><xs:element name="C"/></xs:sequence>', XMLSchemaParseError
|
||||
)
|
||||
self.check_complex_restriction(
|
||||
base, '<sequence><element name="A" minOccurs="0"/><element name="B"/></sequence>',
|
||||
base, '<xs:sequence><xs:element name="A"/><xs:element name="B"/></xs:sequence>'
|
||||
)
|
||||
self.check_complex_restriction(
|
||||
base, '<xs:sequence><xs:element name="A"/><xs:element name="C"/></xs:sequence>', XMLSchemaParseError
|
||||
)
|
||||
self.check_complex_restriction(
|
||||
base, '<xs:sequence><xs:element name="A" minOccurs="0"/><xs:element name="B"/></xs:sequence>',
|
||||
XMLSchemaParseError
|
||||
)
|
||||
self.check_complex_restriction(
|
||||
base, '<sequence><element name="B" minOccurs="0"/><element name="A"/></sequence>',
|
||||
base, '<xs:sequence><xs:element name="B" minOccurs="0"/><xs:element name="A"/></xs:sequence>',
|
||||
XMLSchemaParseError
|
||||
)
|
||||
|
||||
def test_all_group_restriction(self):
|
||||
base = """
|
||||
<all>
|
||||
<element name="A"/>
|
||||
<element name="B" minOccurs="0"/>
|
||||
<element name="C" minOccurs="0"/>
|
||||
</all>
|
||||
<xs:all>
|
||||
<xs:element name="A"/>
|
||||
<xs:element name="B" minOccurs="0"/>
|
||||
<xs:element name="C" minOccurs="0"/>
|
||||
</xs:all>
|
||||
"""
|
||||
self.check_complex_restriction(base, '<all><element name="A"/><element name="C"/></all>')
|
||||
self.check_complex_restriction(
|
||||
base, '<all><element name="C" minOccurs="0"/><element name="A"/></all>', XMLSchemaParseError
|
||||
base, restriction="""
|
||||
<xs:all>
|
||||
<xs:element name="A"/>
|
||||
<xs:element name="C"/>
|
||||
</xs:all>
|
||||
""")
|
||||
self.check_complex_restriction(
|
||||
base, restriction="""
|
||||
<xs:all>
|
||||
<xs:element name="C" minOccurs="0"/>
|
||||
<xs:element name="A"/>
|
||||
</xs:all>
|
||||
""", expected=XMLSchemaParseError
|
||||
)
|
||||
self.check_complex_restriction(
|
||||
base, '<sequence><element name="A"/><element name="C"/></sequence>'
|
||||
base, restriction="""
|
||||
<xs:sequence>
|
||||
<xs:element name="A"/>
|
||||
<xs:element name="C"/>
|
||||
</xs:sequence>
|
||||
""")
|
||||
self.check_complex_restriction(
|
||||
base, '<xs:sequence><xs:element name="C" minOccurs="0"/><xs:element name="A"/></xs:sequence>',
|
||||
)
|
||||
self.check_complex_restriction(
|
||||
base, '<sequence><element name="C" minOccurs="0"/><element name="A"/></sequence>',
|
||||
base, restriction="""
|
||||
<xs:sequence>
|
||||
<xs:element name="C" minOccurs="0"/>
|
||||
<xs:element name="A" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
""", expected=XMLSchemaParseError
|
||||
)
|
||||
self.check_complex_restriction(
|
||||
base, '<sequence><element name="C" minOccurs="0"/><element name="A" minOccurs="0"/></sequence>',
|
||||
XMLSchemaParseError
|
||||
)
|
||||
self.check_complex_restriction(
|
||||
base, '<sequence><element name="A"/><element name="X"/></sequence>', XMLSchemaParseError
|
||||
base, restriction="""
|
||||
<xs:sequence>
|
||||
<xs:element name="A"/>
|
||||
<xs:element name="X"/>
|
||||
</xs:sequence>
|
||||
""", expected=XMLSchemaParseError
|
||||
)
|
||||
|
||||
base = """
|
||||
<all>
|
||||
<element name="A" minOccurs="0" maxOccurs="0"/>
|
||||
</all>
|
||||
<xs:all>
|
||||
<xs:element name="A" minOccurs="0" maxOccurs="0"/>
|
||||
</xs:all>
|
||||
"""
|
||||
self.check_complex_restriction(base, '<all><element name="A"/></all>', XMLSchemaParseError)
|
||||
self.check_complex_restriction(base, '<xs:all><xs:element name="A"/></xs:all>', XMLSchemaParseError)
|
||||
|
||||
def test_choice_group_restriction(self):
|
||||
base = """
|
||||
<choice maxOccurs="2">
|
||||
<element name="A"/>
|
||||
<element name="B"/>
|
||||
<element name="C"/>
|
||||
</choice>
|
||||
<xs:choice maxOccurs="2">
|
||||
<xs:element name="A"/>
|
||||
<xs:element name="B"/>
|
||||
<xs:element name="C"/>
|
||||
</xs:choice>
|
||||
"""
|
||||
self.check_complex_restriction(base, '<choice><element name="A"/><element name="C"/></choice>')
|
||||
self.check_complex_restriction(base, '<xs:choice><xs:element name="A"/><xs:element name="C"/></xs:choice>')
|
||||
self.check_complex_restriction(
|
||||
base, '<choice maxOccurs="2"><element name="C"/><element name="A"/></choice>',
|
||||
base, '<xs:choice maxOccurs="2"><xs:element name="C"/><xs:element name="A"/></xs:choice>',
|
||||
XMLSchemaParseError
|
||||
)
|
||||
|
||||
self.check_complex_restriction(
|
||||
base, '<choice maxOccurs="2"><element name="A"/><element name="C"/></choice>',
|
||||
base, '<xs:choice maxOccurs="2"><xs:element name="A"/><xs:element name="C"/></xs:choice>',
|
||||
)
|
||||
|
||||
def test_occurs_restriction(self):
|
||||
base = """
|
||||
<sequence minOccurs="3" maxOccurs="10">
|
||||
<element name="A"/>
|
||||
</sequence>
|
||||
<xs:sequence minOccurs="3" maxOccurs="10">
|
||||
<xs:element name="A"/>
|
||||
</xs:sequence>
|
||||
"""
|
||||
self.check_complex_restriction(
|
||||
base, '<sequence minOccurs="3" maxOccurs="7"><element name="A"/></sequence>')
|
||||
base, '<xs:sequence minOccurs="3" maxOccurs="7"><xs:element name="A"/></xs:sequence>')
|
||||
self.check_complex_restriction(
|
||||
base, '<sequence minOccurs="4" maxOccurs="10"><element name="A"/></sequence>')
|
||||
base, '<xs:sequence minOccurs="4" maxOccurs="10"><xs:element name="A"/></xs:sequence>')
|
||||
self.check_complex_restriction(
|
||||
base, '<sequence minOccurs="3" maxOccurs="11"><element name="A"/></sequence>',
|
||||
base, '<xs:sequence minOccurs="3" maxOccurs="11"><xs:element name="A"/></xs:sequence>',
|
||||
XMLSchemaParseError
|
||||
)
|
||||
self.check_complex_restriction(
|
||||
base, '<sequence minOccurs="2" maxOccurs="10"><element name="A"/></sequence>',
|
||||
base, '<xs:sequence minOccurs="2" maxOccurs="10"><xs:element name="A"/></xs:sequence>',
|
||||
XMLSchemaParseError
|
||||
)
|
||||
|
||||
def test_union_restrictions(self):
|
||||
# Wrong union restriction (not admitted facets, see issue #67)
|
||||
self.check_schema(r"""
|
||||
<simpleType name="Percentage">
|
||||
<restriction base="ns:Integer">
|
||||
<minInclusive value="0"/>
|
||||
<maxInclusive value="100"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
<simpleType name="Integer">
|
||||
<union memberTypes="int ns:IntegerString"/>
|
||||
</simpleType>
|
||||
<simpleType name="IntegerString">
|
||||
<restriction base="string">
|
||||
<pattern value="-?[0-9]+(\.[0-9]+)?%"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
""", XMLSchemaParseError)
|
||||
<xs:simpleType name="Percentage">
|
||||
<xs:restriction base="Integer">
|
||||
<xs:minInclusive value="0"/>
|
||||
<xs:maxInclusive value="100"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="Integer">
|
||||
<xs:union memberTypes="xs:int IntegerString"/>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name="IntegerString">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:pattern value="-?[0-9]+(\.[0-9]+)?%"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
""", XMLSchemaParseError)
|
||||
|
||||
def test_final_attribute(self):
|
||||
self.check_schema("""
|
||||
<simpleType name="aType" final="list restriction">
|
||||
<restriction base="string"/>
|
||||
</simpleType>
|
||||
""")
|
||||
<xs:simpleType name="aType" final="list restriction">
|
||||
<xs:restriction base="xs:string"/>
|
||||
</xs:simpleType>
|
||||
""")
|
||||
|
||||
def test_wrong_attribute(self):
|
||||
self.check_schema("""
|
||||
<attributeGroup name="alpha">
|
||||
<attribute name="name" type="string"/>
|
||||
<attribute ref="phone"/> <!-- Missing "phone" attribute -->
|
||||
</attributeGroup>
|
||||
""", XMLSchemaParseError)
|
||||
<xs:attributeGroup name="alpha">
|
||||
<xs:attribute name="name" type="xs:string"/>
|
||||
<xs:attribute ref="phone"/> <!-- Missing "phone" attribute -->
|
||||
</xs:attributeGroup>
|
||||
""", XMLSchemaParseError)
|
||||
|
||||
def test_wrong_attribute_group(self):
|
||||
self.check_schema("""
|
||||
<attributeGroup name="alpha">
|
||||
<attribute name="name" type="string"/>
|
||||
<attributeGroup ref="beta"/> <!-- Missing "beta" attribute group -->
|
||||
</attributeGroup>
|
||||
""", XMLSchemaParseError)
|
||||
<xs:attributeGroup name="alpha">
|
||||
<xs:attribute name="name" type="xs:string"/>
|
||||
<xs:attributeGroup ref="beta"/> <!-- Missing "beta" attribute group -->
|
||||
</xs:attributeGroup>
|
||||
""", XMLSchemaParseError)
|
||||
|
||||
schema = self.check_schema("""
|
||||
<attributeGroup name="alpha">
|
||||
<attribute name="name" type="string"/>
|
||||
<attributeGroup name="beta"/> <!-- attribute "name" instead of "ref" -->
|
||||
</attributeGroup>
|
||||
<xs:attributeGroup name="alpha">
|
||||
<xs:attribute name="name" type="xs:string"/>
|
||||
<xs:attributeGroup name="beta"/> <!-- attribute "name" instead of "ref" -->
|
||||
</xs:attributeGroup>
|
||||
""", validation='lax')
|
||||
self.assertTrue(isinstance(schema.all_errors[1], XMLSchemaParseError))
|
||||
|
||||
def test_date_time_facets(self):
|
||||
self.check_schema("""
|
||||
<simpleType name="restricted_date">
|
||||
<restriction base="date">
|
||||
<minInclusive value="1900-01-01"/>
|
||||
<maxInclusive value="2030-12-31"/>
|
||||
</restriction>
|
||||
</simpleType>""")
|
||||
<xs:simpleType name="restricted_date">
|
||||
<xs:restriction base="xs:date">
|
||||
<xs:minInclusive value="1900-01-01"/>
|
||||
<xs:maxInclusive value="2030-12-31"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>""")
|
||||
|
||||
self.check_schema("""
|
||||
<simpleType name="restricted_year">
|
||||
<restriction base="gYear">
|
||||
<minInclusive value="1900"/>
|
||||
<maxInclusive value="2030"/>
|
||||
</restriction>
|
||||
</simpleType>""")
|
||||
<xs:simpleType name="restricted_year">
|
||||
<xs:restriction base="xs:gYear">
|
||||
<xs:minInclusive value="1900"/>
|
||||
<xs:maxInclusive value="2030"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>""")
|
||||
|
||||
def test_base_schemas(self):
|
||||
from xmlschema.validators.schema import XML_SCHEMA_FILE
|
||||
|
@ -433,26 +476,26 @@ class TestXMLSchema10(XMLSchemaTestCase):
|
|||
|
||||
def test_upa_violations(self):
|
||||
self.check_schema("""
|
||||
<complexType name="typeA">
|
||||
<sequence>
|
||||
<sequence minOccurs="0" maxOccurs="unbounded">
|
||||
<element name="A"/>
|
||||
<element name="B"/>
|
||||
</sequence>
|
||||
<element name="A" minOccurs="0"/>
|
||||
</sequence>
|
||||
</complexType>""", XMLSchemaModelError)
|
||||
<xs:complexType name="typeA">
|
||||
<xs:sequence>
|
||||
<xs:sequence minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="A"/>
|
||||
<xs:element name="B"/>
|
||||
</xs:sequence>
|
||||
<xs:element name="A" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>""", XMLSchemaModelError)
|
||||
|
||||
self.check_schema("""
|
||||
<complexType name="typeA">
|
||||
<sequence>
|
||||
<sequence minOccurs="0" maxOccurs="unbounded">
|
||||
<element name="B"/>
|
||||
<element name="A"/>
|
||||
</sequence>
|
||||
<element name="A" minOccurs="0"/>
|
||||
</sequence>
|
||||
</complexType>""")
|
||||
<xs:complexType name="typeA">
|
||||
<xs:sequence>
|
||||
<xs:sequence minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="B"/>
|
||||
<xs:element name="A"/>
|
||||
</xs:sequence>
|
||||
<xs:element name="A" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>""")
|
||||
|
||||
def test_root_elements(self):
|
||||
# Test issue #107 fix
|
||||
|
@ -471,10 +514,26 @@ class TestXMLSchema10(XMLSchemaTestCase):
|
|||
|
||||
def test_is_restriction_method(self):
|
||||
# Test issue #111 fix
|
||||
schema = self.schema_class(source=os.path.join(self.test_cases_dir, 'issues/issue_111/issue_111.xsd'))
|
||||
schema = self.schema_class(source=self.casepath('issues/issue_111/issue_111.xsd'))
|
||||
extended_header_def = schema.types['extendedHeaderDef']
|
||||
self.assertTrue(extended_header_def.is_derived(schema.types['blockDef']))
|
||||
|
||||
@unittest.skipIf(SKIP_REMOTE_TESTS or platform.system() == 'Windows',
|
||||
"Remote networks are not accessible or avoid SSL verification error on Windows.")
|
||||
def test_remote_schemas_loading(self):
|
||||
col_schema = self.schema_class("https://raw.githubusercontent.com/brunato/xmlschema/master/"
|
||||
"xmlschema/tests/test_cases/examples/collection/collection.xsd")
|
||||
self.assertTrue(isinstance(col_schema, self.schema_class))
|
||||
vh_schema = self.schema_class("https://raw.githubusercontent.com/brunato/xmlschema/master/"
|
||||
"xmlschema/tests/test_cases/examples/vehicles/vehicles.xsd")
|
||||
self.assertTrue(isinstance(vh_schema, self.schema_class))
|
||||
|
||||
def test_schema_defuse(self):
|
||||
vh_schema = self.schema_class(self.vh_xsd_file, defuse='always')
|
||||
self.assertIsInstance(vh_schema.root, etree_element)
|
||||
for schema in vh_schema.maps.iter_schemas():
|
||||
self.assertIsInstance(schema.root, etree_element)
|
||||
|
||||
|
||||
class TestXMLSchema11(TestXMLSchema10):
|
||||
|
||||
|
@ -482,21 +541,21 @@ class TestXMLSchema11(TestXMLSchema10):
|
|||
|
||||
def test_explicit_timezone_facet(self):
|
||||
schema = self.check_schema("""
|
||||
<simpleType name='opt-tz-date'>
|
||||
<restriction base='date'>
|
||||
<explicitTimezone value='optional'/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
<simpleType name='req-tz-date'>
|
||||
<restriction base='date'>
|
||||
<explicitTimezone value='required'/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
<simpleType name='no-tz-date'>
|
||||
<restriction base='date'>
|
||||
<explicitTimezone value='prohibited'/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
<xs:simpleType name='opt-tz-date'>
|
||||
<xs:restriction base='xs:date'>
|
||||
<xs:explicitTimezone value='optional'/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name='req-tz-date'>
|
||||
<xs:restriction base='xs:date'>
|
||||
<xs:explicitTimezone value='required'/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:simpleType name='no-tz-date'>
|
||||
<xs:restriction base='xs:date'>
|
||||
<xs:explicitTimezone value='prohibited'/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
""")
|
||||
self.assertTrue(schema.types['req-tz-date'].is_valid('2002-10-10-05:00'))
|
||||
self.assertTrue(schema.types['req-tz-date'].is_valid('2002-10-10Z'))
|
||||
|
@ -504,42 +563,43 @@ class TestXMLSchema11(TestXMLSchema10):
|
|||
|
||||
def test_assertion_facet(self):
|
||||
self.check_schema("""
|
||||
<simpleType name='DimensionType'>
|
||||
<restriction base='integer'>
|
||||
<assertion test='string-length($value) < 2'/>
|
||||
</restriction>
|
||||
</simpleType>""", XMLSchemaParseError)
|
||||
<xs:simpleType name='DimensionType'>
|
||||
<xs:restriction base='xs:integer'>
|
||||
<xs:assertion test='string-length($value) < 2'/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>""", XMLSchemaParseError)
|
||||
|
||||
schema = self.check_schema("""
|
||||
<simpleType name='MeasureType'>
|
||||
<restriction base='integer'>
|
||||
<assertion test='$value > 0'/>
|
||||
</restriction>
|
||||
</simpleType>""")
|
||||
<xs:simpleType name='MeasureType'>
|
||||
<xs:restriction base='xs:integer'>
|
||||
<xs:assertion test='$value > 0'/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>""")
|
||||
self.assertTrue(schema.types['MeasureType'].is_valid('10'))
|
||||
self.assertFalse(schema.types['MeasureType'].is_valid('-1.5'))
|
||||
|
||||
self.check_schema("""
|
||||
<simpleType name='RestrictedDateTimeType'>
|
||||
<restriction base='dateTime'>
|
||||
<assertion test="$value > '1999-12-31T23:59:59'"/>
|
||||
</restriction>
|
||||
</simpleType>""", XMLSchemaParseError)
|
||||
<xs:simpleType name='RestrictedDateTimeType'>
|
||||
<xs:restriction base='xs:dateTime'>
|
||||
<xs:assertion test="$value > '1999-12-31T23:59:59'"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>""", XMLSchemaParseError)
|
||||
|
||||
schema = self.check_schema("""
|
||||
<simpleType name='RestrictedDateTimeType'>
|
||||
<restriction base='dateTime'>
|
||||
<assertion test="$value > xs:dateTime('1999-12-31T23:59:59')"/>
|
||||
</restriction>
|
||||
</simpleType>""")
|
||||
<xs:simpleType name='RestrictedDateTimeType'>
|
||||
<xs:restriction base='xs:dateTime'>
|
||||
<xs:assertion test="$value > xs:dateTime('1999-12-31T23:59:59')"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>""")
|
||||
self.assertTrue(schema.types['RestrictedDateTimeType'].is_valid('2000-01-01T12:00:00'))
|
||||
|
||||
schema = self.check_schema("""<simpleType name="Percentage">
|
||||
<restriction base="integer">
|
||||
<assertion test="$value >= 0"/>
|
||||
<assertion test="$value <= 100"/>
|
||||
</restriction>
|
||||
</simpleType>""")
|
||||
schema = self.check_schema("""
|
||||
<xs:simpleType name="Percentage">
|
||||
<xs:restriction base="xs:integer">
|
||||
<xs:assertion test="$value >= 0"/>
|
||||
<xs:assertion test="$value <= 100"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>""")
|
||||
self.assertTrue(schema.types['Percentage'].is_valid('10'))
|
||||
self.assertTrue(schema.types['Percentage'].is_valid('100'))
|
||||
self.assertTrue(schema.types['Percentage'].is_valid('0'))
|
||||
|
@ -549,11 +609,11 @@ class TestXMLSchema11(TestXMLSchema10):
|
|||
|
||||
def test_complex_type_assertion(self):
|
||||
schema = self.check_schema("""
|
||||
<complexType name="intRange">
|
||||
<attribute name="min" type="int"/>
|
||||
<attribute name="max" type="int"/>
|
||||
<assert test="@min le @max"/>
|
||||
</complexType>""")
|
||||
<xs:complexType name="intRange">
|
||||
<xs:attribute name="min" type="xs:int"/>
|
||||
<xs:attribute name="max" type="xs:int"/>
|
||||
<xs:assert test="@min le @max"/>
|
||||
</xs:complexType>""")
|
||||
|
||||
xsd_type = schema.types['intRange']
|
||||
xsd_type.decode(etree_element('a', attrib={'min': '10', 'max': '19'}))
|
||||
|
@ -564,20 +624,20 @@ class TestXMLSchema11(TestXMLSchema10):
|
|||
|
||||
def test_open_content(self):
|
||||
self.check_schema("""
|
||||
<element name="Book">
|
||||
<complexType>
|
||||
<openContent mode="interleave">
|
||||
<any />
|
||||
</openContent>
|
||||
<sequence>
|
||||
<element name="Title" type="string"/>
|
||||
<element name="Author" type="string" />
|
||||
<element name="Date" type="gYear"/>
|
||||
<element name="ISBN" type="string"/>
|
||||
<element name="Publisher" type="string"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
</element>""")
|
||||
<xs:element name="Book">
|
||||
<xs:complexType>
|
||||
<xs:openContent mode="interleave">
|
||||
<xs:any />
|
||||
</xs:openContent>
|
||||
<xs:sequence>
|
||||
<xs:element name="Title" type="xs:string"/>
|
||||
<xs:element name="Author" type="xs:string" />
|
||||
<xs:element name="Date" type="xs:gYear"/>
|
||||
<xs:element name="ISBN" type="xs:string"/>
|
||||
<xs:element name="Publisher" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>""")
|
||||
|
||||
|
||||
def make_schema_test_class(test_file, test_args, test_num, schema_class, check_with_lxml):
|
||||
|
@ -601,7 +661,7 @@ def make_schema_test_class(test_file, test_args, test_num, schema_class, check_w
|
|||
defuse = test_args.defuse
|
||||
debug_mode = test_args.debug
|
||||
|
||||
class TestSchema(XMLSchemaTestCase):
|
||||
class TestSchema(XsdValidatorTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
|
|
@ -33,7 +33,7 @@ from xmlschema.etree import etree_element, etree_tostring, is_etree_element, Ele
|
|||
from xmlschema.helpers import local_name
|
||||
from xmlschema.qnames import XSI_TYPE
|
||||
from xmlschema.resources import fetch_namespaces
|
||||
from xmlschema.tests import XMLSchemaTestCase, tests_factory
|
||||
from xmlschema.tests import XsdValidatorTestCase, tests_factory
|
||||
from xmlschema.validators import XMLSchema11
|
||||
|
||||
_VEHICLES_DICT = {
|
||||
|
@ -305,7 +305,7 @@ def make_validator_test_class(test_file, test_args, test_num, schema_class, chec
|
|||
skip_strict = test_args.skip
|
||||
debug_mode = test_args.debug
|
||||
|
||||
class TestValidator(XMLSchemaTestCase):
|
||||
class TestValidator(XsdValidatorTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
@ -567,7 +567,7 @@ def make_validator_test_class(test_file, test_args, test_num, schema_class, chec
|
|||
return TestValidator
|
||||
|
||||
|
||||
class TestValidation(XMLSchemaTestCase):
|
||||
class TestValidation(XsdValidatorTestCase):
|
||||
|
||||
def check_validity(self, xsd_component, data, expected, use_defaults=True):
|
||||
if isinstance(expected, type) and issubclass(expected, Exception):
|
||||
|
@ -641,7 +641,7 @@ class TestValidation11(TestValidation):
|
|||
"</tree>"))
|
||||
|
||||
|
||||
class TestDecoding(XMLSchemaTestCase):
|
||||
class TestDecoding(XsdValidatorTestCase):
|
||||
|
||||
def check_decode(self, xsd_component, data, expected, **kwargs):
|
||||
if isinstance(expected, type) and issubclass(expected, Exception):
|
||||
|
@ -751,20 +751,20 @@ class TestDecoding(XMLSchemaTestCase):
|
|||
self.assertEqual(xd, _DATA_DICT)
|
||||
|
||||
def test_datetime_types(self):
|
||||
xs = self.get_schema('<element name="dt" type="dateTime"/>')
|
||||
self.assertEqual(xs.decode('<ns:dt xmlns:ns="ns">2019-01-01T13:40:00</ns:dt>'), '2019-01-01T13:40:00')
|
||||
self.assertEqual(xs.decode('<ns:dt xmlns:ns="ns">2019-01-01T13:40:00</ns:dt>', datetime_types=True),
|
||||
xs = self.get_schema('<xs:element name="dt" type="xs:dateTime"/>')
|
||||
self.assertEqual(xs.decode('<dt>2019-01-01T13:40:00</dt>'), '2019-01-01T13:40:00')
|
||||
self.assertEqual(xs.decode('<dt>2019-01-01T13:40:00</dt>', datetime_types=True),
|
||||
datatypes.DateTime10.fromstring('2019-01-01T13:40:00'))
|
||||
|
||||
xs = self.get_schema('<element name="dt" type="date"/>')
|
||||
self.assertEqual(xs.decode('<ns:dt xmlns:ns="ns">2001-04-15</ns:dt>'), '2001-04-15')
|
||||
self.assertEqual(xs.decode('<ns:dt xmlns:ns="ns">2001-04-15</ns:dt>', datetime_types=True),
|
||||
xs = self.get_schema('<xs:element name="dt" type="xs:date"/>')
|
||||
self.assertEqual(xs.decode('<dt>2001-04-15</dt>'), '2001-04-15')
|
||||
self.assertEqual(xs.decode('<dt>2001-04-15</dt>', datetime_types=True),
|
||||
datatypes.Date10.fromstring('2001-04-15'))
|
||||
|
||||
def test_duration_type(self):
|
||||
xs = self.get_schema('<element name="td" type="duration"/>')
|
||||
self.assertEqual(xs.decode('<ns:td xmlns:ns="ns">P5Y3MT60H30.001S</ns:td>'), 'P5Y3MT60H30.001S')
|
||||
self.assertEqual(xs.decode('<ns:td xmlns:ns="ns">P5Y3MT60H30.001S</ns:td>', datetime_types=True),
|
||||
xs = self.get_schema('<xs:element name="td" type="xs:duration"/>')
|
||||
self.assertEqual(xs.decode('<td>P5Y3MT60H30.001S</td>'), 'P5Y3MT60H30.001S')
|
||||
self.assertEqual(xs.decode('<td>P5Y3MT60H30.001S</td>', datetime_types=True),
|
||||
datatypes.Duration.fromstring('P5Y3M2DT12H30.001S'))
|
||||
|
||||
def test_default_converter(self):
|
||||
|
@ -874,20 +874,20 @@ class TestDecoding(XMLSchemaTestCase):
|
|||
|
||||
def test_decimal_type(self):
|
||||
schema = self.get_schema("""
|
||||
<element name="A" type="ns:A_type" />
|
||||
<simpleType name="A_type">
|
||||
<restriction base="decimal">
|
||||
<minInclusive value="100.50"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
<xs:element name="A" type="A_type" />
|
||||
<xs:simpleType name="A_type">
|
||||
<xs:restriction base="xs:decimal">
|
||||
<xs:minInclusive value="100.50"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
""")
|
||||
|
||||
self.check_decode(schema, '<A xmlns="ns">120.48</A>', Decimal('120.48'))
|
||||
self.check_decode(schema, '<A xmlns="ns">100.50</A>', Decimal('100.50'), process_namespaces=False)
|
||||
self.check_decode(schema, '<A xmlns="ns">100.49</A>', XMLSchemaValidationError)
|
||||
self.check_decode(schema, '<A xmlns="ns">120.48</A>', 120.48, decimal_type=float)
|
||||
self.check_decode(schema, '<A>120.48</A>', Decimal('120.48'))
|
||||
self.check_decode(schema, '<A>100.50</A>', Decimal('100.50'), process_namespaces=False)
|
||||
self.check_decode(schema, '<A>100.49</A>', XMLSchemaValidationError)
|
||||
self.check_decode(schema, '<A>120.48</A>', 120.48, decimal_type=float)
|
||||
# Issue #66
|
||||
self.check_decode(schema, '<A xmlns="ns">120.48</A>', '120.48', decimal_type=str)
|
||||
self.check_decode(schema, '<A>120.48</A>', '120.48', decimal_type=str)
|
||||
|
||||
def test_nillable(self):
|
||||
# Issue #76
|
||||
|
@ -1002,7 +1002,7 @@ class TestDecoding(XMLSchemaTestCase):
|
|||
{'@int_attr': 'wrong', '$': 20})
|
||||
|
||||
def test_error_message(self):
|
||||
schema = self.schema_class(os.path.join(self.test_cases_dir, 'issues/issue_115/Rotation.xsd'))
|
||||
schema = self.schema_class(self.casepath('issues/issue_115/Rotation.xsd'))
|
||||
rotation_data = '<tns:rotation xmlns:tns="http://www.example.org/Rotation/" ' \
|
||||
'pitch="0.0" roll="0.0" yaw="-1.0" />'
|
||||
|
||||
|
@ -1022,26 +1022,26 @@ class TestDecoding11(TestDecoding):
|
|||
schema_class = XMLSchema11
|
||||
|
||||
def test_datetime_types(self):
|
||||
xs = self.get_schema('<element name="dt" type="dateTime"/>')
|
||||
self.assertEqual(xs.decode('<ns:dt xmlns:ns="ns">2019-01-01T13:40:00</ns:dt>'), '2019-01-01T13:40:00')
|
||||
self.assertEqual(xs.decode('<ns:dt xmlns:ns="ns">2019-01-01T13:40:00</ns:dt>', datetime_types=True),
|
||||
xs = self.get_schema('<xs:element name="dt" type="xs:dateTime"/>')
|
||||
self.assertEqual(xs.decode('<dt>2019-01-01T13:40:00</dt>'), '2019-01-01T13:40:00')
|
||||
self.assertEqual(xs.decode('<dt>2019-01-01T13:40:00</dt>', datetime_types=True),
|
||||
datatypes.DateTime.fromstring('2019-01-01T13:40:00'))
|
||||
|
||||
xs = self.get_schema('<element name="dt" type="date"/>')
|
||||
self.assertEqual(xs.decode('<ns:dt xmlns:ns="ns">2001-04-15</ns:dt>'), '2001-04-15')
|
||||
self.assertEqual(xs.decode('<ns:dt xmlns:ns="ns">2001-04-15</ns:dt>', datetime_types=True),
|
||||
xs = self.get_schema('<xs:element name="dt" type="xs:date"/>')
|
||||
self.assertEqual(xs.decode('<dt>2001-04-15</dt>'), '2001-04-15')
|
||||
self.assertEqual(xs.decode('<dt>2001-04-15</dt>', datetime_types=True),
|
||||
datatypes.Date.fromstring('2001-04-15'))
|
||||
|
||||
def test_derived_duration_types(self):
|
||||
xs = self.get_schema('<element name="td" type="yearMonthDuration"/>')
|
||||
self.assertEqual(xs.decode('<ns:td xmlns:ns="ns">P0Y4M</ns:td>'), 'P0Y4M')
|
||||
self.assertEqual(xs.decode('<ns:td xmlns:ns="ns">P2Y10M</ns:td>', datetime_types=True),
|
||||
xs = self.get_schema('<xs:element name="td" type="xs:yearMonthDuration"/>')
|
||||
self.assertEqual(xs.decode('<td>P0Y4M</td>'), 'P0Y4M')
|
||||
self.assertEqual(xs.decode('<td>P2Y10M</td>', datetime_types=True),
|
||||
datatypes.Duration.fromstring('P2Y10M'))
|
||||
|
||||
xs = self.get_schema('<element name="td" type="dayTimeDuration"/>')
|
||||
self.assertEqual(xs.decode('<ns:td xmlns:ns="ns">P2DT6H30M30.001S</ns:td>'), 'P2DT6H30M30.001S')
|
||||
self.assertEqual(xs.decode('<ns:td xmlns:ns="ns">P2DT26H</ns:td>'), 'P2DT26H')
|
||||
self.assertEqual(xs.decode('<ns:td xmlns:ns="ns">P2DT6H30M30.001S</ns:td>', datetime_types=True),
|
||||
xs = self.get_schema('<xs:element name="td" type="xs:dayTimeDuration"/>')
|
||||
self.assertEqual(xs.decode('<td>P2DT6H30M30.001S</td>'), 'P2DT6H30M30.001S')
|
||||
self.assertEqual(xs.decode('<td>P2DT26H</td>'), 'P2DT26H')
|
||||
self.assertEqual(xs.decode('<td>P2DT6H30M30.001S</td>', datetime_types=True),
|
||||
datatypes.Duration.fromstring('P2DT6H30M30.001S'))
|
||||
|
||||
def test_type_alternatives(self):
|
||||
|
@ -1064,7 +1064,7 @@ class TestDecoding11(TestDecoding):
|
|||
self.assertTrue(xs.is_valid('<ns:value xmlns:ns="ns" choice="bool">true</ns:value>'))
|
||||
|
||||
|
||||
class TestEncoding(XMLSchemaTestCase):
|
||||
class TestEncoding(XsdValidatorTestCase):
|
||||
|
||||
def check_encode(self, xsd_component, data, expected, **kwargs):
|
||||
if isinstance(expected, type) and issubclass(expected, Exception):
|
||||
|
@ -1191,77 +1191,77 @@ class TestEncoding(XMLSchemaTestCase):
|
|||
self.check_encode(boolean_or_integer_or_string, "Venice ", u'Venice ')
|
||||
|
||||
def test_simple_elements(self):
|
||||
elem = etree_element('{ns}A')
|
||||
elem = etree_element('A')
|
||||
elem.text = '89'
|
||||
self.check_encode(self.get_element('A', type='string'), '89', elem)
|
||||
self.check_encode(self.get_element('A', type='integer'), 89, elem)
|
||||
self.check_encode(self.get_element('A', type='xs:string'), '89', elem)
|
||||
self.check_encode(self.get_element('A', type='xs:integer'), 89, elem)
|
||||
elem.text = '-10.4'
|
||||
self.check_encode(self.get_element('A', type='float'), -10.4, elem)
|
||||
self.check_encode(self.get_element('A', type='xs:float'), -10.4, elem)
|
||||
elem.text = 'false'
|
||||
self.check_encode(self.get_element('A', type='boolean'), False, elem)
|
||||
self.check_encode(self.get_element('A', type='xs:boolean'), False, elem)
|
||||
elem.text = 'true'
|
||||
self.check_encode(self.get_element('A', type='boolean'), True, elem)
|
||||
self.check_encode(self.get_element('A', type='xs:boolean'), True, elem)
|
||||
|
||||
self.check_encode(self.get_element('A', type='short'), 128000, XMLSchemaValidationError)
|
||||
self.check_encode(self.get_element('A', type='xs:short'), 128000, XMLSchemaValidationError)
|
||||
elem.text = '0'
|
||||
self.check_encode(self.get_element('A', type='nonNegativeInteger'), 0, elem)
|
||||
self.check_encode(self.get_element('A', type='nonNegativeInteger'), '0', XMLSchemaValidationError)
|
||||
self.check_encode(self.get_element('A', type='positiveInteger'), 0, XMLSchemaValidationError)
|
||||
self.check_encode(self.get_element('A', type='xs:nonNegativeInteger'), 0, elem)
|
||||
self.check_encode(self.get_element('A', type='xs:nonNegativeInteger'), '0', XMLSchemaValidationError)
|
||||
self.check_encode(self.get_element('A', type='xs:positiveInteger'), 0, XMLSchemaValidationError)
|
||||
elem.text = '-1'
|
||||
self.check_encode(self.get_element('A', type='negativeInteger'), -1, elem)
|
||||
self.check_encode(self.get_element('A', type='nonNegativeInteger'), -1, XMLSchemaValidationError)
|
||||
self.check_encode(self.get_element('A', type='xs:negativeInteger'), -1, elem)
|
||||
self.check_encode(self.get_element('A', type='xs:nonNegativeInteger'), -1, XMLSchemaValidationError)
|
||||
|
||||
def test_complex_elements(self):
|
||||
schema = self.get_schema("""
|
||||
<element name="A" type="ns:A_type" />
|
||||
<complexType name="A_type" mixed="true">
|
||||
<simpleContent>
|
||||
<extension base="string">
|
||||
<attribute name="a1" type="short" use="required"/>
|
||||
<attribute name="a2" type="negativeInteger"/>
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
<xs:element name="A" type="A_type" />
|
||||
<xs:complexType name="A_type" mixed="true">
|
||||
<xs:simpleContent>
|
||||
<xs:extension base="xs:string">
|
||||
<xs:attribute name="a1" type="xs:short" use="required"/>
|
||||
<xs:attribute name="a2" type="xs:negativeInteger"/>
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
""")
|
||||
self.check_encode(
|
||||
schema.elements['A'], data={'@a1': 10, '@a2': -1, '$': 'simple '},
|
||||
expected='<ns:A xmlns:ns="ns" a1="10" a2="-1">simple </ns:A>',
|
||||
expected='<A a1="10" a2="-1">simple </A>',
|
||||
)
|
||||
self.check_encode(
|
||||
schema.elements['A'], {'@a1': 10, '@a2': -1, '$': 'simple '},
|
||||
ElementTree.fromstring('<A xmlns="ns" a1="10" a2="-1">simple </A>'),
|
||||
ElementTree.fromstring('<A a1="10" a2="-1">simple </A>'),
|
||||
)
|
||||
self.check_encode(
|
||||
schema.elements['A'], {'@a1': 10, '@a2': -1},
|
||||
ElementTree.fromstring('<A xmlns="ns" a1="10" a2="-1"/>')
|
||||
ElementTree.fromstring('<A a1="10" a2="-1"/>')
|
||||
)
|
||||
self.check_encode(
|
||||
schema.elements['A'], {'@a1': 10, '$': 'simple '},
|
||||
ElementTree.fromstring('<A xmlns="ns" a1="10">simple </A>')
|
||||
ElementTree.fromstring('<A a1="10">simple </A>')
|
||||
)
|
||||
self.check_encode(schema.elements['A'], {'@a2': -1, '$': 'simple '}, XMLSchemaValidationError)
|
||||
|
||||
schema = self.get_schema("""
|
||||
<element name="A" type="ns:A_type" />
|
||||
<complexType name="A_type">
|
||||
<sequence>
|
||||
<element name="B1" type="string"/>
|
||||
<element name="B2" type="integer"/>
|
||||
<element name="B3" type="boolean"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
<xs:element name="A" type="A_type" />
|
||||
<xs:complexType name="A_type">
|
||||
<xs:sequence>
|
||||
<xs:element name="B1" type="xs:string"/>
|
||||
<xs:element name="B2" type="xs:integer"/>
|
||||
<xs:element name="B3" type="xs:boolean"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
""")
|
||||
self.check_encode(
|
||||
xsd_component=schema.elements['A'],
|
||||
data=ordered_dict_class([('B1', 'abc'), ('B2', 10), ('B3', False)]),
|
||||
expected=u'<ns:A xmlns:ns="ns">\n<B1>abc</B1>\n<B2>10</B2>\n<B3>false</B3>\n</ns:A>',
|
||||
expected=u'<A>\n<B1>abc</B1>\n<B2>10</B2>\n<B3>false</B3>\n</A>',
|
||||
indent=0,
|
||||
)
|
||||
self.check_encode(schema.elements['A'], {'B1': 'abc', 'B2': 10, 'B4': False}, XMLSchemaValidationError)
|
||||
self.check_encode(
|
||||
xsd_component=schema.elements['A'],
|
||||
data=ordered_dict_class([('B1', 'abc'), ('B2', 10), ('#1', 'hello'), ('B3', True)]),
|
||||
expected=u'<ns:A xmlns:ns="ns">\n<B1>abc</B1>\n<B2>10</B2>\nhello\n<B3>true</B3>\n</ns:A>',
|
||||
expected=u'<A>\n<B1>abc</B1>\n<B2>10</B2>\nhello\n<B3>true</B3>\n</A>',
|
||||
indent=0, cdata_prefix='#'
|
||||
)
|
||||
self.check_encode(
|
||||
|
@ -1271,48 +1271,32 @@ class TestEncoding(XMLSchemaTestCase):
|
|||
)
|
||||
|
||||
def test_encode_datetime(self):
|
||||
xs = self.get_schema('<element name="dt" type="dateTime"/>')
|
||||
|
||||
dt = xs.decode('<ns:dt xmlns:ns="ns">2019-01-01T13:40:00</ns:dt>', datetime_types=True)
|
||||
self.assertEqual(
|
||||
etree_tostring(xs.encode(dt)),
|
||||
'<ns:dt xmlns:ns="ns">2019-01-01T13:40:00</ns:dt>'
|
||||
)
|
||||
xs = self.get_schema('<xs:element name="dt" type="xs:dateTime"/>')
|
||||
dt = xs.decode('<dt>2019-01-01T13:40:00</dt>', datetime_types=True)
|
||||
self.assertEqual(etree_tostring(xs.encode(dt)), '<dt>2019-01-01T13:40:00</dt>')
|
||||
|
||||
def test_encode_date(self):
|
||||
xs = self.get_schema('<element name="dt" type="date"/>')
|
||||
date = xs.decode('<ns:dt xmlns:ns="ns">2001-04-15</ns:dt>', datetime_types=True)
|
||||
self.assertEqual(
|
||||
etree_tostring(xs.encode(date)),
|
||||
'<ns:dt xmlns:ns="ns">2001-04-15</ns:dt>'
|
||||
)
|
||||
xs = self.get_schema('<xs:element name="dt" type="xs:date"/>')
|
||||
date = xs.decode('<dt>2001-04-15</dt>', datetime_types=True)
|
||||
self.assertEqual(etree_tostring(xs.encode(date)), '<dt>2001-04-15</dt>')
|
||||
|
||||
def test_duration(self):
|
||||
xs = self.get_schema('<element name="td" type="duration"/>')
|
||||
duration = xs.decode('<ns:td xmlns:ns="ns">P5Y3MT60H30.001S</ns:td>', datetime_types=True)
|
||||
self.assertEqual(
|
||||
etree_tostring(xs.encode(duration)),
|
||||
'<ns:td xmlns:ns="ns">P5Y3M2DT12H30.001S</ns:td>'
|
||||
)
|
||||
xs = self.get_schema('<xs:element name="td" type="xs:duration"/>')
|
||||
duration = xs.decode('<td>P5Y3MT60H30.001S</td>', datetime_types=True)
|
||||
self.assertEqual(etree_tostring(xs.encode(duration)), '<td>P5Y3M2DT12H30.001S</td>')
|
||||
|
||||
def test_gregorian_year(self):
|
||||
xs = self.get_schema('<element name="td" type="gYear"/>')
|
||||
gyear = xs.decode('<ns:td xmlns:ns="ns">2000</ns:td>', datetime_types=True)
|
||||
self.assertEqual(
|
||||
etree_tostring(xs.encode(gyear)),
|
||||
'<ns:td xmlns:ns="ns">2000</ns:td>'
|
||||
)
|
||||
xs = self.get_schema('<xs:element name="td" type="xs:gYear"/>')
|
||||
gyear = xs.decode('<td>2000</td>', datetime_types=True)
|
||||
self.assertEqual(etree_tostring(xs.encode(gyear)), '<td>2000</td>')
|
||||
|
||||
def test_gregorian_yearmonth(self):
|
||||
xs = self.get_schema('<element name="td" type="gYearMonth"/>')
|
||||
gyear_month = xs.decode('<ns:td xmlns:ns="ns">2000-12</ns:td>', datetime_types=True)
|
||||
self.assertEqual(
|
||||
etree_tostring(xs.encode(gyear_month)),
|
||||
'<ns:td xmlns:ns="ns">2000-12</ns:td>'
|
||||
)
|
||||
xs = self.get_schema('<xs:element name="td" type="xs:gYearMonth"/>')
|
||||
gyear_month = xs.decode('<td>2000-12</td>', datetime_types=True)
|
||||
self.assertEqual(etree_tostring(xs.encode(gyear_month)), '<td>2000-12</td>')
|
||||
|
||||
def test_error_message(self):
|
||||
schema = self.schema_class(os.path.join(self.test_cases_dir, 'issues/issue_115/Rotation.xsd'))
|
||||
schema = self.schema_class(self.casepath('issues/issue_115/Rotation.xsd'))
|
||||
rotation_data = {
|
||||
"@roll": 0.0,
|
||||
"@pitch": 0.0,
|
||||
|
|
|
@ -18,15 +18,15 @@ import xml.etree.ElementTree as ElementTree
|
|||
from elementpath import XPath1Parser, Selector, ElementPathSyntaxError
|
||||
|
||||
from xmlschema import XMLSchema
|
||||
from xmlschema.tests import XMLSchemaTestCase
|
||||
from xmlschema.tests import casepath
|
||||
|
||||
|
||||
class XsdXPathTest(XMLSchemaTestCase):
|
||||
class XsdXPathTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.xs1 = XMLSchema(cls.casepath("examples/vehicles/vehicles.xsd"))
|
||||
cls.xs2 = XMLSchema(cls.casepath("examples/collection/collection.xsd"))
|
||||
cls.xs1 = XMLSchema(casepath("examples/vehicles/vehicles.xsd"))
|
||||
cls.xs2 = XMLSchema(casepath("examples/collection/collection.xsd"))
|
||||
cls.cars = cls.xs1.elements['vehicles'].type.content_type[0]
|
||||
cls.bikes = cls.xs1.elements['vehicles'].type.content_type[1]
|
||||
|
||||
|
|
Loading…
Reference in New Issue