Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-elementpath for openSUSE:Factory checked in at 2023-06-26 18:15:30 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-elementpath (Old) and /work/SRC/openSUSE:Factory/.python-elementpath.new.15902 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-elementpath" Mon Jun 26 18:15:30 2023 rev:17 rq:1095230 version:4.1.3 Changes: -------- --- /work/SRC/openSUSE:Factory/python-elementpath/python-elementpath.changes 2023-05-19 11:55:37.511298811 +0200 +++ /work/SRC/openSUSE:Factory/.python-elementpath.new.15902/python-elementpath.changes 2023-06-26 18:15:31.322317937 +0200 @@ -1,0 +2,7 @@ +Sun Jun 25 18:47:08 UTC 2023 - Dirk Müller <dmuel...@suse.com> + +- update to 4.1.3: + * Fix XP30+ fn:path + * Fix weak tests + +------------------------------------------------------------------- Old: ---- v4.1.2.tar.gz New: ---- v4.1.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-elementpath.spec ++++++ --- /var/tmp/diff_new_pack.CmSpPW/_old 2023-06-26 18:15:32.414322789 +0200 +++ /var/tmp/diff_new_pack.CmSpPW/_new 2023-06-26 18:15:32.418322806 +0200 @@ -20,7 +20,7 @@ %define skip_python36 1 %{?sle15_python_module_pythons} Name: python-elementpath -Version: 4.1.2 +Version: 4.1.3 Release: 0 Summary: XPath 1.0/20 parsers and selectors for ElementTree and lxml License: MIT ++++++ v4.1.2.tar.gz -> v4.1.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elementpath-4.1.2/.github/workflows/test-elementpath.yml new/elementpath-4.1.3/.github/workflows/test-elementpath.yml --- old/elementpath-4.1.2/.github/workflows/test-elementpath.yml 2023-04-28 18:04:10.000000000 +0200 +++ new/elementpath-4.1.3/.github/workflows/test-elementpath.yml 2023-06-17 19:30:54.000000000 +0200 @@ -42,7 +42,7 @@ - name: Lint with mypy if Python version != 3.7 if: ${{ matrix.python-version != '3.7' }} run: | - pip install mypy==1.2.0 xmlschema lxml-stubs + pip install mypy==1.3.0 xmlschema lxml-stubs mypy --show-error-codes --strict elementpath - name: Test with unittest run: | diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elementpath-4.1.2/CHANGELOG.rst new/elementpath-4.1.3/CHANGELOG.rst --- old/elementpath-4.1.2/CHANGELOG.rst 2023-04-28 18:04:10.000000000 +0200 +++ new/elementpath-4.1.3/CHANGELOG.rst 2023-06-17 19:30:54.000000000 +0200 @@ -2,6 +2,11 @@ CHANGELOG ********* +`v4.1.3`_ (2023-06-17) +====================== +* Fix XP30+ fn:path (issue #67) +* Fix weak tests (issues #64 and #66) + `v4.1.2`_ (2023-04-28) ====================== * Add support for Python 3.12 @@ -418,3 +423,4 @@ .. _v4.1.0: https://github.com/sissaschool/elementpath/compare/v4.0.1...v4.1.0 .. _v4.1.1: https://github.com/sissaschool/elementpath/compare/v4.1.0...v4.1.1 .. _v4.1.2: https://github.com/sissaschool/elementpath/compare/v4.1.1...v4.1.2 +.. _v4.1.3: https://github.com/sissaschool/elementpath/compare/v4.1.2...v4.1.3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elementpath-4.1.2/doc/conf.py new/elementpath-4.1.3/doc/conf.py --- old/elementpath-4.1.2/doc/conf.py 2023-04-28 18:04:10.000000000 +0200 +++ new/elementpath-4.1.3/doc/conf.py 2023-06-17 19:30:54.000000000 +0200 @@ -31,7 +31,7 @@ # The short X.Y version version = '4.1' # The full version, including alpha/beta/rc tags -release = '4.1.2' +release = '4.1.3' # -- General configuration --------------------------------------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elementpath-4.1.2/elementpath/__init__.py new/elementpath-4.1.3/elementpath/__init__.py --- old/elementpath-4.1.2/elementpath/__init__.py 2023-04-28 18:04:10.000000000 +0200 +++ new/elementpath-4.1.3/elementpath/__init__.py 2023-06-17 19:30:54.000000000 +0200 @@ -7,7 +7,7 @@ # # @author Davide Brunato <brun...@sissa.it> # -__version__ = '4.1.2' +__version__ = '4.1.3' __author__ = "Davide Brunato" __contact__ = "brun...@sissa.it" __copyright__ = "Copyright 2018-2023, SISSA" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elementpath-4.1.2/elementpath/xpath30/_xpath30_functions.py new/elementpath-4.1.3/elementpath/xpath30/_xpath30_functions.py --- old/elementpath-4.1.2/elementpath/xpath30/_xpath30_functions.py 2023-04-28 18:04:10.000000000 +0200 +++ new/elementpath-4.1.3/elementpath/xpath30/_xpath30_functions.py 2023-06-17 19:30:54.000000000 +0200 @@ -1086,8 +1086,12 @@ if isinstance(context.root, DocumentNode): root = context.root.getroot().elem - path = f'/Q{root.tag}[1]' + if root.tag.startswith('{'): + path = f'/Q{root.tag}[1]' + else: + path = f'/Q{{}}{root.tag}[1]' else: + # If root is an element use the function that returns the root of the tree root = context.root.elem path = 'Q{%s}root()' % XPATH_FUNCTIONS_NAMESPACE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elementpath-4.1.2/publiccode.yml new/elementpath-4.1.3/publiccode.yml --- old/elementpath-4.1.2/publiccode.yml 2023-04-28 18:04:10.000000000 +0200 +++ new/elementpath-4.1.3/publiccode.yml 2023-06-17 19:30:54.000000000 +0200 @@ -6,8 +6,8 @@ name: elementpath url: 'https://github.com/sissaschool/elementpath' landingURL: 'https://github.com/sissaschool/elementpath' -releaseDate: '2023-04-28' -softwareVersion: v4.1.2 +releaseDate: '2023-06-17' +softwareVersion: v4.1.3 developmentStatus: stable platforms: - linux diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elementpath-4.1.2/setup.py new/elementpath-4.1.3/setup.py --- old/elementpath-4.1.2/setup.py 2023-04-28 18:04:10.000000000 +0200 +++ new/elementpath-4.1.3/setup.py 2023-06-17 19:30:54.000000000 +0200 @@ -15,7 +15,7 @@ setup( name='elementpath', - version='4.1.2', + version='4.1.3', packages=find_packages(include=['elementpath', 'elementpath.*']), package_data={ 'elementpath': ['py.typed'], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elementpath-4.1.2/tests/test_typing.py new/elementpath-4.1.3/tests/test_typing.py --- old/elementpath-4.1.2/tests/test_typing.py 2023-04-28 18:04:10.000000000 +0200 +++ new/elementpath-4.1.3/tests/test_typing.py 2023-06-17 19:30:54.000000000 +0200 @@ -11,18 +11,23 @@ """Tests about static typing of elementpath objects.""" import unittest -import subprocess -import re import sys +import importlib from pathlib import Path try: - import mypy + from mypy import api as mypy_api except ImportError: - mypy = None + mypy_api = None +try: + lxml_stubs_module = importlib.import_module('lxml-stubs') +except ImportError: + lxml_stubs_module = None -@unittest.skipIf(mypy is None, "mypy is not installed") + +@unittest.skipIf(mypy_api is None, "mypy is not installed") +@unittest.skipIf(lxml_stubs_module is None, "lxml-stubs is not installed") @unittest.skipIf(sys.version_info < (3, 8), "Python version is lesser than 3.8") class TestTyping(unittest.TestCase): @@ -30,26 +35,14 @@ def setUpClass(cls): cls.cases_dir = Path(__file__).parent.joinpath('mypy_tests') cls.config_file = Path(__file__).parent.parent.joinpath('mypy.ini') - cls.error_pattern = re.compile(r'Found \d+ error', re.IGNORECASE) - - def check_mypy_output(self, testfile, *options): - cmd = ['mypy', '--config-file', str(self.config_file), testfile] - if options: - cmd.extend(str(opt) for opt in options) - process = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - - self.assertEqual(process.stderr, b'') - output = process.stdout.decode('utf-8').strip() - output_lines = output.split('\n') - - self.assertGreater(len(output_lines), 0, msg=output) - self.assertNotRegex(output_lines[-1], self.error_pattern, msg=output) - return output_lines def test_selectors(self): - case_path = self.cases_dir.joinpath('selectors.py') - output_lines = self.check_mypy_output(case_path, '--strict') - self.assertTrue(output_lines[0].startswith('Success:'), msg='\n'.join(output_lines)) + result = mypy_api.run([ + '--strict', + '--config-file', str(self.config_file), + str(self.cases_dir.joinpath('selectors.py')) + ]) + self.assertEqual(result[2], 0, msg=result[1] or result[0]) if __name__ == '__main__': diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elementpath-4.1.2/tests/test_xpath1_parser.py new/elementpath-4.1.3/tests/test_xpath1_parser.py --- old/elementpath-4.1.2/tests/test_xpath1_parser.py 2023-04-28 18:04:10.000000000 +0200 +++ new/elementpath-4.1.3/tests/test_xpath1_parser.py 2023-06-17 19:30:54.000000000 +0200 @@ -19,7 +19,6 @@ # https://www.w3.org/Consortium/Legal/2015/doc-license # https://www.w3.org/TR/charmod-norm/ # -import sys import unittest import io import math @@ -1130,10 +1129,7 @@ root = self.etree.XML(XML_DATA_TEST) context = XPathContext(root, variables=self.variables) self.check_value("sum($values)", 35, context) - if sys.version_info < (3, 12): - self.check_selector("sum(/values/a)", root, 13.299999999999999) - else: - self.check_selector("sum(/values/a)", root, 13.3) + self.check_selector("sum(/values/a)", root, 13.3) if self.parser.version == '1.0': self.check_selector("sum(/values/*)", root, math.isnan) @@ -1679,6 +1675,17 @@ set(root.xpath(path, namespaces=namespaces, **variables)), expected ) self.assertEqual(set(results), expected) + elif isinstance(expected, float): + if math.isnan(expected): + self.assertTrue(math.isnan( + root.xpath(path, namespaces=namespaces, **variables) + )) + self.assertTrue(math.isnan(results)) + else: + self.assertAlmostEqual( + root.xpath(path, namespaces=namespaces, **variables), expected + ) + self.assertAlmostEqual(results, expected) elif not callable(expected): self.assertEqual(root.xpath(path, namespaces=namespaces, **variables), expected) self.assertEqual(results, expected) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elementpath-4.1.2/tests/test_xpath30.py new/elementpath-4.1.3/tests/test_xpath30.py --- old/elementpath-4.1.2/tests/test_xpath30.py 2023-04-28 18:04:10.000000000 +0200 +++ new/elementpath-4.1.3/tests/test_xpath30.py 2023-06-17 19:30:54.000000000 +0200 @@ -19,6 +19,7 @@ # https://www.w3.org/Consortium/Legal/2015/doc-license # https://www.w3.org/TR/charmod-norm/ # +import io import unittest import os import re @@ -26,6 +27,7 @@ import pathlib import platform import xml.etree.ElementTree as ElementTree +from textwrap import dedent from typing import cast try: @@ -40,7 +42,7 @@ else: xmlschema.XMLSchema.meta_schema.build() -from elementpath import XPathContext, MissingContextError, datatypes, XPathFunction +from elementpath import select, XPathContext, MissingContextError, datatypes, XPathFunction from elementpath.namespaces import XPATH_FUNCTIONS_NAMESPACE from elementpath.etree import is_etree_element, is_lxml_etree_document, is_etree_document from elementpath.xpath_nodes import ElementNode, DocumentNode @@ -1179,6 +1181,93 @@ self.check_value("format-integer(123, '0000')", '0123') self.check_source("format-integer(-8912, 'W')") + def test_path_function__issue_067(self): + xml_sample = dedent(""" + <root> + <item> + <name>item 1</name> + <value>value 1</value> + </item> + </root>""") + + root = self.etree.parse(io.StringIO(xml_sample)) + paths = select(root, '//*/path()', parser=self.parser.__class__) + expected = [ + '/Q{}root[1]', + '/Q{}root[1]/Q{}item[1]', + '/Q{}root[1]/Q{}item[1]/Q{}name[1]', + '/Q{}root[1]/Q{}item[1]/Q{}value[1]' + ] + self.assertListEqual(paths, expected) + + root = self.etree.XML(xml_sample) + paths = select(root, '//*/path()', parser=self.parser.__class__) + + expected = [ + 'Q{http://www.w3.org/2005/xpath-functions}root()', + 'Q{http://www.w3.org/2005/xpath-functions}root()/Q{}item[1]', + 'Q{http://www.w3.org/2005/xpath-functions}root()/Q{}item[1]/Q{}name[1]', + 'Q{http://www.w3.org/2005/xpath-functions}root()/Q{}item[1]/Q{}value[1]' + ] + self.assertListEqual(paths, expected) + + def test_path_function_with_namespaces(self): + xml_sample = dedent(""" + <tns:root xmlns:tns="http://xpath.test/ns"> + <item> + <name>item 1</name> + <foo:value xmlns:foo="bar">value 1</foo:value> + </item> + </tns:root>""") + + root = self.etree.parse(io.StringIO(xml_sample)) + paths = select(root, '//*/path()', parser=self.parser.__class__) + expected = [ + '/Q{http://xpath.test/ns}root[1]', + '/Q{http://xpath.test/ns}root[1]/Q{}item[1]', + '/Q{http://xpath.test/ns}root[1]/Q{}item[1]/Q{}name[1]', + '/Q{http://xpath.test/ns}root[1]/Q{}item[1]/Q{bar}value[1]' + ] + self.assertListEqual(paths, expected) + + root = self.etree.XML(xml_sample) + paths = select(root, '//*/path()', parser=self.parser.__class__) + + expected = [ + 'Q{http://www.w3.org/2005/xpath-functions}root()', + 'Q{http://www.w3.org/2005/xpath-functions}root()/Q{}item[1]', + 'Q{http://www.w3.org/2005/xpath-functions}root()/Q{}item[1]/Q{}name[1]', + 'Q{http://www.w3.org/2005/xpath-functions}root()/Q{}item[1]/Q{bar}value[1]' + ] + self.assertListEqual(paths, expected) + + def test_path_function_with_same_child(self): + xml_sample = dedent(""" + <tns:root xmlns:tns="http://xpath.test/ns"> + <item> + <name>item 1</name> + <value>value 1</value> + <name>item 2</name> + <name>item 3</name> + </item> + <item2/> + <item/> + </tns:root>""") + + root = self.etree.parse(io.StringIO(xml_sample)) + paths = select(root, '//*/path()', parser=self.parser.__class__) + expected = [ + '/Q{http://xpath.test/ns}root[1]', + '/Q{http://xpath.test/ns}root[1]/Q{}item[1]', + '/Q{http://xpath.test/ns}root[1]/Q{}item[1]/Q{}name[1]', + '/Q{http://xpath.test/ns}root[1]/Q{}item[1]/Q{}value[1]', + '/Q{http://xpath.test/ns}root[1]/Q{}item[1]/Q{}name[2]', + '/Q{http://xpath.test/ns}root[1]/Q{}item[1]/Q{}name[3]', + '/Q{http://xpath.test/ns}root[1]/Q{}item2[1]', + '/Q{http://xpath.test/ns}root[1]/Q{}item[2]', + ] + self.assertListEqual(paths, expected) + @unittest.skipIf(lxml_etree is None, "The lxml library is not installed") class LxmlXPath30FunctionsTest(XPath30FunctionsTest): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elementpath-4.1.2/tests/xpath_test_class.py new/elementpath-4.1.3/tests/xpath_test_class.py --- old/elementpath-4.1.2/tests/xpath_test_class.py 2023-04-28 18:04:10.000000000 +0200 +++ new/elementpath-4.1.3/tests/xpath_test_class.py 2023-06-17 19:30:54.000000000 +0200 @@ -145,24 +145,31 @@ return raise - if isinstance(expected, type) and issubclass(expected, Exception): - self.assertRaises(expected, root_token.evaluate, context) - elif isinstance(expected, float) and math.isnan(expected): + if isinstance(expected, type): + if issubclass(expected, Exception): + self.assertRaises(expected, root_token.evaluate, context) + else: + self.assertIsInstance(root_token.evaluate(context), expected) + + elif isinstance(expected, float): value = root_token.evaluate(context) - if isinstance(value, list): - self.assertTrue(any(math.isnan(x) for x in value)) + if not math.isnan(expected): + self.assertAlmostEqual(value, expected) else: + if isinstance(value, list): + value = [x for x in value if value is not None and value != []] + self.assertTrue(len(value) == 1) + value = value[0] + + self.assertIsInstance(value, float) self.assertTrue(math.isnan(value)) - elif isinstance(expected, list) and expected: + elif isinstance(expected, list): self.assertListEqual(root_token.evaluate(context), expected) elif isinstance(expected, set): self.assertEqual(set(root_token.evaluate(context)), expected) elif isinstance(expected, XPathFunction) or not callable(expected): self.assertEqual(root_token.evaluate(context), expected) - elif isinstance(expected, type): - value = root_token.evaluate(context) - self.assertIsInstance(value, expected) else: self.assertTrue(expected(root_token.evaluate(context))) @@ -190,10 +197,10 @@ self.assertListEqual(list(root_token.select(context)), expected) elif isinstance(expected, set): self.assertEqual(set(root_token.select(context)), expected) - elif isinstance(expected, XPathFunction) or not callable(expected): - self.assertEqual(list(root_token.select(context)), expected) - else: + elif callable(expected): self.assertTrue(expected(list(root_token.parser.parse(path).select(context)))) + else: + self.assertEqual(list(root_token.select(context)), expected) # must fail def check_selector(self, path, root, expected, namespaces=None, **kwargs): """ @@ -217,8 +224,11 @@ self.assertListEqual(results, expected) elif isinstance(expected, set): self.assertEqual(set(results), expected) - elif isinstance(expected, float) and math.isnan(expected): - self.assertTrue(math.isnan(results)) + elif isinstance(expected, float): + if math.isnan(expected): + self.assertTrue(math.isnan(results)) + else: + self.assertAlmostEqual(results, expected) elif not callable(expected): self.assertEqual(results, expected) elif isinstance(expected, type): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/elementpath-4.1.2/tox.ini new/elementpath-4.1.3/tox.ini --- old/elementpath-4.1.2/tox.ini 2023-04-28 18:04:10.000000000 +0200 +++ new/elementpath-4.1.3/tox.ini 2023-06-17 19:30:54.000000000 +0200 @@ -4,6 +4,7 @@ # and then run "tox" from this directory. [tox] +min_version = 4.0 envlist = py{37,38,39,310,311,312}, pypy3, xmlschema{20}, docs, flake8, mypy-py{38,39,310,311,312,py3}, pytest, coverage @@ -46,7 +47,7 @@ [testenv:mypy-py{38,39,310,311,312,py3}] deps = - mypy==1.2.0 + mypy==1.3.0 xmlschema lxml-stubs commands =