Update test requirements

- Now uses xmlschema~=1.0.14
  - Update fn:in-scope-prefixes()
  - Remove module xpath_helpers.py
This commit is contained in:
Davide Brunato 2019-10-04 09:57:32 +02:00
parent 22d9f4258d
commit de6955b36c
8 changed files with 67 additions and 71 deletions

View File

@ -257,7 +257,11 @@ def select(self, context=None):
xsd_type = self.match_xsd_type(item, name)
if xsd_type is not None:
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):
yield TypedAttribute(item, value)
else:
@ -676,7 +680,6 @@ def select(self, context=None):
yield result
else:
items = []
context2 = context.copy()
left_results = list(self[0].select(context))
context.size = len(left_results)
for context.position, context.item in enumerate(left_results):
@ -749,7 +752,10 @@ def led(self, left):
@method('[')
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):
predicate = list(self[1].select(context.copy()))
if len(predicate) == 1 and isinstance(predicate[0], NumericTypeProxy):
@ -825,14 +831,20 @@ def select(self, context=None):
else:
return
for elem in context.iter_parent(axis=self.symbol):
follows = False
for child in context.iter_children_or_self(elem, child_axis=True):
if follows:
for parent in context.iter_parent(axis=self.symbol):
if isinstance(context, XPathSchemaContext):
for _ in context.iter_children_or_self(parent, child_axis=True):
for result in self[0].select(context):
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'))

View File

@ -19,6 +19,7 @@ import time
import re
import locale
import unicodedata
import xml.etree.ElementTree as ElementTree
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
@ -182,11 +183,21 @@ def select(self, context=None):
elem = self.get_argument(context)
if not is_element_node(elem):
raise self.error('FORG0006', 'argument %r is not a node' % elem)
for e in elem.iter():
tag_ns = get_namespace(e.tag)
for pfx, uri in self.parser.namespaces.items():
if uri == tag_ns:
yield pfx
if isinstance(context, XPathSchemaContext):
# For schema context returns prefixes of static namespaces
for prefix in self.parser.namespaces:
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))

View File

@ -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)

View File

@ -3,6 +3,6 @@ setuptools
tox
coverage
lxml
xmlschema~=1.0.13
xmlschema~=1.0.14
Sphinx
-e .

View File

@ -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_nilled, node_kind, node_name
from elementpath.xpath_token import ordinal
from elementpath.xpath_helpers import boolean_value
from elementpath.xpath1_parser import XPath1Parser
@ -247,20 +246,6 @@ class XPathTokenHelpersTest(unittest.TestCase):
self.assertEqual(ordinal(23), '23rd')
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):
token = self.parser.symbol_table['true'](self.parser)

View File

@ -217,6 +217,17 @@ class XPath1ParserTest(unittest.TestCase):
with self.assertRaises(TypeError):
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):
token = self.parser.parse('true()')
self.assertIsNone(token.data_value(None))

View File

@ -552,6 +552,12 @@ class XPath2ParserTest(test_xpath1_parser.XPath1ParserTest):
)
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):
# Test cases from https://www.w3.org/TR/xquery-operators/#general-seq-funcs
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_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):
self.check_value("xs:string(5.0)", '5.0')

View File

@ -11,7 +11,7 @@ toxworkdir = {homedir}/.tox/elementpath
[testenv]
deps =
lxml
xmlschema~=1.0.13
xmlschema~=1.0.14
docs: Sphinx
flake8: flake8
coverage: coverage
@ -24,7 +24,7 @@ commands = python tests/test_elementpath.py
[testenv:py38]
deps =
lxml==4.3.5
xmlschema~=1.0.13
xmlschema~=1.0.14
commands = python -m unittest
[testenv:docs]