Commit 10e324fe authored by Jérome Perrin's avatar Jérome Perrin

Modernize and add python3 support

This had a dependency on PyXML, which does not support python3 (actually
does not even support python2.7 byt we have been using a patched version).
To drop this dependency, we use lxml sax interface directly.

Modernize several things:
 - enable the doctest
 - use lxml xml comparison to compare XML
 - use python3 compatible syntax
parent 7587ba0a
History
=======
0.5 (unreleased)
0.5 (2022-09-14)
----------------
- Support python3 and python2.7 by dropping dependency on PyXML
0.4 (2010-01-21)
----------------
......
include *.py
include *.rst
include MANIFEST.in
......@@ -4,16 +4,18 @@ Introduction
Apply xupdate diff on XML documents.
Installation
============
Testing
=======
python setup.py install
To run tests::
python -m unittest discover src
Testing
=======
or, using ``zc.buildout`` and ``zope.testrunner``::
buildout
./bin/test
python setup.py test
Usage
=====
......
......@@ -5,4 +5,3 @@ parts = test
[test]
recipe = zc.recipe.testrunner
eggs = xupdate_processor
initialization = from shutil import copy2; from glob import glob; [copy2(f, '../../parts/test/%s' % f.split('/')[-1]) for f in glob('../../*.xml')]
\ No newline at end of file
......@@ -3,15 +3,16 @@
from setuptools import setup, find_packages
version = '0.4'
version = '0.5'
def read(name):
return open(name).read()
with open(name) as f:
return f.read()
long_description=(
read('README.txt')
read('README.rst')
+ '\n' +
read('CHANGES.txt')
read('CHANGES.rst')
)
setup(name="xupdate-processor",
......@@ -20,17 +21,16 @@ setup(name="xupdate-processor",
long_description=long_description,
author="Nicolas DELABY",
author_email="nicolas@nexedi.com",
url="http://nexedi.com",
url="https://lab.nexedi.com/nexedi/xupdate_processor",
license="GPL",
packages=find_packages('src'),
package_dir={'': 'src'},
scripts=["xuproc"],
install_requires=['PyXML', 'lxml', 'erp5diff >= 0.7'],
install_requires=['six', 'lxml', 'erp5diff >= 0.7'],
classifiers=['License :: OSI Approved :: GNU General Public License (GPL)',
'Operating System :: OS Independent',
'Topic :: Text Processing :: Markup :: XML',
'Topic :: Utilities'],
include_package_data=True,
zip_safe=False,
test_suite='xupdate_processor',
)
# -*- coding: utf-8 -*-
from xuproc import applyXUpdate
from __future__ import absolute_import
from __future__ import print_function
from .xuproc import applyXUpdate
from lxml import etree
import sys
def main():
from optparse import OptionParser
......@@ -10,12 +13,13 @@ def main():
options, args = parser.parse_args()
if len(args) != 2:
print parser.print_help()
parser.print_help()
parser.error('incorrect number of arguments')
sys.exit(2)
xu_xml_name = args[0]
doc_xml_name = args[1]
print etree.tostring(applyXUpdate(xml_xu_filename=xu_xml_name,
print(etree.tostring(applyXUpdate(xml_xu_filename=xu_xml_name,
xml_doc_filename=doc_xml_name),
pretty_print=True)
pretty_print=True))
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from lxml import etree
from lxml.etree import Element, _ElementTree, ProcessingInstruction, Comment
from xml.sax.handler import ContentHandler
......
# -*- coding: utf-8 -*-
from __future__ import absolute_import
import unittest
import pkg_resources
from io import BytesIO
import doctest
from ERP5Diff import ERP5Diff
import xupdate_processor
from xupdate_processor import applyXUpdate
import lxml.doctestcompare
from lxml import etree
from cStringIO import StringIO
class TestXUpdateProcessor(unittest.TestCase):
"""
......@@ -17,9 +20,14 @@ class TestXUpdateProcessor(unittest.TestCase):
"""
result_tree = applyXUpdate(xml_xu_string=xml_xu_string,
xml_doc_string=xml_doc_string)
result_string = etree.tostring(result_tree, pretty_print=True)
self.assertEquals(result_string, expected_result_string,
'\n%s\n\n%s' % (result_string, expected_result_string))
result_string = etree.tostring(result_tree, pretty_print=True, encoding="unicode")
checker = lxml.doctestcompare.LXMLOutputChecker()
if not checker.check_output(expected_result_string, result_string, 0):
self.fail(
checker.output_difference(
doctest.Example("", expected_result_string),
result_string,
0))
def test_textNodes(self):
......@@ -683,13 +691,15 @@ class TestXUpdateProcessor(unittest.TestCase):
result_tree = applyXUpdate(xml_xu_filename=xu_filename,
xml_doc_filename=orig_filename)
destination_tree = etree.parse(destination_filename)
destination_buffer = StringIO()
result_buffer = StringIO()
destination_buffer = BytesIO()
result_buffer = BytesIO()
destination_tree.write_c14n(destination_buffer)
destination_buffer.seek(0)
result_tree.write_c14n(result_buffer)
result_buffer.seek(0)
erp5diff = ERP5Diff()
erp5diff.compare(result_buffer.getvalue(), destination_buffer.getvalue())
self.assertEquals(etree.tostring(erp5diff._result),
erp5diff.compare(result_buffer, destination_buffer)
self.assertEqual(etree.tostring(erp5diff._result, encoding='unicode'),
'<xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0"/>')
def test_OOofiles2(self):
......@@ -706,16 +716,23 @@ class TestXUpdateProcessor(unittest.TestCase):
'tests/dest_ooo_2.xml')
result_tree = applyXUpdate(xml_xu_filename=xu_filename, xml_doc_filename=orig_filename)
destination_tree = etree.parse(destination_filename)
destination_buffer = StringIO()
result_buffer = StringIO()
destination_buffer = BytesIO()
result_buffer = BytesIO()
destination_tree.write_c14n(destination_buffer)
destination_buffer.seek(0)
result_tree.write_c14n(result_buffer)
result_buffer.seek(0)
erp5diff = ERP5Diff()
erp5diff.compare(result_buffer.getvalue(), destination_buffer.getvalue())
self.assertEquals(etree.tostring(erp5diff._result),
erp5diff.compare(result_buffer, destination_buffer)
self.assertEqual(etree.tostring(erp5diff._result, encoding='unicode'),
'<xupdate:modifications xmlns:xupdate="http://www.xmldb.org/xupdate" version="1.0"/>')
def load_tests(loader, tests, ignore):
tests.addTests(doctest.DocFileSuite("test_doctest.txt"))
return tests
if __name__ == '__main__':
unittest.main()
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import xml.sax
from __future__ import absolute_import
from __future__ import print_function
import lxml.sax
from lxml import etree
from cStringIO import StringIO
from content_handler import XUpdateHandler
from six import StringIO
from .content_handler import XUpdateHandler
def applyXUpdate(xml_xu_file=None,
xml_doc_file=None,
......@@ -26,16 +28,12 @@ def applyXUpdate(xml_xu_file=None,
if xml_doc_filename:
xml_doc = xml_doc_filename
original_tree = etree.parse(xml_doc, etree_parser)
parser = xml.sax.make_parser()
parser.setFeature(xml.sax.handler.feature_namespaces, True)
parser.setFeature(xml.sax.handler.feature_namespace_prefixes, True)
parser.setContentHandler(XUpdateHandler(original_tree=original_tree))
parser.parse(xml_xu)
content_handler = parser.getContentHandler()
content_handler = XUpdateHandler(original_tree=original_tree)
lxml.sax.saxify(etree.parse(xml_xu, etree_parser), content_handler)
return content_handler.result_tree
if __name__ == '__main__':
import sys
doc_xml_name = sys.argv[1]
xu_xml_name = sys.argv[2]
print etree.tostring(applyXUpdate(xml_xu_filename=xu_xml_name, xml_doc_filename=doc_xml_name), pretty_print=True)
print(etree.tostring(applyXUpdate(xml_xu_filename=xu_xml_name, xml_doc_filename=doc_xml_name), pretty_print=True))
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment