Skip to content

Commit 44e9853

Browse files
committed
Added SpyException base class for module-specific exceptions.
Module-specific exceptions are now all derived from SpyException. InvalidFileError is now raised instead of IOError if a file is determined to be invalid. New classes added: - spectral.SpyException - spectral.io.spyfile.InvalidFileError - spectral.io.envi.EnviDataFileNotFoundError
1 parent 6be8144 commit 44e9853

File tree

6 files changed

+64
-28
lines changed

6 files changed

+64
-28
lines changed

spectral/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@
4343
BIL = 1
4444
BIP = 2
4545

46+
class SpyException(Exception):
47+
'''Base class for spectral module-specific exceptions.'''
48+
pass
49+
4650
from .spectral import (open_image, load_training_sets, save_training_sets,
4751
settings, tile_image, spy_colors, BandInfo)
4852
from .io import *

spectral/io/aviris.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,13 @@ def open(file, band_file=None):
5757
5858
Raises:
5959
60-
IOError
60+
spectral.io.spyfile.InvalidFileError
6161
'''
6262
import numpy as np
6363
from spectral.io.bipfile import BipFile
6464
import os
6565
import glob
66-
from .spyfile import find_file_path
66+
from .spyfile import find_file_path, InvalidFileError
6767
import spectral
6868

6969
class Params:
@@ -75,7 +75,7 @@ class Params:
7575
p.ncols = 614
7676
fileSize = os.stat(p.filename)[6]
7777
if fileSize % 275072 != 0:
78-
raise IOError('File size not consistent with AVIRIS format.')
78+
raise InvalidFileError('File size not consistent with AVIRIS format.')
7979
p.nrows = int(fileSize / 275072)
8080
p.byte_order = 1
8181
p.dtype = np.dtype('i2').str

spectral/io/envi.py

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -69,24 +69,27 @@
6969
envi_to_dtype = dict((k, np.dtype(v).char) for (k, v) in dtype_map)
7070
dtype_to_envi = dict(tuple(reversed(item)) for item in list(envi_to_dtype.items()))
7171

72-
class EnviException(Exception):
72+
from spectral import SpyException
73+
from .spyfile import FileNotFoundError, InvalidFileError
74+
75+
class EnviException(SpyException):
7376
'''Base class for ENVI file-related exceptions.'''
7477
pass
7578

76-
class EnviDataTypeError(TypeError):
77-
'''Exception raised when saving invalid image data type to ENVI format.
79+
class EnviDataTypeError(EnviException, TypeError):
80+
'''Raised when saving invalid image data type to ENVI format.
7881
'''
7982
def __init__(self, dtype):
8083
msg = 'Image data type "{0}" can not be saved to ENVI data file. ' \
8184
'Call spectral.envi.get_supported_dtypes for a list of supported ' \
8285
'data type names.'.format(np.dtype(dtype).name)
8386
super(EnviDataTypeError, self).__init__(msg)
8487

85-
class EnviFeatureNotSupported(NotImplementedError):
88+
class EnviFeatureNotSupported(EnviException, NotImplementedError):
8689
'''A specified ENVI capability is not supported by the spectral module.'''
8790
pass
8891

89-
class FileNotAnEnviHeader(EnviException):
92+
class FileNotAnEnviHeader(EnviException, InvalidFileError):
9093
'''Raised when "ENVI" does not appear on the first line of the file.'''
9194
def __init__(self, msg):
9295
super(FileNotAnEnviHeader, self).__init__(msg)
@@ -97,12 +100,16 @@ def __init__(self, param):
97100
msg = 'Mandatory parameter "%s" missing from header file.' % param
98101
super(MissingEnviHeaderParameter, self).__init__(msg)
99102

100-
class EnviHeaderParsingError(EnviException):
103+
class EnviHeaderParsingError(EnviException, InvalidFileError):
101104
'''Raised upon failure to parse parameter/value pairs from a file.'''
102105
def __init__(self):
103106
msg = 'Failed to parse ENVI header file.'
104107
super(EnviHeaderParsingError, self).__init__(msg)
105108

109+
class EnviDataFileNotFoundError(EnviException, FileNotFoundError):
110+
'''Raised when data file associated with a header is not found.'''
111+
pass
112+
106113
def _validate_dtype(dtype):
107114
'''Raises EnviDataTypeError if dtype can not be written to ENVI file.'''
108115
typename = np.dtype(dtype).name
@@ -273,7 +280,7 @@ def open(file, image=None):
273280
274281
Raises:
275282
276-
TypeError, IOError.
283+
TypeError, EnviDataFileNotFoundError
277284
278285
If the specified file is not found in the current directory, all
279286
directories listed in the SPECTRAL_DATA environment variable will be
@@ -313,7 +320,10 @@ def open(file, image=None):
313320
image = testname
314321
break
315322
if not image:
316-
raise IOError('Unable to determine image file name.')
323+
msg = 'Unable to determine the ENVI data file name for the ' \
324+
'given header file. You can specify the data file by passing ' \
325+
'its name as the optional `image` argument to envi.open.'
326+
raise EnviDataFileNotFoundError(msg)
317327
else:
318328
image = find_file_path(image)
319329

