diff --git a/glymur/jp2box.py b/glymur/jp2box.py
index ab8a6e5..043a1be 100644
--- a/glymur/jp2box.py
+++ b/glymur/jp2box.py
@@ -145,8 +145,8 @@ class Jp2kBox(object):
except KeyError:
msg = 'Unrecognized box ({0}) encountered.'.format(box_id)
warnings.warn(msg)
- box = Jp2kBox(box_id, offset=start, length=num_bytes,
- longname='Unknown box')
+ box = UnknownBox(box_id, offset=start, length=num_bytes,
+ longname='Unknown')
if fptr.tell() != start + 8:
# If the file pointer has advanced, then the KeyError
@@ -2739,6 +2739,37 @@ class DataEntryURLBox(Jp2kBox):
return box
+class UnknownBox(Jp2kBox):
+ """Container for unrecognized boxes.
+
+ Attributes
+ ----------
+ box_id : str
+ 4-character identifier for the box.
+ length : int
+ length of the box in bytes.
+ offset : int
+ offset of the box from the start of the file.
+ longname : str
+ more verbose description of the box.
+ """
+ def __init__(self, box_id, length=0, offset=-1, longname=''):
+ Jp2kBox.__init__(self, box_id=box_id, longname=longname)
+ self.length = length
+ self.offset = offset
+
+ def __repr__(self):
+ msg = "glymur.jp2box.UnknownBox({0})".format(self.box_id)
+ return msg
+
+ def __str__(self):
+ if len(self.box) > 0:
+ msg = self._str_superbox()
+ else:
+ msg = Jp2kBox.__str__(self)
+ return msg
+
+
class UUIDBox(Jp2kBox):
"""Container for UUID box information.
diff --git a/glymur/test/fixtures.py b/glymur/test/fixtures.py
index 6e0a76c..a7906c5 100644
--- a/glymur/test/fixtures.py
+++ b/glymur/test/fixtures.py
@@ -690,3 +690,11 @@ file7_rreq = r"""Reader Requirements Box (rreq) @ (44, 24)
Feature 060: 0x60 e-sRGB enumerated colorspace
Feature 043: 0x40 Deprecated - compositing layer uses restricted ICC profile
Vendor Features:"""
+
+file1_xml = r"""XML Box (xml ) @ (36, 439)
+
+
+ 2001-11-01T13:45:00.000-06:00
+ Professional 120 Image
+
+ """
diff --git a/glymur/test/test_printing.py b/glymur/test/test_printing.py
index 5fe3322..132d1ec 100644
--- a/glymur/test/test_printing.py
+++ b/glymur/test/test_printing.py
@@ -39,6 +39,7 @@ from .fixtures import text_gbr_27, text_gbr_33, text_gbr_34
class TestPrinting(unittest.TestCase):
"""Tests for verifying how printing works."""
def setUp(self):
+ self.jpxfile = glymur.data.jpxfile()
self.jp2file = glymur.data.nemo()
self.j2kfile = glymur.data.goodstuff()
@@ -48,6 +49,31 @@ class TestPrinting(unittest.TestCase):
def tearDown(self):
pass
+ @unittest.skipIf(sys.hexversion < 0x03000000, "Needs unittest in 3.x.")
+ def test_unknown_superbox(self):
+ """Verify that we can handle an unknown superbox."""
+ with tempfile.NamedTemporaryFile(suffix='.jpx') as tfile:
+ with open(self.jpxfile, 'rb') as ifile:
+ tfile.write(ifile.read())
+
+ # Add the header for an unknwon superbox.
+ write_buffer = struct.pack('>I4s', 20, 'grp '.encode())
+ tfile.write(write_buffer)
+ write_buffer = struct.pack('>I4sI', 12, 'free'.encode(), 0)
+ tfile.write(write_buffer)
+ tfile.flush()
+
+ with self.assertWarns(UserWarning):
+ jpx = Jp2k(tfile.name)
+ glymur.set_printoptions(short=True)
+ with patch('sys.stdout', new=StringIO()) as fake_out:
+ print(jpx.box[-1])
+ actual = fake_out.getvalue().strip()
+ lines = ['Unknown Box (grp ) @ (695609, 20)',
+ ' Free Box (free) @ (695617, 12)']
+ expected = '\n'.join(lines)
+ self.assertEqual(actual, expected)
+
def test_printoptions_bad_argument(self):
"""Verify error when bad parameter to set_printoptions"""
with self.assertRaises(TypeError):
@@ -602,27 +628,7 @@ class TestPrinting(unittest.TestCase):
with patch('sys.stdout', new=StringIO()) as fake_out:
print(j.box[2])
actual = fake_out.getvalue().strip()
-
- lines = ['XML Box (xml ) @ (36, 439)',
- ' ',
-
- ' ',
- ' '
- + '2001-11-01T13:45:00.000-06:00'
- + '',
-
- ' '
- + 'Professional 120 Image'
- + '',
-
- ' ',
- ' ']
- expected = '\n'.join(lines)
- self.assertEqual(actual, expected)
+ self.assertEqual(actual, fixtures.file1_xml)
@unittest.skipIf(sys.hexversion < 0x03000000,
"Only trusting python3 for printing non-ascii chars")