diff --git a/CHANGES.txt b/CHANGES.txt index f80b04b..410f243 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,6 @@ +Jul 23, 2013 - v0.2.5 Fixed inconsistency in XML handling, now all instances + are always ElementTree objects (issue82). + Jul 21, 2013 - v0.2.4 Fixed markdown bug for Fedora 17 information, fixed out-of-date windows information (issue79). Fixed incorrect interpretation of Psot parameter (issue78). diff --git a/docs/source/conf.py b/docs/source/conf.py index bd59b1b..d9f833e 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -78,7 +78,7 @@ copyright = u'2013, John Evans' # The short X.Y version. version = '0.1' # The full version, including alpha/beta/rc tags. -release = '0.2.4' +release = '0.2.5' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/source/how_do_i.rst b/docs/source/how_do_i.rst index 8abb693..9ffaee5 100644 --- a/docs/source/how_do_i.rst +++ b/docs/source/how_do_i.rst @@ -185,9 +185,8 @@ Work with XMP UUIDs? ==================== The example JP2 file shipped with glymur has an XMP UUID. :: - >>> from glymur import Jp2k - >>> file = glymur.data.nemo() - >>> j = Jp2k(file) + >>> import glymur + >>> j = glymur.Jp2k(glymur.data.nemo()) >>> print(j.box[4]) UUID Box (uuid) @ (715, 2412) UUID: be7acfcb-97a9-42e8-9c71-999491e3afac (XMP) @@ -198,7 +197,7 @@ The example JP2 file shipped with glymur has an XMP UUID. :: -Since the UUID data in this case is returned as an ElementTree Element, one can +Since the UUID data in this case is returned as an ElementTree instance, one can use ElementTree to access the data. For example, to extract the **CreatorTool** attribute value, the following would work:: diff --git a/docs/source/roadmap.rst b/docs/source/roadmap.rst index ea4a5bd..f1434b2 100644 --- a/docs/source/roadmap.rst +++ b/docs/source/roadmap.rst @@ -6,7 +6,6 @@ Here's an incomplete list of what I'd like to focus on in the near future. * continue to monitor upstream changes in the openjp2 library * investigate using CFFI or cython instead of ctypes to wrap openjp2 - * investigate swapping out ElementTree for LXML * eventually expose the openjp2 API * investigate JPIP diff --git a/glymur/codestream.py b/glymur/codestream.py index 49d7acb..df1575c 100644 --- a/glymur/codestream.py +++ b/glymur/codestream.py @@ -42,16 +42,6 @@ for _marker in range(0xff90, 0xff94): _VALID_MARKERS.append(_marker) -class InconsistentStartOfTileError(IOError): - """To be raised if bad SOT segment encountered. - - SOT segment offsets are recorded as encountered. The offsets should all be - different. - """ - def __init__(self, msg): - IOError.__init__(self, msg) - - class Codestream(object): """Container for codestream information. @@ -115,8 +105,8 @@ class Codestream(object): marker_id, = struct.unpack('>H', read_buffer) if marker_id == 0xff90 and header_only: - # start-of-tile (SOT) means we are out of the main header. - # No need to go any further. + # Start-of-tile (SOT) means that we are out of the main header + # and there is no need to go further. break try: @@ -135,7 +125,7 @@ class Codestream(object): if marker_id == 0xff93: # If SOD, then we need to seek past the tile part bit stream. - if self._parse_tpart_flag: + if self._parse_tpart_flag and not header_only: # But first parse the tile part bit stream for SOP and # EPH segments. self._parse_tile_part_bit_stream(fptr, segment, @@ -143,6 +133,7 @@ class Codestream(object): fptr.seek(self._tile_offset[-1] + self._tile_length[-1]) + def _process_marker_segment(self, fptr, marker_id): """Process and return a segment from the codestream. """ @@ -207,19 +198,12 @@ class Codestream(object): # we encounter start-of-data marker segments. segment = _parse_sot_segment(fptr) - if segment.offset not in self._tile_offset: - self._tile_offset.append(segment.offset) - if segment.psot == 0: - tile_part_length = self.offset + self.length - segment.offset - 2 - else: - tile_part_length = segment.psot - self._tile_length.append(tile_part_length) + self._tile_offset.append(segment.offset) + if segment.psot == 0: + tile_part_length = self.offset + self.length - segment.offset - 2 else: - msg = "Inconsistent start-of-tile (SOT) marker segment " - msg += "encountered in tile with index {0}. " - msg += "Codestream parsing terminated." - msg = msg.format(segment.isot) - raise InconsistentStartOfTileError(msg) + tile_part_length = segment.psot + self._tile_length.append(tile_part_length) elif marker_id == 0xff93: # start of data. Need to seek past the current tile part. diff --git a/glymur/jp2box.py b/glymur/jp2box.py index d205e1b..15471a5 100644 --- a/glymur/jp2box.py +++ b/glymur/jp2box.py @@ -1608,7 +1608,7 @@ class XMLBox(Jp2kBox): offset of the box from the start of the file. longname : str more verbose description of the box. - xml : ElementTree.Element + xml : ElementTree object XML section. """ def __init__(self, xml=None, filename=None, length=0, offset=-1): @@ -1636,10 +1636,7 @@ class XMLBox(Jp2kBox): msg = Jp2kBox.__str__(self) xml = self.xml if self.xml is not None: - try: - msg += _pretty_print_xml(self.xml) - except TypeError: - msg += _pretty_print_xml(self.xml.getroot()) + msg += _pretty_print_xml(self.xml) else: msg += '\n {0}'.format(xml) return msg @@ -1682,7 +1679,8 @@ class XMLBox(Jp2kBox): text = text.rstrip('\0') try: - xml = ET.fromstring(text) + elt = ET.fromstring(text) + xml = ET.ElementTree(elt) except ParseError as parse_error: msg = 'A problem was encountered while parsing an XML box: "{0}"' msg = msg.format(str(parse_error)) @@ -1926,13 +1924,11 @@ class UUIDBox(Jp2kBox): # XMP data. Parse as XML. Seems to be a difference between # ElementTree in version 2.7 and 3.3. if sys.hexversion < 0x03000000: - #parser = ET.XMLParser(encoding='utf-8') - #import pdb; pdb.set_trace() - #self.data = ET.fromstringlist(raw_data, parser=parser) - self.data = ET.fromstring(raw_data) + elt = ET.fromstring(raw_data) else: text = raw_data.decode('utf-8') - self.data = ET.fromstring(text) + elt = ET.fromstring(text) + self.data = ET.ElementTree(elt) elif the_uuid.bytes == b'JpgTiffExif->JP2': exif_obj = Exif(raw_data) ifds = OrderedDict() @@ -2555,8 +2551,8 @@ def _pretty_print_xml(xml, level=0): """Pretty print XML data. """ xml = copy.deepcopy(xml) - _indent(xml, level=level) - xmltext = ET.tostring(xml).decode('utf-8') + _indent(xml.getroot(), level=level) + xmltext = ET.tostring(xml.getroot()).decode('utf-8') # Indent it a bit. lst = [(' ' + x) for x in xmltext.split('\n')] diff --git a/glymur/test/test_jp2box.py b/glymur/test/test_jp2box.py index 8fa566e..178d4a0 100644 --- a/glymur/test/test_jp2box.py +++ b/glymur/test/test_jp2box.py @@ -365,7 +365,7 @@ class TestXML(unittest.TestCase): j2k.wrap(tfile.name, boxes=boxes) jp2 = Jp2k(tfile.name) self.assertEqual(jp2.box[3].box_id, 'xml ') - self.assertEqual(ET.tostring(jp2.box[3].xml), + self.assertEqual(ET.tostring(jp2.box[3].xml.getroot()), b'0') @unittest.skipIf(os.name == "nt", diff --git a/glymur/test/test_opj_suite.py b/glymur/test/test_opj_suite.py index cedd9cf..4aab788 100644 --- a/glymur/test/test_opj_suite.py +++ b/glymur/test/test_opj_suite.py @@ -4021,7 +4021,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(jp2.box[1].compatibility_list[1], 'jp2 ') # XML box - tags = [x.tag for x in jp2.box[2].xml] + tags = [x.tag for x in jp2.box[2].xml.getroot()] self.assertEqual(tags, ['{http://www.jpeg.org/jpx/1.0/xml}' + 'GENERAL_CREATION_INFO']) @@ -4046,7 +4046,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(jp2.box[3].box[1].colorspace, glymur.core.SRGB) # XML box - tags = [x.tag for x in jp2.box[4].xml] + tags = [x.tag for x in jp2.box[4].xml.getroot()] self.assertEqual(tags, ['{http://www.jpeg.org/jpx/1.0/xml}CAPTION', '{http://www.jpeg.org/jpx/1.0/xml}LOCATION', '{http://www.jpeg.org/jpx/1.0/xml}EVENT']) @@ -4376,13 +4376,13 @@ class TestSuiteDump(unittest.TestCase): self.assertIsNone(jp2.box[2].box[1].colorspace) # XML box - tags = [x.tag for x in jp2.box[3].xml] + tags = [x.tag for x in jp2.box[3].xml.getroot()] self.assertEqual(tags, ['{http://www.jpeg.org/jpx/1.0/xml}' + 'GENERAL_CREATION_INFO']) # XML box - tags = [x.tag for x in jp2.box[5].xml] + tags = [x.tag for x in jp2.box[5].xml.getroot()] self.assertEqual(tags, ['{http://www.jpeg.org/jpx/1.0/xml}CAPTION', '{http://www.jpeg.org/jpx/1.0/xml}LOCATION', @@ -6954,8 +6954,7 @@ class TestSuiteDump(unittest.TestCase): self.assertEqual(c.segment[3]._exponent, [4] + [5, 5, 6] * 5) def test_NR_merged_dump(self): - jfile = os.path.join(data_root, - 'input/nonregression/merged.jp2') + jfile = os.path.join(data_root, 'input/nonregression/merged.jp2') jp2 = Jp2k(jfile) ids = [box.box_id for box in jp2.box] diff --git a/setup.py b/setup.py index 95e778b..8d88a3a 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages import sys kwargs = {'name': 'Glymur', - 'version': '0.2.4', + 'version': '0.2.5', 'description': 'Tools for accessing JPEG2000 files', 'long_description': open('README.md').read(), 'author': 'John Evans',