Skip to content

Commit

Permalink
python: Use comprehensions when initializing lists and dicts (OSGeo#4909
Browse files Browse the repository at this point in the history
)

* python: Use comprehensions when initializing lists and dicts

* style: Fix FURB140 [*] Use `itertools.starmap` instead of the generator
  • Loading branch information
echoix authored Jan 4, 2025
1 parent dd87856 commit ed80a6e
Show file tree
Hide file tree
Showing 25 changed files with 144 additions and 209 deletions.
4 changes: 1 addition & 3 deletions python/grass/benchmark/results.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,7 @@ def join_results_from_files(
source_filenames, prefixes=None, select=None, prefixes_as_labels=False
):
"""Join multiple files into one results object."""
to_merge = []
for result_file in source_filenames:
to_merge.append(load_results_from_file(result_file))
to_merge = [load_results_from_file(result_file) for result_file in source_filenames]
return join_results(
to_merge,
prefixes=prefixes,
Expand Down
25 changes: 11 additions & 14 deletions python/grass/benchmark/testsuite/test_benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,10 @@ def test_resolutions(self):
},
]
resolutions = [300, 200, 100]
results = []
for benchmark in benchmarks:
results.append(
benchmark_resolutions(
**benchmark,
resolutions=resolutions,
)
)
results = [
benchmark_resolutions(**benchmark, resolutions=resolutions)
for benchmark in benchmarks
]
plot_file = "test_res_plot.png"
num_cells_plot(results, filename=plot_file)
self.assertTrue(Path(plot_file).is_file())
Expand All @@ -76,9 +72,9 @@ def test_single(self):
"label": label,
}
]
results = []
for benchmark in benchmarks:
results.append(benchmark_single(**benchmark, repeat=repeat))
results = [
benchmark_single(**benchmark, repeat=repeat) for benchmark in benchmarks
]
self.assertEqual(len(results), len(benchmarks))
for result in results:
self.assertTrue(hasattr(result, "all_times"))
Expand All @@ -100,9 +96,10 @@ def test_nprocs(self):
"max_nprocs": 4,
}
]
results = []
for benchmark in benchmarks:
results.append(benchmark_nprocs(**benchmark, repeat=repeat, shuffle=True))
results = [
benchmark_nprocs(**benchmark, repeat=repeat, shuffle=True)
for benchmark in benchmarks
]
self.assertEqual(len(results), len(benchmarks))
for result in results:
self.assertTrue(hasattr(result, "times"))
Expand Down
3 changes: 1 addition & 2 deletions python/grass/benchmark/testsuite/test_benchmark_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ class TestBenchmarkCLI(TestCase):
"""Tests that benchmarkin CLI works"""

json_filename = "plot_test.json"
png_filenames = [f"plot_test1_{i}.png" for i in range(4)]
png_filenames.append("plot_test2.png")
png_filenames = [*[f"plot_test1_{i}.png" for i in range(4)], "plot_test2.png"]

def tearDown(self):
"""Remove test files"""
Expand Down
25 changes: 9 additions & 16 deletions python/grass/grassdb/checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import grass.grassdb.config as cfg
import grass.script as gs
from grass.script import gisenv
from itertools import starmap


