Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
d1f0e0e
style: Fix raise-without-from-inside-except (B904)
echoix Jul 8, 2024
7f0043d
Update frame.py
echoix Jul 13, 2024
eec6c40
Merge branch 'main' into fix-raise-without-from-inside-except
echoix Aug 1, 2024
2596b95
Merge branch 'main' into fix-raise-without-from-inside-except
echoix Mar 30, 2025
a161aac
python: Fix raise-without-from-inside-except (B904)
echoix Mar 30, 2025
22e5e9a
checks: Enable checking for ruff rule B904
echoix Mar 30, 2025
e9fa32d
Merge branch 'main' into fix-raise-without-from-inside-except
echoix May 9, 2025
05d238d
Merge branch 'main' into fix-raise-without-from-inside-except
echoix Jul 23, 2025
e398221
Merge branch 'main' into fix-raise-without-from-inside-except
echoix Jul 26, 2025
e10b250
Merge branch 'main' into fix-raise-without-from-inside-except
echoix Jul 26, 2025
270925a
Merge remote-tracking branch 'upstream/main' into fix-raise-without-f…
wenzeslaus Jul 13, 2026
daf9ef2
grass.pygrass: Do not suppress exception context outside of an except…
wenzeslaus Jul 13, 2026
e9a48ac
grass.script: Chain AttributeError in KeyValue.__getattr__
wenzeslaus Jul 13, 2026
1a279f6
wxGUI: Remove useless try-except in __ll_parts
wenzeslaus Jul 13, 2026
7f17734
grass.utils: Use one name for the caught exception in download_and_ex…
wenzeslaus Jul 13, 2026
4bdae19
Merge remote-tracking branch 'upstream/main' into HEAD
wenzeslaus Jul 14, 2026
2880e76
Merge remote-tracking branch 'upstream/main' into fix-raise-without-f…
wenzeslaus Jul 15, 2026
0d0f3f6
Merge remote-tracking branch 'upstream/main' into fix-raise-without-f…
wenzeslaus Jul 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gui/wxpython/animation/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ def SetName(self, name):
name = validateTimeseriesName(name, self._mapType)
self._maps = getRegisteredMaps(name, self._mapType)
except (GException, ScriptError) as e:
raise ValueError(str(e))
raise ValueError(str(e)) from e
else:
self._maps = validateMapNames(name.split(","), self._mapType)
self._name = name
Expand Down
4 changes: 2 additions & 2 deletions gui/wxpython/animation/nviztask.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ def Load(self, filename):
self.filename = filename
try:
gxwXml = ProcessWorkspaceFile(ET.parse(self.filename))
except Exception:
except Exception as e:
raise GException(
_(
"Reading workspace file <%s> failed.\n"
"Invalid file, unable to parse XML document."
)
% filename
)
) from e
# for display in gxwXml.displays:
# pprint(display)
# for layer in gxwXml.layers:
Expand Down
8 changes: 4 additions & 4 deletions gui/wxpython/core/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -1002,12 +1002,12 @@ def SaveToFile(self, settings=None):
with open(self.filePath, "w") as f:
json.dump(settings, f, indent=2, cls=SettingsJSONEncoder)
except OSError as e:
raise GException(e)
raise GException(e) from e
except Exception as e:
raise GException(
_("Writing settings to file <%(file)s> failed.\n\nDetails: %(detail)s")
% {"file": self.filePath, "detail": e}
)
) from e
return self.filePath

def _parseValue(self, value, read=False):
Expand Down Expand Up @@ -1109,10 +1109,10 @@ def Set(self, group, value, key=None, subkey=None, settings_type="user"):
settings[group][key][subkey] = value
return

except KeyError:
except KeyError as e:
raise GException(
"%s '%s:%s:%s'" % (_("Unable to set "), group, key, subkey)
)
) from e

