diff --git a/.travis.yml b/.travis.yml
index fef41fff360dbb1b2d04087e53f5473eec94114a..f09a211617421649a2b9fd5d1f84948d9372d319 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -55,8 +55,8 @@ after_success:
   - source deactivate
   - conda install -q conda-build anaconda-client
   - conda config --set anaconda_upload no
-  - conda build recipe -q
-  - builddir=(`conda build recipe --output`)
+  - travis_wait conda build recipe -q
+  - travis_wait builddir=(`conda build recipe --output`)
   - |
     if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
       anaconda -t="$CONDA_UPLOAD_TOKEN" upload $builddir --force;
diff --git a/plio/io/io_controlnetwork.py b/plio/io/io_controlnetwork.py
index 1dc4d22bf907a9ddf5a775cd0e09ffe9076e63f3..a10652e2cda82c6c6fed226ab2983187f16c844b 100644
--- a/plio/io/io_controlnetwork.py
+++ b/plio/io/io_controlnetwork.py
@@ -42,19 +42,19 @@ class MeasureMessageType(IntEnum):
     MaximumPixelZScore = 4
     PixelShift = 5
     WholePixelCorrelation = 6
-    SubPixelCorrelation = 7 
+    SubPixelCorrelation = 7
 
 class MeasureLog():
-    
+
     def __init__(self, messagetype, value):
         """
         A protobuf compliant measure log object.
-        
+
         Parameters
         ----------
         messagetype : int or str
                       Either the integer or string representation from the MeasureMessageType enum
-                      
+
         value : int or float
                 The value to be stored in the message log
         """
@@ -64,19 +64,19 @@ class MeasureLog():
         else:
             # by name
             self.messagetype = MeasureMessageType[messagetype]
-        
+
         if not isinstance(value, (float, int)):
             raise TypeError(f'{value} is not a numeric type')
         self.value = value
-        
+
     def __repr__(self):
         return f'{self.messagetype.name}: {self.value}'
-        
+
     def to_protobuf(self, version=2):
         """
         Return protobuf compliant measure log object representation
         of this class.
-        
+
         Returns
         -------
         log_message : obj
@@ -148,7 +148,7 @@ def to_isis(obj, path, mode='wb', version=2,
                                          buffer_header_size, points_bytes,
                                          creation_date, modified_date)
 
-        store.write(header)
+        store.write(header.encode('utf-8'))
 
 class IsisStore(object):
     """
@@ -283,7 +283,7 @@ class IsisStore(object):
 
         # Munge the MeasureLogData into Python objs
         df['measureLog'] = df['measureLog'].apply(lambda x: [MeasureLog.from_protobuf(i) for i in x])
-        
+
         df.header = pvl_header
         return df
 
@@ -292,8 +292,8 @@ class IsisStore(object):
         """
         Parameters
         ----------
-        data : str
-               to be written to the file
+        data : bytes
+               Encoded header to be written to the file
         offset : int
                  The byte offset into the output binary
         """
@@ -461,7 +461,7 @@ class IsisStore(object):
            An ISIS compliant PVL header object
         """
 
-        encoder = pvl.encoder.IsisCubeLabelEncoder
+        encoder = pvl.encoder.ISISEncoder(end_delimiter=False)
 
         header_bytes = buffer_header_size
         points_start_byte = HEADERSTARTBYTE + buffer_header_size
@@ -489,4 +489,4 @@ class IsisStore(object):
                  )
         ])
 
-        return pvl.dumps(header, cls=encoder)
+        return pvl.dumps(header, encoder=encoder)
diff --git a/plio/io/io_spectral_profiler.py b/plio/io/io_spectral_profiler.py
index e2892aa0d89f807a463fef2e25dad94212b9ee03..b10a14aec841851cf8ba697c71cce411e40a20e7 100755
--- a/plio/io/io_spectral_profiler.py
+++ b/plio/io/io_spectral_profiler.py
@@ -100,12 +100,12 @@ class Spectral_Profiler(object):
                          "^SP_SPECTRUM_REF1", "^SP_SPECTRUM_QA", "^L2D_RESULT_ARRAY",
                          "^SP_SPECTRUM_RAD"]:
                     continue
-                if isinstance(v, pvl._collections.Units):
+                if isinstance(v, pvl.collections.Quantity):
                     k = "{}_{}".format(k, v.units)
                     v = v.value
                 keys.append(k)
                 vals.append(v)
-            
+
             vals = [vals] * len(self.ancillary_data)
             new_anc = pd.DataFrame(vals, index=self.ancillary_data.index, columns=keys)
             self.ancillary_data = self.ancillary_data.join(new_anc, how='inner')
diff --git a/plio/io/io_tes.py b/plio/io/io_tes.py
index d084dd7be0bcd6e7032fcd1e4df868f4d0748505..588900666283f69e1b5604395ff126a465d11b03 100644
--- a/plio/io/io_tes.py
+++ b/plio/io/io_tes.py
@@ -239,7 +239,7 @@ class Tes(object):
             with open(var_file, "rb") as var:
                 buffer = var.read()
                 def process_rad(index):
-                    if index is -1:
+                    if index == -1:
                         return None
 
                     length = np.frombuffer(buffer[index:index+2], dtype='>u2')[0]
diff --git a/plio/io/isis_serial_number.py b/plio/io/isis_serial_number.py
index 21edbad29ccfffd081a59f04fe026c5039d7cfe5..faba3bf52d9cd7b4b7e6293969f2199e61bb933e 100644
--- a/plio/io/isis_serial_number.py
+++ b/plio/io/isis_serial_number.py
@@ -2,6 +2,7 @@ import warnings
 
 import pvl
 from pvl.collections import PVLModule
+from itertools import chain
 
 import plio
 from plio.data import get_data
@@ -70,7 +71,7 @@ def generate_serial_number(label):
        The ISIS compatible serial number
     """
     if not isinstance(label, PVLModule):