def mapset_exists(path: str | os.PathLike[str], location=None, mapset=None) -> bool:
Expand Down Expand Up @@ -536,10 +537,7 @@ def get_reasons_locations_not_removable(locations):
Returns messages as list if there were any failed checks, otherwise empty list.
"""
messages = []
for grassdb, location in locations:
messages += get_reasons_location_not_removable(grassdb, location)
return messages
return list(starmap(get_reasons_location_not_removable, locations))


def get_reasons_location_not_removable(grassdb, location):
Expand Down Expand Up @@ -570,9 +568,7 @@ def get_reasons_location_not_removable(grassdb, location):
)

# Append to the list of tuples
mapsets = []
for g_mapset in g_mapsets:
mapsets.append((grassdb, location, g_mapset))
mapsets = [(grassdb, location, g_mapset) for g_mapset in g_mapsets]

# Concentenate both checks
messages += get_reasons_mapsets_not_removable(mapsets, check_permanent=False)
Expand Down Expand Up @@ -601,9 +597,7 @@ def get_reasons_grassdb_not_removable(grassdb):
g_locations = get_list_of_locations(grassdb)

# Append to the list of tuples
locations = []
for g_location in g_locations:
locations.append((grassdb, g_location))
locations = [(grassdb, g_location) for g_location in g_locations]
return get_reasons_locations_not_removable(locations)


Expand All @@ -614,12 +608,11 @@ def get_list_of_locations(dbase):
:return: list of locations (sorted)
"""
locations = []
for location in glob.glob(os.path.join(dbase, "*")):
if os.path.join(location, "PERMANENT") in glob.glob(
os.path.join(location, "*")
):
locations.append(os.path.basename(location))
locations = [
os.path.basename(location)
for location in glob.glob(os.path.join(dbase, "*"))
if os.path.join(location, "PERMANENT") in glob.glob(os.path.join(location, "*"))
]

locations.sort(key=lambda x: x.lower())

Expand Down
4 changes: 1 addition & 3 deletions python/grass/gunittest/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,7 @@ def discover(self, start_dir, pattern="test*.py", top_level_dir=None):
universal_location_value=self.universal_tests_value,
import_modules=True,
)
tests = []
for module in modules:
tests.append(self.loadTestsFromModule(module.module))
tests = [self.loadTestsFromModule(module.module) for module in modules]
return self.suiteClass(tests)


Expand Down
63 changes: 28 additions & 35 deletions python/grass/gunittest/reporters.py
Original file line number Diff line number Diff line change
Expand Up @@ -853,41 +853,34 @@ def finish(self):
svn_info = get_svn_info()
svn_revision = "" if not svn_info else svn_info["revision"]

summary = {}
summary["files_total"] = self.test_files
summary["files_successes"] = self.files_pass
summary["files_failures"] = self.files_fail

summary["names"] = self.names
summary["tested_dirs"] = self.tested_dirs
# TODO: we don't have a general mechanism for storing any type in text
summary["files_returncodes"] = [str(item) for item in self.files_returncodes]

# let's use seconds as a universal time delta format
# (there is no standard way how to store time delta as string)
summary["time"] = self.main_time.total_seconds()

status = "failed" if self.files_fail else "succeeded"
summary["status"] = status

summary["total"] = self.total
summary["successes"] = self.successes
summary["failures"] = self.failures
summary["errors"] = self.errors
summary["skipped"] = self.skipped
summary["expected_failures"] = self.expected_failures
summary["unexpected_successes"] = self.unexpected_success

summary["test_files_authors"] = self.test_files_authors
summary["tested_modules"] = self.modules
summary["svn_revision"] = svn_revision
# ignoring issues with time zones
summary["timestamp"] = self.main_start_time.strftime("%Y-%m-%d %H:%M:%S")
# TODO: add some general metadata here (passed in constructor)

# add additional information
for key, value in self._info.items():
summary[key] = value
summary = {
"files_total": self.test_files,
"files_successes": self.files_pass,
"files_failures": self.files_fail,
"names": self.names,
"tested_dirs": self.tested_dirs,
# TODO: we don't have a general mechanism for storing any type in text
"files_returncodes": [str(item) for item in self.files_returncodes],
# let's use seconds as a universal time delta format
# (there is no standard way how to store time delta as string)
"time": self.main_time.total_seconds(),
"status": "failed" if self.files_fail else "succeeded",
"total": self.total,
"successes": self.successes,
"failures": self.failures,
"errors": self.errors,
"skipped": self.skipped,
"expected_failures": self.expected_failures,
"unexpected_successes": self.unexpected_success,
"test_files_authors": self.test_files_authors,
"tested_modules": self.modules,
"svn_revision": svn_revision,
# ignoring issues with time zones
"timestamp": self.main_start_time.strftime("%Y-%m-%d %H:%M:%S"),
# TODO: add some general metadata here (passed in constructor)
# add additional information
**dict(self._info.items()),
}