def Append(self, dict, group, key, subkey, value, overwrite=True):
"""Set value of key/subkey
Expand Down
15 changes: 7 additions & 8 deletions gui/wxpython/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -471,14 +471,13 @@ def __ll_parts(value, reverse=False, precision=3):
m = m[:-1]
s = "0.0"
except ValueError:
try:
d = value
hs = d[-1]
d = d[:-1]
m = "0"
s = "0.0"
except ValueError:
raise ValueError
# Value without minutes and seconds. Errors are passed to the caller
# as they are.
d = value
hs = d[-1]
d = d[:-1]
m = "0"
s = "0.0"

if hs not in {"N", "S", "E", "W"}:
raise ValueError
Expand Down
10 changes: 5 additions & 5 deletions gui/wxpython/dbmgr/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,15 +179,15 @@ def LoadData(self, layer, columns=None, where=None, sql=None):
keyColumn = self.mapDBInfo.layers[layer]["key"]
try:
self.columns = self.mapDBInfo.tables[tableName]
except KeyError:
except KeyError as err:
raise GException(
_(
"Attribute table <%s> not found. "
"For creating the table switch to "
"'Manage layers' tab."
)
% tableName
)
) from err

if not columns:
columns = self.mapDBInfo.GetColumns(tableName)
Expand Down Expand Up @@ -1568,7 +1568,7 @@ def OnDataItemEdit(self, event):
raise ValueError(
_("Value '%(value)s' needs to be entered as %(type)s.")
% {"value": str(values[i]), "type": column["type"]}
)
) from None

if column["ctype"] == str:
if "'" in values[i]: # replace "'" -> "''"
Expand Down Expand Up @@ -1686,14 +1686,14 @@ def OnDataItemAdd(self, event):
"value": values[i],
"type": tlist.columns[columnName[i]]["type"],
}
)
) from None
except KeyError:
raise KeyError(
_("Column '%(column)s' does not exist.")
% {
"column": columnName[i],
}
)
) from None
columnsString += "%s," % columnName[i]

if tlist.columns[columnName[i]]["ctype"] == str:
Expand Down
2 changes: 1 addition & 1 deletion gui/wxpython/gmodeler/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ def LoadModel(self, filename):
gxmXml = ProcessModelFile(ET.parse(filename))
except Exception as e:
msg = "{}".format(e)
raise GException(msg)
raise GException(msg) from e

if self.canvas:
win = self.canvas.parent
Expand Down
6 changes: 3 additions & 3 deletions gui/wxpython/gui_core/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -3461,7 +3461,7 @@ def ParseCommand(self, cmd, completed=None):
global _blackList
self.grass_task = gtask.parse_interface(cmd[0], blackList=_blackList)
except (ScriptError, ValueError) as e:
raise gcmd.GException(e.value)
raise gcmd.GException(e.value) from e

# if layer parameters previously set, re-insert them into dialog
if completed is not None:
Expand Down Expand Up @@ -3491,15 +3491,15 @@ def ParseCommand(self, cmd, completed=None):
# parameter
try:
key, value = option.split("=", 1)
except ValueError:
except ValueError as e:
if self.grass_task.firstParam:
if i == 0: # add key name of first parameter if not given
key = self.grass_task.firstParam
value = option
else:
raise gcmd.GException(
_("Unable to parse command '%s'") % " ".join(cmd)
)
) from e
else:
continue

Expand Down
5 changes: 2 additions & 3 deletions gui/wxpython/gui_core/toolbars.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,11 +225,10 @@ def Enable(self, tool, enable=True):
id = getattr(self.widget, tool[0])
else:
id = getattr(self.widget, tool)
except AttributeError:
except AttributeError as e:
# TODO: test everything that this is not raised
# this error was ignored for a long time
raise AttributeError("Toolbar does not have a tool %s." % tool)
return
raise AttributeError("Toolbar does not have a tool %s." % tool) from e

self.classObject.EnableTool(self.widget, id, enable)

Expand Down
2 changes: 1 addition & 1 deletion gui/wxpython/mapdisp/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ def __next__(self):
try:
result = items[self._index]
except IndexError:
raise StopIteration
raise StopIteration from None
self._index += 1
return result

Expand Down
8 changes: 4 additions & 4 deletions gui/wxpython/rdigit/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -467,8 +467,8 @@ def _createNewMap(self, mapName, backgroundMap, mapType):
).strip()
if values:
self.uploadMapCategories.emit(values=values.split("\n"))
except CalledModuleError:
raise ScriptError
except CalledModuleError as e:
raise ScriptError(e.msg) from e
self._backupRaster(name)

name = name + "@" + gcore.gisenv()["MAPSET"]
Expand All @@ -494,8 +494,8 @@ def _backupRaster(self, name):
backup = name + "_backupcopy_" + str(os.getpid())
try:
gcore.run_command("g.copy", raster=[name, backup], quiet=True)
except CalledModuleError:
raise ScriptError
except CalledModuleError as e:
raise ScriptError(e.msg) from e

self._backupRasterName = backup

Expand Down
2 changes: 1 addition & 1 deletion gui/wxpython/wxgui.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def main(argv=None):
try:
opts, args = getopt.getopt(argv[1:], "hw:", ["help", "workspace"])
except getopt.error as msg:
raise Usage(msg)
raise Usage(msg) from None
except Usage as err:
print(err.msg, file=sys.stderr)
print(sys.stderr, "for help use --help", file=sys.stderr)
Expand Down
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,6 @@ ignore = [
"B026", # star-arg-unpacking-after-keyword-arg
"B028", # no-explicit-stacklevel
"B034", # re-sub-positional-args
"B904", # raise-without-from-inside-except
"B909", # loop-iterator-mutation
"BLE001", # blind-except
"C414", # unnecessary-double-cast-or-process
Expand Down
2 changes: 1 addition & 1 deletion python/grass/gunittest/case.py
Original file line number Diff line number Diff line change
Expand Up @@ -1336,7 +1336,7 @@ def runModule(cls, module, expecting_stdout=False, **kwargs):
# TODO: message format, parameters
raise CalledModuleError(
module.name, module.get_python(), module.returncode, errors=errors
)
) from None
# TODO: use this also in assert and apply when appropriate
if expecting_stdout and (not module.outputs.stdout.strip()):
if module.outputs.stderr:
Expand Down
4 changes: 2 additions & 2 deletions python/grass/imaging/images2avi.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ def writeAvi(
# Get fps
try:
fps = float(1.0 / duration)
except Exception:
raise ValueError(_("Invalid duration parameter for writeAvi."))
except Exception as e:
raise ValueError(_("Invalid duration parameter for writeAvi.")) from e

# Determine temp dir and create images
tempDir = os.path.join(os.path.expanduser("~"), ".tempIms")
Expand Down
8 changes: 4 additions & 4 deletions python/grass/pydispatch/dispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,18 +213,18 @@ def disconnect(receiver, signal=Any, sender=Any, weak=True):
try:
signals = connections[senderkey]
receivers = signals[signal]
except KeyError:
except KeyError as e:
raise errors.DispatcherKeyError(
"""No receivers found for signal %r from sender %r""" % (signal, sender)
)
) from e
try:
# also removes from receivers
_removeOldBackRefs(senderkey, signal, receiver, receivers)
except ValueError:
except ValueError as e:
raise errors.DispatcherKeyError(
"""No connection to receiver %s for signal %s from sender %s"""
% (receiver, signal, sender)
)
) from e
_cleanupConnections(senderkey, signal)


Expand Down
4 changes: 2 additions & 2 deletions python/grass/pygrass/raster/category.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ def _chk_index(self, index):
if isinstance(index, str):
try:
index = self.labels().index(index)
except ValueError:
raise KeyError(index)
except ValueError as error:
raise KeyError(index) from error
return index

def _chk_value(self, value):
Expand Down
4 changes: 3 additions & 1 deletion python/grass/pygrass/rpc/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,9 @@ def safe_receive(self, message):
except (EOFError, OSError, FatalError) as e:
# The pipe was closed by the checker thread because
# the server process was killed
raise FatalError("Exception raised: " + str(e) + " Message: " + message)
raise FatalError(
"Exception raised: " + str(e) + " Message: " + message
) from e
Comment thread
wenzeslaus marked this conversation as resolved.
Resolved

def stop(self):
"""Stop the check thread, the libgis server and close the pipe
Expand Down
2 changes: 1 addition & 1 deletion python/grass/pygrass/vector/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -1211,7 +1211,7 @@ def execute(self, sql_code=None, cursor=None, many=False, values=None):
"The SQL statement is not correct:\n%r,\n"
"values: %r,\n"
"SQL error: %s" % (sqlc, values, str(exc))
)
) from exc