-        label = pvl.load(label, cls=SerialNumberDecoder)
+        label = pvl.load(label, decoder=SerialNumberDecoder())
     # Get the translation information
     translation = get_isis_translation(label)
 
@@ -99,6 +100,7 @@ def generate_serial_number(label):
             serial_number.append(serial_entry)
         except:
             pass
+
     return '/'.join(serial_number)
 
 
@@ -108,13 +110,69 @@ class SerialNumberDecoder(pvl.decoder.PVLDecoder):
     serial number. Inherits from the PVLDecoder in planetarypy's pvl module.
     """
 
-    def cast_unquoated_string(self, value):
-        """
-        Overrides the parent class's method so that any un-quoted string type value found in the
-        parsed pvl will just return the original value. This is needed so that keyword values
-        are not re-formatted from what is originally in the ISIS cube label.
+    def decode_simple_value(self, value: str):
+        """Returns a Python object based on *value*, assuming
+        that *value* can be decoded as a PVL Simple Value::
 
-        Note: This affects value types that are recognized as null, boolean, number, datetime,
-        et at.
+         <Simple-Value> ::= (<Numeric> | <String>)
+
+         Modified from https://pvl.readthedocs.io/en/stable/_modules/pvl/decoder.html#PVLDecoder.decode_simple_value
+         Modification entails stripping datetime from list of functions.
+        """
+        for d in (
+            self.decode_quoted_string,
+            self.decode_non_decimal,
+            self.decode_decimal,
+        ):
+            try:
+                return d(value)
+            except ValueError:
+                pass
+
+        if value.casefold() == self.grammar.none_keyword.casefold():
+            return None
+
+        if value.casefold() == self.grammar.true_keyword.casefold():
+            return True
+
+        if value.casefold() == self.grammar.false_keyword.casefold():
+            return False
+
+        return self.decode_unquoted_string(value)
+
+    def decode_unquoted_string(self, value: str) -> str:
+        """Returns a Python ``str`` if *value* can be decoded
+        as an unquoted string, based on this decoder's grammar.
+        Raises a ValueError otherwise.
+
+        Modified from: https://pvl.readthedocs.io/en/stable/_modules/pvl/decoder.html#PVLDecoder.decode_unquoted_string
+        Modification entails removal of decode_datetime call
         """
-        return value.decode('utf-8')
+        for coll in (
+            ("a comment", chain.from_iterable(self.grammar.comments)),
+            ("some whitespace", self.grammar.whitespace),
+            ("a special character", self.grammar.reserved_characters),
+        ):
+            for item in coll[1]:
+                if item in value:
+                    raise ValueError(
+                        "Expected a Simple Value, but encountered "
+                        f'{coll[0]} in "{self}": "{item}".'
+                    )
+
+        agg_keywords = self.grammar.aggregation_keywords.items()
+        for kw in chain.from_iterable(agg_keywords):
+            if kw.casefold() == value.casefold():
+                raise ValueError(
+                    "Expected a Simple Value, but encountered "
+                    f'an aggregation keyword: "{value}".'
+                )
+
+        for es in self.grammar.end_statements:
+            if es.casefold() == value.casefold():
+                raise ValueError(
+                    "Expected a Simple Value, but encountered "
+                    f'an End-Statement: "{value}".'
+                )
+
+        return str(value)
diff --git a/plio/utils/utils.py b/plio/utils/utils.py
index 64eba371c93eb9961a04e509bbeb58da97ed5d51..3b5286f9568ab920714eb8a4ce91388745537567 100644
--- a/plio/utils/utils.py
+++ b/plio/utils/utils.py
@@ -28,7 +28,7 @@ def is_number(s):
         return True
     except ValueError:
         return False
-    
+
 def convert_string_to_float(s):
     """
     Attempt to convert a string to a float.
@@ -44,7 +44,7 @@ def convert_string_to_float(s):
       If successful, the converted value, else the argument is passed back
       out.
     """
-    
+
     try:
         return float(s)
     except TypeError:
@@ -240,7 +240,7 @@ def split_all_ext(path):
     """
     base, ext = os.path.splitext(path)
 
-    while len(ext) is not 0:
+    while len(ext) != 0:
         base, ext = os.path.splitext(base)
 
     return base