From e139a4c0fd246bda49a9aff780a6f737306e3358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edouard=20Choini=C3=A8re?= <27212526+echoix@users.noreply.github.com> Date: Mon, 14 Oct 2024 13:06:14 -0400 Subject: [PATCH 01/35] gui: Solve a recursion error in gui/wxpython/lmgr/giface.py (#4514) --- gui/wxpython/lmgr/giface.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gui/wxpython/lmgr/giface.py b/gui/wxpython/lmgr/giface.py index eac9a7fb2d8..67669039d5d 100644 --- a/gui/wxpython/lmgr/giface.py +++ b/gui/wxpython/lmgr/giface.py @@ -54,7 +54,9 @@ def __init__(self, tree): self._tree = tree def __len__(self): - return len(list(self)) + # The list constructor calls __len__ as an optimization if available, + # causing a RecursionError + return len([layer for layer in self]) # noqa: C416 def __iter__(self): """Iterates over the contents of the list.""" From 61b380f1c4e3163d67961448553a091642c27eda Mon Sep 17 00:00:00 2001 From: Nicklas Larsson Date: Mon, 14 Oct 2024 20:11:42 +0200 Subject: [PATCH 02/35] r.mask.status: fix null pointer dereference and false positive string overflow (#4512) Fixes two new issues reported by Coverity Scan: - Handles case of unsuccessful creation of json string - Silences false positive issue for string copy operation to buffer of size GMAPSET_MAX from G_mapset(). --- lib/raster/mask_info.c | 2 +- raster/r.mask.status/main.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/raster/mask_info.c b/lib/raster/mask_info.c index 42102de86dd..317bab75b63 100644 --- a/lib/raster/mask_info.c +++ b/lib/raster/mask_info.c @@ -124,7 +124,7 @@ int Rast__mask_info(char *name, char *mapset) char rname[GNAME_MAX], rmapset[GMAPSET_MAX]; strcpy(rname, "MASK"); - strcpy(rmapset, G_mapset()); + (void)G_strlcpy(rmapset, G_mapset(), GMAPSET_MAX); if (!G_find_raster(rname, rmapset)) return -1; diff --git a/raster/r.mask.status/main.c b/raster/r.mask.status/main.c index 5eb32300240..16790adf35c 100644 --- a/raster/r.mask.status/main.c +++ b/raster/r.mask.status/main.c @@ -109,6 +109,8 @@ int report_status(struct Parameters *params) else json_object_set_null(root_object, "is_reclass_of"); char *serialized_string = json_serialize_to_string_pretty(root_value); + if (!serialized_string) + G_fatal_error(_("Failed to initialize pretty JSON string.")); puts(serialized_string); json_free_serialized_string(serialized_string); json_value_free(root_value); From 761d98a78010e34daa1d217fef433d04020ab82f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edouard=20Choini=C3=A8re?= <27212526+echoix@users.noreply.github.com> Date: Mon, 14 Oct 2024 15:30:57 -0400 Subject: [PATCH 03/35] style: Ignore deprecated PT004 rule (#4520) Ruff rule PT004 is deprecated, so doesn't run with --preview flag, but still appears without the --preview flag. Since the only error won't be fixed, ignore that rule for the time being. --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 6147e2db897..2a2287aaaad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -176,6 +176,7 @@ ignore = [ "PLW1641", # eq-without-hash "PLW2901", # redefined-loop-name "PLW3201", # bad-dunder-method-name + "PT004", # pytest-missing-fixture-name-underscore # deprecated, so doesn't appear with --preview "PTH100", # os-path-abspath "PTH101", # os-chmod "PTH102", # os-mkdir From 3a9059b7e7bec4a302cf6455c65fbd7fea3f2f8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edouard=20Choini=C3=A8re?= <27212526+echoix@users.noreply.github.com> Date: Mon, 14 Oct 2024 16:27:05 -0400 Subject: [PATCH 04/35] pytest: Collect code coverage in multiple workers too (#4451) * pytest: Collect code coverage in multiple workers too * utils: Handle paths that already have a .py extension in coverage_mapper * CI: Set INITIAL_GISBASE and INITIAL_PWD env vars for running pytest with multiple workers * Coverage: Omit gui/wxpython subfolders for now They are not covered at all and take some noticeable time to collect * Coverage: Remove unneeded omit patten for gui/wxpython subfolders --- .coveragerc | 1 + .github/workflows/pytest.yml | 11 +++++++++-- utils/coverage_mapper.py | 6 ++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/.coveragerc b/.coveragerc index 65e13c2234b..409fde55643 100644 --- a/.coveragerc +++ b/.coveragerc @@ -9,6 +9,7 @@ omit = ${INITIAL_PWD-.}/.github/* ${INITIAL_PWD-.}/bin.*/* ${INITIAL_PWD-.}/dist.*/* + **/gui/wxpython/*/** **/OBJ.*/* source = . diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index f2a96cf41ba..e1b3b84b54e 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -83,8 +83,13 @@ jobs: run: | export PYTHONPATH=`grass --config python_path`:$PYTHONPATH export LD_LIBRARY_PATH=$(grass --config path)/lib:$LD_LIBRARY_PATH + export INITIAL_GISBASE="$(grass --config path)" + export INITIAL_PWD="${PWD}" pytest --verbose --color=yes --durations=0 --durations-min=0.5 \ - --numprocesses auto -ra . \ + --numprocesses auto \ + --cov \ + --cov-context=test \ + -ra . \ -m 'not needs_solo_run' - name: Run pytest with a single worker (for tests marked with needs_solo_run) @@ -92,9 +97,11 @@ jobs: export PYTHONPATH=`grass --config python_path`:$PYTHONPATH export LD_LIBRARY_PATH=$(grass --config path)/lib:$LD_LIBRARY_PATH export INITIAL_GISBASE="$(grass --config path)" - INITIAL_PWD="${PWD}" pytest --verbose --color=yes --durations=0 --durations-min=0.5 \ + export INITIAL_PWD="${PWD}" + pytest --verbose --color=yes --durations=0 --durations-min=0.5 \ --cov \ --cov-context=test \ + --cov-append \ -ra . \ -m 'needs_solo_run' - name: Fix non-standard installed script paths in coverage data diff --git a/utils/coverage_mapper.py b/utils/coverage_mapper.py index 9a2f1389781..88fa30f9b54 100644 --- a/utils/coverage_mapper.py +++ b/utils/coverage_mapper.py @@ -22,12 +22,14 @@ def map_scripts_paths(old_path): if INITIAL_GISBASE is None or INITIAL_PWD is None: return old_path p = Path(old_path) + extension = ".py" + p_name = p.stem if p.suffix == extension else p.name temporal_base = Path(INITIAL_GISBASE) / "scripts" / "t.*" base = Path(INITIAL_GISBASE) / "scripts" / "*" if p.match(str(temporal_base)): - return str(Path(INITIAL_PWD) / "temporal" / (p.name) / (p.name)) + ".py" + return str(Path(INITIAL_PWD) / "temporal" / (p_name) / (p_name)) + extension if p.match(str(base)): - return str(Path(INITIAL_PWD) / "scripts" / (p.name) / (p.name)) + ".py" + return str(Path(INITIAL_PWD) / "scripts" / (p_name) / (p_name)) + extension return old_path From a98691f4eff03bb36ac6cd14058eab6edeace742 Mon Sep 17 00:00:00 2001 From: ShubhamDesai <42180509+ShubhamDesai@users.noreply.github.com> Date: Mon, 14 Oct 2024 17:02:46 -0400 Subject: [PATCH 05/35] v.net.timetable: Fix Resource Leak issue in main.c (#4508) * Fix Resource Leak issue * requested changes --- vector/v.net.timetable/main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/vector/v.net.timetable/main.c b/vector/v.net.timetable/main.c index 5fb382009bb..424d8a851bd 100644 --- a/vector/v.net.timetable/main.c +++ b/vector/v.net.timetable/main.c @@ -176,9 +176,7 @@ void write_subroute(struct segment *seg, struct line_pnts *line, int line_id) struct line_cats *Cats; struct ilist *list; - Points = Vect_new_line_struct(); Cats = Vect_new_cats_struct(); - list = Vect_new_list(); r = seg->route; Vect_cat_set(Cats, 2, line_id); @@ -188,6 +186,9 @@ void write_subroute(struct segment *seg, struct line_pnts *line, int line_id) return; } + Points = Vect_new_line_struct(); + list = Vect_new_list(); + for (i = 0; i < nnodes; i++) edges[i] = 0; for (i = 0; i < lines[r]->n_values; i++) From f241532c70217d27955cdd0677d6e9cede697605 Mon Sep 17 00:00:00 2001 From: ShubhamDesai <42180509+ShubhamDesai@users.noreply.github.com> Date: Mon, 14 Oct 2024 21:46:30 -0400 Subject: [PATCH 06/35] v.kernel: Fix resource Leak issue in main.c (#4506) Resource Leak --- vector/v.kernel/main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vector/v.kernel/main.c b/vector/v.kernel/main.c index 96198a4d8f7..c1e7f77a36a 100644 --- a/vector/v.kernel/main.c +++ b/vector/v.kernel/main.c @@ -769,7 +769,9 @@ double compute_all_net_distances(struct Map_info *In, struct Map_info *Net, G_debug(3, " kk = %d", kk); } } - + Vect_destroy_line_struct(APoints); + Vect_destroy_line_struct(BPoints); + Vect_destroy_boxlist(List); return (kk); } From c5c5ec5f51d1e8fe503a3b80f5778ebc80be7efe Mon Sep 17 00:00:00 2001 From: ShubhamDesai <42180509+ShubhamDesai@users.noreply.github.com> Date: Tue, 15 Oct 2024 04:25:27 -0400 Subject: [PATCH 07/35] lib/vector/Vlib: Fix Resource leak issue in geos.c (#4507) --- lib/vector/Vlib/geos.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/vector/Vlib/geos.c b/lib/vector/Vlib/geos.c index 719e0fdd270..2c68a0a6fba 100644 --- a/lib/vector/Vlib/geos.c +++ b/lib/vector/Vlib/geos.c @@ -290,7 +290,7 @@ GEOSCoordSequence *V1_read_line_geos(struct Map_info *Map, long offset, long size; double *x, *y, *z; - GEOSCoordSequence *pseq; + GEOSCoordSequence *pseq = NULL; G_debug(3, "V1_read_line_geos(): offset = %ld", offset); @@ -353,8 +353,6 @@ GEOSCoordSequence *V1_read_line_geos(struct Map_info *Map, long offset, G_debug(3, " n_points = %d dim = %d", n_points, (Map->head.with_z) ? 3 : 2); - pseq = GEOSCoordSeq_create(n_points, (Map->head.with_z) ? 3 : 2); - x = (double *)G_malloc(n_points * sizeof(double)); y = (double *)G_malloc(n_points * sizeof(double)); if (Map->head.with_z) @@ -362,17 +360,22 @@ GEOSCoordSequence *V1_read_line_geos(struct Map_info *Map, long offset, else z = NULL; - if (0 >= dig__fread_port_D(x, n_points, &(Map->dig_fp))) - return NULL; /* end of file */ + if (0 >= dig__fread_port_D(x, n_points, &(Map->dig_fp))) { + goto free_return; /* end of file */ + } - if (0 >= dig__fread_port_D(y, n_points, &(Map->dig_fp))) - return NULL; /* end of file */ + if (0 >= dig__fread_port_D(y, n_points, &(Map->dig_fp))) { + goto free_return; /* end of file */ + } if (Map->head.with_z) { - if (0 >= dig__fread_port_D(z, n_points, &(Map->dig_fp))) - return NULL; /* end of file */ + if (0 >= dig__fread_port_D(z, n_points, &(Map->dig_fp))) { + goto free_return; /* end of file */ + } } + pseq = GEOSCoordSeq_create(n_points, (Map->head.with_z) ? 3 : 2); + for (i = 0; i < n_points; i++) { GEOSCoordSeq_setX(pseq, i, x[i]); GEOSCoordSeq_setY(pseq, i, y[i]); @@ -382,6 +385,7 @@ GEOSCoordSequence *V1_read_line_geos(struct Map_info *Map, long offset, G_debug(3, " off = %ld", (long)dig_ftell(&(Map->dig_fp))); +free_return: G_free((void *)x); G_free((void *)y); if (z) From 15c5737dc601fbe71ab2bb614f14634ad17ddce0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 15 Oct 2024 07:19:47 -0400 Subject: [PATCH 08/35] CI(deps): Update github/codeql-action action to v3.26.13 (#4518) --- .github/workflows/codeql-analysis.yml | 4 ++-- .github/workflows/python-code-quality.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 88158341f13..6672287794c 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -56,7 +56,7 @@ jobs: if: ${{ matrix.language == 'c-cpp' }} - name: Initialize CodeQL - uses: github/codeql-action/init@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12 + uses: github/codeql-action/init@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13 with: languages: ${{ matrix.language }} config-file: ./.github/codeql/codeql-config.yml @@ -81,6 +81,6 @@ jobs: run: .github/workflows/build_ubuntu-22.04.sh "${HOME}/install" - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12 + uses: github/codeql-action/analyze@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/python-code-quality.yml b/.github/workflows/python-code-quality.yml index b8b423b2b16..886cbe56b47 100644 --- a/.github/workflows/python-code-quality.yml +++ b/.github/workflows/python-code-quality.yml @@ -135,7 +135,7 @@ jobs: path: bandit.sarif - name: Upload SARIF File into Security Tab - uses: github/codeql-action/upload-sarif@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12 + uses: github/codeql-action/upload-sarif@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13 with: sarif_file: bandit.sarif From ca171b7e53a5ae075fe4857cb8bbdcb7f764d061 Mon Sep 17 00:00:00 2001 From: Nicklas Larsson Date: Tue, 15 Oct 2024 13:29:47 +0200 Subject: [PATCH 09/35] tests: enable use of md5 bin for checksum in raster_md5test.sh (#4527) Makes the script runnable on e.g. BSD platforms, which does not ship with md5sum. In addition fixes shellcheck warnings. --- testsuite/raster/raster_md5test.sh | 52 ++++++++++++++++-------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/testsuite/raster/raster_md5test.sh b/testsuite/raster/raster_md5test.sh index 0bda0c3428c..b3281d4c505 100755 --- a/testsuite/raster/raster_md5test.sh +++ b/testsuite/raster/raster_md5test.sh @@ -14,19 +14,23 @@ if [ -z "$GISBASE" ] ; then fi #### check if we have sed -if [ ! -x "`which sed`" ] ; then +if [ ! -x "$(which sed)" ] ; then echo "$PROG: sed required, please install first" 1>&2 exit 1 fi -#### check if we have md5sum -if [ ! -x "`which md5sum`" ] ; then - echo "$PROG: md5sum required, please install first" 1>&2 - exit 1 +#### check if we have md5sum or md5 +if [ -x "$(which md5sum)" ] ; then + MD5="md5sum | cut -d' ' -f1" +elif [ -x "$(which md5)" ] ; then + MD5="md5 -q" +else + echo "$PROG: md5sum or md5 required, please install first" 1>&2 + exit 1 fi #### check if we have cut -if [ ! -x "`which cut`" ] ; then +if [ ! -x "$(which cut)" ] ; then echo "$PROG: cut required, please install first" 1>&2 exit 1 fi @@ -38,47 +42,47 @@ export LC_NUMERIC=C # enforce ZLIB export GRASS_COMPRESSOR=ZLIB -eval `g.gisenv` -: ${GISBASE?} ${GISDBASE?} ${LOCATION_NAME?} ${MAPSET?} +eval "$(g.gisenv)" +: "${GISBASE?}" "${GISDBASE?}" "${LOCATION_NAME?}" "${MAPSET?}" MAPSET_PATH=$GISDBASE/$LOCATION_NAME/$MAPSET # some definitions PIXEL=3 PID=$$ -TMPNAME="`echo ${PID}_tmp_testmap | sed 's+\.+_+g'`" +TMPNAME=$(echo ${PID}_tmp_testmap | sed 's+\.+_+g') # some functions - keep order here cleanup() { echo "Removing temporary map" - g.remove -f type=raster name=$TMPNAME > /dev/null + g.remove -f type=raster name="$TMPNAME" > /dev/null } # check if a MASK is already present: -MASKTMP=mask.$TMPNAME -USERMASK=usermask_${MASKTMP} -if test -f $MAPSET_PATH/cell/MASK +MASKTMP="mask.${TMPNAME}" +USERMASK="usermask_${MASKTMP}" +if test -f "${MAPSET_PATH}/cell/MASK" then echo "A user raster mask (MASK) is present. Saving it..." - g.rename raster=MASK,$USERMASK > /dev/null + g.rename raster=MASK,"$USERMASK" > /dev/null fi finalcleanup() { echo "Restoring user region" - g.region region=$TMPNAME - g.remove -f type=region name=$TMPNAME > /dev/null + g.region region="$TMPNAME" + g.remove -f type=region name="$TMPNAME" > /dev/null #restore user mask if present: - if test -f $MAPSET_PATH/cell/$USERMASK ; then + if test -f "${MAPSET_PATH}/cell/${USERMASK}" ; then echo "Restoring user MASK" g.remove -f type=raster name=MASK > /dev/null - g.rename raster=$USERMASK,MASK > /dev/null + g.rename raster="$USERMASK",MASK > /dev/null fi } check_exit_status() { - if [ $1 -ne 0 ] ; then + if [ "$1" -ne 0 ] ; then echo "An error occurred." cleanup ; finalcleanup exit 1 @@ -106,7 +110,7 @@ check_md5sum() } echo "Saving current & setting test region." -g.region save=$TMPNAME +g.region save="$TMPNAME" check_exit_status $? g.region s=0 n=$PIXEL w=0 e=$PIXEL res=1 tbres=1 check_exit_status $? @@ -118,8 +122,8 @@ r.mapcalc "$TMPNAME = 1" check_exit_status $? echo "MD5 checksum on output of INT/CELL test." -MD5="`r.out.ascii $TMPNAME precision=15 | md5sum | cut -d' ' -f1`" -check_md5sum "549e7dabe70df893803690571d2e1503" "$MD5" +SUM=$(r.out.ascii "$TMPNAME" precision=15 | eval "$MD5") +check_md5sum "549e7dabe70df893803690571d2e1503" "$SUM" cleanup echo "INT/CELL md5sum test successful" @@ -132,8 +136,8 @@ r.mapcalc "$TMPNAME = $VALUE" check_exit_status $? echo "MD5 checksum on output of FLOAT/FCELL test." -MD5="`r.out.ascii $TMPNAME precision=15 | md5sum | cut -d' ' -f1`" -check_md5sum "379f3d880b6d509051af6b4ccf470762" "$MD5" +SUM=$(r.out.ascii "$TMPNAME" precision=15 | eval "$MD5") +check_md5sum "379f3d880b6d509051af6b4ccf470762" "$SUM" cleanup echo "FLOAT/FCELL md5sum test successful" From f7d2ecfacca5f5bd9b0c0cd88752e7e0386b41d4 Mon Sep 17 00:00:00 2001 From: Markus Metz <33666869+metzm@users.noreply.github.com> Date: Tue, 15 Oct 2024 15:12:15 +0200 Subject: [PATCH 10/35] lib/vector/Vlib: always write out topo files in update mode (#3459) * Vlib: always write out topo files in update mode * delete support files only when closing * fix pygrass Vect_close --------- Co-authored-by: Huidae Cho --- lib/vector/Vlib/open.c | 1 + python/grass/pygrass/vector/abstract.py | 21 ++++++++------------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/lib/vector/Vlib/open.c b/lib/vector/Vlib/open.c index 501b31eb4cb..0008156c34a 100644 --- a/lib/vector/Vlib/open.c +++ b/lib/vector/Vlib/open.c @@ -572,6 +572,7 @@ int Vect__open_old(struct Map_info *Map, const char *name, const char *mapset, if (access(file_path, F_OK) == 0) /* fidx file exists? */ unlink(file_path); } + Map->support_updated = TRUE; } return level; diff --git a/python/grass/pygrass/vector/abstract.py b/python/grass/pygrass/vector/abstract.py index 6700dca8e4c..79307f0d354 100644 --- a/python/grass/pygrass/vector/abstract.py +++ b/python/grass/pygrass/vector/abstract.py @@ -457,14 +457,14 @@ def close(self, build=False): if hasattr(self, "table") and self.table is not None: self.table.conn.close() if self.is_open(): - if libvect.Vect_close(self.c_mapinfo) != 0: - str_err = "Error when trying to close the map with Vect_close" - raise GrassError(str_err) if ( self.c_mapinfo.contents.mode in {libvect.GV_MODE_RW, libvect.GV_MODE_WRITE} ) and build: self.build() + if libvect.Vect_close(self.c_mapinfo) != 0: + str_err = "Error when trying to close the map with Vect_close" + raise GrassError(str_err) def remove(self): """Remove vector map""" @@ -474,16 +474,11 @@ def remove(self): def build(self): """Close the vector map and build vector Topology""" - self.close() - libvect.Vect_set_open_level(1) - if libvect.Vect_open_old2(self.c_mapinfo, self.name, self.mapset, "0") != 1: - str_err = "Error when trying to open the vector map." - raise GrassError(str_err) - # Vect_build returns 1 on success and 0 on error (bool approach) - if libvect.Vect_build(self.c_mapinfo) != 1: - str_err = "Error when trying build topology with Vect_build" - raise GrassError(str_err) - libvect.Vect_close(self.c_mapinfo) + if self.is_open(): + # Vect_build returns 1 on success and 0 on error (bool approach) + if libvect.Vect_build(self.c_mapinfo) != 1: + str_err = "Error when trying build topology with Vect_build" + raise GrassError(str_err) if __name__ == "__main__": From c0c5380fb920042c9539490e21d30f9af2165b83 Mon Sep 17 00:00:00 2001 From: Anna Petrasova Date: Tue, 15 Oct 2024 09:58:35 -0400 Subject: [PATCH 11/35] r.sim.water: fix logfile writing (#4522) --- raster/r.sim/r.sim.sediment/main.c | 2 ++ raster/r.sim/r.sim.water/main.c | 4 +++- raster/r.sim/simlib/hydro.c | 3 --- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/raster/r.sim/r.sim.sediment/main.c b/raster/r.sim/r.sim.sediment/main.c index dd082fe0f81..d0197c2abb1 100644 --- a/raster/r.sim/r.sim.sediment/main.c +++ b/raster/r.sim/r.sim.sediment/main.c @@ -417,6 +417,8 @@ int main(int argc, char *argv[]) G_message(_("Using metric conversion factor %f, step=%f"), wp.conv, wp.step); + wp.observation = parm.observation->answer; + wp.logfile = parm.logfile->answer; init_library_globals(&wp); if ((wp.tc == NULL) && (wp.et == NULL) && (wp.conc == NULL) && diff --git a/raster/r.sim/r.sim.water/main.c b/raster/r.sim/r.sim.water/main.c index 61f128f5504..209be3e33d9 100644 --- a/raster/r.sim/r.sim.water/main.c +++ b/raster/r.sim/r.sim.water/main.c @@ -220,7 +220,7 @@ int main(int argc, char *argv[]) parm.logfile->required = NO; parm.logfile->description = _("Name for sampling points output text file. For each observation " - "vector point the time series of sediment transport is stored."); + "vector point the time series of water discharge is stored."); parm.logfile->guisection = _("Output"); parm.nwalk = G_define_option(); @@ -525,6 +525,8 @@ int main(int argc, char *argv[]) G_message(_("Using metric conversion factor %f, step=%f"), wp.conv, wp.step); + wp.observation = parm.observation->answer; + wp.logfile = parm.logfile->answer; init_library_globals(&wp); if ((wp.depth == NULL) && (wp.disch == NULL) && (wp.err == NULL)) diff --git a/raster/r.sim/simlib/hydro.c b/raster/r.sim/simlib/hydro.c index 74145ec9bff..eb7649763e9 100644 --- a/raster/r.sim/simlib/hydro.c +++ b/raster/r.sim/simlib/hydro.c @@ -151,9 +151,6 @@ void main_loop(void) maxwa = maxwa / nblock; } - /* Create the observation points */ - create_observation_points(); - G_debug(2, " maxwa, nblock %d %d", maxwa, nblock); for (iblock = 1; iblock <= nblock; iblock++) { From f22c9a2767960598ba99113eff595fda43bbfb8d Mon Sep 17 00:00:00 2001 From: Vaclav Petras Date: Tue, 15 Oct 2024 10:02:36 -0400 Subject: [PATCH 12/35] doc: Use lowercase for 2D raster mask and other masks (#4495) Similarly to #4401, this replaces usage of MASK by mask on additional places. It also improves wording of a warning in i.fft. --- imagery/i.fft/main.c | 5 +++-- imagery/i.pca/i.pca.html | 2 +- lib/ogsf/gk.c | 4 ++-- lib/ogsf/gvd.c | 2 +- raster/r.fill.dir/r.fill.dir.html | 8 ++++---- raster/r.li/TODO | 7 ++++--- raster/r.univar/r.univar.html | 2 +- 7 files changed, 16 insertions(+), 14 deletions(-) diff --git a/imagery/i.fft/main.c b/imagery/i.fft/main.c index ad9a87a7890..051428b77ef 100644 --- a/imagery/i.fft/main.c +++ b/imagery/i.fft/main.c @@ -105,8 +105,9 @@ int main(int argc, char *argv[]) inputfd = Rast_open_old(Cellmap_orig, ""); if (Rast_maskfd() >= 0) - G_warning(_("Raster MASK found, consider to remove " - "(see man-page). Will continue...")); + G_warning(_("Raster mask active, consider removing it" + " and running again without it (see documentation for" + " details). This current process will now continue...")); G_get_set_window(&window); /* get the current window for later */ diff --git a/imagery/i.pca/i.pca.html b/imagery/i.pca/i.pca.html index 17b3f5ed163..6fee184c618 100644 --- a/imagery/i.pca/i.pca.html +++ b/imagery/i.pca/i.pca.html @@ -11,7 +11,7 @@

DESCRIPTION

principal component with the highest importance.

-The current geographic region definition and MASK settings are +The current geographic region definition and raster mask settings are respected when reading the input raster map layers. When the rescale option is used, the output files are rescaled to fit the min,max range. diff --git a/lib/ogsf/gk.c b/lib/ogsf/gk.c index 3390598960a..b4fea635cc4 100644 --- a/lib/ogsf/gk.c +++ b/lib/ogsf/gk.c @@ -172,8 +172,8 @@ void gk_follow_frames(Viewnode *view, int numsteps, Keylist *keys, int step, GS_get_from(tmp); G_debug(3, "gk_follow_frames():"); - G_debug(3, " MASK: %lx", mask); - G_debug(3, " FROM: %f %f %f", tmp[X], tmp[Y], tmp[Z]); + G_debug(3, " mask: %lx", mask); + G_debug(3, " from: %f %f %f", tmp[X], tmp[Y], tmp[Z]); /* ACS 1 line: was GS_get_focus(tmp); with this kanimator works also for flythrough navigation diff --git a/lib/ogsf/gvd.c b/lib/ogsf/gvd.c index 6a6176526a2..84867123c5e 100644 --- a/lib/ogsf/gvd.c +++ b/lib/ogsf/gvd.c @@ -201,7 +201,7 @@ int gvd_vect(geovect *gv, geosurf *gs, int do_fast) } gsd_endline(); } - /* need to handle MASK! */ + /* need to handle mask! */ else if (src == CONST_ATT) { /* for now - but later, do seg intersect maskedge */ if (gs_point_is_masked(gs, bgn) || diff --git a/raster/r.fill.dir/r.fill.dir.html b/raster/r.fill.dir/r.fill.dir.html index 6ad8eb8019c..17173ea3dd3 100644 --- a/raster/r.fill.dir/r.fill.dir.html +++ b/raster/r.fill.dir/r.fill.dir.html @@ -69,11 +69,11 @@

DESCRIPTION

attributes required by other hydrological models.

-As any GRASS GIS module, r.fill.dir is sensitive to the -computational region settings. Thus +As any GRASS GIS module, r.fill.dir respects the +computational region settings. Thus, the module can be used to generate a flow direction map for any -sub-area within the full map layer. Also, r.fill.dir is -sensitive to any raster MASK in effect. +sub-area within the full raster map layer. Also, r.fill.dir +will take into account an active raster mask.

NOTES

diff --git a/raster/r.li/TODO b/raster/r.li/TODO index 61ddd6b0941..382195402a6 100644 --- a/raster/r.li/TODO +++ b/raster/r.li/TODO @@ -24,12 +24,13 @@ d.vect forests type=boundary ######## TODO: CHECK THIS: -# MASK test -g.copy rast=fields,MASK +# Test with raster mask +r.mask raster=fields r.li.patchdensity forests conf=movwindow7 output=forests_p_dens7mask --o d.erase d.rast.leg forests_p_dens7mask -# -> no negative values! but MASK is respected +r.mask -r +# -> no negative values! but mask is respected # zero data test r.mapcalc "forests = 0" diff --git a/raster/r.univar/r.univar.html b/raster/r.univar/r.univar.html index 5220bc64a44..debde03a1d6 100644 --- a/raster/r.univar/r.univar.html +++ b/raster/r.univar/r.univar.html @@ -53,7 +53,7 @@

PERFORMANCE

r.univar supports parallel processing using OpenMP. The user can specify the number of threads to be used with the nprocs parameter. -However, parallelization is disabled when the MASK is set. +However, parallelization is disabled when the raster mask is set.

Due to the differences in summation order, users may encounter small floating points From ec2bc8a7df27b1984c878b7a0a209bad9e977acd Mon Sep 17 00:00:00 2001 From: Mohan Yelugoti Date: Tue, 15 Oct 2024 11:35:11 -0400 Subject: [PATCH 13/35] r3.in.v5d: Prevent integer overflow by changing literal constant type on Cray (#4363) When the code is being compiled for CRAY HPC machines, a macro and a function to convert IEEE single precision floating point number to CRAY number are defined. To adjust the base, '16258' constant is being used, which according to C rules (C99, section 6.4.4.1, subsection semantics) fits into an integer. Right shifting that integer, which is of 32 bits, by 48 results in integer overflow. Avoid this by defining the literal constant with the long data type. This comes with an extended discussion in PR #4363 and an idea to remove the code completely. Signed-off-by: Mohan Yelugoti --- raster3d/r3.in.v5d/binio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/raster3d/r3.in.v5d/binio.c b/raster3d/r3.in.v5d/binio.c index f8582e97313..b47723a2929 100644 --- a/raster3d/r3.in.v5d/binio.c +++ b/raster3d/r3.in.v5d/binio.c @@ -147,7 +147,7 @@ static void if_to_c(long *t, const long *f) { if (*f != 0) { *t = (((*f & 0x8000000000000000) | - ((*f & 0x7f80000000000000) >> 7) + (16258 << 48)) | + ((*f & 0x7f80000000000000) >> 7) + (16258L << 48)) | (((*f & 0x007fffff00000000) >> 8) | (0x0000800000000000))); if ((*f << 1) == 0) *t = 0; @@ -160,7 +160,7 @@ static void if_to_c(long *t, const long *f) #define IF_TO_C(T, F) \ if (F != 0) { \ T = (((F & 0x8000000000000000) | \ - ((F & 0x7f80000000000000) >> 7) + (16258 << 48)) | \ + ((F & 0x7f80000000000000) >> 7) + (16258L << 48)) | \ (((F & 0x007fffff00000000) >> 8) | (0x0000800000000000))); \ if ((F << 1) == 0) \ T = 0; \ From 1adbd2ced8411fcc1e375ac6d6d124c419e497f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edouard=20Choini=C3=A8re?= <27212526+echoix@users.noreply.github.com> Date: Tue, 15 Oct 2024 11:59:46 -0400 Subject: [PATCH 14/35] CI: Assign milestone on merged PRs (#4414) * CI: Create a workflow to assign milestones * Add GH_TOKEN for gh cli * CI: Add GH_REPO for gh cli * CI: View PR from gh cli using html_url * CI: Download and parse version file * CI: Show version file * CI: Download and parse version file using a pipe * Show version file output Clean up * Pipe version file env to head * Rename variables to milestone and title * Edit PR with milestone * Get milestone from gh cli * Add comment on why API call is used for getting milestone * Show if the PR has a milestone set or not * Do not run steps if a milestone is already set * Add pull_request_target closed trigger * Add ref as url parameter * Remove debugging steps * CI: Handle RC followed by numbers in sed pattern replacement --- .github/workflows/milestones.yml | 70 ++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 .github/workflows/milestones.yml diff --git a/.github/workflows/milestones.yml b/.github/workflows/milestones.yml new file mode 100644 index 00000000000..e2ade4eb091 --- /dev/null +++ b/.github/workflows/milestones.yml @@ -0,0 +1,70 @@ +--- +name: Assign Milestone + +on: + pull_request_target: + types: [closed] + +jobs: + assign-milestone: + runs-on: ubuntu-latest + if: github.event.pull_request.merged + steps: + # Retreiving the current milestoone from API instead of github context, + # so up-to-date information is used when running after being queued or for reruns + # Otherwise, the information should be available using + # ${{ github.event.pull_request.milestone.title }} + - name: Get current milestone title + id: current-milestone + run: | + echo "milestone<> "${GITHUB_OUTPUT}" + gh pr view ${{ github.event.pull_request.html_url }} --json milestone \ + --jq .milestone.title >> "${GITHUB_OUTPUT}" + echo 'EOF' >> "${GITHUB_OUTPUT}" + env: + GH_TOKEN: ${{ github.token }} + GH_REPO: ${{ github.repository }} + - name: PR already has a milestone + run: echo "PR already has a milestone" + if: ${{ steps.current-milestone.outputs.milestone }} + - name: PR does not have a milestone + run: echo "PR does not have a milestone" + if: ${{ !steps.current-milestone.outputs.milestone }} + - name: Get VERSION file + if: ${{ !steps.current-milestone.outputs.milestone }} + id: version-file + run: | + echo "version<> "${GITHUB_OUTPUT}" + gh api \ + -H "Accept: application/vnd.github.raw" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "/repos/{owner}/{repo}/contents/include/VERSION?ref=${{ github.sha }}" >> "${GITHUB_OUTPUT}" + echo "EOF" >> "${GITHUB_OUTPUT}" + env: + GH_TOKEN: ${{ github.token }} + GH_REPO: ${{ github.repository }} + - name: Show version file + if: ${{ !steps.current-milestone.outputs.milestone }} + run: echo "${VERSIONFILE}" + env: + VERSIONFILE: ${{ steps.version-file.outputs.version }} + - name: Get milestone title from VERSION file + if: ${{ !steps.current-milestone.outputs.milestone }} + id: milestone + run: | + version=$(echo "$VERSIONFILE" | head -n 3 | xargs | sed 's/ /./g; s/\(RC[0-9]*\|dev\)//g') + echo "title=$version" >> "${GITHUB_OUTPUT}" + env: + VERSIONFILE: ${{ steps.version-file.outputs.version }} + - name: Show milestone title + if: ${{ !steps.current-milestone.outputs.milestone }} + run: echo "${MILESTONE}" + env: + MILESTONE: ${{ steps.milestone.outputs.title }} + - name: Set PR milestone + if: ${{ !steps.current-milestone.outputs.milestone }} + run: gh pr edit ${{ github.event.pull_request.html_url }} --milestone "${MILESTONE}" + env: + GH_TOKEN: ${{ github.token }} + GH_REPO: ${{ github.repository }} + MILESTONE: ${{ steps.milestone.outputs.title }} From 9a79aa4a9a637b7467cdfd7e0b2a2193f623f8a5 Mon Sep 17 00:00:00 2001 From: Vaclav Petras Date: Tue, 15 Oct 2024 19:09:57 -0400 Subject: [PATCH 15/35] tests: Revise content of the root testsuite dir (#4516) * Remove Makefiles. * Move the functioning test to the testsuite directory for the gunittest to pick it up. * Remove the extended example how to run gunittest. Point to the CI in the README instead. * Remove hemisphere generator because it does not test anything by itself (without further processing and a human). * Remove GPS import tests as the tools are not in core. * Remove division into subdirectories. The directories with the code should be used instead. * Improve the test for gunittest loader function with some duplication but now creating an overview of .py and .sh tests. --- python/grass/gunittest/loader.py | 16 +- testsuite/Makefile | 8 - testsuite/README.md | 44 +++--- .../test_framework_GRASS_GIS_with_NC.conf | 29 ---- .../test_framework_GRASS_GIS_with_NC.sh | 144 ------------------ testsuite/raster/Makefile | 3 - testsuite/raster/README | 1 - testsuite/raster/rhemisphere.sh | 48 ------ testsuite/{raster => }/raster_md5test.sh | 0 testsuite/vector/v.in.gps_test.sh | 26 ---- 10 files changed, 42 insertions(+), 277 deletions(-) delete mode 100644 testsuite/Makefile delete mode 100644 testsuite/examples/test_framework_GRASS_GIS_with_NC.conf delete mode 100755 testsuite/examples/test_framework_GRASS_GIS_with_NC.sh delete mode 100644 testsuite/raster/Makefile delete mode 100644 testsuite/raster/README delete mode 100755 testsuite/raster/rhemisphere.sh rename testsuite/{raster => }/raster_md5test.sh (100%) delete mode 100755 testsuite/vector/v.in.gps_test.sh diff --git a/python/grass/gunittest/loader.py b/python/grass/gunittest/loader.py index f01467ef1ba..50fa368f62a 100644 --- a/python/grass/gunittest/loader.py +++ b/python/grass/gunittest/loader.py @@ -235,4 +235,18 @@ def discover(self, start_dir, pattern="test*.py", top_level_dir=None): if __name__ == "__main__": - GrassTestLoader().discover() + for expression in [r".*\.py$", r".*\.sh$"]: + modules = discover_modules( + start_dir=".", + grass_location="all", + file_regexp=expression, + skip_dirs=GrassTestLoader.skip_dirs, + testsuite_dir=GrassTestLoader.testsuite_dir, + all_locations_value=GrassTestLoader.all_tests_value, + universal_location_value=GrassTestLoader.universal_tests_value, + import_modules=False, + exclude=None, + ) + print("Expression:", expression) + print(len(modules)) + print([module.file_path for module in modules]) diff --git a/testsuite/Makefile b/testsuite/Makefile deleted file mode 100644 index 7ed92b67442..00000000000 --- a/testsuite/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -MODULE_TOPDIR = .. - -SUBDIRS = \ - raster - -include $(MODULE_TOPDIR)/include/Make/Dir.make - -default: parsubdirs diff --git a/testsuite/README.md b/testsuite/README.md index 491fa4597af..36dda7d3da2 100644 --- a/testsuite/README.md +++ b/testsuite/README.md @@ -1,29 +1,39 @@ # Test suite -This directory contains scripts to check some functionality of GRASS GIS. +Tests are in directories `tests` and `testsuite` under each directory which has tests. +This directory contains additional scripts and information to test functionality +without a focus on a specific part of the code. -GRASS GIS testsuite documentation: +There are two testing mechanism in place, _pytest_ which is the modern way of testing +GRASS GIS. Tests using _pytest_ are written just as any other Python tests. -## Simple test data +In parallel, there is also custom unittest-based framework centered around +_grass.gunittest_ package. These tests run in the NC sample datasets and can be +executed using _pytest_ or directly. The unittest-based adds a number of custom +assert methods to accommodate different data and outputs typical in GRASS GIS. +_grass.gunittest_ documentation: + -Some tests may be launched in the location `../demolocation/`: +## Running tests + +Tests can be executed using _pytest_: ```bash -# create new mapset for test -grass ../demolocation/user1 -c -# run the test -make +# Setup the Python environment (if not set up already). +# Replace grass by path to the executable if not installed on path. +export PYTHONPATH=\$(grass --config python_path):\$PYTHONPATH +export LD_LIBRARY_PATH=\$(grass --config path)/lib:\$LD_LIBRARY_PATH +# Run the test. +pytest ``` -## Extended test data - -Most tests require the North Carolina Sample dataset, available from - +## Test data -## Notes +To test manually or to write tests, you may need to use the North Carolina +Sample dataset, available from +. -Since 2020: For a more advanced test suite, see - +## CI -Until 2019: For a more advanced test suite, see - +Most tests run in the CI. See the `.github` directory for details and +use it as a reference. diff --git a/testsuite/examples/test_framework_GRASS_GIS_with_NC.conf b/testsuite/examples/test_framework_GRASS_GIS_with_NC.conf deleted file mode 100644 index 6256108f6a8..00000000000 --- a/testsuite/examples/test_framework_GRASS_GIS_with_NC.conf +++ /dev/null @@ -1,29 +0,0 @@ -### CONFIGURATION -# -# name of binary: -GRASSBIN=grass -# source code directory as full path: -GRASSSRC="$(realpath ../../)" -# temporary grassdata directory -GRASSDATA="$HOME/grassdata" - -# leave 1 or more CPU free for other usage than testing -FREECPU=1 - -# Python binary to be used (python|python3) -PYTHON=python - -# here we suppose default compilation settings of GRASS GIS and no 'make install' -# may be no|yes -COMPILE="no" -# configure metascript with compiler flags: -CONFIGURE="${GRASSSRC}/conf_grass8.sh" - -# directory to store reports, e.g. in a subdirectory -REPORTS="testreports" - -# publish report on WWW Server (not needed for local tests) -# may be no|yes -PUBLISH="no" -# upload WWW dir on server for report publication (not used for local tests) -SERVERDIR="/var/www/html/grassgistestreports" diff --git a/testsuite/examples/test_framework_GRASS_GIS_with_NC.sh b/testsuite/examples/test_framework_GRASS_GIS_with_NC.sh deleted file mode 100755 index 808b4b9c716..00000000000 --- a/testsuite/examples/test_framework_GRASS_GIS_with_NC.sh +++ /dev/null @@ -1,144 +0,0 @@ -#!/bin/bash -############################################################################ -# -# MODULE: Example script to run testsuite -# AUTHOR(S): Markus Neteler, Sören Gebbert, Vaclav Petras -# PURPOSE: Test GRASS GIS using the test framework -# Documentation: -# https://trac.osgeo.org/grass/wiki/GSoC/2014/TestingFrameworkForGRASS -# https://grass.osgeo.org/grass-devel/manuals/libpython/gunittest_running_tests.html#example-bash-script-to-run-be-used-as-a-cron-job -# -# Data: -# We use the full NC dataset (nc_spm_full_v2_alpha.tar.gz) -# -# COPYRIGHT: (C) 2019-2021 by Markus Neteler, and the GRASS Development Team -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -############################################################################ - -### Fetch CONFIGURATION - -CONF="test_framework_GRASS_GIS_with_NC.conf" - -usage_msg(){ -echo "Usage: - $0 [conf_file] - -Example: - $0 ./${CONF} -" -} - -if [ ! -z "$1" ] ; then - case "$1" in - -h | --h | -help | --help) - usage_msg - exit 0 - ;; - *) - if [ -f ${1} ] ; then - CONF="$1" - else - echo "ERROR: $1 is not a file" - exit 1 - fi - ;; - esac -else - usage_msg - exit 0 -fi - -source ${CONF} - -######### nothing to change below - -set -e # fail fast - -# computer architecture: -ARCH=`${GRASSBIN} --config arch` - -# here we suppose default compilation settings of GRASS GIS and no make install -GRASSBIN="$GRASSSRC/bin.${ARCH}/${GRASSBIN}" -GRASSDIST="$GRASSSRC/dist.${ARCH}" - -# necessary hardcoded GRASS paths -GRASSDIST_PYTHON="$GRASSDIST/etc/python" -GRASS_MULTI_RUNNER="$GRASSSRC/python/grass/gunittest/multirunner.py" -GRASS_MULTI_REPORTER="$GRASSSRC/python/grass/gunittest/multireport.py" - -DATE_FLAGS="--utc +%Y-%m-%d-%H-%M" -NOW=$(date $DATE_FLAGS) - -# get number of processors of current machine -MYNPROC=`getconf _NPROCESSORS_ONLN` -# leave some free for other tasks -GCCTHREADS=`expr $MYNPROC - $FREECPU` -if [ $GCCTHREADS -lt 1 ] ; then - GCCTHREADS=1 -fi - -# contains last executed command stdout and stderr -# here were rely on reports being absolute -OUTPUT_LOGFILE="$REPORTS/output-$NOW.txt" - -# these are relative to REPORTS -CURRENT_REPORT_BASENAME="reports_for_date-" -FINAL_REPORT_DIR="summary_report" -CURRENT_REPORTS_DIR="$CURRENT_REPORT_BASENAME$NOW" -LOGFILE="$REPORTS/runs.log" - -mkdir -p $REPORTS/$CURRENT_REPORTS_DIR -mkdir -p $GRASSDATA - -# fetch sample data -SAMPLEDATA=nc_spm_full_v2alpha -(cd $GRASSDATA ; wget -c https://grass.osgeo.org/sampledata/north_carolina/$SAMPLEDATA.tar.gz ; tar xfz $SAMPLEDATA.tar.gz --strip-components 2) - -set -x - -echo "Testing of GRASS GIS started: $NOW" >> ${LOGFILE} - -if [ "$COMPILE" = "yes" ] ; then - ## compile current source code from scratch - cd $GRASSSRC - make distclean -j$GCCTHREADS - git pull - ./$CONFIGURE ... # configure meta script containing all the compiler flags - make -j$GCCTHREADS -fi - -# run tests for the current source code -cd $REPORTS/$CURRENT_REPORTS_DIR -$PYTHON $GRASS_MULTI_RUNNER \ - --grassbin $GRASSBIN \ - --grasssrc $GRASSSRC \ - --grassdata $GRASSDATA \ - --location $SAMPLEDATA --location-type nc # \ -# --location other_location --location-type other_type - -# create overall report of all so far executed tests -# the script depends on GRASS but just Python part is enough -export PYTHONPATH="$GRASSDIST_PYTHON:$PYTHONPATH" -$PYTHON $GRASS_MULTI_REPORTER --output $FINAL_REPORT_DIR \ - $CURRENT_REPORT_BASENAME*/* - -# publish on Web site -if [ "$PUBLISH" = "yes" ] ; then - ## although we cannot be sure the tests were executed was successfully - ## so publish or archive results - rsync -rtvu --delete $REPORTS/ $SERVERDIR -fi - -echo "Nightly ($NOW) GRASS GIS test finished: $(date $DATE_FLAGS)" >> ${LOGFILE} - -exit 0 diff --git a/testsuite/raster/Makefile b/testsuite/raster/Makefile deleted file mode 100644 index 21c1f8eb6c0..00000000000 --- a/testsuite/raster/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -all: - ./raster_md5test.sh - ./rmapcalc_test.sh diff --git a/testsuite/raster/README b/testsuite/raster/README deleted file mode 100644 index bc5b0940789..00000000000 --- a/testsuite/raster/README +++ /dev/null @@ -1 +0,0 @@ -Raster map tests go here diff --git a/testsuite/raster/rhemisphere.sh b/testsuite/raster/rhemisphere.sh deleted file mode 100755 index e312f7b36d1..00000000000 --- a/testsuite/raster/rhemisphere.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/sh - -# Markus Neteler, 2006 -# This program is free software under the GNU General Public -# License (>=v2). Read the file COPYING that comes with GRASS -# for details. -# Test cases for 2D raster data -# generate a hemisphere to test slope, aspect, curvatures - -# some definitions: -BOXLENGTH=1000 # side length of test area -RADIUS=500 # half BOXLENGTH - -############ - -if [ -z "$GISBASE" ] ; then - echo "You must be in GRASS GIS to run this program." >&2 - exit 1 -fi - -# some functions - keep order here -TMP="disk.$$" - -cleanup() -{ - echo "Removing temporary map" - g.remove --q -f type=raster name=$TMP > /dev/null -} - -######################## - -g.region n=$BOXLENGTH s=0 w=0 e=$BOXLENGTH -p res=1 - -X="(col() - $RADIUS)" -Y="($RADIUS - row())" -r="sqrt($X^2 + $Y^2)" - -#Mask out unwanted parts (check for <= ??): -r.mapcalc "$TMP = if($r<$RADIUS,$r,null())" - -ALPHA="acos ($TMP/$RADIUS)" -HEIGHT="$RADIUS * sin($ALPHA)" - - -r.mapcalc "hemisphere = $HEIGHT" -cleanup -g.message "Generated raster map " -#echo "Now generate aspect + slope on " diff --git a/testsuite/raster/raster_md5test.sh b/testsuite/raster_md5test.sh similarity index 100% rename from testsuite/raster/raster_md5test.sh rename to testsuite/raster_md5test.sh diff --git a/testsuite/vector/v.in.gps_test.sh b/testsuite/vector/v.in.gps_test.sh deleted file mode 100755 index 62b2f5b651c..00000000000 --- a/testsuite/vector/v.in.gps_test.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh -# v.in.garmin and v.in.gpsbabel test script -# by Hamish Bowman 18 May 2007 ; public domain -# assumes downloading from a garmin on port /dev/gps - -for PGM in garmin gpsbabel ; do - for DO_PTS in pts lines ; do - for TASK in w t r ; do - if [ $TASK = w ] && [ $DO_PTS = "lines" ] ; then - continue - fi - if [ $DO_PTS = "pts" ] ; then - PTFLAG="-p" - else - PTFLAG="" - fi - MAPNAME="test_${PGM}_${TASK}_${DO_PTS}_$$" - echo "-- Running [v.in.$PGM] for [$TASK] download as [$DO_PTS] into <$MAPNAME> --" - v.in.$PGM -$TASK $PTFLAG out="$MAPNAME" - if [ $? -ne 0 ] ; then - exit 1 - fi - awk 'BEGIN {printf("\n\n\n\n")}' - done - done -done From bc9cb2a3f9540b031a6b8e8e7d7257ca01492d3e Mon Sep 17 00:00:00 2001 From: Vaclav Petras Date: Tue, 15 Oct 2024 19:17:08 -0400 Subject: [PATCH 16/35] doc: Use lowercase for mask (#4529) Again, use lowercase mask and other wording instead of MASK when talking about masking, similar to #4401 and #4495. It also adjusts the wording in r.topidx and i.segment. --- imagery/i.segment/i.segment.html | 2 +- imagery/i.segment/iseg.h | 2 +- ps/ps.map/r_instructions.c | 2 +- raster/r.resamp.interp/r.resamp.interp.html | 2 +- raster/r.topidx/r.topidx.html | 8 +++++--- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/imagery/i.segment/i.segment.html b/imagery/i.segment/i.segment.html index 1e2596c1d7e..e30f21d3743 100644 --- a/imagery/i.segment/i.segment.html +++ b/imagery/i.segment/i.segment.html @@ -118,7 +118,7 @@

Mean shift

Boundary Constraints

Boundary constraints limit the adjacency of pixels and segments. Each unique value present in the bounds raster are -considered as a MASK. Thus no segments in the final segmentated map +considered as a mask. Thus, no segments in the final segmented map will cross a boundary, even if their spectral data is very similar.

Minimum Segment Size

diff --git a/imagery/i.segment/iseg.h b/imagery/i.segment/iseg.h index 1e301d2cefa..a8dfb5542c3 100644 --- a/imagery/i.segment/iseg.h +++ b/imagery/i.segment/iseg.h @@ -118,7 +118,7 @@ struct globals { /* processing flags */ FLAG *candidate_flag, - *null_flag; /*TODO, need some way to remember MASK/NULL values. Was + *null_flag; /*TODO, need some way to remember mask/NULL values. Was using -1, 0, 1 in int array. Better to use 2 FLAG structures, better readability? */ diff --git a/ps/ps.map/r_instructions.c b/ps/ps.map/r_instructions.c index 0e2c012fd92..87a2e4bbfcf 100644 --- a/ps/ps.map/r_instructions.c +++ b/ps/ps.map/r_instructions.c @@ -29,7 +29,7 @@ static char *help[] = { "read unix-file eps Encapsulated PostScript file", "border [y|n] mapinfo map information", "window region definition region region definition", - "maskcolor MASK color", + "maskcolor mask color", "rectangle east north east north", "scale 1:#|# inches|# panels|1 inch = # miles", "outline map composition outline", diff --git a/raster/r.resamp.interp/r.resamp.interp.html b/raster/r.resamp.interp/r.resamp.interp.html index e4b77ac0d34..3c3eecc68a9 100644 --- a/raster/r.resamp.interp/r.resamp.interp.html +++ b/raster/r.resamp.interp/r.resamp.interp.html @@ -28,7 +28,7 @@

NOTES

Note that for bilinear, bicubic and lanczos interpolation, cells of the output raster that cannot be bounded by the appropriate number of input cell centers are set to NULL (NULL propagation). This could occur -due to the input cells being outside the current region, being NULL or MASKed. +due to the input cells being outside the current region, being NULL or masked.

For longitude-latitude coordinate reference systems, diff --git a/raster/r.topidx/r.topidx.html b/raster/r.topidx/r.topidx.html index 56dd001f20a..75938e6a231 100644 --- a/raster/r.topidx/r.topidx.html +++ b/raster/r.topidx/r.topidx.html @@ -10,12 +10,14 @@

DESCRIPTION

the local surface topographic slope (delta vertical) / (delta horizontal).
-

Input maps may have NULL values. For example, if you have a MASK for a -watershed (basin map from r.water.outlet), the following command will -create a masked elevation map (belev): +

Input maps may have NULL values. For example, if you have a raster mask set +for a watershed (using basin map from r.water.outlet), the following +command will create a masked elevation map (belev): +

 r.mapcalc "belev = if(isnull(basin), basin, elev)"
 
+

r.stats -Anc prints out averaged statistics for topographic index. From 241589424d9612b913ef7f5502839ee6ab2151bc Mon Sep 17 00:00:00 2001 From: ShubhamDesai <42180509+ShubhamDesai@users.noreply.github.com> Date: Wed, 16 Oct 2024 04:08:22 -0400 Subject: [PATCH 17/35] r.in.gridatb: check if opening of file succeeds (#4532) --- raster/r.in.gridatb/file_io.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/raster/r.in.gridatb/file_io.c b/raster/r.in.gridatb/file_io.c index 256f9869473..52ad174df4d 100644 --- a/raster/r.in.gridatb/file_io.c +++ b/raster/r.in.gridatb/file_io.c @@ -12,6 +12,9 @@ void rdwr_gridatb(void) float idx; fp = fopen(file, "r"); + if (!fp) { + G_fatal_error(_("Unable to open file: %s"), file); + } buf[0] = 0; if (fscanf(fp, "%[^\n]", buf) != 1) From 362bee3ae66cec995805e355bb40cffe75c838f7 Mon Sep 17 00:00:00 2001 From: Arohan Ajit Date: Wed, 16 Oct 2024 09:27:43 -0400 Subject: [PATCH 18/35] grass.script: Fixed E722 in v.what.shrds/ (#4530) --- .flake8 | 2 +- scripts/v.what.strds/v.what.strds.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.flake8 b/.flake8 index c01dc46b255..6bfcc1e5527 100644 --- a/.flake8 +++ b/.flake8 @@ -115,7 +115,7 @@ per-file-ignores = scripts/r.in.srtm/r.in.srtm.py: E722 scripts/r.fillnulls/r.fillnulls.py: E722 scripts/d.rast.edit/d.rast.edit.py: E722 - scripts/v.what.strds/v.what.strds.py: E722, E501 + scripts/v.what.strds/v.what.strds.py: E501 # Line too long (esp. module interface definitions) scripts/*/*.py: E501 temporal/t.rast.to.vect/t.rast.to.vect.py: E501 diff --git a/scripts/v.what.strds/v.what.strds.py b/scripts/v.what.strds/v.what.strds.py index 0e1bf893f98..8be00f3536d 100644 --- a/scripts/v.what.strds/v.what.strds.py +++ b/scripts/v.what.strds/v.what.strds.py @@ -225,7 +225,7 @@ def main(): pymap = Vector(output) try: pymap.open("r") - except: + except Exception: dbif.close() gs.fatal(_("Unable to create vector map <%s>") % output) From 39ff021208e8cbca0615c3545ffa9d191e149e88 Mon Sep 17 00:00:00 2001 From: Arohan Ajit Date: Thu, 17 Oct 2024 10:49:45 -0400 Subject: [PATCH 19/35] wxGUI: Fixed F841 in mapwindow.py (#4538) --- gui/wxpython/nviz/mapwindow.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gui/wxpython/nviz/mapwindow.py b/gui/wxpython/nviz/mapwindow.py index 8cf972704e2..1eea5b278a9 100644 --- a/gui/wxpython/nviz/mapwindow.py +++ b/gui/wxpython/nviz/mapwindow.py @@ -412,7 +412,7 @@ def OnPaint(self, event): Debug.msg(1, "GLCanvas.OnPaint()") self.render["overlays"] = True - dc = wx.PaintDC(self) + wx.PaintDC(self) self.DoPaint() def DoPaint(self): @@ -1438,7 +1438,7 @@ def UnloadDataLayers(self, force=False): GError(parent=self, message=e.value) if force and self.baseId > 0: # unload base surface when quitting - ret = self._display.UnloadSurface(self.baseId) + self._display.UnloadSurface(self.baseId) self.baseId = -1 if update: self.lmgr.nviz.UpdateSettings() @@ -2134,10 +2134,10 @@ def UpdateVolumeProperties(self, id, data, isosurfId=None): # sliceId = 0 for slice in data["slice"]: - ret = self._display.AddSlice(id, slice_id=sliceId) + self._display.AddSlice(id, slice_id=sliceId) if "update" in slice["position"]: pos = slice["position"] - ret = self._display.SetSlicePosition( + self._display.SetSlicePosition( id, sliceId, pos["x1"], From a740da1d4a638c0e129ac95e7c298961f06f3111 Mon Sep 17 00:00:00 2001 From: Arohan Ajit Date: Thu, 17 Oct 2024 10:51:50 -0400 Subject: [PATCH 20/35] wxGUI: Added TypeError to lmgr/ (#4537) --- gui/wxpython/lmgr/frame.py | 6 +++--- gui/wxpython/lmgr/layertree.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/gui/wxpython/lmgr/frame.py b/gui/wxpython/lmgr/frame.py index 2413d3b7c4a..963a36e3a58 100644 --- a/gui/wxpython/lmgr/frame.py +++ b/gui/wxpython/lmgr/frame.py @@ -1135,7 +1135,7 @@ def GetMenuCmd(self, event): layer = self.GetLayerTree().layer_selected name = self.GetLayerTree().GetLayerInfo(layer, key="maplayer").name type = self.GetLayerTree().GetLayerInfo(layer, key="type") - except AttributeError: + except (AttributeError, TypeError): layer = None if layer and len(cmdlist) == 1: # only if no parameters given @@ -1183,7 +1183,7 @@ def OnVDigit(self, event): # available only for vector map layers try: mapLayer = tree.GetLayerInfo(layer, key="maplayer") - except AttributeError: + except (AttributeError, TypeError): mapLayer = None if not mapLayer or mapLayer.GetType() != "vector": @@ -1860,7 +1860,7 @@ def OnShowAttributeTable(self, event, selection=None): # available only for vector map layers try: maptype = tree.GetLayerInfo(layer, key="maplayer").type - except AttributeError: + except (AttributeError, TypeError): maptype = None if not maptype or maptype != "vector": diff --git a/gui/wxpython/lmgr/layertree.py b/gui/wxpython/lmgr/layertree.py index 86531bcb5ad..855896e35ab 100644 --- a/gui/wxpython/lmgr/layertree.py +++ b/gui/wxpython/lmgr/layertree.py @@ -1758,7 +1758,7 @@ def OnDeleteLayer(self, event): try: if self.GetLayerInfo(item, key="type") != "group": self.Map.DeleteLayer(self.GetLayerInfo(item, key="maplayer")) - except AttributeError: + except (AttributeError, TypeError): pass # redraw map if auto-rendering is enabled @@ -2399,7 +2399,7 @@ def __FindSubItemByName(self, item, value): while item and item.IsOk(): try: itemLayer = self.GetLayerInfo(item, key="maplayer") - except KeyError: + except (KeyError, TypeError): return None if itemLayer and value == itemLayer.GetName(): From 4e8b0bf5e890f398b528f630c112b86b5a6d9471 Mon Sep 17 00:00:00 2001 From: Arohan Ajit Date: Thu, 17 Oct 2024 11:01:06 -0400 Subject: [PATCH 21/35] wxGUI: Fixed F841 in modules/ (#4528) --- .flake8 | 2 +- gui/wxpython/modules/histogram.py | 1 - gui/wxpython/modules/import_export.py | 11 ++--------- gui/wxpython/modules/mapsets_picker.py | 2 +- 4 files changed, 4 insertions(+), 12 deletions(-) diff --git a/.flake8 b/.flake8 index 6bfcc1e5527..dfc22985b42 100644 --- a/.flake8 +++ b/.flake8 @@ -24,7 +24,7 @@ per-file-ignores = doc/python/m.distance.py: E501 gui/scripts/d.wms.py: E501 gui/wxpython/image2target/g.gui.image2target.py: E501 - gui/wxpython/modules/*: F841, E722 + gui/wxpython/modules/*: E722 gui/wxpython/nviz/*: F841, E266, E722, F403, F405 gui/wxpython/photo2image/*: F841, E722, E265 gui/wxpython/photo2image/g.gui.photo2image.py: E501, F841 diff --git a/gui/wxpython/modules/histogram.py b/gui/wxpython/modules/histogram.py index 92510406ac7..c8001858dff 100644 --- a/gui/wxpython/modules/histogram.py +++ b/gui/wxpython/modules/histogram.py @@ -496,7 +496,6 @@ def SaveToFile(self, event): def PrintMenu(self, event): """Print options and output menu""" - point = wx.GetMousePosition() printmenu = Menu() # Add items to the menu setup = wx.MenuItem(printmenu, id=wx.ID_ANY, text=_("Page setup")) diff --git a/gui/wxpython/modules/import_export.py b/gui/wxpython/modules/import_export.py index f2f70e47831..a0bd17e289c 100644 --- a/gui/wxpython/modules/import_export.py +++ b/gui/wxpython/modules/import_export.py @@ -461,7 +461,6 @@ def OnRun(self, event): dsn = self.dsnInput.GetDsn() if not dsn: return - ext = self.dsnInput.GetFormatExt() for layer, output, listId in data: userData = {} @@ -613,7 +612,7 @@ def OnRun(self, event): return if not data: - GMessage(_("No layers selected. Operation canceled."), parent=self) + GMessage(parent=self, message=_("No layers selected. Operation canceled.")) return if not self._validateOutputMapName(): @@ -644,13 +643,7 @@ def OnRun(self, event): if ext and layer.rfind(ext) > -1: layer = layer.replace("." + ext, "") if "|" in layer: - layer, geometry = layer.split("|", 1) - else: - geometry = None - - # TODO: v.import has no geometry option - # if geometry: - # cmd.append('geometry=%s' % geometry) + layer = layer.split("|", 1)[0] cmd = self.getSettingsPageCmd() cmd.append("input=%s" % dsn) diff --git a/gui/wxpython/modules/mapsets_picker.py b/gui/wxpython/modules/mapsets_picker.py index e7ea7a3e40a..73df8fde3cc 100755 --- a/gui/wxpython/modules/mapsets_picker.py +++ b/gui/wxpython/modules/mapsets_picker.py @@ -12,7 +12,7 @@ def main(): - app = wx.App() + wx.App() dlg = MapsetAccess(parent=None) dlg.CenterOnScreen() From 941b52f87c44e6f19b3be960553d37deb7c0f1e8 Mon Sep 17 00:00:00 2001 From: Anna Petrasova Date: Thu, 17 Oct 2024 11:02:44 -0400 Subject: [PATCH 22/35] GUI: fix crashing due to File menu translation issues (#4513) --- gui/wxpython/lmgr/workspace.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/gui/wxpython/lmgr/workspace.py b/gui/wxpython/lmgr/workspace.py index 774c22bf4ed..b1e7aa400f0 100644 --- a/gui/wxpython/lmgr/workspace.py +++ b/gui/wxpython/lmgr/workspace.py @@ -519,12 +519,20 @@ def CreateRecentFilesMenu(self, menu=None): :return None """ if menu: - file_menu = menu.GetMenu( - menuIndex=menu.FindMenu(title=_("File")), - ) - workspace_item = file_menu.FindItem( - id=file_menu.FindItem(itemString=_("Workspace")), - )[0] + menu_index = menu.FindMenu(_("File")) + if menu_index == wx.NOT_FOUND: + # try untranslated version + menu_index = menu.FindMenu("File") + if menu_index == wx.NOT_FOUND: + return + file_menu = menu.GetMenu(menu_index) + workspace_index = file_menu.FindItem(_("Workspace")) + if workspace_index == wx.NOT_FOUND: + workspace_index = file_menu.FindItem("Workspace") + if workspace_index == wx.NOT_FOUND: + return + workspace_item = file_menu.FindItemById(workspace_index) + self._recent_files = RecentFilesMenu( app_name="main", parent_menu=workspace_item.GetSubMenu(), From fd347b9e837a6903d1f917bd56edd3aa8a9995ba Mon Sep 17 00:00:00 2001 From: Arohan Ajit Date: Thu, 17 Oct 2024 14:25:48 -0400 Subject: [PATCH 23/35] wxGUI: Fixed F841 in tools.py (#4539) --- .flake8 | 4 ++-- gui/wxpython/nviz/tools.py | 21 +++------------------ 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/.flake8 b/.flake8 index dfc22985b42..afe61c74642 100644 --- a/.flake8 +++ b/.flake8 @@ -24,8 +24,8 @@ per-file-ignores = doc/python/m.distance.py: E501 gui/scripts/d.wms.py: E501 gui/wxpython/image2target/g.gui.image2target.py: E501 - gui/wxpython/modules/*: E722 - gui/wxpython/nviz/*: F841, E266, E722, F403, F405 + gui/wxpython/modules/*: F841, E722 + gui/wxpython/nviz/*: E266, E722, F403, F405 gui/wxpython/photo2image/*: F841, E722, E265 gui/wxpython/photo2image/g.gui.photo2image.py: E501, F841 gui/wxpython/psmap/*: F841, E266, E722, F405, F403 diff --git a/gui/wxpython/nviz/tools.py b/gui/wxpython/nviz/tools.py index 20b1df1ffbd..153f8ffef86 100644 --- a/gui/wxpython/nviz/tools.py +++ b/gui/wxpython/nviz/tools.py @@ -667,7 +667,6 @@ def _createAnimationPage(self): parent=panel, id=wx.ID_ANY, label=" %s " % (_("Save image sequence")) ) boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL) - vSizer = wx.BoxSizer(wx.VERTICAL) gridSizer = wx.GridBagSizer(vgap=5, hgap=10) pwd = str(Path.cwd()) @@ -2817,7 +2816,6 @@ def OnAnimationFinished(self, mode): self.UpdateFrameIndex(index=0) slider = self.FindWindowById(self.win["anim"]["frameIndex"]["slider"]) - text = self.FindWindowById(self.win["anim"]["frameIndex"]["text"]) if mode == "record": count = anim.GetFrameCount() @@ -2922,7 +2920,7 @@ def OnConstantSelection(self, event): layerIdx = self.FindWindowById(self.win["constant"]["surface"]).GetSelection() if layerIdx == wx.NOT_FOUND: return - name = _("constant#") + str(layerIdx + 1) + data = self.mapWindow.constants[layerIdx] for attr, value in data["constant"].items(): if attr == "color": @@ -3123,8 +3121,6 @@ def _createIsosurfacePanel(self, parent): def _createSlicePanel(self, parent): panel = wx.Panel(parent=parent, id=wx.ID_ANY) - vSizer = wx.BoxSizer(wx.HORIZONTAL) - box = StaticBox( parent=panel, id=wx.ID_ANY, label=" %s " % (_("Slice attributes")) ) @@ -3412,12 +3408,11 @@ def OnSetSurface(self, event): """Surface selected, currently used for fringes""" name = event.GetString() try: - data = self._getLayerPropertiesByName(name, mapType="raster")["surface"] + self._getLayerPropertiesByName(name, mapType="raster")["surface"] except: self.EnablePage("fringe", False) return - layer = self._getMapLayerByName(name, mapType="raster") self.EnablePage("fringe", True) def OnSetRaster(self, event): @@ -3425,7 +3420,7 @@ def OnSetRaster(self, event): name = event.GetString() try: data = self._getLayerPropertiesByName(name, mapType="raster")["surface"] - except TypeError as e: + except TypeError: self.EnablePage("surface", False) return @@ -4590,10 +4585,6 @@ def OnVolumeSelect(self, event): if not winUp.IsEnabled(): winUp.Enable() - # update dialog - name = self.FindWindowById(self.win["volume"]["map"]).GetValue() - layer = self._getMapLayerByName(name, mapType="raster_3d") - if mode == "isosurf": data = self.GetLayerData("volume")["volume"]["isosurface"][selection] self.UpdateVolumeIsosurfPage(data) @@ -4694,8 +4685,6 @@ def OnVolumeDelete(self, event): if list.GetCount() > 0: list.SetSelection(list.GetCount() - 1) - name = self.FindWindowById(self.win["volume"]["map"]).GetValue() - layer = self._getMapLayerByName(name, mapType="raster_3d") data = self.GetLayerData("volume")["volume"] vid = data["object"]["id"] @@ -4736,8 +4725,6 @@ def OnVolumeMoveUp(self, event): if sel < 1: return # this should not happen - name = self.FindWindowById(self.win["volume"]["map"]).GetValue() - layer = self._getMapLayerByName(name, mapType="raster_3d") data = self.GetLayerData("volume")["volume"] id = data["object"]["id"] @@ -4776,8 +4763,6 @@ def OnVolumeMoveDown(self, event): if sel >= list.GetCount() - 1: return # this should not happen - name = self.FindWindowById(self.win["volume"]["map"]).GetValue() - layer = self._getMapLayerByName(name, mapType="raster_3d") data = self.GetLayerData("volume")["volume"] id = data["object"]["id"] From daee9896da48bced7d59cfb998952f7ff6e2245b Mon Sep 17 00:00:00 2001 From: Arohan Ajit Date: Thu, 17 Oct 2024 14:27:05 -0400 Subject: [PATCH 24/35] wxGUI: Fixed F405 in psmap/ (#4541) --- .flake8 | 2 +- gui/wxpython/psmap/dialogs.py | 53 +++++++++++++++++++++------ gui/wxpython/psmap/frame.py | 57 +++++++++++++++++++++--------- gui/wxpython/psmap/instructions.py | 20 ++++++++--- 4 files changed, 100 insertions(+), 32 deletions(-) diff --git a/.flake8 b/.flake8 index afe61c74642..5c23d51bd36 100644 --- a/.flake8 +++ b/.flake8 @@ -28,7 +28,7 @@ per-file-ignores = gui/wxpython/nviz/*: E266, E722, F403, F405 gui/wxpython/photo2image/*: F841, E722, E265 gui/wxpython/photo2image/g.gui.photo2image.py: E501, F841 - gui/wxpython/psmap/*: F841, E266, E722, F405, F403 + gui/wxpython/psmap/*: F841, E266, E722 gui/wxpython/vdigit/*: F841, E722, F405, F403 gui/wxpython/vnet/*: F841 gui/wxpython/wxgui.py: F841 diff --git a/gui/wxpython/psmap/dialogs.py b/gui/wxpython/psmap/dialogs.py index 66ac66d9348..0bbe779818a 100644 --- a/gui/wxpython/psmap/dialogs.py +++ b/gui/wxpython/psmap/dialogs.py @@ -42,9 +42,8 @@ import wx import wx.lib.agw.floatspin as fs -from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin - from core import globalvar +from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin if globalvar.wxPythonPhoenix: from wx import Validator @@ -52,24 +51,25 @@ from wx import PyValidator as Validator import grass.script as gs - -from core.utils import PilImageToWxImage +from core.gcmd import GError, GMessage, RunCommand +from core.utils import PilImageToWxImage, cmp from dbmgr.vinfo import VectorDBInfo -from gui_core.gselect import Select -from core.gcmd import RunCommand, GError, GMessage from gui_core.dialogs import SymbolDialog +from gui_core.gselect import Select from gui_core.wrap import ( BitmapButton, BitmapComboBox, BitmapFromImage, Button, CheckBox, + CheckListCtrlMixin, Choice, ClientDC, ColourPickerCtrl, Dialog, DirBrowseButton, EmptyBitmap, + EmptyImage, ExpandoTextCtrl, FileBrowseButton, FloatSpin, @@ -86,11 +86,44 @@ StaticText, TextCtrl, TextEntryDialog, - EmptyImage, - CheckListCtrlMixin, ) -from psmap.utils import * -from psmap.instructions import * + +# Explicit imports from psmap.instructions +from psmap.instructions import ( + Image, + Labels, + Line, + MapFrame, + Mapinfo, + NewId, + NorthArrow, + Point, + Raster, + RasterLegend, + Rectangle, + Scalebar, + Text, + Vector, + VectorLegend, + VProperties, +) + +# Explicit imports from psmap.utils +from psmap.utils import ( + AutoAdjust, + BBoxAfterRotation, + ComputeSetRegion, + PaperMapCoordinates, + PILImage, + Rect2D, + Rect2DPP, + SetResolution, + UnitConversion, + convertRGB, + getRasterType, + havePILImage, + projInfo, +) # grass.set_raise_on_error(True) diff --git a/gui/wxpython/psmap/frame.py b/gui/wxpython/psmap/frame.py index b3196d348fa..13fdc91a984 100644 --- a/gui/wxpython/psmap/frame.py +++ b/gui/wxpython/psmap/frame.py @@ -16,10 +16,9 @@ """ import os -import sys - import queue as Queue -from math import sin, cos, pi, sqrt +import sys +from math import cos, pi, sin, sqrt import wx @@ -29,25 +28,51 @@ import wx.lib.flatnotebook as FN import grass.script as gs - from core import globalvar -from gui_core.menu import Menu -from core.gconsole import CmdThread, EVT_CMD_DONE -from psmap.toolbars import PsMapToolbar -from core.gcmd import RunCommand, GError, GMessage +from core.gcmd import GError, GMessage, RunCommand +from core.gconsole import EVT_CMD_DONE, CmdThread from core.settings import UserSettings from core.utils import PilImageToWxImage -from gui_core.forms import GUI -from gui_core.widgets import GNotebook from gui_core.dialogs import HyperlinkDialog +from gui_core.forms import GUI from gui_core.ghelp import ShowAboutDialog -from gui_core.wrap import ClientDC, PseudoDC, Rect, StockCursor, EmptyBitmap -from psmap.menudata import PsMapMenuData +from gui_core.menu import Menu from gui_core.toolbars import ToolSwitcher - -from psmap.dialogs import * -from psmap.instructions import * -from psmap.utils import * +from gui_core.widgets import GNotebook +from gui_core.wrap import ClientDC, EmptyBitmap, PseudoDC, Rect, StockCursor + +from psmap.dialogs import ( + ImageDialog, + LabelsDialog, + LegendDialog, + MainVectorDialog, + MapDialog, + MapinfoDialog, + NorthArrowDialog, + PageSetupDialog, + PointDialog, + RasterDialog, + RectangleDialog, + ScalebarDialog, + TextDialog, +) +from psmap.instructions import InitMap, Instruction, NewId, SetResolution, PageSetup +from psmap.menudata import PsMapMenuData +from psmap.toolbars import PsMapToolbar +from psmap.utils import ( + AutoAdjust, + ComputeSetRegion, + GetMapBounds, + PaperMapCoordinates, + PILImage, + Rect2D, + Rect2DPP, + Rect2DPS, + UnitConversion, + convertRGB, + havePILImage, + projInfo, +) class PsMapFrame(wx.Frame): diff --git a/gui/wxpython/psmap/instructions.py b/gui/wxpython/psmap/instructions.py index 9db64679422..845e99b2e6a 100644 --- a/gui/wxpython/psmap/instructions.py +++ b/gui/wxpython/psmap/instructions.py @@ -35,17 +35,27 @@ import os import string from math import ceil -from time import strftime, localtime +from time import localtime, strftime -import wx import grass.script as gs -from grass.script.task import cmdlist_to_tuple - +import wx from core.gcmd import GError, GMessage, GWarning from core.utils import GetCmdString from dbmgr.vinfo import VectorDBInfo +from grass.script.task import cmdlist_to_tuple from gui_core.wrap import NewId as wxNewId -from psmap.utils import * + +from psmap.utils import ( # Add any additional required names from psmap.utils here + BBoxAfterRotation, + GetMapBounds, + PaperMapCoordinates, + Rect2D, + Rect2DPP, + SetResolution, + UnitConversion, + getRasterType, + projInfo, +) def NewId(): From 0adc4dc2ec42e07c82012fb948b0b9cac4b4afb3 Mon Sep 17 00:00:00 2001 From: Arohan Ajit Date: Thu, 17 Oct 2024 14:29:38 -0400 Subject: [PATCH 25/35] wxGUI: Fixed unused variable F841 (#4542) --- .flake8 | 1 - gui/wxpython/wxgui.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.flake8 b/.flake8 index 5c23d51bd36..92611007661 100644 --- a/.flake8 +++ b/.flake8 @@ -31,7 +31,6 @@ per-file-ignores = gui/wxpython/psmap/*: F841, E266, E722 gui/wxpython/vdigit/*: F841, E722, F405, F403 gui/wxpython/vnet/*: F841 - gui/wxpython/wxgui.py: F841 gui/wxpython/animation/g.gui.animation.py: E501 gui/wxpython/tplot/frame.py: F841, E722 gui/wxpython/tplot/g.gui.tplot.py: E501 diff --git a/gui/wxpython/wxgui.py b/gui/wxpython/wxgui.py index 447821c6724..8fac39c4d5a 100644 --- a/gui/wxpython/wxgui.py +++ b/gui/wxpython/wxgui.py @@ -164,7 +164,7 @@ def main(argv=None): app = GMApp(workspaceFile) # suppress wxPython logs - q = wx.LogNull() + wx.LogNull() set_raise_on_error(True) # register GUI PID From e540efc76618837947fefca21d8b141913ff6376 Mon Sep 17 00:00:00 2001 From: Ivan Mincik Date: Thu, 17 Oct 2024 19:48:24 +0000 Subject: [PATCH 26/35] nix: Fix locales in development environment (#4540) This fixes locales in nix provided development environment by setting environment variable. Closes #4503 --- flake.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/flake.nix b/flake.nix index 51174e1da74..a105607417f 100644 --- a/flake.nix +++ b/flake.nix @@ -34,6 +34,8 @@ pytest ]; + LOCALE_ARCHIVE = "${pkgs.glibcLocales}/lib/locale/locale-archive"; + shellHook = '' function dev-help { echo -e "\nWelcome to a GRASS development environment !" From 9dbc8c96b05eaff6df9dc2ffd55c7e8f45fa25e9 Mon Sep 17 00:00:00 2001 From: Markus Neteler Date: Thu, 17 Oct 2024 23:33:50 +0200 Subject: [PATCH 27/35] docs: add intro text to imageryintro.html (#4536) This PR adds an overview text to imageryintro.html including a link to addons. (aside, addons URL fix in g.gui.gmodeler.html) Co-authored-by: Nicklas Larsson Co-authored-by: Vaclav Petras --- gui/wxpython/gmodeler/g.gui.gmodeler.html | 2 +- imagery/imageryintro.html | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/gui/wxpython/gmodeler/g.gui.gmodeler.html b/gui/wxpython/gmodeler/g.gui.gmodeler.html index 631c06de9d8..a840768abeb 100644 --- a/gui/wxpython/gmodeler/g.gui.gmodeler.html +++ b/gui/wxpython/gmodeler/g.gui.gmodeler.html @@ -466,7 +466,7 @@

SEE ALSO

See also selected user models available from -GRASS Addons repository. +GRASS Addons repository.

See also diff --git a/imagery/imageryintro.html b/imagery/imageryintro.html index 4b80951af9e..9018b4871ae 100644 --- a/imagery/imageryintro.html +++ b/imagery/imageryintro.html @@ -2,6 +2,21 @@

Image processing in general

+GRASS GIS provides a powerful suite of tools for the processing and +analysis of geospatial raster data, including satellite imagery and +aerial photography. Its image processing capabilities encompass a broad +range of preprocessing operations, such as data import, georeferencing, +radiometric calibration, and atmospheric correction. It is particularly +suited for handling Earth observation data, enabling the analysis of +multispectral and temporal datasets. GRASS GIS supports advanced +functionalities such as image classification, sensor fusion, and point +cloud statistics. The calculation of vegetation indices further enables +analyses of environmental, agricultural, and land cover dynamics. An +extensive collection of +addons +further enhances its image processing capabilities, particularly in the +context of Earth observation and remote sensing applications. + Digital numbers and physical values (reflection/radiance-at-sensor):

Satellite imagery is commonly stored in Digital Numbers (DN) for From 37d40827fce95fc0e1231616d621f6bb496172ba Mon Sep 17 00:00:00 2001 From: Markus Neteler Date: Thu, 17 Oct 2024 23:44:17 +0200 Subject: [PATCH 28/35] GUI: EPSG code source: replace epsg.io with spatialreference.org (#4535) As epsg.io is partially outdated (see [source](https://github.com/maptiler/epsg.io/issues/171) and related) and PROJ is our engine anyway, this PR switches the references in the GUI to https://spatialreference.org. * "See also" section: added URLs to CRS Explorer and EPSG Geodetic Parameter Dataset Co-authored-by: Vaclav Petras --- gui/wxpython/location_wizard/wizard.py | 11 +++++++---- lib/init/helptext.html | 6 ++++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/gui/wxpython/location_wizard/wizard.py b/gui/wxpython/location_wizard/wizard.py index d8b6b4180ba..1f8de66dda6 100644 --- a/gui/wxpython/location_wizard/wizard.py +++ b/gui/wxpython/location_wizard/wizard.py @@ -1604,9 +1604,12 @@ def __init__(self, wizard, parent): self, data=None, columns=[_("Code"), _("Description"), _("Parameters")] ) - # epsg.io hyperlink + # A hyperlink to a CRS database (PROJ related) self.tlink = HyperlinkCtrl( - self, id=wx.ID_ANY, label="epsg.io", url="https://epsg.io/" + self, + id=wx.ID_ANY, + label="spatialreference.org", + url="https://spatialreference.org/", ) self.tlink.SetNormalColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) self.tlink.SetVisitedColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_GRAYTEXT)) @@ -1688,14 +1691,14 @@ def EnableNext(self, enable=True): def OnTextChange(self, event): value = self.searchb.GetValue() if value == "": - self.tlink.SetURL("https://epsg.io/") + self.tlink.SetURL("https://spatialreference.org/") self.epsgcode = None self.epsgdesc = self.epsgparams = "" self.searchb.ChangeValue("") self.OnBrowseCodes(None) self.EnableNext(False) else: - self.tlink.SetURL(str("https://epsg.io/?q={0}".format(value))) + self.tlink.SetURL(f"https://spatialreference.org/ref/?&search={value}") data = self.epsglist.Search(index=[0, 1, 2], pattern=value, firstOnly=False) if data: index = 0 diff --git a/lib/init/helptext.html b/lib/init/helptext.html index d988b6b0376..4a14dd52df1 100644 --- a/lib/init/helptext.html +++ b/lib/init/helptext.html @@ -62,7 +62,7 @@

GRASS started in the default project, now what?

Creating a New project with the Project Wizard

If you know the CRS of your data or study area, -you can fill EPSG code +you can fill EPSG code or description and Project Wizard finds appropriate CRS from a predefined list of projections. @@ -97,4 +97,6 @@

See also

- List of EPSG codes (Database of worldwide coordinate systems) + List of EPSG codes (Database of worldwide coordinate systems), + CRS Explorer - PROJ codes, and + EPSG Geodetic Parameter Dataset From 3c678251df9b4dbe30c6cef2f075eeea18efa1df Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 18 Oct 2024 01:47:57 +0000 Subject: [PATCH 29/35] CI(deps): Update ruff to v0.7.0 (#4544) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * CI(deps): Update ruff to v0.7.0 * style: Fix FURB156: Use of hardcoded string charset --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Edouard Choinière <27212526+echoix@users.noreply.github.com> --- .github/workflows/python-code-quality.yml | 2 +- .pre-commit-config.yaml | 2 +- gui/wxpython/core/utils.py | 3 ++- gui/wxpython/gui_core/goutput.py | 3 ++- python/grass/imaging/images2ims.py | 3 ++- scripts/d.rast.edit/d.rast.edit.py | 4 +++- 6 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.github/workflows/python-code-quality.yml b/.github/workflows/python-code-quality.yml index 886cbe56b47..9f71c28e922 100644 --- a/.github/workflows/python-code-quality.yml +++ b/.github/workflows/python-code-quality.yml @@ -36,7 +36,7 @@ jobs: # renovate: datasource=pypi depName=bandit BANDIT_VERSION: "1.7.10" # renovate: datasource=pypi depName=ruff - RUFF_VERSION: "0.6.9" + RUFF_VERSION: "0.7.0" runs-on: ${{ matrix.os }} permissions: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2c136da40ff..4c82e138950 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -37,7 +37,7 @@ repos: ) - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.6.9 + rev: v0.7.0 hooks: # Run the linter. - id: ruff diff --git a/gui/wxpython/core/utils.py b/gui/wxpython/core/utils.py index 3c1b4a7dd14..2b1f3f4997a 100644 --- a/gui/wxpython/core/utils.py +++ b/gui/wxpython/core/utils.py @@ -20,6 +20,7 @@ import re import inspect import operator +from string import digits from grass.script import core as grass from grass.script import task as gtask @@ -936,7 +937,7 @@ def SetAddOnPath(addonPath=None, key="PATH"): def color_resolve(color): - if len(color) > 0 and color[0] in "0123456789": + if len(color) > 0 and color[0] in digits: rgb = tuple(map(int, color.split(":"))) label = color else: diff --git a/gui/wxpython/gui_core/goutput.py b/gui/wxpython/gui_core/goutput.py index 3c8927f2233..6676eb69935 100644 --- a/gui/wxpython/gui_core/goutput.py +++ b/gui/wxpython/gui_core/goutput.py @@ -20,6 +20,7 @@ """ import textwrap +from string import digits import wx from wx import stc @@ -624,7 +625,7 @@ def AddStyledMessage(self, message, style=None): self.linePos = self.GetCurrentPos() if c != " ": last_c = c - if last_c not in ("0123456789"): + if last_c not in (digits): self.AddTextWrapped("\n", wrap=None) self.linePos = -1 else: diff --git a/python/grass/imaging/images2ims.py b/python/grass/imaging/images2ims.py index a5cee9b49de..d86a2247952 100644 --- a/python/grass/imaging/images2ims.py +++ b/python/grass/imaging/images2ims.py @@ -32,6 +32,7 @@ import os from operator import itemgetter +from string import digits try: import numpy as np @@ -117,7 +118,7 @@ def _getSequenceNumber(filename, part1, part2): # Get all numeric chars seq2 = "" for c in seq: - if c in "0123456789": + if c in digits: seq2 += c else: break diff --git a/scripts/d.rast.edit/d.rast.edit.py b/scripts/d.rast.edit/d.rast.edit.py index 6519d10c7a1..ea6cc1e46bf 100755 --- a/scripts/d.rast.edit/d.rast.edit.py +++ b/scripts/d.rast.edit/d.rast.edit.py @@ -77,6 +77,8 @@ import sys import math import atexit +from string import digits + import grass.script as gs from grass.script.setup import set_gui_path @@ -448,7 +450,7 @@ def OnClose(self, ev): def OnReturn(self, ev): self.app.brush = self.newval.GetValue() - if self.app.brush != "*" and self.app.brush.strip("0123456789") != "": + if self.app.brush != "*" and self.app.brush.strip(digits) != "": self.app.brush = "*" self.brush_update() From d788eee193b3e3a4d10194775cec9d4429802403 Mon Sep 17 00:00:00 2001 From: Mohan Yelugoti Date: Fri, 18 Oct 2024 00:31:28 -0400 Subject: [PATCH 30/35] i.atcorr: fix out of bound access in trunca, os and iso (#4493) * i.atcorr: fix out of bound access in trunca, os and iso In trunca(), under 2 if conditionals (if rumu[1] > 0.8 and rmu[1] > 0.94), k and kk values are set to -1 respectively. When these values are used to access an array, it leads to out of bound access, which is undefined behavior in c++. Similarly in os() and iso(), if `taup < h[i]` for all values, iplane would still be -1 and we would be accessing an array with this as an index, which is undefined behavior. In both cases, to avoid that, set that index to zero. This was found using cppcheck tool. Signed-off-by: Mohan Yelugoti * Update imagery/i.atcorr/computations.cpp When plane layer couldn't be determined, throw out an error and exit. Co-authored-by: Markus Metz <33666869+metzm@users.noreply.github.com> * Update imagery/i.atcorr/computations.cpp When plane layer couldn't be determined, throw out an error and exit. Co-authored-by: Markus Metz <33666869+metzm@users.noreply.github.com> * Fix clang-format issues Signed-off-by: Mohan Yelugoti --------- Signed-off-by: Mohan Yelugoti Co-authored-by: Markus Metz <33666869+metzm@users.noreply.github.com> --- imagery/i.atcorr/computations.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/imagery/i.atcorr/computations.cpp b/imagery/i.atcorr/computations.cpp index 53f8664ee06..6e5a38c5b07 100644 --- a/imagery/i.atcorr/computations.cpp +++ b/imagery/i.atcorr/computations.cpp @@ -102,14 +102,14 @@ double trunca() for (i = 0; i < 83; i++) { if (rmu[i] > 0.8) break; - k = i - 1; + k = i; } int kk = 0; for (i = 0; i < 83; i++) { if (rmu[i] > 0.94) break; - kk = i - 1; + kk = i; } double aa = @@ -118,7 +118,7 @@ double trunca() double x1 = (double)(log10(sixs_trunc.pha[kk])); double x2 = (double)acos(rmu[kk]); - for (i = kk + 1; i < 83; i++) { + for (i = kk; i < 83; i++) { double a; if (fabs(rmu[i] - 1) <= 1e-08) a = x1 - aa * x2; @@ -445,9 +445,14 @@ void os(const double tamoy, const double trmoy, const double pizmoy, /* compute position of the plane layer */ double taup = tap + trp; iplane = -1; - for (int i = 0; i <= ntp; i++) + for (int i = 0; i <= ntp; i++) { if (taup >= h[i]) iplane = i; + } + if (iplane == -1) { + G_fatal_error( + _("Position of the plane layer could not be determined")); + } /* update the layer from the end to the position to update if necessary */ @@ -1006,9 +1011,14 @@ void iso(const double tamoy, const double trmoy, const double pizmoy, /* compute position of the plane layer */ double taup = tap + trp; iplane = -1; - for (int i = 0; i <= ntp; i++) + for (int i = 0; i <= ntp; i++) { if (taup >= h[i]) iplane = i; + } + if (iplane == -1) { + G_fatal_error( + _("Position of the plane layer could not be determined")); + } /* update the layer from the end to the position to update if necessary */ From 0cb20eb612b933dc914461f6c541510213bc71e0 Mon Sep 17 00:00:00 2001 From: Arohan Ajit Date: Fri, 18 Oct 2024 09:18:53 -0400 Subject: [PATCH 31/35] wxGUI: Fixed F841 in vnet/ (#4543) --- .flake8 | 1 - gui/wxpython/vnet/dialogs.py | 2 -- gui/wxpython/vnet/toolbars.py | 1 - gui/wxpython/vnet/vnet_core.py | 18 ------------------ gui/wxpython/vnet/vnet_data.py | 2 +- gui/wxpython/vnet/vnet_utils.py | 1 - gui/wxpython/vnet/widgets.py | 2 -- 7 files changed, 1 insertion(+), 26 deletions(-) diff --git a/.flake8 b/.flake8 index 92611007661..306a11fe02b 100644 --- a/.flake8 +++ b/.flake8 @@ -30,7 +30,6 @@ per-file-ignores = gui/wxpython/photo2image/g.gui.photo2image.py: E501, F841 gui/wxpython/psmap/*: F841, E266, E722 gui/wxpython/vdigit/*: F841, E722, F405, F403 - gui/wxpython/vnet/*: F841 gui/wxpython/animation/g.gui.animation.py: E501 gui/wxpython/tplot/frame.py: F841, E722 gui/wxpython/tplot/g.gui.tplot.py: E501 diff --git a/gui/wxpython/vnet/dialogs.py b/gui/wxpython/vnet/dialogs.py index 39cf2e4ae84..8d24b08df91 100644 --- a/gui/wxpython/vnet/dialogs.py +++ b/gui/wxpython/vnet/dialogs.py @@ -1245,8 +1245,6 @@ def __init__( wx.Dialog.__init__(self, parent, id, title, pos, size, style) self.vnet_mgr = vnet_mgr - - maxValue = 1e8 self.parent = parent self.settings = {} diff --git a/gui/wxpython/vnet/toolbars.py b/gui/wxpython/vnet/toolbars.py index 5f80e50cd9d..d31313091fe 100644 --- a/gui/wxpython/vnet/toolbars.py +++ b/gui/wxpython/vnet/toolbars.py @@ -235,6 +235,5 @@ def __init__(self, parent, vnet_mgr): self.Realize() def _toolbarData(self): - icons = {} return self._getToolbarData(()) diff --git a/gui/wxpython/vnet/vnet_core.py b/gui/wxpython/vnet/vnet_core.py index 8dda73b6770..2e98aa2ee8f 100644 --- a/gui/wxpython/vnet/vnet_core.py +++ b/gui/wxpython/vnet/vnet_core.py @@ -459,11 +459,6 @@ def _vnetPathRunAn(self, analysis, output, params, flags, catPts): return False mapName, mapSet = ParseMapStr(self.tmpTurnAn.GetVectMapName()) - cmdCopy = [ - "g.copy", - "vector=%s,%s" % (params["input"], mapName), - "--overwrite", - ] cmdParams.append("input=" + self.tmpTurnAn.GetVectMapName()) ret, msg, err = RunCommand( @@ -550,11 +545,6 @@ def _runTurnsAn(self, analysis, output, params, flags, catPts): # create and run commands which goes to analysis thread mapName, mapSet = ParseMapStr(self.tmpTurnAn.GetVectMapName()) - cmdCopy = [ - "g.copy", - "vector=%s,%s" % (params["input"], mapName), - "--overwrite", - ] cmdParams.append("input=" + self.tmpTurnAn.GetVectMapName()) ret, msg, err = RunCommand( @@ -580,14 +570,6 @@ def _updateTtbByGlobalCosts(self, vectMapName, tlayer): # TODO get layer number do not use it directly intervals = self.turnsData["global"].GetData() - cmdUpdGlob = [ - "v.db.update", - "map=", - self.inputData["input"].GetValue(), - "layer=%d" % tlayer, - "column=cost", - ] - dbInfo = VectorDBInfo(vectMapName) table = dbInfo.GetTable(tlayer) driver, database = dbInfo.GetDbSettings(tlayer) diff --git a/gui/wxpython/vnet/vnet_data.py b/gui/wxpython/vnet/vnet_data.py index 3adc5fa64e9..f2f17b0bfb5 100644 --- a/gui/wxpython/vnet/vnet_data.py +++ b/gui/wxpython/vnet/vnet_data.py @@ -1377,7 +1377,7 @@ def SetValue(self, value, line, col): def SetUTurns(self, value): """Checked if checeBox is checed""" - useUTurns = value + self.useUTurns = value def AppendRow(self, values): self.turn_data.append(values) diff --git a/gui/wxpython/vnet/vnet_utils.py b/gui/wxpython/vnet/vnet_utils.py index f0a354691bc..e3cc11aee17 100644 --- a/gui/wxpython/vnet/vnet_utils.py +++ b/gui/wxpython/vnet/vnet_utils.py @@ -133,7 +133,6 @@ def GetNearestNodeCat(e, n, layer, tresh, vectMap): vectlib.Vect_select_lines_by_box(openedMap, byref(box), vectlib.GV_POINT, List) found = 0 - dcost = 0 Cats = POINTER(vectlib.line_cats) Cats = vectlib.Vect_new_cats_struct() diff --git a/gui/wxpython/vnet/widgets.py b/gui/wxpython/vnet/widgets.py index ed1f2aa514c..71fcd0e0739 100644 --- a/gui/wxpython/vnet/widgets.py +++ b/gui/wxpython/vnet/widgets.py @@ -217,7 +217,6 @@ def GetCellValue(self, key, colName): if colNum < 0: return None - iColEd = self.dataTypes["colEditable"] if self.selIdxs[key][colNum] != -1: return self.selIdxs[key][colNum] @@ -230,7 +229,6 @@ def GetCellSelIdx(self, key, colName): :return: -1 if column does not has values to choose """ colNum = self._getColumnNum(colName) - iColEd = self.dataTypes["colEditable"] return self.selIdxs[key][colNum] def EditCellIndex(self, index, colName, cellData): From 6fd21a886dad53a02cbfb73fafe70eb9914b65be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edouard=20Choini=C3=A8re?= <27212526+echoix@users.noreply.github.com> Date: Fri, 18 Oct 2024 09:39:56 -0400 Subject: [PATCH 32/35] tests: Call t.remove and g.remove once with multiple inputs as list (#4523) * t.rast.accumulate: Call t.remove with multiple inputs in test_accumulation * t.rast.accdetect: Call t.remove with multiple inputs * t.rast.univar: Call t.remove once with multiple inputs * tests: Call g.remove once with multiple names to remove One call per type, when all other arguments are the same * benchmark: Call g.remove once with multiple names to remove One call per type, when all other arguments are the same * utils/thumbnails: Call g.remove once with multiple names to remove * Use tuple for supplying multiple input maps --- imagery/i.gensig/testsuite/test_i_gensig.py | 10 +++-- imagery/i.maxlik/testsuite/test_i_maxlik.py | 11 +++-- imagery/i.vi/testsuite/test_vi.py | 14 +++---- lib/imagery/testsuite/test_imagery_sigfile.py | 9 ++-- .../testsuite/test_imagery_sigsetfile.py | 9 ++-- raster/r.contour/testsuite/test_r_contour.py | 7 ++-- .../testsuite/test_r_in_pdal_binning.py | 8 +++- .../testsuite/test_r_in_pdal_selection.py | 8 +++- raster/r.kappa/testsuite/test_r_kappa.py | 15 ++++--- .../benchmark/benchmark_r_mfilter_nprocs.py | 3 +- .../benchmark/benchmark_r_neighbors_nprocs.py | 3 +- raster/r.random/testsuite/test_r_random.py | 28 ++++++------- .../benchmark/benchmark_r_resamp_filter.py | 3 +- .../benchmark/benchmark_r_resamp_interp.py | 3 +- .../r.series/benchmark/benchmark_r_series.py | 3 +- .../benchmark/benchmark_r_slope_aspect.py | 12 +++--- .../benchmark_r_slope_aspect_memory.py | 11 +++-- raster/r.tile/testsuite/test_r_tile.py | 42 +++++-------------- .../r.univar/benchmark/benchmark_r_univar.py | 3 +- raster/r.univar/testsuite/test_r_univar.py | 11 ++--- raster3d/r3.null/testsuite/test.r3.null.sh | 9 +--- .../testsuite/test_rmapcalcsimple.py | 5 ++- .../testsuite/test_r_reclass_area.py | 8 +++- .../testsuite/test_v_rast_stats.py | 11 ++--- .../t.rast.accdetect/testsuite/test_simple.py | 3 +- .../testsuite/test_accumulation.py | 4 +- .../t.rast.series/testsuite/test_series.py | 24 +++++++---- .../testsuite/test_t_rast_univar.py | 3 +- .../t.topology/test.t.topology.reltime.sh | 3 +- .../t.vect.extract/test.t.vect.extract.sh | 3 +- utils/thumbnails.py | 9 ++-- vector/v.random/testsuite/test_v_random.py | 5 ++- .../benchmark/benchmark_v_surf_rst.py | 3 +- .../benchmark/benchmark_v_surf_rst_cv.py | 3 +- 34 files changed, 151 insertions(+), 155 deletions(-) diff --git a/imagery/i.gensig/testsuite/test_i_gensig.py b/imagery/i.gensig/testsuite/test_i_gensig.py index d75e3da2af4..836550fd1e6 100644 --- a/imagery/i.gensig/testsuite/test_i_gensig.py +++ b/imagery/i.gensig/testsuite/test_i_gensig.py @@ -92,9 +92,13 @@ def tearDownClass(cls): """Remove the temporary region and generated data""" cls.del_temp_region() shutil.rmtree(cls.sig_dir1, ignore_errors=True) - cls.runModule("g.remove", flags="f", type="raster", name=cls.b1, quiet=True) - cls.runModule("g.remove", flags="f", type="raster", name=cls.b2, quiet=True) - cls.runModule("g.remove", flags="f", type="raster", name=cls.train, quiet=True) + cls.runModule( + "g.remove", + flags="f", + type="raster", + name=(cls.b1, cls.b2, cls.train), + quiet=True, + ) def test_creation(self): """Test creating a signature""" diff --git a/imagery/i.maxlik/testsuite/test_i_maxlik.py b/imagery/i.maxlik/testsuite/test_i_maxlik.py index e7fbf6c1a79..2245d0d6d58 100644 --- a/imagery/i.maxlik/testsuite/test_i_maxlik.py +++ b/imagery/i.maxlik/testsuite/test_i_maxlik.py @@ -163,13 +163,12 @@ def tearDownClass(cls): cls.del_temp_region() shutil.rmtree(cls.sig_dir1, ignore_errors=True) shutil.rmtree(cls.sig_dir2, ignore_errors=True) - cls.runModule("g.remove", flags="f", type="raster", name=cls.b1, quiet=True) - cls.runModule("g.remove", flags="f", type="raster", name=cls.b2, quiet=True) cls.runModule( - "g.remove", flags="f", type="raster", name=cls.v1_class, quiet=True - ) - cls.runModule( - "g.remove", flags="f", type="raster", name=cls.v2_class, quiet=True + "g.remove", + flags="f", + type="raster", + name=(cls.b1, cls.b2, cls.v1_class, cls.v2_class), + quiet=True, ) cls.runModule("g.remove", flags="f", type="group", name=cls.group, quiet=True) diff --git a/imagery/i.vi/testsuite/test_vi.py b/imagery/i.vi/testsuite/test_vi.py index 0c383417257..b2160f924ed 100644 --- a/imagery/i.vi/testsuite/test_vi.py +++ b/imagery/i.vi/testsuite/test_vi.py @@ -26,14 +26,12 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): - cls.runModule("g.remove", flags="f", type="raster", name="ipvi") - cls.runModule("g.remove", flags="f", type="raster", name="ndwi") - cls.runModule("g.remove", flags="f", type="raster", name="dvi") - cls.runModule("g.remove", flags="f", type="raster", name="sr") - cls.runModule("g.remove", flags="f", type="raster", name="evi") - cls.runModule("g.remove", flags="f", type="raster", name="evi2") - cls.runModule("g.remove", flags="f", type="raster", name="gari") - cls.runModule("g.remove", flags="f", type="raster", name="gemi") + cls.runModule( + "g.remove", + flags="f", + type="raster", + name="ipvi,ndwi,dvi,sr,evi,evi2,gari,gemi", + ) cls.del_temp_region() def test_vinameipvi(self): diff --git a/lib/imagery/testsuite/test_imagery_sigfile.py b/lib/imagery/testsuite/test_imagery_sigfile.py index 8d0e288561d..731ef047063 100644 --- a/lib/imagery/testsuite/test_imagery_sigfile.py +++ b/lib/imagery/testsuite/test_imagery_sigfile.py @@ -349,9 +349,12 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): cls.del_temp_region() - cls.runModule("g.remove", flags="f", type="raster", name=cls.map1) - cls.runModule("g.remove", flags="f", type="raster", name=cls.map2) - cls.runModule("g.remove", flags="f", type="raster", name=cls.map3) + cls.runModule( + "g.remove", + flags="f", + type="raster", + name=(cls.map1, cls.map2, cls.map3), + ) def test_symmetric_complete_difference(self): # Prepare imagery group reference struct diff --git a/lib/imagery/testsuite/test_imagery_sigsetfile.py b/lib/imagery/testsuite/test_imagery_sigsetfile.py index d526e920885..80be7c0d3a5 100644 --- a/lib/imagery/testsuite/test_imagery_sigsetfile.py +++ b/lib/imagery/testsuite/test_imagery_sigsetfile.py @@ -242,9 +242,12 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): cls.del_temp_region() - cls.runModule("g.remove", flags="f", type="raster", name=cls.map1) - cls.runModule("g.remove", flags="f", type="raster", name=cls.map2) - cls.runModule("g.remove", flags="f", type="raster", name=cls.map3) + cls.runModule( + "g.remove", + flags="f", + type="raster", + name=(cls.map1, cls.map2, cls.map3), + ) def test_symmetric_complete_difference(self): # Prepare imagery group reference struct diff --git a/raster/r.contour/testsuite/test_r_contour.py b/raster/r.contour/testsuite/test_r_contour.py index c9ee4c9876a..49617ef043d 100644 --- a/raster/r.contour/testsuite/test_r_contour.py +++ b/raster/r.contour/testsuite/test_r_contour.py @@ -32,10 +32,11 @@ def setUpClass(cls): def tearDownClass(cls): cls.del_temp_region() - cls.runModule("g.remove", type="vector", flags="f", name=cls.output) - cls.runModule("g.remove", type="vector", flags="f", name=cls.output + "_cut") cls.runModule( - "g.remove", type="vector", flags="f", name=cls.output + "_cut_flag_t" + "g.remove", + type="vector", + flags="f", + name=(cls.output, cls.output + "_cut", cls.output + "_cut_flag_t"), ) if os.path.isfile("testReport"): diff --git a/raster/r.in.pdal/testsuite/test_r_in_pdal_binning.py b/raster/r.in.pdal/testsuite/test_r_in_pdal_binning.py index a8a793f5bc7..c256224590d 100644 --- a/raster/r.in.pdal/testsuite/test_r_in_pdal_binning.py +++ b/raster/r.in.pdal/testsuite/test_r_in_pdal_binning.py @@ -68,8 +68,12 @@ def tearDown(self): This is executed after each test run. """ - self.runModule("g.remove", flags="f", type="raster", name=self.bin_raster) - self.runModule("g.remove", flags="f", type="raster", name=self.ref_raster) + self.runModule( + "g.remove", + flags="f", + type="raster", + name=(self.bin_raster, self.ref_raster), + ) @unittest.skipIf(shutil.which("r.in.pdal") is None, "Cannot find r.in.pdal") def test_method_n(self): diff --git a/raster/r.in.pdal/testsuite/test_r_in_pdal_selection.py b/raster/r.in.pdal/testsuite/test_r_in_pdal_selection.py index b7d5acd6b28..4796702d2f6 100644 --- a/raster/r.in.pdal/testsuite/test_r_in_pdal_selection.py +++ b/raster/r.in.pdal/testsuite/test_r_in_pdal_selection.py @@ -67,8 +67,12 @@ def tearDown(self): This is executed after each test run. """ - self.runModule("g.remove", flags="f", type="raster", name=self.imp_raster) - self.runModule("g.remove", flags="f", type="raster", name=self.ref_raster) + self.runModule( + "g.remove", + flags="f", + type="raster", + name=(self.imp_raster, self.ref_raster), + ) try: self.runModule("g.remove", flags="f", type="raster", name=self.base_raster) except AttributeError: diff --git a/raster/r.kappa/testsuite/test_r_kappa.py b/raster/r.kappa/testsuite/test_r_kappa.py index 620a4f4979b..ff11f477925 100644 --- a/raster/r.kappa/testsuite/test_r_kappa.py +++ b/raster/r.kappa/testsuite/test_r_kappa.py @@ -51,8 +51,9 @@ def setUpClass(cls): def tearDownClass(cls): """Remove temporary data""" cls.del_temp_region() - cls.runModule("g.remove", flags="f", type="raster", name=cls.ref_1) - cls.runModule("g.remove", flags="f", type="raster", name=cls.class_1) + cls.runModule( + "g.remove", flags="f", type="raster", name=(cls.ref_1, cls.class_1) + ) def test_m(self): """Test printing matrix only @@ -119,8 +120,9 @@ def setUpClass(cls): def tearDownClass(cls): """Remove temporary data""" cls.del_temp_region() - cls.runModule("g.remove", flags="f", type="raster", name=cls.ref_1) - cls.runModule("g.remove", flags="f", type="raster", name=cls.class_1) + cls.runModule( + "g.remove", flags="f", type="raster", name=(cls.ref_1, cls.class_1) + ) def match(self, pat, ref): if pat == "NA" or ref == "NA": @@ -233,8 +235,9 @@ def setUpClass(cls): def tearDownClass(cls): """Remove temporary data""" cls.del_temp_region() - cls.runModule("g.remove", flags="f", type="raster", name=cls.ref_1) - cls.runModule("g.remove", flags="f", type="raster", name=cls.class_1) + cls.runModule( + "g.remove", flags="f", type="raster", name=(cls.ref_1, cls.class_1) + ) def match(self, pat, ref): if pat == "NA" or ref == "NA": diff --git a/raster/r.mfilter/benchmark/benchmark_r_mfilter_nprocs.py b/raster/r.mfilter/benchmark/benchmark_r_mfilter_nprocs.py index 2dc85b411d8..9a0591f7cfc 100644 --- a/raster/r.mfilter/benchmark/benchmark_r_mfilter_nprocs.py +++ b/raster/r.mfilter/benchmark/benchmark_r_mfilter_nprocs.py @@ -55,8 +55,7 @@ def benchmark(size, label, results): overwrite=True, ) results.append(bm.benchmark_nprocs(module, label=label, max_nprocs=16, repeat=3)) - Module("g.remove", quiet=True, flags="f", type="raster", name=reference) - Module("g.remove", quiet=True, flags="f", type="raster", name=output) + Module("g.remove", quiet=True, flags="f", type="raster", name=(reference, output)) def generate_map(rows, cols, fname): diff --git a/raster/r.neighbors/benchmark/benchmark_r_neighbors_nprocs.py b/raster/r.neighbors/benchmark/benchmark_r_neighbors_nprocs.py index d355792a734..e7b3196c246 100644 --- a/raster/r.neighbors/benchmark/benchmark_r_neighbors_nprocs.py +++ b/raster/r.neighbors/benchmark/benchmark_r_neighbors_nprocs.py @@ -38,8 +38,7 @@ def benchmark(size, label, results): overwrite=True, ) results.append(bm.benchmark_nprocs(module, label=label, max_nprocs=16, repeat=3)) - Module("g.remove", quiet=True, flags="f", type="raster", name=reference) - Module("g.remove", quiet=True, flags="f", type="raster", name=output) + Module("g.remove", quiet=True, flags="f", type="raster", name=(reference, output)) def generate_map(rows, cols, fname): diff --git a/raster/r.random/testsuite/test_r_random.py b/raster/r.random/testsuite/test_r_random.py index ce12c719c8e..16aae357ebf 100644 --- a/raster/r.random/testsuite/test_r_random.py +++ b/raster/r.random/testsuite/test_r_random.py @@ -28,30 +28,30 @@ def setUpClass(cls): def tearDownClass(cls): cls.del_temp_region() - cls.runModule("g.remove", type="raster", flags="f", name=cls.raster) - cls.runModule("g.remove", type="raster", flags="f", name=cls.raster + "_null") - cls.runModule( - "g.remove", type="raster", flags="f", name=cls.raster + "_without_topology" - ) - cls.runModule("g.remove", type="raster", flags="f", name=cls.raster + "_3D") cls.runModule( "g.remove", type="raster", flags="f", - name=cls.raster + "_cover_landcover_1m", + name=( + cls.raster, + cls.raster + "_null", + cls.raster + "_without_topology", + cls.raster + "_3D", + cls.raster + "_cover_landcover_1m", + ), ) - cls.runModule("g.remove", type="vector", flags="f", name=cls.vector) - cls.runModule("g.remove", type="vector", flags="f", name=cls.vector + "_null") - cls.runModule( - "g.remove", type="vector", flags="f", name=cls.vector + "_without_topology" - ) - cls.runModule("g.remove", type="vector", flags="f", name=cls.vector + "_3D") cls.runModule( "g.remove", type="vector", flags="f", - name=cls.vector + "_cover_landcover_1m", + name=( + cls.vector, + cls.vector + "_null", + cls.vector + "_without_topology", + cls.vector + "_3D", + cls.vector + "_cover_landcover_1m", + ), ) def test_random_raster(self): diff --git a/raster/r.resamp.filter/benchmark/benchmark_r_resamp_filter.py b/raster/r.resamp.filter/benchmark/benchmark_r_resamp_filter.py index 8c7799e74fc..9ec46132c81 100644 --- a/raster/r.resamp.filter/benchmark/benchmark_r_resamp_filter.py +++ b/raster/r.resamp.filter/benchmark/benchmark_r_resamp_filter.py @@ -40,8 +40,7 @@ def benchmark(size, label, results): overwrite=True, ) results.append(bm.benchmark_nprocs(module, label=label, max_nprocs=8, repeat=3)) - Module("g.remove", quiet=True, flags="f", type="raster", name=reference) - Module("g.remove", quiet=True, flags="f", type="raster", name=output) + Module("g.remove", quiet=True, flags="f", type="raster", name=(reference, output)) def generate_map(rows, cols, fname): diff --git a/raster/r.resamp.interp/benchmark/benchmark_r_resamp_interp.py b/raster/r.resamp.interp/benchmark/benchmark_r_resamp_interp.py index 20196bc44bc..616dc045aa3 100644 --- a/raster/r.resamp.interp/benchmark/benchmark_r_resamp_interp.py +++ b/raster/r.resamp.interp/benchmark/benchmark_r_resamp_interp.py @@ -38,8 +38,7 @@ def benchmark(size, label, results): overwrite=True, ) results.append(bm.benchmark_nprocs(module, label=label, max_nprocs=16, repeat=3)) - Module("g.remove", quiet=True, flags="f", type="raster", name=reference) - Module("g.remove", quiet=True, flags="f", type="raster", name=output) + Module("g.remove", quiet=True, flags="f", type="raster", name=(reference, output)) def generate_map(rows, cols, fname): diff --git a/raster/r.series/benchmark/benchmark_r_series.py b/raster/r.series/benchmark/benchmark_r_series.py index ecf4432f2dd..72c9c3bd23c 100644 --- a/raster/r.series/benchmark/benchmark_r_series.py +++ b/raster/r.series/benchmark/benchmark_r_series.py @@ -37,8 +37,7 @@ def benchmark(size, label, results): overwrite=True, ) results.append(bm.benchmark_nprocs(module, label=label, max_nprocs=16, repeat=3)) - Module("g.remove", quiet=True, flags="f", type="raster", name=reference) - Module("g.remove", quiet=True, flags="f", type="raster", name=output) + Module("g.remove", quiet=True, flags="f", type="raster", name=(reference, output)) def generate_map(rows, cols, fname): diff --git a/raster/r.slope.aspect/benchmark/benchmark_r_slope_aspect.py b/raster/r.slope.aspect/benchmark/benchmark_r_slope_aspect.py index 220b813e323..522a938f26c 100644 --- a/raster/r.slope.aspect/benchmark/benchmark_r_slope_aspect.py +++ b/raster/r.slope.aspect/benchmark/benchmark_r_slope_aspect.py @@ -42,11 +42,13 @@ def benchmark(size, label, results): overwrite=True, ) results.append(bm.benchmark_nprocs(module, label=label, max_nprocs=16, repeat=3)) - Module("g.remove", quiet=True, flags="f", type="raster", name=reference) - Module("g.remove", quiet=True, flags="f", type="raster", name=slope) - Module("g.remove", quiet=True, flags="f", type="raster", name=aspect) - Module("g.remove", quiet=True, flags="f", type="raster", name=pcurv) - Module("g.remove", quiet=True, flags="f", type="raster", name=tcurv) + Module( + "g.remove", + quiet=True, + flags="f", + type="raster", + name=(reference, slope, aspect, pcurv, tcurv), + ) def generate_map(rows, cols, fname): diff --git a/raster/r.slope.aspect/benchmark/benchmark_r_slope_aspect_memory.py b/raster/r.slope.aspect/benchmark/benchmark_r_slope_aspect_memory.py index c8f5ac09f00..31824233bbc 100644 --- a/raster/r.slope.aspect/benchmark/benchmark_r_slope_aspect_memory.py +++ b/raster/r.slope.aspect/benchmark/benchmark_r_slope_aspect_memory.py @@ -46,10 +46,13 @@ def benchmark(memory, label, results, reference): ) results.append(bm.benchmark_nprocs(module, label=label, max_nprocs=20, repeat=10)) - Module("g.remove", quiet=True, flags="f", type="raster", name=slope) - Module("g.remove", quiet=True, flags="f", type="raster", name=aspect) - Module("g.remove", quiet=True, flags="f", type="raster", name=pcurv) - Module("g.remove", quiet=True, flags="f", type="raster", name=tcurv) + Module( + "g.remove", + quiet=True, + flags="f", + type="raster", + name=(slope, aspect, pcurv, tcurv), + ) def generate_map(rows, cols, fname): diff --git a/raster/r.tile/testsuite/test_r_tile.py b/raster/r.tile/testsuite/test_r_tile.py index f1dd3afcd3b..c2e62b60dd2 100644 --- a/raster/r.tile/testsuite/test_r_tile.py +++ b/raster/r.tile/testsuite/test_r_tile.py @@ -28,42 +28,20 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): cls.del_temp_region() - cls.runModule( - "g.remove", type="raster", flags="f", name=cls.output_prefix + "-000-000" - ) - cls.runModule( - "g.remove", type="raster", flags="f", name=cls.output_prefix + "-000-001" - ) - cls.runModule( - "g.remove", type="raster", flags="f", name=cls.output_prefix + "-001-000" - ) - cls.runModule( - "g.remove", type="raster", flags="f", name=cls.output_prefix + "-001-001" - ) - - cls.runModule( - "g.remove", - type="raster", - flags="f", - name=cls.output_prefix + "overlap" + "-000-000", - ) - cls.runModule( - "g.remove", - type="raster", - flags="f", - name=cls.output_prefix + "overlap" + "-000-001", - ) - cls.runModule( - "g.remove", - type="raster", - flags="f", - name=cls.output_prefix + "overlap" + "-001-000", - ) cls.runModule( "g.remove", type="raster", flags="f", - name=cls.output_prefix + "overlap" + "-001-001", + name=( + cls.output_prefix + "-000-000", + cls.output_prefix + "-000-001", + cls.output_prefix + "-001-000", + cls.output_prefix + "-001-001", + cls.output_prefix + "overlap" + "-000-000", + cls.output_prefix + "overlap" + "-000-001", + cls.output_prefix + "overlap" + "-001-000", + cls.output_prefix + "overlap" + "-001-001", + ), ) def test_raster_tile(self): diff --git a/raster/r.univar/benchmark/benchmark_r_univar.py b/raster/r.univar/benchmark/benchmark_r_univar.py index 507e6b4b23e..58d607645c7 100644 --- a/raster/r.univar/benchmark/benchmark_r_univar.py +++ b/raster/r.univar/benchmark/benchmark_r_univar.py @@ -35,8 +35,7 @@ def benchmark(size, label, results): overwrite=True, ) results.append(bm.benchmark_nprocs(module, label=label, max_nprocs=16, repeat=3)) - Module("g.remove", quiet=True, flags="f", type="raster", name=reference) - Module("g.remove", quiet=True, flags="f", type="raster", name=output) + Module("g.remove", quiet=True, flags="f", type="raster", name=(reference, output)) def generate_map(rows, cols, fname): diff --git a/raster/r.univar/testsuite/test_r_univar.py b/raster/r.univar/testsuite/test_r_univar.py index de28f0753d5..c2ae6669df6 100644 --- a/raster/r.univar/testsuite/test_r_univar.py +++ b/raster/r.univar/testsuite/test_r_univar.py @@ -23,11 +23,12 @@ def tearDownClass(cls): cls.del_temp_region() def tearDown(self): - self.runModule("g.remove", flags="f", type="raster", name="map_a") - self.runModule("g.remove", flags="f", type="raster", name="map_b") - self.runModule("g.remove", flags="f", type="raster", name="map_negative") - self.runModule("g.remove", flags="f", type="raster", name="zone_map") - self.runModule("g.remove", flags="f", type="raster", name="zone_map_with_gap") + self.runModule( + "g.remove", + flags="f", + type="raster", + name="map_a,map_b,map_negative,zone_map,zone_map_with_gap", + ) def setUp(self): """Create input data""" diff --git a/raster3d/r3.null/testsuite/test.r3.null.sh b/raster3d/r3.null/testsuite/test.r3.null.sh index 1cf93110b24..d6a6ec35810 100755 --- a/raster3d/r3.null/testsuite/test.r3.null.sh +++ b/raster3d/r3.null/testsuite/test.r3.null.sh @@ -56,14 +56,7 @@ diff data/test_volume_double_null_1.ref test_volume_double_null_1.txt diff data/test_volume_double_null_2.ref test_volume_double_null_2.txt # Cleanup -g.remove -f type=raster_3d name=test_volume_float_1 -g.remove -f type=raster_3d name=test_volume_float_2 -g.remove -f type=raster_3d name=test_volume_float_null_1 -g.remove -f type=raster_3d name=test_volume_float_null_2 -g.remove -f type=raster_3d name=test_volume_double_1 -g.remove -f type=raster_3d name=test_volume_double_2 -g.remove -f type=raster_3d name=test_volume_double_null_1 -g.remove -f type=raster_3d name=test_volume_double_null_2 +g.remove -f type=raster_3d name=test_volume_float_1,test_volume_float_2,test_volume_float_null_1,test_volume_float_null_2,test_volume_double_1,test_volume_double_2,test_volume_double_null_1,test_volume_double_null_2 rm test_volume_float_1.txt rm test_volume_float_2.txt rm test_volume_float_null_1.txt diff --git a/scripts/r.mapcalc.simple/testsuite/test_rmapcalcsimple.py b/scripts/r.mapcalc.simple/testsuite/test_rmapcalcsimple.py index d400ccc7980..f133da22f7d 100644 --- a/scripts/r.mapcalc.simple/testsuite/test_rmapcalcsimple.py +++ b/scripts/r.mapcalc.simple/testsuite/test_rmapcalcsimple.py @@ -24,8 +24,9 @@ def setUpClass(cls): def tearDownClass(cls): map_output1 = "test1" map_output2 = "test2" - cls.runModule("g.remove", flags="f", type="raster", name=map_output1) - cls.runModule("g.remove", flags="f", type="raster", name=map_output2) + cls.runModule( + "g.remove", flags="f", type="raster", name=(map_output1, map_output2) + ) cls.del_temp_region() def test_rmapcalcsimple(self): diff --git a/scripts/r.reclass.area/testsuite/test_r_reclass_area.py b/scripts/r.reclass.area/testsuite/test_r_reclass_area.py index c8009ce5a1d..96c922bda05 100644 --- a/scripts/r.reclass.area/testsuite/test_r_reclass_area.py +++ b/scripts/r.reclass.area/testsuite/test_r_reclass_area.py @@ -26,8 +26,12 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): cls.del_temp_region() - cls.runModule("g.remove", type="raster", flags="f", name=cls.output + "Greater") - cls.runModule("g.remove", type="raster", flags="f", name=cls.output + "Lesser") + cls.runModule( + "g.remove", + type="raster", + flags="f", + name=(cls.output + "Greater", cls.output + "Lesser"), + ) def test_reclassaeaGreater(self): """Testing r.reclass.area with greater""" diff --git a/scripts/v.rast.stats/testsuite/test_v_rast_stats.py b/scripts/v.rast.stats/testsuite/test_v_rast_stats.py index 56acbce5964..01ae6d4a7d2 100644 --- a/scripts/v.rast.stats/testsuite/test_v_rast_stats.py +++ b/scripts/v.rast.stats/testsuite/test_v_rast_stats.py @@ -24,11 +24,12 @@ def tearDownClass(cls): cls.del_temp_region() def tearDown(self): - self.runModule("g.remove", flags="f", type="raster", name="map_a") - self.runModule("g.remove", flags="f", type="raster", name="map_b") - self.runModule("g.remove", flags="f", type="raster", name="zone_map") - self.runModule("g.remove", flags="f", type="raster", name="row_map") - self.runModule("g.remove", flags="f", type="raster", name="test_line") + self.runModule( + "g.remove", + flags="f", + type="raster", + name="map_a,map_b,zone_map,row_map,test_line", + ) def setUp(self): """Create input data""" diff --git a/temporal/t.rast.accdetect/testsuite/test_simple.py b/temporal/t.rast.accdetect/testsuite/test_simple.py index 522c13f93e4..d67537487d5 100644 --- a/temporal/t.rast.accdetect/testsuite/test_simple.py +++ b/temporal/t.rast.accdetect/testsuite/test_simple.py @@ -62,8 +62,7 @@ def tearDownClass(cls): def tearDown(self): """Remove generated data""" - self.runModule("t.remove", flags="df", type="strds", inputs="B") - self.runModule("t.remove", flags="df", type="strds", inputs="C") + self.runModule("t.remove", flags="df", type="strds", inputs="B,C") def test_simple(self): self.assertModule( diff --git a/temporal/t.rast.accumulate/testsuite/test_accumulation.py b/temporal/t.rast.accumulate/testsuite/test_accumulation.py index f5bf6dcf5d7..566c1971f99 100644 --- a/temporal/t.rast.accumulate/testsuite/test_accumulation.py +++ b/temporal/t.rast.accumulate/testsuite/test_accumulation.py @@ -95,9 +95,7 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): """Remove the temporary region""" - cls.runModule("t.remove", flags="df", type="strds", inputs="A") - cls.runModule("t.remove", flags="df", type="strds", inputs="Lower") - cls.runModule("t.remove", flags="df", type="strds", inputs="Upper") + cls.runModule("t.remove", flags="df", type="strds", inputs="A,Lower,Upper") cls.del_temp_region() def tearDown(self): diff --git a/temporal/t.rast.series/testsuite/test_series.py b/temporal/t.rast.series/testsuite/test_series.py index 99fe69d4352..e936e10e0e7 100644 --- a/temporal/t.rast.series/testsuite/test_series.py +++ b/temporal/t.rast.series/testsuite/test_series.py @@ -61,11 +61,15 @@ def tearDownClass(cls): type="raster", maps="series_average,series_maximum,series_minimum,series_minimum_2", ) - cls.runModule("g.remove", flags="f", type="raster", name="series_average") - cls.runModule("g.remove", flags="f", type="raster", name="series_maximum") - cls.runModule("g.remove", flags="f", type="raster", name="series_minimum") - cls.runModule("g.remove", flags="f", type="raster", name="series_minimum_2") - cls.runModule("g.remove", flags="f", type="raster", name="series_quantile") + cls.runModule( + "g.remove", + flags="f", + type="raster", + name=( + "series_average,series_maximum" + + ",series_minimum,series_minimum_2,series_quantile" + ), + ) def test_time_stamp(self): self.assertModule( @@ -206,10 +210,12 @@ def tearDownClass(cls): type="raster", maps="series_average,series_maximum,series_minimum,series_minimum_2", ) - cls.runModule("g.remove", flags="f", type="raster", name="series_average") - cls.runModule("g.remove", flags="f", type="raster", name="series_maximum") - cls.runModule("g.remove", flags="f", type="raster", name="series_minimum") - cls.runModule("g.remove", flags="f", type="raster", name="series_minimum_2") + cls.runModule( + "g.remove", + flags="f", + type="raster", + name="series_average,series_maximum,series_minimum,series_minimum_2", + ) def test_average(self): self.assertModule( diff --git a/temporal/t.rast.univar/testsuite/test_t_rast_univar.py b/temporal/t.rast.univar/testsuite/test_t_rast_univar.py index dca870d6a98..17831b9b5b9 100644 --- a/temporal/t.rast.univar/testsuite/test_t_rast_univar.py +++ b/temporal/t.rast.univar/testsuite/test_t_rast_univar.py @@ -147,8 +147,7 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): """Remove the temporary region""" - cls.runModule("t.remove", flags="df", type="strds", inputs="A") - cls.runModule("t.remove", flags="df", type="strds", inputs="B") + cls.runModule("t.remove", flags="df", type="strds", inputs="A,B") cls.runModule("g.remove", flags="f", type="raster", name="zones") cls.del_temp_region() diff --git a/temporal/t.topology/test.t.topology.reltime.sh b/temporal/t.topology/test.t.topology.reltime.sh index 847289c4b2f..60e49355e9a 100755 --- a/temporal/t.topology/test.t.topology.reltime.sh +++ b/temporal/t.topology/test.t.topology.reltime.sh @@ -96,6 +96,5 @@ cat "${n5}" t.topology input=precip_rel_y t.topology -m input=precip_rel_y -t.remove type=strds input=precip_rel_d -t.remove type=strds input=precip_rel_y +t.remove type=strds input=precip_rel_d,precip_rel_y t.unregister type=raster file="${n1}" diff --git a/temporal/t.vect.extract/test.t.vect.extract.sh b/temporal/t.vect.extract/test.t.vect.extract.sh index b5cd6882e94..8b176dcc8ed 100755 --- a/temporal/t.vect.extract/test.t.vect.extract.sh +++ b/temporal/t.vect.extract/test.t.vect.extract.sh @@ -44,5 +44,4 @@ t.vect.list input=soil_abs3 columns=name,start_time,end_time,primitives # @postprocess t.unregister type=vector maps=soil_1,soil_2,soil_3,soil_4,soil_5,soil_6,soil_7,soil_8 t.remove type=stvds input=soil_abs1,soil_abs2,soil_abs3 -g.remove -f type=vector name=soil_1,soil_2,soil_3,soil_4,soil_5,soil_6,soil_7,soil_8 -g.remove -f type=vector name=new_vect_1,new_vect_2,new_vect_3,new_vect_4,new_vect_5,new_vect_6 +g.remove -f type=vector name=soil_1,soil_2,soil_3,soil_4,soil_5,soil_6,soil_7,soil_8,new_vect_1,new_vect_2,new_vect_3,new_vect_4,new_vect_5,new_vect_6 diff --git a/utils/thumbnails.py b/utils/thumbnails.py index ee9bd5e17ab..181a16aa666 100755 --- a/utils/thumbnails.py +++ b/utils/thumbnails.py @@ -23,13 +23,14 @@ def cleanup(): + names = [] if tmp_grad_rel: - gs.run_command( - "g.remove", flags="f", type="raster", name=tmp_grad_rel, quiet=True - ) + names.append(tmp_grad_rel) if tmp_grad_abs: + names.append(tmp_grad_abs) + if len(names) > 0: gs.run_command( - "g.remove", flags="f", type="raster", name=tmp_grad_abs, quiet=True + "g.remove", flags="f", type="raster", name=",".join(names), quiet=True ) diff --git a/vector/v.random/testsuite/test_v_random.py b/vector/v.random/testsuite/test_v_random.py index e5cc95a93db..d11faf458f9 100644 --- a/vector/v.random/testsuite/test_v_random.py +++ b/vector/v.random/testsuite/test_v_random.py @@ -31,8 +31,9 @@ def tearDownClass(cls): cls.del_temp_region() def tearDown(cls): - cls.runModule("g.remove", type="vector", flags="f", name=cls.output) - cls.runModule("g.remove", type="vector", flags="f", name=cls.output2) + cls.runModule( + "g.remove", type="vector", flags="f", name=(cls.output, cls.output2) + ) def test_num_points(self): """Checking if number of points equals 100""" diff --git a/vector/v.surf.rst/benchmark/benchmark_v_surf_rst.py b/vector/v.surf.rst/benchmark/benchmark_v_surf_rst.py index 91fd784e0b3..ac69b441010 100644 --- a/vector/v.surf.rst/benchmark/benchmark_v_surf_rst.py +++ b/vector/v.surf.rst/benchmark/benchmark_v_surf_rst.py @@ -36,8 +36,7 @@ def benchmark(size, label, results): ) results.append(bm.benchmark_nprocs(module, label=label, max_nprocs=8, repeat=3)) - Module("g.remove", quiet=True, flags="f", type="raster", name=reference) - Module("g.remove", quiet=True, flags="f", type="raster", name=output) + Module("g.remove", quiet=True, flags="f", type="raster", name=(reference, output)) def generate_map(npoints, rows, cols, fname): diff --git a/vector/v.surf.rst/benchmark/benchmark_v_surf_rst_cv.py b/vector/v.surf.rst/benchmark/benchmark_v_surf_rst_cv.py index 21a3c7459eb..f140ee67b8a 100644 --- a/vector/v.surf.rst/benchmark/benchmark_v_surf_rst_cv.py +++ b/vector/v.surf.rst/benchmark/benchmark_v_surf_rst_cv.py @@ -37,8 +37,7 @@ def benchmark(size, label, results): ) results.append(bm.benchmark_nprocs(module, label=label, max_nprocs=8, repeat=3)) - Module("g.remove", quiet=True, flags="f", type="raster", name=reference) - Module("g.remove", quiet=True, flags="f", type="raster", name=output) + Module("g.remove", quiet=True, flags="f", type="raster", name=(reference, output)) def generate_map(npoints, rows, cols, fname): From 62b001b1318fb331334d6a9bab3ec0f6fba60360 Mon Sep 17 00:00:00 2001 From: ww2406 <57472892+ww2406@users.noreply.github.com> Date: Fri, 18 Oct 2024 07:41:20 -0700 Subject: [PATCH 33/35] gui: Add fix for wxGUI Data import Python error (#4504) This fixes #648 by adding a command tracker queue. When the queue is not empty, closing the dialog is prevented to ensure the completion callback can still access UI elements. --- gui/wxpython/modules/import_export.py | 47 +++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/gui/wxpython/modules/import_export.py b/gui/wxpython/modules/import_export.py index a0bd17e289c..c3106d0467b 100644 --- a/gui/wxpython/modules/import_export.py +++ b/gui/wxpython/modules/import_export.py @@ -18,9 +18,11 @@ @author Martin Landa @author Anna Kratochvilova (GroupDialog, SymbolDialog) +@author William Welch (commands running queue) """ import os +from collections import deque from pathlib import Path @@ -60,6 +62,8 @@ def __init__( self.commandId = -1 # id of running command + self._commands_running = deque() + wx.Dialog.__init__( self, parent, id, title, style=style, name="MultiImportDialog" ) @@ -122,8 +126,9 @@ def __init__( # buttons # # cancel + self._DEFAULT_CLOSE_BTN_TEXT = _("Close dialog") self.btn_close = CloseButton(parent=self.panel) - self.btn_close.SetToolTip(_("Close dialog")) + self.btn_close.SetToolTip(_(self._DEFAULT_CLOSE_BTN_TEXT)) self.btn_close.Bind(wx.EVT_BUTTON, self.OnClose) # run self.btn_run = Button(parent=self.panel, id=wx.ID_OK, label=_("&Import")) @@ -131,7 +136,7 @@ def __init__( self.btn_run.SetDefault() self.btn_run.Bind(wx.EVT_BUTTON, self.OnRun) - self.Bind(wx.EVT_CLOSE, lambda evt: self.Destroy()) + self.Bind(wx.EVT_CLOSE, self._handleCloseEvent) self.notebook = GNotebook(parent=self, style=globalvar.FNPageDStyle) @@ -270,6 +275,33 @@ def _validateOutputMapName(self): return False return True + def _handleCloseEvent(self, event: wx.CloseEvent): + if event.CanVeto() and len(self._commands_running) > 0: + # prevent dialog close while async commands are running + event.Veto() + return + self.Destroy() + + def _addToCommandQueue(self): + self._commands_running.append(True) + + # disable the dialog close button + self.btn_close.SetToolTip( + _("Dialog cannot be closed while command is running.") + ) + self.btn_close.Disable() + + def _removeFromCommandQueue(self): + try: + self._commands_running.pop() + except IndexError: + pass + finally: + if len(self._commands_running) == 0: + # enable the dialog close button + self.btn_close.Enable() + self.btn_close.SetToolTip(self._DEFAULT_CLOSE_BTN_TEXT) + def OnClose(self, event=None): """Close dialog""" self.Close() @@ -518,6 +550,7 @@ def OnRun(self, event): ): cmd.append("--overwrite") + self._addToCommandQueue() # run in Layer Manager self._giface.RunCmd( cmd, onDone=self.OnCmdDone, userData=userData, addLayer=False @@ -526,9 +559,11 @@ def OnRun(self, event): def OnCmdDone(self, event): """Load layers and close if required""" if not hasattr(self, "AddLayers"): + self._removeFromCommandQueue() return self.AddLayers(event.returncode, event.cmd, event.userData) + self._removeFromCommandQueue() if event.returncode == 0 and self.closeOnFinish.IsChecked(): self.Close() @@ -663,6 +698,7 @@ def OnRun(self, event): ): cmd.append("--overwrite") + self._addToCommandQueue() # run in Layer Manager self._giface.RunCmd( cmd, onDone=self.OnCmdDone, userData=userData, addLayer=False @@ -671,10 +707,13 @@ def OnRun(self, event): def OnCmdDone(self, event): """Load layers and close if required""" if not hasattr(self, "AddLayers"): + self._removeFromCommandQueue() return self.AddLayers(event.returncode, event.cmd, event.userData) + self._removeFromCommandQueue() + if self.popOGR: os.environ.pop("GRASS_VECTOR_OGR") @@ -873,16 +912,20 @@ def OnRun(self, event): ): cmd.append("--overwrite") + self._commands_running.append(True) # run in Layer Manager self._giface.RunCmd(cmd, onDone=self.OnCmdDone, addLayer=False) def OnCmdDone(self, event): """Load layers and close if required""" if not hasattr(self, "AddLayers"): + self._removeFromCommandQueue() return self.AddLayers(event.returncode, event.cmd) + self._removeFromCommandQueue() + if self.closeOnFinish.IsChecked(): self.Close() From 5cff700eb5bcaa9adcba7cb67c790d16407acaf1 Mon Sep 17 00:00:00 2001 From: Arohan Ajit Date: Fri, 18 Oct 2024 16:35:35 -0400 Subject: [PATCH 34/35] docs: Fixed E721 in gunittest/ (#4549) --- .flake8 | 3 --- python/grass/gunittest/invoker.py | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.flake8 b/.flake8 index 306a11fe02b..a5588997635 100644 --- a/.flake8 +++ b/.flake8 @@ -66,7 +66,6 @@ per-file-ignores = # TODO: Is this really needed? python/grass/pygrass/vector/__init__.py: E402 python/grass/pygrass/raster/__init__.py: E402 - python/grass/gunittest/invoker.py: E721 python/grass/pygrass/vector/__init__.py: E402 python/grass/pygrass/modules/interface/*.py: F401 python/grass/pygrass/modules/grid/*.py: F401 @@ -82,13 +81,11 @@ per-file-ignores = python/grass/temporal/temporal_granularity.py: E722 python/grass/temporal/temporal_raster_base_algebra.py: E722 python/grass/temporal/temporal_topology_dataset_connector.py: E722 - python/grass/temporal/univar_statistics.py: E231 # Current benchmarks/tests are changing sys.path before import. # Possibly, a different approach should be taken there anyway. python/grass/pygrass/tests/benchmark.py: E402, F401, F821 # Configuration file for Sphinx: # Ignoring import/code mix and line length. - python/grass/docs/conf.py: E402 # Files not managed by Black python/grass/imaging/images2gif.py: E226 # Unused imports in init files diff --git a/python/grass/gunittest/invoker.py b/python/grass/gunittest/invoker.py index f07e8dd5a84..2fe9c898b8b 100644 --- a/python/grass/gunittest/invoker.py +++ b/python/grass/gunittest/invoker.py @@ -244,7 +244,7 @@ def try_decode(data, encodings): Path(stdout_path).write_text(stdout) with open(stderr_path, "w") as stderr_file: - if type(stderr) == "bytes": + if isinstance(stderr, bytes): stderr_file.write(decode(stderr)) elif isinstance(stderr, str): stderr_file.write(stderr) From 2a0ad5f1057ad66f716f044bc13bc4d6a7be5d95 Mon Sep 17 00:00:00 2001 From: Arohan Ajit Date: Fri, 18 Oct 2024 16:52:08 -0400 Subject: [PATCH 35/35] wxGUI: Fixed E266 in nviz/ (#4547) --- .flake8 | 2 +- gui/wxpython/nviz/tools.py | 46 -------------------------------------- 2 files changed, 1 insertion(+), 47 deletions(-) diff --git a/.flake8 b/.flake8 index a5588997635..5d2d792b0c3 100644 --- a/.flake8 +++ b/.flake8 @@ -25,7 +25,7 @@ per-file-ignores = gui/scripts/d.wms.py: E501 gui/wxpython/image2target/g.gui.image2target.py: E501 gui/wxpython/modules/*: F841, E722 - gui/wxpython/nviz/*: E266, E722, F403, F405 + gui/wxpython/nviz/*: E722, F403, F405 gui/wxpython/photo2image/*: F841, E722, E265 gui/wxpython/photo2image/g.gui.photo2image.py: E501, F841 gui/wxpython/psmap/*: F841, E266, E722 diff --git a/gui/wxpython/nviz/tools.py b/gui/wxpython/nviz/tools.py index 153f8ffef86..7ced7d157e1 100644 --- a/gui/wxpython/nviz/tools.py +++ b/gui/wxpython/nviz/tools.py @@ -1196,33 +1196,6 @@ def _createSurfacePage(self, parent): flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border=3, ) - # - # mask - # - # box = wx.StaticBox (parent = panel, id = wx.ID_ANY, - # label = " %s " % (_("Mask"))) - ## boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL) - ## gridSizer = wx.GridBagSizer(vgap = 5, hgap = 5) - ## - # gridSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY, - # label = _("Mask zeros:")), - # pos = (0, 0), flag = wx.ALIGN_CENTER_VERTICAL) - ## - # elev = wx.CheckBox(parent = panel, id = wx.ID_ANY, - # label = _("by elevation")) - # elev.Enable(False) # TODO: not implemented yet - ## gridSizer.Add(item = elev, pos = (0, 1)) - ## - # color = wx.CheckBox(parent = panel, id = wx.ID_ANY, - # label = _("by color")) - # color.Enable(False) # TODO: not implemented yet - ## gridSizer.Add(item = color, pos = (0, 2)) - ## - # boxSizer.Add(item = gridSizer, proportion = 1, - # flag = wx.ALL | wx.EXPAND, border = 3) - # pageSizer.Add(item = boxSizer, proportion = 0, - ## flag = wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, - # border = 3) panel.SetSizer(pageSizer) @@ -1852,24 +1825,6 @@ def _createVectorPage(self, parent): icolor.Bind(csel.EVT_COLOURSELECT, self.OnVectorPoints) gridSizer.Add(icolor, flag=wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT, pos=(0, 4)) - # icon width - seems to do nothing - # gridSizer.Add(item = wx.StaticText(parent = panel, id = wx.ID_ANY, - # label = _("width")), - # pos = (1, 1), flag = wx.ALIGN_CENTER_VERTICAL | - # wx.ALIGN_RIGHT) - ## - # iwidth = wx.SpinCtrl(parent = panel, id = wx.ID_ANY, size = (65, -1), - ## initial = 1, - ## min = 1, - # max = 1e6) - # iwidth.SetName('value') - # iwidth.SetValue(100) - ## self.win['vector']['points']['width'] = iwidth.GetId() - ## iwidth.Bind(wx.EVT_SPINCTRL, self.OnVectorPoints) - ## iwidth.Bind(wx.EVT_TEXT, self.OnVectorPoints) - # gridSizer.Add(item = iwidth, pos = (1, 2), - # flag = wx.ALIGN_CENTER_VERTICAL | wx.ALIGN_LEFT) - # icon symbol gridSizer.Add( StaticText(parent=panel, id=wx.ID_ANY, label=_("symbol:")), pos=(0, 5), @@ -3084,7 +3039,6 @@ def _createIsosurfacePanel(self, parent): ) value.Bind(wx.EVT_TEXT_ENTER, self.OnVolumeIsosurfMap) value.Bind(wx.EVT_KILL_FOCUS, self.OnVolumeIsosurfMap) - ## value.Bind(wx.EVT_TEXT, self.OnVolumeIsosurfMap) else: size = (65, -1) value = SpinCtrl(parent=panel, id=wx.ID_ANY, size=size, initial=0)