def exist(self, cursor=None):
"""Return True if the table already exists in the DB, False otherwise
Expand Down
10 changes: 5 additions & 5 deletions python/grass/script/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1035,17 +1035,17 @@ def _parse_opts(lines: list) -> tuple[dict[str, str], dict[str, bool]]:
break
try:
var, val = line.split(b"=", 1)
except ValueError:
except ValueError as err:
msg = "invalid output from g.parser: {}".format(line)
raise SyntaxError(msg)
raise SyntaxError(msg) from err
try:
var = decode(var)
val = decode(val)
except UnicodeError as error:
msg = "invalid output from g.parser ({error}): {line}".format(
error=error, line=line
)
raise SyntaxError(msg)
raise SyntaxError(msg) from error
if var.startswith("flag_"):
flags[var[5:]] = bool(int(val))
elif var.startswith("opt_"):
Expand Down Expand Up @@ -2256,7 +2256,7 @@ def _set_location_description(path, location, text):
try:
_set_project_description(Path(path) / location, text)
except OSError as e:
raise ScriptError(repr(e))
raise ScriptError(repr(e)) from e


def _create_location_xy(database, location):
Expand All @@ -2273,7 +2273,7 @@ def _create_location_xy(database, location):
try:
create_xy_project(Path(database) / location)
except OSError as e:
raise ScriptError(repr(e))
raise ScriptError(repr(e)) from e
Comment thread
wenzeslaus marked this conversation as resolved.
Resolved


# interface to g.version
Expand Down
4 changes: 2 additions & 2 deletions python/grass/script/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ def get_interface_description(cmd):
"Unable to fetch interface description for command '<{cmd}>'."
"\n\nDetails: <{det}>"
).format(cmd=cmd, det=e)
)
) from e
Comment thread
wenzeslaus marked this conversation as resolved.
Resolved

desc = convert_xml_to_utf8(cmdout)
return desc.replace(
Expand Down Expand Up @@ -520,7 +520,7 @@ def parse_interface(name, parser=processTask, blackList=None):
_("Cannot parse interface description of <{name}> module: {error}").format(
name=name, error=error
)
)
) from error
task = parser(tree, blackList=blackList).get_task()
# if name from interface is different than the originally
# provided name, then the provided name is likely a full path needed
Expand Down
2 changes: 1 addition & 1 deletion python/grass/script/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ def __getattr__(self, key: str) -> VT:
try:
return self[key]
except KeyError:
raise AttributeError(key)
raise AttributeError(key) from None

def __setattr__(self, key: str, value: VT) -> None:
self[key] = value
Expand Down
6 changes: 3 additions & 3 deletions python/grass/script/vector.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ def vector_what(
try:
ret = read_command("v.what", env=env, **cmdParams).strip()
except CalledModuleError as e:
raise ScriptError(e.msg)
raise ScriptError(e.msg) from e

data = []
if not ret:
Expand All @@ -460,10 +460,10 @@ def vector_what(

try:
result = json.loads(ret, **kwargs)
except ValueError:
except ValueError as err:
raise ScriptError(
_("v.what output is not valid JSON format:\n {ret}").format(ret=ret)
)
) from err

if multiple:
for vmap in result["Maps"]:
Expand Down
4 changes: 2 additions & 2 deletions python/grass/semantic_label/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def _read_config(self):
config = json.load(fd, object_pairs_hook=OrderedDict)
except json.decoder.JSONDecodeError as e:
msg = "Unable to parse '{}': {}".format(json_file, e)
raise SemanticLabelReaderError(msg)
raise SemanticLabelReaderError(msg) from e

# check if configuration is valid
self._check_config(config)
Expand Down Expand Up @@ -112,7 +112,7 @@ def print_info(self, shortcut=None, band=None, semantic_label=None, extended=Fal
continue
except re.error as e:
msg = "Invalid pattern: {}".format(e)
raise SemanticLabelReaderError(msg)
raise SemanticLabelReaderError(msg) from e

found = True
if band and band not in item["bands"]:
Expand Down
Loading
Loading