Repository: pydicom/pydicom

Issue:
(0x00e1, 0x1002) Error
#### Description

Accessing the `(0x00e1, 0x1002)` item in the dicom data raises an exception

Terminal output

```
Python 3.5.2 (default, Nov 17 2016, 17:05:23) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pydicom
>>> pydicom.__file__
'${HOME}/repo/pydicom/pydicom/__init__.py'
>>> data = pydicom.read_file('00811195')
>>> (0x00e1, 0x1002) in data
>>> data
Traceback (most recent call last):
  File "${HOME}/repo/pydicom/pydicom/datadict.py", line 243, in get_private_entry
    dict_entry = private_dict[tag]
KeyError: (00e1, 1002)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "${HOME}/repo/pydicom/pydicom/tagtools.py", line 17, in tag_in_exception
    yield
  File "${HOME}/repo/pydicom/pydicom/dataset.py", line 1145, in _pretty_str
    strings.append(indent_str + repr(data_element))
  File "${HOME}/repo/pydicom/pydicom/dataelem.py", line 392, in __repr__
    return str(self)
  File "${HOME}/repo/pydicom/pydicom/dataelem.py", line 297, in __str__
    self.description()[:self.descripWidth],
  File "${HOME}/repo/pydicom/pydicom/dataelem.py", line 357, in description
    self.private_creator)
  File "${HOME}/repo/pydicom/pydicom/datadict.py", line 272, in private_dictionary_description
    return get_private_entry(tag, private_creator)[2]
  File "${HOME}/repo/pydicom/pydicom/datadict.py", line 251, in get_private_entry
    msg += "dictionary for private creator {1}".format(private_creator)
IndexError: tuple index out of range

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "${HOME}/repo/pydicom/pydicom/dataset.py", line 1335, in __str__
    return self._pretty_str()
  File "${HOME}/repo/pydicom/pydicom/dataset.py", line 1145, in _pretty_str
    strings.append(indent_str + repr(data_element))
  File "/usr/lib/python3.5/contextlib.py", line 77, in __exit__
    self.gen.throw(type, value, traceback)
  File "${HOME}/repo/pydicom/pydicom/tagtools.py", line 21, in tag_in_exception
    raise type(e)(err)
IndexError: Invalid tag (00e1, 1002): tuple index out of range
>>> 
```

not sure if other fields are affected.

git blame show that the line originating the exception (`msg += "dictionary for private creator {1}".format(private_creator)`) was introduced in commit 8550b39 *finishing up contrib*

#### Versions

```
>>> import platform; print(platform.platform())
Linux-4.10.0-27-generic-x86_64-with-Ubuntu-16.04-xenial
>>> import sys; print("Python", sys.version)
Python 3.5.2 (default, Nov 17 2016, 17:05:23) 
[GCC 5.4.0 20160609]
>>> import numpy; print("numpy", numpy.__version__)
numpy 1.13.1
>>> import pydicom; print("pydicom", pydicom.__version__)
pydicom 1.0.0a1
```


Discussion:
darcymason: Thanks for this.  Would you mind adding test coverage?

Patch:
diff --git a/pydicom/datadict.py b/pydicom/datadict.py
index 000125050..cad2a17a8 100644
--- a/pydicom/datadict.py
+++ b/pydicom/datadict.py
@@ -247,8 +247,8 @@ def get_private_entry(tag, private_creator):
         elem_str = "%04x" % tag.elem
         key = "%sxx%s" % (group_str, elem_str[-2:])
         if key not in private_dict:
-            msg = "Tag {0} not in private ".format(key)
-            msg += "dictionary for private creator {1}".format(private_creator)
+            msg = ("Tag {0} not in private dictionary "
+                   "for private creator {1}".format(key, private_creator))
             raise KeyError(msg)
         dict_entry = private_dict[key]
     return dict_entry
diff --git a/pydicom/dataset.py b/pydicom/dataset.py
index ce2a7cdfe..d9674b7f6 100644
--- a/pydicom/dataset.py
+++ b/pydicom/dataset.py
@@ -960,10 +960,11 @@ class Dataset(dict):
             if self.BitsAllocated > 8:
                 raise NotImplementedError("JPEG Lossy only supported if Bits "
                                           "Allocated = 8")
