From 76958057df4013ce30f0d6d15b1699832e0aadab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edouard=20Choini=C3=A8re?= <27212526+echoix@users.noreply.github.com> Date: Sat, 13 Jul 2024 18:53:25 -0400 Subject: [PATCH] style: Fix read-whole-file (FURB101) and write-whole-file (FURB103) (#4047) * style: Fix read-whole-file (FURB101) Ruff rule: https://docs.astral.sh/ruff/rules/read-whole-file/ * style: Extract repeated config_directory variable in generate_release_notes * style: Fix write-whole-file (FURB103) Ruff rule: https://docs.astral.sh/ruff/rules/write-whole-file/ --- display/d.text/test.py | 5 +- gui/wxpython/core/render.py | 8 +- gui/wxpython/core/toolboxes.py | 4 +- gui/wxpython/gui_core/pyedit.py | 9 +- man/build_manual_gallery.py | 6 +- pyproject.toml | 2 - python/grass/benchmark/results.py | 7 +- python/grass/grassdb/history.py | 39 ++++--- python/grass/gunittest/invoker.py | 33 +++--- python/grass/gunittest/reporters.py | 12 +-- .../gunittest/testsuite/test_assertions.py | 12 +-- python/grass/jupyter/baseseriesmap.py | 4 +- python/grass/jupyter/interactivemap.py | 6 +- python/grass/pygrass/raster/category.py | 14 +-- python/grass/pygrass/shell/show.py | 5 +- .../benchmark/benchmark_r_mfilter_nprocs.py | 9 +- .../r.neighbors/testsuite/test_r_neighbors.py | 6 +- scripts/g.extension/g.extension.py | 15 +-- .../testsuite/test_addons_download.py | 3 +- scripts/r.in.wms/wms_base.py | 4 +- scripts/r.unpack/r.unpack.py | 4 +- scripts/v.db.addcolumn/v.db.addcolumn.py | 4 +- scripts/v.in.wfs/v.in.wfs.py | 11 +- .../testsuite/test_distr_tgis_db_raster.py | 7 +- .../testsuite/test_distr_tgis_db_raster3d.py | 7 +- .../testsuite/test_distr_tgis_db_vector.py | 7 +- .../testsuite/test_t_register_raster_file.py | 102 +++++++++--------- utils/g.html2man/g.html2man.py | 6 +- utils/generate_release_notes.py | 16 ++- utils/mkhtml.py | 4 +- utils/update_version.py | 4 +- 31 files changed, 175 insertions(+), 200 deletions(-) diff --git a/display/d.text/test.py b/display/d.text/test.py index ffc50cfc8aa..c68449ed7be 100755 --- a/display/d.text/test.py +++ b/display/d.text/test.py @@ -2,6 +2,7 @@ # Author: Owen Smith - Rewritten from test.pl by Huidae Cho # Run: d.mon start=wx0 && ./test.py | d.text at=0,100 import math +from pathlib import Path import re # Quiet black syntax checking for fonts and colors to keep the code printed to @@ -66,8 +67,8 @@ def text(in_text): color("gray") rc(1, 1) -with open(__file__) as f: - src = f.read() + +src = Path(__file__).read_text() print( ".L 0\n" diff --git a/gui/wxpython/core/render.py b/gui/wxpython/core/render.py index 6fe9d7f4592..2021f491fc1 100644 --- a/gui/wxpython/core/render.py +++ b/gui/wxpython/core/render.py @@ -22,6 +22,7 @@ """ import os +from pathlib import Path import sys import glob import math @@ -725,10 +726,9 @@ def OnRenderDone(self, env): continue if os.path.isfile(layer._legrow) and not layer.hidden: - with open(layer._legrow) as infile: - line = infile.read() - outfile.write(line) - new_legend.append(line) + line = Path(layer._legrow).read_text() + outfile.write(line) + new_legend.append(line) self._rendering = False if wx.IsBusy(): diff --git a/gui/wxpython/core/toolboxes.py b/gui/wxpython/core/toolboxes.py index e9960ac2e62..798df081e06 100644 --- a/gui/wxpython/core/toolboxes.py +++ b/gui/wxpython/core/toolboxes.py @@ -13,6 +13,7 @@ """ import os +from pathlib import Path import sys import copy import shutil @@ -846,8 +847,7 @@ def module_test(): return 0 menudataFile = "data/test_toolboxes_menudata_ref.xml" - with open(menudataFile) as correctMenudata: - correct = str(correctMenudata.read()) + correct = str(Path(menudataFile).read_text()) import difflib diff --git a/gui/wxpython/gui_core/pyedit.py b/gui/wxpython/gui_core/pyedit.py index 573496cbbfc..b7c8baf4001 100644 --- a/gui/wxpython/gui_core/pyedit.py +++ b/gui/wxpython/gui_core/pyedit.py @@ -10,6 +10,7 @@ :authors: Martin Landa """ +from pathlib import Path import sys import os import stat @@ -300,8 +301,7 @@ def _openFile(self, file_path): :return str or None: file content or None """ try: - with open(file_path, "r") as f: - return f.read() + return Path(file_path).read_text() except PermissionError: GError( message=_( @@ -327,9 +327,8 @@ def _writeFile(self, file_path, content, additional_err_message=""): :return None or True: file written or None """ try: - with open(file_path, "w") as f: - f.write(content) - return True + Path(file_path).write_text(content) + return True except PermissionError: GError( message=_( diff --git a/man/build_manual_gallery.py b/man/build_manual_gallery.py index 414b36c8a85..ea1ffb449c2 100755 --- a/man/build_manual_gallery.py +++ b/man/build_manual_gallery.py @@ -14,6 +14,7 @@ ############################################################################# import os +from pathlib import Path import sys import fnmatch import re @@ -97,9 +98,8 @@ def img_in_html(filename, imagename): # for some reason, calling search just once is much faster # than calling it on every line (time is spent in _compile) pattern = re.compile("".format(imagename)) - with open(filename) as file: - if re.search(pattern, file.read()): - return True + if re.search(pattern, Path(filename).read_text()): + return True return False diff --git a/pyproject.toml b/pyproject.toml index 4cc2f9a3d8d..7d544473f60 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -151,8 +151,6 @@ ignore = [ "FBT001", # boolean-type-hint-positional-argument "FBT002", # boolean-default-value-positional-argument "FBT003", # boolean-positional-value-in-call - "FURB101", # read-whole-file - "FURB103", # write-whole-file. "FURB118", # reimplemented-operator "FURB152", # math-constant "FURB154", # repeated-global diff --git a/python/grass/benchmark/results.py b/python/grass/benchmark/results.py index c89d8f1c80b..123e5dd8458 100644 --- a/python/grass/benchmark/results.py +++ b/python/grass/benchmark/results.py @@ -15,6 +15,7 @@ import copy import json +from pathlib import Path from types import SimpleNamespace @@ -48,8 +49,7 @@ def save_results_to_file(results, filename): See :func:`save_results` for details. """ text = save_results(results) - with open(filename, "w", encoding="utf-8") as file: - file.write(text) + Path(filename).write_text(text, encoding="utf-8") def load_results(data): @@ -67,8 +67,7 @@ def load_results_from_file(filename): See :func:`load_results` for details. """ - with open(filename, "r", encoding="utf-8") as file: - return load_results(file.read()) + return load_results(Path(filename).read_text(encoding="utf-8")) def join_results(results, prefixes=None, select=None, prefixes_as_labels=False): diff --git a/python/grass/grassdb/history.py b/python/grass/grassdb/history.py index 85ebdb5b452..60b5459700d 100644 --- a/python/grass/grassdb/history.py +++ b/python/grass/grassdb/history.py @@ -103,27 +103,24 @@ def _read_from_JSON(history_path): """ content_list = [] try: - with open( - history_path, encoding="utf-8", mode="r", errors="replace" - ) as file_history: - content = file_history.read() - if content: - try: - history_entries = json.loads(content) - except ValueError as ve: - raise ValueError( - _("Error decoding content of JSON history file {}").format( - history_path - ) - ) from ve - # Process the content as a list of dictionaries - content_list = [ - { - "command": entry["command"], - "command_info": entry["command_info"], - } - for entry in history_entries - ] + content = Path(history_path).read_text(encoding="utf-8", errors="replace") + if content: + try: + history_entries = json.loads(content) + except ValueError as ve: + raise ValueError( + _("Error decoding content of JSON history file {}").format( + history_path + ) + ) from ve + # Process the content as a list of dictionaries + content_list = [ + { + "command": entry["command"], + "command_info": entry["command_info"], + } + for entry in history_entries + ] except OSError as e: raise OSError( _("Unable to read from JSON history file {}").format(history_path) diff --git a/python/grass/gunittest/invoker.py b/python/grass/gunittest/invoker.py index 2b2de7f5e40..9a19be4c85d 100644 --- a/python/grass/gunittest/invoker.py +++ b/python/grass/gunittest/invoker.py @@ -11,6 +11,7 @@ import collections import os +from pathlib import Path import shutil import subprocess import sys @@ -39,8 +40,7 @@ # TODO: this might be more extend then update def update_keyval_file(filename, module, returncode): if os.path.exists(filename): - with open(filename, "r") as keyval_file: - keyval = text_to_keyvalue(keyval_file.read(), sep="=") + keyval = text_to_keyvalue(Path(filename).read_text(), sep="=") else: keyval = {} @@ -62,8 +62,7 @@ def update_keyval_file(filename, module, returncode): keyval["returncode"] = returncode keyval["test_file_authors"] = test_file_authors - with open(filename, "w") as keyval_file: - keyval_file.write(keyvalue_to_text(keyval)) + Path(filename).write_text(keyvalue_to_text(keyval)) return keyval @@ -243,8 +242,7 @@ def try_decode(data, encodings): stdout = try_decode(stdout, encodings=encodings) stderr = try_decode(stderr, encodings=encodings) - with open(stdout_path, "w") as stdout_file: - stdout_file.write(stdout) + Path(stdout_path).write_text(stdout) with open(stderr_path, "w") as stderr_file: if type(stderr) == "bytes": stderr_file.write(decode(stderr)) @@ -337,18 +335,17 @@ def run_in_location(self, gisdbase, location, location_type, results_dir, exclud # TODO: move this to some (new?) reporter # TODO: add basic summary of linked files so that the page is not empty - with open(os.path.join(results_dir, "index.html"), "w") as main_index: - main_index.write( - "" - "

Tests for <{location}>" - " using <{type}> type tests

" - "