@@ -367,15 +377,15 @@ def check_new_filename(hdr_file, img_ext, force):
367377
hdr_file = os.path.realpath(hdr_file)
368378
(base, ext) = os.path.splitext(hdr_file)
369379
if ext.lower() != '.hdr':
370-
raise ValueError('Header file name must end in ".hdr" or ".HDR".')
380+
raise EnviException('Header file name must end in ".hdr" or ".HDR".')
371381
image_file = base + img_ext
372382
if not force:
373383
if os.path.isfile(hdr_file):
374-
raise Exception('Header file %s already exists. Use `force` '
375-
'keyword to force overwrite.' % hdr_file)
384+
raise EnviException('Header file %s already exists. Use `force` '
385+
'keyword to force overwrite.' % hdr_file)
376386
if os.path.isfile(image_file):
377-
raise Exception('Image file %s already exists. Use `force` '
378-
'keyword to force overwrite.' % image_file)
387+
raise EnviException('Image file %s already exists. Use `force` '
388+
'keyword to force overwrite.' % image_file)
379389
return (hdr_file, image_file)
380390

381391

@@ -818,15 +828,15 @@ def create_image(hdr_file, metadata=None, **kwargs):
818828

819829
# Verify minimal set of parameters have been provided
820830
if 'lines' not in metadata:
821-
raise Exception('Number of image rows is not defined.')
831+
raise EnviException('Number of image rows is not defined.')
822832
elif 'samples' not in metadata:
823-
raise Exception('Number of image columns is not defined.')
833+
raise EnviException('Number of image columns is not defined.')
824834
elif 'bands' not in metadata:
825-
raise Exception('Number of image bands is not defined.')
835+
raise EnviException('Number of image bands is not defined.')
826836
elif 'samples' not in metadata:
827-
raise Exception('Number of image columns is not defined.')
837+
raise EnviException('Number of image columns is not defined.')
828838
elif 'data type' not in metadata:
829-
raise Exception('Image data type is not defined.')
839+
raise EnviException('Image data type is not defined.')
830840

831841
params = gen_params(metadata)
832842
dt = np.dtype(params.dtype).char

spectral/io/erdas.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,13 @@ def open(file):
105105
106106
Raises:
107107
108-
IOError
108+
spectral.io.spyfile.InvalidFileError
109109
'''
110110

111111
import numpy as np
112112
import spectral
113113
from .bilfile import BilFile
114-
from .spyfile import find_file_path
114+
from .spyfile import find_file_path, InvalidFileError
115115

116116

117117
# ERDAS 7.5 headers do not specify byte order so we'll guess little endian.
@@ -141,10 +141,11 @@ class Params:
141141
elif lh["packing"] == 0:
142142
p.dtype = np.dtype('i1').str
143143
elif lh["packing"] == 1:
144-
raise Exception(
145-
'4-bit data type not supported in SPy ERDAS/Lan format handler.')
144+
msg = '4-bit data type not supported in SPy ERDAS/Lan format handler.'
145+
raise InvalidFileError(msg)
146146
else:
147-
raise Exception('Unexpected data type specified in ERDAS/Lan header.')
147+
msg = 'Unexpected data type specified in ERDAS/Lan header.'
148+
raise InvalidFileError(msg)
148149
if spectral.byte_order != 0:
149150
p.dtype = np.dtype(p.dtype).newbyteorder().str
150151

@@ -168,6 +169,7 @@ def read_erdas_lan_header(fileName, byte_order=0):
168169
import sys
169170
import spectral
170171
from spectral.utilities.python23 import IS_PYTHON3, typecode
172+
from .spyfile import InvalidFileError
171173

172174
if IS_PYTHON3:
173175
import builtins
@@ -183,7 +185,7 @@ def read_erdas_lan_header(fileName, byte_order=0):
183185

184186
h["type"] = f.read(6)
185187
if h["type"] not in (b'HEAD74', b'HEADER'):
186-
raise IOError('Does not look like an ERDAS Lan header.')
188+
raise InvalidFileError('Does not look like an ERDAS Lan header.')
187189

188190
# Read all header data into arrays
189191
word = array(typecode('h'))

spectral/io/spyfile.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,14 @@
112112

113113
import numpy
114114
import numpy as np
115+
from spectral import SpyException
115116
from spectral.spectral import Image
116117

117-
class FileNotFoundError(Exception):
118+
class FileNotFoundError(SpyException):
119+
pass
120+
121+
class InvalidFileError(SpyException):
122+
'''Raised when file contents are invalid for the exepected file type.'''
118123
pass
119124

120125
def find_file_path(filename):

spectral/tests/envi.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,21 @@ def test_missing_ENVI_in_header_fails(self):
284284
else:
285285
raise Exception('Failed to raise EnviMissingHeaderParameter')
286286

287+
def test_open_missing_data_raises_envidatafilenotfounderror(self):
288+
'''EnviDataFileNotFound should be raise if data file is not found.'''
289+
import os
290+
import spectral as spy
291+
img = spy.open_image('92AV3C.lan')
292+
fname = os.path.join(testdir, 'header_without_data.hdr')
293+
spy.envi.save_image(fname, img, ext='.img')
294+
os.unlink(os.path.splitext(fname)[0] + '.img')
295+
try:
296+
img2 = spy.envi.open(fname)
297+
except spy.envi.EnviDataFileNotFoundError:
298+
pass
299+
else:
300+
raise Exception('Expected EnviDataFileNotFoundError')
301+
287302
def run():
288303
print('\n' + '-' * 72)
289304
print('Running ENVI tests.')

0 commit comments

Comments
 (0)