-            generic_jpeg_file_header = (b'\xff\xd8\xff\xe0\x00\x10JFIF\x00',
-                                        b'\x01\x01\x01\x00\x01\x00\x01\x00',
+            generic_jpeg_file_header = (b'\xff\xd8\xff\xe0\x00\x10JFIF\x00'
+                                        b'\x01\x01\x01\x00\x01\x00\x01\x00'
                                         b'\x00')
             frame_start_from = 2
+
         elif (self.file_meta.TransferSyntaxUID in
                 pydicom.uid.JPEG2000CompressedPixelTransferSyntaxes):
             generic_jpeg_file_header = b''
diff --git a/pydicom/filebase.py b/pydicom/filebase.py
index cbd5f3898..449dd4c02 100644
--- a/pydicom/filebase.py
+++ b/pydicom/filebase.py
@@ -88,7 +88,7 @@ class DicomIO(object):
             num_bytes = len(bytes_read)
             if num_bytes < length:
                 start_pos = self.tell() - num_bytes
-                msg = ("Unexpected end of file. Read {0} bytes of {1} ",
+                msg = ("Unexpected end of file. Read {0} bytes of {1} "
                        "expected starting at position 0x{2:x}".format(
                            len(bytes_read), length, start_pos))
                 raise EOFError(msg)
diff --git a/pydicom/filewriter.py b/pydicom/filewriter.py
index 9ca728be9..a10c77884 100644
--- a/pydicom/filewriter.py
+++ b/pydicom/filewriter.py
@@ -366,8 +366,8 @@ def write_data_element(fp, data_element, encoding=default_encoding):
     VR = data_element.VR
     if not fp.is_implicit_VR:
         if len(VR) != 2:
-            msg = ("Cannot write ambiguous VR of '{}' for data element with ",
-                   "tag {}.\nSet the correct VR before writing, or use an ",
+            msg = ("Cannot write ambiguous VR of '{}' for data element with "
+                   "tag {}.\nSet the correct VR before writing, or use an "
                    "implicit VR transfer syntax".format(
                        VR, repr(data_element.tag)))
             raise ValueError(msg)


Test patch:
diff --git a/pydicom/tests/test_dictionary.py b/pydicom/tests/test_dictionary.py
index 95fbb5cfe..361e909a5 100644
--- a/pydicom/tests/test_dictionary.py
+++ b/pydicom/tests/test_dictionary.py
@@ -10,7 +10,7 @@ from pydicom.dataset import Dataset
 from pydicom.tag import Tag
 from pydicom.datadict import (keyword_for_tag, dictionary_description,
                               dictionary_has_tag, repeater_has_tag,
-                              repeater_has_keyword)
+                              repeater_has_keyword, get_private_entry)
 from pydicom.datadict import add_dict_entry, add_dict_entries
 
 
@@ -41,6 +41,25 @@ class DictTests(unittest.TestCase):
         self.assertTrue(repeater_has_keyword('OverlayData'))
         self.assertFalse(repeater_has_keyword('PixelData'))
 
+    def test_get_private_entry(self):
+        """Test get_private_entry"""
+        # existing entry
+        entry = get_private_entry((0x0903, 0x0011), 'GEIIS PACS')
+        self.assertEqual('US', entry[0])  # VR
+        self.assertEqual('1', entry[1])  # VM
+        self.assertEqual('Significant Flag', entry[2])  # name
+        self.assertFalse(entry[3])  # is retired
+
+        # existing entry in another slot
+        entry = get_private_entry((0x0903, 0x1011), 'GEIIS PACS')
+        self.assertEqual('Significant Flag', entry[2])  # name
+
+        # non-existing entry
+        self.assertRaises(KeyError, get_private_entry,
+                          (0x0903, 0x0011), 'Nonexisting')
+        self.assertRaises(KeyError, get_private_entry,
+                          (0x0903, 0x0091), 'GEIIS PACS')
+
     def testAddEntry(self):
         """dicom_dictionary: Can add and use a single dictionary entry"""
         add_dict_entry(0x10011001, "UL", "TestOne", "Test One")