Update test requirements
- Now uses xmlschema~=1.0.14 - Update fn:in-scope-prefixes() - Remove module xpath_helpers.py
This commit is contained in:
parent
22d9f4258d
commit
de6955b36c
|
@ -257,7 +257,11 @@ def select(self, context=None):
|
||||||
xsd_type = self.match_xsd_type(item, name)
|
xsd_type = self.match_xsd_type(item, name)
|
||||||
if xsd_type is not None:
|
if xsd_type is not None:
|
||||||
primitive_type = self.parser.schema.get_primitive_type(xsd_type)
|
primitive_type = self.parser.schema.get_primitive_type(xsd_type)
|
||||||
value = XSD_BUILTIN_TYPES[primitive_type.local_name].value
|
try:
|
||||||
|
value = XSD_BUILTIN_TYPES[primitive_type.local_name or 'anyType'].value
|
||||||
|
except KeyError:
|
||||||
|
value = XSD_BUILTIN_TYPES['anyType'].value
|
||||||
|
|
||||||
if isinstance(item, AttributeNode):
|
if isinstance(item, AttributeNode):
|
||||||
yield TypedAttribute(item, value)
|
yield TypedAttribute(item, value)
|
||||||
else:
|
else:
|
||||||
|
@ -676,7 +680,6 @@ def select(self, context=None):
|
||||||
yield result
|
yield result
|
||||||
else:
|
else:
|
||||||
items = []
|
items = []
|
||||||
context2 = context.copy()
|
|
||||||
left_results = list(self[0].select(context))
|
left_results = list(self[0].select(context))
|
||||||
context.size = len(left_results)
|
context.size = len(left_results)
|
||||||
for context.position, context.item in enumerate(left_results):
|
for context.position, context.item in enumerate(left_results):
|
||||||
|
@ -749,7 +752,10 @@ def led(self, left):
|
||||||
|
|
||||||
@method('[')
|
@method('[')
|
||||||
def select(self, context=None):
|
def select(self, context=None):
|
||||||
if context is not None:
|
if isinstance(context, XPathSchemaContext):
|
||||||
|
for item in self[0].select(context):
|
||||||
|
yield item
|
||||||
|
elif context is not None:
|
||||||
for position, item in enumerate(self[0].select(context), start=1):
|
for position, item in enumerate(self[0].select(context), start=1):
|
||||||
predicate = list(self[1].select(context.copy()))
|
predicate = list(self[1].select(context.copy()))
|
||||||
if len(predicate) == 1 and isinstance(predicate[0], NumericTypeProxy):
|
if len(predicate) == 1 and isinstance(predicate[0], NumericTypeProxy):
|
||||||
|
@ -825,14 +831,20 @@ def select(self, context=None):
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
||||||
for elem in context.iter_parent(axis=self.symbol):
|
for parent in context.iter_parent(axis=self.symbol):
|
||||||
follows = False
|
if isinstance(context, XPathSchemaContext):
|
||||||
for child in context.iter_children_or_self(elem, child_axis=True):
|
for _ in context.iter_children_or_self(parent, child_axis=True):
|
||||||
if follows:
|
|
||||||
for result in self[0].select(context):
|
for result in self[0].select(context):
|
||||||
yield result
|
yield result
|
||||||
elif item is child:
|
|
||||||
follows = True
|
else:
|
||||||
|
follows = False
|
||||||
|
for child in context.iter_children_or_self(parent, child_axis=True):
|
||||||
|
if follows:
|
||||||
|
for result in self[0].select(context):
|
||||||
|
yield result
|
||||||
|
elif item is child:
|
||||||
|
follows = True
|
||||||
|
|
||||||
|
|
||||||
@method(axis('following'))
|
@method(axis('following'))
|
||||||
|
|
|
@ -19,6 +19,7 @@ import time
|
||||||
import re
|
import re
|
||||||
import locale
|
import locale
|
||||||
import unicodedata
|
import unicodedata
|
||||||
|
import xml.etree.ElementTree as ElementTree
|
||||||
|
|
||||||
from .compat import PY3, string_base_type, unicode_chr, urlparse, urljoin, urllib_quote, unicode_type
|
from .compat import PY3, string_base_type, unicode_chr, urlparse, urljoin, urllib_quote, unicode_type
|
||||||
from .datatypes import QNAME_PATTERN, DateTime10, Date10, Time, Timezone, Duration, DayTimeDuration
|
from .datatypes import QNAME_PATTERN, DateTime10, Date10, Time, Timezone, Duration, DayTimeDuration
|
||||||
|
@ -182,11 +183,21 @@ def select(self, context=None):
|
||||||
elem = self.get_argument(context)
|
elem = self.get_argument(context)
|
||||||
if not is_element_node(elem):
|
if not is_element_node(elem):
|
||||||
raise self.error('FORG0006', 'argument %r is not a node' % elem)
|
raise self.error('FORG0006', 'argument %r is not a node' % elem)
|
||||||
for e in elem.iter():
|
|
||||||
tag_ns = get_namespace(e.tag)
|
if isinstance(context, XPathSchemaContext):
|
||||||
for pfx, uri in self.parser.namespaces.items():
|
# For schema context returns prefixes of static namespaces
|
||||||
if uri == tag_ns:
|
for prefix in self.parser.namespaces:
|
||||||
yield pfx
|
yield prefix
|
||||||
|
elif hasattr(elem, 'nsmap'):
|
||||||
|
# For lxml returns Element's prefixes
|
||||||
|
for prefix in elem.nsmap:
|
||||||
|
yield prefix or ''
|
||||||
|
else:
|
||||||
|
# For ElementTree returns module registered prefixes
|
||||||
|
prefixes = {x for x in self.parser.namespaces}
|
||||||
|
prefixes.update(x for x in ElementTree._namespace_map.values())
|
||||||
|
for prefix in prefixes:
|
||||||
|
yield prefix
|
||||||
|
|
||||||
|
|
||||||
@method(function('resolve-QName', nargs=2))
|
@method(function('resolve-QName', nargs=2))
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
# -*- 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>
|
|
||||||
#
|
|
||||||
from .exceptions import xpath_error
|
|
||||||
from .xpath_nodes import is_element_node
|
|
||||||
|
|
||||||
|
|
||||||
def boolean_value(obj, token=None):
|
|
||||||
"""
|
|
||||||
The effective boolean value, as computed by fn:boolean().
|
|
||||||
Moved to token class but kept for backward compatibility.
|
|
||||||
"""
|
|
||||||
if isinstance(obj, list):
|
|
||||||
if not obj:
|
|
||||||
return False
|
|
||||||
elif isinstance(obj[0], tuple) or is_element_node(obj[0]):
|
|
||||||
return True
|
|
||||||
elif len(obj) == 1:
|
|
||||||
return bool(obj[0])
|
|
||||||
else:
|
|
||||||
raise xpath_error(
|
|
||||||
code='FORG0006', token=token, prefix=getattr(token, 'error_prefix', 'err'),
|
|
||||||
message="Effective boolean value is not defined for a sequence of two or "
|
|
||||||
"more items not starting with an XPath node.",
|
|
||||||
)
|
|
||||||
elif isinstance(obj, tuple) or is_element_node(obj):
|
|
||||||
raise xpath_error(
|
|
||||||
code='FORG0006', token=token, prefix=getattr(token, 'error_prefix', 'err'),
|
|
||||||
message="Effective boolean value is not defined for {}.".format(obj)
|
|
||||||
)
|
|
||||||
return bool(obj)
|
|
|
@ -3,6 +3,6 @@ setuptools
|
||||||
tox
|
tox
|
||||||
coverage
|
coverage
|
||||||
lxml
|
lxml
|
||||||
xmlschema~=1.0.13
|
xmlschema~=1.0.14
|
||||||
Sphinx
|
Sphinx
|
||||||
-e .
|
-e .
|
||||||
|
|
|
@ -23,7 +23,6 @@ from elementpath.xpath_nodes import AttributeNode, NamespaceNode, is_etree_eleme
|
||||||
node_base_uri, node_document_uri, node_children, node_is_id, node_is_idrefs, \
|
node_base_uri, node_document_uri, node_children, node_is_id, node_is_idrefs, \
|
||||||
node_nilled, node_kind, node_name
|
node_nilled, node_kind, node_name
|
||||||
from elementpath.xpath_token import ordinal
|
from elementpath.xpath_token import ordinal
|
||||||
from elementpath.xpath_helpers import boolean_value
|
|
||||||
from elementpath.xpath1_parser import XPath1Parser
|
from elementpath.xpath1_parser import XPath1Parser
|
||||||
|
|
||||||
|
|
||||||
|
@ -247,20 +246,6 @@ class XPathTokenHelpersTest(unittest.TestCase):
|
||||||
self.assertEqual(ordinal(23), '23rd')
|
self.assertEqual(ordinal(23), '23rd')
|
||||||
self.assertEqual(ordinal(34), '34th')
|
self.assertEqual(ordinal(34), '34th')
|
||||||
|
|
||||||
def test_boolean_value_function(self):
|
|
||||||
elem = ElementTree.Element('A')
|
|
||||||
|
|
||||||
self.assertFalse(boolean_value([]))
|
|
||||||
self.assertTrue(boolean_value([elem]))
|
|
||||||
self.assertFalse(boolean_value([0]))
|
|
||||||
self.assertTrue(boolean_value([1]))
|
|
||||||
with self.assertRaises(TypeError):
|
|
||||||
boolean_value([1, 1])
|
|
||||||
with self.assertRaises(TypeError):
|
|
||||||
boolean_value(elem)
|
|
||||||
self.assertFalse(boolean_value(0))
|
|
||||||
self.assertTrue(boolean_value(1))
|
|
||||||
|
|
||||||
def test_get_argument_method(self):
|
def test_get_argument_method(self):
|
||||||
token = self.parser.symbol_table['true'](self.parser)
|
token = self.parser.symbol_table['true'](self.parser)
|
||||||
|
|
||||||
|
|
|
@ -217,6 +217,17 @@ class XPath1ParserTest(unittest.TestCase):
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
token.boolean_value(elem)
|
token.boolean_value(elem)
|
||||||
|
|
||||||
|
self.assertFalse(token.boolean_value([]))
|
||||||
|
self.assertTrue(token.boolean_value([elem]))
|
||||||
|
self.assertFalse(token.boolean_value([0]))
|
||||||
|
self.assertTrue(token.boolean_value([1]))
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
token.boolean_value([1, 1])
|
||||||
|
with self.assertRaises(TypeError):
|
||||||
|
token.boolean_value(elem)
|
||||||
|
self.assertFalse(token.boolean_value(0))
|
||||||
|
self.assertTrue(token.boolean_value(1))
|
||||||
|
|
||||||
def test_data_value_function(self):
|
def test_data_value_function(self):
|
||||||
token = self.parser.parse('true()')
|
token = self.parser.parse('true()')
|
||||||
self.assertIsNone(token.data_value(None))
|
self.assertIsNone(token.data_value(None))
|
||||||
|
|
|
@ -552,6 +552,12 @@ class XPath2ParserTest(test_xpath1_parser.XPath1ParserTest):
|
||||||
)
|
)
|
||||||
self.assertIsNone(parser.parse('fn:resolve-uri(())').evaluate(context))
|
self.assertIsNone(parser.parse('fn:resolve-uri(())').evaluate(context))
|
||||||
|
|
||||||
|
def test_predicate(self):
|
||||||
|
super(XPath2ParserTest, self).test_predicate()
|
||||||
|
root = self.etree.XML('<A><B1><B2/><B2/></B1><C1><C2/><C2/></C1></A>')
|
||||||
|
self.check_selector("/(A/*/*)[1]", root, [root[0][0]])
|
||||||
|
self.check_selector("/A/*/*[1]", root, [root[0][0], root[1][0]])
|
||||||
|
|
||||||
def test_sequence_general_functions(self):
|
def test_sequence_general_functions(self):
|
||||||
# Test cases from https://www.w3.org/TR/xquery-operators/#general-seq-funcs
|
# Test cases from https://www.w3.org/TR/xquery-operators/#general-seq-funcs
|
||||||
self.check_value('fn:empty(("hello", "world"))', False)
|
self.check_value('fn:empty(("hello", "world"))', False)
|
||||||
|
@ -647,7 +653,16 @@ class XPath2ParserTest(test_xpath1_parser.XPath1ParserTest):
|
||||||
self.check_value("fn:namespace-uri-for-prefix('eg', .)", 'http://www.example.com/ns/', context=context)
|
self.check_value("fn:namespace-uri-for-prefix('eg', .)", 'http://www.example.com/ns/', context=context)
|
||||||
self.check_selector("fn:namespace-uri-for-prefix('p3', .)", root, NameError, namespaces={'p3': ''})
|
self.check_selector("fn:namespace-uri-for-prefix('p3', .)", root, NameError, namespaces={'p3': ''})
|
||||||
|
|
||||||
self.check_selector("fn:in-scope-prefixes(.)", root, ['p2', 'p0'], namespaces={'p0': 'ns0', 'p2': 'ns2'})
|
def test_in_scope_prefixes_function(self):
|
||||||
|
root = self.etree.XML('<p1:A xmlns:p1="ns1" xmlns:p0="ns0">'
|
||||||
|
' <B1><p2:C xmlns:p2="ns2"/></B1><B2/>'
|
||||||
|
' <p0:B3><eg:C1 xmlns:eg="http://www.example.com/ns/"/><C2/></p0:B3>'
|
||||||
|
'</p1:A>')
|
||||||
|
if self.etree is lxml_etree:
|
||||||
|
prefixes = {'p0', 'p1'}
|
||||||
|
else:
|
||||||
|
prefixes = {'p0', 'p2', 'fn', 'xlink', 'err'} | {x for x in self.etree._namespace_map.values()}
|
||||||
|
self.check_selector("fn:in-scope-prefixes(.)", root, prefixes, namespaces={'p0': 'ns0', 'p2': 'ns2'})
|
||||||
|
|
||||||
def test_string_constructors(self):
|
def test_string_constructors(self):
|
||||||
self.check_value("xs:string(5.0)", '5.0')
|
self.check_value("xs:string(5.0)", '5.0')
|
||||||
|
|
4
tox.ini
4
tox.ini
|
@ -11,7 +11,7 @@ toxworkdir = {homedir}/.tox/elementpath
|
||||||
[testenv]
|
[testenv]
|
||||||
deps =
|
deps =
|
||||||
lxml
|
lxml
|
||||||
xmlschema~=1.0.13
|
xmlschema~=1.0.14
|
||||||
docs: Sphinx
|
docs: Sphinx
|
||||||
flake8: flake8
|
flake8: flake8
|
||||||
coverage: coverage
|
coverage: coverage
|
||||||
|
@ -24,7 +24,7 @@ commands = python tests/test_elementpath.py
|
||||||
[testenv:py38]
|
[testenv:py38]
|
||||||
deps =
|
deps =
|
||||||
lxml==4.3.5
|
lxml==4.3.5
|
||||||
xmlschema~=1.0.13
|
xmlschema~=1.0.14
|
||||||
commands = python -m unittest
|
commands = python -m unittest
|
||||||
|
|
||||||
[testenv:docs]
|
[testenv:docs]
|
||||||
|
|
Loading…
Reference in New Issue