summary_filename = os.path.join(self.result_dir, "test_keyvalue_result.txt")
text = keyvalue_to_text(summary, sep="=", vsep="\n", isep=",")
Expand Down
8 changes: 2 additions & 6 deletions python/grass/imaging/images2gif.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,9 +508,7 @@ def writeGifPillow(filename, images, duration=0.1, repeat=True):
"""
loop = 0 if repeat else 1
quantized = []
for im in images:
quantized.append(im.quantize())
quantized = [im.quantize() for im in images]
quantized[0].save(
filename,
save_all=True,
Expand Down Expand Up @@ -667,9 +665,7 @@ def readGif(filename, asNumpy=True):
# Convert to normal PIL images if needed
if not asNumpy:
images2 = images
images = []
for im in images2:
images.append(PIL.Image.fromarray(im))
images = [PIL.Image.fromarray(im) for im in images2]

# Done
return images
Expand Down
4 changes: 1 addition & 3 deletions python/grass/imaging/images2swf.py
Original file line number Diff line number Diff line change
Expand Up @@ -987,9 +987,7 @@ def readSwf(filename, asNumpy=True):
# Convert to normal PIL images if needed
if not asNumpy:
images2 = images
images = []
for im in images2:
images.append(PIL.Image.fromarray(im))
images = [PIL.Image.fromarray(im) for im in images2]

# Done
return images
4 changes: 1 addition & 3 deletions python/grass/jupyter/baseseriesmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,9 +239,7 @@ def save(
if not self._layers_rendered:
self.render()

input_files = []
for index in self._indices:
input_files.append(self._base_filename_dict[index])
input_files = [self._base_filename_dict[index] for index in self._indices]

save_gif(
input_files,
Expand Down
41 changes: 17 additions & 24 deletions python/grass/pygrass/modules/grid/grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,34 +319,27 @@ def get_cmd(cmdd):
>>> get_cmd(slp.get_dict()) # doctest: +ELLIPSIS
['r.slope.aspect', 'elevation=ele', 'format=degrees', ..., '--o']
"""
cmd = [
return [
cmdd["name"],
]
cmd.extend(("%s=%s" % (k, v) for k, v in cmdd["inputs"] if not isinstance(v, list)))
cmd.extend(
(
*("%s=%s" % (k, v) for k, v in cmdd["inputs"] if not isinstance(v, list)),
*(
"%s=%s"
% (
k,
",".join(vals if isinstance(vals[0], str) else [repr(v) for v in vals]),
)
for k, vals in cmdd["inputs"]
if isinstance(vals, list)
)
)
cmd.extend(
("%s=%s" % (k, v) for k, v in cmdd["outputs"] if not isinstance(v, list))
)
cmd.extend(
(
),
*("%s=%s" % (k, v) for k, v in cmdd["outputs"] if not isinstance(v, list)),
*(
"%s=%s" % (k, ",".join([repr(v) for v in vals]))
for k, vals in cmdd["outputs"]
if isinstance(vals, list)
)
)
cmd.extend(f"-{flg}" for flg in cmdd["flags"] if len(flg) == 1)
cmd.extend(f"--{flg[0]}" for flg in cmdd["flags"] if len(flg) > 1)
return cmd
),
*(f"-{flg}" for flg in cmdd["flags"] if len(flg) == 1),
*(f"--{flg[0]}" for flg in cmdd["flags"] if len(flg) > 1),
]


