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