Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-xmldiff for openSUSE:Factory checked in at 2026-06-15 19:44:57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-xmldiff (Old) and /work/SRC/openSUSE:Factory/.python-xmldiff.new.1981 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-xmldiff" Mon Jun 15 19:44:57 2026 rev:25 rq:1359310 version:3.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-xmldiff/python-xmldiff.changes 2025-08-05 14:22:30.004280582 +0200 +++ /work/SRC/openSUSE:Factory/.python-xmldiff.new.1981/python-xmldiff.changes 2026-06-15 19:48:19.783706034 +0200 @@ -1,0 +2,16 @@ +Sun Jun 14 20:10:27 UTC 2026 - Dirk Müller <[email protected]> + +- update to 3.0: + * Updated Python versions. 3.8 and 3.9 still works, but is + officially unsupported, added 3.13, 3.14 and 3.15 to the + supported versions. + * Speeding up diffing by using dequeue [barucden] + * Support namespace-prefixed move nodes [barucden] + * Improved matching in certain cases [barucden] + * UpdateTextIn() and UpdateTextAfter() now also has optional + parameters "oldtext" which contains the text before update, + or None, if there was no text. + * Fixed a bug in the parsing of diff files. +- drop fix-error-type.patch (upstream) + +------------------------------------------------------------------- Old: ---- fix-error-type.patch xmldiff-2.7.0.tar.gz New: ---- xmldiff-3.0.tar.gz ----------(Old B)---------- Old: * Fixed a bug in the parsing of diff files. - drop fix-error-type.patch (upstream) ----------(Old E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-xmldiff.spec ++++++ --- /var/tmp/diff_new_pack.rYveh2/_old 2026-06-15 19:48:20.379731079 +0200 +++ /var/tmp/diff_new_pack.rYveh2/_new 2026-06-15 19:48:20.383731248 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-xmldiff # -# Copyright (c) 2025 SUSE LLC +# Copyright (c) 2026 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,21 +18,18 @@ %define oldpython python Name: python-xmldiff -Version: 2.7.0 +Version: 3.0 Release: 0 Summary: Tree to tree correction between XML documents License: MIT URL: https://github.com/Shoobx/xmldiff Source: https://files.pythonhosted.org/packages/source/x/xmldiff/xmldiff-%{version}.tar.gz -# PATCH-FIX-UPSTREAM fix-error-type.patch taken from https://github.com/Shoobx/xmldiff/commit/57e16ce3d92067c6246c3de04f2d4b9803f6f25b -Patch0: fix-error-type.patch BuildRequires: %{python_module pip} -BuildRequires: %{python_module setuptools} +BuildRequires: %{python_module setuptools >= 61.2} BuildRequires: %{python_module wheel} BuildRequires: fdupes BuildRequires: python-rpm-macros Requires: python-lxml >= 3.1.0 -Requires: python-setuptools Requires(post): update-alternatives Requires(postun): update-alternatives Conflicts: %{oldpython}-xmldiff < %{version} ++++++ xmldiff-2.7.0.tar.gz -> xmldiff-3.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/.pre-commit-config.yaml new/xmldiff-3.0/.pre-commit-config.yaml --- old/xmldiff-2.7.0/.pre-commit-config.yaml 1970-01-01 01:00:00.000000000 +0100 +++ new/xmldiff-3.0/.pre-commit-config.yaml 2026-06-11 17:00:00.000000000 +0200 @@ -0,0 +1,18 @@ +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: check-yaml + - id: trailing-whitespace +- repo: https://github.com/astral-sh/ruff-pre-commit + # Ruff version. + rev: v0.12.2 + hooks: + # Run the linter. + - id: ruff-check + # Run the formatter. + - id: ruff-format +- repo: https://github.com/regebro/pyroma + rev: '5.0b2' + hooks: + - id: pyroma diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/CHANGES.rst new/xmldiff-3.0/CHANGES.rst --- old/xmldiff-2.7.0/CHANGES.rst 2024-05-13 14:15:38.000000000 +0200 +++ new/xmldiff-3.0/CHANGES.rst 2026-06-11 17:00:00.000000000 +0200 @@ -1,6 +1,28 @@ Changes ======= +3.0 (2026-06-11) +---------------- + +- Updated Python versions. 3.8 and 3.9 still works, but is officially unsupported, + added 3.13, 3.14 and 3.15 to the supported versions. + +- Speeding up diffing by using dequeue [barucden] + +- Support namespace-prefixed move nodes [barucden] + +- Improved matching in certain cases [barucden] + + +3.0b1 (2025-07-14) +------------------ + +- UpdateTextIn() and UpdateTextAfter() now also has optional parameters "oldtext" + which contains the text before update, or None, if there was no text. + +- Fixed a bug in the parsing of diff files. + + 2.7.0 (2024-05-13) ------------------ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/CHANGES.txt new/xmldiff-3.0/CHANGES.txt --- old/xmldiff-2.7.0/CHANGES.txt 2024-05-13 14:15:38.000000000 +0200 +++ new/xmldiff-3.0/CHANGES.txt 1970-01-01 01:00:00.000000000 +0100 @@ -1,7 +0,0 @@ -- Added option to XMLFormatter to use replace tags - -- in _make_diff_tags after diffing, neighboring delete/insert diffs are joined to a replace tag - -- the deleted text is added as an attribute ("old-text") - -- the inserted text is the element's text \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/MANIFEST.in new/xmldiff-3.0/MANIFEST.in --- old/xmldiff-2.7.0/MANIFEST.in 2024-05-13 14:15:38.000000000 +0200 +++ new/xmldiff-3.0/MANIFEST.in 2026-06-11 17:00:00.000000000 +0200 @@ -14,3 +14,6 @@ recursive-include docs *.xslt recursive-include docs Makefile recursive-exclude docs/build * + +# added by check-manifest +include *.yaml diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/Makefile new/xmldiff-3.0/Makefile --- old/xmldiff-2.7.0/Makefile 2024-05-13 14:15:38.000000000 +0200 +++ new/xmldiff-3.0/Makefile 2026-06-11 17:00:00.000000000 +0200 @@ -14,8 +14,7 @@ $(bin_dir)/pip install -e .[devenv] check: devenv - $(bin_dir)/black xmldiff tests - $(bin_dir)/flake8 xmldiff tests + $(bin_dir)/ruff check xmldiff tests $(bin_dir)/pyroma -d . coverage: devenv diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/PKG-INFO new/xmldiff-3.0/PKG-INFO --- old/xmldiff-2.7.0/PKG-INFO 2024-05-13 14:15:38.185385700 +0200 +++ new/xmldiff-3.0/PKG-INFO 2026-06-11 17:00:01.086637300 +0200 @@ -1,36 +1,35 @@ Metadata-Version: 2.1 Name: xmldiff -Version: 2.7.0 +Version: 3.0 Summary: Creates diffs of XML files -Home-page: https://github.com/Shoobx/xmldiff -Author: Lennart Regebro -Author-email: [email protected] +Author-email: Lennart Regebro <[email protected]> License: MIT +Project-URL: Homepage, https://github.com/Shoobx/xmldiff Project-URL: Source Code, https://github.com/Shoobx/xmldiff -Keywords: xml,html,diff +Keywords: diff,html,xml Classifier: Development Status :: 4 - Beta Classifier: Intended Audience :: Developers Classifier: Intended Audience :: End Users/Desktop -Classifier: Topic :: Text Processing :: Markup :: XML -Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.8 -Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 -Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Programming Language :: Python :: 3.13 +Classifier: Programming Language :: Python :: 3.14 +Classifier: Programming Language :: Python :: 3.15 +Classifier: Topic :: Text Processing :: Markup :: XML +Classifier: License :: OSI Approved :: MIT License Requires-Python: >=3.8 +Description-Content-Type: text/x-rst License-File: LICENSE.txt -Requires-Dist: setuptools Requires-Dist: lxml>=3.1.0 Provides-Extra: devenv -Requires-Dist: black; extra == "devenv" -Requires-Dist: coverage; extra == "devenv" -Requires-Dist: flake8; extra == "devenv" +Requires-Dist: ruff; extra == "devenv" +Requires-Dist: pyroma>=5.0b1; extra == "devenv" Requires-Dist: zest.releaser[recommended]; extra == "devenv" xmldiff @@ -127,158 +126,10 @@ * Thomas Pfitzinger, [email protected] + * Alexandre Detiste + + * Denis Barucic, [email protected] + The diff algorithm is based on "`Change Detection in Hierarchically Structured Information <http://infolab.stanford.edu/c3/papers/html/tdiff3-8/tdiff3-8.html>`_", and the text diff is using Google's ``diff_match_patch`` algorithm. - -Changes -======= - -2.7.0 (2024-05-13) ------------------- - -- Changed the comparison to make accurate and standard more accurate, - although fast gets less accurate as a result. - -- Changed usage of deprecated `pkg_resources` package to `importlib.metadata`. - -- A `use_replace` flag was added to the `XMLFormatter` by Thomas Pfitzinger. - It changes text replacement from delete and insert tags to a replace tag. - It's not currently accessaible thtough the CLI, the question is it is better - to add a new formatter name, or an option to pass in formatter flags. - - - Added option to XMLFormatter to use replace tags - - in _make_diff_tags after diffing, neighboring delete/insert diffs are joined to a replace tag - - the deleted text is added as an attribute ("old-text") - - the inserted text is the element's text - -2.6.3 (2023-05-21) ------------------- - -- And there was a namespace bug in the patch as well. #118 - - -2.6.2 (2023-05-21) ------------------- - -- Solved an error in the xmlformatter when using default namespaces. #89 - - -2.6.1 (2023-04-05) ------------------- - -- #108: Fixed an error that happens if using namespaces like ns0 or ns1. - - -2.6 (2023-04-03) ----------------- - -- Added `InsertNamespace` and `DeleteNamespace` actions for better handling - of changing namespaces. Should improve any "Unknown namespace prefix" - errors. Changing the URI of a a namespace prefix is not supported, and will - raise an error. - -2.6b1 (2023-01-12) ------------------- - -- Used geometric mean for the node_ratio, for better handling of simple nodes. - -- Added an experimental --best-match method that is slower, but generate - smaller diffs when you have many nodes that are similar. - -- The -F argument now also affects the --fast-match stage. - - -2.5 (2023-01-11) ----------------- - -- Make it possible to adjust the attributes considered when comparing nodes. - -- Python versions 3.7 to 3.11 are now supported. - -- Improved node matching method, that puts more emphasis similarities than - differences when weighing attributes vs children. - -- Added a parameter to return error code 1 when there are differences between the files - -- Added a parameter for ignoring attributes in comparison. - -- Solved a bug in xmlpatch in certain namespace situations. - -- Added a --diff-encoding parameter to xmlpatch, to support diff-files that are - not in your system default encoding. - - -2.4 (2019-10-09) ----------------- - -- Added an option to pass pairs of (element, attr) as unique - attributes for tree matching. Exposed this option on the command - line, too. - - -2.3 (2019-02-27) ----------------- - -- Added a simple ``xmlpatch`` command and API. - -- Multiple updates to documentation and code style - - -2.2 (2018-10-12) ----------------- - -- A workaround for dealing with top level comments and the xml formatter - - -2.1 (2018-10-03) ----------------- - -- Changed the substitution unicode character area to use the Private Use Area - in BMP(0), to support narrow Python builds - -- Added --unique-attributes argument. - - -2.1b1 (2018-10-01) ------------------- - -- Added options for faster node comparisons. The "middle" option is now - default, it had very few changes in matches, but is much faster. - -- Implemented a Fast Match algorithm for even faster diffing. - -- Speed improvements through caching - -- Fixed a bug where MoveNode actions sometimes was in the wrong order - -- Added an InsertComment action, as comments require different handling, - so it's easier to deal with them this way. You can still use DeleteNode and - UpdateTextIn for them with no special handling. - -- When renaming tags the XMLFormatter will mark them with "diff:rename" - instead of making a new tag and deleting the old. - -- Tags will now be moved first, and updated and renamed later, as the new - tag name or attributes might not be valid in the old location. - - -2.0 (2018-09-25) ----------------- - -- A complete, bottom-up, pure-python rewrite - -- New easy API - -- 100% test coverage - -- New output formats: - - - A new default output format with new actions - - - A format intended to be parseable by anyone parsing the old format. - - - XML with changes marked though tags and attributes - -- xmldiff 2.0 is significantly slower than xmldiff 0.6 or 1.0, - the emphasis so far is on correctness, not speed. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/README.rst new/xmldiff-3.0/README.rst --- old/xmldiff-2.7.0/README.rst 2024-05-13 14:15:38.000000000 +0200 +++ new/xmldiff-3.0/README.rst 2026-06-11 17:00:00.000000000 +0200 @@ -92,6 +92,10 @@ * Thomas Pfitzinger, [email protected] + * Alexandre Detiste + + * Denis Barucic, [email protected] + The diff algorithm is based on "`Change Detection in Hierarchically Structured Information <http://infolab.stanford.edu/c3/papers/html/tdiff3-8/tdiff3-8.html>`_", and the text diff is using Google's ``diff_match_patch`` algorithm. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/docs/source/advanced.rst new/xmldiff-3.0/docs/source/advanced.rst --- old/xmldiff-2.7.0/docs/source/advanced.rst 2024-05-13 14:15:38.000000000 +0200 +++ new/xmldiff-3.0/docs/source/advanced.rst 2026-06-11 17:00:00.000000000 +0200 @@ -18,7 +18,7 @@ >>> left = '<body><p>Old Content</p></body>' >>> right = '<body><p>New Content</p></body>' >>> main.diff_texts(left, right) - [UpdateTextIn(node='/body/p[1]', text='New Content')] + [UpdateTextIn(node='/body/p[1]', text='New Content', oldtext='Old Content')] The ``xml`` formatter will set tags around the text marking it as inserted or deleted: @@ -211,8 +211,8 @@ >>> result = main.diff_texts(left, right, ... diff_options={'fast_match': True}) >>> result - [UpdateTextIn(node='/html/body/p[1]', text='Last paragraph'), - UpdateTextIn(node='/html/body/p[3]', text='The First paragraph')] + [UpdateTextIn(node='/html/body/p[1]', text='Last paragraph', oldtext='The First paragraph'), + UpdateTextIn(node='/html/body/p[3]', text='The First paragraph', oldtext='Last paragraph')] Now we instead got two update actions. This means the resulting HTML is quite different: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/docs/source/api.rst new/xmldiff-3.0/docs/source/api.rst --- old/xmldiff-2.7.0/docs/source/api.rst 2024-05-13 14:15:38.000000000 +0200 +++ new/xmldiff-3.0/docs/source/api.rst 2026-06-11 17:00:00.000000000 +0200 @@ -14,9 +14,9 @@ >>> main.diff_files("../tests/test_data/insert-node.left.html", ... "../tests/test_data/insert-node.right.html", ... diff_options={'F': 0.5, 'ratio_mode': 'fast'}) - [UpdateTextIn(node='/body/div[1]', text=None), + [UpdateTextIn(node='/body/div[1]', text=None, oldtext='\n '), InsertNode(target='/body/div[1]', tag='p', position=0), - UpdateTextIn(node='/body/div/p[1]', text='Simple text')] + UpdateTextIn(node='/body/div/p[1]', text='Simple text', oldtext=None)] Which one you choose depends on if the XML is contained in files, text strings or ``lxml`` trees. @@ -182,9 +182,9 @@ >>> print(main.diff_files("../tests/test_data/insert-node.left.html", ... "../tests/test_data/insert-node.right.html", ... formatter=formatter)) - [update-text, /body/div[1], null] + [update-text, /body/div[1], null, "\n "] [insert, /body/div[1], p, 0] - [update-text, /body/div/p[1], "Simple text"] + [update-text, /body/div/p[1], "Simple text", null] XmlDiffFormatter @@ -405,7 +405,7 @@ >>> left = '<document><node>Content</node></document>' >>> right = '<document><node>New Content</node></document>' >>> main.diff_texts(left, right) - [UpdateTextIn(node='/document/node[1]', text='New Content')] + [UpdateTextIn(node='/document/node[1]', text='New Content', oldtext='Content')] ``UpdateTextAfter(node, name)`` @@ -422,7 +422,7 @@ >>> left = '<document><node>Content</node></document>' >>> right = '<document><node>Content</node>Trailing text</document>' >>> main.diff_texts(left, right) - [UpdateTextAfter(node='/document/node[1]', text='Trailing text')] + [UpdateTextAfter(node='/document/node[1]', text='Trailing text', oldtext=None)] ``InsertComment(target, position, text)`` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/pyproject.toml new/xmldiff-3.0/pyproject.toml --- old/xmldiff-2.7.0/pyproject.toml 1970-01-01 01:00:00.000000000 +0100 +++ new/xmldiff-3.0/pyproject.toml 2026-06-11 17:00:00.000000000 +0200 @@ -0,0 +1,66 @@ +[build-system] +requires = ["setuptools>=61.2"] +build-backend = "setuptools.build_meta" + +[project] +name = "xmldiff" +version = "3.0" +description = "Creates diffs of XML files" +readme = "README.rst" +license = { text = "MIT" } +requires-python = ">=3.8" +authors = [ + { name = "Lennart Regebro", email = "[email protected]" }, +] +keywords = [ + "diff", + "html", + "xml", +] +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "Intended Audience :: End Users/Desktop", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: Implementation :: PyPy", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", + "Programming Language :: Python :: 3.15", + "Topic :: Text Processing :: Markup :: XML", + "License :: OSI Approved :: MIT License", +] +dependencies = [ + "lxml>=3.1.0", +] + +[project.optional-dependencies] +devenv = [ + "ruff", + "pyroma>=5.0b1", + "zest.releaser[recommended]", +] + +[project.scripts] +xmldiff = "xmldiff.main:diff_command" +xmlpatch = "xmldiff.main:patch_command" + +[project.urls] +Homepage = "https://github.com/Shoobx/xmldiff" +"Source Code" = "https://github.com/Shoobx/xmldiff" + +[tool.setuptools] +packages = ["xmldiff"] +include-package-data = true +zip-safe = false + +[tool.ruff] +exclude = ["xmldiff/diff_match_patch.py"] + +[tool.zest.releaser] +create-wheel = true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/setup.cfg new/xmldiff-3.0/setup.cfg --- old/xmldiff-2.7.0/setup.cfg 2024-05-13 14:15:38.185385700 +0200 +++ new/xmldiff-3.0/setup.cfg 2026-06-11 17:00:01.086637300 +0200 @@ -1,77 +1,3 @@ -[metadata] -name = xmldiff -version = 2.7.0 -description = Creates diffs of XML files -long_description = file: README.rst, CHANGES.rst -classifiers = - Development Status :: 4 - Beta - Intended Audience :: Developers - Intended Audience :: End Users/Desktop - Topic :: Text Processing :: Markup :: XML - License :: OSI Approved :: MIT License - Operating System :: OS Independent - Programming Language :: Python - Programming Language :: Python :: 3 - Programming Language :: Python :: 3.8 - Programming Language :: Python :: 3.9 - Programming Language :: Python :: 3.10 - Programming Language :: Python :: 3.11 - Programming Language :: Python :: 3.12 - Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: Implementation :: PyPy -keywords = xml, html, diff -author = Lennart Regebro -author_email = [email protected] -url = https://github.com/Shoobx/xmldiff -license = MIT -project_urls = - Source Code = https://github.com/Shoobx/xmldiff - -[options] -python_requires = >=3.8 -zip_safe = True -include_package_data = True -packages = find: -package_dir = - = . -install_requires = - setuptools - lxml>=3.1.0 - -[options.packages.find] -where = . -exclude = - doc - tests - -[options.extras_require] -devenv = - black - coverage - flake8 - zest.releaser[recommended] - -[options.entry_points] -console_scripts = - xmldiff = xmldiff.main:diff_command - xmlpatch = xmldiff.main:patch_command - -[flake8] -max-line-length = 120 -exclude = - xmldiff/*diff_match_patch*.py - -[tool:pytest] -testpaths = - tests - -[check-manifest] -ignore = - .pre-commit-config.yaml - -[zest.releaser] -create-wheel = yes - [egg_info] tag_build = tag_date = 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/setup.py new/xmldiff-3.0/setup.py --- old/xmldiff-2.7.0/setup.py 2024-05-13 14:15:38.000000000 +0200 +++ new/xmldiff-3.0/setup.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,3 +0,0 @@ -from setuptools import setup - -setup() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/tests/test_diff.py new/xmldiff-3.0/tests/test_diff.py --- old/xmldiff-2.7.0/tests/test_diff.py 2024-05-13 14:15:38.000000000 +0200 +++ new/xmldiff-3.0/tests/test_diff.py 2026-06-11 17:00:00.000000000 +0200 @@ -966,6 +966,24 @@ ], ) + def test_best_match_no_double_match(self): + left = """\ +<a> + <p>x<b>xy</b></p> +</a> +""" + right = """\ +<a> + <p>x</p> +</a> +""" + matches = self._match(left, right, best_match=True) + # All matched paths should be exactly equal, + # and /a/p/b should not be matched with anything + for lpath, rpath in matches: + self.assertEqual(lpath, rpath) + self.assertNotIn("/a/p/b", [m[0] for m in matches]) + class UpdateNodeTests(unittest.TestCase): """Testing only the update phase of the diffing""" @@ -1019,8 +1037,8 @@ RenameAttrib("/root/node[1]", "attr1", "attr4"), InsertAttrib("/root/node[1]", "attr5", "new"), DeleteAttrib("/root/node[1]", "attr0"), - UpdateTextIn("/root/node[1]", "The new text"), - UpdateTextAfter("/root/node[1]", "Also a tail!"), + UpdateTextIn("/root/node[1]", "The new text", "The contained text"), + UpdateTextAfter("/root/node[1]", "Also a tail!", "And a tail!"), ], ) @@ -1263,8 +1281,9 @@ InsertAttrib("/document/story/app:section[4]/app:term[1]", "set", "ol"), InsertNode("/document/story/app:section[4]", "para", 1), UpdateTextIn( - "/document/story/app:section[1]/para[2]/" "app:placeholder[1]", + "/document/story/app:section[1]/para[2]/app:placeholder[1]", "consectetur", + "vestibulum", ), InsertNode( "/document/story/app:section[4]/para[1]", @@ -1305,14 +1324,30 @@ "/document/story/app:section[4]/para/app:placeholder[1]", "asellus congue accumsan tempor. Donec vel risus se", ), - UpdateTextIn("/document/story/app:section[5]/para/app:ref[1]", "4"), - UpdateTextIn("/document/story/app:section[6]/para/app:ref[1]", "5"), - UpdateTextIn("/document/story/app:section[7]/para/app:ref[1]", "6"), - UpdateTextIn("/document/story/app:section[8]/para/app:ref[1]", "7"), - UpdateTextIn("/document/story/app:section[9]/para/app:ref[1]", "8"), - UpdateTextIn("/document/story/app:section[10]/para/app:ref[1]", "9"), - UpdateTextIn("/document/story/app:section[11]/para/app:ref[1]", "10"), - UpdateTextIn("/document/story/app:section[12]/para/app:ref[1]", "11"), + UpdateTextIn( + "/document/story/app:section[5]/para/app:ref[1]", "4", "3" + ), + UpdateTextIn( + "/document/story/app:section[6]/para/app:ref[1]", "5", "4" + ), + UpdateTextIn( + "/document/story/app:section[7]/para/app:ref[1]", "6", "5" + ), + UpdateTextIn( + "/document/story/app:section[8]/para/app:ref[1]", "7", "6" + ), + UpdateTextIn( + "/document/story/app:section[9]/para/app:ref[1]", "8", "7" + ), + UpdateTextIn( + "/document/story/app:section[10]/para/app:ref[1]", "9", "8" + ), + UpdateTextIn( + "/document/story/app:section[11]/para/app:ref[1]", "10", "9" + ), + UpdateTextIn( + "/document/story/app:section[12]/para/app:ref[1]", "11", "10" + ), InsertNode("/document/story/app:section[4]/para/u[1]", "b", 0), UpdateTextIn( "/document/story/app:section[4]/para/u/b[1]", "ger nec ferme" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/tests/test_formatting.py new/xmldiff-3.0/tests/test_formatting.py --- old/xmldiff-2.7.0/tests/test_formatting.py 2024-05-13 14:15:38.000000000 +0200 +++ new/xmldiff-3.0/tests/test_formatting.py 2026-06-11 17:00:00.000000000 +0200 @@ -63,7 +63,7 @@ replacer.do_element(element) self.assertEqual( - element.text, "This \ue007 a \ue008 with \ue00aformatted" "\ue009 text." + element.text, "This \ue007 a \ue008 with \ue00aformatted\ue009 text." ) replacer.undo_element(element) @@ -79,7 +79,7 @@ replacer.do_element(element) self.assertEqual( - element.text, "This is \ue008doubly \ue00aformatted\ue009" "\ue007 text." + element.text, "This is \ue008doubly \ue00aformatted\ue009\ue007 text." ) replacer.undo_element(element) @@ -153,7 +153,7 @@ # self.assertEqual( - element.text, "This \uf906 a \uf907 with \uf909some" "\uf908 text." + element.text, "This \uf906 a \uf907 with \uf909some\uf908 text." ) try: @@ -172,8 +172,7 @@ # This should raise an error on a narrow build self.assertEqual( element.text, - "This \U00010006 a \U00010007 with \U00010009some" - "\U00010008 text.", + "This \U00010006 a \U00010007 with \U00010009some\U00010008 text.", ) except ValueError: if sys.maxunicode > 0x10000: @@ -227,7 +226,7 @@ def test_insert_attr(self): left = "<document><node>We need more text</node></document>" action = actions.InsertAttrib("/document/node", "attr", "val") - expected = START + ' attr="val" diff:add-attr="attr">' "We need more text" + END + expected = START + ' attr="val" diff:add-attr="attr">We need more text' + END self._format_test(left, action, expected) @@ -243,7 +242,7 @@ # renamed: left = '<document><node attr="val">Text</node></document>' action = actions.RenameAttrib("/document/node", "attr", "bottr") - expected = START + ' bottr="val" diff:rename-attr="attr:bottr"' ">Text" + END + expected = START + ' bottr="val" diff:rename-attr="attr:bottr">Text' + END self._format_test(left, action, expected) @@ -271,14 +270,14 @@ def test_rename_node(self): left = "<document><node><para>Content</para>Tail</node></document>" action = actions.RenameNode("/document/node[1]/para[1]", "newtag") - expected = START + '><newtag diff:rename="para">Content' "</newtag>Tail" + END + expected = START + '><newtag diff:rename="para">Content</newtag>Tail' + END self._format_test(left, action, expected) def test_update_attr(self): left = '<document><node attr="val"/></document>' action = actions.UpdateAttrib("/document/node", "attr", "newval") - expected = START + ' attr="newval" diff:update-attr="attr:val"/>' "</document>" + expected = START + ' attr="newval" diff:update-attr="attr:val"/></document>' self._format_test(left, action, expected) @@ -302,7 +301,7 @@ def test_update_text_after_1(self): left = "<document><node/><node/></document>" action = actions.UpdateTextAfter("/document/node[1]", "Text") - expected = START + "/><diff:insert>Text</diff:insert>" "<node/></document>" + expected = START + "/><diff:insert>Text</diff:insert><node/></document>" self._format_test(left, action, expected) @@ -337,7 +336,7 @@ def test_replace_text_after_1(self): left = "<document><node/><node/></document>" action = actions.UpdateTextAfter("/document/node[1]", "Text") - expected = START + "/><diff:insert>Text</diff:insert>" "<node/></document>" + expected = START + "/><diff:insert>Text</diff:insert><node/></document>" self._format_test(left, action, expected, use_replace=True) @@ -381,7 +380,7 @@ def test_del_text(self): action = actions.UpdateTextIn("/document/node", None) - expected = "[update-text, /document/node, null]" + expected = "[update-text, /document/node, null, null]" self._format_test(action, expected) def test_insert_attr(self): @@ -430,21 +429,25 @@ def test_update_text_in(self): action = actions.UpdateTextIn("/document/node", "Text") - expected = '[update-text, /document/node, "Text"]' + expected = '[update-text, /document/node, "Text", null]' self._format_test(action, expected) action = actions.UpdateTextIn("/document/node", 'Also a bit of text, "rick"') - expected = "[update-text, /document/node, " '"Also a bit of text, \\"rick\\""]' + expected = ( + '[update-text, /document/node, "Also a bit of text, \\"rick\\"", null]' + ) self._format_test(action, expected) def test_update_text_after_1(self): action = actions.UpdateTextAfter("/document/node[1]", "Text") - expected = '[update-text-after, /document/node[1], "Text"]' + expected = '[update-text-after, /document/node[1], "Text", null]' self._format_test(action, expected) def test_update_text_after_2(self): action = actions.UpdateTextAfter("/document/node", "Also a bit of text, rick") - expected = "[update-text-after, /document/node, " '"Also a bit of text, rick"]' + expected = ( + '[update-text-after, /document/node, "Also a bit of text, rick", null]' + ) self._format_test(action, expected) def test_insert_comment(self): @@ -511,7 +514,7 @@ action = actions.UpdateTextIn("/document/node", 'Also a bit of text, "rick"') expected = ( - "[update, /document/node/text()[1], " '"Also a bit of text, \\"rick\\""]' + '[update, /document/node/text()[1], "Also a bit of text, \\"rick\\""]' ) self._format_test(action, expected) @@ -522,7 +525,7 @@ def test_update_text_after_2(self): action = actions.UpdateTextAfter("/document/node", "Also a bit of text, rick") - expected = "[update, /document/node/text()[2], " '"Also a bit of text, rick"]' + expected = '[update, /document/node/text()[2], "Also a bit of text, rick"]' self._format_test(action, expected) def test_all_actions(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/tests/test_main.py new/xmldiff-3.0/tests/test_main.py --- old/xmldiff-2.7.0/tests/test_main.py 2024-05-13 14:15:38.000000000 +0200 +++ new/xmldiff-3.0/tests/test_main.py 2026-06-11 17:00:00.000000000 +0200 @@ -44,7 +44,7 @@ with open(LEFT_FILE, "rb") as infile: with open(RIGHT_FILE, "rb") as infile: # Give something else, and it fails: - with self.assertRaises(ValueError): + with self.assertRaises(TypeError): main.diff_texts(infile, infile) def test_api_diff_trees(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/tests/test_patch.py new/xmldiff-3.0/tests/test_patch.py --- old/xmldiff-2.7.0/tests/test_patch.py 2024-05-13 14:15:38.000000000 +0200 +++ new/xmldiff-3.0/tests/test_patch.py 2026-06-11 17:00:00.000000000 +0200 @@ -23,12 +23,10 @@ class PatcherTests(unittest.TestCase): - patcher = Patcher() - def _test(self, start, action, end): - tree = etree.fromstring(start) - self.patcher.handle_action(action, tree) - self.assertEqual(etree.tounicode(tree), end) + patcher = Patcher() + result = patcher.patch([action], etree.fromstring(start)) + self.assertEqual(etree.tounicode(result), end) def test_delete_node(self): self._test("<root><deleteme/></root>", DeleteNode("/root/deleteme"), "<root/>") @@ -54,6 +52,13 @@ "<root><anode/><moveme/></root>", ) + def test_move_node_with_namespace(self): + self._test( + '<root xmlns:ns="http://example.com/ns"><ns:src><moveme/></ns:src><ns:dst/></root>', + MoveNode("/root/ns:src/moveme", "/root/ns:dst", 0), + '<root xmlns:ns="http://example.com/ns"><ns:src/><ns:dst><moveme/></ns:dst></root>', + ) + def test_update_text_in(self): self._test( "<root><anode/></root>", @@ -253,3 +258,13 @@ expected = f.read() # lxml.etree.parse() will strip ending whitespace self.assertEqual(result, expected.rstrip()) + + def test_parse_commas(self): + parser = DiffParser() + + # There should be able to be a comma in the value + actions = list(parser.parse('[update-text-after, /root/anode[1], "foo,bar"]')) + self.assertEqual( + actions, + [UpdateTextAfter(node="/root/anode[1]", text="foo,bar", oldtext=None)], + ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/xmldiff/actions.py new/xmldiff-3.0/xmldiff/actions.py --- old/xmldiff-2.7.0/xmldiff/actions.py 2024-05-13 14:15:38.000000000 +0200 +++ new/xmldiff-3.0/xmldiff/actions.py 2026-06-11 17:00:00.000000000 +0200 @@ -6,8 +6,8 @@ RenameNode = namedtuple("RenameNode", "node tag") MoveNode = namedtuple("MoveNode", "node target position") -UpdateTextIn = namedtuple("UpdateTextIn", "node text") -UpdateTextAfter = namedtuple("UpdateTextAfter", "node text") +UpdateTextIn = namedtuple("UpdateTextIn", "node text oldtext", defaults=[None]) +UpdateTextAfter = namedtuple("UpdateTextAfter", "node text oldtext", defaults=[None]) UpdateAttrib = namedtuple("UpdateAttrib", "node name value") DeleteAttrib = namedtuple("DeleteAttrib", "node name") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/xmldiff/diff.py new/xmldiff-3.0/xmldiff/diff.py --- old/xmldiff-2.7.0/xmldiff/diff.py 2024-05-13 14:15:38.000000000 +0200 +++ new/xmldiff-3.0/xmldiff/diff.py 2026-06-11 17:00:00.000000000 +0200 @@ -65,9 +65,7 @@ right = right.getroot() if not (etree.iselement(left) and etree.iselement(right)): - raise TypeError( - "The 'left' and 'right' parameters must be " "lxml Elements." - ) + raise TypeError("The 'left' and 'right' parameters must be lxml Elements.") # Left gets modified as a part of the diff, deepcopy it first. self.left = deepcopy(left) @@ -157,10 +155,16 @@ unmatched_lnodes.append((lnode, match_node, max_match)) # unmatched_lnodes.append(lnode) + # Sort by descending match quality so better matches get + # priority, and remove matched rnodes to prevent multiple + # left nodes from matching the same right node. lnodes = [] - for lnode, rnode, max_match in unmatched_lnodes: + for lnode, rnode, max_match in sorted( + unmatched_lnodes, key=lambda x: -x[2] + ): if max_match >= self.F and rnode in rnodes: self.append_match(lnode, rnode, max_match) + rnodes.remove(rnode) else: lnodes.append(lnode) @@ -334,11 +338,11 @@ left_xpath = utils.getpath(left) if left.text != right.text: - yield actions.UpdateTextIn(left_xpath, right.text) + yield actions.UpdateTextIn(left_xpath, right.text, left.text) left.text = right.text if left.tail != right.tail: - yield actions.UpdateTextAfter(left_xpath, right.tail) + yield actions.UpdateTextAfter(left_xpath, right.tail, left.tail) left.tail = right.tail def find_pos(self, node): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/xmldiff/formatting.py new/xmldiff-3.0/xmldiff/formatting.py --- old/xmldiff-2.7.0/xmldiff/formatting.py 2024-05-13 14:15:38.000000000 +0200 +++ new/xmldiff-3.0/xmldiff/formatting.py 2026-06-11 17:00:00.000000000 +0200 @@ -766,10 +766,20 @@ return ("update-attribute", action.node, action.name, json.dumps(action.value)) def _handle_UpdateTextIn(self, action): - return "update-text", action.node, json.dumps(action.text) + return ( + "update-text", + action.node, + json.dumps(action.text), + json.dumps(action.oldtext), + ) def _handle_UpdateTextAfter(self, action): - return "update-text-after", action.node, json.dumps(action.text) + return ( + "update-text-after", + action.node, + json.dumps(action.text), + json.dumps(action.oldtext), + ) def _handle_RenameNode(self, action): return "rename", action.node, action.tag diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/xmldiff/main.py new/xmldiff-3.0/xmldiff/main.py --- old/xmldiff-2.7.0/xmldiff/main.py 2024-05-13 14:15:38.000000000 +0200 +++ new/xmldiff-3.0/xmldiff/main.py 2026-06-11 17:00:00.000000000 +0200 @@ -1,4 +1,5 @@ """All major API points and command-line tools""" + from importlib import metadata from argparse import ArgumentParser, ArgumentTypeError diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/xmldiff/patch.py new/xmldiff-3.0/xmldiff/patch.py --- old/xmldiff-2.7.0/xmldiff/patch.py 2024-05-13 14:15:38.000000000 +0200 +++ new/xmldiff-3.0/xmldiff/patch.py 2026-06-11 17:00:00.000000000 +0200 @@ -1,10 +1,14 @@ +import re + from copy import deepcopy -from csv import reader from json import loads from lxml import etree from xmldiff import actions +DIFF_SPLIT = re.compile('(?:"[^"]*"|[^, ])+|(?<![^,])(?![^,])') + + class Patcher: @property def nsmap(self): @@ -47,7 +51,7 @@ def _handle_MoveNode(self, action, tree): node = tree.xpath(action.node, namespaces=self.nsmap)[0] node.getparent().remove(node) - target = tree.xpath(action.target)[0] + target = tree.xpath(action.target, namespaces=self.nsmap)[0] target.insert(action.position, node) def _handle_UpdateTextIn(self, action, tree): @@ -119,7 +123,7 @@ line = line[1:-1] # Split the line on commas (ignoring commas in quoted strings) and # strip extraneous spaces. The first is the action, the rest params. - parts = [x.strip() for x in next(reader([line]))] + parts = DIFF_SPLIT.findall(line) action = parts[0] params = parts[1:] # Get the method, and return the result of calling it @@ -138,10 +142,10 @@ def _handle_move(self, node, target, position): return actions.MoveNode(node, target, int(position)) - def _handle_update_text(self, node, text): + def _handle_update_text(self, node, text, oldtext=None): return actions.UpdateTextIn(node, loads(text)) - def _handle_update_text_after(self, node, text): + def _handle_update_text_after(self, node, text, oldtext=None): return actions.UpdateTextAfter(node, loads(text)) def _handle_update_attribute(self, node, name, value): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/xmldiff/utils.py new/xmldiff-3.0/xmldiff/utils.py --- old/xmldiff-2.7.0/xmldiff/utils.py 2024-05-13 14:15:38.000000000 +0200 +++ new/xmldiff-3.0/xmldiff/utils.py 2026-06-11 17:00:00.000000000 +0200 @@ -1,5 +1,6 @@ import re +from collections import deque from operator import eq # This namespace is reserved for lxml internal use, which only @@ -23,10 +24,10 @@ def breadth_first_traverse(node): # First yield the root node - queue = [node] + queue = deque([node]) while queue: - item = queue.pop(0) + item = queue.popleft() yield item queue.extend(item.getchildren()) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/xmldiff.egg-info/PKG-INFO new/xmldiff-3.0/xmldiff.egg-info/PKG-INFO --- old/xmldiff-2.7.0/xmldiff.egg-info/PKG-INFO 2024-05-13 14:15:38.000000000 +0200 +++ new/xmldiff-3.0/xmldiff.egg-info/PKG-INFO 2026-06-11 17:00:01.000000000 +0200 @@ -1,36 +1,35 @@ Metadata-Version: 2.1 Name: xmldiff -Version: 2.7.0 +Version: 3.0 Summary: Creates diffs of XML files -Home-page: https://github.com/Shoobx/xmldiff -Author: Lennart Regebro -Author-email: [email protected] +Author-email: Lennart Regebro <[email protected]> License: MIT +Project-URL: Homepage, https://github.com/Shoobx/xmldiff Project-URL: Source Code, https://github.com/Shoobx/xmldiff -Keywords: xml,html,diff +Keywords: diff,html,xml Classifier: Development Status :: 4 - Beta Classifier: Intended Audience :: Developers Classifier: Intended Audience :: End Users/Desktop -Classifier: Topic :: Text Processing :: Markup :: XML -Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.8 -Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 -Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Programming Language :: Python :: 3.13 +Classifier: Programming Language :: Python :: 3.14 +Classifier: Programming Language :: Python :: 3.15 +Classifier: Topic :: Text Processing :: Markup :: XML +Classifier: License :: OSI Approved :: MIT License Requires-Python: >=3.8 +Description-Content-Type: text/x-rst License-File: LICENSE.txt -Requires-Dist: setuptools Requires-Dist: lxml>=3.1.0 Provides-Extra: devenv -Requires-Dist: black; extra == "devenv" -Requires-Dist: coverage; extra == "devenv" -Requires-Dist: flake8; extra == "devenv" +Requires-Dist: ruff; extra == "devenv" +Requires-Dist: pyroma>=5.0b1; extra == "devenv" Requires-Dist: zest.releaser[recommended]; extra == "devenv" xmldiff @@ -127,158 +126,10 @@ * Thomas Pfitzinger, [email protected] + * Alexandre Detiste + + * Denis Barucic, [email protected] + The diff algorithm is based on "`Change Detection in Hierarchically Structured Information <http://infolab.stanford.edu/c3/papers/html/tdiff3-8/tdiff3-8.html>`_", and the text diff is using Google's ``diff_match_patch`` algorithm. - -Changes -======= - -2.7.0 (2024-05-13) ------------------- - -- Changed the comparison to make accurate and standard more accurate, - although fast gets less accurate as a result. - -- Changed usage of deprecated `pkg_resources` package to `importlib.metadata`. - -- A `use_replace` flag was added to the `XMLFormatter` by Thomas Pfitzinger. - It changes text replacement from delete and insert tags to a replace tag. - It's not currently accessaible thtough the CLI, the question is it is better - to add a new formatter name, or an option to pass in formatter flags. - - - Added option to XMLFormatter to use replace tags - - in _make_diff_tags after diffing, neighboring delete/insert diffs are joined to a replace tag - - the deleted text is added as an attribute ("old-text") - - the inserted text is the element's text - -2.6.3 (2023-05-21) ------------------- - -- And there was a namespace bug in the patch as well. #118 - - -2.6.2 (2023-05-21) ------------------- - -- Solved an error in the xmlformatter when using default namespaces. #89 - - -2.6.1 (2023-04-05) ------------------- - -- #108: Fixed an error that happens if using namespaces like ns0 or ns1. - - -2.6 (2023-04-03) ----------------- - -- Added `InsertNamespace` and `DeleteNamespace` actions for better handling - of changing namespaces. Should improve any "Unknown namespace prefix" - errors. Changing the URI of a a namespace prefix is not supported, and will - raise an error. - -2.6b1 (2023-01-12) ------------------- - -- Used geometric mean for the node_ratio, for better handling of simple nodes. - -- Added an experimental --best-match method that is slower, but generate - smaller diffs when you have many nodes that are similar. - -- The -F argument now also affects the --fast-match stage. - - -2.5 (2023-01-11) ----------------- - -- Make it possible to adjust the attributes considered when comparing nodes. - -- Python versions 3.7 to 3.11 are now supported. - -- Improved node matching method, that puts more emphasis similarities than - differences when weighing attributes vs children. - -- Added a parameter to return error code 1 when there are differences between the files - -- Added a parameter for ignoring attributes in comparison. - -- Solved a bug in xmlpatch in certain namespace situations. - -- Added a --diff-encoding parameter to xmlpatch, to support diff-files that are - not in your system default encoding. - - -2.4 (2019-10-09) ----------------- - -- Added an option to pass pairs of (element, attr) as unique - attributes for tree matching. Exposed this option on the command - line, too. - - -2.3 (2019-02-27) ----------------- - -- Added a simple ``xmlpatch`` command and API. - -- Multiple updates to documentation and code style - - -2.2 (2018-10-12) ----------------- - -- A workaround for dealing with top level comments and the xml formatter - - -2.1 (2018-10-03) ----------------- - -- Changed the substitution unicode character area to use the Private Use Area - in BMP(0), to support narrow Python builds - -- Added --unique-attributes argument. - - -2.1b1 (2018-10-01) ------------------- - -- Added options for faster node comparisons. The "middle" option is now - default, it had very few changes in matches, but is much faster. - -- Implemented a Fast Match algorithm for even faster diffing. - -- Speed improvements through caching - -- Fixed a bug where MoveNode actions sometimes was in the wrong order - -- Added an InsertComment action, as comments require different handling, - so it's easier to deal with them this way. You can still use DeleteNode and - UpdateTextIn for them with no special handling. - -- When renaming tags the XMLFormatter will mark them with "diff:rename" - instead of making a new tag and deleting the old. - -- Tags will now be moved first, and updated and renamed later, as the new - tag name or attributes might not be valid in the old location. - - -2.0 (2018-09-25) ----------------- - -- A complete, bottom-up, pure-python rewrite - -- New easy API - -- 100% test coverage - -- New output formats: - - - A new default output format with new actions - - - A format intended to be parseable by anyone parsing the old format. - - - XML with changes marked though tags and attributes - -- xmldiff 2.0 is significantly slower than xmldiff 0.6 or 1.0, - the emphasis so far is on correctness, not speed. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/xmldiff.egg-info/SOURCES.txt new/xmldiff-3.0/xmldiff.egg-info/SOURCES.txt --- old/xmldiff-2.7.0/xmldiff.egg-info/SOURCES.txt 2024-05-13 14:15:38.000000000 +0200 +++ new/xmldiff-3.0/xmldiff.egg-info/SOURCES.txt 2026-06-11 17:00:01.000000000 +0200 @@ -1,22 +1,13 @@ .coveragerc .coveralls.yml +.pre-commit-config.yaml .travis.yml CHANGES.rst -CHANGES.txt LICENSE.txt MANIFEST.in Makefile README.rst -setup.cfg -setup.py -./xmldiff/__init__.py -./xmldiff/actions.py -./xmldiff/diff.py -./xmldiff/diff_match_patch.py -./xmldiff/formatting.py -./xmldiff/main.py -./xmldiff/patch.py -./xmldiff/utils.py +pyproject.toml docs/Makefile docs/make.bat docs/requirements.txt @@ -59,10 +50,18 @@ tests/test_data/sbt_template.expected.xml tests/test_data/sbt_template.left.xml tests/test_data/sbt_template.right.xml +xmldiff/__init__.py +xmldiff/actions.py +xmldiff/diff.py +xmldiff/diff_match_patch.py +xmldiff/formatting.py +xmldiff/main.py +xmldiff/patch.py +xmldiff/utils.py xmldiff.egg-info/PKG-INFO xmldiff.egg-info/SOURCES.txt xmldiff.egg-info/dependency_links.txt xmldiff.egg-info/entry_points.txt +xmldiff.egg-info/not-zip-safe xmldiff.egg-info/requires.txt -xmldiff.egg-info/top_level.txt -xmldiff.egg-info/zip-safe \ No newline at end of file +xmldiff.egg-info/top_level.txt \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/xmldiff.egg-info/not-zip-safe new/xmldiff-3.0/xmldiff.egg-info/not-zip-safe --- old/xmldiff-2.7.0/xmldiff.egg-info/not-zip-safe 1970-01-01 01:00:00.000000000 +0100 +++ new/xmldiff-3.0/xmldiff.egg-info/not-zip-safe 2026-06-11 17:00:01.000000000 +0200 @@ -0,0 +1 @@ + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/xmldiff.egg-info/requires.txt new/xmldiff-3.0/xmldiff.egg-info/requires.txt --- old/xmldiff-2.7.0/xmldiff.egg-info/requires.txt 2024-05-13 14:15:38.000000000 +0200 +++ new/xmldiff-3.0/xmldiff.egg-info/requires.txt 2026-06-11 17:00:01.000000000 +0200 @@ -1,8 +1,6 @@ -setuptools lxml>=3.1.0 [devenv] -black -coverage -flake8 +ruff +pyroma>=5.0b1 zest.releaser[recommended] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xmldiff-2.7.0/xmldiff.egg-info/zip-safe new/xmldiff-3.0/xmldiff.egg-info/zip-safe --- old/xmldiff-2.7.0/xmldiff.egg-info/zip-safe 2024-05-13 14:15:38.000000000 +0200 +++ new/xmldiff-3.0/xmldiff.egg-info/zip-safe 1970-01-01 01:00:00.000000000 +0100 @@ -1 +0,0 @@ -
