Repository: pydicom/pydicom

Issue:
Circle CI crashes when encounters html-noplot rule
see [here](https://circleci.com/gh/pydicom/pydicom/58?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link)

Discussion:

Patch:
diff --git a/Makefile b/Makefile
index f67bdaab1..c5c61355e 100644
--- a/Makefile
+++ b/Makefile
@@ -17,9 +17,6 @@ test: test-code test-doc
 doc:
 	make -C doc html
 
-doc-noplot:
-	make -C doc html-noplot
-
 clean:
 	find . -name "*.so" -o -name "*.pyc" -o -name "*.md5" -o -name "*.pyd" -o -name "*~" | xargs rm -f
 	find . -name "*.pyx" -exec ./tools/rm_pyx_c_file.sh {} \;
diff --git a/build_tools/circle/build_doc.sh b/build_tools/circle/build_doc.sh
index b22f59e80..c353badee 100755
--- a/build_tools/circle/build_doc.sh
+++ b/build_tools/circle/build_doc.sh
@@ -78,7 +78,7 @@ then
     MAKE_TARGET="dist LATEXMKOPTS=-halt-on-error"
 elif [[ "$build_type" =~ ^QUICK ]]
 then
-	MAKE_TARGET=html-noplot
+	MAKE_TARGET=html
 else
     MAKE_TARGET=html
 fi
diff --git a/pydicom/filereader.py b/pydicom/filereader.py
index 8735955f7..aa575f5a4 100644
--- a/pydicom/filereader.py
+++ b/pydicom/filereader.py
@@ -1,16 +1,17 @@
-# filereader.py
 """Read a dicom media file"""
 # Copyright (c) 2008-2012 Darcy Mason
 # This file is part of pydicom, released under a modified MIT license.
 #    See the file license.txt included with this distribution, also
 #    available at https://github.com/darcymason/pydicom
 from __future__ import absolute_import
+
 # Need zlib and io.BytesIO for deflate-compressed file
 import os.path
 import warnings
 import zlib
 from io import BytesIO
 
+from pydicom.misc import size_in_bytes
 from pydicom.tag import TupleTag
 from pydicom.dataelem import RawDataElement
 from pydicom.util.hexutil import bytes2hex
@@ -20,15 +21,8 @@ from pydicom.compat import in_py2
 from pydicom import compat
 from pydicom import config  # don't import datetime_conversion directly
 from pydicom.config import logger
-
-stat_available = True
-try:
-    from os import stat
-except ImportError:
-    stat_available = False
-
 from pydicom.errors import InvalidDicomError
-import pydicom.uid  # for Implicit/Explicit/Little/Big Endian transfer syntax UIDs
+import pydicom.uid  # for transfer syntax UIDs
 from pydicom.filebase import DicomFile
 from pydicom.dataset import Dataset, FileDataset
 from pydicom.dicomdir import DicomDir
@@ -39,12 +33,19 @@ from pydicom.sequence import Sequence
 from pydicom.fileutil import read_undefined_length_value
 from struct import Struct, unpack
 from sys import byteorder
+
+try:
+    from os import stat
+except ImportError:
+    stat = None
+
 sys_is_little_endian = (byteorder == 'little')
 
 
 class DicomIter(object):
     """Iterator over DICOM data elements created from a file-like object
     """
+
     def __init__(self, fp, stop_when=None, force=False):
         """Read the preamble and meta info and prepare iterator for remainder of file.
 
@@ -109,13 +110,15 @@ class DicomIter(object):
             yield self.file_meta_info[tag]
 
         for data_element in data_element_generator(self.fp,
-                                                   self._is_implicit_VR, self._is_little_endian,
+                                                   self._is_implicit_VR,
+                                                   self._is_little_endian,
                                                    stop_when=self.stop_when):
             yield data_element
 
 
 def data_element_generator(fp, is_implicit_VR, is_little_endian,
-                           stop_when=None, defer_size=None, encoding=default_encoding):
+                           stop_when=None, defer_size=None,
+                           encoding=default_encoding):
     """Create a generator to efficiently return the raw data elements.
 
     Parameters
@@ -182,6 +185,7 @@ def data_element_generator(fp, is_implicit_VR, is_little_endian,
     logger_debug = logger.debug
     debugging = config.debugging
     element_struct_unpack = element_struct.unpack
+    defer_size = size_in_bytes(defer_size)
 
     while True:
         # Read tag, VR, length, get ready to read value
@@ -233,9 +237,10 @@ def data_element_generator(fp, is_implicit_VR, is_little_endian,
         # Reading the value
         # First case (most common): reading a value with a defined length
         if length != 0xFFFFFFFF:
-            # don't defer loading of Specific Character Set value as it is needed
-            # immediately to get the character encoding for other tags
-            if defer_size is not None and length > defer_size and tag != (0x08, 0x05):
+            # don't defer loading of Specific Character Set value as it is
+            # needed immediately to get the character encoding for other tags
+            if defer_size is not None and length > defer_size and tag != (
+                    0x08, 0x05):
                 # Flag as deferred by setting value to None, and skip bytes
                 value = None
                 logger_debug("Defer size exceeded. "
@@ -248,13 +253,18 @@ def data_element_generator(fp, is_implicit_VR, is_little_endian,
                     if length > 12:
                         dotdot = "..."
                     logger_debug("%08x: %-34s %s %r %s" % (value_tell,
-                                                           bytes2hex(value[:12]), dotdot, value[:12], dotdot))
+                                                           bytes2hex(
+                                                               value[:12]),
+                                                           dotdot,
+                                                           value[:12], dotdot))
 
             # If the tag is (0008,0005) Specific Character Set, then store it
             if tag == (0x08, 0x05):
                 from pydicom.values import convert_string
-                encoding = convert_string(value, is_little_endian, encoding=default_encoding)
-                # Store the encoding value in the generator for use with future elements (SQs)
+                encoding = convert_string(value, is_little_endian,
+                                          encoding=default_encoding)
+                # Store the encoding value in the generator
+                # for use with future elements (SQs)
                 encoding = convert_encodings(encoding)
 
             yield RawDataElement(tag, VR, length, value, value_tell,
@@ -273,7 +283,8 @@ def data_element_generator(fp, is_implicit_VR, is_little_endian,
                 try:
                     VR = dictionary_VR(tag)
                 except KeyError:
-                    # Look ahead to see if it consists of items and is thus a SQ
+                    # Look ahead to see if it consists of items
+                    # and is thus a SQ
                     next_tag = TupleTag(unpack(endian_chr + "HH", fp_read(4)))
                     # Rewind the file
                     fp.seek(fp_tell() - 4)
@@ -295,11 +306,14 @@ def data_element_generator(fp, is_implicit_VR, is_little_endian,
                 value = read_undefined_length_value(fp, is_little_endian,
                                                     delimiter, defer_size)
 
-                # If the tag is (0008,0005) Specific Character Set, then store it
+                # If the tag is (0008,0005) Specific Character Set,
+                # then store it
                 if tag == (0x08, 0x05):
                     from pydicom.values import convert_string
-                    encoding = convert_string(value, is_little_endian, encoding=default_encoding)
-                    # Store the encoding value in the generator for use with future elements (SQs)
+                    encoding = convert_string(value, is_little_endian,
+                                              encoding=default_encoding)
+                    # Store the encoding value in the generator for use
+                    # with future elements (SQs)
                     encoding = convert_encodings(encoding)
 
                 yield RawDataElement(tag, VR, length, value, value_tell,
@@ -307,7 +321,8 @@ def data_element_generator(fp, is_implicit_VR, is_little_endian,
 
 
 def read_dataset(fp, is_implicit_VR, is_little_endian, bytelength=None,
-                 stop_when=None, defer_size=None, parent_encoding=default_encoding):
+                 stop_when=None, defer_size=None,
+                 parent_encoding=default_encoding):
     """Return a Dataset instance containing the next dataset in the file.
 
     Parameters
@@ -389,7 +404,8 @@ def read_sequence(fp, is_implicit_VR, is_little_endian, bytelength, encoding,
     return seq
 
 
-def read_sequence_item(fp, is_implicit_VR, is_little_endian, encoding, offset=0):
+def read_sequence_item(fp, is_implicit_VR, is_little_endian, encoding,
+                       offset=0):
     """Read and return a single sequence item, i.e. a Dataset"""
     seq_item_tell = fp.tell() + offset
     if is_little_endian:
@@ -399,15 +415,17 @@ def read_sequence_item(fp, is_implicit_VR, is_little_endian, encoding, offset=0)
     try:
         bytes_read = fp.read(8)
         group, element, length = unpack(tag_length_format, bytes_read)
-    except:
+    except BaseException:
         raise IOError("No tag to read at file position "
                       "{0:05x}".format(fp.tell() + offset))
     tag = (group, element)
     if tag == SequenceDelimiterTag:  # No more items, time to stop reading
-        logger.debug("{0:08x}: {1}".format(fp.tell() - 8 + offset, "End of Sequence"))
+        logger.debug(
+            "{0:08x}: {1}".format(fp.tell() - 8 + offset, "End of Sequence"))
         if length != 0:
             logger.warning("Expected 0x00000000 after delimiter, found 0x%x, "
-                           "at position 0x%x" % (length, fp.tell() - 4 + offset))
+                           "at position 0x%x" % (
+                               length, fp.tell() - 4 + offset))
         return None
     if tag != ItemTag:
         logger.warning("Expected sequence item with tag %s at file position "
@@ -429,11 +447,12 @@ def read_sequence_item(fp, is_implicit_VR, is_little_endian, encoding, offset=0)
 
 
 def _read_command_set_elements(fp):
-    """Return a Dataset containing any Command Set (0000,eeee) elements in `fp`.
+    """Return a Dataset containing any Command Set (0000,eeee) elements
+    in `fp`.
 
     Command Set elements are always Implicit VR Little Endian (as per PS3.7
-    Section 6.3). Once any Command Set elements are read `fp` will be positioned
-    at the start of the next group of elements.
+    Section 6.3). Once any Command Set elements are read `fp` will be
+    positioned at the start of the next group of elements.
 
     Parameters
     ----------
@@ -446,6 +465,7 @@ def _read_command_set_elements(fp):
         The command set elements as a Dataset instance. May be empty if no
         command set elements are present.
     """
+
     def _not_group_0000(tag, VR, length):
         """Return True if the tag is not in group 0x0000, False otherwise."""
         return (tag.group != 0)
@@ -474,9 +494,10 @@ def _read_file_meta_info(fp):
         The File Meta elements as a Dataset instance. May be empty if no
         File Meta are present.
     """
+
     def _not_group_0002(tag, VR, length):
         """Return True if the tag is not in group 0x0002, False otherwise."""
-        return (tag.group != 2)
+        return tag.group != 2
 
     start_file_meta = fp.tell()
     file_meta = read_dataset(fp, is_implicit_VR=False, is_little_endian=True,
@@ -491,9 +512,9 @@ def _read_file_meta_info(fp):
             logger.info("_read_file_meta_info: (0002,0000) 'File Meta "
                         "Information Group Length' value doesn't match the "
                         "actual File Meta Information length ({0} vs {1} "
-                        "bytes).".format(
-                        file_meta.FileMetaInformationGroupLength,
-                        length_file_meta))
+                        "bytes)."
+                        .format(file_meta.FileMetaInformationGroupLength,
+                                length_file_meta))
     return file_meta
 
 
@@ -512,11 +533,11 @@ def read_file_meta_info(filename):
 def read_preamble(fp, force):
     """Return the 128-byte DICOM preamble in `fp` if present.
 
-    `fp` should be positioned at the start of the file-like. If the preamble and
-    prefix are found then after reading `fp` will be positioned at the first
-    byte after the prefix (byte offset 133). If either the preamble or prefix
-    are missing and `force` is True then after reading `fp` will be positioned
-    at the start of the file-like.
+    `fp` should be positioned at the start of the file-like. If the preamble
+    and prefix are found then after reading `fp` will be positioned at the
+    first byte after the prefix (byte offset 133). If either the preamble or
+    prefix are missing and `force` is True then after reading `fp` will be
+    positioned at the start of the file-like.
 
     Parameters
     ----------
@@ -551,10 +572,11 @@ def read_preamble(fp, force):
     logger.debug("Reading File Meta Information prefix...")
     magic = fp.read(4)
     if magic != b"DICM" and force:
-        logger.info("File is not conformant with the DICOM File Format: 'DICM' "
-                    "prefix is missing from the File Meta Information header "
-                    "or the header itself is missing. Assuming no header and "
-                    "continuing.")
+        logger.info(
+            "File is not conformant with the DICOM File Format: 'DICM' "
+            "prefix is missing from the File Meta Information header "
+            "or the header itself is missing. Assuming no header and "
+            "continuing.")
         preamble = None
         fp.seek(0)
     elif magic != b"DICM" and not force:
@@ -598,13 +620,15 @@ def read_partial(fileobj, stop_when=None, defer_size=None, force=False):
     read_file
         More generic file reading function.
     """
-    ## Read File Meta Information
+    # Read File Meta Information
+
     # Read preamble (if present)
     preamble = read_preamble(fileobj, force)
     # Read any File Meta Information group (0002,eeee) elements (if present)
     file_meta_dataset = _read_file_meta_info(fileobj)
 
-    ## Read Dataset
+    # Read Dataset
+
     # Read any Command Set group (0000,eeee) elements (if present)
     command_set = _read_command_set_elements(fileobj)
 
@@ -612,14 +636,14 @@ def read_partial(fileobj, stop_when=None, defer_size=None, force=False):
     peek = fileobj.read(1)
     fileobj.seek(-1, 1)
 
-    # `filobj` should be positioned at the start of the dataset by this point,
+    # `filobj` should be positioned at the start of the dataset by this point.
     # Ensure we have appropriate values for `is_implicit_VR` and
-    #   `is_little_endian` before we try decoding. We assume an initial
-    #   transfer syntax of implicit VR little endian and correct it as necessary
+    # `is_little_endian` before we try decoding. We assume an initial
+    # transfer syntax of implicit VR little endian and correct it as necessary
     is_implicit_VR = True
     is_little_endian = True
     transfer_syntax = file_meta_dataset.get("TransferSyntaxUID")
-    if peek == b'': # EOF
+    if peek == b'':  # EOF
         pass
     elif transfer_syntax is None:  # issue 258
         # If no TransferSyntaxUID element then we have to try and figure out
@@ -693,11 +717,12 @@ def read_partial(fileobj, stop_when=None, defer_size=None, force=False):
 def read_file(fp, defer_size=None, stop_before_pixels=False, force=False):
     """Read and parse a DICOM dataset stored in the DICOM File Format.
 
-    Read a DICOM dataset stored in accordance with the DICOM File Format (DICOM
-    Standard Part 10 Section 7). If the dataset is not stored in accordance
-    with the File Format (i.e. the preamble and prefix are missing, there are
-    missing required Type 1 File Meta Information Group elements or the entire
-    File Meta Information is missing) then you will have to set `force` to True.
+    Read a DICOM dataset stored in accordance with the DICOM File Format
+    (DICOM Standard Part 10 Section 7). If the dataset is not stored in
+    accordance with the File Format (i.e. the preamble and prefix are missing,
+    there are missing required Type 1 File Meta Information Group elements
+    or the entire File Meta Information is missing) then you will have to
+    set `force` to True.
 
     Parameters
     ----------
@@ -772,10 +797,8 @@ def read_file(fp, defer_size=None, stop_before_pixels=False, force=False):
             logger.debug("Caller passed file name")
         logger.debug("-" * 80)
 
-    # Convert size to defer reading into bytes, and store in file object
-    # if defer_size is not None:
-    #    defer_size = size_in_bytes(defer_size)
-    # fp.defer_size = defer_size
+    # Convert size to defer reading into bytes
+    defer_size = size_in_bytes(defer_size)
 
     # Iterate through all items and store them --include file meta if present
     stop_when = None
@@ -816,7 +839,8 @@ def read_dicomdir(filename="DICOMDIR"):
     ds = read_file(filename)
     # Here, check that it is in fact DicomDir
     if not isinstance(ds, DicomDir):
-        msg = u"File '{0}' is not a Media Storage Directory file".format(filename)
+        msg = u"File '{0}' is not a Media Storage Directory file".format(
+            filename)
         raise InvalidDicomError(msg)
     return ds
 
@@ -824,7 +848,7 @@ def read_dicomdir(filename="DICOMDIR"):
 def data_element_offset_to_value(is_implicit_VR, VR):
     """Return number of bytes from start of data element to start of value"""
     if is_implicit_VR:
-        offset = 8   # tag of 4 plus 4-byte length
+        offset = 8  # tag of 4 plus 4-byte length
     else:
         if VR in extra_length_VRs:
             offset = 12  # tag 4 + 2 VR + 2 reserved + 4 length
@@ -846,7 +870,7 @@ def read_deferred_data_element(fileobj_type, filename, timestamp,
     if not os.path.exists(filename):
         raise IOError(u"Deferred read -- original file "
                       "{0:s} is missing".format(filename))
-    if stat_available and (timestamp is not None):
+    if stat is not None and (timestamp is not None):
         statinfo = os.stat(filename)
         if statinfo.st_mtime != timestamp:
             warnings.warn("Deferred read warning -- file modification time "
@@ -867,10 +891,12 @@ def read_deferred_data_element(fileobj_type, filename, timestamp,
     fp.close()
     if data_elem.VR != raw_data_elem.VR:
         raise ValueError("Deferred read VR {0:s} does not match "
-                         "original {1:s}".format(data_elem.VR, raw_data_elem.VR))
+                         "original {1:s}".format(data_elem.VR,
+                                                 raw_data_elem.VR))
     if data_elem.tag != raw_data_elem.tag:
         raise ValueError("Deferred read tag {0!r} does not match "
-                         "original {1!r}".format(data_elem.tag, raw_data_elem.tag))
+                         "original {1!r}".format(data_elem.tag,
+                                                 raw_data_elem.tag))
 
     # Everything is ok, now this object should act like usual DataElement
     return data_elem
diff --git a/pydicom/fileutil.py b/pydicom/fileutil.py
index 146fa8ebb..e3eab5c5d 100644
--- a/pydicom/fileutil.py
+++ b/pydicom/fileutil.py
@@ -1,11 +1,12 @@
-# fileutil.py
-"""Functions for reading to certain bytes, e.g. delimiters"""
+"""Functions for reading to certain bytes, e.g. delimiters."""
 # Copyright (c) 2009-2012 Darcy Mason
 # This file is part of pydicom, released under a modified MIT license.
 #    See the file license.txt included with this distribution, also
 #    available at https://github.com/darcymason/pydicom
 
 from struct import pack, unpack
+
+from pydicom.misc import size_in_bytes
 from pydicom.tag import TupleTag, Tag
 from pydicom.datadict import dictionary_description
 
@@ -21,16 +22,20 @@ def absorb_delimiter_item(fp, is_little_endian, delimiter):
     group, elem, length = unpack(struct_format, fp.read(8))
     tag = TupleTag((group, elem))
     if tag != delimiter:
-        msg = "Did not find expected delimiter '%s'" % dictionary_description(delimiter)
-        msg += ", instead found %s at file position 0x%x" % (str(tag), fp.tell() - 8)
+        msg = ("Did not find expected delimiter '%s'" %
+               dictionary_description(delimiter))
+        msg += ", instead found %s at file position 0x%x" % (
+            str(tag), fp.tell() - 8)
         logger.warn(msg)
         fp.seek(fp.tell() - 8)
         return
-    logger.debug("%04x: Found Delimiter '%s'", fp.tell() - 8, dictionary_description(delimiter))
+    logger.debug("%04x: Found Delimiter '%s'", fp.tell() - 8,
+                 dictionary_description(delimiter))
     if length == 0:
         logger.debug("%04x: Read 0 bytes after delimiter", fp.tell() - 4)
     else:
-        logger.debug("%04x: Expected 0x00000000 after delimiter, found 0x%x", fp.tell() - 4, length)
+        logger.debug("%04x: Expected 0x00000000 after delimiter, found 0x%x",
+                     fp.tell() - 4, length)
 
 
 def find_bytes(fp, bytes_to_find, read_size=128, rewind=True):
@@ -38,6 +43,7 @@ def find_bytes(fp, bytes_to_find, read_size=128, rewind=True):
 
     Parameters
     ----------
+    fp : file-like object
     bytes_to_find : str
         Contains the bytes to find. Must be in correct
         endian order already.
@@ -56,25 +62,27 @@ def find_bytes(fp, bytes_to_find, read_size=128, rewind=True):
     search_rewind = len(bytes_to_find) - 1
 
     found = False
-    EOF = False
+    eof = False
     while not found:
         chunk_start = fp.tell()
         bytes_read = fp.read(read_size)
         if len(bytes_read) < read_size:
-            # try again - if still don't get required amount, this is last block
+            # try again - if still don't get required amount,
+            # this is the last block
             new_bytes = fp.read(read_size - len(bytes_read))
             bytes_read += new_bytes
             if len(bytes_read) < read_size:
-                EOF = True  # but will still check whatever we did get
+                eof = True  # but will still check whatever we did get
         index = bytes_read.find(bytes_to_find)
         if index != -1:
             found = True
-        elif EOF:
+        elif eof:
             if rewind:
                 fp.seek(data_start)
             return None
         else:
-            fp.seek(fp.tell() - search_rewind)  # rewind a bit in case delimiter crossed read_size boundary
+            # rewind a bit in case delimiter crossed read_size boundary
+            fp.seek(fp.tell() - search_rewind)
     # if get here then have found the byte string
     found_at = chunk_start + index
     if rewind:
@@ -84,18 +92,25 @@ def find_bytes(fp, bytes_to_find, read_size=128, rewind=True):
     return found_at
 
 
-def read_undefined_length_value(fp, is_little_endian, delimiter_tag, defer_size=None,
+def read_undefined_length_value(fp, is_little_endian, delimiter_tag,
+                                defer_size=None,
                                 read_size=128):
-    """Read until the delimiter tag found and return the value; ignore the delimiter.
+    """Read until the delimiter tag found and return the value;
+     ignore the delimiter.
 
-    On completion, the file will be set to the first byte after the delimiter and its
-    following four zero bytes.
+    On completion, the file will be set to the first byte after the delimiter
+    and its following four zero bytes.
 
     Parameters
     ----------
     fp : a file-like object
     is_little_endian : boolean
         True if file transfer syntax is little endian, else False.
+    delimiter_tag : BaseTag
+        tag used as and marker for reading
+    defer_size : int, None, optional
+        Size to avoid loading large elements in memory.
+        See ``filereader.read_file`` for more parameter info.
     read_size : int
         Number of bytes to read at one time.
 
@@ -119,18 +134,20 @@ def read_undefined_length_value(fp, is_little_endian, delimiter_tag, defer_size=
     bytes_to_find = pack(bytes_format, delimiter_tag.group, delimiter_tag.elem)
 
     found = False
-    EOF = False
+    eof = False
     value_chunks = []
+    defer_size = size_in_bytes(defer_size)
     byte_count = 0  # for defer_size checks
     while not found:
         chunk_start = fp.tell()
         bytes_read = fp.read(read_size)
         if len(bytes_read) < read_size:
-            # try again - if still don't get required amount, this is last block
+            # try again - if still don't get required amount,
+            # this is the last block
             new_bytes = fp.read(read_size - len(bytes_read))
             bytes_read += new_bytes
             if len(bytes_read) < read_size:
-                EOF = True  # but will still check whatever we did get
+                eof = True  # but will still check whatever we did get
         index = bytes_read.find(bytes_to_find)
         if index != -1:
             found = True
@@ -141,26 +158,31 @@ def read_undefined_length_value(fp, is_little_endian, delimiter_tag, defer_size=
             fp.seek(chunk_start + index + 4)  # rewind to end of delimiter
             length = fp.read(4)
             if length != b"\0\0\0\0":
-                msg = "Expected 4 zero bytes after undefined length delimiter at pos {0:04x}"
+                msg = ("Expected 4 zero bytes after undefined length delimiter"
+                       " at pos {0:04x}")
                 logger.error(msg.format(fp.tell() - 4))
-        elif EOF:
+        elif eof:
             fp.seek(data_start)
-            raise EOFError("End of file reached before delimiter {0!r} found".format(delimiter_tag))
+            raise EOFError(
+                "End of file reached before delimiter {0!r} found".format(
+                    delimiter_tag))
         else:
-            fp.seek(fp.tell() - search_rewind)  # rewind a bit in case delimiter crossed read_size boundary
+            # rewind a bit in case delimiter crossed read_size boundary
+            fp.seek(fp.tell() - search_rewind)
             # accumulate the bytes read (not including the rewind)
             new_bytes = bytes_read[:-search_rewind]
             byte_count += len(new_bytes)
             if defer_size is None or byte_count < defer_size:
                 value_chunks.append(new_bytes)
     # if get here then have found the byte string
-    if defer_size is not None and defer_size >= defer_size:
+    if defer_size is not None and byte_count >= defer_size:
         return None
     else:
         return b"".join(value_chunks)
 
 
-def find_delimiter(fp, delimiter, is_little_endian, read_size=128, rewind=True):
+def find_delimiter(fp, delimiter, is_little_endian, read_size=128,
+                   rewind=True):
     """Return file position where 4-byte delimiter is located.
 
     Parameters
@@ -181,13 +203,15 @@ def find_delimiter(fp, delimiter, is_little_endian, read_size=128, rewind=True):
     if not is_little_endian:
         struct_format = ">H"
     delimiter = Tag(delimiter)
-    bytes_to_find = pack(struct_format, delimiter.group) + pack(struct_format, delimiter.elem)
+    bytes_to_find = pack(struct_format, delimiter.group) + pack(struct_format,
+                                                                delimiter.elem)
     return find_bytes(fp, bytes_to_find, read_size=read_size, rewind=rewind)
 
 
-def length_of_undefined_length(fp, delimiter, is_little_endian, read_size=128, rewind=True):
-    """Search through the file to find the delimiter and return the length of the data
-    element.
+def length_of_undefined_length(fp, delimiter, is_little_endian, read_size=128,
+                               rewind=True):
+    """Search through the file to find the delimiter and return the length
+    of the data element.
 
     Parameters
     ----------
@@ -206,11 +230,12 @@ def length_of_undefined_length(fp, delimiter, is_little_endian, read_size=128, r
 
     Notes
     -----
-    Note the data element that the delimiter starts is not read here, the calling
-    routine must handle that. Delimiter must be 4 bytes long.
+    Note the data element that the delimiter starts is not read here,
+    the calling routine must handle that. Delimiter must be 4 bytes long.
     """
     data_start = fp.tell()
-    delimiter_pos = find_delimiter(fp, delimiter, is_little_endian, rewind=rewind)
+    delimiter_pos = find_delimiter(fp, delimiter, is_little_endian,
+                                   rewind=rewind)
     length = delimiter_pos - data_start
     return length
 
@@ -222,7 +247,9 @@ def read_delimiter_item(fp, delimiter):
     """
     found = fp.read(4)
     if found != delimiter:
-        logger.warn("Expected delimitor %s, got %s at file position 0x%x", Tag(delimiter), Tag(found), fp.tell() - 4)
+        logger.warn("Expected delimitor %s, got %s at file position 0x%x",
+                    Tag(delimiter), Tag(found), fp.tell() - 4)
     length = fp.read_UL()
     if length != 0:
-        logger.warn("Expected delimiter item to have length 0, got %d at file position 0x%x", length, fp.tell() - 4)
+        logger.warn("Expected delimiter item to have length 0, "
+                    "got %d at file position 0x%x", length, fp.tell() - 4)
diff --git a/pydicom/misc.py b/pydicom/misc.py
index 2540a0b47..5e5e5c4f8 100644
--- a/pydicom/misc.py
+++ b/pydicom/misc.py
@@ -12,6 +12,8 @@ _size_factors = dict(KB=1024, MB=1024 * 1024, GB=1024 * 1024 * 1024)
 def size_in_bytes(expr):
     """Return the number of bytes for a defer_size argument to read_file()
     """
+    if expr is None:
+        return None
     try:
         return int(expr)
     except ValueError:
@@ -20,13 +22,15 @@ def size_in_bytes(expr):
             val = float(expr[:-2]) * _size_factors[unit]
             return val
         else:
-            raise ValueError("Unable to parse length with unit '{0:s}'".format(unit))
+            raise ValueError(
+                "Unable to parse length with unit '{0:s}'".format(unit))
 
 
 def is_dicom(file):
     """Boolean specifying if file is a proper DICOM file.
 
-    This function is a pared down version of read_preamble meant for a fast return.
+    This function is a pared down version of read_preamble meant for a
+    fast return.
     The file is read for a proper preamble ('DICM'), returning True if so,
     and False otherwise. This is a conservative approach.
 
@@ -45,9 +49,6 @@ def is_dicom(file):
         raise IOError("File passed was not a valid file")
         # TODO: error is only in Py3; what's a better Py2/3 error?
     fp = open(file, 'rb')
-    preamble = fp.read(0x80)
+    fp.read(0x80)  # preamble
     magic = fp.read(4)
-    if magic == b"DICM":
-        return True
-    else:
-        return False
+    return magic == b"DICM"
diff --git a/pydicom/util/leanread.py b/pydicom/util/leanread.py
index 59df2292f..296e9777c 100644
--- a/pydicom/util/leanread.py
+++ b/pydicom/util/leanread.py
@@ -1,10 +1,11 @@
-# leanread.py
 """Read a dicom media file"""
 # Copyright (c) 2013 Darcy Mason
 # This file is part of pydicom, released under a modified MIT license.
 #    See the file license.txt included with this distribution, also
 #    available at https://github.com/darcymason/pydicom
 
+from pydicom.misc import size_in_bytes
+from struct import Struct, unpack
 
 extra_length_VRs_b = (b'OB', b'OW', b'OF', b'SQ', b'UN', b'UT')
 ExplicitVRLittleEndian = b'1.2.840.10008.1.2.1'
@@ -17,9 +18,6 @@ ItemDelimiterTag = 0xFFFEE00D  # end of Sequence Item
 SequenceDelimiterTag = 0xFFFEE0DD  # end of Sequence of undefined length
 
 
-from struct import Struct, unpack
-
-
 class dicomfile(object):
     """Context-manager based DICOM file object with data element iteration"""
 
@@ -46,7 +44,8 @@ class dicomfile(object):
         # Yield the file meta info elements
         file_meta_gen = data_element_generator(self.fobj, is_implicit_VR=False,
                                                is_little_endian=True,
-                                               stop_when=lambda gp, elem: gp != 2)
+                                               stop_when=lambda gp,
+                                               elem: gp != 2)
         for data_elem in file_meta_gen:
             if data_elem[0] == (0x0002, 0x0010):
                 transfer_syntax_uid = data_elem[3]
@@ -57,12 +56,14 @@ class dicomfile(object):
             if transfer_syntax_uid.endswith(b' ') or \
                     transfer_syntax_uid.endswith(b'\0'):
                 transfer_syntax_uid = transfer_syntax_uid[:-1]
-            is_implicit_VR, is_little_endian = transfer_syntax(transfer_syntax_uid)
+            is_implicit_VR, is_little_endian = transfer_syntax(
+                transfer_syntax_uid)
             # print is_implicit_VR
         else:
             raise NotImplementedError("No transfer syntax in file meta info")
 
-        ds_gen = data_element_generator(self.fobj, is_implicit_VR, is_little_endian)
+        ds_gen = data_element_generator(self.fobj, is_implicit_VR,
+                                        is_little_endian)
         for data_elem in ds_gen:
             yield data_elem
 
@@ -114,6 +115,7 @@ def data_element_generator(fp, is_implicit_VR, is_little_endian,
     fp_read = fp.read
     fp_tell = fp.tell
     element_struct_unpack = element_struct.unpack
+    defer_size = size_in_bytes(defer_size)
 
     while True:
         # Read tag, VR, length, get ready to read value
@@ -166,7 +168,8 @@ def data_element_generator(fp, is_implicit_VR, is_little_endian,
                 try:
                     VR = dictionary_VR(tag)
                 except KeyError:
-                    # Look ahead to see if it consists of items and is thus a SQ
+                    # Look ahead to see if it consists of items and
+                    # is thus a SQ
                     next_tag = TupleTag(unpack(endian_chr + "HH", fp_read(4)))
                     # Rewind the file
                     fp.seek(fp_tell() - 4)
@@ -180,7 +183,8 @@ def data_element_generator(fp, is_implicit_VR, is_little_endian,
                 # yield DataElement(tag, VR, seq, value_tell,
                 #                   is_undefined_length=True)
             else:
-                raise NotImplementedError("This reader does not handle undefined length except for SQ")
+                raise NotImplementedError("This reader does not handle "
+                                          "undefined length except for SQ")
                 from pydicom.fileio.fileutil import read_undefined_length_value
 
                 delimiter = SequenceDelimiterTag


Test patch:
diff --git a/tests/test_filereader.py b/tests/test_filereader.py
index 7a07748c5..57d634ddf 100644
--- a/tests/test_filereader.py
+++ b/tests/test_filereader.py
@@ -14,47 +14,24 @@ import shutil
 import sys
 import tempfile
 import unittest
-from pydicom.util.testing.warncheck import assertWarns
-
-try:
-    unittest.skipUnless
-except AttributeError:
-    try:
-        import unittest2 as unittest
-    except ImportError:
-        print("unittest2 is required for testing in python2.6")
 
 # os.stat is only available on Unix and Windows   XXX Mac?
 # Not sure if on other platforms the import fails, or the call to it??
-stat_available = True
 try:
     from os import stat  # NOQA
-except:
-    stat_available = False
+except ImportError:
+    stat = None
 
-have_numpy = True
 try:
     import numpy  # NOQA
-except:
-    have_numpy = False
-
-from pydicom.dataset import Dataset, FileDataset
-from pydicom.dataelem import DataElement
-from pydicom.filebase import DicomBytesIO
-from pydicom.filereader import read_file, data_element_generator
-from pydicom.errors import InvalidDicomError
-from pydicom.dataset import PropertyError
-from pydicom.tag import Tag, TupleTag
-from pydicom.uid import ImplicitVRLittleEndian
-import pydicom.valuerep
+except ImportError:
+    numpy = None
 
-have_jpeg_ls = True
 try:
     import jpeg_ls
 except ImportError:
-    have_jpeg_ls = False
+    jpeg_ls = None
 
-have_pillow = True
 try:
     from PIL import Image as PILImg
 except ImportError:
@@ -63,13 +40,26 @@ except ImportError:
         import Image as PILImg
     except ImportError:
         # Neither worked, so it's likely not installed.
-        have_pillow = False
+        PILImg = None
+
+from pydicom.dataset import Dataset, FileDataset
+from pydicom.dataelem import DataElement
+from pydicom.filereader import read_file
+from pydicom.errors import InvalidDicomError
+from pydicom.tag import Tag, TupleTag
+from pydicom.uid import ImplicitVRLittleEndian
+from pydicom.util.testing.warncheck import assertWarns
+import pydicom.valuerep
 
+have_numpy = numpy is not None
+have_jpeg_ls = jpeg_ls is not None
+have_pillow = PILImg is not None
 
 test_dir = os.path.dirname(__file__)
 test_files = os.path.join(test_dir, 'test_files')
 
-empty_number_tags_name = os.path.join(test_files, "reportsi_with_empty_number_tags.dcm")
+empty_number_tags_name = os.path.join(test_files,
+                                      "reportsi_with_empty_number_tags.dcm")
 rtplan_name = os.path.join(test_files, "rtplan.dcm")
 rtdose_name = os.path.join(test_files, "rtdose.dcm")
 ct_name = os.path.join(test_files, "CT_small.dcm")
@@ -77,14 +67,16 @@ mr_name = os.path.join(test_files, "MR_small.dcm")
 truncated_mr_name = os.path.join(test_files, "MR_truncated.dcm")
 jpeg2000_name = os.path.join(test_files, "JPEG2000.dcm")
 jpeg2000_lossless_name = os.path.join(test_files, "MR_small_jp2klossless.dcm")
-jpeg_ls_lossless_name = os.path.join(test_files, "MR_small_jpeg_ls_lossless.dcm")
+jpeg_ls_lossless_name = os.path.join(test_files,
+                                     "MR_small_jpeg_ls_lossless.dcm")
 jpeg_lossy_name = os.path.join(test_files, "JPEG-lossy.dcm")
 jpeg_lossless_name = os.path.join(test_files, "JPEG-LL.dcm")
 deflate_name = os.path.join(test_files, "image_dfl.dcm")
 rtstruct_name = os.path.join(test_files, "rtstruct.dcm")
 priv_SQ_name = os.path.join(test_files, "priv_SQ.dcm")
 nested_priv_SQ_name = os.path.join(test_files, "nested_priv_SQ.dcm")
-meta_missing_tsyntax_name = os.path.join(test_files, "meta_missing_tsyntax.dcm")
+meta_missing_tsyntax_name = os.path.join(test_files,
+                                         "meta_missing_tsyntax.dcm")
 no_meta_group_length = os.path.join(test_files, "no_meta_group_length.dcm")
 gzip_name = os.path.join(test_files, "zipMR.gz")
 color_px_name = os.path.join(test_files, "color-px.dcm")
@@ -93,8 +85,10 @@ explicit_vr_le_no_meta = os.path.join(test_files, "ExplVR_LitEndNoMeta.dcm")
 explicit_vr_be_no_meta = os.path.join(test_files, "ExplVR_BigEndNoMeta.dcm")
 emri_name = os.path.join(test_files, "emri_small.dcm")
 emri_big_endian_name = os.path.join(test_files, "emri_small_big_endian.dcm")
-emri_jpeg_ls_lossless = os.path.join(test_files, "emri_small_jpeg_ls_lossless.dcm")
-emri_jpeg_2k_lossless = os.path.join(test_files, "emri_small_jpeg_2k_lossless.dcm")
+emri_jpeg_ls_lossless = os.path.join(test_files,
+                                     "emri_small_jpeg_ls_lossless.dcm")
+emri_jpeg_2k_lossless = os.path.join(test_files,
+                                     "emri_small_jpeg_2k_lossless.dcm")
 color_3d_jpeg_baseline = os.path.join(test_files, "color3d_jpeg_baseline.dcm")
 dir_name = os.path.dirname(sys.argv[0])
 save_dir = os.getcwd()
@@ -104,7 +98,7 @@ def isClose(a, b, epsilon=0.000001):
     """Compare within some tolerance, to avoid machine roundoff differences"""
     try:
         a.append  # see if is a list
-    except:  # (is not)
+    except BaseException:  # (is not)
         return abs(a - b) < epsilon
     else:
         if len(a) != len(b):
@@ -117,7 +111,8 @@ def isClose(a, b, epsilon=0.000001):
 
 class ReaderTests(unittest.TestCase):
     def testEmptyNumbersTag(self):
-        """Tests that an empty tag with a number VR (FL, UL, SL, US, SS, FL, FD, OF) reads as an empty string"""
+        """Tests that an empty tag with a number VR (FL, UL, SL, US,
+        SS, FL, FD, OF) reads as an empty string"""
         empty_number_tags_ds = read_file(empty_number_tags_name)
         self.assertEqual(empty_number_tags_ds.ExaminedBodyThickness, '')
         self.assertEqual(empty_number_tags_ds.SimpleFrameList, '')
@@ -135,56 +130,72 @@ class ReaderTests(unittest.TestCase):
         self.assertTrue(ds is not None)
 
     def testRTPlan(self):
-        """Returns correct values for sample data elements in test RT Plan file"""
+        """Returns correct values for sample data elements in test
+        RT Plan file.
+        """
         plan = read_file(rtplan_name)
         beam = plan.BeamSequence[0]
-        cp0, cp1 = beam.ControlPointSequence  # if not two controlpoints, then this would raise exception
+        # if not two controlpoints, then this would raise exception
+        cp0, cp1 = beam.ControlPointSequence
 
-        self.assertEqual(beam.TreatmentMachineName, "unit001", "Incorrect unit name")
+        self.assertEqual(beam.TreatmentMachineName, "unit001",
+                         "Incorrect unit name")
         self.assertEqual(beam.TreatmentMachineName, beam[0x300a, 0x00b2].value,
-                         "beam TreatmentMachineName does not match the value accessed by tag number")
+                         "beam TreatmentMachineName does not match "
+                         "the value accessed by tag number")
 
-        got = cp1.ReferencedDoseReferenceSequence[0].CumulativeDoseReferenceCoefficient
+        got = cp1.ReferencedDoseReferenceSequence[
+            0].CumulativeDoseReferenceCoefficient
         DS = pydicom.valuerep.DS
         expected = DS('0.9990268')
         self.assertTrue(got == expected,
-                        "Cum Dose Ref Coeff not the expected value (CP1, Ref'd Dose Ref")
+                        "Cum Dose Ref Coeff not the expected value "
+                        "(CP1, Ref'd Dose Ref")
         got = cp0.BeamLimitingDevicePositionSequence[0].LeafJawPositions
         self.assertTrue(got[0] == DS('-100') and got[1] == DS('100.0'),
                         "X jaws not as expected (control point 0)")
 
     def testRTDose(self):
-        """Returns correct values for sample data elements in test RT Dose file"""
+        """Returns correct values for sample data elements in test
+        RT Dose file"""
         dose = read_file(rtdose_name)
         self.assertEqual(dose.FrameIncrementPointer, Tag((0x3004, 0x000c)),
                          "Frame Increment Pointer not the expected value")
         self.assertEqual(dose.FrameIncrementPointer, dose[0x28, 9].value,
-                         "FrameIncrementPointer does not match the value accessed by tag number")
+                         "FrameIncrementPointer does not match the value "
+                         "accessed by tag number")
 
-        # try a value that is nested the deepest (so deep I break it into two steps!)
-        fract = dose.ReferencedRTPlanSequence[0].ReferencedFractionGroupSequence[0]
+        # try a value that is nested the deepest
+        # (so deep I break it into two steps!)
+        fract = \
+            dose.ReferencedRTPlanSequence[0].ReferencedFractionGroupSequence[0]
         beamnum = fract.ReferencedBeamSequence[0].ReferencedBeamNumber
         self.assertEqual(beamnum, 1, "Beam number not the expected value")
 
     def testCT(self):
-        """Returns correct values for sample data elements in test CT file...."""
+        """Returns correct values for sample data elements in test CT file."""
         ct = read_file(ct_name)
-        self.assertEqual(ct.file_meta.ImplementationClassUID, '1.3.6.1.4.1.5962.2',
+        self.assertEqual(ct.file_meta.ImplementationClassUID,
+                         '1.3.6.1.4.1.5962.2',
                          "ImplementationClassUID not the expected value")
         self.assertEqual(ct.file_meta.ImplementationClassUID,
                          ct.file_meta[0x2, 0x12].value,
-                         "ImplementationClassUID does not match the value accessed by tag number")
-        # (0020, 0032) Image Position (Patient)  [-158.13580300000001, -179.035797, -75.699996999999996]
+                         "ImplementationClassUID does not match the value "
+                         "accessed by tag number")
+        # (0020, 0032) Image Position (Patient)
+        # [-158.13580300000001, -179.035797, -75.699996999999996]
         got = ct.ImagePositionPatient
         DS = pydicom.valuerep.DS
         expected = [DS('-158.135803'), DS('-179.035797'), DS('-75.699997')]
-        self.assertTrue(got == expected, "ImagePosition(Patient) values not as expected."
+        self.assertTrue(got == expected,
+                        "ImagePosition(Patient) values not as expected."
                         "got {0}, expected {1}".format(got, expected))
 
         self.assertEqual(ct.Rows, 128, "Rows not 128")
         self.assertEqual(ct.Columns, 128, "Columns not 128")
         self.assertEqual(ct.BitsStored, 16, "Bits Stored not 16")
-        self.assertEqual(len(ct.PixelData), 128 * 128 * 2, "Pixel data not expected length")
+        self.assertEqual(len(ct.PixelData), 128 * 128 * 2,
+                         "Pixel data not expected length")
 
         # Also test private elements name can be resolved:
         expected = "[Duration of X-ray on]"
@@ -194,20 +205,24 @@ class ReaderTests(unittest.TestCase):
 
     @unittest.skipUnless(have_numpy, "Numpy not installed")
     def testCTPixelData(self):
-        """Check that we can read pixel data. Tests that we get last one in array."""
+        """Check that we can read pixel data.
+        Tests that we get last one in array.
+        """
         ct = read_file(ct_name)
         expected = 909
         got = ct.pixel_array[-1][-1]
-        msg = "Did not get correct value for last pixel: expected %d, got %r" % (expected, got)
+        msg = ("Did not get correct value for last pixel: "
+               "expected %d, got %r" % (expected, got))
         self.assertEqual(expected, got, msg)
 
     def testNoForce(self):
-        """Raises exception if missing DICOM header and force==False..........."""
+        """Raises exception if missing DICOM header and force==False."""
         self.assertRaises(InvalidDicomError, read_file, rtstruct_name)
 
     def testRTstruct(self):
-        """Returns correct values for sample elements in test RTSTRUCT file...."""
-        # RTSTRUCT test file has complex nested sequences -- see rtstruct.dump file
+        """Returns correct values for sample elements in test RTSTRUCT file."""
+        # RTSTRUCT test file has complex nested sequences
+        # -- see rtstruct.dump file
         # Also has no DICOM header ... so tests 'force' argument of read_file
 
         rtss = read_file(rtstruct_name, force=True)
@@ -230,7 +245,8 @@ class ReaderTests(unittest.TestCase):
         self.assertEqual(expected, got, msg)
 
     def testDir(self):
-        """Returns correct dir attributes for both Dataset and DICOM names (python >= 2.6).."""
+        """Returns correct dir attributes for both Dataset and DICOM names
+        (python >= 2.6).."""
         # Only python >= 2.6 calls __dir__ for dir() call
         rtss = read_file(rtstruct_name, force=True)
         # sample some expected 'dir' values
@@ -238,7 +254,8 @@ class ReaderTests(unittest.TestCase):
         expect_in_dir = ['pixel_array', 'add_new', 'ROIContourSequence',
                          'StructureSetDate']
         for name in expect_in_dir:
-            self.assertTrue(name in got_dir, "Expected name '%s' in dir()" % name)
+            self.assertTrue(name in got_dir,
+                            "Expected name '%s' in dir()" % name)
 
         # Now check for some items in dir() of a nested item
         roi0 = rtss.ROIContourSequence[0]
@@ -246,52 +263,65 @@ class ReaderTests(unittest.TestCase):
         expect_in_dir = ['pixel_array', 'add_new', 'ReferencedROINumber',
                          'ROIDisplayColor']
         for name in expect_in_dir:
-            self.assertTrue(name in got_dir, "Expected name '%s' in dir()" % name)
+            self.assertTrue(name in got_dir,
+                            "Expected name '%s' in dir()" % name)
 
     def testMR(self):
-        """Returns correct values for sample data elements in test MR file....."""
+        """Returns correct values for sample data elements in test MR file."""
         mr = read_file(mr_name)
         # (0010, 0010) Patient's Name           'CompressedSamples^MR1'
         mr.decode()
-        self.assertEqual(mr.PatientName, 'CompressedSamples^MR1', "Wrong patient name")
+        self.assertEqual(mr.PatientName, 'CompressedSamples^MR1',
+                         "Wrong patient name")
         self.assertEqual(mr.PatientName, mr[0x10, 0x10].value,
-                         "Name does not match value found when accessed by tag number")
+                         "Name does not match value found when "
+                         "accessed by tag number")
         got = mr.PixelSpacing
         DS = pydicom.valuerep.DS
         expected = [DS('0.3125'), DS('0.3125')]
         self.assertTrue(got == expected, "Wrong pixel spacing")
 
     def testDeflate(self):
-        """Returns correct values for sample data elements in test compressed (zlib deflate) file"""
-        # Everything after group 2 is compressed. If we can read anything else, the decompression must have been ok.
+        """Returns correct values for sample data elements in test compressed
+         (zlib deflate) file
+         """
+        # Everything after group 2 is compressed.
+        # If we can read anything else, the decompression must have been ok.
         ds = read_file(deflate_name)
         got = ds.ConversionType
         expected = "WSD"
-        self.assertEqual(got, expected, "Attempted to read deflated file data element Conversion Type, expected '%s', got '%s'" % (expected, got))
+        self.assertEqual(got, expected,
+                         "Attempted to read deflated file data element "
+                         "Conversion Type, expected '%s', got '%s'" % (
+                             expected, got))
 
     def testNoPixelsRead(self):
-        """Returns all data elements before pixels using stop_before_pixels=False"""
+        """Returns all data elements before pixels using
+        stop_before_pixels=False.
+        """
         # Just check the tags, and a couple of values
         ctpartial = read_file(ct_name, stop_before_pixels=True)
         ctpartial_tags = sorted(ctpartial.keys())
         ctfull = read_file(ct_name)
         ctfull_tags = sorted(ctfull.keys())
-        msg = "Tag list of partial CT read (except pixel tag and padding) did not match full read"
+        msg = ("Tag list of partial CT read (except pixel tag and padding) "
+               "did not match full read")
         msg += "\nExpected: %r\nGot %r" % (ctfull_tags[:-2], ctpartial_tags)
         missing = [Tag(0x7fe0, 0x10), Tag(0xfffc, 0xfffc)]
         self.assertEqual(ctfull_tags, ctpartial_tags + missing, msg)
 
     def testPrivateSQ(self):
-        """Can read private undefined length SQ without error...................."""
-        # From issues 91, 97, 98. Bug introduced by fast reading, due to VR=None
-        #    in raw data elements, then an undefined length private item VR is looked up,
-        #    and there is no such tag, generating an exception
+        """Can read private undefined length SQ without error."""
+        # From issues 91, 97, 98. Bug introduced by fast reading, due to
+        #    VR=None in raw data elements, then an undefined length private
+        #    item VR is looked up, and there is no such tag,
+        #    generating an exception
 
         # Simply read the file, in 0.9.5 this generated an exception
         read_file(priv_SQ_name)
 
     def testNestedPrivateSQ(self):
-        """Can successfully read a private SQ which contains additional SQ's....."""
+        """Can successfully read a private SQ which contains additional SQs."""
         # From issue 113. When a private SQ of undefined length is used, the
         #   sequence is read in and the length of the SQ is determined upon
         #   identification of the SQ termination sequence. When using nested
@@ -303,7 +333,8 @@ class ReaderTests(unittest.TestCase):
         # Make sure that the entire dataset was read in
         pixel_data_tag = TupleTag((0x7fe0, 0x10))
         self.assertTrue(pixel_data_tag in ds,
-                        "Entire dataset was not parsed properly. PixelData is not present")
+                        "Entire dataset was not parsed properly. "
+                        "PixelData is not present")
 
         # Check that the DataElement is indeed a Sequence
         tag = TupleTag((0x01, 0x01))
@@ -328,44 +359,54 @@ class ReaderTests(unittest.TestCase):
                          "Expected a value of %s, got %s'" % (expected, got))
 
     def testNoMetaGroupLength(self):
-        """Read file with no group length in file meta..........................."""
+        """Read file with no group length in file meta."""
         # Issue 108 -- iView example file with no group length (0002,0002)
         # Originally crashed, now check no exception, but also check one item
         #     in file_meta, and second one in followinsg dataset
         ds = read_file(no_meta_group_length)
         got = ds.InstanceCreationDate
         expected = "20111130"
-        self.assertEqual(got, expected, "Sample data element after file meta with no group length failed, expected '%s', got '%s'" % (expected, got))
+        self.assertEqual(got, expected,
+                         "Sample data element after file meta with no "
+                         "group length failed, expected '%s', got '%s'" % (
+                             expected, got))
 
     def testNoTransferSyntaxInMeta(self):
-        """Read file with file_meta, but has no TransferSyntaxUID in it............"""
+        """Read file with file_meta, but has no TransferSyntaxUID in it."""
         # From issue 258: if file has file_meta but no TransferSyntaxUID in it,
         #   should assume default transfer syntax
-        ds = read_file(meta_missing_tsyntax_name)  # is dicom default transfer syntax
+        ds = read_file(
+            meta_missing_tsyntax_name)  # is dicom default transfer syntax
 
         # Repeat one test from nested private sequence test to maker sure
         #    file was read correctly
         pixel_data_tag = TupleTag((0x7fe0, 0x10))
         self.assertTrue(pixel_data_tag in ds,
-                        "Failed to properly read a file with no Transfer Syntax in file_meta")
+                        "Failed to properly read a file with no "
+                        "Transfer Syntax in file_meta")
 
     def testExplicitVRLittleEndianNoMeta(self):
-        """Read file without file meta with Little Endian Explicit VR dataset...."""
+        """Read file without file meta with Little Endian Explicit VR dataset.
+        """
         # Example file from CMS XiO 5.0 and above
         # Still need to force read data since there is no 'DICM' marker present
         ds = read_file(explicit_vr_le_no_meta, force=True)
         got = ds.InstanceCreationDate
         expected = "20150529"
-        self.assertEqual(got, expected, "Sample data element from dataset failed, expected '%s', got '%s'" % (expected, got))
+        self.assertEqual(got, expected,
+                         "Sample data element from dataset failed, "
+                         "expected '%s', got '%s'" % (expected, got))
 
     def testExplicitVRBigEndianNoMeta(self):
-        """Read file without file meta with Big Endian Explicit VR dataset......."""
+        """Read file without file meta with Big Endian Explicit VR dataset."""
         # Example file from CMS XiO 5.0 and above
         # Still need to force read data since there is no 'DICM' marker present
         ds = read_file(explicit_vr_be_no_meta, force=True)
         got = ds.InstanceCreationDate
         expected = "20150529"
-        self.assertEqual(got, expected, "Sample data element from dataset failed, expected '%s', got '%s'" % (expected, got))
+        self.assertEqual(got, expected,
+                         "Sample data element from dataset failed, "
+                         "expected '%s', got '%s'" % (expected, got))
 
     def testPlanarConfig(self):
         px_data_ds = read_file(color_px_name)
@@ -407,7 +448,8 @@ class ReaderTests(unittest.TestCase):
         self.assertEqual(ds[0x7fe00010].VR, 'OB')
 
     def test_long_specific_char_set(self):
-        """Test that specific character set is read even if it is longer than defer_size"""
+        """Test that specific character set is read even if it is longer
+         than defer_size"""
         ds = Dataset()
 
         long_specific_char_set_value = ['ISO 2022IR 100'] * 9
@@ -422,52 +464,62 @@ class ReaderTests(unittest.TestCase):
 
     def test_no_preamble_file_meta_dataset(self):
         """Test correct read of group 2 elements with no preamble."""
-        bytestream = b'\x02\x00\x02\x00\x55\x49\x16\x00\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31' \
-                     b'\x30\x30\x30\x38\x2e\x35\x2e\x31\x2e\x31\x2e\x39\x00\x02\x00\x10\x00' \
-                     b'\x55\x49\x12\x00\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31\x30\x30\x30\x38' \
-                     b'\x2e\x31\x2e\x32\x00\x20\x20\x10\x00\x02\x00\x00\x00\x01\x00\x20\x20' \
-                     b'\x20\x00\x06\x00\x00\x00\x4e\x4f\x52\x4d\x41\x4c'
+        bytestream = (b'\x02\x00\x02\x00\x55\x49\x16\x00\x31\x2e\x32\x2e'
+                      b'\x38\x34\x30\x2e\x31\x30\x30\x30\x38\x2e\x35\x2e'
+                      b'\x31\x2e\x31\x2e\x39\x00\x02\x00\x10\x00\x55\x49'
+                      b'\x12\x00\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31\x30'
+                      b'\x30\x30\x38\x2e\x31\x2e\x32\x00\x20\x20\x10\x00'
+                      b'\x02\x00\x00\x00\x01\x00\x20\x20\x20\x00\x06\x00'
+                      b'\x00\x00\x4e\x4f\x52\x4d\x41\x4c')
 
         fp = BytesIO(bytestream)
         ds = read_file(fp, force=True)
         self.assertTrue('MediaStorageSOPClassUID' in ds.file_meta)
-        self.assertEqual(ds.file_meta.TransferSyntaxUID, ImplicitVRLittleEndian)
+        self.assertEqual(ds.file_meta.TransferSyntaxUID,
+                         ImplicitVRLittleEndian)
         self.assertEqual(ds.Polarity, 'NORMAL')
         self.assertEqual(ds.ImageBoxPosition, 1)
 
     def test_no_preamble_command_group_dataset(self):
         """Test correct read of group 0 and 2 elements with no preamble."""
-        bytestream = b'\x02\x00\x02\x00\x55\x49\x16\x00\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31' \
-                     b'\x30\x30\x30\x38\x2e\x35\x2e\x31\x2e\x31\x2e\x39\x00\x02\x00\x10\x00' \
-                     b'\x55\x49\x12\x00\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31\x30\x30\x30\x38' \
-                     b'\x2e\x31\x2e\x32\x00' \
-                     b'\x20\x20\x10\x00\x02\x00\x00\x00\x01\x00\x20\x20' \
-                     b'\x20\x00\x06\x00\x00\x00\x4e\x4f\x52\x4d\x41\x4c' \
-                     b'\x00\x00\x10\x01\x02\x00\x00\x00\x03\x00'
+        bytestream = (b'\x02\x00\x02\x00\x55\x49\x16\x00\x31\x2e\x32\x2e'
+                      b'\x38\x34\x30\x2e\x31\x30\x30\x30\x38\x2e\x35\x2e'
+                      b'\x31\x2e\x31\x2e\x39\x00\x02\x00\x10\x00\x55\x49'
+                      b'\x12\x00\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31\x30'
+                      b'\x30\x30\x38\x2e\x31\x2e\x32\x00'
+                      b'\x20\x20\x10\x00\x02\x00\x00\x00\x01\x00\x20\x20'
+                      b'\x20\x00\x06\x00\x00\x00\x4e\x4f\x52\x4d\x41\x4c'
+                      b'\x00\x00\x10\x01\x02\x00\x00\x00\x03\x00')
 
         fp = BytesIO(bytestream)
         ds = read_file(fp, force=True)
         self.assertTrue('MediaStorageSOPClassUID' in ds.file_meta)
-        self.assertEqual(ds.file_meta.TransferSyntaxUID, ImplicitVRLittleEndian)
+        self.assertEqual(ds.file_meta.TransferSyntaxUID,
+                         ImplicitVRLittleEndian)
         self.assertEqual(ds.Polarity, 'NORMAL')
         self.assertEqual(ds.ImageBoxPosition, 1)
         self.assertEqual(ds.MessageID, 3)
 
     def test_group_length_wrong(self):
-        """Test file is read correctly even if FileMetaInformationGroupLength is incorrect."""
-        bytestream = b'\x02\x00\x00\x00\x55\x4C\x04\x00\x0A\x00\x00\x00' \
-                     b'\x02\x00\x02\x00\x55\x49\x16\x00\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31' \
-                     b'\x30\x30\x30\x38\x2e\x35\x2e\x31\x2e\x31\x2e\x39\x00\x02\x00\x10\x00' \
-                     b'\x55\x49\x12\x00\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31\x30\x30\x30\x38' \
-                     b'\x2e\x31\x2e\x32\x00' \
-                     b'\x20\x20\x10\x00\x02\x00\x00\x00\x01\x00\x20\x20' \
-                     b'\x20\x00\x06\x00\x00\x00\x4e\x4f\x52\x4d\x41\x4c'
+        """Test file is read correctly even if FileMetaInformationGroupLength
+        is incorrect.
+        """
+        bytestream = (b'\x02\x00\x00\x00\x55\x4C\x04\x00\x0A\x00\x00\x00'
+                      b'\x02\x00\x02\x00\x55\x49\x16\x00\x31\x2e\x32\x2e'
+                      b'\x38\x34\x30\x2e\x31\x30\x30\x30\x38\x2e\x35\x2e'
+                      b'\x31\x2e\x31\x2e\x39\x00\x02\x00\x10\x00\x55\x49'
+                      b'\x12\x00\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31\x30'
+                      b'\x30\x30\x38\x2e\x31\x2e\x32\x00'
+                      b'\x20\x20\x10\x00\x02\x00\x00\x00\x01\x00\x20\x20'
+                      b'\x20\x00\x06\x00\x00\x00\x4e\x4f\x52\x4d\x41\x4c')
         fp = BytesIO(bytestream)
         ds = read_file(fp, force=True)
-        self.assertFalse(len(bytestream) - 12 == ds.file_meta.FileMetaInformationGroupLength)
+        self.assertFalse(len(
+            bytestream) - 12 == ds.file_meta.FileMetaInformationGroupLength)
         self.assertTrue(ds.file_meta.FileMetaInformationGroupLength == 10)
         self.assertTrue('MediaStorageSOPClassUID' in ds.file_meta)
-        self.assertEqual(ds.file_meta.TransferSyntaxUID, ImplicitVRLittleEndian)
+        self.assertEqual(ds.file_meta.TransferSyntaxUID,
+                         ImplicitVRLittleEndian)
         self.assertEqual(ds.Polarity, 'NORMAL')
         self.assertEqual(ds.ImageBoxPosition, 1)
 
@@ -475,18 +527,19 @@ class ReaderTests(unittest.TestCase):
         """Test reading only preamble, command and meta elements"""
         preamble = b'\x00' * 128
         prefix = b'DICM'
-        command = b'\x00\x00\x00\x00\x04\x00\x00\x00\x38' \
-                  b'\x00\x00\x00\x00\x00\x02\x00\x12\x00\x00' \
-                  b'\x00\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31' \
-                  b'\x30\x30\x30\x38\x2e\x31\x2e\x31\x00\x00' \
-                  b'\x00\x00\x01\x02\x00\x00\x00\x30\x00\x00' \
-                  b'\x00\x10\x01\x02\x00\x00\x00\x07\x00\x00' \
-                  b'\x00\x00\x08\x02\x00\x00\x00\x01\x01'
-        meta = b'\x02\x00\x00\x00\x55\x4C\x04\x00\x0A\x00\x00\x00' \
-               b'\x02\x00\x02\x00\x55\x49\x16\x00\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31' \
-               b'\x30\x30\x30\x38\x2e\x35\x2e\x31\x2e\x31\x2e\x39\x00\x02\x00\x10\x00' \
-               b'\x55\x49\x12\x00\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31\x30\x30\x30\x38' \
-               b'\x2e\x31\x2e\x32\x00'
+        command = (b'\x00\x00\x00\x00\x04\x00\x00\x00\x38'
+                   b'\x00\x00\x00\x00\x00\x02\x00\x12\x00\x00'
+                   b'\x00\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31'
+                   b'\x30\x30\x30\x38\x2e\x31\x2e\x31\x00\x00'
+                   b'\x00\x00\x01\x02\x00\x00\x00\x30\x00\x00'
+                   b'\x00\x10\x01\x02\x00\x00\x00\x07\x00\x00'
+                   b'\x00\x00\x08\x02\x00\x00\x00\x01\x01')
+        meta = (b'\x02\x00\x00\x00\x55\x4C\x04\x00\x0A\x00\x00\x00'
+                b'\x02\x00\x02\x00\x55\x49\x16\x00\x31\x2e\x32\x2e'
+                b'\x38\x34\x30\x2e\x31\x30\x30\x30\x38\x2e\x35\x2e'
+                b'\x31\x2e\x31\x2e\x39\x00\x02\x00\x10\x00\x55\x49'
+                b'\x12\x00\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31\x30'
+                b'\x30\x30\x38\x2e\x31\x2e\x32\x00')
 
         bytestream = preamble + prefix + meta + command
         fp = BytesIO(bytestream)
@@ -498,11 +551,12 @@ class ReaderTests(unittest.TestCase):
         """Test reading only preamble and meta elements"""
         preamble = b'\x00' * 128
         prefix = b'DICM'
-        meta = b'\x02\x00\x00\x00\x55\x4C\x04\x00\x0A\x00\x00\x00' \
-               b'\x02\x00\x02\x00\x55\x49\x16\x00\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31' \
-               b'\x30\x30\x30\x38\x2e\x35\x2e\x31\x2e\x31\x2e\x39\x00\x02\x00\x10\x00' \
-               b'\x55\x49\x12\x00\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31\x30\x30\x30\x38' \
-               b'\x2e\x31\x2e\x32\x00'
+        meta = (b'\x02\x00\x00\x00\x55\x4C\x04\x00\x0A\x00\x00\x00'
+                b'\x02\x00\x02\x00\x55\x49\x16\x00\x31\x2e\x32\x2e'
+                b'\x38\x34\x30\x2e\x31\x30\x30\x30\x38\x2e\x35\x2e'
+                b'\x31\x2e\x31\x2e\x39\x00\x02\x00\x10\x00\x55\x49'
+                b'\x12\x00\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31\x30'
+                b'\x30\x30\x38\x2e\x31\x2e\x32\x00')
 
         bytestream = preamble + prefix + meta
         fp = BytesIO(bytestream)
@@ -515,13 +569,13 @@ class ReaderTests(unittest.TestCase):
         """Test reading only preamble and command set"""
         preamble = b'\x00' * 128
         prefix = b'DICM'
-        command = b'\x00\x00\x00\x00\x04\x00\x00\x00\x38' \
-                  b'\x00\x00\x00\x00\x00\x02\x00\x12\x00\x00' \
-                  b'\x00\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31' \
-                  b'\x30\x30\x30\x38\x2e\x31\x2e\x31\x00\x00' \
-                  b'\x00\x00\x01\x02\x00\x00\x00\x30\x00\x00' \
-                  b'\x00\x10\x01\x02\x00\x00\x00\x07\x00\x00' \
-                  b'\x00\x00\x08\x02\x00\x00\x00\x01\x01'
+        command = (b'\x00\x00\x00\x00\x04\x00\x00\x00\x38'
+                   b'\x00\x00\x00\x00\x00\x02\x00\x12\x00\x00'
+                   b'\x00\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31'
+                   b'\x30\x30\x30\x38\x2e\x31\x2e\x31\x00\x00'
+                   b'\x00\x00\x01\x02\x00\x00\x00\x30\x00\x00'
+                   b'\x00\x10\x01\x02\x00\x00\x00\x07\x00\x00'
+                   b'\x00\x00\x08\x02\x00\x00\x00\x01\x01')
         bytestream = preamble + prefix + command
 
         fp = BytesIO(bytestream)
@@ -531,11 +585,12 @@ class ReaderTests(unittest.TestCase):
 
     def test_meta_no_dataset(self):
         """Test reading only meta elements"""
-        bytestream = b'\x02\x00\x00\x00\x55\x4C\x04\x00\x0A\x00\x00\x00' \
-                     b'\x02\x00\x02\x00\x55\x49\x16\x00\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31' \
-                     b'\x30\x30\x30\x38\x2e\x35\x2e\x31\x2e\x31\x2e\x39\x00\x02\x00\x10\x00' \
-                     b'\x55\x49\x12\x00\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31\x30\x30\x30\x38' \
-                     b'\x2e\x31\x2e\x32\x00'
+        bytestream = (b'\x02\x00\x00\x00\x55\x4C\x04\x00\x0A\x00\x00\x00'
+                      b'\x02\x00\x02\x00\x55\x49\x16\x00\x31\x2e\x32\x2e'
+                      b'\x38\x34\x30\x2e\x31\x30\x30\x30\x38\x2e\x35\x2e'
+                      b'\x31\x2e\x31\x2e\x39\x00\x02\x00\x10\x00\x55\x49'
+                      b'\x12\x00\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31\x30'
+                      b'\x30\x30\x38\x2e\x31\x2e\x32\x00')
         fp = BytesIO(bytestream)
         ds = read_file(fp, force=True)
         self.assertTrue('TransferSyntaxUID' in ds.file_meta)
@@ -543,13 +598,13 @@ class ReaderTests(unittest.TestCase):
 
     def test_commandset_no_dataset(self):
         """Test reading only command set elements"""
-        bytestream = b'\x00\x00\x00\x00\x04\x00\x00\x00\x38' \
-                     b'\x00\x00\x00\x00\x00\x02\x00\x12\x00\x00' \
-                     b'\x00\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31' \
-                     b'\x30\x30\x30\x38\x2e\x31\x2e\x31\x00\x00' \
-                     b'\x00\x00\x01\x02\x00\x00\x00\x30\x00\x00' \
-                     b'\x00\x10\x01\x02\x00\x00\x00\x07\x00\x00' \
-                     b'\x00\x00\x08\x02\x00\x00\x00\x01\x01'
+        bytestream = (b'\x00\x00\x00\x00\x04\x00\x00\x00\x38'
+                      b'\x00\x00\x00\x00\x00\x02\x00\x12\x00\x00'
+                      b'\x00\x31\x2e\x32\x2e\x38\x34\x30\x2e\x31'
+                      b'\x30\x30\x30\x38\x2e\x31\x2e\x31\x00\x00'
+                      b'\x00\x00\x01\x02\x00\x00\x00\x30\x00\x00'
+                      b'\x00\x10\x01\x02\x00\x00\x00\x07\x00\x00'
+                      b'\x00\x00\x08\x02\x00\x00\x00\x01\x01')
         fp = BytesIO(bytestream)
         ds = read_file(fp, force=True)
         self.assertTrue('MessageID' in ds)
@@ -569,23 +624,24 @@ class ReaderTests(unittest.TestCase):
 class ReadDataElementTests(unittest.TestCase):
     def setUp(self):
         ds = Dataset()
-        ds.DoubleFloatPixelData = b'\x00\x01\x02\x03\x04\x05\x06\x07' \
-                                  b'\x01\x01\x02\x03\x04\x05\x06\x07' # VR of OD
-        ds.SelectorOLValue = b'\x00\x01\x02\x03\x04\x05\x06\x07' \
-                             b'\x01\x01\x02\x03' # VR of OL
-        ds.PotentialReasonsForProcedure = ['A', 'B', 'C'] # VR of UC, odd length
-        ds.StrainDescription = 'Test' # Even length
-        ds.URNCodeValue = 'http://test.com' # VR of UR
-        ds.RetrieveURL = 'ftp://test.com  ' # Test trailing spaces ignored
-        ds.DestinationAE = '    TEST  12    ' # 16 characters max for AE
-
-        self.fp = BytesIO() # Implicit little
+        ds.DoubleFloatPixelData = (b'\x00\x01\x02\x03\x04\x05\x06\x07'
+                                   b'\x01\x01\x02\x03\x04\x05\x06\x07')  # OD
+        ds.SelectorOLValue = (b'\x00\x01\x02\x03\x04\x05\x06\x07'
+                              b'\x01\x01\x02\x03')  # VR of OL
+        ds.PotentialReasonsForProcedure = ['A', 'B',
+                                           'C']  # VR of UC, odd length
+        ds.StrainDescription = 'Test'  # Even length
+        ds.URNCodeValue = 'http://test.com'  # VR of UR
+        ds.RetrieveURL = 'ftp://test.com  '  # Test trailing spaces ignored
+        ds.DestinationAE = '    TEST  12    '  # 16 characters max for AE
+
+        self.fp = BytesIO()  # Implicit little
         file_ds = FileDataset(self.fp, ds)
         file_ds.is_implicit_VR = True
         file_ds.is_little_endian = True
         file_ds.save_as(self.fp)
 
-        self.fp_ex = BytesIO() # Explicit little
+        self.fp_ex = BytesIO()  # Explicit little
         file_ds = FileDataset(self.fp_ex, ds)
         file_ds.is_implicit_VR = False
         file_ds.is_little_endian = True
@@ -595,32 +651,36 @@ class ReadDataElementTests(unittest.TestCase):
         """Check creation of OD DataElement from byte data works correctly."""
         ds = read_file(self.fp, force=True)
         ref_elem = ds.get(0x7fe00009)
-        elem = DataElement(0x7fe00009, 'OD', b'\x00\x01\x02\x03\x04\x05\x06\x07' \
-                                             b'\x01\x01\x02\x03\x04\x05\x06\x07')
+        elem = DataElement(0x7fe00009, 'OD',
+                           b'\x00\x01\x02\x03\x04\x05\x06\x07'
+                           b'\x01\x01\x02\x03\x04\x05\x06\x07')
         self.assertEqual(ref_elem, elem)
 
     def test_read_OD_explicit_little(self):
         """Check creation of OD DataElement from byte data works correctly."""
         ds = read_file(self.fp_ex, force=True)
         ref_elem = ds.get(0x7fe00009)
-        elem = DataElement(0x7fe00009, 'OD', b'\x00\x01\x02\x03\x04\x05\x06\x07' \
-                                             b'\x01\x01\x02\x03\x04\x05\x06\x07')
+        elem = DataElement(0x7fe00009, 'OD',
+                           b'\x00\x01\x02\x03\x04\x05\x06\x07'
+                           b'\x01\x01\x02\x03\x04\x05\x06\x07')
         self.assertEqual(ref_elem, elem)
 
     def test_read_OL_implicit_little(self):
         """Check creation of OL DataElement from byte data works correctly."""
         ds = read_file(self.fp, force=True)
         ref_elem = ds.get(0x00720075)
-        elem = DataElement(0x00720075, 'OL', b'\x00\x01\x02\x03\x04\x05\x06\x07' \
-                                             b'\x01\x01\x02\x03')
+        elem = DataElement(0x00720075, 'OL',
+                           b'\x00\x01\x02\x03\x04\x05\x06\x07'
+                           b'\x01\x01\x02\x03')
         self.assertEqual(ref_elem, elem)
 
     def test_read_OL_explicit_little(self):
         """Check creation of OL DataElement from byte data works correctly."""
         ds = read_file(self.fp_ex, force=True)
         ref_elem = ds.get(0x00720075)
-        elem = DataElement(0x00720075, 'OL', b'\x00\x01\x02\x03\x04\x05\x06\x07' \
-                                             b'\x01\x01\x02\x03')
+        elem = DataElement(0x00720075, 'OL',
+                           b'\x00\x01\x02\x03\x04\x05\x06\x07'
+                           b'\x01\x01\x02\x03')
         self.assertEqual(ref_elem, elem)
 
     def test_read_UC_implicit_little(self):
@@ -650,24 +710,24 @@ class ReadDataElementTests(unittest.TestCase):
     def test_read_UR_implicit_little(self):
         """Check creation of DataElement from byte data works correctly."""
         ds = read_file(self.fp, force=True)
-        ref_elem = ds.get(0x00080120) # URNCodeValue
+        ref_elem = ds.get(0x00080120)  # URNCodeValue
         elem = DataElement(0x00080120, 'UR', 'http://test.com')
         self.assertEqual(ref_elem, elem)
 
         # Test trailing spaces ignored
-        ref_elem = ds.get(0x00081190) # RetrieveURL
+        ref_elem = ds.get(0x00081190)  # RetrieveURL
         elem = DataElement(0x00081190, 'UR', 'ftp://test.com')
         self.assertEqual(ref_elem, elem)
 
     def test_read_UR_explicit_little(self):
         """Check creation of DataElement from byte data works correctly."""
         ds = read_file(self.fp_ex, force=True)
-        ref_elem = ds.get(0x00080120) # URNCodeValue
+        ref_elem = ds.get(0x00080120)  # URNCodeValue
         elem = DataElement(0x00080120, 'UR', 'http://test.com')
         self.assertEqual(ref_elem, elem)
 
         # Test trailing spaces ignored
-        ref_elem = ds.get(0x00081190) # RetrieveURL
+        ref_elem = ds.get(0x00081190)  # RetrieveURL
         elem = DataElement(0x00081190, 'UR', 'ftp://test.com')
         self.assertEqual(ref_elem, elem)
 
@@ -690,9 +750,11 @@ class JPEG_LS_Tests(unittest.TestCase):
             a = self.jpeg_ls_lossless.pixel_array
             b = self.mr_small.pixel_array
             self.assertEqual(a.mean(), b.mean(),
-                             "Decoded pixel data is not all {0} (mean == {1})".format(b.mean(), a.mean()))
+                             "Decoded pixel data is not all {0} "
+                             "(mean == {1})".format(b.mean(), a.mean()))
         else:
-            self.assertRaises(NotImplementedError, self.jpeg_ls_lossless._get_pixel_array)
+            self.assertRaises(NotImplementedError,
+                              self.jpeg_ls_lossless._get_pixel_array)
 
     def test_emri_JPEG_LS_PixelArray(self):
         """JPEG LS Lossless: Now works"""
@@ -700,9 +762,11 @@ class JPEG_LS_Tests(unittest.TestCase):
             a = self.emri_jpeg_ls_lossless.pixel_array
             b = self.emri_small.pixel_array
             self.assertEqual(a.mean(), b.mean(),
-                             "Decoded pixel data is not all {0} (mean == {1})".format(b.mean(), a.mean()))
+                             "Decoded pixel data is not all {0} "
+                             "(mean == {1})".format(b.mean(), a.mean()))
         else:
-            self.assertRaises(NotImplementedError, self.emri_jpeg_ls_lossless._get_pixel_array)
+            self.assertRaises(NotImplementedError,
+                              self.emri_jpeg_ls_lossless._get_pixel_array)
 
 
 class BigEndian_Tests(unittest.TestCase):
@@ -716,9 +780,11 @@ class BigEndian_Tests(unittest.TestCase):
             a = self.emri_big_endian.pixel_array
             b = self.emri_small.pixel_array
             self.assertEqual(a.mean(), b.mean(),
-                             "Decoded big endian pixel data is not all {0} (mean == {1})".format(b.mean(), a.mean()))
+                             "Decoded big endian pixel data is not all {0} "
+                             "(mean == {1})".format(b.mean(), a.mean()))
         else:
-            self.assertRaises(ImportError, self.emri_big_endian._get_pixel_array)
+            self.assertRaises(ImportError,
+                              self.emri_big_endian._get_pixel_array)
 
 
 class JPEG2000Tests(unittest.TestCase):
@@ -730,14 +796,19 @@ class JPEG2000Tests(unittest.TestCase):
         self.emri_small = read_file(emri_name)
 
     def testJPEG2000(self):
-        """JPEG2000: Returns correct values for sample data elements............"""
-        expected = [Tag(0x0054, 0x0010), Tag(0x0054, 0x0020)]  # XX also tests multiple-valued AT data element
+        """JPEG2000: Returns correct values for sample data elements."""
+        # XX also tests multiple-valued AT data element
+        expected = [Tag(0x0054, 0x0010), Tag(0x0054, 0x0020)]
         got = self.jpeg.FrameIncrementPointer
-        self.assertEqual(got, expected, "JPEG2000 file, Frame Increment Pointer: expected %s, got %s" % (expected, got))
+        self.assertEqual(got, expected,
+                         "JPEG2000 file, Frame Increment Pointer: "
+                         "expected %s, got %s" % (expected, got))
 
         got = self.jpeg.DerivationCodeSequence[0].CodeMeaning
         expected = 'Lossy Compression'
-        self.assertEqual(got, expected, "JPEG200 file, Code Meaning got %s, expected %s" % (got, expected))
+        self.assertEqual(got, expected,
+                         "JPEG200 file, Code Meaning got %s, expected %s" % (
+                             got, expected))
 
     def testJPEG2000PixelArray(self):
         """JPEG2000: Now works"""
@@ -745,9 +816,11 @@ class JPEG2000Tests(unittest.TestCase):
             a = self.jpegls.pixel_array
             b = self.mr_small.pixel_array
             self.assertEqual(a.mean(), b.mean(),
-                             "Decoded pixel data is not all {0} (mean == {1})".format(b.mean(), a.mean()))
+                             "Decoded pixel data is not all {0} "
+                             "(mean == {1})".format(b.mean(), a.mean()))
         else:
-            self.assertRaises(NotImplementedError, self.jpegls._get_pixel_array)
+            self.assertRaises(NotImplementedError,
+                              self.jpegls._get_pixel_array)
 
     def test_emri_JPEG2000PixelArray(self):
         """JPEG2000: Now works"""
@@ -755,25 +828,28 @@ class JPEG2000Tests(unittest.TestCase):
             a = self.emri_jpeg_2k_lossless.pixel_array
             b = self.emri_small.pixel_array
             self.assertEqual(a.mean(), b.mean(),
-                             "Decoded pixel data is not all {0} (mean == {1})".format(b.mean(), a.mean()))
+                             "Decoded pixel data is not all {0} "
+                             "(mean == {1})".format(b.mean(), a.mean()))
         else:
-            self.assertRaises(NotImplementedError, self.emri_jpeg_2k_lossless._get_pixel_array)
+            self.assertRaises(NotImplementedError,
+                              self.emri_jpeg_2k_lossless._get_pixel_array)
 
 
 class JPEGlossyTests(unittest.TestCase):
-
     def setUp(self):
         self.jpeg = read_file(jpeg_lossy_name)
         self.color_3d_jpeg = read_file(color_3d_jpeg_baseline)
 
     def testJPEGlossy(self):
-        """JPEG-lossy: Returns correct values for sample data elements.........."""
+        """JPEG-lossy: Returns correct values for sample data elements."""
         got = self.jpeg.DerivationCodeSequence[0].CodeMeaning
         expected = 'Lossy Compression'
-        self.assertEqual(got, expected, "JPEG-lossy file, Code Meaning got %s, expected %s" % (got, expected))
+        self.assertEqual(got, expected,
+                         "JPEG-lossy file, Code Meaning got %s, "
+                         "expected %s" % (got, expected))
 
     def testJPEGlossyPixelArray(self):
-        """JPEG-lossy: Fails gracefully when uncompressed data is asked for....."""
+        """JPEG-lossy: Fails gracefully when uncompressed data is asked for."""
         if have_pillow and have_numpy:
             self.assertRaises(NotImplementedError, self.jpeg._get_pixel_array)
         else:
@@ -787,7 +863,8 @@ class JPEGlossyTests(unittest.TestCase):
             self.assertEqual(tuple(a[3, 159, 290, :]), (41, 41, 41))
             self.assertEqual(tuple(a[3, 169, 290, :]), (57, 57, 57))
         else:
-            self.assertRaises(NotImplementedError, self.color_3d_jpeg._get_pixel_array)
+            self.assertRaises(NotImplementedError,
+                              self.color_3d_jpeg._get_pixel_array)
 
 
 class JPEGlosslessTests(unittest.TestCase):
@@ -795,13 +872,17 @@ class JPEGlosslessTests(unittest.TestCase):
         self.jpeg = read_file(jpeg_lossless_name)
 
     def testJPEGlossless(self):
-        """JPEGlossless: Returns correct values for sample data elements........"""
-        got = self.jpeg.SourceImageSequence[0].PurposeOfReferenceCodeSequence[0].CodeMeaning
+        """JPEGlossless: Returns correct values for sample data elements."""
+        got = self.jpeg.SourceImageSequence[0].PurposeOfReferenceCodeSequence[
+            0].CodeMeaning
         expected = 'Uncompressed predecessor'
-        self.assertEqual(got, expected, "JPEG-lossless file, Code Meaning got %s, expected %s" % (got, expected))
+        self.assertEqual(got, expected,
+                         "JPEG-lossless file, Code Meaning got %s, "
+                         "expected %s" % (got, expected))
 
     def testJPEGlosslessPixelArray(self):
-        """JPEGlossless: Fails gracefully when uncompressed data is asked for..."""
+        """JPEGlossless: Fails gracefully when uncompressed data is asked for.
+        """
         # This test passes if the call raises either an
         # ImportError when there is no Pillow module
         # Or
@@ -823,6 +904,7 @@ class DeferredReadTests(unittest.TestCase):
     """Test that deferred data element reading (for large size)
     works as expected
     """
+
     # Copy one of test files and use temporarily, then later remove.
     def setUp(self):
         self.testfile_name = ct_name + ".tmp"
@@ -830,8 +912,8 @@ class DeferredReadTests(unittest.TestCase):
 
     def testTimeCheck(self):
         """Deferred read warns if file has been modified..........."""
-        if stat_available:
-            ds = read_file(self.testfile_name, defer_size=2000)
+        if stat is not None:
+            ds = read_file(self.testfile_name, defer_size='2 kB')
             from time import sleep
             sleep(1)
             with open(self.testfile_name, "r+") as f:
@@ -859,7 +941,8 @@ class DeferredReadTests(unittest.TestCase):
         ds_defer = read_file(self.testfile_name, defer_size=2000)
         for data_elem in ds_norm:
             tag = data_elem.tag
-            self.assertEqual(data_elem.value, ds_defer[tag].value, "Mismatched value for tag %r" % tag)
+            self.assertEqual(data_elem.value, ds_defer[tag].value,
+                             "Mismatched value for tag %r" % tag)
 
     def testZippedDeferred(self):
         """Deferred values from a gzipped file works.............."""
@@ -867,8 +950,8 @@ class DeferredReadTests(unittest.TestCase):
         fobj = gzip.open(gzip_name)
         ds = read_file(fobj, defer_size=1)
         fobj.close()
-        # before the fix, this threw an error as file reading was not in right place,
-        #    it was re-opened as a normal file, not zip file
+        # before the fix, this threw an error as file reading was not in
+        # the right place, it was re-opened as a normal file, not a zip file
         ds.InstanceNumber
 
     def tearDown(self):
@@ -880,9 +963,11 @@ class ReadTruncatedFileTests(unittest.TestCase):
     def testReadFileWithMissingPixelData(self):
         mr = read_file(truncated_mr_name)
         mr.decode()
-        self.assertEqual(mr.PatientName, 'CompressedSamples^MR1', "Wrong patient name")
+        self.assertEqual(mr.PatientName, 'CompressedSamples^MR1',
+                         "Wrong patient name")
         self.assertEqual(mr.PatientName, mr[0x10, 0x10].value,
-                         "Name does not match value found when accessed by tag number")
+                         "Name does not match value found when "
+                         "accessed by tag number")
         got = mr.PixelSpacing
         DS = pydicom.valuerep.DS
         expected = [DS('0.3125'), DS('0.3125')]
@@ -892,35 +977,48 @@ class ReadTruncatedFileTests(unittest.TestCase):
     def testReadFileWithMissingPixelDataArray(self):
         mr = read_file(truncated_mr_name)
         mr.decode()
-        with self.assertRaisesRegexp(AttributeError, "Amount of pixel data.*does not match the expected data"):
+        with self.assertRaisesRegexp(AttributeError,
+                                     "Amount of pixel data.*does not match "
+                                     "the expected data"):
             mr.pixel_array
 
 
 class FileLikeTests(unittest.TestCase):
-    """Test that can read DICOM files with file-like object rather than filename"""
+    """Test that can read DICOM files with file-like object rather than
+    filename
+    """
+
     def testReadFileGivenFileObject(self):
         """filereader: can read using already opened file............"""
         f = open(ct_name, 'rb')
         ct = read_file(f)
-        # Tests here simply repeat testCT -- perhaps should collapse the code together?
+        # Tests here simply repeat testCT -- perhaps should collapse
+        # the code together?
         got = ct.ImagePositionPatient
         DS = pydicom.valuerep.DS
         expected = [DS('-158.135803'), DS('-179.035797'), DS('-75.699997')]
-        self.assertTrue(got == expected, "ImagePosition(Patient) values not as expected")
-        self.assertEqual(ct.file_meta.ImplementationClassUID, '1.3.6.1.4.1.5962.2',
+        self.assertTrue(got == expected,
+                        "ImagePosition(Patient) values not as expected")
+        self.assertEqual(ct.file_meta.ImplementationClassUID,
+                         '1.3.6.1.4.1.5962.2',
                          "ImplementationClassUID not the expected value")
         self.assertEqual(ct.file_meta.ImplementationClassUID,
                          ct.file_meta[0x2, 0x12].value,
-                         "ImplementationClassUID does not match the value accessed by tag number")
-        # (0020, 0032) Image Position (Patient)  [-158.13580300000001, -179.035797, -75.699996999999996]
+                         "ImplementationClassUID does not match the "
+                         "value accessed by tag number")
+        # (0020, 0032) Image Position (Patient)
+        # [-158.13580300000001, -179.035797, -75.699996999999996]
         got = ct.ImagePositionPatient
         expected = [DS('-158.135803'), DS('-179.035797'), DS('-75.699997')]
-        self.assertTrue(got == expected, "ImagePosition(Patient) values not as expected")
+        self.assertTrue(got == expected,
+                        "ImagePosition(Patient) values not as expected")
         self.assertEqual(ct.Rows, 128, "Rows not 128")
         self.assertEqual(ct.Columns, 128, "Columns not 128")
         self.assertEqual(ct.BitsStored, 16, "Bits Stored not 16")
-        self.assertEqual(len(ct.PixelData), 128 * 128 * 2, "Pixel data not expected length")
-        # Should also be able to close the file ourselves without exception raised:
+        self.assertEqual(len(ct.PixelData), 128 * 128 * 2,
+                         "Pixel data not expected length")
+        # Should also be able to close the file ourselves without
+        # exception raised:
         f.close()
 
     def testReadFileGivenFileLikeObject(self):
@@ -932,13 +1030,17 @@ class FileLikeTests(unittest.TestCase):
         got = ct.ImagePositionPatient
         DS = pydicom.valuerep.DS
         expected = [DS('-158.135803'), DS('-179.035797'), DS('-75.699997')]
-        self.assertTrue(got == expected, "ImagePosition(Patient) values not as expected")
-        self.assertEqual(len(ct.PixelData), 128 * 128 * 2, "Pixel data not expected length")
-        # Should also be able to close the file ourselves without exception raised:
+        self.assertTrue(got == expected,
+                        "ImagePosition(Patient) values not as expected")
+        self.assertEqual(len(ct.PixelData), 128 * 128 * 2,
+                         "Pixel data not expected length")
+        # Should also be able to close the file ourselves without
+        # exception raised:
         file_like.close()
 
 
 if __name__ == "__main__":
     # This is called if run alone, but not if loaded through run_tests.py
-    # If not run from the directory where the sample images are, then need to switch there
+    # If not run from the directory where the sample images are, then need
+    # to switch there
     unittest.main()
diff --git a/tests/test_misc.py b/tests/test_misc.py
index 2472e99d6..040938495 100644
--- a/tests/test_misc.py
+++ b/tests/test_misc.py
@@ -3,12 +3,13 @@
 import unittest
 import os.path as osp
 
-from pydicom.misc import is_dicom
+from pydicom.misc import is_dicom, size_in_bytes
 
-test_file = osp.join(osp.dirname(osp.abspath(__file__)), 'test_files', 'CT_small.dcm')
+test_file = osp.join(osp.dirname(osp.abspath(__file__)), 'test_files',
+                     'CT_small.dcm')
 
-class Test_Misc(unittest.TestCase):
 
+class TestMisc(unittest.TestCase):
     def test_is_dicom(self):
         """Test the is_dicom function."""
         invalid_file = test_file.replace('CT_', 'CT')  # invalid file
@@ -22,3 +23,19 @@ class Test_Misc(unittest.TestCase):
 
         # test invalid path
         self.assertRaises(IOError, is_dicom, invalid_file)
+
+    def test_size_in_bytes(self):
+        """Test convenience function size_in_bytes()."""
+        # None or numbers shall be returned unchanged
+        self.assertIsNone(size_in_bytes(None))
+        self.assertEqual(1234, size_in_bytes(1234))
+
+        # string shall be parsed
+        self.assertEqual(1234, size_in_bytes('1234'))
+        self.assertEqual(4096, size_in_bytes('4 kb'))
+        self.assertEqual(0x4000, size_in_bytes('16 KB'))
+        self.assertEqual(0x300000, size_in_bytes('3  MB'))
+        self.assertEqual(0x80000000, size_in_bytes('2gB'))
+
+        self.assertRaises(ValueError, size_in_bytes, '2 TB')
+        self.assertRaises(ValueError, size_in_bytes, 'KB 2')