Add logging for schema initialization and building
- Add loglevel argument to schema init - Fallback location (for XLink and XHTML) moved at the end of import tentatives (full fix for issue #137) - Fix TestGlobalMaps after the remove of XLink from base schemas
This commit is contained in:
parent
433970cf72
commit
690a172502
|
@ -164,8 +164,6 @@ Resource access API
|
|||
.. autofunction:: xmlschema.normalize_url
|
||||
|
||||
|
||||
|
||||
|
||||
XSD components API
|
||||
------------------
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import pdb
|
|||
import os
|
||||
import pickle
|
||||
import time
|
||||
import logging
|
||||
import warnings
|
||||
|
||||
from xmlschema import XMLSchemaBase
|
||||
|
@ -46,6 +47,7 @@ def make_schema_test_class(test_file, test_args, test_num, schema_class, check_w
|
|||
locations = test_args.locations
|
||||
defuse = test_args.defuse
|
||||
debug_mode = test_args.debug
|
||||
loglevel = logging.DEBUG if debug_mode else None
|
||||
|
||||
class TestSchema(XsdValidatorTestCase):
|
||||
|
||||
|
@ -61,9 +63,10 @@ def make_schema_test_class(test_file, test_args, test_num, schema_class, check_w
|
|||
|
||||
def check_xsd_file(self):
|
||||
if expected_errors > 0:
|
||||
xs = schema_class(xsd_file, validation='lax', locations=locations, defuse=defuse)
|
||||
xs = schema_class(xsd_file, validation='lax', locations=locations,
|
||||
defuse=defuse, loglevel=loglevel)
|
||||
else:
|
||||
xs = schema_class(xsd_file, locations=locations, defuse=defuse)
|
||||
xs = schema_class(xsd_file, locations=locations, defuse=defuse, loglevel=loglevel)
|
||||
self.errors.extend(xs.maps.all_errors)
|
||||
|
||||
if inspect:
|
||||
|
|
|
@ -281,33 +281,33 @@ class TestGlobalMaps(unittest.TestCase):
|
|||
|
||||
def test_xsd_10_globals(self):
|
||||
self.assertEqual(len(XMLSchema10.meta_schema.maps.notations), 2)
|
||||
self.assertEqual(len(XMLSchema10.meta_schema.maps.types), 108)
|
||||
self.assertEqual(len(XMLSchema10.meta_schema.maps.attributes), 18)
|
||||
self.assertEqual(len(XMLSchema10.meta_schema.maps.attribute_groups), 9)
|
||||
self.assertEqual(len(XMLSchema10.meta_schema.maps.groups), 18)
|
||||
self.assertEqual(len(XMLSchema10.meta_schema.maps.elements), 45)
|
||||
self.assertEqual(len([e.is_global() for e in XMLSchema10.meta_schema.maps.iter_globals()]), 200)
|
||||
self.assertEqual(len(XMLSchema10.meta_schema.maps.types), 92)
|
||||
self.assertEqual(len(XMLSchema10.meta_schema.maps.attributes), 8)
|
||||
self.assertEqual(len(XMLSchema10.meta_schema.maps.attribute_groups), 3)
|
||||
self.assertEqual(len(XMLSchema10.meta_schema.maps.groups), 12)
|
||||
self.assertEqual(len(XMLSchema10.meta_schema.maps.elements), 41)
|
||||
self.assertEqual(len([e.is_global() for e in XMLSchema10.meta_schema.maps.iter_globals()]), 158)
|
||||
self.assertEqual(len(XMLSchema10.meta_schema.maps.substitution_groups), 0)
|
||||
|
||||
def test_xsd_11_globals(self):
|
||||
self.assertEqual(len(XMLSchema11.meta_schema.maps.notations), 2)
|
||||
self.assertEqual(len(XMLSchema11.meta_schema.maps.types), 119)
|
||||
self.assertEqual(len(XMLSchema11.meta_schema.maps.attributes), 24)
|
||||
self.assertEqual(len(XMLSchema11.meta_schema.maps.attribute_groups), 10)
|
||||
self.assertEqual(len(XMLSchema11.meta_schema.maps.groups), 19)
|
||||
self.assertEqual(len(XMLSchema11.meta_schema.maps.elements), 51)
|
||||
self.assertEqual(len([e.is_global() for e in XMLSchema11.meta_schema.maps.iter_globals()]), 225)
|
||||
self.assertEqual(len(XMLSchema11.meta_schema.maps.types), 103)
|
||||
self.assertEqual(len(XMLSchema11.meta_schema.maps.attributes), 14)
|
||||
self.assertEqual(len(XMLSchema11.meta_schema.maps.attribute_groups), 4)
|
||||
self.assertEqual(len(XMLSchema11.meta_schema.maps.groups), 13)
|
||||
self.assertEqual(len(XMLSchema11.meta_schema.maps.elements), 47)
|
||||
self.assertEqual(len([e.is_global() for e in XMLSchema11.meta_schema.maps.iter_globals()]), 183)
|
||||
self.assertEqual(len(XMLSchema11.meta_schema.maps.substitution_groups), 1)
|
||||
|
||||
def test_xsd_10_build(self):
|
||||
self.assertEqual(len([e for e in XMLSchema10.meta_schema.maps.iter_globals()]), 200)
|
||||
self.assertEqual(len([e for e in XMLSchema10.meta_schema.maps.iter_globals()]), 158)
|
||||
self.assertTrue(XMLSchema10.meta_schema.maps.built)
|
||||
XMLSchema10.meta_schema.maps.clear()
|
||||
XMLSchema10.meta_schema.maps.build()
|
||||
self.assertTrue(XMLSchema10.meta_schema.maps.built)
|
||||
|
||||
def test_xsd_11_build(self):
|
||||
self.assertEqual(len([e for e in XMLSchema11.meta_schema.maps.iter_globals()]), 225)
|
||||
self.assertEqual(len([e for e in XMLSchema11.meta_schema.maps.iter_globals()]), 183)
|
||||
self.assertTrue(XMLSchema11.meta_schema.maps.built)
|
||||
XMLSchema11.meta_schema.maps.clear()
|
||||
XMLSchema11.meta_schema.maps.build()
|
||||
|
@ -321,8 +321,8 @@ class TestGlobalMaps(unittest.TestCase):
|
|||
total_counter += 1
|
||||
if c.is_global():
|
||||
global_counter += 1
|
||||
self.assertEqual(global_counter, 200)
|
||||
self.assertEqual(total_counter, 901)
|
||||
self.assertEqual(global_counter, 158)
|
||||
self.assertEqual(total_counter, 782)
|
||||
|
||||
def test_xsd_11_components(self):
|
||||
total_counter = 0
|
||||
|
@ -332,8 +332,8 @@ class TestGlobalMaps(unittest.TestCase):
|
|||
total_counter += 1
|
||||
if c.is_global():
|
||||
global_counter += 1
|
||||
self.assertEqual(global_counter, 225)
|
||||
self.assertEqual(total_counter, 1051)
|
||||
self.assertEqual(global_counter, 183)
|
||||
self.assertEqual(total_counter, 932)
|
||||
|
||||
def test_xsd_11_restrictions(self):
|
||||
all_model_type = XMLSchema11.meta_schema.types['all']
|
||||
|
|
|
@ -55,6 +55,9 @@ from .wildcards import XsdAnyElement, XsdAnyAttribute, Xsd11AnyElement, \
|
|||
Xsd11AnyAttribute, XsdDefaultOpenContent
|
||||
from .globals_ import XsdGlobals
|
||||
|
||||
logger = logging.getLogger('xmlschema')
|
||||
logging.basicConfig(format='[%(levelname)s] %(message)s')
|
||||
|
||||
XSD_VERSION_PATTERN = re.compile(r'^\d+\.\d+$')
|
||||
|
||||
# Elements for building dummy groups
|
||||
|
@ -172,6 +175,9 @@ class XMLSchemaBase(XsdValidator, ValidationMixin, ElementPathMixin):
|
|||
meta-schema is added at the end. In the latter case the meta-schema is rebuilt if any base \
|
||||
namespace has been overridden by an import. Ignored if the argument *global_maps* is provided.
|
||||
:type use_meta: bool
|
||||
:param loglevel: for setting a different logging level for schema initialization \
|
||||
and building. For default is WARNING (30).
|
||||
:type loglevel: int
|
||||
|
||||
:cvar XSD_VERSION: store the XSD version (1.0 or 1.1).
|
||||
:vartype XSD_VERSION: str
|
||||
|
@ -258,10 +264,18 @@ class XMLSchemaBase(XsdValidator, ValidationMixin, ElementPathMixin):
|
|||
default_open_content = None
|
||||
override = None
|
||||
|
||||
def __init__(self, source, namespace=None, validation='strict', global_maps=None, converter=None,
|
||||
locations=None, base_url=None, defuse='remote', timeout=300, build=True, use_meta=True):
|
||||
def __init__(self, source, namespace=None, validation='strict', global_maps=None,
|
||||
converter=None, locations=None, base_url=None, defuse='remote',
|
||||
timeout=300, build=True, use_meta=True, loglevel=None):
|
||||
super(XMLSchemaBase, self).__init__(validation)
|
||||
if loglevel is not None:
|
||||
logger.setLevel(loglevel)
|
||||
elif build and global_maps is None:
|
||||
logger.setLevel(logging.WARNING)
|
||||
|
||||
self.source = XMLResource(source, base_url, defuse, timeout, lazy=False)
|
||||
logger.debug("Read schema from %r", self.source)
|
||||
|
||||
self.imports = {}
|
||||
self.includes = {}
|
||||
self.warnings = []
|
||||
|
@ -291,6 +305,9 @@ class XMLSchemaBase(XsdValidator, ValidationMixin, ElementPathMixin):
|
|||
if '' not in self.namespaces:
|
||||
self.namespaces[''] = namespace
|
||||
|
||||
logger.debug("Schema targetNamespace is %r", self.target_namespace)
|
||||
logger.debug("Declared namespaces: %r", self.namespaces)
|
||||
|
||||
# Parses the schema defaults
|
||||
if 'attributeFormDefault' in root.attrib:
|
||||
try:
|
||||
|
@ -321,11 +338,7 @@ class XMLSchemaBase(XsdValidator, ValidationMixin, ElementPathMixin):
|
|||
except ValueError as err:
|
||||
self.parse_error(err, root)
|
||||
|
||||
# Set locations hints
|
||||
self.locations = NamespaceResourcesMap(self.source.get_locations(locations))
|
||||
if self.meta_schema is not None:
|
||||
self.locations.update(self.FALLBACK_LOCATIONS)
|
||||
|
||||
self.converter = self.get_converter(converter)
|
||||
self.xpath_proxy = XMLSchemaProxy(self)
|
||||
self.empty_attribute_group = self.BUILDERS.attribute_group_class(
|
||||
|
@ -396,8 +409,12 @@ class XMLSchemaBase(XsdValidator, ValidationMixin, ElementPathMixin):
|
|||
self.default_open_content = XsdDefaultOpenContent(child, self)
|
||||
break
|
||||
|
||||
if build:
|
||||
self.maps.build()
|
||||
try:
|
||||
if build:
|
||||
self.maps.build()
|
||||
finally:
|
||||
if loglevel is not None:
|
||||
logger.setLevel(logging.WARNING) # Restore default logging
|
||||
|
||||
def __repr__(self):
|
||||
if self.url:
|
||||
|
@ -829,7 +846,9 @@ class XMLSchemaBase(XsdValidator, ValidationMixin, ElementPathMixin):
|
|||
"""Processes schema document inclusions and redefinitions."""
|
||||
for child in filter(lambda x: x.tag == XSD_INCLUDE, self.root):
|
||||
try:
|
||||
self.include_schema(child.attrib['schemaLocation'], self.base_url)
|
||||
location = child.attrib['schemaLocation'].strip()
|
||||
logger.info("Include schema from %r", location)
|
||||
self.include_schema(location, self.base_url)
|
||||
except KeyError:
|
||||
pass
|
||||
except (OSError, IOError) as err:
|
||||
|
@ -850,7 +869,9 @@ class XMLSchemaBase(XsdValidator, ValidationMixin, ElementPathMixin):
|
|||
|
||||
for child in filter(lambda x: x.tag == XSD_REDEFINE, self.root):
|
||||
try:
|
||||
schema = self.include_schema(child.attrib['schemaLocation'], self.base_url)
|
||||
location = child.attrib['schemaLocation'].strip()
|
||||
logger.info("Redefine schema %r", location)
|
||||
schema = self.include_schema(location, self.base_url)
|
||||
except KeyError:
|
||||
pass # Attribute missing error already found by validation against meta-schema
|
||||
except (OSError, IOError) as err:
|
||||
|
@ -940,13 +961,18 @@ class XMLSchemaBase(XsdValidator, ValidationMixin, ElementPathMixin):
|
|||
if local_hints:
|
||||
locations = local_hints + locations
|
||||
|
||||
if namespace in self.FALLBACK_LOCATIONS:
|
||||
locations.append(self.FALLBACK_LOCATIONS[namespace])
|
||||
|
||||
import_error = None
|
||||
for url in locations:
|
||||
try:
|
||||
logger.debug("Import namespace %r from %r", namespace, url)
|
||||
self.import_schema(namespace, url, self.base_url)
|
||||
except (OSError, IOError) as err:
|
||||
# It's not an error if the location access fails (ref. section 4.2.6.2):
|
||||
# https://www.w3.org/TR/2012/REC-xmlschema11-1-20120405/#composition-schemaImport
|
||||
logger.debug('%s', err)
|
||||
if import_error is None:
|
||||
import_error = err
|
||||
except (XMLSchemaURLError, XMLSchemaParseError, XMLSchemaTypeError, ParseError) as err:
|
||||
|
@ -963,6 +989,7 @@ class XMLSchemaBase(XsdValidator, ValidationMixin, ElementPathMixin):
|
|||
except XMLSchemaValueError as err:
|
||||
self.parse_error(err)
|
||||
else:
|
||||
logger.info("Namespace %r imported from %r", namespace, url)
|
||||
break
|
||||
else:
|
||||
if import_error is not None:
|
||||
|
@ -1505,7 +1532,9 @@ class XMLSchema11(XMLSchemaBase):
|
|||
|
||||
for child in filter(lambda x: x.tag == XSD_OVERRIDE, self.root):
|
||||
try:
|
||||
schema = self.include_schema(child.attrib['schemaLocation'], self.base_url)
|
||||
location = child.attrib['schemaLocation'].strip()
|
||||
logger.info("Override schema %r", location)
|
||||
schema = self.include_schema(location, self.base_url)
|
||||
except KeyError:
|
||||
pass # Attribute missing error already found by validation against meta-schema
|
||||
except (OSError, IOError) as err:
|
||||
|
|
Loading…
Reference in New Issue