Skip to content
Snippets Groups Projects
Commit 00f47b191939 authored by Charlie Clark's avatar Charlie Clark
Browse files

Add some docs and test imports.

parent 7e57ef3f132d
No related branches found
No related tags found
No related merge requests found
The authors in alphabetical order
* Charlie Clark
* Elias Rabel
\ No newline at end of file
This software is under the MIT Licence
======================================
Copyright (c) 2010 openpyxl
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Odict implementation in openpyxl/writer/odict.py uses the following licence:
Copyright (c) 2001-2011 Python Software Foundation
2011 Raymond Hettinger
License: PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
See http://www.opensource.org/licenses/Python-2.0 for full terms
Note: backport changes by Raymond were originally distributed under MIT
license, but since the original license for Python is more
restrictive than MIT, code cannot be released under its terms and
still adheres to the limitations of Python license.
et_xmfile
=========
et_xmlfile is a low memory library for creating large XML files.
It is based upon the `xmlfile module from lxml <http://lxml.de/api.html#incremental-xml-generation>`_ with the aim of allowing code to be developed that will work with both libraries. It was developed initially for the openpyxl project but is now a standalone module.
The code was written by Elias Rabel as part of the `Python Düsseldorf <http://pyddf.de>`_ openpyxl sprint in September 2014.
Note on performance
-------------------
The code was not developed with performance in mind but turned out to be faster than the existing SAX-based implementation but is significantly slower than lxml's xmlfile. There is one area where an optimisation for lxml will negatively affect the performance of et_xmfile and that is when using the `.element()` method on an xmlfile context manager. It is, therefore, recommended not to use this, though the method is provided for code compatibility.
import os
import os.path
import re
import gc
import sys
import unittest
try:
import urlparse
except ImportError:
import urllib.parse as urlparse
try:
from urllib import pathname2url
except:
from urllib.request import pathname2url
from lxml import etree
def make_version_tuple(version_string):
l = []
for part in re.findall('([0-9]+|[^0-9.]+)', version_string):
try:
l.append(int(part))
except ValueError:
l.append(part)
return tuple(l)
IS_PYPY = (getattr(sys, 'implementation', None) == 'pypy' or
getattr(sys, 'pypy_version_info', None) is not None)
IS_PYTHON3 = sys.version_info[0] >= 3
try:
from xml.etree import ElementTree # Python 2.5+
except ImportError:
try:
from elementtree import ElementTree # standard ET
except ImportError:
ElementTree = None
if hasattr(ElementTree, 'VERSION'):
ET_VERSION = make_version_tuple(ElementTree.VERSION)
else:
ET_VERSION = (0,0,0)
try:
from xml.etree import cElementTree # Python 2.5+
except ImportError:
try:
import cElementTree # standard ET
except ImportError:
cElementTree = None
if hasattr(cElementTree, 'VERSION'):
CET_VERSION = make_version_tuple(cElementTree.VERSION)
else:
CET_VERSION = (0,0,0)
def filter_by_version(test_class, version_dict, current_version):
"""Remove test methods that do not work with the current lib version.
"""
find_required_version = version_dict.get
def dummy_test_method(self):
pass
for name in dir(test_class):
expected_version = find_required_version(name, (0,0,0))
if expected_version > current_version:
setattr(test_class, name, dummy_test_method)
try:
import doctest
# check if the system version has everything we need
doctest.DocFileSuite
doctest.DocTestParser
doctest.NORMALIZE_WHITESPACE
doctest.ELLIPSIS
except (ImportError, AttributeError):
# we need our own version to make it work (Python 2.3?)
import local_doctest as doctest
try:
sorted
except NameError:
def sorted(seq, **kwargs):
seq = list(seq)
seq.sort(**kwargs)
return seq
else:
locals()['sorted'] = sorted
try:
next
except NameError:
def next(it):
return it.next()
else:
locals()['next'] = next
try:
import pytest
except ImportError:
class skipif(object):
"Using a class because a function would bind into a method when used in classes"
def __init__(self, *args): pass
def __call__(self, func, *args): return func
else:
skipif = pytest.mark.skipif
def _get_caller_relative_path(filename, frame_depth=2):
module = sys.modules[sys._getframe(frame_depth).f_globals['__name__']]
return os.path.normpath(os.path.join(
os.path.dirname(getattr(module, '__file__', '')), filename))
from io import StringIO
if sys.version_info[0] >= 3:
# Python 3
from builtins import str as unicode
def _str(s, encoding="UTF-8"):
return s
def _bytes(s, encoding="UTF-8"):
return s.encode(encoding)
from io import BytesIO as _BytesIO
def BytesIO(*args):
if args and isinstance(args[0], str):
args = (args[0].encode("UTF-8"),)
return _BytesIO(*args)
doctest_parser = doctest.DocTestParser()
_fix_unicode = re.compile(r'(\s+)u(["\'])').sub
_fix_exceptions = re.compile(r'(.*except [^(]*),\s*(.*:)').sub
def make_doctest(filename):
filename = _get_caller_relative_path(filename)
doctests = read_file(filename)
doctests = _fix_unicode(r'\1\2', doctests)
doctests = _fix_exceptions(r'\1 as \2', doctests)
return doctest.DocTestCase(
doctest_parser.get_doctest(
doctests, {}, os.path.basename(filename), filename, 0))
else:
# Python 2
from __builtin__ import unicode
def _str(s, encoding="UTF-8"):
return unicode(s, encoding=encoding)
def _bytes(s, encoding="UTF-8"):
return s
from io import BytesIO
doctest_parser = doctest.DocTestParser()
_fix_traceback = re.compile(r'^(\s*)(?:\w+\.)+(\w*(?:Error|Exception|Invalid):)', re.M).sub
_fix_exceptions = re.compile(r'(.*except [^(]*)\s+as\s+(.*:)').sub
_fix_bytes = re.compile(r'(\s+)b(["\'])').sub
def make_doctest(filename):
filename = _get_caller_relative_path(filename)
doctests = read_file(filename)
doctests = _fix_traceback(r'\1\2', doctests)
doctests = _fix_exceptions(r'\1, \2', doctests)
doctests = _fix_bytes(r'\1\2', doctests)
return doctest.DocTestCase(
doctest_parser.get_doctest(
doctests, {}, os.path.basename(filename), filename, 0))
try:
skipIf = unittest.skipIf
except AttributeError:
def skipIf(condition, why,
_skip=lambda test_method: None,
_keep=lambda test_method: test_method):
if condition:
return _skip
return _keep
class HelperTestCase(unittest.TestCase):
def tearDown(self):
gc.collect()
def parse(self, text, parser=None):
f = BytesIO(text) if isinstance(text, bytes) else StringIO(text)
return etree.parse(f, parser=parser)
def _rootstring(self, tree):
return etree.tostring(tree.getroot()).replace(
_bytes(' '), _bytes('')).replace(_bytes('\n'), _bytes(''))
# assertFalse doesn't exist in Python 2.3
try:
unittest.TestCase.assertFalse
except AttributeError:
assertFalse = unittest.TestCase.failIf
class SillyFileLike:
def __init__(self, xml_data=_bytes('<foo><bar/></foo>')):
self.xml_data = xml_data
def read(self, amount=None):
if self.xml_data:
if amount:
data = self.xml_data[:amount]
self.xml_data = self.xml_data[amount:]
else:
data = self.xml_data
self.xml_data = _bytes('')
return data
return _bytes('')
class LargeFileLike:
def __init__(self, charlen=100, depth=4, children=5):
self.data = BytesIO()
self.chars = _bytes('a') * charlen
self.children = range(children)
self.more = self.iterelements(depth)
def iterelements(self, depth):
yield _bytes('<root>')
depth -= 1
if depth > 0:
for child in self.children:
for element in self.iterelements(depth):
yield element
yield self.chars
else:
yield self.chars
yield _bytes('</root>')
def read(self, amount=None):
data = self.data
append = data.write
if amount:
for element in self.more:
append(element)
if data.tell() >= amount:
break
else:
for element in self.more:
append(element)
result = data.getvalue()
data.seek(0)
data.truncate()
if amount:
append(result[amount:])
result = result[:amount]
return result
class LargeFileLikeUnicode(LargeFileLike):
def __init__(self, charlen=100, depth=4, children=5):
LargeFileLike.__init__(self, charlen, depth, children)
self.data = StringIO()
self.chars = _str('a') * charlen
self.more = self.iterelements(depth)
def iterelements(self, depth):
yield _str('<root>')
depth -= 1
if depth > 0:
for child in self.children:
for element in self.iterelements(depth):
yield element
yield self.chars
else:
yield self.chars
yield _str('</root>')
def fileInTestDir(name):
_testdir = os.path.dirname(__file__)
return os.path.join(_testdir, name)
def path2url(path):
return urlparse.urljoin(
'file:', pathname2url(path))
def fileUrlInTestDir(name):
return path2url(fileInTestDir(name))
def read_file(name, mode='r'):
f = open(name, mode)
try:
data = f.read()
finally:
f.close()
return data
def write_to_file(name, data, mode='w'):
f = open(name, mode)
try:
data = f.write(data)
finally:
f.close()
def readFileInTestDir(name, mode='r'):
return read_file(fileInTestDir(name), mode)
def canonicalize(xml):
tree = etree.parse(BytesIO(xml) if isinstance(xml, bytes) else StringIO(xml))
f = BytesIO()
tree.write_c14n(f)
return f.getvalue()
def unentitify(xml):
for entity_name, value in re.findall("(&#([0-9]+);)", xml):
xml = xml.replace(entity_name, unichr(int(value)))
return xml
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
import tempfile, os, sys import tempfile, os, sys
from .common_imports import etree, HelperTestCase, skipIf from .common_imports import etree, HelperTestCase, skipIf
from .. import xmlfile as etree from . import xmlfile as etree
import pytest import pytest
from openpyxl.tests.helper import compare_xml from openpyxl.tests.helper import compare_xml
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment