Skip to content

Commit

Permalink
Enforce ruff/bugbear rule B904
Browse files Browse the repository at this point in the history
B904 Within an `except` clause, raise exceptions with `raise ... from err` or
     `raise ... from None` to distinguish them from errors in exception handling
  • Loading branch information
DimitriPapadopoulos committed May 28, 2024
1 parent 3338289 commit 78f1f2e
Show file tree
Hide file tree
Showing 12 changed files with 63 additions and 51 deletions.
4 changes: 2 additions & 2 deletions bin/create_iods_modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ def _create_modules(directory):
# https://github.com/innolitics/dicom-standard/tree/master/standard
try:
directory = sys.argv[1]
except IndexError:
raise ValueError('Path to directory must be provided.')
except IndexError as e:
raise ValueError('Path to directory must be provided.') from e
if not os.path.exists(directory):
raise OSError('Path does not exist: "{}"'.format(directory))
if not os.path.isdir(directory):
Expand Down
4 changes: 2 additions & 2 deletions src/highdicom/_module_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ def check_required_attributes(
for p in base_path:
try:
tree = tree['attributes'][p]
except KeyError:
raise AttributeError(f"Invalid base path: {base_path}.")
except KeyError as e:
raise AttributeError(f"Invalid base path: {base_path}.") from e

# Define recursive function
def check(
Expand Down
10 changes: 5 additions & 5 deletions src/highdicom/ann/content.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def get_values(self, number_of_annotations: int) -> np.ndarray:
f'annotation indices: {error}. This may either be due to '
'incorrect encoding of the measurements or due to incorrectly '
'specified "number_of_annotations".'
)
) from error
return values

@classmethod
Expand Down Expand Up @@ -339,11 +339,11 @@ def __init__(

try:
coordinates = np.concatenate(graphic_data, axis=0)
except ValueError:
except ValueError as e:
raise ValueError(
'Items of argument "graphic_data" must be arrays with the '
'same dimensions.'
)
) from e

if coordinates.dtype.kind in ('u', 'i'):
coordinates = coordinates.astype(np.float32)
Expand Down Expand Up @@ -420,8 +420,8 @@ def __init__(
)
try:
measured_values = item.get_values(self.NumberOfAnnotations)
except IndexError:
raise ValueError(error_message)
except IndexError as e:
raise ValueError(error_message) from e
if len(measured_values) != self.NumberOfAnnotations:
# This should not occur, but safety first.
raise ValueError(error_message)
Expand Down
10 changes: 6 additions & 4 deletions src/highdicom/color.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ def __init__(self, icc_profile: bytes):
"""
try:
self._icc_transform = self._build_icc_transform(icc_profile)
except OSError:
raise ValueError('Could not read ICC Profile.')
except OSError as e:
raise ValueError('Could not read ICC Profile.') from e

def transform_frame(self, array: np.ndarray) -> np.ndarray:
"""Transforms a frame by applying the ICC profile.
Expand Down Expand Up @@ -138,8 +138,10 @@ def _build_icc_transform(icc_profile: bytes) -> ImageCmsTransform:
profile: bytes
try:
profile = ImageCmsProfile(BytesIO(icc_profile))
except OSError:
raise ValueError('Cannot read ICC Profile in image metadata.')
except OSError as e:
raise ValueError(
'Cannot read ICC Profile in image metadata.'
) from e
name = getProfileName(profile).strip()
description = getProfileDescription(profile).strip()
logger.debug(f'found ICC Profile "{name}": "{description}"')
Expand Down
22 changes: 14 additions & 8 deletions src/highdicom/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,12 +313,14 @@ def open(self) -> None:
if self._fp is None:
try:
self._fp = DicomFile(str(self._filename), mode='rb')
except FileNotFoundError:
raise FileNotFoundError(f'File not found: "{self._filename}"')
except Exception:
except FileNotFoundError as e:
raise FileNotFoundError(
f'File not found: "{self._filename}"'
) from e
except Exception as e:
raise OSError(
f'Could not open file for reading: "{self._filename}"'
)
) from e
is_little_endian, is_implicit_VR = self._check_file_format(self._fp)
self._fp.is_little_endian = is_little_endian
self._fp.is_implicit_VR = is_implicit_VR
Expand Down Expand Up @@ -378,7 +380,9 @@ def _read_metadata(self) -> None:
try:
metadata = dcmread(self._fp, stop_before_pixels=True)
except Exception as err:
raise OSError(f'DICOM metadata cannot be read from file: "{err}"')
raise OSError(
f'DICOM metadata cannot be read from file: "{err}"'
) from err

# Cache Transfer Syntax UID, since we need it to decode frame items
self._transfer_syntax_uid = UID(metadata.file_meta.TransferSyntaxUID)
Expand All @@ -392,10 +396,10 @@ def _read_metadata(self) -> None:
# Determine whether dataset contains a Pixel Data element
try:
tag = TupleTag(self._fp.read_tag())
except EOFError:
except EOFError as e:
raise ValueError(
'Dataset does not represent an image information entity.'
)
) from e
if int(tag) not in _PIXEL_DATA_TAGS:
raise ValueError(
'Dataset does not represent an image information entity.'
Expand All @@ -413,7 +417,9 @@ def _read_metadata(self) -> None:
try:
self._basic_offset_table = _get_bot(self._fp, number_of_frames)
except Exception as err:
raise OSError(f'Failed to build Basic Offset Table: "{err}"')
raise OSError(
f'Failed to build Basic Offset Table: "{err}"'
) from err
self._first_frame_offset = self._fp.tell()
else:
if self._fp.is_implicit_VR:
Expand Down
4 changes: 2 additions & 2 deletions src/highdicom/ko/sop.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,11 @@ def resolve_reference(self, sop_instance_uid: str) -> Tuple[str, str, str]:
"""
try:
return self._reference_lut[sop_instance_uid]
except KeyError:
except KeyError as e:
raise ValueError(
'Could not find any evidence for SOP Instance UID '
f'"{sop_instance_uid}" in KOS document.'
)
) from e

@classmethod
def from_dataset(cls, dataset: Dataset) -> 'KeyObjectSelectionDocument':
Expand Down
18 changes: 10 additions & 8 deletions src/highdicom/legacy/sop.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,10 @@ def _convert_legacy_to_enhanced(
from highdicom._modules import MODULE_ATTRIBUTE_MAP
try:
ref_ds = sf_datasets[0]
except IndexError:
raise ValueError('No data sets of single-frame legacy images provided.')
except IndexError as e:
raise ValueError(
'No data sets of single-frame legacy images provided.'
) from e

if mf_dataset is None:
mf_dataset = Dataset()
Expand Down Expand Up @@ -455,8 +457,8 @@ def __init__(

try:
ref_ds = legacy_datasets[0]
except IndexError:
raise ValueError('No DICOM data sets of provided.')
except IndexError as e:
raise ValueError('No DICOM data sets of provided.') from e

if ref_ds.Modality != 'MR':
raise ValueError(
Expand Down Expand Up @@ -548,8 +550,8 @@ def __init__(

try:
ref_ds = legacy_datasets[0]
except IndexError:
raise ValueError('No DICOM data sets of provided.')
except IndexError as e:
raise ValueError('No DICOM data sets of provided.') from e

if ref_ds.Modality != 'CT':
raise ValueError(
Expand Down Expand Up @@ -627,8 +629,8 @@ def __init__(

try:
ref_ds = legacy_datasets[0]
except IndexError:
raise ValueError('No DICOM data sets of provided.')
except IndexError as e:
raise ValueError('No DICOM data sets of provided.') from e

if ref_ds.Modality != 'PT':
raise ValueError(
Expand Down
12 changes: 7 additions & 5 deletions src/highdicom/pm/sop.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,8 +456,8 @@ def __init__(
sffg_item.RealWorldValueMappingSequence = real_world_value_mappings
try:
real_world_value_mappings[0]
except IndexError:
raise TypeError(error_message)
except IndexError as e:
raise TypeError(error_message) from e
if not isinstance(
real_world_value_mappings[0],
RealWorldValueMapping
Expand All @@ -479,8 +479,8 @@ def __init__(
)
try:
real_world_value_mappings[0][0]
except IndexError:
raise TypeError(error_message)
except IndexError as e:
raise TypeError(error_message) from e
if not isinstance(
real_world_value_mappings[0][0],
RealWorldValueMapping
Expand Down Expand Up @@ -700,7 +700,9 @@ def __init__(
palette_color_lut_transformation,
'PaletteColorLookupTableUID'
):
self.PaletteColorLookupTableUID = palette_color_lut_transformation.PaletteColorLookupTableUID
self.PaletteColorLookupTableUID = (
palette_color_lut_transformation.PaletteColorLookupTableUID
)
else:
self.PixelPresentation = 'MONOCHROME'

Expand Down
2 changes: 1 addition & 1 deletion src/highdicom/seg/sop.py
Original file line number Diff line number Diff line change
Expand Up @@ -2061,7 +2061,7 @@ def __init__(
'Could not determine position of plane '
f'#{plane_index} in three dimensional coordinate '
f'system based on dimension index values: {error}'
)
) from error
else:
dimension_index_values = []

Expand Down
4 changes: 2 additions & 2 deletions src/highdicom/sr/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -624,11 +624,11 @@ def _get_coded_modality(sop_class_uid: str) -> Code:
}
try:
return sopclass_to_modality_map[sop_class_uid]
except KeyError:
except KeyError as e:
raise ValueError(
'SOP Class UID does not identify a SOP Class '
'for storage of an image information entity.'
)
) from e


class Template(ContentSequence):
Expand Down
8 changes: 4 additions & 4 deletions src/highdicom/sr/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,11 @@ def get_coded_name(item: Dataset) -> CodedConcept:
"""
try:
name = item.ConceptNameCodeSequence[0]
except AttributeError:
except AttributeError as e:
raise AttributeError(
'Dataset does not contain attribute "ConceptNameCodeSequence" and '
'thus doesn\'t represent a SR Content Item.'
)
) from e
return CodedConcept.from_dataset(name)