def cmd_exe(args):
Expand Down Expand Up @@ -385,10 +378,7 @@ def cmd_exe(args):
sub.Popen(["g.region", "raster=%s" % key], shell=shell, env=env).wait()
else:
# set the computational region
lcmd = [
"g.region",
]
lcmd.extend(["%s=%s" % (k, v) for k, v in bbox.items()])
lcmd = ["g.region", *["%s=%s" % (k, v) for k, v in bbox.items()]]
sub.Popen(lcmd, shell=shell, env=env).wait()
if groups:
copy_groups(groups, gisrc_src, gisrc_dst)
Expand Down Expand Up @@ -602,9 +592,12 @@ def get_works(self):
for key in self.inlist:
inms[key] = "%s@%s" % (self.inlist[key][indx], self.mset.name)
# set the computational region, prepare the region parameters
bbox = {k[0]: str(v) for k, v in box.items()[:-2]}
bbox["nsres"] = "%f" % reg.nsres
bbox["ewres"] = "%f" % reg.ewres
bbox = {
**{k[0]: str(v) for k, v in box.items()[:-2]},
"nsres": "%f" % reg.nsres,
"ewres": "%f" % reg.ewres,
}

new_mset = (
self.msetstr % (self.start_row + row, self.start_col + col),
)
Expand Down
22 changes: 10 additions & 12 deletions python/grass/pygrass/modules/grid/split.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,9 @@ def split_region_in_overlapping_tiles(region=None, width=100, height=100, overla
box_list = []
# print reg
for row in range(nrows):
row_list = []
for col in range(ncols):
# print 'c', c, 'r', r
row_list.append(get_bbox(reg, row, col, width, height, overlap))
row_list = [
get_bbox(reg, row, col, width, height, overlap) for col in range(ncols)
]
box_list.append(row_list)
return box_list

Expand All @@ -123,9 +122,10 @@ def split_region_tiles(region=None, width=100, height=100):
nrows = (reg.rows + height - 1) // height
box_list = []
for row in range(nrows):
row_list = []
for col in range(ncols):
row_list.append(get_tile_start_end_row_col(reg, row, col, width, height))
row_list = [
get_tile_start_end_row_col(reg, row, col, width, height)
for col in range(ncols)
]
box_list.append(row_list)
return box_list

Expand All @@ -146,11 +146,9 @@ def get_overlap_region_tiles(region=None, width=100, height=100, overlap=0):
ncols = (reg.cols + width - 1) // width
nrows = (reg.rows + height - 1) // height
box_list = []
# print reg
for row in range(nrows):
row_list = []
for col in range(ncols):
# print 'c', c, 'r', r
row_list.append(get_bbox(reg, row, col, width, height, -overlap))
row_list = [
get_bbox(reg, row, col, width, height, -overlap) for col in range(ncols)
]
box_list.append(row_list)
return box_list
12 changes: 6 additions & 6 deletions python/grass/pygrass/modules/interface/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -774,12 +774,12 @@ def get_dict(self):
"""Return a dictionary that includes the name, all valid
inputs, outputs and flags
"""
dic = {}
dic["name"] = self.name
dic["inputs"] = [(k, v.value) for k, v in self.inputs.items() if v.value]
dic["outputs"] = [(k, v.value) for k, v in self.outputs.items() if v.value]
dic["flags"] = [flg for flg in self.flags if self.flags[flg].value]
return dic
return {
"name": self.name,
"inputs": [(k, v.value) for k, v in self.inputs.items() if v.value],
"outputs": [(k, v.value) for k, v in self.outputs.items() if v.value],
"flags": [flg for flg in self.flags if self.flags[flg].value],
}

def make_cmd(self):
"""Create the command string that can be executed in a shell
Expand Down
6 changes: 1 addition & 5 deletions python/grass/pygrass/modules/interface/typedict.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,4 @@ def __reduce__(self):
)

def used(self):
key_dict = {}
for key in self:
if getattr(self, key):
key_dict[key] = getattr(self, key)
return key_dict
return {key: getattr(self, key) for key in self if getattr(self, key)}
Loading

0 comments on commit ed80a6e

Please sign in to comment.