Expand All @@ -162,11 +162,11 @@ def get_coded_value(item: Dataset) -> CodedConcept:
"""
try:
value = item.ConceptCodeSequence[0]
except AttributeError:
except AttributeError as e:
raise AttributeError(
'Dataset does not contain attribute "ConceptCodeSequence" and '
'thus doesn\'t represent a SR Content Item of Value Type CODE.'
)
) from e
return CodedConcept.from_dataset(value)


Expand Down
16 changes: 8 additions & 8 deletions src/highdicom/sr/value_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,12 +424,12 @@ def index(self, val: ContentItem) -> int: # type: ignore[override]
error_message = f'Item "{val.name}" is not in Sequence.'
try:
matches = self._lut[val.name]
except KeyError:
raise ValueError(error_message)
except KeyError as e:
raise ValueError(error_message) from e
try:
index = matches.index(val)
except ValueError:
raise ValueError(error_message)
except ValueError as e:
raise ValueError(error_message) from e
return index

def find(self, name: Union[Code, CodedConcept]) -> 'ContentSequence':
Expand Down Expand Up @@ -618,17 +618,17 @@ def _check_dataset(
)
try:
ValueTypeValues(dataset.ValueType)
except TypeError:
except TypeError as e:
raise ValueError(
f'Item #{index} of sequence is not an SR Content Item '
f'because it has unknown Value Type "{dataset.ValueType}":'
f'\n{dataset}'
)
except AttributeError:
) from e
except AttributeError as e:
raise AttributeError(
f'Item #{index} of sequence is not an SR Content Item:\n'
f'{dataset}'
)
) from e
if not hasattr(dataset, 'RelationshipType') and not is_root and is_sr:
raise AttributeError(
f'Item #{index} of sequence is not a value SR Content Item '
Expand Down

0 comments on commit 78f1f2e

Please sign in to comment.