From 6e5643d2b91372acc1a0106400670b61b41f1eb9 Mon Sep 17 00:00:00 2001 From: Arohan Ajit Date: Tue, 29 Oct 2024 14:03:17 -0400 Subject: [PATCH 01/57] v.import: Fixed E722 bare except (#4614) --- .flake8 | 2 +- scripts/v.import/v.import.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.flake8 b/.flake8 index 075fb37d075..21272791e52 100644 --- a/.flake8 +++ b/.flake8 @@ -97,7 +97,7 @@ per-file-ignores = scripts/db.out.ogr/db.out.ogr.py: F841 scripts/g.extension/g.extension.py: F841, E722, E501 scripts/v.unpack/v.unpack.py: E722, E501 - scripts/v.import/v.import.py: E722, E501 + scripts/v.import/v.import.py: E501 scripts/db.univar/db.univar.py: E501 scripts/i.pansharpen/i.pansharpen.py: E501 scripts/v.what.strds/v.what.strds.py: E501 diff --git a/scripts/v.import/v.import.py b/scripts/v.import/v.import.py index 4f579c4bf45..1e467cd190b 100755 --- a/scripts/v.import/v.import.py +++ b/scripts/v.import/v.import.py @@ -263,7 +263,7 @@ def main(): if OGRdatasource.lower().endswith("gml"): try: from osgeo import gdal - except: + except ImportError: gs.fatal( _( "Unable to load GDAL Python bindings (requires package " @@ -338,7 +338,7 @@ def main(): if OGRdatasource.lower().endswith("gml"): try: from osgeo import gdal - except: + except ImportError: gs.fatal( _( "Unable to load GDAL Python bindings (requires package " From 86497131a7d1999936d380d1f57870e87690b9db Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2024 21:02:19 +0000 Subject: [PATCH 02/57] CI(deps): Lock file maintenance (#4564) --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index eacc92d3c4f..c507c1ec951 100644 --- a/flake.lock +++ b/flake.lock @@ -19,11 +19,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1728538411, - "narHash": "sha256-f0SBJz1eZ2yOuKUr5CA9BHULGXVSn6miBuUWdTyhUhU=", + "lastModified": 1730045389, + "narHash": "sha256-4spSNTZ6h8Xmvrr9oqfuxc9jarasGj1QOcsgw8BfNd8=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "b69de56fac8c2b6f8fd27f2eca01dcda8e0a4221", + "rev": "0fcb98acb6633445764dafe180e6833eb0f95208", "type": "github" }, "original": { From 9be02eeba6bfd198acb46aacf522f676fcd90fa2 Mon Sep 17 00:00:00 2001 From: Arohan Ajit Date: Wed, 30 Oct 2024 16:55:17 -0400 Subject: [PATCH 03/57] v.unpack: Fixed bare 'except' (#4616) * updated E722 * updated .flake8 * Update v.unpack.py --- .flake8 | 4 ++-- scripts/v.unpack/v.unpack.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.flake8 b/.flake8 index 21272791e52..4bc6b924620 100644 --- a/.flake8 +++ b/.flake8 @@ -95,8 +95,8 @@ per-file-ignores = scripts/r.semantic.label/r.semantic.label.py: E501 scripts/v.report/v.report.py: E721 scripts/db.out.ogr/db.out.ogr.py: F841 - scripts/g.extension/g.extension.py: F841, E722, E501 - scripts/v.unpack/v.unpack.py: E722, E501 + scripts/g.extension/g.extension.py: E501 + scripts/v.unpack/v.unpack.py: E501 scripts/v.import/v.import.py: E501 scripts/db.univar/db.univar.py: E501 scripts/i.pansharpen/i.pansharpen.py: E501 diff --git a/scripts/v.unpack/v.unpack.py b/scripts/v.unpack/v.unpack.py index c3a7a55deb7..7baa1042ccd 100644 --- a/scripts/v.unpack/v.unpack.py +++ b/scripts/v.unpack/v.unpack.py @@ -77,7 +77,7 @@ def main(): tar = tarfile.TarFile.open(name=input_base, mode="r") try: data_name = tar.getnames()[0] - except: + except IndexError: grass.fatal(_("Pack file unreadable")) if flags["p"]: From 9581ca185bf001301f3907fd3f1ca6da09e9e287 Mon Sep 17 00:00:00 2001 From: Arohan Ajit Date: Wed, 30 Oct 2024 17:14:00 -0400 Subject: [PATCH 04/57] wxGUI: Fixed bare 'except' in nviz/ (#4613) * updated E722 * updates * updates --------- Co-authored-by: Anna Petrasova --- .flake8 | 1 - gui/wxpython/nviz/mapwindow.py | 2 +- gui/wxpython/nviz/tools.py | 62 ++++++++++------------------------ 3 files changed, 19 insertions(+), 46 deletions(-) diff --git a/.flake8 b/.flake8 index 4bc6b924620..f0ac4155990 100644 --- a/.flake8 +++ b/.flake8 @@ -23,7 +23,6 @@ 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/nviz/*: E722 gui/wxpython/photo2image/g.gui.photo2image.py: E501 gui/wxpython/psmap/*: E501, E722 gui/wxpython/vdigit/*: F841, E722, F405, F403 diff --git a/gui/wxpython/nviz/mapwindow.py b/gui/wxpython/nviz/mapwindow.py index d3f93f94938..b6609427895 100644 --- a/gui/wxpython/nviz/mapwindow.py +++ b/gui/wxpython/nviz/mapwindow.py @@ -1390,7 +1390,7 @@ def LoadDataLayers(self): GError(parent=self, message=e.value) # when nviz.tools is not yet ready # during opening 3D view 2nd time - except: + except Exception: pass stop = gs.clock() diff --git a/gui/wxpython/nviz/tools.py b/gui/wxpython/nviz/tools.py index dce751e6b27..77f379ef019 100644 --- a/gui/wxpython/nviz/tools.py +++ b/gui/wxpython/nviz/tools.py @@ -160,7 +160,7 @@ def SetInitialMaps(self): else: try: selection = layers[0].GetName() - except: + except (AttributeError, IndexError): continue if ltype == "raster": self.FindWindowById(self.win["surface"]["map"]).SetValue(selection) @@ -734,24 +734,11 @@ def _createDataPage(self): self.mainPanelData = SP.ScrolledPanel(parent=self) self.mainPanelData.SetupScrolling(scroll_x=False) self.mainPanelData.AlwaysShowScrollbars(hflag=False) - try: # wxpython <= 2.8.10 - self.foldpanelData = fpb.FoldPanelBar( - parent=self.mainPanelData, - id=wx.ID_ANY, - style=fpb.FPB_DEFAULT_STYLE, - extraStyle=fpb.FPB_SINGLE_FOLD, - ) - except: - try: # wxpython >= 2.8.11 - self.foldpanelData = fpb.FoldPanelBar( - parent=self.mainPanelData, - id=wx.ID_ANY, - agwStyle=fpb.FPB_SINGLE_FOLD, - ) - except: # to be sure - self.foldpanelData = fpb.FoldPanelBar( - parent=self.mainPanelData, id=wx.ID_ANY, style=fpb.FPB_SINGLE_FOLD - ) + self.foldpanelData = fpb.FoldPanelBar( + parent=self.mainPanelData, + id=wx.ID_ANY, + agwStyle=fpb.FPB_SINGLE_FOLD, + ) self.foldpanelData.Bind(fpb.EVT_CAPTIONBAR, self.OnPressCaption) @@ -814,24 +801,11 @@ def _createAppearancePage(self): self.mainPanelAppear = SP.ScrolledPanel(parent=self) self.mainPanelAppear.SetupScrolling(scroll_x=False) self.mainPanelAppear.AlwaysShowScrollbars(hflag=False) - try: # wxpython <= 2.8.10 - self.foldpanelAppear = fpb.FoldPanelBar( - parent=self.mainPanelAppear, - id=wx.ID_ANY, - style=fpb.FPB_DEFAULT_STYLE, - extraStyle=fpb.FPB_SINGLE_FOLD, - ) - except: - try: # wxpython >= 2.8.11 - self.foldpanelAppear = fpb.FoldPanelBar( - parent=self.mainPanelAppear, - id=wx.ID_ANY, - agwStyle=fpb.FPB_SINGLE_FOLD, - ) - except: # to be sure - self.foldpanelAppear = fpb.FoldPanelBar( - parent=self.mainPanelAppear, id=wx.ID_ANY, style=fpb.FPB_SINGLE_FOLD - ) + self.foldpanelAppear = fpb.FoldPanelBar( + parent=self.mainPanelAppear, + id=wx.ID_ANY, + agwStyle=fpb.FPB_SINGLE_FOLD, + ) self.foldpanelAppear.Bind(fpb.EVT_CAPTIONBAR, self.OnPressCaption) # light page @@ -3360,7 +3334,7 @@ def OnSetSurface(self, event): name = event.GetString() try: self._getLayerPropertiesByName(name, mapType="raster")["surface"] - except: + except (AttributeError, TypeError, KeyError): self.EnablePage("fringe", False) return @@ -3384,7 +3358,7 @@ def OnSetVector(self, event): name = event.GetString() try: data = self._getLayerPropertiesByName(name, mapType="vector")["vector"] - except: + except (AttributeError, TypeError, KeyError): self.EnablePage("vector", False) return layer = self._getMapLayerByName(name, mapType="vector") @@ -3396,7 +3370,7 @@ def OnSetRaster3D(self, event): name = event.GetString() try: data = self._getLayerPropertiesByName(name, mapType="raster_3d")["volume"] - except: + except (AttributeError, TypeError, KeyError): self.EnablePage("volume", False) return @@ -4925,7 +4899,7 @@ def OnCPlaneSelection(self, event): try: planeIndex = int(plane.split()[-1]) - 1 self.EnablePage("cplane", enabled=True) - except: + except (ValueError, IndexError): planeIndex = -1 self.EnablePage("cplane", enabled=False) self.mapWindow.SelectCPlane(planeIndex) @@ -4942,7 +4916,7 @@ def OnCPlaneChanging(self, event): plane = self.FindWindowById(self.win["cplane"]["planes"]).GetStringSelection() try: planeIndex = int(plane.split()[-1]) - 1 - except: # TODO disabled page + except (ValueError, IndexError): # TODO disabled page planeIndex = -1 if event.GetId() in ( @@ -4984,7 +4958,7 @@ def OnCPlaneShading(self, event): plane = self.FindWindowById(self.win["cplane"]["planes"]).GetStringSelection() try: planeIndex = int(plane.split()[-1]) - 1 - except: # TODO disabled page + except (ValueError, IndexError): # TODO disabled page planeIndex = -1 self.mapWindow.cplanes[planeIndex]["shading"] = shading @@ -4999,7 +4973,7 @@ def OnCPlaneReset(self, event): plane = self.FindWindowById(self.win["cplane"]["planes"]).GetStringSelection() try: planeIndex = int(plane.split()[-1]) - 1 - except: # TODO disabled page + except (ValueError, IndexError): # TODO disabled page planeIndex = -1 self.mapWindow.cplanes[planeIndex] = copy.deepcopy( From 528763fb33ed7c696ea7fa19505b5d9ad02fb62e Mon Sep 17 00:00:00 2001 From: ShubhamDesai <42180509+ShubhamDesai@users.noreply.github.com> Date: Wed, 30 Oct 2024 17:28:17 -0400 Subject: [PATCH 05/57] lib/ogsf: Dereference after null check in gvl2.c (#4588) Dereference after null check --- lib/ogsf/gvl2.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/ogsf/gvl2.c b/lib/ogsf/gvl2.c index 473d3e9406e..2c861c4b5ad 100644 --- a/lib/ogsf/gvl2.c +++ b/lib/ogsf/gvl2.c @@ -316,10 +316,16 @@ void GVL_get_dims(int id, int *rows, int *cols, int *depths) *rows = gvl->rows; *cols = gvl->cols; *depths = gvl->depths; - } - G_debug(3, "GVL_get_dims() id=%d, rows=%d, cols=%d, depths=%d", - gvl->gvol_id, gvl->rows, gvl->cols, gvl->depths); + G_debug(3, "GVL_get_dims() id=%d, rows=%d, cols=%d, depths=%d", + gvl->gvol_id, gvl->rows, gvl->cols, gvl->depths); + } + else { + G_debug(2, + "GVL_get_dims(): Attempted to access a null volume structure " + "for id=%d", + id); + } return; } From 00f51c9e7c22b9643de2b472bc4f6ef4296ceb90 Mon Sep 17 00:00:00 2001 From: Arohan Ajit Date: Thu, 31 Oct 2024 11:27:33 -0400 Subject: [PATCH 06/57] v.report: Updated instance checks (#4618) --- .flake8 | 1 - scripts/v.report/v.report.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.flake8 b/.flake8 index f0ac4155990..3adda73f281 100644 --- a/.flake8 +++ b/.flake8 @@ -92,7 +92,6 @@ per-file-ignores = scripts/r.in.wms/wms_drv.py: E402, E722 scripts/r.in.wms/srs.py: E722 scripts/r.semantic.label/r.semantic.label.py: E501 - scripts/v.report/v.report.py: E721 scripts/db.out.ogr/db.out.ogr.py: F841 scripts/g.extension/g.extension.py: E501 scripts/v.unpack/v.unpack.py: E501 diff --git a/scripts/v.report/v.report.py b/scripts/v.report/v.report.py index 29d9d3c914e..80e9e8a1189 100755 --- a/scripts/v.report/v.report.py +++ b/scripts/v.report/v.report.py @@ -224,7 +224,7 @@ def main(): # calculate percentages records4 = [float(r[-1]) * 100 / total for r in records3] - if type(records1[0]) == int: + if isinstance(records1[0], int): records3 = [[r1] + [r4] for r1, r4 in zip(records1, records4)] else: records3 = [r1 + [r4] for r1, r4 in zip(records1, records4)] From ba0a4951958b20b0c1fca339c4fa92714095bacc Mon Sep 17 00:00:00 2001 From: Vaclav Petras Date: Thu, 31 Oct 2024 12:49:36 -0400 Subject: [PATCH 07/57] r.mask.status: Always output name of the mask (#4531) For both active and inactive raster mask, show the name of the raster which is used (or would be used) for the mask. This will allow tools like r.mask or GUI to do lower-level operations with or around mask without a need to know about defaults or user mechanism to change the name. I'm repurposing the existing 'name' (full_name) key which is now always set (as opposed to being null when no mask is present) as the 'present' boolean key already has the information on the mask presence. I'm renaming full_name to name because that creates a simpler interface (which is whole point of outputting full name as opposed to two keys to get name and mapset). --- include/grass/defs/raster.h | 1 + lib/raster/mask_info.c | 21 ++++++++++++ raster/r.mask.status/main.c | 34 +++++++------------ raster/r.mask.status/r.mask.status.html | 20 ++++++++--- .../r.mask.status/tests/r_mask_status_test.py | 23 +++++++------ 5 files changed, 63 insertions(+), 36 deletions(-) diff --git a/include/grass/defs/raster.h b/include/grass/defs/raster.h index 7f358562c72..bbdc8bfeaa1 100644 --- a/include/grass/defs/raster.h +++ b/include/grass/defs/raster.h @@ -392,6 +392,7 @@ int Rast_option_to_interp_type(const struct Option *); /* mask_info.c */ char *Rast_mask_info(void); +char *Rast_mask_name(void); bool Rast_mask_status(char *, char *, bool *, char *, char *); int Rast__mask_info(char *, char *); bool Rast_mask_is_present(void); diff --git a/lib/raster/mask_info.c b/lib/raster/mask_info.c index 317bab75b63..25d61341ebe 100644 --- a/lib/raster/mask_info.c +++ b/lib/raster/mask_info.c @@ -49,6 +49,27 @@ char *Rast_mask_info(void) return G_store(text); } +/** + * @brief Retrieves the name of the raster mask to use. + * + * The returned raster map name is fully qualified, i.e., in the form + % "name@mapset". + * + * The mask name is "MASK@", where is the current + * mapset. + * + * The memory for the returned mask name is dynamically allocated using + * G_store(). It is the caller's responsibility to free the memory with + * G_free() when it is no longer needed. + * + * @returns A dynamically allocated string containing the mask name. + */ +char *Rast_mask_name(void) +{ + // Mask name is always "MASK@". + return G_fully_qualified_name("MASK", G_mapset()); +} + /** * @brief Get raster mask status information * diff --git a/raster/r.mask.status/main.c b/raster/r.mask.status/main.c index 16790adf35c..b0a7b9185c0 100644 --- a/raster/r.mask.status/main.c +++ b/raster/r.mask.status/main.c @@ -89,7 +89,7 @@ int report_status(struct Parameters *params) } // Mask raster - char *full_mask = G_fully_qualified_name(name, mapset); + char *full_mask = Rast_mask_name(); // Underlying raster if applicable char *full_underlying = NULL; if (is_mask_reclass) @@ -99,10 +99,7 @@ int report_status(struct Parameters *params) JSON_Value *root_value = json_value_init_object(); JSON_Object *root_object = json_object(root_value); json_object_set_boolean(root_object, "present", present); - if (present) - json_object_set_string(root_object, "full_name", full_mask); - else - json_object_set_null(root_object, "full_name"); + json_object_set_string(root_object, "name", full_mask); if (is_mask_reclass) json_object_set_string(root_object, "is_reclass_of", full_underlying); @@ -121,9 +118,7 @@ int report_status(struct Parameters *params) printf("1"); else printf("0"); - printf("\nfull_name="); - if (present) - printf("%s", full_mask); + printf("\nname=%s", full_mask); printf("\nis_reclass_of="); if (is_mask_reclass) printf("%s", full_underlying); @@ -135,19 +130,16 @@ int report_status(struct Parameters *params) printf("true"); else printf("false"); - printf("\nfull_name: "); - if (present) - printf("|-\n %s", full_mask); - else - printf("null"); - // Null values in YAML can be an empty (no) value (rather than null), - // so we could use that, but using the explicit null as a reasonable - // starting point. + printf("\nname: "); + printf("|-\n %s", full_mask); printf("\nis_reclass_of: "); // Using block scalar with |- to avoid need for escaping. // Alternatively, we could check mapset naming limits against YAML // escaping needs for different types of strings and do the necessary // escaping here. + // Null values in YAML can be an empty (no) value (rather than null), + // so we could use that, but using the explicit null as a reasonable + // starting point. if (is_mask_reclass) printf("|-\n %s", full_underlying); else @@ -155,14 +147,14 @@ int report_status(struct Parameters *params) printf("\n"); } else { - if (present) - printf(_("Mask is active")); - else - printf(_("Mask is not present")); if (present) { - printf("\n"); + printf(_("Mask is active")); printf(_("Mask name: %s"), full_mask); } + else { + printf(_("Mask is not present")); + printf(_("If activated, mask name will be: %s"), full_mask); + } if (is_mask_reclass) { printf("\n"); printf(_("Mask is a raster reclassified from: %s"), diff --git a/raster/r.mask.status/r.mask.status.html b/raster/r.mask.status/r.mask.status.html index 248ee3ea317..cb3897820f5 100644 --- a/raster/r.mask.status/r.mask.status.html +++ b/raster/r.mask.status/r.mask.status.html @@ -1,11 +1,21 @@

DESCRIPTION

The r.mask.status reports information about the 2D raster mask and its -status. If the mask is present, the tool reports a full name of the raster (name -including the mapset) which represents the mask. It can also report full name of -the underlying raster if the mask is reclassified from another raster. - -

+status. The tool reports whether the mask is present or not. For both active +and inactive mask, the tool reports a full name of the raster (name including +the mapset) which represents or would represent the mask. +It can also report full name of the underlying raster if the mask is +reclassified from another raster. + +The tool can be used to check if the mask is currently set +(present boolean in JSON), what is raster name used to represent +the mask (name string in JSON), and whether the raster is +reclassifed from another (is_reclass_of string or null in JSON). +YAML and shell script style outputs are following the JSON output if possible. +The plain text format outputs multi-line human-readable information in natural +language. + +

With the -t flag, no output is printed, instead a return code is used to indicate presence or absence. The convention is the same same the POSIX test utility, so r.mask.status returns 0 when the mask is diff --git a/raster/r.mask.status/tests/r_mask_status_test.py b/raster/r.mask.status/tests/r_mask_status_test.py index deafdfb145b..a5d406ad581 100644 --- a/raster/r.mask.status/tests/r_mask_status_test.py +++ b/raster/r.mask.status/tests/r_mask_status_test.py @@ -15,10 +15,11 @@ def test_json_no_mask(session_no_data): session = session_no_data data = gs.parse_command("r.mask.status", format="json", env=session.env) assert "present" in data - assert "full_name" in data + assert "name" in data + assert data["name"], "Mask name needs to be always set" + assert data["name"] == "MASK@PERMANENT", "Default mask name and current mapset" assert "is_reclass_of" in data assert data["present"] is False - assert not data["full_name"] assert not data["is_reclass_of"] @@ -28,13 +29,13 @@ def test_json_with_r_mask(session_with_data): gs.run_command("r.mask", raster="a", env=session.env) data = gs.parse_command("r.mask.status", format="json", env=session.env) assert data["present"] is True - assert data["full_name"] == "MASK@PERMANENT" + assert data["name"] == "MASK@PERMANENT" assert data["is_reclass_of"] == "a@PERMANENT" # Now remove the mask. gs.run_command("r.mask", flags="r", env=session.env) data = gs.parse_command("r.mask.status", format="json", env=session.env) assert data["present"] is False - assert not data["full_name"] + assert data["name"] == "MASK@PERMANENT" assert not data["is_reclass_of"] @@ -44,13 +45,13 @@ def test_json_with_g_copy(session_with_data): gs.run_command("g.copy", raster="a,MASK", env=session.env) data = gs.parse_command("r.mask.status", format="json", env=session.env) assert data["present"] is True - assert data["full_name"] == "MASK@PERMANENT" + assert data["name"] == "MASK@PERMANENT" assert not data["is_reclass_of"] # Now remove the mask. gs.run_command("g.remove", type="raster", name="MASK", flags="f", env=session.env) data = gs.parse_command("r.mask.status", format="json", env=session.env) assert data["present"] is False - assert not data["full_name"] + assert data["name"] == "MASK@PERMANENT" assert not data["is_reclass_of"] @@ -60,13 +61,13 @@ def test_shell(session_with_data): gs.run_command("r.mask", raster="a", env=session.env) data = gs.parse_command("r.mask.status", format="shell", env=session.env) assert int(data["present"]) - assert data["full_name"] == "MASK@PERMANENT" + assert data["name"] == "MASK@PERMANENT" assert data["is_reclass_of"] == "a@PERMANENT" # Now remove the mask. gs.run_command("r.mask", flags="r", env=session.env) data = gs.parse_command("r.mask.status", format="shell", env=session.env) assert not int(data["present"]) - assert not data["full_name"] + assert data["name"] == "MASK@PERMANENT" assert not data["is_reclass_of"] @@ -78,14 +79,14 @@ def test_yaml(session_with_data): text = gs.read_command("r.mask.status", format="yaml", env=session.env) data = yaml.safe_load(text) assert data["present"] is True - assert data["full_name"] == "MASK@PERMANENT" + assert data["name"] == "MASK@PERMANENT" assert data["is_reclass_of"] == "a@PERMANENT" # Now remove the mask. gs.run_command("r.mask", flags="r", env=session.env) text = gs.read_command("r.mask.status", format="yaml", env=session.env) data = yaml.safe_load(text) assert data["present"] is False - assert not data["full_name"] + assert data["name"] == "MASK@PERMANENT" assert not data["is_reclass_of"] @@ -101,6 +102,8 @@ def test_plain(session_with_data): gs.run_command("r.mask", flags="r", env=session.env) text = gs.read_command("r.mask.status", format="plain", env=session.env) assert text + assert "MASK@PERMANENT" in text + assert "a@PERMANENT" not in text def test_without_parameters(session_no_data): From f9f01e1e40ab9eb8a28fd91717178935946e6606 Mon Sep 17 00:00:00 2001 From: Stefan Blumentrath Date: Thu, 31 Oct 2024 20:23:21 +0100 Subject: [PATCH 08/57] r.buildvrt: document performance issues with external data (#4441) * document performance issue * address code review * Apply suggestions from code review Co-authored-by: Markus Neteler * consistent recommendation * remove leftover dot --------- Co-authored-by: Markus Neteler --- raster/r.buildvrt/r.buildvrt.html | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/raster/r.buildvrt/r.buildvrt.html b/raster/r.buildvrt/r.buildvrt.html index 67368179efb..d5118ba5150 100644 --- a/raster/r.buildvrt/r.buildvrt.html +++ b/raster/r.buildvrt/r.buildvrt.html @@ -12,6 +12,8 @@

NOTES

the original raster maps which is only valid if the original raster maps remain in the originally indicated mapset. A VRT can also be built from raster maps registered with r.external. +However, GRASS VRTs built from external registered data (see below) +are known to have performance issues.

Reading the whole VRT is slower than reading the equivalent single @@ -48,12 +50,23 @@

VRT from a DEM in the North Carolina sample dataset

r.buildvrt file=tilelist.csv output=elev_state_50m_vrt +

KNOWN ISSUES

+ +Users may experience significant performance degradation with virtual rasters built +with r.buildvrt over GDAL-linked (r.external) raster maps, +especially on slower file systems with latency like NFS. Performance degradation +may also occur on local file systems, but is usually less severe. For such use cases +consider using the GRASS GIS addon +r.buildvrt.gdal +or building GDAL VRTs, e.g. with gdalbuildvrt. +

SEE ALSO

r.tile, r.patch, r.external +r.buildvrt.gdal

From d5a87229ae30cf04ff90f7cfcdc923ec0afa5a36 Mon Sep 17 00:00:00 2001 From: Arohan Ajit Date: Thu, 31 Oct 2024 16:12:20 -0400 Subject: [PATCH 09/57] db.out.ogr: Removed unused variable (#4617) --- .flake8 | 2 +- scripts/db.out.ogr/db.out.ogr.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.flake8 b/.flake8 index 3adda73f281..33920703ca6 100644 --- a/.flake8 +++ b/.flake8 @@ -94,7 +94,7 @@ per-file-ignores = scripts/r.semantic.label/r.semantic.label.py: E501 scripts/db.out.ogr/db.out.ogr.py: F841 scripts/g.extension/g.extension.py: E501 - scripts/v.unpack/v.unpack.py: E501 + scripts/v.unpack/v.unpack.py: E501n scripts/v.import/v.import.py: E501 scripts/db.univar/db.univar.py: E501 scripts/i.pansharpen/i.pansharpen.py: E501 diff --git a/scripts/db.out.ogr/db.out.ogr.py b/scripts/db.out.ogr/db.out.ogr.py index 4fdfed23648..4fe5b4f9854 100755 --- a/scripts/db.out.ogr/db.out.ogr.py +++ b/scripts/db.out.ogr/db.out.ogr.py @@ -67,7 +67,6 @@ def main(): layer = options["layer"] format = options["format"] output = options["output"] - table = options["table"] if format.lower() == "dbf": format = "ESRI_Shapefile" From 5b9b46a0cb1606ea7fd0c69d5145ce879b9a6c31 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 31 Oct 2024 20:37:29 +0000 Subject: [PATCH 10/57] CI(deps): Update softprops/action-gh-release action to v2.0.9 (#4624) --- .github/workflows/create_release_draft.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/create_release_draft.yml b/.github/workflows/create_release_draft.yml index efefb0fd0c7..fb71e35d2ff 100644 --- a/.github/workflows/create_release_draft.yml +++ b/.github/workflows/create_release_draft.yml @@ -73,7 +73,7 @@ jobs: sha256sum ${{ env.GRASS }}.tar.xz > ${{ env.GRASS }}.tar.xz.sha256 - name: Publish draft distribution to GitHub (for tags only) if: startsWith(github.ref, 'refs/tags/') - uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191 # v2.0.8 + uses: softprops/action-gh-release@e7a8f85e1c67a31e6ed99a94b41bd0b71bbee6b8 # v2.0.9 with: name: GRASS GIS ${{ github.ref_name }} body: | From 3f0b69fdf56879fcd35d36da51c0227765948dca Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 31 Oct 2024 17:23:31 -0400 Subject: [PATCH 11/57] CI(deps): Update docker/dockerfile Docker tag to v1.11 (#4621) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Dockerfile | 2 +- docker/ubuntu/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index a5c6ab1ee1d..6b928fb46c9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -# syntax=docker/dockerfile:1.10@sha256:865e5dd094beca432e8c0a1d5e1c465db5f998dca4e439981029b3b81fb39ed5 +# syntax=docker/dockerfile:1.11@sha256:1f2be5a2aa052cbd9aedf893d17c63277c3d1c51b3fb0f3b029c6b34f658d057 # Note: This file must be kept in sync in ./Dockerfile and ./docker/ubuntu/Dockerfile. # Changes to this file must be copied over to the other file. diff --git a/docker/ubuntu/Dockerfile b/docker/ubuntu/Dockerfile index a5c6ab1ee1d..6b928fb46c9 100644 --- a/docker/ubuntu/Dockerfile +++ b/docker/ubuntu/Dockerfile @@ -1,4 +1,4 @@ -# syntax=docker/dockerfile:1.10@sha256:865e5dd094beca432e8c0a1d5e1c465db5f998dca4e439981029b3b81fb39ed5 +# syntax=docker/dockerfile:1.11@sha256:1f2be5a2aa052cbd9aedf893d17c63277c3d1c51b3fb0f3b029c6b34f658d057 # Note: This file must be kept in sync in ./Dockerfile and ./docker/ubuntu/Dockerfile. # Changes to this file must be copied over to the other file. From 7d9bbac1f28a6e5f093e4bac55f6b0d6c7227272 Mon Sep 17 00:00:00 2001 From: Arohan Ajit Date: Thu, 31 Oct 2024 22:18:23 -0400 Subject: [PATCH 12/57] r.in.wms: Removed bare 'except' and repositioned imports (#4622) --- .flake8 | 3 --- scripts/r.in.wms/srs.py | 2 +- scripts/r.in.wms/wms_drv.py | 23 ++++++++++------------- scripts/r.in.wms/wms_gdal_drv.py | 2 +- 4 files changed, 12 insertions(+), 18 deletions(-) diff --git a/.flake8 b/.flake8 index 33920703ca6..ab4038e4749 100644 --- a/.flake8 +++ b/.flake8 @@ -88,9 +88,6 @@ per-file-ignores = python/grass/*/*/__init__.py: F403 python/grass/*/*/*/__init__.py: F403 # E402 module level import not at top of file - scripts/r.in.wms/wms_gdal_drv.py: E722 - scripts/r.in.wms/wms_drv.py: E402, E722 - scripts/r.in.wms/srs.py: E722 scripts/r.semantic.label/r.semantic.label.py: E501 scripts/db.out.ogr/db.out.ogr.py: F841 scripts/g.extension/g.extension.py: E501 diff --git a/scripts/r.in.wms/srs.py b/scripts/r.in.wms/srs.py index 8d996fcde94..752f71d8151 100644 --- a/scripts/r.in.wms/srs.py +++ b/scripts/r.in.wms/srs.py @@ -79,7 +79,7 @@ def __init__(self, srs): # code is always the last value try: self.code = int(values[-1]) - except: + except (IndexError, ValueError): self.code = values[-1] elif len(values) == 2: # it's an authority:code code diff --git a/scripts/r.in.wms/wms_drv.py b/scripts/r.in.wms/wms_drv.py index e825aabe438..f9dc42d2383 100644 --- a/scripts/r.in.wms/wms_drv.py +++ b/scripts/r.in.wms/wms_drv.py @@ -18,13 +18,13 @@ """ import socket -import grass.script as gs - from time import sleep +import grass.script as gs + try: from osgeo import gdal -except: +except ImportError: gs.fatal( _( "Unable to load GDAL Python bindings (requires package 'python-gdal' " @@ -32,21 +32,18 @@ ) ) -import numpy as np - -np.arrayrange = np.arange - -from math import pi, floor - -from urllib.error import HTTPError from http.client import HTTPException - +from math import floor, pi +from urllib.error import HTTPError from xml.etree.ElementTree import ParseError -from wms_base import GetEpsg, GetSRSParamVal, WMSBase +import numpy as np -from wms_cap_parsers import WMTSCapabilitiesTree, OnEarthCapabilitiesTree from srs import Srs +from wms_base import GetEpsg, GetSRSParamVal, WMSBase +from wms_cap_parsers import OnEarthCapabilitiesTree, WMTSCapabilitiesTree + +np.arrayrange = np.arange class WMSDrv(WMSBase): diff --git a/scripts/r.in.wms/wms_gdal_drv.py b/scripts/r.in.wms/wms_gdal_drv.py index 830be2b593e..869f71195a2 100644 --- a/scripts/r.in.wms/wms_gdal_drv.py +++ b/scripts/r.in.wms/wms_gdal_drv.py @@ -17,7 +17,7 @@ try: from osgeo import gdal -except: +except ImportError: gs.fatal( _( "Unable to load GDAL Python bindings (requires package 'python-gdal' being " From 4385b2650bcc5432080b29756c855ba0a05d6036 Mon Sep 17 00:00:00 2001 From: Michael Barton Date: Thu, 31 Oct 2024 21:26:09 -0500 Subject: [PATCH 13/57] lib: Add new SRTM_percent color table (#4608) This color table uses the color ramp from the srtm_plus color table for terrain to create colors for relative elevation (spread over the range of elevations in a raster map) rather than absolute elevation in meters. This applies srtm colors in a way similar to the way the elevation color table applies them. This color table is especially useful in creating nice looking elevation maps and shading relief maps. --- lib/gis/colors.desc | 1 + lib/gis/colors/srtm_percent | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 lib/gis/colors/srtm_percent diff --git a/lib/gis/colors.desc b/lib/gis/colors.desc index 673c0db8f91..c501e00c93b 100644 --- a/lib/gis/colors.desc +++ b/lib/gis/colors.desc @@ -48,6 +48,7 @@ sepia: yellowish-brown through to white slope: r.slope.aspect-type slope colors for raster values 0-90 soilmoisture: soilmoisture color table (0.0-1.0) srtm: color palette for Shuttle Radar Topography Mission elevation +srtm_percent: color palette for Shuttle Radar Topography Mission using relative elevation srtm_plus: color palette for Shuttle Radar Topography Mission elevation (with seafloor colors) terrain: global elevation color table covering -11000 to +8850m viridis: perceptually uniform sequential color table viridis diff --git a/lib/gis/colors/srtm_percent b/lib/gis/colors/srtm_percent new file mode 100644 index 00000000000..a8e0d857f76 --- /dev/null +++ b/lib/gis/colors/srtm_percent @@ -0,0 +1,7 @@ +0% 57 151 105 +25% 117 194 93 +40% 230 230 128 +55% 214 187 98 +70% 185 154 100 +80% 150 120 80 +100% 220 220 220 From 4964f451589a1428c48112f8e9349450e1e2edb0 Mon Sep 17 00:00:00 2001 From: Arohan Ajit Date: Fri, 1 Nov 2024 11:54:21 -0400 Subject: [PATCH 14/57] r.in.wms: Replace long-deprecated `np.arrayrange` alias with `np.arange` (#4629) --- scripts/r.in.wms/wms_drv.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/scripts/r.in.wms/wms_drv.py b/scripts/r.in.wms/wms_drv.py index f9dc42d2383..f5e8cbeb914 100644 --- a/scripts/r.in.wms/wms_drv.py +++ b/scripts/r.in.wms/wms_drv.py @@ -43,8 +43,6 @@ from wms_base import GetEpsg, GetSRSParamVal, WMSBase from wms_cap_parsers import OnEarthCapabilitiesTree, WMTSCapabilitiesTree -np.arrayrange = np.arange - class WMSDrv(WMSBase): def _download(self): @@ -288,9 +286,9 @@ def _pct2rgb(self, src_filename, dst_filename): # Build color table lookup = [ - np.arrayrange(256), - np.arrayrange(256), - np.arrayrange(256), + np.arange(256), + np.arange(256), + np.arange(256), np.ones(256) * 255, ] From cb3d12b490528b595729589e373887bc5a5923a6 Mon Sep 17 00:00:00 2001 From: Vaclav Petras Date: Fri, 1 Nov 2024 17:23:39 -0400 Subject: [PATCH 15/57] grass.script: Pass environment to message functions (#4630) While the message functions (fatal, warning, message, info, debug, verbose, percent) have env parameter, grass.script was not consistently passing the env parameter to these functions. This fixes all the clear cases in functions which themselves have env (but does not touch any which don't have it where the fix needs to be more complex). These functions can now be called and produce these messages even for non-global sessions. --- python/grass/script/core.py | 10 ++++++---- python/grass/script/db.py | 7 ++++--- python/grass/script/raster.py | 8 ++++++-- python/grass/script/raster3d.py | 5 ++++- python/grass/script/vector.py | 9 +++++---- 5 files changed, 25 insertions(+), 14 deletions(-) diff --git a/python/grass/script/core.py b/python/grass/script/core.py index f51814a5900..e6de4331b43 100644 --- a/python/grass/script/core.py +++ b/python/grass/script/core.py @@ -1447,7 +1447,7 @@ def list_strings(type, pattern=None, mapset=None, exclude=None, flag="", env=Non :return: list of elements """ if type == "cell": - verbose(_('Element type should be "raster" and not "%s"') % type) + verbose(_('Element type should be "raster" and not "%s"') % type, env=env) result = [] for line in read_command( @@ -1520,7 +1520,9 @@ def list_grouped( flag += "t" for i in range(len(types)): if types[i] == "cell": - verbose(_('Element type should be "raster" and not "%s"') % types[i]) + verbose( + _('Element type should be "raster" and not "%s"') % types[i], env=env + ) types[i] = "raster" result = {} if check_search_path: @@ -1543,7 +1545,7 @@ def list_grouped( try: name, mapset = line.split("@") except ValueError: - warning(_("Invalid element '%s'") % line) + warning(_("Invalid element '%s'") % line, env=env) continue if store_types: @@ -1701,7 +1703,7 @@ def mapsets(search_path=False, env=None): flags = "p" if search_path else "l" mapsets = read_command("g.mapsets", flags=flags, sep="newline", quiet=True, env=env) if not mapsets: - fatal(_("Unable to list mapsets")) + fatal(_("Unable to list mapsets"), env=env) return mapsets.splitlines() diff --git a/python/grass/script/db.py b/python/grass/script/db.py index 60813379501..5591b92d4ca 100644 --- a/python/grass/script/db.py +++ b/python/grass/script/db.py @@ -55,7 +55,7 @@ def db_describe(table, env=None, **args): args.pop("driver") s = read_command("db.describe", flags="c", table=table, env=env, **args) if not s: - fatal(_("Unable to describe table <%s>") % table) + fatal(_("Unable to describe table <%s>") % table, env=env) cols = [] result = {} @@ -179,7 +179,8 @@ def db_select(sql=None, filename=None, table=None, env=None, **args): "Programmer error: '%(sql)s', '%(filename)s', or '%(table)s' must be \ provided" ) - % {"sql": "sql", "filename": "filename", "table": "table"} + % {"sql": "sql", "filename": "filename", "table": "table"}, + env=env, ) if "sep" not in args: @@ -188,7 +189,7 @@ def db_select(sql=None, filename=None, table=None, env=None, **args): try: run_command("db.select", quiet=True, flags="c", output=fname, env=env, **args) except CalledModuleError: - fatal(_("Fetching data failed")) + fatal(_("Fetching data failed"), env=env) ofile = open(fname) result = [tuple(x.rstrip(os.linesep).split(args["sep"])) for x in ofile] diff --git a/python/grass/script/raster.py b/python/grass/script/raster.py index d82780d7c5c..aaf9e0179b0 100644 --- a/python/grass/script/raster.py +++ b/python/grass/script/raster.py @@ -66,7 +66,8 @@ def raster_history(map, overwrite=False, env=None): "Unable to write history for <%(map)s>. " "Raster map <%(map)s> not found in current mapset." ) - % {"map": map} + % {"map": map}, + env=env, ) return False @@ -143,7 +144,10 @@ def mapcalc( overwrite=overwrite, ) except CalledModuleError: - fatal(_("An error occurred while running r.mapcalc with expression: %s") % e) + fatal( + _("An error occurred while running r.mapcalc with expression: %s") % e, + env=env, + ) def mapcalc_start( diff --git a/python/grass/script/raster3d.py b/python/grass/script/raster3d.py index e3db5398158..1a4a2782984 100644 --- a/python/grass/script/raster3d.py +++ b/python/grass/script/raster3d.py @@ -108,4 +108,7 @@ def mapcalc3d( overwrite=overwrite, ) except CalledModuleError: - fatal(_("An error occurred while running r3.mapcalc with expression: %s") % e) + fatal( + _("An error occurred while running r3.mapcalc with expression: %s") % e, + env=env, + ) diff --git a/python/grass/script/vector.py b/python/grass/script/vector.py index 2d484f7d590..4adf3e38da1 100644 --- a/python/grass/script/vector.py +++ b/python/grass/script/vector.py @@ -87,7 +87,7 @@ def vector_layer_db(map, layer, env=None): try: f = vector_db(map, env=env)[int(layer)] except KeyError: - fatal(_("Database connection not defined for layer %s") % layer) + fatal(_("Database connection not defined for layer %s") % layer, env=env) return f @@ -250,7 +250,8 @@ def vector_db_select(map, layer=1, env=None, **kwargs): except KeyError: error( _("Missing layer %(layer)d in vector map <%(map)s>") - % {"layer": layer, "map": map} + % {"layer": layer, "map": map}, + env=env, ) return {"columns": [], "values": {}} @@ -259,13 +260,13 @@ def vector_db_select(map, layer=1, env=None, **kwargs): if key not in kwargs["columns"].split(","): # add key column if missing include_key = False - debug("Adding key column to the output") + debug("Adding key column to the output", env=env) kwargs["columns"] += "," + key ret = read_command("v.db.select", map=map, layer=layer, env=env, **kwargs) if not ret: - error(_("vector_db_select() failed")) + error(_("vector_db_select() failed"), env=env) return {"columns": [], "values": {}} columns = [] From 0824e8842edde3af2588d3865d12ba67493666f0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 2 Nov 2024 01:16:45 +0000 Subject: [PATCH 16/57] CI(deps): Update ruff to v0.7.2 (#4631) --- .github/workflows/python-code-quality.yml | 2 +- .pre-commit-config.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python-code-quality.yml b/.github/workflows/python-code-quality.yml index aa6bd33724f..f7f741a7bb1 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.7.1" + RUFF_VERSION: "0.7.2" runs-on: ${{ matrix.os }} permissions: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2f3216877de..fd6d6c67f50 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.7.1 + rev: v0.7.2 hooks: # Run the linter. - id: ruff From e37730b936cf4ed27878b2ded63c7fe68b8d979e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edouard=20Choini=C3=A8re?= <27212526+echoix@users.noreply.github.com> Date: Sat, 2 Nov 2024 11:31:34 -0400 Subject: [PATCH 17/57] style: Sort package lists, configure options, and other various sortable files (#4563) * style: Sort packages in Vagrantfile * style: Sort configure flags in package.nix * style: Sort .gunittest.cfg * style: Sort Travis build files * style: Sort python optional_requirements.txt * style: Sort configure flags in GitHub workflows * style: Sort packages and configure flags for binder * style: Sort packages, configure flags, cmake flags and wget downloads in Dockerfiles * style: Sort configure flags in Vagrant script * style: Sort svn author name files with linux sort command * style: Sort contributors.csv and contributors_extra.csv * style: Sort rpm package spec * style: Sort packages and configure flags in mswindows build scripts * style: Sort macosx build script Readme * style: Sort singularity file * Apply changes from https://src.fedoraproject.org/rpms/grass/blob/rawhide/f/grass.spec --- .github/workflows/build_ubuntu-22.04.sh | 24 +-- .../workflows/build_ubuntu-22.04_without_x.sh | 26 +-- .github/workflows/coverity.yml | 27 +-- .github/workflows/macos_install.sh | 64 +++---- .github/workflows/optional_requirements.txt | 2 +- .gunittest.cfg | 2 +- .travis/linux.script.sh | 28 ++-- Dockerfile | 2 +- Vagrantfile | 24 +-- binder/apt.txt | 1 - binder/postBuild | 12 +- contributors.csv | 32 ++-- contributors_extra.csv | 6 +- docker/alpine/Dockerfile | 2 +- docker/debian/Dockerfile | 18 +- docker/ubuntu/Dockerfile | 2 +- docker/ubuntu_wxgui/Dockerfile | 20 +-- macosx/ReadMe.md | 112 +++++++++---- mswindows/crosscompile.sh | 44 ++--- mswindows/osgeo4w/build_osgeo4w.sh | 57 ++++--- mswindows/osgeo4w/package.sh | 90 +++++----- package.nix | 2 +- rpm/grass.spec | 156 +++++++++++------- singularity/debian/singularityfile_debian | 30 ++-- utils/svn_name_git_author.csv | 2 +- utils/svn_name_github_name.csv | 52 +++--- utils/vagrant/compile.sh | 32 ++-- 27 files changed, 478 insertions(+), 391 deletions(-) diff --git a/.github/workflows/build_ubuntu-22.04.sh b/.github/workflows/build_ubuntu-22.04.sh index 3beeccf9bbd..677c46d5f33 100755 --- a/.github/workflows/build_ubuntu-22.04.sh +++ b/.github/workflows/build_ubuntu-22.04.sh @@ -31,26 +31,26 @@ set -u export INSTALL_PREFIX=$1 ./configure \ - --prefix="$INSTALL_PREFIX/" \ --enable-largefile \ - --with-cxx \ - --with-zstd \ - --with-bzlib \ + --prefix="$INSTALL_PREFIX/" \ --with-blas \ + --with-bzlib \ + --with-cxx \ + --with-fftw \ + --with-freetype \ + --with-freetype-includes="/usr/include/freetype2/" \ + --with-geos \ --with-lapack \ --with-libsvm \ - --with-readline \ + --with-netcdf \ --with-openmp \ --with-pdal \ - --with-pthread \ - --with-tiff \ - --with-freetype \ - --with-freetype-includes="/usr/include/freetype2/" \ --with-proj-share=/usr/share/proj \ - --with-geos \ + --with-pthread \ + --with-readline \ --with-sqlite \ - --with-fftw \ - --with-netcdf + --with-tiff \ + --with-zstd eval $makecmd make install diff --git a/.github/workflows/build_ubuntu-22.04_without_x.sh b/.github/workflows/build_ubuntu-22.04_without_x.sh index 5df3a0b7e33..7e05457a4ee 100755 --- a/.github/workflows/build_ubuntu-22.04_without_x.sh +++ b/.github/workflows/build_ubuntu-22.04_without_x.sh @@ -30,25 +30,25 @@ set -u export INSTALL_PREFIX=$1 ./configure \ - --prefix="$INSTALL_PREFIX/" \ --enable-largefile \ - --with-cxx \ - --with-zstd \ - --with-bzlib \ + --prefix="$INSTALL_PREFIX/" \ --with-blas \ - --with-lapack \ - --with-readline \ - --without-openmp \ - --with-pdal \ - --without-pthread \ - --with-tiff \ + --with-bzlib \ + --with-cxx \ + --with-fftw \ --with-freetype \ --with-freetype-includes="/usr/include/freetype2/" \ - --with-proj-share=/usr/share/proj \ --with-geos \ + --with-lapack \ + --with-netcdf \ + --with-pdal \ + --with-proj-share=/usr/share/proj \ + --with-readline \ --with-sqlite \ - --with-fftw \ - --with-netcdf + --with-tiff \ + --with-zstd \ + --without-openmp \ + --without-pthread eval $makecmd make install diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml index 51ab83015ca..5253a9ee7a4 100644 --- a/.github/workflows/coverity.yml +++ b/.github/workflows/coverity.yml @@ -58,25 +58,26 @@ jobs: echo "CFLAGS=${{ env.CFLAGS }}" >> $GITHUB_ENV echo "CXXFLAGS=${{ env.CXXFLAGS }}" >> $GITHUB_ENV ./configure \ - --prefix="$HOME/install/" \ --enable-largefile \ - --with-cxx \ - --with-zstd \ - --with-bzlib \ + --prefix="$HOME/install/" \ --with-blas \ - --with-lapack \ - --with-readline \ - --without-openmp \ - --with-pdal \ - --without-pthread \ - --with-tiff \ + --with-bzlib \ + --with-cxx \ + --with-fftw \ --with-freetype \ --with-freetype-includes="/usr/include/freetype2/" \ - --with-proj-share=/usr/share/proj \ --with-geos \ + --with-lapack \ + --with-netcdf \ + --with-pdal \ + --with-proj-share=/usr/share/proj \ + --with-readline \ --with-sqlite \ - --with-fftw \ - --with-netcdf + --with-tiff \ + --with-zstd \ + --without-openmp \ + --without-pthread + env: CFLAGS: -fPIC -g CXXFLAGS: -fPIC -g diff --git a/.github/workflows/macos_install.sh b/.github/workflows/macos_install.sh index 8a94bc15c6a..31d7d23ce8d 100755 --- a/.github/workflows/macos_install.sh +++ b/.github/workflows/macos_install.sh @@ -12,51 +12,51 @@ INSTALL_PREFIX=$1 CONFIGURE_FLAGS="\ --prefix=${INSTALL_PREFIX} \ - --with-opengl=aqua \ - --with-openmp \ - --without-x \ + --with-blas=openblas \ + --with-bzlib \ + --with-bzlib-includes=${CONDA_PREFIX}/include \ + --with-bzlib-libs=${CONDA_PREFIX}/lib \ + --with-cairo \ + --with-cairo-includes=${CONDA_PREFIX}/include/cairo \ + --with-cairo-ldflags="-lcairo" \ + --with-cairo-libs=${CONDA_PREFIX}/lib \ + --with-cxx \ + --with-fftw-includes=${CONDA_PREFIX}/include \ + --with-fftw-libs=${CONDA_PREFIX}/lib \ --with-freetype \ --with-freetype-includes=${CONDA_PREFIX}/include/freetype2 \ --with-freetype-libs=${CONDA_PREFIX}/lib \ --with-gdal=${CONDA_PREFIX}/bin/gdal-config \ - --with-proj-includes=${CONDA_PREFIX}/include \ - --with-proj-libs=${CONDA_PREFIX}/lib \ - --with-proj-share=${CONDA_PREFIX}/share/proj \ --with-geos=${CONDA_PREFIX}/bin/geos-config \ + --with-includes=${CONDA_PREFIX}/include \ + --with-lapack=openblas \ --with-libpng=${CONDA_PREFIX}/bin/libpng-config \ - --with-tiff-includes=${CONDA_PREFIX}/include \ - --with-tiff-libs=${CONDA_PREFIX}/lib \ - --with-postgres=yes \ - --with-postgres-includes=${CONDA_PREFIX}/include \ - --with-postgres-libs=${CONDA_PREFIX}/lib \ - --without-mysql \ - --with-sqlite \ - --with-sqlite-libs=${CONDA_PREFIX}/lib \ - --with-sqlite-includes=${CONDA_PREFIX}/include \ - --with-fftw-includes=${CONDA_PREFIX}/include \ - --with-fftw-libs=${CONDA_PREFIX}/lib \ - --with-cxx \ - --with-cairo \ - --with-cairo-includes=${CONDA_PREFIX}/include/cairo \ - --with-cairo-libs=${CONDA_PREFIX}/lib \ - --with-cairo-ldflags="-lcairo" \ - --with-zstd \ - --with-zstd-libs=${CONDA_PREFIX}/lib \ - --with-zstd-includes=${CONDA_PREFIX}/include \ - --with-bzlib \ - --with-bzlib-libs=${CONDA_PREFIX}/lib \ - --with-bzlib-includes=${CONDA_PREFIX}/include \ + --with-libs=${CONDA_PREFIX}/lib \ --with-netcdf=${CONDA_PREFIX}/bin/nc-config \ - --with-blas=openblas \ - --with-lapack=openblas \ --with-netcdf=${CONDA_PREFIX}/bin/nc-config \ --with-nls \ - --with-libs=${CONDA_PREFIX}/lib \ - --with-includes=${CONDA_PREFIX}/include \ + --with-opengl=aqua \ + --with-openmp \ --with-pdal \ + --with-postgres-includes=${CONDA_PREFIX}/include \ + --with-postgres-libs=${CONDA_PREFIX}/lib \ + --with-postgres=yes \ + --with-proj-includes=${CONDA_PREFIX}/include \ + --with-proj-libs=${CONDA_PREFIX}/lib \ + --with-proj-share=${CONDA_PREFIX}/share/proj \ --with-readline \ --with-readline-includes=${CONDA_PREFIX}/include/readline \ --with-readline-libs=${CONDA_PREFIX}/lib + --with-sqlite \ + --with-sqlite-includes=${CONDA_PREFIX}/include \ + --with-sqlite-libs=${CONDA_PREFIX}/lib \ + --with-tiff-includes=${CONDA_PREFIX}/include \ + --with-tiff-libs=${CONDA_PREFIX}/lib \ + --with-zstd \ + --with-zstd-includes=${CONDA_PREFIX}/include \ + --with-zstd-libs=${CONDA_PREFIX}/lib \ + --without-mysql \ + --without-x \ " export CFLAGS="-O2 -pipe -arch ${CONDA_ARCH} -DGL_SILENCE_DEPRECATION -Wall -Wextra -Wpedantic -Wvla" diff --git a/.github/workflows/optional_requirements.txt b/.github/workflows/optional_requirements.txt index 244a75e2933..078e9fadfb8 100644 --- a/.github/workflows/optional_requirements.txt +++ b/.github/workflows/optional_requirements.txt @@ -1,4 +1,4 @@ folium +ipyleaflet jupyter PyVirtualDisplay -ipyleaflet diff --git a/.gunittest.cfg b/.gunittest.cfg index 2117fde9d7a..45ae87c12a4 100644 --- a/.gunittest.cfg +++ b/.gunittest.cfg @@ -12,8 +12,8 @@ exclude = python/grass/temporal/testsuite/unittests_temporal_raster_algebra_equal_ts.py python/grass/temporal/testsuite/unittests_temporal_raster_conditionals_complement_else.py raster/r.in.lidar/testsuite/test_base_resolution.sh - temporal/t.connect/testsuite/test_distr_tgis_db_raster3d.py temporal/t.connect/testsuite/test_distr_tgis_db_raster.py + temporal/t.connect/testsuite/test_distr_tgis_db_raster3d.py temporal/t.connect/testsuite/test_distr_tgis_db_vector.py temporal/t.info/testsuite/test.t.info.sh temporal/t.rast.aggregate/testsuite/test_aggregation_relative.py diff --git a/.travis/linux.script.sh b/.travis/linux.script.sh index 4944f7e894e..f2ab000dfc3 100755 --- a/.travis/linux.script.sh +++ b/.travis/linux.script.sh @@ -11,28 +11,28 @@ echo "MAKEFLAGS is '$MAKEFLAGS'" ./configure --host=x86_64-linux-gnu \ --build=x86_64-linux-gnu \ + --enable-largefile \ + --enable-shared \ --prefix=/usr/lib \ - --sysconfdir=/etc \ --sharedstatedir=/var \ - --enable-shared \ - --with-postgres \ + --sysconfdir=/etc \ + --with-blas \ + --with-cairo \ --with-cxx \ - --with-gdal \ --with-freetype \ - --with-readline \ - --with-nls \ - --with-odbc \ + --with-freetype-includes=/usr/include/freetype2/ \ + --with-gdal \ --with-geos \ --with-lapack \ --with-netcdf \ - --with-blas \ - --with-sqlite \ - --with-zstd \ - --enable-largefile \ - --with-freetype-includes=/usr/include/freetype2/ \ + --with-nls \ + --with-odbc \ + --with-pdal \ + --with-postgres \ --with-postgres-includes=/usr/include/postgresql/ \ --with-proj-share=/usr/share/proj \ - --with-cairo \ - --with-pdal + --with-readline \ + --with-sqlite \ + --with-zstd make CFLAGS="$CFLAGS $GRASS_EXTRA_CFLAGS" CXXFLAGS="$CXXFLAGS $GRASS_EXTRA_CXXFLAGS" diff --git a/Dockerfile b/Dockerfile index 6b928fb46c9..a3645bc558d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -131,9 +131,9 @@ ARG GRASS_CONFIG="\ " ARG GRASS_PYTHON_PACKAGES="\ - Pillow \ matplotlib \ numpy \ + Pillow \ pip \ ply \ psycopg2 \ diff --git a/Vagrantfile b/Vagrantfile index 035bb0c64cb..99c373e82ef 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -43,11 +43,11 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| packageList = [ "autoconf2.69", "autotools-dev", - "make", + "bison", + "flex", "g++", "gettext", - "flex", - "bison", + "libblas-dev", "libcairo2-dev", "libfftw3-dev", "libfreetype6-dev", @@ -55,27 +55,27 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| "libgeos-dev", "libglu1-mesa-dev", "libjpeg-dev", - "libpng-dev", - "libtiff-dev", + "liblapack-dev", "libmysqlclient-dev", "libncurses5-dev", + "libnetcdf-dev", + "libpng-dev", "libpq-dev", "libproj-dev", - "proj-bin", "libreadline-dev", "libsqlite3-dev", + "libtiff-dev", "libxmu-dev", + "make", + "netcdf-bin", + "proj-bin", "python3", - "python3-wxgtk4.0", "python3-dateutil", "python3-dev", "python3-numpy", - "python3-ply", "python3-pil", - "libnetcdf-dev", - "netcdf-bin", - "libblas-dev", - "liblapack-dev", + "python3-ply", + "python3-wxgtk4.0", "unixodbc-dev", "zlib1g-dev", # "libpdal-dev" diff --git a/binder/apt.txt b/binder/apt.txt index 1ee0d6836f9..7f4a3500c82 100644 --- a/binder/apt.txt +++ b/binder/apt.txt @@ -19,7 +19,6 @@ liblapack-dev libncurses5-dev libnetcdf-dev libpdal-dev -libgeos-dev libpng-dev libpq-dev libproj-dev diff --git a/binder/postBuild b/binder/postBuild index 138326daa18..fd462729ec3 100755 --- a/binder/postBuild +++ b/binder/postBuild @@ -5,15 +5,15 @@ set -e # compile ./configure \ - --with-nls \ - --with-cxx \ - --with-readline \ --with-bzlib \ - --with-proj-share=/usr/share/proj \ - --with-geos=/usr/bin/geos-config \ --with-cairo \ - --with-opengl-libs=/usr/include/GL \ + --with-cxx \ --with-freetype=yes --with-freetype-includes="/usr/include/freetype2/" \ + --with-geos=/usr/bin/geos-config \ + --with-nls \ + --with-opengl-libs=/usr/include/GL \ + --with-proj-share=/usr/share/proj \ + --with-readline \ --with-sqlite=yes \ --without-pdal make diff --git a/contributors.csv b/contributors.csv index 5f501d9f077..c9236bb1aea 100644 --- a/contributors.csv +++ b/contributors.csv @@ -1,25 +1,25 @@ cvs_id,name,email,country,osgeo_id,rfc2_agreed,orcid --,Ivan Shmakov,,Russia,1gray,yes,- --,Eric Patton,,Canada,epatton,yes,- --,Laura Toma,,USA,ltoma,yes,- --,Markus Metz,,Germany,mmetz,yes,0000-0002-4038-8754 --,Maris Nartiss,,Latvia,marisn,yes,0000-0002-3875-740X --,Marco Pasetti,,Italy,marcopx,yes,- --,Yann Chemin,,France,ychemin,yes,0000-0001-9232-5512 --,Colin Nielsen,,USA,cnielsen,yes,- +-,Anna Petrášová,,Czech Republic,annakrat,yes,0000-0002-5120-5538 -,Anne Ghisla,,Italy,aghisla,yes,- +-,Colin Nielsen,,USA,cnielsen,yes,- +-,Eric Patton,,Canada,epatton,yes,- -,Helmut Kudrnovsky,,Austria,hellik,yes,0000-0001-6622-7169 --,Anna Petrášová,,Czech Republic,annakrat,yes,0000-0002-5120-5538 +-,Ivan Shmakov,,Russia,1gray,yes,- +-,Laura Toma,,USA,ltoma,yes,- -,Luca Delucchi,,Italy,lucadelu,yes,0000-0002-0493-3516 --,Václav Petráš,,Czech Republic,wenzeslaus,yes,0000-0001-5566-9236 --,Pietro Zambelli,,Italy,zarch,yes,0000-0002-6187-3572 --,Štěpán Turek,,Czech Republic,turek,yes,- +-,Marco Pasetti,,Italy,marcopx,yes,- -,Margherita Di Leo,,Italy,madi,yes,0000-0002-0279-7557 --,Veronica Andreo,,Argentina,veroandreo,yes,0000-0002-4633-2161 --,Stefan Blumentrath,,Norway,sbl,yes,0000-0001-6675-1331 +-,Maris Nartiss,,Latvia,marisn,yes,0000-0002-3875-740X +-,Markus Metz,,Germany,mmetz,yes,0000-0002-4038-8754 +-,Nicklas Larsson,,Hungary/Sweden,nilason,yes,- -,Ondřej Pešek,,Czech Republic,pesekon2,yes,0000-0002-2363-8002 +-,Pietro Zambelli,,Italy,zarch,yes,0000-0002-6187-3572 +-,Stefan Blumentrath,,Norway,sbl,yes,0000-0001-6675-1331 +-,Štěpán Turek,,Czech Republic,turek,yes,- -,Tomáš Zigo,,Slovak Republic,tmszi,yes,- --,Nicklas Larsson,,Hungary/Sweden,nilason,yes,- +-,Václav Petráš,,Czech Republic,wenzeslaus,yes,0000-0001-5566-9236 +-,Veronica Andreo,,Argentina,veroandreo,yes,0000-0002-4633-2161 +-,Yann Chemin,,France,ychemin,yes,0000-0001-9232-5512 alex,Alex Shevlakov,,Russia,-,-,- andreas,Andreas Lange,,Germany,-,-,- benjamin,Benjamin Ducke,,Germany,benducke,yes,0000-0002-0560-4749 @@ -52,9 +52,9 @@ michel,Michel Wurtz,,France,-,-,- mike,Mike Thomas,,Australia,-,-,- moritz,Moritz Lennert,,Belgium,mlennert,yes,0000-0002-2870-4515 msieczka,Maciej Sieczka,,Poland,msieczka,yes,- +pallech,Serena Pallecchi,,Italy,-,-,- paul,Paul Kelly,,UK,pkelly,yes,- paulo,Paulo Marcondes,,Brazil,pmarcondes,-,- -pallech,Serena Pallecchi,,Italy,-,-,- radim,Radim Blazek,,Czech Republic,rblazek,-,- roberto,Roberto Micarelli,,Italy,-,-,- robertoa,Roberto Antolin,,Spain,rantolin,yes,- diff --git a/contributors_extra.csv b/contributors_extra.csv index 5bcbcaaa67d..1cfa5ac4a82 100644 --- a/contributors_extra.csv +++ b/contributors_extra.csv @@ -1,11 +1,11 @@ name,email,country,rfc2_agreed Adam Laža,,Czech Republic,yes +Aldo Clerici,,Italy,- Alfonso Vitti,,Italy,- -Anna Zanchetta,,Italy,yes Andrea Aime,,Italy,- Angus Carr,,Canada,- +Anna Zanchetta,,Italy,yes Antonio Galea,,Italy,- -Aldo Clerici,,Italy,- Ari Jolma,,Finland,- Bill Hughes,,USA,- Brook Milligan,,USA,- @@ -23,8 +23,8 @@ Eric Mitchell,,-,- Francesco Pirotti,,Italy,- Ivan Mincik,,Slovakia,- Jacques Bouchard,,France,- -Jarrett Keifer,,USA,- Jaro Hofierka,,Slovakia,- +Jarrett Keifer,,USA,- Jeshua Lacock,,USA,- Lars Ahlzen,,-,- Lorenzo Moretti,,Italy,- diff --git a/docker/alpine/Dockerfile b/docker/alpine/Dockerfile index b6dbebf6666..8163b5d9b08 100644 --- a/docker/alpine/Dockerfile +++ b/docker/alpine/Dockerfile @@ -29,11 +29,11 @@ ENV GRASS_RUN_PACKAGES="\ gdal-driver-JP2OpenJPEG \ gdal-driver-LIBKML \ gdal-driver-MSSQLSpatial \ + gdal-driver-netCDF \ gdal-driver-ODBC \ gdal-driver-PG \ gdal-driver-PNG \ gdal-driver-WMS \ - gdal-driver-netCDF \ gdal-tools \ geos \ geos-dev \ diff --git a/docker/debian/Dockerfile b/docker/debian/Dockerfile index 8021ccf409e..6df50c8e14d 100644 --- a/docker/debian/Dockerfile +++ b/docker/debian/Dockerfile @@ -88,15 +88,15 @@ RUN echo en_US.UTF-8 UTF-8 >> /etc/locale.gen && locale-gen WORKDIR /src RUN mkdir vdatum && \ cd vdatum && \ - wget -q http://download.osgeo.org/proj/vdatum/usa_geoid2012.zip && unzip -j -u usa_geoid2012.zip -d /usr/share/proj; \ - wget -q http://download.osgeo.org/proj/vdatum/usa_geoid2009.zip && unzip -j -u usa_geoid2009.zip -d /usr/share/proj; \ - wget -q http://download.osgeo.org/proj/vdatum/usa_geoid2003.zip && unzip -j -u usa_geoid2003.zip -d /usr/share/proj; \ + wget -q http://download.osgeo.org/proj/vdatum/egm08_25/egm08_25.gtx && mv egm08_25.gtx /usr/share/proj; \ + wget -q http://download.osgeo.org/proj/vdatum/egm96_15/egm96_15.gtx && mv egm96_15.gtx /usr/share/proj; \ wget -q http://download.osgeo.org/proj/vdatum/usa_geoid1999.zip && unzip -j -u usa_geoid1999.zip -d /usr/share/proj; \ + wget -q http://download.osgeo.org/proj/vdatum/usa_geoid2003.zip && unzip -j -u usa_geoid2003.zip -d /usr/share/proj; \ + wget -q http://download.osgeo.org/proj/vdatum/usa_geoid2009.zip && unzip -j -u usa_geoid2009.zip -d /usr/share/proj; \ + wget -q http://download.osgeo.org/proj/vdatum/usa_geoid2012.zip && unzip -j -u usa_geoid2012.zip -d /usr/share/proj; \ wget -q http://download.osgeo.org/proj/vdatum/vertcon/vertconc.gtx && mv vertconc.gtx /usr/share/proj; \ wget -q http://download.osgeo.org/proj/vdatum/vertcon/vertcone.gtx && mv vertcone.gtx /usr/share/proj; \ wget -q http://download.osgeo.org/proj/vdatum/vertcon/vertconw.gtx && mv vertconw.gtx /usr/share/proj; \ - wget -q http://download.osgeo.org/proj/vdatum/egm96_15/egm96_15.gtx && mv egm96_15.gtx /usr/share/proj; \ - wget -q http://download.osgeo.org/proj/vdatum/egm08_25/egm08_25.gtx && mv egm08_25.gtx /usr/share/proj; \ cd .. && \ rm -rf vdatum @@ -116,16 +116,16 @@ RUN wget -q \ -DCMAKE_C_COMPILER=gcc \ -DCMAKE_CXX_COMPILER=g++ \ -DCMAKE_MAKE_PROGRAM=make \ - -DBUILD_PLUGIN_PYTHON=ON \ + -DBUILD_PGPOINTCLOUD_TESTS=OFF \ -DBUILD_PLUGIN_CPD=OFF \ -DBUILD_PLUGIN_GREYHOUND=ON \ -DBUILD_PLUGIN_HEXBIN=ON \ - -DHEXER_INCLUDE_DIR=/usr/include/ \ - -DBUILD_PLUGIN_NITF=OFF \ -DBUILD_PLUGIN_ICEBRIDGE=ON \ + -DBUILD_PLUGIN_NITF=OFF \ -DBUILD_PLUGIN_PGPOINTCLOUD=OFF \ - -DBUILD_PGPOINTCLOUD_TESTS=OFF \ + -DBUILD_PLUGIN_PYTHON=ON \ -DBUILD_PLUGIN_SQLITE=ON \ + -DHEXER_INCLUDE_DIR=/usr/include/ \ -DWITH_LASZIP=OFF \ -DWITH_LAZPERF=ON \ -DWITH_TESTS=ON && \ diff --git a/docker/ubuntu/Dockerfile b/docker/ubuntu/Dockerfile index 6b928fb46c9..a3645bc558d 100644 --- a/docker/ubuntu/Dockerfile +++ b/docker/ubuntu/Dockerfile @@ -131,9 +131,9 @@ ARG GRASS_CONFIG="\ " ARG GRASS_PYTHON_PACKAGES="\ - Pillow \ matplotlib \ numpy \ + Pillow \ pip \ ply \ psycopg2 \ diff --git a/docker/ubuntu_wxgui/Dockerfile b/docker/ubuntu_wxgui/Dockerfile index 0d1ead788a3..80dbbb1d409 100644 --- a/docker/ubuntu_wxgui/Dockerfile +++ b/docker/ubuntu_wxgui/Dockerfile @@ -122,15 +122,15 @@ RUN echo en_US.UTF-8 UTF-8 >> /etc/locale.gen && locale-gen WORKDIR /src RUN mkdir vdatum && \ cd vdatum && \ - wget -q http://download.osgeo.org/proj/vdatum/usa_geoid2012.zip && unzip -j -u usa_geoid2012.zip -d /usr/share/proj; \ - wget -q http://download.osgeo.org/proj/vdatum/usa_geoid2009.zip && unzip -j -u usa_geoid2009.zip -d /usr/share/proj; \ - wget -q http://download.osgeo.org/proj/vdatum/usa_geoid2003.zip && unzip -j -u usa_geoid2003.zip -d /usr/share/proj; \ + wget -q http://download.osgeo.org/proj/vdatum/egm08_25/egm08_25.gtx && mv egm08_25.gtx /usr/share/proj; \ + wget -q http://download.osgeo.org/proj/vdatum/egm96_15/egm96_15.gtx && mv egm96_15.gtx /usr/share/proj; \ wget -q http://download.osgeo.org/proj/vdatum/usa_geoid1999.zip && unzip -j -u usa_geoid1999.zip -d /usr/share/proj; \ + wget -q http://download.osgeo.org/proj/vdatum/usa_geoid2003.zip && unzip -j -u usa_geoid2003.zip -d /usr/share/proj; \ + wget -q http://download.osgeo.org/proj/vdatum/usa_geoid2009.zip && unzip -j -u usa_geoid2009.zip -d /usr/share/proj; \ + wget -q http://download.osgeo.org/proj/vdatum/usa_geoid2012.zip && unzip -j -u usa_geoid2012.zip -d /usr/share/proj; \ wget -q http://download.osgeo.org/proj/vdatum/vertcon/vertconc.gtx && mv vertconc.gtx /usr/share/proj; \ wget -q http://download.osgeo.org/proj/vdatum/vertcon/vertcone.gtx && mv vertcone.gtx /usr/share/proj; \ wget -q http://download.osgeo.org/proj/vdatum/vertcon/vertconw.gtx && mv vertconw.gtx /usr/share/proj; \ - wget -q http://download.osgeo.org/proj/vdatum/egm96_15/egm96_15.gtx && mv egm96_15.gtx /usr/share/proj; \ - wget -q http://download.osgeo.org/proj/vdatum/egm08_25/egm08_25.gtx && mv egm08_25.gtx /usr/share/proj; \ cd .. && \ rm -rf vdatum @@ -150,16 +150,16 @@ RUN wget -q \ -DCMAKE_C_COMPILER=gcc \ -DCMAKE_CXX_COMPILER=g++ \ -DCMAKE_MAKE_PROGRAM=make \ - -DBUILD_PLUGIN_PYTHON=ON \ + -DBUILD_PGPOINTCLOUD_TESTS=OFF \ -DBUILD_PLUGIN_CPD=OFF \ -DBUILD_PLUGIN_GREYHOUND=ON \ -DBUILD_PLUGIN_HEXBIN=ON \ - -DHEXER_INCLUDE_DIR=/usr/include/ \ - -DBUILD_PLUGIN_NITF=OFF \ -DBUILD_PLUGIN_ICEBRIDGE=ON \ + -DBUILD_PLUGIN_NITF=OFF \ -DBUILD_PLUGIN_PGPOINTCLOUD=OFF \ - -DBUILD_PGPOINTCLOUD_TESTS=OFF \ + -DBUILD_PLUGIN_PYTHON=ON \ -DBUILD_PLUGIN_SQLITE=ON \ + -DHEXER_INCLUDE_DIR=/usr/include/ \ -DWITH_LASZIP=OFF \ -DWITH_LAZPERF=ON \ -DWITH_TESTS=ON && \ @@ -186,8 +186,8 @@ ENV CXXFLAGS "$MYCXXFLAGS" # Configure compile and install GRASS GIS # wxGUI require -# --with-x # --with-nls +# --with-x ENV NUMTHREADS=4 RUN make distclean || echo "nothing to clean" RUN /src/grass_build/configure \ diff --git a/macosx/ReadMe.md b/macosx/ReadMe.md index 86fb1c0ba38..085c09c691b 100644 --- a/macosx/ReadMe.md +++ b/macosx/ReadMe.md @@ -172,6 +172,11 @@ just remove the `--prefix` and `--enable-macosx-app` flags)*: ```bash ./configure \ + --enable-macosx-app \ + --prefix=/Applications \ + --with-cxx \ + --with-fftw-includes=/Library/Frameworks/FFTW3.framework/unix/include \ + --with-fftw-libs=/Library/Frameworks/FFTW3.framework/unix/lib \ --with-freetype \ --with-freetype-includes= \ "/Library/Frameworks/FreeType.framework/unix/include/freetype2 \ @@ -179,36 +184,31 @@ just remove the `--prefix` and `--enable-macosx-app` flags)*: --with-freetype-libs=/Library/Frameworks/FreeType.framework/unix/lib \ --with-gdal=/Library/Frameworks/GDAL.framework/Programs/gdal-config \ --with-geos=/Library/Frameworks/GEOS.framework/Programs/geos-config \ - --with-proj \ - --with-proj-includes=/Library/Frameworks/PROJ.framework/unix/include \ - --with-proj-libs=/Library/Frameworks/PROJ.framework/unix/lib \ - --with-proj-share=/Library/Frameworks/PROJ.framework/Resources/proj \ --with-jpeg-includes=/Library/Frameworks/UnixImageIO.framework/unix/include \ --with-jpeg-libs=/Library/Frameworks/UnixImageIO.framework/unix/lib \ + --with-odbc \ + --with-opengl=aqua \ --with-png-includes=/Library/Frameworks/UnixImageIO.framework/unix/include \ --with-png-libs=/Library/Frameworks/UnixImageIO.framework/unix/lib \ - --with-tiff-includes=/Library/Frameworks/UnixImageIO.framework/unix/include \ - --with-tiff-libs=/Library/Frameworks/UnixImageIO.framework/unix/lib \ - --without-postgres \ - --without-mysql \ - --with-odbc \ + --with-proj \ + --with-proj-includes=/Library/Frameworks/PROJ.framework/unix/include \ + --with-proj-libs=/Library/Frameworks/PROJ.framework/unix/lib \ + --with-proj-share=/Library/Frameworks/PROJ.framework/Resources/proj \ --with-sqlite \ - --with-sqlite-libs=/Library/Frameworks/SQLite3.framework/unix/lib \ --with-sqlite-includes=/Library/Frameworks/SQLite3.framework/unix/include \ - --with-fftw-includes=/Library/Frameworks/FFTW3.framework/unix/include \ - --with-fftw-libs=/Library/Frameworks/FFTW3.framework/unix/lib \ - --with-cxx \ + --with-sqlite-libs=/Library/Frameworks/SQLite3.framework/unix/lib \ --with-tcltk-includes="/Library/Frameworks/Tcl.framework/Headers \ /Library/Frameworks/Tk.framework/Headers \ /Library/Frameworks/Tk.framework/PrivateHeaders" \ --with-tcltk-libs=/usr/local/lib \ + --with-tiff-includes=/Library/Frameworks/UnixImageIO.framework/unix/include \ + --with-tiff-libs=/Library/Frameworks/UnixImageIO.framework/unix/lib \ --with-x \ - --without-motif \ --without-glw \ - --with-opengl=aqua \ - --without-readline \ - --prefix=/Applications \ - --enable-macosx-app + --without-motif \ + --without-mysql \ + --without-postgres \ + --without-readline ``` That's a long line, but you have to be very explicit in the GRASS configure @@ -533,10 +533,21 @@ For i386: ```sh cd build-i386 -../configure --enable-shared --disable-static --disable-debug \ - --disable-ffserver --disable-network --enable-gpl --enable-pthreads \ - --enable-swscale --disable-vhook --disable-ffplay --disable-ffmpeg \ - --disable-amd3dnow --arch=i386 --extra-cflags="-arch i386" \ +../configure \ + --arch=i386 \ + --disable-amd3dnow \ + --disable-debug \ + --disable-ffmpeg \ + --disable-ffplay \ + --disable-ffserver \ + --disable-network \ + --disable-static \ + --disable-vhook \ + --enable-gpl \ + --enable-pthreads \ + --enable-shared \ + --enable-swscale \ + --extra-cflags="-arch i386" \ --extra-ldflags="-arch i386" ``` @@ -555,10 +566,21 @@ Now, the PPC build: ```sh cd ../build-ppc -../configure --enable-shared --disable-static --disable-debug \ - --disable-ffserver --disable-network --enable-gpl --enable-pthreads \ - --enable-swscale --disable-vhook --disable-ffplay --disable-ffmpeg \ - --enable-altivec --arch=ppc --extra-cflags="-arch ppc" \ +../configure \ + --arch=ppc \ + --disable-debug \ + --disable-ffmpeg \ + --disable-ffplay \ + --disable-ffserver \ + --disable-network \ + --disable-static \ + --disable-vhook \ + --enable-altivec \ + --enable-gpl \ + --enable-pthreads \ + --enable-shared \ + --enable-swscale \ + --extra-cflags="-arch ppc" \ --extra-ldflags="-arch ppc" make ``` @@ -572,10 +594,21 @@ For x86_64: ```sh cd build-x86_64 -../configure --enable-shared --disable-static --disable-debug \ - --disable-ffserver --disable-network --enable-gpl --enable-pthreads \ - --enable-swscale --disable-vhook --disable-ffplay --disable-ffmpeg \ - --disable-amd3dnow --arch=x86_64 --extra-cflags="-arch x86\_64" \ +../configure \ + --arch=x86_64 \ + --disable-amd3dnow \ + --disable-debug \ + --disable-ffmpeg \ + --disable-ffplay \ + --disable-ffserver \ + --disable-network \ + --disable-static \ + --disable-vhook \ + --enable-gpl \ + --enable-pthreads \ + --enable-shared \ + --enable-swscale \ + --extra-cflags="-arch x86\_64" \ --extra-ldflags="-arch x86_64" ``` @@ -588,10 +621,21 @@ And ppc64: ```sh cd ../build-ppc64 -../configure --enable-shared --disable-static --disable-debug \ - --disable-ffserver --disable-network --enable-gpl --enable-pthreads \ - --enable-swscale --disable-vhook --disable-ffplay --disable-ffmpeg \ - --enable-altivec --arch=ppc64 --extra-cflags="-arch ppc64" \ +../configure \ + --arch=ppc64 \ + --disable-debug \ + --disable-ffmpeg \ + --disable-ffplay \ + --disable-ffserver \ + --disable-network \ + --disable-static \ + --disable-vhook \ + --enable-altivec \ + --enable-gpl \ + --enable-pthreads \ + --enable-shared \ + --enable-swscale \ + --extra-cflags="-arch ppc64" \ --extra-ldflags="-arch ppc64" ``` diff --git a/mswindows/crosscompile.sh b/mswindows/crosscompile.sh index d1b834df008..ec43dcab689 100755 --- a/mswindows/crosscompile.sh +++ b/mswindows/crosscompile.sh @@ -129,17 +129,17 @@ CFLAGS="-g -O2 -Wall" \ CXXFLAGS="-g -O2 -Wall" \ LDFLAGS="-lcurses" \ ./configure \ ---with-nls \ ---with-readline \ ---with-freetype-includes=$freetype_include \ ---with-bzlib \ ---with-postgres \ ---with-pthread \ ---with-openmp \ --with-blas \ ---with-lapack \ +--with-bzlib \ +--with-freetype-includes=$freetype_include \ --with-geos \ +--with-lapack \ --with-netcdf \ +--with-nls \ +--with-openmp \ +--with-postgres \ +--with-pthread \ +--with-readline \ >> /dev/stdout make clean default @@ -159,10 +159,10 @@ fi build_arch=`sed -n '/^ARCH[ \t]*=/{s/^.*=[ \t]*//; p}' include/Make/Platform.make` for i in \ config.log \ - include/Make/Platform.make \ + error.log \ include/Make/Doxyfile_arch_html \ include/Make/Doxyfile_arch_latex \ - error.log \ + include/Make/Platform.make \ ; do cp -a $i $i.$build_arch done @@ -186,19 +186,19 @@ PKG_CONFIG=$mxe_bin-pkg-config \ ./configure \ --build=$build_arch \ --host=$arch \ ---with-nls \ ---with-readline \ ---with-freetype-includes=$mxe_shared/include/freetype2 \ ---with-bzlib \ ---with-postgres \ ---with-pthread \ ---with-openmp \ --with-blas \ ---with-lapack \ +--with-bzlib \ +--with-freetype-includes=$mxe_shared/include/freetype2 \ +--with-gdal=$mxe_shared/bin/gdal-config \ --with-geos=$mxe_shared/bin/geos-config \ +--with-lapack \ --with-netcdf=$mxe_shared/bin/nc-config \ ---with-gdal=$mxe_shared/bin/gdal-config \ +--with-nls \ --with-opengl=windows \ +--with-openmp \ +--with-postgres \ +--with-pthread \ +--with-readline \ >> /dev/stdout make clean default @@ -217,10 +217,10 @@ fi arch=`sed -n '/^ARCH[ \t]*=/{s/^.*=[ \t]*//; p}' include/Make/Platform.make` for i in \ config.log \ - include/Make/Platform.make \ + error.log \ include/Make/Doxyfile_arch_html \ include/Make/Doxyfile_arch_latex \ - error.log \ + include/Make/Platform.make \ ; do cp -a $i $i.$arch done @@ -307,8 +307,8 @@ for i in \ done for i in \ - proj \ gdal \ + proj \ ; do rm -rf $dist/share/$i cp -a $mxe_shared/share/$i $dist/share/$i diff --git a/mswindows/osgeo4w/build_osgeo4w.sh b/mswindows/osgeo4w/build_osgeo4w.sh index d38354d4b78..98ed16aac1e 100755 --- a/mswindows/osgeo4w/build_osgeo4w.sh +++ b/mswindows/osgeo4w/build_osgeo4w.sh @@ -22,49 +22,48 @@ export PYTHONHOME=${OSGEO4W_ROOT_MSYS}/apps/Python312 export ARCH=x86_64-w64-mingw32 ./configure \ + --bindir=${OSGEO4W_ROOT_MSYS}/bin \ + --enable-largefile \ + --enable-shared \ --host=${ARCH} \ - --with-libs="${OSGEO4W_ROOT_MSYS}/lib ${OSGEO4W_ROOT_MSYS}/bin" \ - --with-includes=${OSGEO4W_ROOT_MSYS}/include \ + --includedir=${OSGEO4W_ROOT_MSYS}/include \ --libexecdir=${OSGEO4W_ROOT_MSYS}/bin \ --prefix=${OSGEO4W_ROOT_MSYS}/apps/grass \ - --bindir=${OSGEO4W_ROOT_MSYS}/bin \ - --includedir=${OSGEO4W_ROOT_MSYS}/include \ - --without-x \ + --with-blas \ + --with-bzlib \ + --with-cairo \ + --with-cairo-includes=${OSGEO4W_ROOT_MSYS}/include \ + --with-cairo-ldflags="-L${SRC}/mswindows/osgeo4w/lib -lcairo" \ + --with-cairo-libs=$OSGEO4W_ROOT_MSYS/lib \ --with-cxx \ - --enable-shared \ - --enable-largefile \ - --with-openmp \ --with-fftw \ - --with-nls \ - --with-readline \ - --with-blas \ - --with-lapack \ --with-freetype \ --with-freetype-includes=${OSGEO4W_ROOT_MSYS}/include/freetype2 \ - --with-proj-share=${OSGEO4W_ROOT_MSYS}/share/proj \ - --with-proj-includes=${OSGEO4W_ROOT_MSYS}/include \ - --with-proj-libs=${OSGEO4W_ROOT_MSYS}/lib \ + --with-gdal=${SRC}/mswindows/osgeo4w/gdal-config \ + --with-geos=${SRC}/mswindows/osgeo4w/geos-config \ + --with-includes=${OSGEO4W_ROOT_MSYS}/include \ + --with-lapack \ + --with-liblas=${SRC}/mswindows/osgeo4w/liblas-config \ + --with-libs="${OSGEO4W_ROOT_MSYS}/lib ${OSGEO4W_ROOT_MSYS}/bin" \ + --with-netcdf=${OSGEO4W_ROOT_MSYS}/bin/nc-config \ + --with-nls \ + --with-odbc \ + --with-opengl=windows \ + --with-openmp \ --with-postgres \ --with-postgres-includes=${OSGEO4W_ROOT_MSYS}/include \ --with-postgres-libs=${OSGEO4W_ROOT_MSYS}/lib \ - --with-gdal=${SRC}/mswindows/osgeo4w/gdal-config \ - --with-geos=${SRC}/mswindows/osgeo4w/geos-config \ + --with-proj-includes=${OSGEO4W_ROOT_MSYS}/include \ + --with-proj-libs=${OSGEO4W_ROOT_MSYS}/lib \ + --with-proj-share=${OSGEO4W_ROOT_MSYS}/share/proj \ + --with-readline \ + --with-regex \ --with-sqlite \ --with-sqlite-includes=${OSGEO4W_ROOT_MSYS}/include \ --with-sqlite-libs=${OSGEO4W_ROOT_MSYS}/lib \ - --with-regex \ - --with-nls \ --with-zstd \ - --with-odbc \ - --with-cairo \ - --with-cairo-includes=${OSGEO4W_ROOT_MSYS}/include \ - --with-cairo-libs=$OSGEO4W_ROOT_MSYS/lib \ - --with-cairo-ldflags="-L${SRC}/mswindows/osgeo4w/lib -lcairo" \ - --with-opengl=windows \ - --with-bzlib \ - --with-liblas=${SRC}/mswindows/osgeo4w/liblas-config \ - --with-netcdf=${OSGEO4W_ROOT_MSYS}/bin/nc-config \ - --without-pdal + --without-pdal \ + --without-x make diff --git a/mswindows/osgeo4w/package.sh b/mswindows/osgeo4w/package.sh index b3113292c99..c189cf92c93 100755 --- a/mswindows/osgeo4w/package.sh +++ b/mswindows/osgeo4w/package.sh @@ -107,32 +107,32 @@ fi exec 3>&1 > >(tee mswindows/osgeo4w/package.log) 2>&1 DLLS=" - /mingw64/bin/zlib1.dll - /mingw64/bin/libbz2-1.dll - /mingw64/bin/libiconv-2.dll - /mingw64/bin/libfontconfig-1.dll - /mingw64/bin/libgfortran-5.dll - /mingw64/bin/libbrotlidec.dll + /mingw64/bin/libblas.dll /mingw64/bin/libbrotlicommon.dll - /mingw64/bin/libintl-8.dll - /mingw64/bin/libsystre-0.dll - /mingw64/bin/libtre-5.dll - /mingw64/bin/libwinpthread-1.dll + /mingw64/bin/libbrotlidec.dll + /mingw64/bin/libbz2-1.dll /mingw64/bin/libcairo-2.dll - /mingw64/bin/libpixman-1-0.dll - /mingw64/bin/libpng16-16.dll + /mingw64/bin/libfftw3-3.dll + /mingw64/bin/libfontconfig-1.dll /mingw64/bin/libfreetype-6.dll - /mingw64/bin/libharfbuzz-0.dll + /mingw64/bin/libgcc_s_seh-1.dll + /mingw64/bin/libgfortran-5.dll /mingw64/bin/libglib-2.0-0.dll /mingw64/bin/libgomp-1.dll /mingw64/bin/libgraphite2.dll - /mingw64/bin/libpcre-1.dll - /mingw64/bin/libstdc++-6.dll - /mingw64/bin/libgcc_s_seh-1.dll - /mingw64/bin/libfftw3-3.dll - /mingw64/bin/libblas.dll + /mingw64/bin/libharfbuzz-0.dll + /mingw64/bin/libiconv-2.dll + /mingw64/bin/libintl-8.dll /mingw64/bin/liblapack.dll + /mingw64/bin/libpcre-1.dll + /mingw64/bin/libpixman-1-0.dll + /mingw64/bin/libpng16-16.dll /mingw64/bin/libquadmath-0.dll + /mingw64/bin/libstdc++-6.dll + /mingw64/bin/libsystre-0.dll + /mingw64/bin/libtre-5.dll + /mingw64/bin/libwinpthread-1.dll + /mingw64/bin/zlib1.dll " if ! [ -f mswindows/osgeo4w/configure-stamp ]; then @@ -153,47 +153,47 @@ if ! [ -f mswindows/osgeo4w/configure-stamp ]; then log configure ./configure \ + --bindir=$OSGEO4W_ROOT_MSYS/bin \ + --enable-largefile \ + --enable-shared \ --host=x86_64-w64-mingw32 \ - --with-libs="$OSGEO4W_ROOT_MSYS/lib" \ - --with-includes=$OSGEO4W_ROOT_MSYS/include \ + --includedir=$OSGEO4W_ROOT_MSYS/include \ --libexecdir=$OSGEO4W_ROOT_MSYS/bin \ --prefix=$OSGEO4W_ROOT_MSYS/apps/grass \ - --bindir=$OSGEO4W_ROOT_MSYS/bin \ - --includedir=$OSGEO4W_ROOT_MSYS/include \ - --with-opengl=windows \ - --without-x \ + --with-blas \ + --with-bzlib \ + --with-cairo \ + --with-cairo-includes=$OSGEO4W_ROOT_MSYS/include \ + --with-cairo-ldflags="-L$PWD/mswindows/osgeo4w/lib -lcairo -lfontconfig" \ --with-cxx \ - --enable-shared \ - --enable-largefile \ --with-fftw \ --with-freetype \ --with-freetype-includes=/mingw64/include/freetype2 \ - --with-proj-share=$OSGEO4W_ROOT_MSYS/share/proj \ - --with-proj-includes=$OSGEO4W_ROOT_MSYS/include \ - --with-proj-libs=$OSGEO4W_ROOT_MSYS/lib \ + --with-gdal=$PWD/mswindows/osgeo4w/gdal-config \ + --with-geos=$PWD/mswindows/osgeo4w/geos-config \ + --with-includes=$OSGEO4W_ROOT_MSYS/include \ + --with-lapack \ + --with-lapack-includes=/mingw64/include \ + --with-liblas=$PWD/mswindows/osgeo4w/liblas-config \ + --with-libs="$OSGEO4W_ROOT_MSYS/lib" \ + --with-netcdf=${OSGEO4W_ROOT_MSYS}/bin/nc-config \ + --with-nls \ + --with-odbc \ + --with-opengl=windows \ + --with-openmp \ --with-postgres \ --with-postgres-includes=$OSGEO4W_ROOT_MSYS/include \ --with-postgres-libs=$PWD/mswindows/osgeo4w/lib \ - --with-gdal=$PWD/mswindows/osgeo4w/gdal-config \ - --with-geos=$PWD/mswindows/osgeo4w/geos-config \ + --with-proj-includes=$OSGEO4W_ROOT_MSYS/include \ + --with-proj-libs=$OSGEO4W_ROOT_MSYS/lib \ + --with-proj-share=$OSGEO4W_ROOT_MSYS/share/proj \ + --with-regex \ --with-sqlite \ --with-sqlite-includes=$OSGEO4W_ROOT_MSYS/include \ --with-sqlite-libs=$PWD/mswindows/osgeo4w/lib \ - --with-regex \ - --with-nls \ --with-zstd \ - --with-odbc \ - --with-netcdf=${OSGEO4W_ROOT_MSYS}/bin/nc-config \ - --with-blas \ - --with-lapack \ - --with-lapack-includes=/mingw64/include \ - --with-openmp \ - --with-cairo \ - --with-cairo-includes=$OSGEO4W_ROOT_MSYS/include \ - --with-cairo-ldflags="-L$PWD/mswindows/osgeo4w/lib -lcairo -lfontconfig" \ - --with-bzlib \ - --with-liblas=$PWD/mswindows/osgeo4w/liblas-config \ - --without-pdal + --without-pdal \ + --without-x touch mswindows/osgeo4w/configure-stamp fi diff --git a/package.nix b/package.nix index 3f1d03697c7..edf1e3e18a4 100644 --- a/package.nix +++ b/package.nix @@ -100,8 +100,8 @@ stdenv.mkDerivation (finalAttrs: { "--with-cxx" "--with-fftw" "--with-freetype" - "--with-geos" "--with-gdal" + "--with-geos" "--with-lapack" "--with-libsvm" "--with-nls" diff --git a/rpm/grass.spec b/rpm/grass.spec index 90c79bc939f..3e4675db621 100644 --- a/rpm/grass.spec +++ b/rpm/grass.spec @@ -1,8 +1,8 @@ -%global shortver 83 +%global shortver 84 %global macrosdir %(d=%{_rpmconfigdir}/macros.d; [ -d $d ] || d=%{_sysconfdir}/rpm; echo $d) Name: grass -Version: 8.3.0 +Version: 8.4.0 Release: 3%{?dist} Summary: GRASS GIS - Geographic Resources Analysis Support System @@ -37,64 +37,66 @@ BuildRequires: flexiblas-devel %else BuildRequires: blas-devel, lapack-devel %endif +BuildRequires: bzip2-devel BuildRequires: cairo-devel -BuildRequires: gcc-c++ BuildRequires: desktop-file-utils BuildRequires: fftw-devel BuildRequires: flex BuildRequires: freetype-devel +BuildRequires: gcc-c++ BuildRequires: gdal-devel BuildRequires: geos-devel BuildRequires: gettext BuildRequires: laszip-devel BuildRequires: libappstream-glib BuildRequires: libpng-devel +%if 0%{?rhel} && 0%{?rhel} == 7 +BuildRequires: postgresql-devel +%else +BuildRequires: libpq-devel +%endif BuildRequires: libtiff-devel BuildRequires: libXmu-devel -BuildRequires: mesa-libGL-devel -BuildRequires: mesa-libGLU-devel +BuildRequires: libzstd-devel +BuildRequires: make %if (0%{?rhel} > 7 || 0%{?fedora}) BuildRequires: mariadb-connector-c-devel openssl-devel %else BuildRequires: mysql-devel %endif +BuildRequires: mesa-libGL-devel +BuildRequires: mesa-libGLU-devel BuildRequires: netcdf-devel +BuildRequires: PDAL +BuildRequires: PDAL-devel +BuildRequires: PDAL-libs +BuildRequires: proj-devel BuildRequires: python3 %if 0%{?rhel} == 7 # EPEL7 -BuildRequires: python%{python3_version_nodots}-numpy -%else -BuildRequires: python3-numpy -%endif -%if 0%{?rhel} && 0%{?rhel} == 7 -BuildRequires: postgresql-devel +BuildRequires: python%{python3_version_nodots}-dateutil %else -BuildRequires: libpq-devel +BuildRequires: python3-dateutil %endif -BuildRequires: proj-devel +BuildRequires: python3-devel %if 0%{?rhel} == 7 # EPEL7 -BuildRequires: python%{python3_version_nodots}-dateutil +BuildRequires: python%{python3_version_nodots}-numpy %else -BuildRequires: python3-dateutil +BuildRequires: python3-numpy %endif -BuildRequires: python3-devel BuildRequires: python3-pillow -BuildRequires: PDAL -BuildRequires: PDAL-libs -BuildRequires: PDAL-devel BuildRequires: readline-devel BuildRequires: sqlite-devel BuildRequires: subversion BuildRequires: unixODBC-devel BuildRequires: zlib-devel -BuildRequires: bzip2-devel -BuildRequires: libzstd-devel -BuildRequires: make Requires: bzip2-libs -Requires: libzstd Requires: geos +Requires: libzstd +Requires: PDAL +Requires: PDAL-libs # fedora >= 34: Nothing %if (0%{?rhel} > 7 || 0%{?fedora} < 34) Requires: proj-datumgrid @@ -103,26 +105,23 @@ Requires: proj-datumgrid-world Requires: python3 %if 0%{?rhel} == 7 # EPEL7 -Requires: python%{python3_version_nodots}-numpy +Requires: python%{python3_version_nodots}-dateutil %else -Requires: python3-numpy +Requires: python3-dateutil %endif %if 0%{?rhel} == 7 # EPEL7 -Requires: python%{python3_version_nodots}-dateutil +Requires: python%{python3_version_nodots}-numpy %else -Requires: python3-dateutil +Requires: python3-numpy %endif Requires: python3-wxpython4 -Requires: PDAL -Requires: PDAL-libs %if "%{_lib}" == "lib" %global cpuarch 32 %else %global cpuarch 64 %endif - Requires: %{name}-libs%{?_isa} = %{version}-%{release} %description @@ -170,47 +169,50 @@ find -name \*.pl | xargs sed -i -e 's,#!/usr/bin/env perl,#!%{__perl},' %build %configure \ --prefix=%{_libdir} \ - --with-cxx \ - --with-tiff \ - --with-png \ - --with-postgres \ -%if 0%{?rhel} > 7 - --with-mysql=no \ -%else - --with-mysql \ -%endif - --with-opengl \ - --with-odbc \ - --with-fftw \ --with-blas \ - --with-lapack \ %if %{with flexiblas} --with-blas-includes=%{_includedir}/flexiblas \ - --with-lapack-includes=%{_includedir}/flexiblas \ %endif + --with-bzlib \ --with-cairo \ + --with-cairo-ldflags=-lfontconfig \ + --with-cxx \ + --with-fftw \ --with-freetype \ - --with-nls \ - --with-pdal \ - --with-readline \ - --with-regex \ - --with-openmp \ + --with-freetype-includes=%{_includedir}/freetype2 \ --with-gdal=%{_bindir}/gdal-config \ - --with-wxwidgets=%{_bindir}/wx-config \ --with-geos=%{_bindir}/geos-config \ - --with-netcdf=%{_bindir}/nc-config \ + --with-lapack \ +%if %{with flexiblas} + --with-lapack-includes=%{_includedir}/flexiblas \ +%endif +%if 0%{?rhel} > 7 + --with-mysql=no \ +%else + --with-mysql \ +%endif --with-mysql-includes=%{_includedir}/mysql \ %if (0%{?fedora} >= 27) --with-mysql-libs=%{_libdir} \ %else --with-mysql-libs=%{_libdir}/mysql \ %endif + --with-netcdf=%{_bindir}/nc-config \ + --with-nls \ + --with-odbc \ + --with-opengl \ + --with-openmp \ + --with-pdal \ + --with-png \ + --with-postgres \ --with-postgres-includes=%{_includedir}/pgsql \ - --with-cairo-ldflags=-lfontconfig \ - --with-freetype-includes=%{_includedir}/freetype2 \ - --with-bzlib \ - --with-zstd \ - --with-proj-share=%{_datadir}/proj + --with-proj-share=%{_datadir}/proj \ + --with-readline \ + --with-regex \ + --with-tiff \ + --with-wxwidgets=%{_bindir}/wx-config \ + --with-zstd + # .package_note hack for RHBZ #2084342 and RHBZ #2102895 sed -i "s+ -Wl,-dT,${RPM_BUILD_DIR}/grass-%{version}/.package_note-grass-%{version}-%{release}.%{_arch}.ld++g" include/Make/Platform.make @@ -338,6 +340,48 @@ fi %{_libdir}/%{name}%{shortver}/include %changelog +* Sat Oct 26 2024 Markus Neteler - 8.4.0-3 +- Sort requirements and flags (https://github.com/OSGeo/grass/pull/4563/ by Edouard Choinière) + +* Fri Sep 06 2024 Sandro Mani - 8.4.0-2 +- Rebuild (PDAL) + +* Sun Jul 28 2024 Markus Neteler - 8.4.0-1 +- Update to 8.4.0 + +* Thu Jul 18 2024 Fedora Release Engineering - 8.3.2-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild + +* Tue May 14 2024 Sandro Mani - 8.3.2-3 +- Rebuild (gdal) + +* Tue Mar 19 2024 Sandro Mani - 8.3.2-2 +- Rebuild (PDAL) + +* Thu Mar 07 2024 Markus Neteler - 8.3.2-1 +- Update to 8.3.2 (#2268514) + +* Wed Jan 24 2024 Fedora Release Engineering - 8.3.1-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Sat Jan 20 2024 Fedora Release Engineering - 8.3.1-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Wed Jan 3 2024 Florian Weimer - 8.3.1-4 +- Fix C compatibility issue in MySQL port handling + +* Wed Nov 15 2023 Sandro Mani - 8.3.1-3 +- Rebuild (gdal) + +* Sat Oct 28 2023 Markus Neteler 8.3.1-2 +- fix obsolete configure parameters + +* Thu Oct 26 2023 Fedora Release Monitoring - 8.3.1-1 +- Update to GRASS GIS 8.3.1 (#2246359) + +* Sat Oct 14 2023 Sandro Mani - 8.3.0-4 +- Rebuild (PDAL) + * Sun Aug 06 2023 Alexandre Detiste - 8.3.0-3 - Remove support for RHEL6: Grass is now Python3 only diff --git a/singularity/debian/singularityfile_debian b/singularity/debian/singularityfile_debian index 267d7a74ad5..5858bec6911 100644 --- a/singularity/debian/singularityfile_debian +++ b/singularity/debian/singularityfile_debian @@ -17,8 +17,8 @@ Singularity container for GRASS GIS to be run into GRASS main directory # Install useful libraries apt-get -y update apt-get -y install \ - build-essential \ bison \ + build-essential \ bzip2 \ cmake \ curl \ @@ -40,10 +40,10 @@ Singularity container for GRASS GIS to be run into GRASS main directory libgsl-dev \ libjpeg-dev \ libjsoncpp-dev \ + libncurses5-dev \ + libnetcdf-dev \ libopenblas-base \ libopenblas-dev \ - libnetcdf-dev \ - libncurses5-dev \ libopenjp2-7 \ libopenjp2-7-dev \ libpdal-dev \ @@ -94,29 +94,29 @@ Singularity container for GRASS GIS to be run into GRASS main directory GRASS_PYTHON=/usr/bin/python3 ./configure \ --enable-largefile \ - --with-cxx \ - --with-nls \ - --with-readline \ - --with-sqlite \ --with-bzlib \ - --with-zstd \ --with-cairo \ --with-cairo-ldflags=-lfontconfig \ + --with-cxx \ + --with-fftw \ --with-freetype \ --with-freetype-includes="/usr/include/freetype2/" \ - --with-fftw \ + --with-geos=/usr/bin/geos-config \ --with-netcdf \ + --with-nls \ --with-pdal \ - --with-proj \ - --with-proj-share=/usr/share/proj \ - --with-geos=/usr/bin/geos-config \ --with-postgres \ --with-postgres-includes="/usr/include/postgresql" \ + --with-proj \ + --with-proj-share=/usr/share/proj \ + --with-readline \ + --with-sqlite \ + --with-zstd \ + --without-ffmpeg \ --without-mysql \ --without-odbc \ - --without-openmp \ - --without-ffmpeg \ - --without-opengl + --without-opengl \ + --without-openmp make -j 2 && make install && ldconfig # Create generic GRASS GIS binary name regardless of version number ln -sf `find /usr/local/bin -name "grass??" | sort | tail -n 1` /usr/local/bin/grass diff --git a/utils/svn_name_git_author.csv b/utils/svn_name_git_author.csv index 4811a539a82..ba1ac70d21d 100644 --- a/utils/svn_name_git_author.csv +++ b/utils/svn_name_git_author.csv @@ -130,7 +130,6 @@ paul,Paul Kelly pcav,Paolo Cavallini pesekon2,Ondřej Pešek pierreroudier,Pierre Roudier -rodrigopitanga,Rodrigo Rodrigues Da Silva pkelly,Paul Kelly pmarcondes,Paulo Marcondes @@ -146,6 +145,7 @@ robertomarzocchi,Roberto Marzocchi roberto,Roberto Flor roberto,Roberto Micarelli Robifag,Roberta Fagandini +rodrigopitanga,Rodrigo Rodrigues Da Silva roger,Roger S. Miller rorschach,Ben Hur sbl,Stefan Blumentrath diff --git a/utils/svn_name_github_name.csv b/utils/svn_name_github_name.csv index 55504c24d67..97f0f859267 100644 --- a/utils/svn_name_github_name.csv +++ b/utils/svn_name_github_name.csv @@ -1,56 +1,56 @@ svn_name,github_name 1gray,1gray aghisla,aghisla -benjamin,benducke +annakrat,petrasovaa +barton,cmbarton benducke,benducke +benjamin,benducke bernhard,bernhardreiter -cnielsen,cdwren -pvanbosgeo,ecodiv -radim,blazek -barton,cmbarton -cmbarton,cmbarton -michael,cmbarton -mic,zwischenloesung -maciej,czka -msieczka,czka +cepicky,jachym +chemin,YannChemin +cho,HuidaeCho clements,glynnc +cmbarton,cmbarton +cnielsen,cdwren +frankw,warmerdam glynn,glynnc hamish,HamishB -hellik,hellik +hcho,HuidaeCho helena,hmitaso -soeren,huhabla +hellik,hellik huhabla,huhabla -cho,HuidaeCho -hcho,HuidaeCho +isaacullah,isaacullah jachym,jachym -cepicky,jachym -william,kyngchaos kyngchaos,kyngchaos landa,landam -martinl,landam ltoma,lauratoma lucadelu,lucadelu +maciej,czka madi,madi -mmetz,metzm +markus,neteler +martinl,landam +michael,cmbarton +mic,zwischenloesung mlennert,mlennert +mmetz,metzm moritz,mlennert -markus,neteler +msieczka,czka neteler,neteler nikosa,NikosAlexandris -sbl,ninsbl -turek,ostepok paulo,paulomarcondes -annakrat,petrasovaa +pvanbosgeo,ecodiv +radim,blazek rantolin,rantolin robertoa,rantolin +sbl,ninsbl sholl,sholl +soeren,huhabla stephan,sholl +turek,ostepok +ullah,isaacullah veroandreo,veroandreo -frankw,warmerdam warmerdam,warmerdam wenzeslaus,wenzeslaus -chemin,YannChemin +william,kyngchaos ychemin,YannChemin zarch,zarch -ullah,isaacullah -isaacullah,isaacullah diff --git a/utils/vagrant/compile.sh b/utils/vagrant/compile.sh index 058eb70b1f9..5e1abc01735 100755 --- a/utils/vagrant/compile.sh +++ b/utils/vagrant/compile.sh @@ -19,31 +19,31 @@ cd /vagrant if [ ! -f "include/Make/Platform.make" ] ; then ./configure \ --bindir=/usr/bin \ - --srcdir=/vagrant \ - --prefix=/usr/lib \ + --enable-largefile \ --enable-shared \ - --with-postgres \ - --with-mysql \ + --prefix=/usr/lib \ + --srcdir=/vagrant \ + --with-blas \ + --with-bzlib \ + --with-cairo \ --with-cxx \ - --with-x \ + --with-freetype \ + --with-freetype-includes=/usr/include/freetype2 \ --with-gdal \ --with-geos \ - --with-freetype \ - --with-readline \ + --with-lapack \ + --with-mysql \ + --with-mysql-includes=`mysql_config --include | sed -e 's/-I//'` \ + --with-netcdf \ --with-nls \ --with-odbc \ - --with-netcdf \ - --with-blas \ - --with-lapack \ - --with-sqlite \ - --enable-largefile \ - --with-freetype-includes=/usr/include/freetype2 \ + --with-postgres \ --with-postgres-includes=`pg_config --includedir` \ - --with-mysql-includes=`mysql_config --include | sed -e 's/-I//'` \ --with-proj-share=/usr/share/proj \ - --with-cairo \ --with-pthread \ - --with-bzlib \ + --with-readline \ + --with-sqlite \ + --with-x \ --without-pdal fi From 35ebcb33a3275f335f6a86b283e8d5a65676a4e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edouard=20Choini=C3=A8re?= <27212526+echoix@users.noreply.github.com> Date: Sun, 3 Nov 2024 10:59:24 -0500 Subject: [PATCH 18/57] python: Add typing to RPC server and Messenger (#4639) * grass.pygrass.rpc.base: Add typing annotations for lock and conn * grass.pygrass.rpc.base: Use context manager for lock in dummy_server * grass.pygrass.rpc.base: Use context manager for threadLock in RPCServerBase * grass.pygrass.rpc.base: Remove release lock in context manager * grass.pygrass.rpc.base: Add more typing annotations * grass.pygrass.rpc.base: Check for None to satisfy mypy type checking * grass.pygrass.rpc.base: Remove release lock in context managers, as they would be released when unlocked (RuntimeError: release unlocked lock) * grass.pygrass.rpc.base: Sort imports * grass.temporal.c_libraries_interface: Use context manager for lock in c_library_server * grass.temporal.c_libraries_interface: Add typing annotations for lock and conn * grass.pygrass.rpc.base: Change date of file header * grass.pygrass.rpc.base: Update docs of conn argument to mention that it is a multiprocessing.Connection object obtained from multiprocessing.Pipe * grass.temporal.c_libraries_interface: Change date of file header * grass.pygrass.rpc: Sort imports * grass.temporal.c_libraries_interface: Sort imports * Update docs of conn argument to mention that it is a multiprocessing.Connection object obtained from multiprocessing.Pipe * grass.pygrass.messages: Sort imports * Update docs of conn argument to mention that it is a multiprocessing.connection.Connection object obtained from multiprocessing.Pipe * grass.pygrass.rpc: Use context manager to acquire and release the lock * Fix typo in python/grass/pygrass/messages/testsuite/test_pygrass_messages_doctests.py * grass.pygrass.messages: Fix typo in message_server * grass.pygrass.messages: Missing "IMPORTANT" message type in message_server * grass.pygrass.messages: Add return type to get_msgr * grass.pygrass.messages: Add types to signatures in Messenger class and rest of file * grass.pygrass.messages: Use context manager for acquiring the lock in message_server() * grass.pygrass.messages: Add types to message_types to track missing conditions * grass.pygrass.messages: Extract message only for message_types where the variable is used * grass.pygrass.messages: Add parameter descriptions to percent(self, n, d, s) * grass.pygrass.messages: Initialize Messenger fields without setting them to None * grass.pygrass.messages: Fix typo * grass.pygrass.messages: Change date of file header --- python/grass/pygrass/messages/__init__.py | 158 +++++++++--------- .../test_pygrass_messages_doctests.py | 2 +- python/grass/pygrass/rpc/__init__.py | 29 ++-- python/grass/pygrass/rpc/base.py | 107 ++++++------ .../grass/temporal/c_libraries_interface.py | 108 +++++++----- 5 files changed, 223 insertions(+), 181 deletions(-) diff --git a/python/grass/pygrass/messages/__init__.py b/python/grass/pygrass/messages/__init__.py index 54d9af1b1c5..b5fe052883c 100644 --- a/python/grass/pygrass/messages/__init__.py +++ b/python/grass/pygrass/messages/__init__.py @@ -6,34 +6,45 @@ Fast and exit-safe interface to GRASS C-library message functions -(C) 2013 by the GRASS Development Team +(C) 2013-2024 by the GRASS Development Team This program is free software under the GNU General Public License (>=v2). Read the file COPYING that comes with GRASS for details. -@author Soeren Gebbert +@author Soeren Gebbert, Edouard Choinière """ +from __future__ import annotations + import sys -from multiprocessing import Process, Lock, Pipe +from multiprocessing import Lock, Pipe, Process +from typing import TYPE_CHECKING, Literal, NoReturn import grass.lib.gis as libgis - from grass.exceptions import FatalError +if TYPE_CHECKING: + from multiprocessing.connection import Connection + from multiprocessing.context import _LockLike + + _MessagesLiteral = Literal[ + "INFO", "IMPORTANT", "VERBOSE", "WARNING", "ERROR", "FATAL" + ] + -def message_server(lock, conn): +def message_server(lock: _LockLike, conn: Connection) -> NoReturn: """The GRASS message server function designed to be a target for multiprocessing.Process :param lock: A multiprocessing.Lock - :param conn: A multiprocessing.Pipe + :param conn: A multiprocessing.connection.Connection object obtained from + multiprocessing.Pipe This function will use the G_* message C-functions from grass.lib.gis to provide an interface to the GRASS C-library messaging system. - The data that is send through the pipe must provide an + The data that is sent through the pipe must provide an identifier string to specify which C-function should be called. The following identifiers are supported: @@ -52,9 +63,9 @@ def message_server(lock, conn): - "FATAL" Calls G_fatal_error(), this functions is only for testing purpose - The that is end through the pipe must be a list of values: + The data that is sent through the pipe must be a list of values: - - Messages: ["INFO|VERBOSE|WARNING|ERROR|FATAL", "MESSAGE"] + - Messages: ["INFO|IMPORTANT|VERBOSE|WARNING|ERROR|FATAL", "MESSAGE"] - Debug: ["DEBUG", level, "MESSAGE"] - Percent: ["PERCENT", n, d, s] @@ -65,44 +76,42 @@ def message_server(lock, conn): # Avoid busy waiting conn.poll(None) data = conn.recv() - message_type = data[0] + message_type: Literal[_MessagesLiteral, "DEBUG", "PERCENT", "STOP"] = data[0] # Only one process is allowed to write to stderr - lock.acquire() - - # Stop the pipe and the infinite loop - if message_type == "STOP": - conn.close() - lock.release() - libgis.G_debug(1, "Stop messenger server") - sys.exit() - - message = data[1] - - if message_type == "PERCENT": - n = int(data[1]) - d = int(data[2]) - s = int(data[3]) - libgis.G_percent(n, d, s) - elif message_type == "DEBUG": - level = data[1] - message = data[2] - libgis.G_debug(level, message) - elif message_type == "VERBOSE": - libgis.G_verbose_message(message) - elif message_type == "INFO": - libgis.G_message(message) - elif message_type == "IMPORTANT": - libgis.G_important_message(message) - elif message_type == "WARNING": - libgis.G_warning(message) - elif message_type == "ERROR": - libgis.G_important_message("ERROR: %s" % message) - # This is for testing only - elif message_type == "FATAL": - libgis.G_fatal_error(message) - - lock.release() + with lock: + # Stop the pipe and the infinite loop + if message_type == "STOP": + conn.close() + libgis.G_debug(1, "Stop messenger server") + sys.exit() + + if message_type == "PERCENT": + n = int(data[1]) + d = int(data[2]) + s = int(data[3]) + libgis.G_percent(n, d, s) + continue + if message_type == "DEBUG": + level = int(data[1]) + message_debug = data[2] + libgis.G_debug(level, message_debug) + continue + + message: str = data[1] + if message_type == "VERBOSE": + libgis.G_verbose_message(message) + elif message_type == "INFO": + libgis.G_message(message) + elif message_type == "IMPORTANT": + libgis.G_important_message(message) + elif message_type == "WARNING": + libgis.G_warning(message) + elif message_type == "ERROR": + libgis.G_important_message("ERROR: %s" % message) + # This is for testing only + elif message_type == "FATAL": + libgis.G_fatal_error(message) class Messenger: @@ -165,14 +174,19 @@ class Messenger: """ - def __init__(self, raise_on_error=False): - self.client_conn = None - self.server_conn = None - self.server = None + client_conn: Connection + server_conn: Connection + server: Process + + def __init__(self, raise_on_error: bool = False) -> None: self.raise_on_error = raise_on_error - self.start_server() + self.client_conn, self.server_conn = Pipe() + self.lock = Lock() + self.server = Process(target=message_server, args=(self.lock, self.server_conn)) + self.server.daemon = True + self.server.start() - def start_server(self): + def start_server(self) -> None: """Start the messenger server and open the pipe""" self.client_conn, self.server_conn = Pipe() self.lock = Lock() @@ -180,7 +194,7 @@ def start_server(self): self.server.daemon = True self.server.start() - def _check_restart_server(self): + def _check_restart_server(self) -> None: """Restart the server if it was terminated""" if self.server.is_alive() is True: return @@ -189,55 +203,50 @@ def _check_restart_server(self): self.start_server() self.warning("Needed to restart the messenger server") - def message(self, message): + def message(self, message: str) -> None: """Send a message to stderr :param message: the text of message - :type message: str G_message() will be called in the messenger server process """ self._check_restart_server() self.client_conn.send(["INFO", message]) - def verbose(self, message): + def verbose(self, message: str) -> None: """Send a verbose message to stderr :param message: the text of message - :type message: str G_verbose_message() will be called in the messenger server process """ self._check_restart_server() self.client_conn.send(["VERBOSE", message]) - def important(self, message): + def important(self, message: str) -> None: """Send an important message to stderr :param message: the text of message - :type message: str G_important_message() will be called in the messenger server process """ self._check_restart_server() self.client_conn.send(["IMPORTANT", message]) - def warning(self, message): + def warning(self, message: str) -> None: """Send a warning message to stderr :param message: the text of message - :type message: str G_warning() will be called in the messenger server process """ self._check_restart_server() self.client_conn.send(["WARNING", message]) - def error(self, message): + def error(self, message: str) -> None: """Send an error message to stderr :param message: the text of message - :type message: str G_important_message() with an additional "ERROR:" string at the start will be called in the messenger server process @@ -245,11 +254,10 @@ def error(self, message): self._check_restart_server() self.client_conn.send(["ERROR", message]) - def fatal(self, message): + def fatal(self, message: str) -> NoReturn: """Send an error message to stderr, call sys.exit(1) or raise FatalError :param message: the text of message - :type message: str This function emulates the behavior of G_fatal_error(). It prints an error message to stderr and calls sys.exit(1). If raise_on_error @@ -264,30 +272,29 @@ def fatal(self, message): raise FatalError(message) sys.exit(1) - def debug(self, level, message): + def debug(self, level: int, message: str) -> None: """Send a debug message to stderr :param message: the text of message - :type message: str G_debug() will be called in the messenger server process """ self._check_restart_server() self.client_conn.send(["DEBUG", level, message]) - def percent(self, n, d, s): + def percent(self, n: int, d: int, s: int) -> None: """Send a percentage to stderr - :param message: the text of message - :type message: str - + :param n: The current element + :param d: Total number of elements + :param s: Increment size G_percent() will be called in the messenger server process """ self._check_restart_server() self.client_conn.send(["PERCENT", n, d, s]) - def stop(self): + def stop(self) -> None: """Stop the messenger server and close the pipe""" if self.server is not None and self.server.is_alive(): self.client_conn.send( @@ -300,12 +307,11 @@ def stop(self): if self.client_conn is not None: self.client_conn.close() - def set_raise_on_error(self, raise_on_error=True): + def set_raise_on_error(self, raise_on_error: bool = True) -> None: """Set the fatal error behavior :param raise_on_error: if True a FatalError exception will be raised instead of calling sys.exit(1) - :type raise_on_error: bool - If raise_on_error == True, a FatalError exception will be raised if fatal() is called @@ -315,7 +321,7 @@ def set_raise_on_error(self, raise_on_error=True): """ self.raise_on_error = raise_on_error - def get_raise_on_error(self): + def get_raise_on_error(self) -> bool: """Get the fatal error behavior :returns: True if a FatalError exception will be raised or False if @@ -323,7 +329,7 @@ def get_raise_on_error(self): """ return self.raise_on_error - def test_fatal_error(self, message): + def test_fatal_error(self, message: str) -> None: """Force the messenger server to call G_fatal_error()""" import time @@ -338,7 +344,7 @@ def get_msgr( ], *args, **kwargs, -): +) -> Messenger: """Return a Messenger instance. :returns: the Messenger instance. diff --git a/python/grass/pygrass/messages/testsuite/test_pygrass_messages_doctests.py b/python/grass/pygrass/messages/testsuite/test_pygrass_messages_doctests.py index 72c20873cd6..67cd9cb3aed 100644 --- a/python/grass/pygrass/messages/testsuite/test_pygrass_messages_doctests.py +++ b/python/grass/pygrass/messages/testsuite/test_pygrass_messages_doctests.py @@ -28,7 +28,7 @@ def load_tests(loader, tests, ignore): # TODO: this must be somewhere when doctest is called, not here - # TODO: ultimate solution is not to use _ as a buildin in lib/python + # TODO: ultimate solution is not to use _ as a builtin in lib/python # for now it is the only place where it works grass.gunittest.utils.do_doctest_gettext_workaround() # this should be called at some top level diff --git a/python/grass/pygrass/rpc/__init__.py b/python/grass/pygrass/rpc/__init__.py index a6ab19b9369..e95c3453250 100644 --- a/python/grass/pygrass/rpc/__init__.py +++ b/python/grass/pygrass/rpc/__init__.py @@ -11,17 +11,18 @@ """ import sys -from multiprocessing import Process, Lock, Pipe from ctypes import CFUNCTYPE, c_void_p +from multiprocessing import Lock, Pipe, Process +import grass.lib.gis as libgis from grass.exceptions import FatalError +from grass.pygrass import utils +from grass.pygrass.gis.region import Region +from grass.pygrass.raster import RasterRow, raster2numpy_img from grass.pygrass.vector import VectorTopo from grass.pygrass.vector.basic import Bbox -from grass.pygrass.raster import RasterRow, raster2numpy_img -import grass.lib.gis as libgis + from .base import RPCServerBase -from grass.pygrass.gis.region import Region -from grass.pygrass import utils ############################################################################### ############################################################################### @@ -41,7 +42,8 @@ def _get_raster_image_as_np(lock, conn, data): a numpy array with RGB or Gray values. :param lock: A multiprocessing.Lock instance - :param conn: A multiprocessing.Pipe instance used to send True or False + :param conn: A multiprocessing.connection.Connection object obtained from + multiprocessing.Pipe used to send True or False :param data: The list of data entries [function_id, raster_name, extent, color] """ array = None @@ -87,7 +89,8 @@ def _get_vector_table_as_dict(lock, conn, data): """Get the table of a vector map layer as dictionary :param lock: A multiprocessing.Lock instance - :param conn: A multiprocessing.Pipe instance used to send True or False + :param conn: A multiprocessing.connection.Connection object obtained from + multiprocessing.Pipe used to send True or False :param data: The list of data entries [function_id, name, mapset, where] """ @@ -128,7 +131,8 @@ def _get_vector_features_as_wkb_list(lock, conn, data): point, centroid, line, boundary, area :param lock: A multiprocessing.Lock instance - :param conn: A multiprocessing.Pipe instance used to send True or False + :param conn: A multiprocessing.connection.Connection object obtained from + multiprocessing.Pipe used to send True or False :param data: The list of data entries [function_id,name,mapset,extent, feature_type, field] @@ -196,7 +200,8 @@ def data_provider_server(lock, conn): multiprocessing.Process :param lock: A multiprocessing.Lock - :param conn: A multiprocessing.Pipe + :param conn: A multiprocessing.connection.Connection object obtained from + multiprocessing.Pipe """ def error_handler(data): @@ -229,9 +234,8 @@ def error_handler(data): # Avoid busy waiting conn.poll(None) data = conn.recv() - lock.acquire() - functions[data[0]](lock, conn, data) - lock.release() + with lock: + functions[data[0]](lock, conn, data) test_vector_name = "data_provider_vector_map" @@ -461,6 +465,7 @@ def get_vector_features_as_wkb_list( if __name__ == "__main__": import doctest + from grass.pygrass.modules import Module Module("g.region", n=40, s=0, e=40, w=0, res=10) diff --git a/python/grass/pygrass/rpc/base.py b/python/grass/pygrass/rpc/base.py index 38cf48c1581..c436300c170 100644 --- a/python/grass/pygrass/rpc/base.py +++ b/python/grass/pygrass/rpc/base.py @@ -2,7 +2,7 @@ Fast and exit-safe interface to PyGRASS Raster and Vector layer using multiprocessing -(C) 2015 by the GRASS Development Team +(C) 2015-2024 by the GRASS Development Team This program is free software under the GNU General Public License (>=v2). Read the file COPYING that comes with GRASS for details. @@ -10,35 +10,42 @@ :authors: Soeren Gebbert """ -from grass.exceptions import FatalError -import time -import threading -import sys -from multiprocessing import Process, Lock, Pipe +from __future__ import annotations + import logging +import sys +import threading +import time +from multiprocessing import Lock, Pipe, Process +from typing import TYPE_CHECKING, NoReturn + +from grass.exceptions import FatalError + +if TYPE_CHECKING: + from multiprocessing.connection import Connection + from multiprocessing.synchronize import _LockLike ############################################################################### -def dummy_server(lock, conn): +def dummy_server(lock: _LockLike, conn: Connection) -> NoReturn: """Dummy server process :param lock: A multiprocessing.Lock - :param conn: A multiprocessing.Pipe + :param conn: A multiprocessing.connection.Connection object obtained from + multiprocessing.Pipe """ while True: # Avoid busy waiting conn.poll(None) data = conn.recv() - lock.acquire() - if data[0] == 0: - conn.close() - lock.release() - sys.exit() - if data[0] == 1: - raise Exception("Server process intentionally killed by exception") - lock.release() + with lock: + if data[0] == 0: + conn.close() + sys.exit() + if data[0] == 1: + raise Exception("Server process intentionally killed by exception") class RPCServerBase: @@ -82,12 +89,12 @@ class RPCServerBase: """ - def __init__(self): - self.client_conn = None - self.server_conn = None + def __init__(self) -> None: + self.client_conn: Connection | None = None + self.server_conn: Connection | None = None self.queue = None self.server = None - self.checkThread = None + self.checkThread: threading.Thread | None = None self.threadLock = threading.Lock() self.start_server() self.start_checker_thread() @@ -96,10 +103,10 @@ def __init__(self): # logging.basicConfig(level=logging.DEBUG) def is_server_alive(self): - return self.server.is_alive() + return self.server.is_alive() if self.server is not None else False def is_check_thread_alive(self): - return self.checkThread.is_alive() + return self.checkThread.is_alive() if self.checkThread is not None else False def start_checker_thread(self): if self.checkThread is not None and self.checkThread.is_alive(): @@ -111,21 +118,19 @@ def start_checker_thread(self): self.checkThread.start() def stop_checker_thread(self): - self.threadLock.acquire() - self.stopThread = True - self.threadLock.release() - self.checkThread.join(None) + with self.threadLock: + self.stopThread = True + if self.checkThread is not None: + self.checkThread.join(None) def thread_checker(self): """Check every 200 micro seconds if the server process is alive""" while True: time.sleep(0.2) self._check_restart_server(caller="Server check thread") - self.threadLock.acquire() - if self.stopThread is True: - self.threadLock.release() - return - self.threadLock.release() + with self.threadLock: + if self.stopThread is True: + return def start_server(self): """This function must be re-implemented in the subclasses""" @@ -140,24 +145,25 @@ def start_server(self): def check_server(self): self._check_restart_server() - def _check_restart_server(self, caller="main thread"): + def _check_restart_server(self, caller="main thread") -> None: """Restart the server if it was terminated""" logging.debug("Check libgis server restart") - self.threadLock.acquire() - if self.server.is_alive() is True: - self.threadLock.release() - return - self.client_conn.close() - self.server_conn.close() - self.start_server() - - if self.stopped is not True: - logging.warning( - "Needed to restart the libgis server, caller: {caller}", caller=caller - ) + with self.threadLock: + if self.server is not None and self.server.is_alive() is True: + return + if self.client_conn is not None: + self.client_conn.close() + if self.server_conn is not None: + self.server_conn.close() + self.start_server() + + if self.stopped is not True: + logging.warning( + "Needed to restart the libgis server, caller: {caller}", + caller=caller, + ) - self.threadLock.release() self.stopped = False def safe_receive(self, message): @@ -184,11 +190,12 @@ def stop(self): self.stop_checker_thread() if self.server is not None and self.server.is_alive(): - self.client_conn.send( - [ - 0, - ] - ) + if self.client_conn is not None: + self.client_conn.send( + [ + 0, + ] + ) self.server.terminate() if self.client_conn is not None: self.client_conn.close() diff --git a/python/grass/temporal/c_libraries_interface.py b/python/grass/temporal/c_libraries_interface.py index 0d24fc0f732..2b7f9f033f3 100644 --- a/python/grass/temporal/c_libraries_interface.py +++ b/python/grass/temporal/c_libraries_interface.py @@ -2,7 +2,7 @@ Fast and exit-safe interface to GRASS C-library functions using ctypes and multiprocessing -(C) 2013 by the GRASS Development Team +(C) 2013-2024 by the GRASS Development Team This program is free software under the GNU General Public License (>=v2). Read the file COPYING that comes with GRASS for details. @@ -10,11 +10,14 @@ :authors: Soeren Gebbert """ +from __future__ import annotations + import logging import sys from ctypes import CFUNCTYPE, POINTER, byref, c_int, c_void_p, cast from datetime import datetime from multiprocessing import Lock, Pipe, Process +from typing import TYPE_CHECKING import grass.lib.date as libdate import grass.lib.gis as libgis @@ -29,6 +32,10 @@ from grass.pygrass.vector import VectorTopo from grass.script.utils import encode +if TYPE_CHECKING: + from multiprocessing.connection import Connection + from multiprocessing.synchronize import _LockLike + ############################################################################### @@ -63,12 +70,13 @@ class RPCDefs: ############################################################################### -def _read_map_full_info(lock, conn, data): +def _read_map_full_info(lock: _LockLike, conn: Connection, data): """Read full map specific metadata from the spatial database using PyGRASS functions. :param lock: A multiprocessing.Lock instance - :param conn: A multiprocessing.Pipe instance used to send True or False + :param conn: A multiprocessing.connection.Connection object obtained from + multiprocessing.Pipe used to send True or False :param data: The list of data entries [function_id, maptype, name, mapset] """ info = None @@ -190,7 +198,7 @@ def _read_vector_full_info(name, mapset, layer=None): return info -def _fatal_error(lock, conn, data): +def _fatal_error(lock: _LockLike, conn: Connection, data): """Calls G_fatal_error()""" libgis.G_fatal_error("Fatal Error in C library server") @@ -198,11 +206,12 @@ def _fatal_error(lock, conn, data): ############################################################################### -def _get_mapset(lock, conn, data): +def _get_mapset(lock: _LockLike, conn: Connection, data): """Return the current mapset :param lock: A multiprocessing.Lock instance - :param conn: A multiprocessing.Pipe instance used to send True or False + :param conn: A multiprocessing.connection.Connection object obtained from + multiprocessing.Pipe used to send True or False :param data: The mapset as list entry 1 [function_id] :returns: Name of the current mapset @@ -214,11 +223,12 @@ def _get_mapset(lock, conn, data): ############################################################################### -def _get_location(lock, conn, data): +def _get_location(lock: _LockLike, conn: Connection, data): """Return the current location :param lock: A multiprocessing.Lock instance - :param conn: A multiprocessing.Pipe instance used to send True or False + :param conn: A multiprocessing.connection.Connection object obtained from + multiprocessing.Pipe used to send True or False :param data: The mapset as list entry 1 [function_id] :returns: Name of the location @@ -230,11 +240,12 @@ def _get_location(lock, conn, data): ############################################################################### -def _get_gisdbase(lock, conn, data): +def _get_gisdbase(lock: _LockLike, conn: Connection, data): """Return the current gisdatabase :param lock: A multiprocessing.Lock instance - :param conn: A multiprocessing.Pipe instance used to send True or False + :param conn: A multiprocessing.connection.Connection object obtained from + multiprocessing.Pipe used to send True or False :param data: The mapset as list entry 1 [function_id] :returns: Name of the gisdatabase @@ -246,11 +257,12 @@ def _get_gisdbase(lock, conn, data): ############################################################################### -def _get_driver_name(lock, conn, data): +def _get_driver_name(lock: _LockLike, conn: Connection, data): """Return the temporal database driver of a specific mapset :param lock: A multiprocessing.Lock instance - :param conn: A multiprocessing.Pipe instance used to send True or False + :param conn: A multiprocessing.connection.Connection object obtained from + multiprocessing.Pipe used to send True or False :param data: The mapset as list entry 1 [function_id, mapset] :returns: Name of the driver or None if no temporal database present @@ -264,11 +276,12 @@ def _get_driver_name(lock, conn, data): ############################################################################### -def _get_database_name(lock, conn, data): +def _get_database_name(lock: _LockLike, conn: Connection, data): """Return the temporal database name of a specific mapset :param lock: A multiprocessing.Lock instance - :param conn: A multiprocessing.Pipe instance used to send True or False + :param conn: A multiprocessing.connection.Connection object obtained from + multiprocessing.Pipe used to send True or False :param data: The mapset as list entry 1 [function_id, mapset] :returns: Name of the database or None if no temporal database present @@ -293,11 +306,12 @@ def _get_database_name(lock, conn, data): ############################################################################### -def _available_mapsets(lock, conn, data): +def _available_mapsets(lock: _LockLike, conn: Connection, data): """Return all available mapsets the user can access as a list of strings :param lock: A multiprocessing.Lock instance - :param conn: A multiprocessing.Pipe instance used to send True or False + :param conn: A multiprocessing.connection.Connection object obtained from + multiprocessing.Pipe used to send True or False :param data: The list of data entries [function_id] :returns: Names of available mapsets as list of strings @@ -349,12 +363,13 @@ def _available_mapsets(lock, conn, data): ############################################################################### -def _has_timestamp(lock, conn, data): +def _has_timestamp(lock: _LockLike, conn: Connection, data): """Check if the file based GRASS timestamp is present and send True or False using the provided pipe. :param lock: A multiprocessing.Lock instance - :param conn: A multiprocessing.Pipe instance used to send True or False + :param conn: A multiprocessing.connection.Connection object obtained from + multiprocessing.Pipe used to send True or False :param data: The list of data entries [function_id, maptype, name, mapset, layer] @@ -381,7 +396,7 @@ def _has_timestamp(lock, conn, data): ############################################################################### -def _read_timestamp(lock, conn, data): +def _read_timestamp(lock: _LockLike, conn: Connection, data): """Read the file based GRASS timestamp and send the result using the provided pipe. @@ -401,7 +416,8 @@ def _read_timestamp(lock, conn, data): The end time may be None in case of a time instance. :param lock: A multiprocessing.Lock instance - :param conn: A multiprocessing.Pipe instance used to send the result + :param conn: A multiprocessing.connection.Connection object obtained from + multiprocessing.Pipe used to send the result :param data: The list of data entries [function_id, maptype, name, mapset, layer] @@ -429,7 +445,7 @@ def _read_timestamp(lock, conn, data): ############################################################################### -def _write_timestamp(lock, conn, data): +def _write_timestamp(lock: _LockLike, conn: Connection, data): """Write the file based GRASS timestamp the return values of the called C-functions using the provided pipe. @@ -440,7 +456,8 @@ def _write_timestamp(lock, conn, data): values description. :param lock: A multiprocessing.Lock instance - :param conn: A multiprocessing.Pipe instance used to send True or False + :param conn: A multiprocessing.connection.Connection object obtained from + multiprocessing.Pipe used to send True or False :param data: The list of data entries [function_id, maptype, name, mapset, layer, timestring] """ @@ -473,7 +490,7 @@ def _write_timestamp(lock, conn, data): ############################################################################### -def _remove_timestamp(lock, conn, data): +def _remove_timestamp(lock: _LockLike, conn: Connection, data): """Remove the file based GRASS timestamp the return values of the called C-functions using the provided pipe. @@ -484,7 +501,8 @@ def _remove_timestamp(lock, conn, data): values description. :param lock: A multiprocessing.Lock instance - :param conn: A multiprocessing.Pipe instance used to send True or False + :param conn: A multiprocessing.connection.Connection object obtained from + multiprocessing.Pipe used to send True or False :param data: The list of data entries [function_id, maptype, name, mapset, layer] @@ -508,7 +526,7 @@ def _remove_timestamp(lock, conn, data): ############################################################################### -def _read_semantic_label(lock, conn, data): +def _read_semantic_label(lock: _LockLike, conn: Connection, data): """Read the file based GRASS band identifier the result using the provided pipe. @@ -516,7 +534,8 @@ def _read_semantic_label(lock, conn, data): Rast_read_semantic_label: either a semantic label string or None. :param lock: A multiprocessing.Lock instance - :param conn: A multiprocessing.Pipe instance used to send True or False + :param conn: A multiprocessing.connection.Connection object obtained from + multiprocessing.Pipe used to send True or False :param data: The list of data entries [function_id, maptype, name, mapset, layer, timestring] @@ -547,14 +566,15 @@ def _read_semantic_label(lock, conn, data): ############################################################################### -def _write_semantic_label(lock, conn, data): +def _write_semantic_label(lock: _LockLike, conn: Connection, data): """Write the file based GRASS band identifier. Rises ValueError on invalid semantic label. Always sends back True. :param lock: A multiprocessing.Lock instance - :param conn: A multiprocessing.Pipe instance used to send True or False + :param conn: A multiprocessing.connection.Connection object obtained from + multiprocessing.Pipe used to send True or False :param data: The list of data entries [function_id, maptype, name, mapset, layer, timestring] @@ -583,13 +603,14 @@ def _write_semantic_label(lock, conn, data): ############################################################################### -def _remove_semantic_label(lock, conn, data): +def _remove_semantic_label(lock: _LockLike, conn: Connection, data): """Remove the file based GRASS band identifier. The value to be send via pipe is the return value of G_remove_misc. :param lock: A multiprocessing.Lock instance - :param conn: A multiprocessing.Pipe instance used to send True or False + :param conn: A multiprocessing.connection.Connection object obtained from + multiprocessing.Pipe used to send True or False :param data: The list of data entries [function_id, maptype, name, mapset, layer, timestring] @@ -616,14 +637,15 @@ def _remove_semantic_label(lock, conn, data): ############################################################################### -def _map_exists(lock, conn, data): +def _map_exists(lock: _LockLike, conn: Connection, data): """Check if a map exists in the spatial database The value to be send via pipe is True in case the map exists and False if not. :param lock: A multiprocessing.Lock instance - :param conn: A multiprocessing.Pipe instance used to send True or False + :param conn: A multiprocessing.connection.Connection object obtained from + multiprocessing.Pipe used to send True or False :param data: The list of data entries [function_id, maptype, name, mapset] """ @@ -648,12 +670,13 @@ def _map_exists(lock, conn, data): ############################################################################### -def _read_map_info(lock, conn, data): +def _read_map_info(lock: _LockLike, conn: Connection, data): """Read map specific metadata from the spatial database using C-library functions :param lock: A multiprocessing.Lock instance - :param conn: A multiprocessing.Pipe instance used to send True or False + :param conn: A multiprocessing.connection.Connection object obtained from + multiprocessing.Pipe used to send True or False :param data: The list of data entries [function_id, maptype, name, mapset] """ kvp = None @@ -955,11 +978,12 @@ def _read_vector_info(name, mapset): ############################################################################### -def _read_map_history(lock, conn, data): +def _read_map_history(lock: _LockLike, conn: Connection, data): """Read map history from the spatial database using C-library functions :param lock: A multiprocessing.Lock instance - :param conn: A multiprocessing.Pipe instance used to send True or False + :param conn: A multiprocessing.connection.Connection object obtained from + multiprocessing.Pipe used to send True or False :param data: The list of data entries [function_id, maptype, name, mapset] """ kvp = None @@ -1174,7 +1198,7 @@ def _convert_timestamp_from_grass(ts): ############################################################################### -def _stop(lock, conn, data): +def _stop(lock: _LockLike, conn: Connection, data): libgis.G_debug(1, "Stop C-interface server") conn.close() lock.release() @@ -1184,12 +1208,13 @@ def _stop(lock, conn, data): ############################################################################### -def c_library_server(lock, conn): +def c_library_server(lock: _LockLike, conn: Connection): """The GRASS C-libraries server function designed to be a target for multiprocessing.Process :param lock: A multiprocessing.Lock - :param conn: A multiprocessing.Pipe + :param conn: A multiprocessing.connection.Connection object obtained from + multiprocessing.Pipe """ def error_handler(data): @@ -1239,9 +1264,8 @@ def error_handler(data): # Avoid busy waiting conn.poll(None) data = conn.recv() - lock.acquire() - functions[data[0]](lock, conn, data) - lock.release() + with lock: + functions[data[0]](lock, conn, data) class CLibrariesInterface(RPCServerBase): From d4bb783424e1799a3306f26e413dcfaa148de9bc Mon Sep 17 00:00:00 2001 From: Nicklas Larsson Date: Mon, 4 Nov 2024 23:29:36 +0100 Subject: [PATCH 19/57] CI: add expat dependency to macOS runner (#4646) --- .github/workflows/macos_dependencies.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/macos_dependencies.txt b/.github/workflows/macos_dependencies.txt index 8ef1d3460f6..28e680d3ae5 100644 --- a/.github/workflows/macos_dependencies.txt +++ b/.github/workflows/macos_dependencies.txt @@ -2,6 +2,7 @@ cairo clangxx_osx-arm64 clang_osx-arm64 cmake +expat fftw flex freetype From 7cd22e98da1fb58aeebb3de57b8c50d375dbe6e0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 5 Nov 2024 02:31:22 +0000 Subject: [PATCH 20/57] CI(deps): Update DeterminateSystems/nix-installer-action action to v15 (#4645) --- .github/workflows/test-nix.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-nix.yml b/.github/workflows/test-nix.yml index 43a1b5d40ab..6ce1285de9f 100644 --- a/.github/workflows/test-nix.yml +++ b/.github/workflows/test-nix.yml @@ -31,7 +31,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Install nix - uses: DeterminateSystems/nix-installer-action@da36cb69b1c3247ad7a1f931ebfd954a1105ef14 # v14 + uses: DeterminateSystems/nix-installer-action@b92f66560d6f97d6576405a7bae901ab57e72b6a # v15 - name: Setup cachix uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 From 847944e18e8c11f412e41c7767424f8ced6dbb3f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 5 Nov 2024 02:34:13 +0000 Subject: [PATCH 21/57] CI(deps): Lock file maintenance (#4643) --- flake.lock | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/flake.lock b/flake.lock index c507c1ec951..f36f65a6375 100644 --- a/flake.lock +++ b/flake.lock @@ -5,11 +5,11 @@ "nixpkgs-lib": "nixpkgs-lib" }, "locked": { - "lastModified": 1727826117, - "narHash": "sha256-K5ZLCyfO/Zj9mPFldf3iwS6oZStJcU4tSpiXTMYaaL0=", + "lastModified": 1730504689, + "narHash": "sha256-hgmguH29K2fvs9szpq2r3pz2/8cJd2LPS+b4tfNFCwE=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "3d04084d54bedc3d6b8b736c70ef449225c361b1", + "rev": "506278e768c2a08bec68eb62932193e341f55c90", "type": "github" }, "original": { @@ -19,11 +19,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1730045389, - "narHash": "sha256-4spSNTZ6h8Xmvrr9oqfuxc9jarasGj1QOcsgw8BfNd8=", + "lastModified": 1730272153, + "narHash": "sha256-B5WRZYsRlJgwVHIV6DvidFN7VX7Fg9uuwkRW9Ha8z+w=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "0fcb98acb6633445764dafe180e6833eb0f95208", + "rev": "2d2a9ddbe3f2c00747398f3dc9b05f7f2ebb0f53", "type": "github" }, "original": { @@ -35,14 +35,14 @@ }, "nixpkgs-lib": { "locked": { - "lastModified": 1727825735, - "narHash": "sha256-0xHYkMkeLVQAMa7gvkddbPqpxph+hDzdu1XdGPJR+Os=", + "lastModified": 1730504152, + "narHash": "sha256-lXvH/vOfb4aGYyvFmZK/HlsNsr/0CVWlwYvo2rxJk3s=", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/fb192fec7cc7a4c26d51779e9bab07ce6fa5597a.tar.gz" + "url": "https://github.com/NixOS/nixpkgs/archive/cc2f28000298e1269cea6612cd06ec9979dd5d7f.tar.gz" }, "original": { "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/fb192fec7cc7a4c26d51779e9bab07ce6fa5597a.tar.gz" + "url": "https://github.com/NixOS/nixpkgs/archive/cc2f28000298e1269cea6612cd06ec9979dd5d7f.tar.gz" } }, "root": { From 3307797b5b552b395cbf9761fc7ee515cfd33ada Mon Sep 17 00:00:00 2001 From: ShubhamDesai <42180509+ShubhamDesai@users.noreply.github.com> Date: Tue, 5 Nov 2024 02:59:38 -0500 Subject: [PATCH 22/57] lib/vector/Vlib: Fix Resource Leak issues in break_polygons.c (#4612) --- lib/vector/Vlib/break_polygons.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/vector/Vlib/break_polygons.c b/lib/vector/Vlib/break_polygons.c index 2b82d8eff62..1eb548f96c1 100644 --- a/lib/vector/Vlib/break_polygons.c +++ b/lib/vector/Vlib/break_polygons.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -131,11 +132,19 @@ void Vect_break_polygons_file(struct Map_info *Map, int type, filename = G_tempfile(); fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600); RTree = RTreeCreateTree(fd, 0, 2); - remove(filename); + (void)remove(filename); + G_free(filename); filename = G_tempfile(); xpntfd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600); - remove(filename); + if (xpntfd < 0) { + close(RTree->fd); + G_free(filename); + G_fatal_error(_("Failed to create xpnt temporary file: %s"), + strerror(errno)); + } + (void)remove(filename); + G_free(filename); BPoints = Vect_new_line_struct(); Points = Vect_new_line_struct(); @@ -651,6 +660,7 @@ void Vect_break_polygons_mem(struct Map_info *Map, int type, Vect_destroy_line_struct(Points); Vect_destroy_line_struct(BPoints); Vect_destroy_cats_struct(Cats); + Vect_destroy_cats_struct(ErrCats); G_verbose_message(_("Breaks: %d"), nbreaks); } From 0ad65e4ebd336ca43e21be8f1b38980552da3836 Mon Sep 17 00:00:00 2001 From: ShubhamDesai <42180509+ShubhamDesai@users.noreply.github.com> Date: Tue, 5 Nov 2024 03:03:07 -0500 Subject: [PATCH 23/57] v.delaunay: Fix Resource Leak issues in in_out.c (#4625) --- vector/v.delaunay/in_out.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vector/v.delaunay/in_out.c b/vector/v.delaunay/in_out.c index 8cc62cd8a0e..51938859847 100644 --- a/vector/v.delaunay/in_out.c +++ b/vector/v.delaunay/in_out.c @@ -178,6 +178,8 @@ void output_triangles(unsigned int n, int mode3d UNUSED, int type, e = NEXT(e, u); } while (!SAME_EDGE(e, e_start)); } + Vect_destroy_line_struct(Points); + Vect_destroy_cats_struct(Cats); } void remove_duplicates(unsigned int *size) From 7d878593c3fa3e8009e394097876a8a0812c13ec Mon Sep 17 00:00:00 2001 From: ShubhamDesai <42180509+ShubhamDesai@users.noreply.github.com> Date: Tue, 5 Nov 2024 03:06:44 -0500 Subject: [PATCH 24/57] lib/ogsf: Fix resource leak issue in gsd_img_tif.c (#4626) --- lib/ogsf/gsd_img_tif.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ogsf/gsd_img_tif.c b/lib/ogsf/gsd_img_tif.c index 47f9b4ebbc5..c2518bb8bea 100644 --- a/lib/ogsf/gsd_img_tif.c +++ b/lib/ogsf/gsd_img_tif.c @@ -116,6 +116,7 @@ int GS_write_tif(const char *name) } G_free((void *)pixbuf); + G_free(buf); (void)TIFFClose(out); return (0); From baf93a5c43e36363d2698440fcd419f07d3eb59b Mon Sep 17 00:00:00 2001 From: Nicklas Larsson Date: Tue, 5 Nov 2024 13:32:47 +0100 Subject: [PATCH 25/57] r.viewshed: address -Wunused-value warnings (#4609) --- raster/r.viewshed/grass.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/raster/r.viewshed/grass.cpp b/raster/r.viewshed/grass.cpp index 89d2879db0d..6ab70e4d9e2 100644 --- a/raster/r.viewshed/grass.cpp +++ b/raster/r.viewshed/grass.cpp @@ -450,6 +450,7 @@ AMI_STREAM *init_event_list(char *rastName, Viewpoint *vp, Rast_set_null_value(inrast[2], ncols, data_type); /*scan through the raster data */ + // int isnull = 0; dimensionType i, j; double ax, ay; AEvent e; @@ -483,7 +484,7 @@ AMI_STREAM *init_event_list(char *rastName, Viewpoint *vp, e.col = j; /*read the elevation value into the event */ - Rast_is_null_value(&(inrast[1][j]), data_type); + // isnull = Rast_is_null_value(&(inrast[1][j]), data_type); e.elev[1] = inrast[1][j]; /* adjust for curvature */ @@ -971,18 +972,19 @@ void save_io_vis_and_elev_to_GRASS(IOVisibilityGrid *visgrid, char *elevfname, for (j = 0; j < Rast_window_cols(); j++) { /* read the current elevation value */ + // int isNull = 0; switch (elev_data_type) { case CELL_TYPE: - Rast_is_c_null_value(&((CELL *)elevrast)[j]); + // isNull = Rast_is_c_null_value(&((CELL *)elevrast)[j]); elev = (double)(((CELL *)elevrast)[j]); break; case FCELL_TYPE: - Rast_is_f_null_value(&((FCELL *)elevrast)[j]); + // isNull = Rast_is_f_null_value(&((FCELL *)elevrast)[j]); elev = (double)(((FCELL *)elevrast)[j]); break; case DCELL_TYPE: - Rast_is_d_null_value(&((DCELL *)elevrast)[j]); + // isNull = Rast_is_d_null_value(&((DCELL *)elevrast)[j]); elev = (double)(((DCELL *)elevrast)[j]); break; } From 16c5f6fef8aa6958d50c172cb32f37e4b04301d2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 5 Nov 2024 07:38:34 -0500 Subject: [PATCH 26/57] CI(deps): Update mamba-org/setup-micromamba action to v2.0.1 (#4648) --- .github/workflows/macos.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index cdc02ad1432..466a61967b7 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -50,7 +50,7 @@ jobs: # Year and week of year so cache key changes weekly run: echo "date=$(date +%Y-%U)" >> "${GITHUB_OUTPUT}" - name: Setup Mamba - uses: mamba-org/setup-micromamba@617811f69075e3fd3ae68ca64220ad065877f246 # v2.0.0 + uses: mamba-org/setup-micromamba@ab6bf8bf7403e8023a094abeec19d6753bdc143e # v2.0.1 with: init-shell: bash environment-file: .github/workflows/macos_dependencies.txt From f7537c41c00dbf9f5e5253aca412c1e4100d4a99 Mon Sep 17 00:00:00 2001 From: Mohan Yelugoti Date: Tue, 5 Nov 2024 09:30:35 -0500 Subject: [PATCH 27/57] lib/ogsf: fix possible overflow errors in gsd_surf.c (#4635) ogsf: fix possible overflow errors in gsd modules In a lot of places, `(255 << 24)` which causes integer overflow and positive number gets converted to negative number. We were then assigning this to an unsigned integer in multiple places, which does conversion in a different way. For example: If we do unsigned int x = -20, `UINT_MAX + 1 - 20` is assigned to x. I do not think that's what is intended when we do `ktrans = (255 << 24)`. Fix instances of that, by using an unsigned int literal over int literal. This issue was found using cppcheck tool. Signed-off-by: Mohan Yelugoti --- lib/ogsf/gsd_surf.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/ogsf/gsd_surf.c b/lib/ogsf/gsd_surf.c index d22e17a8918..ae7c9d5dd49 100644 --- a/lib/ogsf/gsd_surf.c +++ b/lib/ogsf/gsd_surf.c @@ -228,7 +228,7 @@ int gsd_surf_map_old(geosurf *surf) */ check_transp = 0; tratt = &(surf->att[ATT_TRANSP]); - ktrans = (255 << 24); + ktrans = (255U << 24); trans_src = surf->att[ATT_TRANSP].att_src; if (CONST_ATT == trans_src && surf->att[ATT_TRANSP].constant != 0.0) { @@ -344,7 +344,7 @@ int gsd_surf_map_old(geosurf *surf) if (check_transp) { GET_MAPATT(trbuff, offset, ttr); ktrans = (char)SCALE_ATT(tratt, ttr, 0, 255); - ktrans = (char)(255 - ktrans) << 24; + ktrans = (char)(255U - ktrans) << 24; } gsd_litvert_func(n, ktrans | curcolor, pt); @@ -369,7 +369,7 @@ int gsd_surf_map_old(geosurf *surf) if (check_transp) { GET_MAPATT(trbuff, offset, ttr); ktrans = (char)SCALE_ATT(tratt, ttr, 0, 255); - ktrans = (char)(255 - ktrans) << 24; + ktrans = (char)(255U - ktrans) << 24; } if (check_material) { @@ -469,7 +469,7 @@ int gsd_surf_map_old(geosurf *surf) if (check_transp) { GET_MAPATT(trbuff, offset, ttr); ktrans = (char)SCALE_ATT(tratt, ttr, 0, 255); - ktrans = (char)(255 - ktrans) << 24; + ktrans = (char)(255U - ktrans) << 24; } if (check_material) { @@ -524,7 +524,7 @@ int gsd_surf_map_old(geosurf *surf) if (check_transp) { GET_MAPATT(trbuff, offset, ttr); ktrans = (char)SCALE_ATT(tratt, ttr, 0, 255); - ktrans = (char)(255 - ktrans) << 24; + ktrans = (char)(255U - ktrans) << 24; } if (check_material) { @@ -580,7 +580,7 @@ int gsd_surf_map_old(geosurf *surf) if (check_transp) { GET_MAPATT(trbuff, offset, ttr); ktrans = (char)SCALE_ATT(tratt, ttr, 0, 255); - ktrans = (char)(255 - ktrans) << 24; + ktrans = (char)(255U - ktrans) << 24; } if (check_material) { @@ -649,7 +649,7 @@ int gsd_surf_map_old(geosurf *surf) if (check_transp) { GET_MAPATT(trbuff, offset, ttr); ktrans = (char)SCALE_ATT(tratt, ttr, 0, 255); - ktrans = (char)(255 - ktrans) << 24; + ktrans = (char)(255U - ktrans) << 24; } if (check_material) { @@ -2144,7 +2144,7 @@ int gsd_surf_map(geosurf *surf) */ check_transp = 0; tratt = &(surf->att[ATT_TRANSP]); - ktrans = (255 << 24); + ktrans = (255U << 24); trans_src = surf->att[ATT_TRANSP].att_src; if (CONST_ATT == trans_src && surf->att[ATT_TRANSP].constant != 0.0) { @@ -2328,7 +2328,7 @@ int gsd_surf_map(geosurf *surf) if (check_transp) { GET_MAPATT(trbuff, offset2[ii], ttr); ktrans = (char)SCALE_ATT(tratt, ttr, 0, 255); - ktrans = (char)(255 - ktrans) << 24; + ktrans = (char)(255U - ktrans) << 24; } if (check_material) { From 4854f491a00d482bfaad1817113c39f4b90fb06f Mon Sep 17 00:00:00 2001 From: ShubhamDesai <42180509+ShubhamDesai@users.noreply.github.com> Date: Tue, 5 Nov 2024 09:31:05 -0500 Subject: [PATCH 28/57] lib/vector/Vlib: Fix resource leak issue in clean_nodes.c (#4627) fix resource leak issue Co-authored-by: Shubham Vasudeo Desai --- lib/vector/Vlib/clean_nodes.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/vector/Vlib/clean_nodes.c b/lib/vector/Vlib/clean_nodes.c index bff6d502129..2ba34985549 100644 --- a/lib/vector/Vlib/clean_nodes.c +++ b/lib/vector/Vlib/clean_nodes.c @@ -241,6 +241,10 @@ int Vect_clean_small_angles_at_nodes(struct Map_info *Map, int otype, } } G_verbose_message(_("Modifications: %d"), nmodif); + Vect_destroy_line_struct(Points); + Vect_destroy_cats_struct(OCats); + Vect_destroy_cats_struct(LCats); + Vect_destroy_cats_struct(SCats); return (nmodif); } From c1d855738a428be4d55a7dfbae7f97c3ed0c3f05 Mon Sep 17 00:00:00 2001 From: Mohan Yelugoti Date: Tue, 5 Nov 2024 09:31:35 -0500 Subject: [PATCH 29/57] lib/ogsf: fix possible overflow errors in gvld.c (#4637) ogsf: fix possible overflow errors in gvld module We were doing `(255 << 24)` which causes integer overflow and positive number gets converted to negative number. We were then assigning this to an unsigned integer in multiple places, which does conversion in a different way. For example: If we do unsigned int x = -20, `UINT_MAX + 1 - 20` is assigned to x. I do not think that's what is intended when we do `ktrans = (255 << 24)`. Fix instances of that, by using an unsigned int literal over int literal. This issue was found using cppcheck tool. Signed-off-by: Mohan Yelugoti --- lib/ogsf/gvld.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ogsf/gvld.c b/lib/ogsf/gvld.c index 91734eaac49..9c0831b5bcd 100644 --- a/lib/ogsf/gvld.c +++ b/lib/ogsf/gvld.c @@ -188,7 +188,7 @@ int gvld_isosurf(geovol *gvl) /* transparency */ check_transp[i] = 0; - ktrans[i] = (255 << 24); + ktrans[i] = (255U << 24); if (CONST_ATT == isosurf->att[ATT_TRANSP].att_src && isosurf->att[ATT_TRANSP].constant != 0.0) { ktrans[i] = (255 - (int)isosurf->att[ATT_TRANSP].constant) << 24; From 206cabcbb7275debed2bcdd9c1a3869ab58552fc Mon Sep 17 00:00:00 2001 From: Mohan Yelugoti Date: Tue, 5 Nov 2024 09:32:14 -0500 Subject: [PATCH 30/57] lib/ogsf: fix possible overflow errors in gsd_wire.c (#4636) ogsf: fix possible overflow errors in gsd_wire In a code, we were doing `(255 << 24)` which causes integer overflow and positive number gets converted to negative number. We were then assigning this to an unsigned integer in multiple places, which does conversion in a different way. For example: If we do `unsigned int x = -20`, `UINT_MAX + 1 - 20` is assigned to x. I do not think that's what is intended when we do with `ktrans = (255 << 24)`. Fix instances of that, by using an `unsigned int literal` over `int literal`. This issue was found using cppcheck tool. Signed-off-by: Mohan Yelugoti --- lib/ogsf/gsd_wire.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ogsf/gsd_wire.c b/lib/ogsf/gsd_wire.c index 0da492b9b15..1b3b8e6c084 100644 --- a/lib/ogsf/gsd_wire.c +++ b/lib/ogsf/gsd_wire.c @@ -645,7 +645,7 @@ int gsd_coarse_surf_map(geosurf *surf) */ check_transp = 0; tratt = &(surf->att[ATT_TRANSP]); - ktrans = (255 << 24); + ktrans = (255U << 24); trans_src = surf->att[ATT_TRANSP].att_src; if (CONST_ATT == trans_src && surf->att[ATT_TRANSP].constant != 0.0) { @@ -798,7 +798,7 @@ int gsd_coarse_surf_map(geosurf *surf) if (check_transp) { GET_MAPATT(trbuff, offset2[ii], ttr); ktrans = (char)SCALE_ATT(tratt, ttr, 0, 255); - ktrans = (char)(255 - ktrans) << 24; + ktrans = (char)(255U - ktrans) << 24; } if (check_material) { From 039183d9be2c1baf6e63fc07f6554fe6c2a06276 Mon Sep 17 00:00:00 2001 From: Nishant Bansal <103022832+NishantBansal2003@users.noreply.github.com> Date: Tue, 5 Nov 2024 20:36:43 +0530 Subject: [PATCH 31/57] v.info: add json output for columns (#4590) --- vector/v.info/local_proto.h | 3 +- vector/v.info/main.c | 12 ++-- vector/v.info/print.c | 88 +++++++++++++++++++++++---- vector/v.info/testsuite/test_vinfo.py | 21 +++++++ 4 files changed, 106 insertions(+), 18 deletions(-) diff --git a/vector/v.info/local_proto.h b/vector/v.info/local_proto.h index 1ed32468562..b1a7d5795cb 100644 --- a/vector/v.info/local_proto.h +++ b/vector/v.info/local_proto.h @@ -19,7 +19,8 @@ void parse_args(int, char **, char **, char **, int *, int *, int *, void format_double(double, char *); void print_region(struct Map_info *, enum OutputFormat, JSON_Object *); void print_topo(struct Map_info *, enum OutputFormat, JSON_Object *); -void print_columns(struct Map_info *, const char *, const char *); +void print_columns(struct Map_info *, const char *, const char *, + enum OutputFormat); void print_info(struct Map_info *); void print_shell(struct Map_info *, const char *, enum OutputFormat, JSON_Object *); diff --git a/vector/v.info/main.c b/vector/v.info/main.c index 6f4aa9a8fcf..ef1f5c44d06 100644 --- a/vector/v.info/main.c +++ b/vector/v.info/main.c @@ -54,11 +54,6 @@ int main(int argc, char *argv[]) parse_args(argc, argv, &input_opt, &field_opt, &hist_flag, &col_flag, &shell_flag, &format); - if (format == JSON) { - root_value = json_value_init_object(); - root_object = json_value_get_object(root_value); - } - /* try to open head-only on level 2 */ if (Vect_open_old_head2(&Map, input_opt, "", field_opt) < 2) { /* force level 1, open fully @@ -85,13 +80,18 @@ int main(int argc, char *argv[]) } } else if (col_flag) { - print_columns(&Map, input_opt, field_opt); + print_columns(&Map, input_opt, field_opt, format); } Vect_close(&Map); return (EXIT_SUCCESS); } + if (format == JSON) { + root_value = json_value_init_object(); + root_object = json_value_get_object(root_value); + } + if ((shell_flag & SHELL_BASIC) || format == JSON) { print_shell(&Map, field_opt, format, root_object); } diff --git a/vector/v.info/print.c b/vector/v.info/print.c index 6c36d6391f6..ae913bf2e3d 100644 --- a/vector/v.info/print.c +++ b/vector/v.info/print.c @@ -176,7 +176,7 @@ void print_topo(struct Map_info *Map, enum OutputFormat format, } void print_columns(struct Map_info *Map, const char *input_opt, - const char *field_opt) + const char *field_opt, enum OutputFormat format) { int num_dblinks, col, ncols; @@ -189,6 +189,7 @@ void print_columns(struct Map_info *Map, const char *input_opt, num_dblinks = Vect_get_num_dblinks(Map); if (num_dblinks <= 0) { + Vect_close(Map); G_fatal_error( _("Database connection for map <%s> is not defined in DB file"), input_opt); @@ -198,32 +199,97 @@ void print_columns(struct Map_info *Map, const char *input_opt, "layer <%s>:"), field_opt); - if ((fi = Vect_get_field2(Map, field_opt)) == NULL) + if ((fi = Vect_get_field2(Map, field_opt)) == NULL) { + Vect_close(Map); G_fatal_error( _("Database connection not defined for layer <%s> of <%s>"), field_opt, input_opt); + } driver = db_start_driver(fi->driver); - if (driver == NULL) + if (driver == NULL) { + Vect_close(Map); G_fatal_error(_("Unable to open driver <%s>"), fi->driver); + } db_init_handle(&handle); db_set_handle(&handle, fi->database, NULL); - if (db_open_database(driver, &handle) != DB_OK) + if (db_open_database(driver, &handle) != DB_OK) { + db_shutdown_driver(driver); + Vect_close(Map); G_fatal_error(_("Unable to open database <%s> by driver <%s>"), fi->database, fi->driver); + } db_init_string(&table_name); db_set_string(&table_name, fi->table); - if (db_describe_table(driver, &table_name, &table) != DB_OK) + if (db_describe_table(driver, &table_name, &table) != DB_OK) { + db_close_database_shutdown_driver(driver); + Vect_close(Map); G_fatal_error(_("Unable to describe table <%s>"), fi->table); + } + + JSON_Value *root_value = NULL, *columns_value = NULL, *column_value = NULL; + JSON_Object *root_object = NULL, *column_object = NULL; + JSON_Array *columns_array = NULL; + + if (format == JSON) { + root_value = json_value_init_object(); + root_object = json_object(root_value); + columns_value = json_value_init_array(); + columns_array = json_array(columns_value); + json_object_set_value(root_object, "columns", columns_value); + } ncols = db_get_table_number_of_columns(table); - for (col = 0; col < ncols; col++) - fprintf(stdout, "%s|%s\n", - db_sqltype_name( - db_get_column_sqltype(db_get_table_column(table, col))), + for (col = 0; col < ncols; col++) { + switch (format) { + case SHELL: + break; + + case JSON: + column_value = json_value_init_object(); + column_object = json_object(column_value); + + json_object_set_string( + column_object, "name", db_get_column_name(db_get_table_column(table, col))); - db_close_database(driver); - db_shutdown_driver(driver); + int sql_type = + db_get_column_sqltype(db_get_table_column(table, col)); + json_object_set_string(column_object, "sql_type", + db_sqltype_name(sql_type)); + + int c_type = db_sqltype_to_Ctype(sql_type); + json_object_set_boolean( + column_object, "is_number", + (c_type == DB_C_TYPE_INT || c_type == DB_C_TYPE_DOUBLE)); + + json_array_append_value(columns_array, column_value); + break; + + case PLAIN: + fprintf(stdout, "%s|%s\n", + db_sqltype_name( + db_get_column_sqltype(db_get_table_column(table, col))), + db_get_column_name(db_get_table_column(table, col))); + break; + } + } + + if (format == JSON) { + char *serialized_string = NULL; + serialized_string = json_serialize_to_string_pretty(root_value); + if (serialized_string == NULL) { + json_value_free(root_value); + db_close_database_shutdown_driver(driver); + Vect_close(Map); + G_fatal_error(_("Failed to initialize pretty JSON string.")); + } + puts(serialized_string); + json_free_serialized_string(serialized_string); + json_value_free(root_value); + } + + Vect_destroy_field_info(fi); + db_close_database_shutdown_driver(driver); } void print_shell(struct Map_info *Map, const char *field_opt, diff --git a/vector/v.info/testsuite/test_vinfo.py b/vector/v.info/testsuite/test_vinfo.py index c8183f76412..366859aebae 100644 --- a/vector/v.info/testsuite/test_vinfo.py +++ b/vector/v.info/testsuite/test_vinfo.py @@ -250,6 +250,27 @@ def test_json(self): result.pop(field) self.assertDictEqual(expected, result) + def test_json_column(self): + module = SimpleModule( + "v.info", map=self.test_vinfo_with_db_3d, format="json", flags="c" + ) + self.runModule(module) + + expected_json = { + "columns": [ + {"is_number": True, "name": "cat", "sql_type": "INTEGER"}, + { + "is_number": True, + "name": "elevation", + "sql_type": "DOUBLE PRECISION", + }, + ] + } + + result = json.loads(module.outputs.stdout) + + self.assertDictEqual(expected_json, result) + def test_database_table(self): """Test the database table column and type of the two vector maps with attribute data""" self.assertModuleKeyValue( From f15230d4268166d050086fcf44d2959eed545f58 Mon Sep 17 00:00:00 2001 From: Anna Petrasova Date: Tue, 5 Nov 2024 18:33:15 -0500 Subject: [PATCH 32/57] GUI: fix for Python3.13 (#4653) --- gui/wxpython/core/gconsole.py | 34 ++++++++++++++++++++-------------- gui/wxpython/core/gthread.py | 18 +++++++++++------- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/gui/wxpython/core/gconsole.py b/gui/wxpython/core/gconsole.py index 5b58c08cc55..cde41710cd9 100644 --- a/gui/wxpython/core/gconsole.py +++ b/gui/wxpython/core/gconsole.py @@ -120,6 +120,14 @@ def SetId(self, id): def run(self): os.environ["GRASS_MESSAGE_FORMAT"] = "gui" while True: + variables = { + "callable": None, + "onDone": None, + "onPrepare": None, + "userData": None, + "addLayer": None, + "notification": None, + } requestId, args, kwds = self.requestQ.get() for key in ( "callable", @@ -130,13 +138,11 @@ def run(self): "notification", ): if key in kwds: - vars()[key] = kwds[key] + variables[key] = kwds[key] del kwds[key] - else: - vars()[key] = None - if not vars()["callable"]: - vars()["callable"] = GrassCmd + if not variables["callable"]: + variables["callable"] = GrassCmd requestTime = time.time() @@ -146,21 +152,21 @@ def run(self): cmd=args[0], time=requestTime, pid=requestId, - onPrepare=vars()["onPrepare"], - userData=vars()["userData"], + onPrepare=variables["onPrepare"], + userData=variables["userData"], ) wx.PostEvent(self.receiver, event) # run command event = wxCmdRun( - cmd=args[0], pid=requestId, notification=vars()["notification"] + cmd=args[0], pid=requestId, notification=variables["notification"] ) wx.PostEvent(self.receiver, event) time.sleep(0.1) - self.requestCmd = vars()["callable"](*args, **kwds) + self.requestCmd = variables["callable"](*args, **kwds) if self._want_abort_all and self.requestCmd is not None: self.requestCmd.abort() if self.requestQ.empty(): @@ -211,7 +217,7 @@ def run(self): "map=%s" % mapName, "color=%s" % colorTable, ] - self.requestCmdColor = vars()["callable"](*argsColor, **kwds) + self.requestCmdColor = variables["callable"](*argsColor, **kwds) self.resultQ.put((requestId, self.requestCmdColor.run())) if self.receiver: @@ -221,10 +227,10 @@ def run(self): returncode=returncode, time=requestTime, pid=requestId, - onDone=vars()["onDone"], - userData=vars()["userData"], - addLayer=vars()["addLayer"], - notification=vars()["notification"], + onDone=variables["onDone"], + userData=variables["userData"], + addLayer=variables["addLayer"], + notification=variables["notification"], ) # send event diff --git a/gui/wxpython/core/gthread.py b/gui/wxpython/core/gthread.py index 3437d04bf56..3e1eae86623 100644 --- a/gui/wxpython/core/gthread.py +++ b/gui/wxpython/core/gthread.py @@ -86,21 +86,25 @@ def SetId(self, id): gThread.requestId = id def run(self): + variables = { + "callable": None, + "ondone": None, + "userdata": None, + "onterminate": None, + } while True: requestId, args, kwds = self.requestQ.get() for key in ("callable", "ondone", "userdata", "onterminate"): if key in kwds: - vars()[key] = kwds[key] + variables[key] = kwds[key] del kwds[key] - else: - vars()[key] = None ret = None exception = None time.sleep(0.01) self._terminate_evt = wxThdTerminate( - onterminate=vars()["onterminate"], + onterminate=variables["onterminate"], kwds=kwds, args=args, pid=requestId, @@ -109,7 +113,7 @@ def run(self): if self.terminate: return - ret = vars()["callable"](*args, **kwds) + ret = variables["callable"](*args, **kwds) if self.terminate: return @@ -119,12 +123,12 @@ def run(self): self.resultQ.put((requestId, ret)) event = wxCmdDone( - ondone=vars()["ondone"], + ondone=variables["ondone"], kwds=kwds, args=args, # TODO expand args to kwds ret=ret, exception=exception, - userdata=vars()["userdata"], + userdata=variables["userdata"], pid=requestId, ) From 760d763d9ee991a43d9ed34e1a37d15a5bf3f19b Mon Sep 17 00:00:00 2001 From: Nishant Bansal <103022832+NishantBansal2003@users.noreply.github.com> Date: Wed, 6 Nov 2024 05:05:37 +0530 Subject: [PATCH 33/57] r.colors.out: Add JSON support (#4555) * r.colors.out: added json output Signed-off-by: Nishant Bansal * fixed CI build issues Signed-off-by: Nishant Bansal * refactor code Signed-off-by: Nishant Bansal * added more color formats and tests Signed-off-by: Nishant Bansal * additional changes based on review Signed-off-by: Nishant Bansal * fixes prototype declaration Signed-off-by: Nishant Bansal * fixes test Signed-off-by: Nishant Bansal * added option instead of flags Signed-off-by: Nishant Bansal * Add a standard parser option for color formatting Signed-off-by: Nishant Bansal * added changes based on review Signed-off-by: Nishant Bansal * fixes function name Signed-off-by: Nishant Bansal * fixes pytest failure Signed-off-by: Nishant Bansal * Update lib/gis/parser_standard_options.c --------- Signed-off-by: Nishant Bansal --- general/g.parser/standard_option.c | 1 + include/grass/gis.h | 5 +- lib/gis/parser_standard_options.c | 17 ++ raster/r.colors.out/Makefile | 8 +- raster/r.colors.out/local_proto.h | 7 + raster/r.colors.out/prt_json.c | 265 ++++++++++++++++++ raster/r.colors.out/r.colors.out.html | 1 + raster/r.colors.out/r3.colors.out.html | 1 + raster/r.colors.out/raster3d_main.c | 35 ++- raster/r.colors.out/raster_main.c | 35 ++- raster/r.colors.out/tests/conftest.py | 52 ++++ .../r.colors.out/tests/r3_colors_out_test.py | 175 ++++++++++++ .../r.colors.out/tests/r_colors_out_test.py | 175 ++++++++++++ 13 files changed, 765 insertions(+), 12 deletions(-) create mode 100644 raster/r.colors.out/local_proto.h create mode 100644 raster/r.colors.out/prt_json.c create mode 100644 raster/r.colors.out/tests/conftest.py create mode 100644 raster/r.colors.out/tests/r3_colors_out_test.py create mode 100644 raster/r.colors.out/tests/r_colors_out_test.py diff --git a/general/g.parser/standard_option.c b/general/g.parser/standard_option.c index 12c08f96f2e..14c816a0e18 100644 --- a/general/g.parser/standard_option.c +++ b/general/g.parser/standard_option.c @@ -55,6 +55,7 @@ static char *STD_OPT_STRINGS[] = {"G_OPT_UNDEFINED", "G_OPT_F_SEP", "G_OPT_C", "G_OPT_CN", + "G_OPT_C_FORMAT", "G_OPT_M_UNITS", "G_OPT_M_DATATYPE", "G_OPT_M_MAPSET", diff --git a/include/grass/gis.h b/include/grass/gis.h index c032b40de06..fcc53535f47 100644 --- a/include/grass/gis.h +++ b/include/grass/gis.h @@ -316,8 +316,9 @@ typedef enum { G_OPT_F_OUTPUT, /*!< new output file */ G_OPT_F_SEP, /*!< data field separator */ - G_OPT_C, /*!< color */ - G_OPT_CN, /*!< color or none */ + G_OPT_C, /*!< color */ + G_OPT_CN, /*!< color or none */ + G_OPT_C_FORMAT, /*!< set color format to rgb,hex,hsv or triplet */ G_OPT_M_UNITS, /*!< units */ G_OPT_M_DATATYPE, /*!< datatype */ diff --git a/lib/gis/parser_standard_options.c b/lib/gis/parser_standard_options.c index 5c3da23c7bf..2addde624bf 100644 --- a/lib/gis/parser_standard_options.c +++ b/lib/gis/parser_standard_options.c @@ -97,6 +97,7 @@ - colors - G_OPT_C - G_OPT_CN + - G_OPT_C_FORMAT - misc - G_OPT_M_DIR @@ -652,6 +653,22 @@ struct Option *G_define_standard_option(int opt) Opt->description = _("Either a standard color name, R:G:B triplet, or \"none\""); break; + case G_OPT_C_FORMAT: + Opt->key = "color_format"; + Opt->type = TYPE_STRING; + Opt->key_desc = "name"; + Opt->required = YES; + Opt->multiple = NO; + Opt->answer = "hex"; + Opt->options = "rgb,hex,hsv,triplet"; + Opt->label = _("Color format"); + Opt->description = _("Color format for output values."); + G_asprintf( + (char **)&(Opt->descriptions), "rgb;%s;hex;%s;hsv;%s;triplet;%s", + _("output color in RGB format"), _("output color in HEX format"), + _("output color in HSV format (experimental)"), + _("output color in colon-separated RGB format")); + break; /* misc */ diff --git a/raster/r.colors.out/Makefile b/raster/r.colors.out/Makefile index b6717d12937..e2acf03ca41 100644 --- a/raster/r.colors.out/Makefile +++ b/raster/r.colors.out/Makefile @@ -1,13 +1,13 @@ MODULE_TOPDIR = ../.. -LIBES2 = $(RASTERLIB) $(GISLIB) -LIBES3 = $(RASTER3DLIB) $(RASTERLIB) $(GISLIB) +LIBES2 = $(RASTERLIB) $(GISLIB) $(PARSONLIB) +LIBES3 = $(RASTER3DLIB) $(RASTERLIB) $(GISLIB) $(PARSONLIB) DEPENDENCIES = $(RASTER3DDEP) $(GISDEP) $(RASTERDEP) PROGRAMS = r.colors.out r3.colors.out -r_colors_out_OBJS = raster_main.o -r3_colors_out_OBJS = raster3d_main.o +r_colors_out_OBJS = raster_main.o prt_json.o +r3_colors_out_OBJS = raster3d_main.o prt_json.o include $(MODULE_TOPDIR)/include/Make/Multi.make diff --git a/raster/r.colors.out/local_proto.h b/raster/r.colors.out/local_proto.h new file mode 100644 index 00000000000..5ed09a06e69 --- /dev/null +++ b/raster/r.colors.out/local_proto.h @@ -0,0 +1,7 @@ +#include +#include + +enum ColorFormat { RGB, HEX, HSV, TRIPLET }; + +void print_json_colors(struct Colors *colors, DCELL min, DCELL max, FILE *fp, + int perc, enum ColorFormat clr_frmt); diff --git a/raster/r.colors.out/prt_json.c b/raster/r.colors.out/prt_json.c new file mode 100644 index 00000000000..816a63e1b0e --- /dev/null +++ b/raster/r.colors.out/prt_json.c @@ -0,0 +1,265 @@ +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "local_proto.h" + +#define COLOR_STRING_LENGTH 30 + +/*! + \brief Closes the file if it is not stdout. + + \param fp file where to print color table rules + */ +static void close_file(FILE *fp) +{ + if (fp != stdout) + fclose(fp); +} + +/*! + \brief Converts RGB color values to HSV format. + + \note This implementation is experimental and may be subject to change. + + \param r red component of the RGB color + \param g green component of the RGB color + \param b blue component of the RGB color + \param[out] h pointer to store the calculated hue + \param[out] s pointer to store the calculated saturation + \param[out] v pointer to store the calculated value + */ +static void rgb_to_hsv(int r, int g, int b, float *h, float *s, float *v) +{ + float r_norm = (float)r / 255.0f; + float g_norm = (float)g / 255.0f; + float b_norm = (float)b / 255.0f; + + float cmax = MAX(r_norm, MAX(g_norm, b_norm)); + float cmin = MIN(r_norm, MIN(g_norm, b_norm)); + float diff = cmax - cmin; + + if (cmax == cmin) { + *h = 0; + } + else if (cmax == r_norm) { + *h = fmodf((60.0f * ((g_norm - b_norm) / diff) + 360.0f), 360.0f); + } + else if (cmax == g_norm) { + *h = fmodf((60.0f * ((b_norm - r_norm) / diff) + 120.0f), 360.0f); + } + else { + *h = fmodf((60.0f * ((r_norm - g_norm) / diff) + 240.0f), 360.0f); + } + + if (cmax == 0) { + *s = 0; + } + else { + *s = (diff / cmax) * 100.0f; + } + + *v = cmax * 100.0f; +} + +/*! + \brief Writes color entry in JSON in specified clr_frmt. + + \param r red component of RGB color + \param g green component of RGB color + \param b blue component of RGB color + \param clr_frmt color format to be used (RGB, HEX, HSV, TRIPLET). + \param color_object pointer to the JSON object + */ +static void set_color(int r, int g, int b, enum ColorFormat clr_frmt, + JSON_Object *color_object) +{ + char color_string[COLOR_STRING_LENGTH]; + float h, s, v; + + switch (clr_frmt) { + case RGB: + snprintf(color_string, sizeof(color_string), "rgb(%d, %d, %d)", r, g, + b); + json_object_set_string(color_object, "rgb", color_string); + break; + + case HEX: + snprintf(color_string, sizeof(color_string), "#%02X%02X%02X", r, g, b); + json_object_set_string(color_object, "hex", color_string); + break; + + case HSV: + rgb_to_hsv(r, g, b, &h, &s, &v); + snprintf(color_string, sizeof(color_string), "hsv(%d, %d, %d)", (int)h, + (int)s, (int)v); + json_object_set_string(color_object, "hsv", color_string); + break; + + case TRIPLET: + snprintf(color_string, sizeof(color_string), "%d:%d:%d", r, g, b); + json_object_set_string(color_object, "triplet", color_string); + break; + } +} + +/*! + \brief Writes a JSON rule for a specific color entry. + + \param val pointer to the DCELL value + \param min,max minimum and maximum value for percentage output (used only + when \p perc is non-zero) + \param r red component of RGB color + \param g green component of RGB color + \param b blue component of RGB color + \param root_array pointer to the JSON array + \param perc TRUE for percentage output + \param clr_frmt color format to be used (RBG, HEX, HSV, TRIPLET). + \param fp file where to print color table rules + \param root_value pointer to json value + */ +static void write_json_rule(DCELL *val, DCELL *min, DCELL *max, int r, int g, + int b, JSON_Array *root_array, int perc, + enum ColorFormat clr_frmt, FILE *fp, + JSON_Value *root_value) +{ + static DCELL v0; + static int r0 = -1, g0 = -1, b0 = -1; + + // Skip writing if the current color is the same as the last one + if (v0 == *val && r0 == r && g0 == g && b0 == b) + return; + // Update last processed values + v0 = *val, r0 = r, g0 = g, b0 = b; + + JSON_Value *color_value = json_value_init_object(); + if (color_value == NULL) { + json_value_free(root_value); + close_file(fp); + G_fatal_error(_("Failed to initialize JSON object. Out of memory?")); + } + JSON_Object *color_object = json_object(color_value); + + // Set the value as a percentage if requested, otherwise set it as-is + if (perc) + json_object_set_number(color_object, "value", + 100 * (*val - *min) / (*max - *min)); + else + json_object_set_number(color_object, "value", *val); + + set_color(r, g, b, clr_frmt, color_object); + + json_array_append_value(root_array, color_value); +} + +/*! + \brief Print color table in JSON format + + \param colors pointer to Colors structure + \param min,max minimum and maximum value for percentage output (used only + when \p perc is non-zero) + \param fp file where to print color table rules + \param perc TRUE for percentage output + \param clr_frmt color format to be used (RBG, HEX, HSV, TRIPLET). + */ +void print_json_colors(struct Colors *colors, DCELL min, DCELL max, FILE *fp, + int perc, enum ColorFormat clr_frmt) +{ + JSON_Value *root_value = json_value_init_array(); + if (root_value == NULL) { + close_file(fp); + G_fatal_error(_("Failed to initialize JSON array. Out of memory?")); + } + JSON_Array *root_array = json_array(root_value); + + if (colors->version < 0) { + /* 3.0 format */ + CELL lo, hi; + + // Retrieve the integer color range + Rast_get_c_color_range(&lo, &hi, colors); + + for (int i = lo; i <= hi; i++) { + unsigned char r, g, b, set; + DCELL val = (DCELL)i; + + // Look up the color for the current value and write JSON rule + Rast_lookup_c_colors(&i, &r, &g, &b, &set, 1, colors); + write_json_rule(&val, &min, &max, r, g, b, root_array, perc, + clr_frmt, fp, root_value); + } + } + else { + // Get the count of floating-point color rules + int count = Rast_colors_count(colors); + + for (int i = 0; i < count; i++) { + DCELL val1, val2; + unsigned char r1, g1, b1, r2, g2, b2; + + // Retrieve the color rule values and their respective RGB colors + Rast_get_fp_color_rule(&val1, &r1, &g1, &b1, &val2, &r2, &g2, &b2, + colors, count - 1 - i); + + // write JSON rule + write_json_rule(&val1, &min, &max, r1, g1, b1, root_array, perc, + clr_frmt, fp, root_value); + write_json_rule(&val2, &min, &max, r2, g2, b2, root_array, perc, + clr_frmt, fp, root_value); + } + } + + // Add special color entries for "null" and "default" values + { + int r, g, b; + + // Get RGB color for null values and create JSON entry + Rast_get_null_value_color(&r, &g, &b, colors); + JSON_Value *nv_value = json_value_init_object(); + if (nv_value == NULL) { + json_value_free(root_value); + close_file(fp); + G_fatal_error( + _("Failed to initialize JSON object. Out of memory?")); + } + JSON_Object *nv_object = json_object(nv_value); + json_object_set_string(nv_object, "value", "nv"); + set_color(r, g, b, clr_frmt, nv_object); + json_array_append_value(root_array, nv_value); + + // Get RGB color for default values and create JSON entry + Rast_get_default_color(&r, &g, &b, colors); + JSON_Value *default_value = json_value_init_object(); + if (default_value == NULL) { + json_value_free(root_value); + close_file(fp); + G_fatal_error( + _("Failed to initialize JSON object. Out of memory?")); + } + JSON_Object *default_object = json_object(default_value); + json_object_set_string(default_object, "value", "default"); + set_color(r, g, b, clr_frmt, default_object); + json_array_append_value(root_array, default_value); + } + + // Serialize JSON array to a string and print to the file + char *json_string = json_serialize_to_string_pretty(root_value); + if (!json_string) { + json_value_free(root_value); + close_file(fp); + G_fatal_error(_("Failed to serialize JSON to pretty format.")); + } + + fputs(json_string, fp); + + json_free_serialized_string(json_string); + json_value_free(root_value); + + close_file(fp); +} diff --git a/raster/r.colors.out/r.colors.out.html b/raster/r.colors.out/r.colors.out.html index 29423001db6..357bd1ebf6c 100644 --- a/raster/r.colors.out/r.colors.out.html +++ b/raster/r.colors.out/r.colors.out.html @@ -9,6 +9,7 @@

EXAMPLES

 r.colors.out map=el_D782_6m rules=rules.txt
 r.colors map=el_D783_6m rules=rules.txt
+r.colors.out map=el_D782_6m rules=rules.json format=json
 

SEE ALSO

diff --git a/raster/r.colors.out/r3.colors.out.html b/raster/r.colors.out/r3.colors.out.html index f86bf57b89c..04472d4de8c 100644 --- a/raster/r.colors.out/r3.colors.out.html +++ b/raster/r.colors.out/r3.colors.out.html @@ -9,6 +9,7 @@

EXAMPLES

 r3.colors.out map=volume_1 rules=rules.txt
 r3.colors map=volume_2 rules=rules.txt
+r3.colors.out map=volume_1 rules=rules.json format=json
 

SEE ALSO

diff --git a/raster/r.colors.out/raster3d_main.c b/raster/r.colors.out/raster3d_main.c index 95c05e545f1..904db24a91f 100644 --- a/raster/r.colors.out/raster3d_main.c +++ b/raster/r.colors.out/raster3d_main.c @@ -21,13 +21,16 @@ #include #include #include +#include + +#include "local_proto.h" /* Run in raster3d mode */ int main(int argc, char **argv) { struct GModule *module; struct { - struct Option *map, *file; + struct Option *map, *file, *format, *color_format; } opt; struct { struct Flag *p; @@ -38,6 +41,8 @@ int main(int argc, char **argv) struct Colors colors; struct FPRange range; + enum ColorFormat clr_frmt; + G_gisinit(argv[0]); module = G_define_module(); @@ -55,6 +60,12 @@ int main(int argc, char **argv) opt.file->description = _("If not given write to standard output"); opt.file->required = NO; + opt.format = G_define_standard_option(G_OPT_F_FORMAT); + opt.format->guisection = _("Print"); + + opt.color_format = G_define_standard_option(G_OPT_C_FORMAT); + opt.color_format->guisection = _("Color"); + flag.p = G_define_flag(); flag.p->key = 'p'; flag.p->description = _("Output values as percentages"); @@ -78,8 +89,26 @@ int main(int argc, char **argv) G_fatal_error(_("Unable to open output file <%s>"), file); } - Rast_print_colors(&colors, range.min, range.max, fp, - flag.p->answer ? 1 : 0); + if (strcmp(opt.format->answer, "json") == 0) { + if (strcmp(opt.color_format->answer, "rgb") == 0) { + clr_frmt = RGB; + } + else if (strcmp(opt.color_format->answer, "triplet") == 0) { + clr_frmt = TRIPLET; + } + else if (strcmp(opt.color_format->answer, "hsv") == 0) { + clr_frmt = HSV; + } + else { + clr_frmt = HEX; + } + print_json_colors(&colors, range.min, range.max, fp, + flag.p->answer ? 1 : 0, clr_frmt); + } + else { + Rast_print_colors(&colors, range.min, range.max, fp, + flag.p->answer ? 1 : 0); + } exit(EXIT_SUCCESS); } diff --git a/raster/r.colors.out/raster_main.c b/raster/r.colors.out/raster_main.c index b2a0a139157..6b4a8ed36ee 100644 --- a/raster/r.colors.out/raster_main.c +++ b/raster/r.colors.out/raster_main.c @@ -20,13 +20,16 @@ #include #include #include +#include + +#include "local_proto.h" /* Run in raster mode */ int main(int argc, char **argv) { struct GModule *module; struct { - struct Option *map, *file; + struct Option *map, *file, *format, *color_format; } opt; struct { struct Flag *p; @@ -37,6 +40,8 @@ int main(int argc, char **argv) struct Colors colors; struct FPRange range; + enum ColorFormat clr_frmt; + G_gisinit(argv[0]); module = G_define_module(); @@ -54,6 +59,12 @@ int main(int argc, char **argv) opt.file->description = _("If not given write to standard output"); opt.file->required = NO; + opt.format = G_define_standard_option(G_OPT_F_FORMAT); + opt.format->guisection = _("Print"); + + opt.color_format = G_define_standard_option(G_OPT_C_FORMAT); + opt.color_format->guisection = _("Color"); + flag.p = G_define_flag(); flag.p->key = 'p'; flag.p->description = _("Output values as percentages"); @@ -77,8 +88,26 @@ int main(int argc, char **argv) G_fatal_error(_("Unable to open output file <%s>"), file); } - Rast_print_colors(&colors, range.min, range.max, fp, - flag.p->answer ? 1 : 0); + if (strcmp(opt.format->answer, "json") == 0) { + if (strcmp(opt.color_format->answer, "rgb") == 0) { + clr_frmt = RGB; + } + else if (strcmp(opt.color_format->answer, "triplet") == 0) { + clr_frmt = TRIPLET; + } + else if (strcmp(opt.color_format->answer, "hsv") == 0) { + clr_frmt = HSV; + } + else { + clr_frmt = HEX; + } + print_json_colors(&colors, range.min, range.max, fp, + flag.p->answer ? 1 : 0, clr_frmt); + } + else { + Rast_print_colors(&colors, range.min, range.max, fp, + flag.p->answer ? 1 : 0); + } exit(EXIT_SUCCESS); } diff --git a/raster/r.colors.out/tests/conftest.py b/raster/r.colors.out/tests/conftest.py new file mode 100644 index 00000000000..c0c6790a75c --- /dev/null +++ b/raster/r.colors.out/tests/conftest.py @@ -0,0 +1,52 @@ +"""Fixture for r.colors.out and r3.colors.out test""" + +import os +import pytest +import grass.script as gs + + +@pytest.fixture +def raster_color_dataset(tmp_path): + """Set up a GRASS session and create test rasters with color rules.""" + project = tmp_path / "raster_color_project" + gs.create_project(project) + with gs.setup.init(project, env=os.environ.copy()) as session: + gs.run_command( + "g.region", + s=0, + n=90, + w=0, + e=100, + b=0, + t=1, + rows=3, + cols=3, + res=10, + env=session.env, + ) + gs.mapcalc("a = int(row())", env=session.env) + gs.run_command("r.colors", map="a", color="elevation", env=session.env) + yield session + + +@pytest.fixture +def raster3_color_dataset(tmp_path): + """Set up a GRASS session and create test raster3 with color rules.""" + project = tmp_path / "raster3_color_project" + gs.create_project(project) + with gs.setup.init(project, env=os.environ.copy()) as session: + gs.run_command( + "g.region", + s=0, + n=100, + w=0, + e=100, + b=5, + t=50, + tbres=10, + res3=20, + env=session.env, + ) + gs.mapcalc3d("b = double(row())", env=session.env) + gs.run_command("r3.colors", map="b", color="elevation", env=session.env) + yield session diff --git a/raster/r.colors.out/tests/r3_colors_out_test.py b/raster/r.colors.out/tests/r3_colors_out_test.py new file mode 100644 index 00000000000..670c1ef13a6 --- /dev/null +++ b/raster/r.colors.out/tests/r3_colors_out_test.py @@ -0,0 +1,175 @@ +"""Tests of r3.colors.out""" + +import grass.script as gs + + +def validate_plain_text_output(data): + """Validate the structure and content of the plain text output.""" + assert data + assert len(data) == 8, "The output does not match the expected number of items (8)." + expected = { + "1 0:191:191", + "1.8 0:255:0", + "2.6 255:255:0", + "3.4 255:127:0", + "4.2 191:127:63", + "5 200:200:200", + "nv 255:255:255", + "default 255:255:255", + } + assert ( + expected == data.keys() + ), f"test failed: expected {expected} but got {data.keys()}" + + +def test_r3_colors_out_plain_output(raster3_color_dataset): + """Test r3.colors.out command for plain output format.""" + session = raster3_color_dataset + data = gs.parse_command("r3.colors.out", map="b", format="plain", env=session.env) + validate_plain_text_output(data) + + +def test_r3_colors_out_without_format_option(raster3_color_dataset): + """Test r3.colors.out command without any format option.""" + session = raster3_color_dataset + data = gs.parse_command("r3.colors.out", map="b", env=session.env) + validate_plain_text_output(data) + + +def test_r3_colors_out_with_p_flag(raster3_color_dataset): + """Test r3.colors.out command with percentage values.""" + session = raster3_color_dataset + data = gs.parse_command("r3.colors.out", map="b", flags="p", env=session.env) + assert data + assert len(data) == 8, "The output does not match the expected number of items (8)." + expected = { + "0% 0:191:191", + "20% 0:255:0", + "40% 255:255:0", + "60% 255:127:0", + "80% 191:127:63", + "100% 200:200:200", + "nv 255:255:255", + "default 255:255:255", + } + assert ( + expected == data.keys() + ), f"test failed: expected {expected} but got {data.keys()}" + + +def validate_common_json_structure(data): + """Validate the common structure and content of the JSON output.""" + assert isinstance(data, list), "Output data should be a list of entries." + assert ( + len(data) == 8 + ), "The length of the output JSON does not match the expected value of 8." + + +def test_r3_colors_out_json_with_default_option(raster3_color_dataset): + """Test r3.colors.out command for JSON output format for default color option.""" + session = raster3_color_dataset + data = gs.parse_command("r3.colors.out", map="b", format="json", env=session.env) + validate_common_json_structure(data) + expected = [ + {"value": 1, "hex": "#00BFBF"}, + {"value": 1.8, "hex": "#00FF00"}, + {"value": 2.6, "hex": "#FFFF00"}, + {"value": 3.4, "hex": "#FF7F00"}, + {"value": 4.2, "hex": "#BF7F3F"}, + {"value": 5, "hex": "#C8C8C8"}, + {"value": "nv", "hex": "#FFFFFF"}, + {"value": "default", "hex": "#FFFFFF"}, + ] + assert expected == data, f"test failed: expected {expected} but got {data}" + + +def test_r3_colors_out_json_with_triplet_option(raster3_color_dataset): + """Test r3.colors.out command for JSON output format for triplet color option.""" + session = raster3_color_dataset + data = gs.parse_command( + "r3.colors.out", map="b", format="json", color_format="triplet", env=session.env + ) + validate_common_json_structure(data) + expected = [ + {"value": 1, "triplet": "0:191:191"}, + {"value": 1.8, "triplet": "0:255:0"}, + {"value": 2.6, "triplet": "255:255:0"}, + {"value": 3.4, "triplet": "255:127:0"}, + {"value": 4.2, "triplet": "191:127:63"}, + {"value": 5, "triplet": "200:200:200"}, + {"value": "nv", "triplet": "255:255:255"}, + {"value": "default", "triplet": "255:255:255"}, + ] + assert expected == data, f"test failed: expected {expected} but got {data}" + + +def test_r3_colors_out_json_with_rgb_option(raster3_color_dataset): + """Test r3.colors.out command for JSON output format for rgb color option.""" + session = raster3_color_dataset + data = gs.parse_command( + "r3.colors.out", + map="b", + format="json", + color_format="rgb", + env=session.env, + ) + validate_common_json_structure(data) + expected = [ + {"value": 1, "rgb": "rgb(0, 191, 191)"}, + {"value": 1.8, "rgb": "rgb(0, 255, 0)"}, + {"value": 2.6, "rgb": "rgb(255, 255, 0)"}, + {"value": 3.4, "rgb": "rgb(255, 127, 0)"}, + {"value": 4.2, "rgb": "rgb(191, 127, 63)"}, + {"value": 5, "rgb": "rgb(200, 200, 200)"}, + {"value": "nv", "rgb": "rgb(255, 255, 255)"}, + {"value": "default", "rgb": "rgb(255, 255, 255)"}, + ] + assert expected == data, f"test failed: expected {expected} but got {data}" + + +def test_r3_colors_out_json_with_hex_option(raster3_color_dataset): + """Test r3.colors.out command for JSON output format for hex color option.""" + session = raster3_color_dataset + data = gs.parse_command( + "r3.colors.out", + map="b", + format="json", + color_format="hex", + env=session.env, + ) + validate_common_json_structure(data) + expected = [ + {"value": 1, "hex": "#00BFBF"}, + {"value": 1.8, "hex": "#00FF00"}, + {"value": 2.6, "hex": "#FFFF00"}, + {"value": 3.4, "hex": "#FF7F00"}, + {"value": 4.2, "hex": "#BF7F3F"}, + {"value": 5, "hex": "#C8C8C8"}, + {"value": "nv", "hex": "#FFFFFF"}, + {"value": "default", "hex": "#FFFFFF"}, + ] + assert expected == data, f"test failed: expected {expected} but got {data}" + + +def test_r3_colors_out_json_with_hsv_option(raster3_color_dataset): + """Test r3.colors.out command for JSON output format for hsv color option.""" + session = raster3_color_dataset + data = gs.parse_command( + "r3.colors.out", + map="b", + format="json", + color_format="hsv", + env=session.env, + ) + validate_common_json_structure(data) + expected = [ + {"value": 1, "hsv": "hsv(180, 100, 74)"}, + {"value": 1.8, "hsv": "hsv(120, 100, 100)"}, + {"value": 2.6, "hsv": "hsv(60, 100, 100)"}, + {"value": 3.4, "hsv": "hsv(29, 100, 100)"}, + {"value": 4.2, "hsv": "hsv(30, 67, 74)"}, + {"value": 5, "hsv": "hsv(0, 0, 78)"}, + {"value": "nv", "hsv": "hsv(0, 0, 100)"}, + {"value": "default", "hsv": "hsv(0, 0, 100)"}, + ] + assert expected == data, f"test failed: expected {expected} but got {data}" diff --git a/raster/r.colors.out/tests/r_colors_out_test.py b/raster/r.colors.out/tests/r_colors_out_test.py new file mode 100644 index 00000000000..d1abec82592 --- /dev/null +++ b/raster/r.colors.out/tests/r_colors_out_test.py @@ -0,0 +1,175 @@ +"""Tests of r.colors.out""" + +import grass.script as gs + + +def validate_plain_text_output(data): + """Validate the structure and content of the plain text output.""" + assert data + assert len(data) == 8, "The output does not match the expected number of items (8)." + expected = { + "1 0:191:191", + "1.4 0:255:0", + "1.8 255:255:0", + "2.2 255:127:0", + "2.6 191:127:63", + "3 200:200:200", + "nv 255:255:255", + "default 255:255:255", + } + assert ( + expected == data.keys() + ), f"test failed: expected {expected} but got {data.keys()}" + + +def test_r_colors_out_plain_output(raster_color_dataset): + """Test r.colors.out command for plain output format.""" + session = raster_color_dataset + data = gs.parse_command("r.colors.out", map="a", format="plain", env=session.env) + validate_plain_text_output(data) + + +def test_r_colors_out_without_format_option(raster_color_dataset): + """Test r.colors.out command without any format option.""" + session = raster_color_dataset + data = gs.parse_command("r.colors.out", map="a", env=session.env) + validate_plain_text_output(data) + + +def test_r_colors_out_with_p_flag(raster_color_dataset): + """Test r.colors.out command with percentage values.""" + session = raster_color_dataset + data = gs.parse_command("r.colors.out", map="a", flags="p", env=session.env) + assert data + assert len(data) == 8, "The output does not match the expected number of items (8)." + expected = { + "0% 0:191:191", + "20% 0:255:0", + "40% 255:255:0", + "60% 255:127:0", + "80% 191:127:63", + "100% 200:200:200", + "nv 255:255:255", + "default 255:255:255", + } + assert ( + expected == data.keys() + ), f"test failed: expected {expected} but got {data.keys()}" + + +def validate_common_json_structure(data): + """Validate the common structure and content of the JSON output.""" + assert isinstance(data, list), "Output data should be a list of entries." + assert ( + len(data) == 8 + ), "The length of the output JSON does not match the expected value of 8." + + +def test_r_colors_out_json_with_default_option(raster_color_dataset): + """Test r.colors.out command for JSON output format for default color option.""" + session = raster_color_dataset + data = gs.parse_command("r.colors.out", map="a", format="json", env=session.env) + validate_common_json_structure(data) + expected = [ + {"value": 1, "hex": "#00BFBF"}, + {"value": 1.4, "hex": "#00FF00"}, + {"value": 1.8, "hex": "#FFFF00"}, + {"value": 2.2, "hex": "#FF7F00"}, + {"value": 2.6, "hex": "#BF7F3F"}, + {"value": 3, "hex": "#C8C8C8"}, + {"value": "nv", "hex": "#FFFFFF"}, + {"value": "default", "hex": "#FFFFFF"}, + ] + assert expected == data, f"test failed: expected {expected} but got {data}" + + +def test_r_colors_out_json_with_triplet_option(raster_color_dataset): + """Test r.colors.out command for JSON output format for triplet color option.""" + session = raster_color_dataset + data = gs.parse_command( + "r.colors.out", map="a", format="json", color_format="triplet", env=session.env + ) + validate_common_json_structure(data) + expected = [ + {"value": 1, "triplet": "0:191:191"}, + {"value": 1.4, "triplet": "0:255:0"}, + {"value": 1.8, "triplet": "255:255:0"}, + {"value": 2.2, "triplet": "255:127:0"}, + {"value": 2.6, "triplet": "191:127:63"}, + {"value": 3, "triplet": "200:200:200"}, + {"value": "nv", "triplet": "255:255:255"}, + {"value": "default", "triplet": "255:255:255"}, + ] + assert expected == data, f"test failed: expected {expected} but got {data}" + + +def test_r_colors_out_json_with_rgb_option(raster_color_dataset): + """Test r.colors.out command for JSON output format for rgb color option.""" + session = raster_color_dataset + data = gs.parse_command( + "r.colors.out", + map="a", + format="json", + color_format="rgb", + env=session.env, + ) + validate_common_json_structure(data) + expected = [ + {"value": 1, "rgb": "rgb(0, 191, 191)"}, + {"value": 1.4, "rgb": "rgb(0, 255, 0)"}, + {"value": 1.8, "rgb": "rgb(255, 255, 0)"}, + {"value": 2.2, "rgb": "rgb(255, 127, 0)"}, + {"value": 2.6, "rgb": "rgb(191, 127, 63)"}, + {"value": 3, "rgb": "rgb(200, 200, 200)"}, + {"value": "nv", "rgb": "rgb(255, 255, 255)"}, + {"value": "default", "rgb": "rgb(255, 255, 255)"}, + ] + assert expected == data, f"test failed: expected {expected} but got {data}" + + +def test_r_colors_out_json_with_hex_option(raster_color_dataset): + """Test r.colors.out command for JSON output format for hex color option.""" + session = raster_color_dataset + data = gs.parse_command( + "r.colors.out", + map="a", + format="json", + color_format="hex", + env=session.env, + ) + validate_common_json_structure(data) + expected = [ + {"value": 1, "hex": "#00BFBF"}, + {"value": 1.4, "hex": "#00FF00"}, + {"value": 1.8, "hex": "#FFFF00"}, + {"value": 2.2, "hex": "#FF7F00"}, + {"value": 2.6, "hex": "#BF7F3F"}, + {"value": 3, "hex": "#C8C8C8"}, + {"value": "nv", "hex": "#FFFFFF"}, + {"value": "default", "hex": "#FFFFFF"}, + ] + assert expected == data, f"test failed: expected {expected} but got {data}" + + +def test_r_colors_out_json_with_hsv_option(raster_color_dataset): + """Test r.colors.out command for JSON output format for hsv color option.""" + session = raster_color_dataset + data = gs.parse_command( + "r.colors.out", + map="a", + format="json", + color_format="hsv", + env=session.env, + ) + validate_common_json_structure(data) + expected = [ + {"value": 1, "hsv": "hsv(180, 100, 74)"}, + {"value": 1.4, "hsv": "hsv(120, 100, 100)"}, + {"value": 1.8, "hsv": "hsv(60, 100, 100)"}, + {"value": 2.2, "hsv": "hsv(29, 100, 100)"}, + {"value": 2.6, "hsv": "hsv(30, 67, 74)"}, + {"value": 3, "hsv": "hsv(0, 0, 78)"}, + {"value": "nv", "hsv": "hsv(0, 0, 100)"}, + {"value": "default", "hsv": "hsv(0, 0, 100)"}, + ] + assert expected == data, f"test failed: expected {expected} but got {data}" From 98bccea20be0a2ea983221873a3b7a3f6fc51f21 Mon Sep 17 00:00:00 2001 From: Arohan Ajit Date: Tue, 5 Nov 2024 23:08:59 -0500 Subject: [PATCH 34/57] wxGUI: Fixed bare 'except' for psmap/ (#4623) --- .flake8 | 2 +- gui/wxpython/psmap/frame.py | 18 ++++-------------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/.flake8 b/.flake8 index ab4038e4749..a44d0182e5f 100644 --- a/.flake8 +++ b/.flake8 @@ -24,7 +24,7 @@ per-file-ignores = gui/scripts/d.wms.py: E501 gui/wxpython/image2target/g.gui.image2target.py: E501 gui/wxpython/photo2image/g.gui.photo2image.py: E501 - gui/wxpython/psmap/*: E501, E722 + gui/wxpython/psmap/*: E501 gui/wxpython/vdigit/*: F841, E722, F405, F403 gui/wxpython/animation/g.gui.animation.py: E501 gui/wxpython/tplot/frame.py: F841, E722 diff --git a/gui/wxpython/psmap/frame.py b/gui/wxpython/psmap/frame.py index 8926b8d1e75..22194ece0c0 100644 --- a/gui/wxpython/psmap/frame.py +++ b/gui/wxpython/psmap/frame.py @@ -1045,19 +1045,9 @@ def makePSFont(self, textDict): if "Bold" in fontstyle: weight = wx.FONTWEIGHT_BOLD - try: - fn = wx.Font( - pointSize=fontsize, family=family, style=style, weight=weight, face=face - ) - except: - fn = wx.Font( - pointSize=fontsize, - family=wx.FONTFAMILY_DEFAULT, - style=wx.FONTSTYLE_NORMAL, - weight=wx.FONTWEIGHT_NORMAL, - ) - - return fn + return wx.Font( + pointSize=fontsize, family=family, style=style, weight=weight, faceName=face + ) def getTextExtent(self, textDict): """Estimates bounding rectangle of text""" @@ -1071,7 +1061,7 @@ def getTextExtent(self, textDict): dc.SetFont(fn) w, h, lh = dc.GetFullMultiLineTextExtent(textDict["text"]) return (w, h) - except: + except (wx.PyAssertionError, ValueError, KeyError): return (0, 0) def getInitMap(self): From 48e382c35b80b7f92cd8621d7c0163443ff44184 Mon Sep 17 00:00:00 2001 From: Tomas Zigo <50632337+tmszi@users.noreply.github.com> Date: Wed, 6 Nov 2024 06:33:20 +0100 Subject: [PATCH 35/57] python/grass/utils: fix checking server response content type/dispostion header (#4658) To allow to download ZIP file. Server response headers which indicating ZIP file: content-type: application/octet-stream content-disposition: attachment; filename=natural_earth_dataset.zip Fix download Natural Earth Dataset in WGS84 from the server URL https://zenodo.org/records/13370131/files/natural_earth_dataset.zip --- python/grass/utils/download.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/python/grass/utils/download.py b/python/grass/utils/download.py index f6b734b7291..ade1ac9411c 100644 --- a/python/grass/utils/download.py +++ b/python/grass/utils/download.py @@ -13,6 +13,7 @@ """Download and extract various archives""" import os +import re import shutil import tarfile import tempfile @@ -23,6 +24,10 @@ from urllib.request import urlretrieve +reponse_content_type_header_pattern = re.compile(r"application/(zip|octet-stream)") +reponse_content_disposition_header_pattern = re.compile(r"attachment; filename=.*.zip$") + + def debug(*args, **kwargs): """Print a debug message (to be used in this module only) @@ -170,7 +175,13 @@ def download_and_extract(source, reporthook=None): ) except URLError: raise DownloadError(url_error_message.format(url=source)) - if headers.get("content-type", "") != "application/zip": + + if not re.search( + reponse_content_type_header_pattern, headers.get("content-type", "") + ) and not re.search( + reponse_content_disposition_header_pattern, + headers.get("content-disposition", ""), + ): raise DownloadError( _( "Download of <{url}> failed or file <{name}> is not a ZIP file" From aa07454545da7574e952256169259f03ce924e75 Mon Sep 17 00:00:00 2001 From: Markus Neteler Date: Wed, 6 Nov 2024 09:48:42 +0100 Subject: [PATCH 36/57] docs: i.albedo and r.li manual HTML fixes (#4654) doc: i.albedo and r.li manual HTML fixes This PR removes the unneeded header of the `r.li.html` metapage. Additionally: - style fix in `i.albedo.html` --- imagery/i.albedo/i.albedo.html | 2 +- raster/r.li/r.li.html | 23 ----------------------- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/imagery/i.albedo/i.albedo.html b/imagery/i.albedo/i.albedo.html index bc21720d19c..76b7e04696e 100644 --- a/imagery/i.albedo/i.albedo.html +++ b/imagery/i.albedo/i.albedo.html @@ -43,7 +43,7 @@

TODO

Maybe change input requirement of MODIS to [0.0-1.0]? -

References

+

REFERENCES

For a 2 band determination of the Aster BB Albedo see the following:

diff --git a/raster/r.li/r.li.html b/raster/r.li/r.li.html index 0ad8e5b6d77..bfe7c3498d0 100644 --- a/raster/r.li/r.li.html +++ b/raster/r.li/r.li.html @@ -1,26 +1,3 @@ - - - -r.li - GRASS GIS manual - - - - - - -

- -GRASS logo -
- -

NAME

- -r.li - Toolset for multiscale analysis of landscape structure - -

KEYWORDS

- -raster, landscape structure analysis, diversity index, patch index -

DESCRIPTION

From 9537d7474bc08a0899790554a5edc69fdf301814 Mon Sep 17 00:00:00 2001 From: Vaclav Petras Date: Wed, 6 Nov 2024 17:02:13 -0500 Subject: [PATCH 37/57] r.report: Work with any mask name (also for r.kappa) (#4633) Use Rast_mask_status in r.report and r.kappa to get the name and state. --- raster/r.kappa/mask.c | 10 ++++++---- raster/r.report/maskinfo.c | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/raster/r.kappa/mask.c b/raster/r.kappa/mask.c index 729f7c5b13a..718245b6838 100644 --- a/raster/r.kappa/mask.c +++ b/raster/r.kappa/mask.c @@ -13,15 +13,17 @@ char *maskinfo(void) { struct Reclass reclass; char *results; - char text[100]; + char text[2 * GNAME_MAX + GMAPSET_MAX]; int next; int first; + char mask_name[GNAME_MAX]; + char mask_mapset[GMAPSET_MAX]; results = NULL; - if (G_find_raster("MASK", G_mapset()) == NULL) + if (!Rast_mask_status(mask_name, mask_mapset, NULL, NULL, NULL)) return "none"; - if (Rast_get_reclass("MASK", G_mapset(), &reclass) <= 0) { - sprintf(text, "MASK in %s", G_mapset()); + if (Rast_get_reclass(mask_name, mask_mapset, &reclass) <= 0) { + sprintf(text, "%s in %s", mask_name, mask_mapset); return append(results, text); } diff --git a/raster/r.report/maskinfo.c b/raster/r.report/maskinfo.c index cfe2a382029..70f9043d0f8 100644 --- a/raster/r.report/maskinfo.c +++ b/raster/r.report/maskinfo.c @@ -13,15 +13,17 @@ char *maskinfo(void) { struct Reclass reclass; char *results; - char text[100]; + char text[2 * GNAME_MAX + GMAPSET_MAX]; int next; int first; + char mask_name[GNAME_MAX]; + char mask_mapset[GMAPSET_MAX]; results = NULL; - if (G_find_raster("MASK", G_mapset()) == NULL) + if (!Rast_mask_status(mask_name, mask_mapset, NULL, NULL, NULL)) return "none"; - if (Rast_get_reclass("MASK", G_mapset(), &reclass) <= 0) { - sprintf(text, "MASK in %s", G_mapset()); + if (Rast_get_reclass(mask_name, mask_mapset, &reclass) <= 0) { + sprintf(text, "%s in %s", mask_name, mask_mapset); return append(results, text); } From 54d613f814cf18b4af64976c1b57205ebfe3d5cc Mon Sep 17 00:00:00 2001 From: Vaclav Petras Date: Wed, 6 Nov 2024 17:04:24 -0500 Subject: [PATCH 38/57] raster: Work with any mask name (r.surf.contour, r.random.cells, r.random.surface) (#4634) Use Rast_mask_status instead of hardcoded name MASK for r.surf.contour, r.random.cells, and r.random.surface. Raster mask if present, is loaded in a special way in these tools. After this change, the name of the mask is retrieved from the library (that's the important part) and the library is at the same time used to test the presence of the mask (as opposed to testing presence of raster directly, but that's just more convenient rather than conceptual). The change in r.random.surface code switching the if and else branches is to make it easier to write and more consistent with the other two. --- raster/r.random.cells/init.c | 6 ++++-- raster/r.random.surface/init.c | 14 ++++++++------ raster/r.surf.contour/main.c | 6 ++++-- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/raster/r.random.cells/init.c b/raster/r.random.cells/init.c index 1f6ec1c7737..4cb49ce9a99 100644 --- a/raster/r.random.cells/init.c +++ b/raster/r.random.cells/init.c @@ -42,8 +42,10 @@ void Init(void) Cells = FlagCreate(Rs, Cs); CellCount = 0; - if (G_find_raster2("MASK", G_mapset())) { - FD = Rast_open_old("MASK", G_mapset()); + char mask_name[GNAME_MAX]; + char mask_mapset[GMAPSET_MAX]; + if (Rast_mask_status(mask_name, mask_mapset, NULL, NULL, NULL)) { + FD = Rast_open_old(mask_name, mask_mapset); { for (row = 0; row < Rs; row++) { Rast_get_c_row_nomask(FD, CellBuffer, row); diff --git a/raster/r.random.surface/init.c b/raster/r.random.surface/init.c index a2b4af5dc8b..44d79fd2bf8 100644 --- a/raster/r.random.surface/init.c +++ b/raster/r.random.surface/init.c @@ -35,12 +35,10 @@ void Init(void) else MinRes = NS; - if (NULL == G_find_file("cell", "MASK", G_mapset())) { - MapCount = Rs * Cs; - FDM = -1; - } - else { - FDM = Rast_open_old("MASK", G_mapset()); + char mask_name[GNAME_MAX]; + char mask_mapset[GMAPSET_MAX]; + if (Rast_mask_status(mask_name, mask_mapset, NULL, NULL, NULL)) { + FDM = Rast_open_old(mask_name, mask_mapset); { MapCount = 0; CellBuffer = Rast_allocate_c_buf(); @@ -53,6 +51,10 @@ void Init(void) } } } + else { + MapCount = Rs * Cs; + FDM = -1; + } if (Uniform->answer) sprintf(Buf, "Uni. R. S."); diff --git a/raster/r.surf.contour/main.c b/raster/r.surf.contour/main.c index 4c28d848822..202cc99e758 100644 --- a/raster/r.surf.contour/main.c +++ b/raster/r.surf.contour/main.c @@ -80,8 +80,10 @@ int main(int argc, char *argv[]) alt_row = (DCELL *)G_malloc(ncols * sizeof(DCELL)); seen = flag_create(nrows, ncols); mask = flag_create(nrows, ncols); - if (NULL != G_find_file("cell", "MASK", G_mapset())) { - file_fd = Rast_open_old("MASK", G_mapset()); + char mask_name[GNAME_MAX]; + char mask_mapset[GMAPSET_MAX]; + if (Rast_mask_status(mask_name, mask_mapset, NULL, NULL, NULL)) { + file_fd = Rast_open_old(mask_name, mask_mapset); for (r = 0; r < nrows; r++) { Rast_get_d_row_nomask(file_fd, alt_row, r); for (c = 0; c < ncols; c++) From 69b20cfed18dbc19cc9d0860f5d364d300c5953c Mon Sep 17 00:00:00 2001 From: Vaclav Petras Date: Wed, 6 Nov 2024 17:04:56 -0500 Subject: [PATCH 39/57] r.volume: Work with any mask name (#4632) Avoid hardcoded MASK by using the Rast_mask_status function. The rest of the logic stays the same so mask is read just as the plain raster map is read. Documentation is updated to use 'raster mask' instead of 'MASK'. --- raster/r.volume/main.c | 42 ++++++++++++++++++++--------------- raster/r.volume/r.volume.html | 8 +++---- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/raster/r.volume/main.c b/raster/r.volume/main.c index 236cc3f6255..4fd71b56071 100644 --- a/raster/r.volume/main.c +++ b/raster/r.volume/main.c @@ -12,10 +12,10 @@ * * PURPOSE: r.volume is a program to compute the total, and average of * cell values within regions of a map defined by clumps or - * patches on a second map (or MASK). It also computes the - * "volume" by multiplying the total within a clump by the area - * of each cell. It also outputs the "centroid" location of each - * clump. Output is to standard out. + * patches on a second map (or by raster mask). It also computes + * the "volume" by multiplying the total within a clump by the + * area of each cell. It also outputs the "centroid" location of + * each clump. Output is to standard out. * * COPYRIGHT: (C) 1999-2006, 2013 by the GRASS Development Team * @@ -43,7 +43,8 @@ int main(int argc, char *argv[]) CELL i, max; int row, col, rows, cols; - int out_mode, use_MASK; + int out_mode; + bool use_mask; unsigned long *n, *e; long int *count; int fd_data, fd_clump; @@ -92,7 +93,8 @@ int main(int argc, char *argv[]) opt.clump->required = NO; opt.clump->label = _("Name of input clump raster map"); opt.clump->description = _("Preferably the output of r.clump. " - "If no clump map is given than MASK is used."); + "If no clump map is given, " + "raster mask is used instead."); opt.centroids = G_define_standard_option(G_OPT_V_OUTPUT); opt.centroids->key = "centroids"; @@ -134,24 +136,28 @@ int main(int argc, char *argv[]) out_mode = (!flag.report->answer); /* - * see if MASK or a separate "clumpmap" raster map is to be used + * see if raster mask or a separate "clumpmap" raster map is to be used * -- it must(!) be one of those two choices. */ - use_MASK = 0; + use_mask = false; + char mask_name[GNAME_MAX]; + char mask_mapset[GMAPSET_MAX]; if (!clumpmap) { - clumpmap = "MASK"; - use_MASK = 1; - if (!G_find_raster2(clumpmap, G_mapset())) - G_fatal_error(_("No MASK found. If no clump map is given than the " - "MASK is required. " - "You need to define a clump raster map or create a " - "MASK by r.mask command.")); - G_important_message(_("No clump map given, using MASK")); + bool present = + Rast_mask_status(mask_name, mask_mapset, NULL, NULL, NULL); + if (!present) + G_fatal_error(_("No clump map <%s> given and no raster mask found. " + "You need to define a clump raster map or create " + "a raster mask using r.mask."), + opt.clump->key); + clumpmap = mask_name; + use_mask = true; + G_important_message(_("No clump map given, using raster mask")); } /* open input and clump raster maps */ fd_data = Rast_open_old(datamap, ""); - fd_clump = Rast_open_old(clumpmap, use_MASK ? G_mapset() : ""); + fd_clump = Rast_open_old(clumpmap, use_mask ? mask_mapset : ""); /* initialize vector map (for centroids) if needed */ if (centroidsmap) { @@ -175,7 +181,7 @@ int main(int argc, char *argv[]) } /* initialize data accumulation arrays */ - max = Rast_get_max_c_cat(clumpmap, use_MASK ? G_mapset() : ""); + max = Rast_get_max_c_cat(clumpmap, use_mask ? mask_mapset : ""); sum = (double *)G_malloc((max + 1) * sizeof(double)); count = (long int *)G_malloc((max + 1) * sizeof(long int)); diff --git a/raster/r.volume/r.volume.html b/raster/r.volume/r.volume.html index 6f79e6ee76f..f9c20e324c1 100644 --- a/raster/r.volume/r.volume.html +++ b/raster/r.volume/r.volume.html @@ -8,7 +8,7 @@

DESCRIPTION

from a input raster map sorted by category on a clump raster map, and optionally generates a vector points map of the centroids for each clump. If a clump map is not specified, the -current MASK is used. The MASK can be defined +current raster mask is used. The raster mask can be defined by r.mask. The sum is multiplied by the area of a cell to give the volume occupied by that cell. See below for an example of the output table. @@ -24,12 +24,12 @@

DESCRIPTION

NOTES

-If a clump map is not given and a MASK not set, the program exits with -an error message. +If a clump map is not given and a raster mask is not set, the program exits +with an error message.

r.volume works in the current region and respects the current -MASK. +raster mask.

CENTROIDS

From 410cf5ccfd9c8617162ab73411248ddc053fd389 Mon Sep 17 00:00:00 2001 From: ShubhamDesai <42180509+ShubhamDesai@users.noreply.github.com> Date: Thu, 7 Nov 2024 12:05:48 -0500 Subject: [PATCH 40/57] r.to.vect: Fix Resource Leak issue in areas_io.c (#4663) Fix Resource Leak issue --- raster/r.to.vect/areas_io.c | 1 + 1 file changed, 1 insertion(+) diff --git a/raster/r.to.vect/areas_io.c b/raster/r.to.vect/areas_io.c index 86760038d61..6d9cfd10e84 100644 --- a/raster/r.to.vect/areas_io.c +++ b/raster/r.to.vect/areas_io.c @@ -371,6 +371,7 @@ int write_area( if (equivs) G_free(equivs); + Vect_destroy_line_struct(points); return 0; } From 53c28f3cb1f11fdbec158b1f1a95b53273e0812c Mon Sep 17 00:00:00 2001 From: Nicklas Larsson Date: Fri, 8 Nov 2024 00:02:09 +0100 Subject: [PATCH 41/57] CI: create versioned directory name of extracted tarball (#4659) Extracting the tarball will with this create a containing directory named 'grass-x.y.z', where x, y, z stands for major, minor, micro/patch version. --- .github/workflows/create_release_draft.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/create_release_draft.yml b/.github/workflows/create_release_draft.yml index fb71e35d2ff..8147136c2eb 100644 --- a/.github/workflows/create_release_draft.yml +++ b/.github/workflows/create_release_draft.yml @@ -63,7 +63,8 @@ jobs: run: | cd .. tar -cvf ${{ env.OUT_DIR }}/${{ env.GRASS }}.tar \ - --exclude=".gi*" --exclude=".tr*" grass + --exclude=".gi*" --exclude=".tr*" \ + --transform s/grass/${{ env.GRASS }}/ grass cd ${{ env.OUT_DIR }} gzip -9k ${{ env.GRASS }}.tar md5sum ${{ env.GRASS }}.tar.gz > ${{ env.GRASS }}.tar.gz.md5 From b9298093ee685c98555c0e275c0961afb6fb5932 Mon Sep 17 00:00:00 2001 From: Stefan Blumentrath Date: Fri, 8 Nov 2024 02:05:26 +0100 Subject: [PATCH 42/57] t.rast.univar: allow r-flag combined with zones option (#4577) * allow r-flag and zones * add test for r-flag and zones * use region env only with zones * use region env for r3.univar * Update docstring --- python/grass/temporal/univar_statistics.py | 15 +++---- temporal/t.rast.univar/t.rast.univar.py | 5 +-- .../testsuite/test_t_rast_univar.py | 39 +++++++++++++++++++ 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/python/grass/temporal/univar_statistics.py b/python/grass/temporal/univar_statistics.py index b6a9c1ac508..77ebaca30b1 100755 --- a/python/grass/temporal/univar_statistics.py +++ b/python/grass/temporal/univar_statistics.py @@ -13,7 +13,7 @@ .. -(C) 2012-2013 by the GRASS Development Team +(C) 2012-2024 by the GRASS Development Team This program is free software under the GNU General Public License (>=v2). Read the file COPYING that comes with GRASS for details. @@ -57,7 +57,7 @@ def compute_univar_stats(registered_map_info, stats_module, fs, rast_region=Fals ) stats_module.inputs.map = id - if rast_region: + if rast_region and (stats_module.inputs.zones or stats_module.name == "r3.univar"): stats_module.env = gs.region_env(raster=id) stats_module.run() @@ -139,7 +139,6 @@ def print_gridded_dataset_univar_statistics( :param nprocs: Number of cores to use for processing :param rast_region: If set True ignore the current region settings and use the raster map regions for univar statistical calculation. - Only available for strds. :param region_relation: Process only maps with the given spatial relation to the computational region. A string with one of the following values: "overlaps": maps that spatially overlap ("intersect") @@ -154,9 +153,6 @@ def print_gridded_dataset_univar_statistics( sp = open_old_stds(input, type, dbif) - if output is not None: - out_file = open(output, "w") - spatial_extent = None if region_relation: spatial_extent = gs.parse_command("g.region", flags="3gu") @@ -187,10 +183,11 @@ def print_gridded_dataset_univar_statistics( ).format(type=sp.get_new_map_instance(None).get_type(), id=sp.get_id()) ) - if output is not None: - out_file.close() return + if output is not None: + out_file = open(output, "w") + if no_header is False: cols = ( ["id", "semantic_label", "start", "end"] @@ -235,7 +232,7 @@ def print_gridded_dataset_univar_statistics( flag = "g" if extended is True: flag += "e" - if type == "strds" and rast_region is True: + if type == "strds" and rast_region is True and not zones: flag += "r" # Setup pygrass module to use for computation diff --git a/temporal/t.rast.univar/t.rast.univar.py b/temporal/t.rast.univar/t.rast.univar.py index bd199f9e801..dbc2a31ab4d 100755 --- a/temporal/t.rast.univar/t.rast.univar.py +++ b/temporal/t.rast.univar/t.rast.univar.py @@ -91,7 +91,6 @@ # %rules # % requires: percentile,-e -# % exclusive: zones,-r # %end import grass.script as gs @@ -130,9 +129,7 @@ def main(): # Make sure the temporal database exists tgis.init() - if not output: - output = None - if output == "-": + if not output or output == "-": output = None # Check if zones map exists and is of type CELL 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 83e5c2d6229..7bdfe9f7f6a 100644 --- a/temporal/t.rast.univar/testsuite/test_t_rast_univar.py +++ b/temporal/t.rast.univar/testsuite/test_t_rast_univar.py @@ -348,6 +348,45 @@ def test_with_zones(self): a_4@PERMANENT||2001-10-01 00:00:00|2002-01-01 00:00:00|1|400|400|400|400|0|0|0|240000|0|600|600 a_4@PERMANENT||2001-10-01 00:00:00|2002-01-01 00:00:00|2|400|400|400|400|0|0|0|672000|0|1680|1680 a_4@PERMANENT||2001-10-01 00:00:00|2002-01-01 00:00:00|3|400|400|400|400|0|0|0|2928000|0|7320|7320 +""" + + for ref, res in zip( + univar_text.split("\n"), t_rast_univar.outputs.stdout.split("\n") + ): + if ref and res: + ref_line = ref.split("|", 1)[1] + res_line = res.split("|", 1)[1] + self.assertLooksLike(ref_line, res_line) + + @xfail_windows + def test_with_zones_and_r(self): + """Test use of zones and r-flag""" + + t_rast_univar = SimpleModule( + "t.rast.univar", + flags="r", + input="A", + where="start_time >= '2001-01-01'", + zones="zones", + overwrite=True, + verbose=True, + ) + self.runModule("g.region", **self.default_region, res=1) + self.assertModule(t_rast_univar) + + univar_text = """id|semantic_label|start|end|zone|mean|min|max|mean_of_abs|stddev|variance|coeff_var|sum|null_cells|cells|non_null_cells +a_1@PERMANENT||2001-01-01 00:00:00|2001-04-01 00:00:00|1|100|100|100|100|0|0|0|60000|0|600|600 +a_1@PERMANENT||2001-01-01 00:00:00|2001-04-01 00:00:00|2|100|100|100|100|0|0|0|168000|0|1680|1680 +a_1@PERMANENT||2001-01-01 00:00:00|2001-04-01 00:00:00|3|100|100|100|100|0|0|0|732000|0|7320|7320 +a_2@PERMANENT||2001-04-01 00:00:00|2001-07-01 00:00:00|1|200|200|200|200|0|0|0|120000|0|600|600 +a_2@PERMANENT||2001-04-01 00:00:00|2001-07-01 00:00:00|2|200|200|200|200|0|0|0|336000|0|1680|1680 +a_2@PERMANENT||2001-04-01 00:00:00|2001-07-01 00:00:00|3|200|200|200|200|0|0|0|1464000|0|7320|7320 +a_3@PERMANENT||2001-07-01 00:00:00|2001-10-01 00:00:00|1|300|300|300|300|0|0|0|180000|0|600|600 +a_3@PERMANENT||2001-07-01 00:00:00|2001-10-01 00:00:00|2|300|300|300|300|0|0|0|504000|0|1680|1680 +a_3@PERMANENT||2001-07-01 00:00:00|2001-10-01 00:00:00|3|300|300|300|300|0|0|0|2196000|0|7320|7320 +a_4@PERMANENT||2001-10-01 00:00:00|2002-01-01 00:00:00|1|400|400|400|400|0|0|0|240000|0|600|600 +a_4@PERMANENT||2001-10-01 00:00:00|2002-01-01 00:00:00|2|400|400|400|400|0|0|0|672000|0|1680|1680 +a_4@PERMANENT||2001-10-01 00:00:00|2002-01-01 00:00:00|3|400|400|400|400|0|0|0|2928000|0|7320|7320 """ for ref, res in zip( From 8716ba51bc5fbc9fcfe96398fe80292c632958db Mon Sep 17 00:00:00 2001 From: Tomas Zigo <50632337+tmszi@users.noreply.github.com> Date: Fri, 8 Nov 2024 05:12:13 +0100 Subject: [PATCH 43/57] wxGUI/vdigit: fix map window focus after starting edits (#2525) --- gui/wxpython/dbmgr/manager.py | 2 ++ gui/wxpython/vdigit/toolbars.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/gui/wxpython/dbmgr/manager.py b/gui/wxpython/dbmgr/manager.py index b1cbd93ab71..c3821abb4ef 100644 --- a/gui/wxpython/dbmgr/manager.py +++ b/gui/wxpython/dbmgr/manager.py @@ -204,6 +204,8 @@ def OnCloseWindow(self, event): if self.parent and self.parent.GetName() == "LayerManager": # deregister ATM self.parent.dialogs["atm"].remove(self) + # set map window focus + self.parent.GetMapDisplay().GetMapWindow().SetFocus() if not isinstance(event, wx.CloseEvent): self.Destroy() diff --git a/gui/wxpython/vdigit/toolbars.py b/gui/wxpython/vdigit/toolbars.py index a9cafe3dfb4..09833758882 100644 --- a/gui/wxpython/vdigit/toolbars.py +++ b/gui/wxpython/vdigit/toolbars.py @@ -1035,6 +1035,8 @@ def OnSelectMap(self, event): # select the given map layer for editing self.StartEditing(self.layers[selection]) + wx.CallLater(100, self.MapWindow.SetFocus) + event.Skip() def StartEditing(self, mapLayer): From 600caae8f146ccbd3d2e2f7d0544e1559fb524d4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 8 Nov 2024 05:46:58 +0000 Subject: [PATCH 44/57] CI(deps): Update docker/dockerfile:1.11 Docker digest to 10c699f (#4669) --- Dockerfile | 2 +- docker/ubuntu/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index a3645bc558d..66b15d5970e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -# syntax=docker/dockerfile:1.11@sha256:1f2be5a2aa052cbd9aedf893d17c63277c3d1c51b3fb0f3b029c6b34f658d057 +# syntax=docker/dockerfile:1.11@sha256:10c699f1b6c8bdc8f6b4ce8974855dd8542f1768c26eb240237b8f1c9c6c9976 # Note: This file must be kept in sync in ./Dockerfile and ./docker/ubuntu/Dockerfile. # Changes to this file must be copied over to the other file. diff --git a/docker/ubuntu/Dockerfile b/docker/ubuntu/Dockerfile index a3645bc558d..66b15d5970e 100644 --- a/docker/ubuntu/Dockerfile +++ b/docker/ubuntu/Dockerfile @@ -1,4 +1,4 @@ -# syntax=docker/dockerfile:1.11@sha256:1f2be5a2aa052cbd9aedf893d17c63277c3d1c51b3fb0f3b029c6b34f658d057 +# syntax=docker/dockerfile:1.11@sha256:10c699f1b6c8bdc8f6b4ce8974855dd8542f1768c26eb240237b8f1c9c6c9976 # Note: This file must be kept in sync in ./Dockerfile and ./docker/ubuntu/Dockerfile. # Changes to this file must be copied over to the other file. From 54f206875904a70708811c33483ae852cd63fa4f Mon Sep 17 00:00:00 2001 From: Shreshth Malik Date: Fri, 8 Nov 2024 00:53:56 -0500 Subject: [PATCH 45/57] r.buffer: Added test script (#4482) * Added test script for r.buffer * Corrected input map and added tearDown method to delete temp maps * Added pre commit fixes * Added resolution for feedback * Tweaked the last test and used f string * Update raster/r.buffer/testsuite/test_buffer.py Reduced the region of the test Co-authored-by: Anna Petrasova * Corrected redudancy * Streamlined output map initialization --------- Co-authored-by: Anna Petrasova --- raster/r.buffer/testsuite/test_buffer.py | 99 ++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 raster/r.buffer/testsuite/test_buffer.py diff --git a/raster/r.buffer/testsuite/test_buffer.py b/raster/r.buffer/testsuite/test_buffer.py new file mode 100644 index 00000000000..97fea861104 --- /dev/null +++ b/raster/r.buffer/testsuite/test_buffer.py @@ -0,0 +1,99 @@ +from grass.gunittest.case import TestCase +from grass.gunittest.main import test +from grass.gunittest.gmodules import SimpleModule +import grass.script as gs + + +class TestRBuffer(TestCase): + + @classmethod + def setUpClass(cls): + """Set up a temporary region for testing.""" + cls.output = "test_buffer" + cls.use_temp_region() + cls.runModule("g.region", n=223000, s=220000, w=640000, e=643000, nsres=100) + + @classmethod + def tearDownClass(cls): + """Clean up after tests.""" + cls.del_temp_region() + + def tearDown(self): + """Remove temporary maps created during tests""" + gs.run_command( + "g.remove", + type="raster", + name="test_buffer,zero_map,null_map", + flags="f", + ) + + def test_buffer_creation(self): + """Test creating a buffer around roadsmajor with multiple distances.""" + distances = [100, 200, 300, 400, 500] + + module = SimpleModule( + "r.buffer", + input="roadsmajor", + output=self.output, + distances=distances, + overwrite=True, + ) + self.assertModule(module) + + self.assertRasterExists(self.output) + + expected_categories = [i + 1 for i in range(len(distances) + 1)] + + self.assertRasterMinMax( + map=self.output, + refmin=min(expected_categories), + refmax=max(expected_categories), + msg=f"Buffer zones should have category values from 1 to {max(expected_categories)}", + ) + + def test_no_non_null_values(self): + """Test r.buffer with null input raster resulting in an empty output.""" + null_map = "null_map" + self.runModule("r.mapcalc", expression=f"{null_map} = null()") + + distances = [100, 200, 300] + + module = SimpleModule( + "r.buffer", + input=null_map, + output=self.output, + distances=distances, + overwrite=True, + ) + self.assertModule(module) + + self.assertRasterExists(self.output) + + expected_stats = {"n": 0} + self.assertRasterFitsUnivar(self.output, reference=expected_stats) + + def test_ignore_zero_values(self): + """Test r.buffer with input raster of only zero values using -z flag.""" + zero_map = "zero_map" + self.runModule("r.mapcalc", expression=f"{zero_map} = 0") + + distances = [100] + + module = SimpleModule( + "r.buffer", + input=zero_map, + output=self.output, + distances=distances, + flags="z", + overwrite=True, + ) + self.assertModule(module) + + self.assertRasterExists(self.output) + + expected_stats = {"n": 0} + self.assertRasterFitsUnivar(self.output, reference=expected_stats) + + +if __name__ == "__main__": + test() From 12e3e5667f5adf28f099547cc65596a2c8f2dbd7 Mon Sep 17 00:00:00 2001 From: Nicklas Larsson Date: Fri, 8 Nov 2024 13:16:44 +0100 Subject: [PATCH 46/57] configure: build external libraries first (#4671) Enable use of external libraries in GRASS libraries. --- lib/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Makefile b/lib/Makefile index a313a656f36..91c38f5c73b 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -4,11 +4,11 @@ include $(MODULE_TOPDIR)/include/Make/Vars.make #order is relevant: SUBDIRS = \ + external \ datetime \ gis \ proj \ raster \ - external \ gmath \ linkm \ driver \ From 941e220799cb3e2c6d108a3585241c5ac7f9ea6f Mon Sep 17 00:00:00 2001 From: Corey White Date: Fri, 8 Nov 2024 07:45:38 -0500 Subject: [PATCH 47/57] i.vi: Add ndwi color table to output (#4668) * i.vi: Add ndwi color table to output * Changed the min max values when setting the color table --------- Co-authored-by: Corey White --- imagery/i.vi/main.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/imagery/i.vi/main.c b/imagery/i.vi/main.c index dd1ceb8d6cf..7947aee6c50 100644 --- a/imagery/i.vi/main.c +++ b/imagery/i.vi/main.c @@ -593,6 +593,16 @@ int main(int argc, char *argv[]) else G_fatal_error(_("Unknown color request '%s'"), style); } + else if (!strcasecmp(viflag, "ndwi")) { + /* apply predefined NDWI color table */ + const char *style = "ndwi"; + + if (G_find_color_rule("ndwi")) { + Rast_make_fp_colors(&colors, style, -1.0, 1.0); + } + else + G_fatal_error(_("Unknown color request '%s'"), style); + } else { /* Color from -1.0 to +1.0 in grey */ Rast_init_colors(&colors); From fddbf9f0cb38e4d67b064a8190337c5fe3f8e17c Mon Sep 17 00:00:00 2001 From: Mohan Yelugoti Date: Fri, 8 Nov 2024 07:47:18 -0500 Subject: [PATCH 48/57] lib/gis: Fix out of scope memory access error in file_name function call (#4650) lib/gis: Fix out of scope memory access error in file_name() When execution takes else path, pname, a pointer, is set to point to a local variable array which has limited scope. This same pointer is accessed outside of the block containing the local variable, essentially creating a scenario where we are accessing memory outside its score, which is undefined behavior. Move the variable array out of the loop, so that it has the same scope as pname. This was found using cppcheck tool. Signed-off-by: Mohan Yelugoti --- lib/gis/file_name.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/gis/file_name.c b/lib/gis/file_name.c index 7bf7b9d2539..a3e7bd5d786 100644 --- a/lib/gis/file_name.c +++ b/lib/gis/file_name.c @@ -161,13 +161,13 @@ char *file_name(char *path, const char *dir, const char *element, const char *name, const char *mapset, const char *base) { const char *pname = name; + char xname[GNAME_MAX] = {'\0'}; if (base && *base) { sprintf(path, "%s", base); } else { - char xname[GNAME_MAX]; - char xmapset[GMAPSET_MAX]; + char xmapset[GMAPSET_MAX] = {'\0'}; char *location = G__location_path(); /* From 177f5b441185bbd0121d2a5c81fa25a19104e529 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hern=C3=A1n=20De=20Angelis?= <51515911+dhdeangelis@users.noreply.github.com> Date: Fri, 8 Nov 2024 15:37:53 +0100 Subject: [PATCH 49/57] docs: v.rectify.html fix typos (#4619) --- vector/v.rectify/v.rectify.html | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/vector/v.rectify/v.rectify.html b/vector/v.rectify/v.rectify.html index 6bfb8e628bf..a90eefef229 100644 --- a/vector/v.rectify/v.rectify.html +++ b/vector/v.rectify/v.rectify.html @@ -46,11 +46,12 @@

Coordinate transformation and RMSE

The desired order of transformation (1, 2, or 3) is selected with the order option. -v.rectify will calculate the RMSE if the -r flag is -given and print out statistcs in tabular format. The last row gives a -summary with the first column holding the number of active points, -followed by average deviations for each dimension and both forward and -backward transformation and finally forward and backward overall RMSE. +If the -r flag is given, v.rectify will calculate the +Root Mean Square Error (RMSE) and print out statistics in tabular format. +The last row gives a summary with the first column holding the number of +active points, followed by average deviations for each dimension and both +forward and backward transformation and finally forward and backward +overall RMSE.

2D linear affine transformation (1st order transformation)

From 4f5da027b21a916e88b8670e0a63f1daf306d7a9 Mon Sep 17 00:00:00 2001 From: Arohan Ajit Date: Fri, 8 Nov 2024 09:41:56 -0500 Subject: [PATCH 50/57] temporal: Fixed bare 'except' PEP8 error (#4670) --- .flake8 | 1 - .../temporal_topology_dataset_connector.py | 22 +++++++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/.flake8 b/.flake8 index a44d0182e5f..45792c60cf7 100644 --- a/.flake8 +++ b/.flake8 @@ -74,7 +74,6 @@ per-file-ignores = python/grass/temporal/temporal_algebra.py: E722 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 # 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, F821 diff --git a/python/grass/temporal/temporal_topology_dataset_connector.py b/python/grass/temporal/temporal_topology_dataset_connector.py index fddf478ad71..a296d9d4d78 100644 --- a/python/grass/temporal/temporal_topology_dataset_connector.py +++ b/python/grass/temporal/temporal_topology_dataset_connector.py @@ -160,47 +160,47 @@ def get_number_of_temporal_relations(self): relations = {} try: relations["equal"] = len(self._temporal_topology["EQUAL"]) - except: + except KeyError: relations["equal"] = 0 try: relations["follows"] = len(self._temporal_topology["FOLLOWS"]) - except: + except KeyError: relations["follows"] = 0 try: relations["precedes"] = len(self._temporal_topology["PRECEDES"]) - except: + except KeyError: relations["precedes"] = 0 try: relations["overlaps"] = len(self._temporal_topology["OVERLAPS"]) - except: + except KeyError: relations["overlaps"] = 0 try: relations["overlapped"] = len(self._temporal_topology["OVERLAPPED"]) - except: + except KeyError: relations["overlapped"] = 0 try: relations["during"] = len(self._temporal_topology["DURING"]) - except: + except KeyError: relations["during"] = 0 try: relations["contains"] = len(self._temporal_topology["CONTAINS"]) - except: + except KeyError: relations["contains"] = 0 try: relations["starts"] = len(self._temporal_topology["STARTS"]) - except: + except KeyError: relations["starts"] = 0 try: relations["started"] = len(self._temporal_topology["STARTED"]) - except: + except KeyError: relations["started"] = 0 try: relations["finishes"] = len(self._temporal_topology["FINISHES"]) - except: + except KeyError: relations["finishes"] = 0 try: relations["finished"] = len(self._temporal_topology["FINISHED"]) - except: + except KeyError: relations["finished"] = 0 return relations From b18e390b0c9729764fbac132cd2bfa509eb1c1c4 Mon Sep 17 00:00:00 2001 From: Shreshth Malik Date: Fri, 8 Nov 2024 09:44:11 -0500 Subject: [PATCH 51/57] r.circle: Add tests for raster circle tool (#4598) --- raster/r.circle/testsuite/test_circle.py | 85 ++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 raster/r.circle/testsuite/test_circle.py diff --git a/raster/r.circle/testsuite/test_circle.py b/raster/r.circle/testsuite/test_circle.py new file mode 100644 index 00000000000..1c0a4b62f54 --- /dev/null +++ b/raster/r.circle/testsuite/test_circle.py @@ -0,0 +1,85 @@ +from grass.gunittest.case import TestCase +from grass.gunittest.main import test +import grass.script as gs +from grass.gunittest.gmodules import SimpleModule + + +class TestRCircle(TestCase): + + @classmethod + def setUpClass(cls): + """Set up a temporary region for testing.""" + cls.output = "test_circle" + cls.use_temp_region() + cls.runModule("g.region", n=30, s=0, e=30, w=0, res=10) + + @classmethod + def tearDownClass(cls): + """Clean up after tests.""" + cls.del_temp_region() + + def tearDown(self): + gs.run_command( + "g.remove", + type="raster", + name=self.output, + flags="f", + ) + + def test_create_circle_with_b_flag(self): + """Test creating a binary circle with r.circle using -b flag.""" + + module = SimpleModule( + "r.circle", output=self.output, coordinates=(15, 15), max=10, flags="b" + ) + + self.assertModule(module) + + self.assertRasterExists(self.output) + + self.assertRasterMinMax( + map=self.output, + refmin=1, + refmax=1, + msg="Binary circle should have category value of 1", + ) + + def test_create_circle_without_b_flag(self): + """Test creating a circle with r.circle without -b flag.""" + + module = SimpleModule( + "r.circle", output=self.output, coordinates=(15, 15), max=10 + ) + + self.assertModule(module) + + self.assertRasterExists(self.output) + + self.assertRasterMinMax( + map=self.output, + refmin=0, + refmax=10, + msg="Circle should have distance values from 0 to 10", + ) + + def test_create_circle_with_multiplier(self): + """Test creating a circle with r.circle with a multiplier.""" + + module = SimpleModule( + "r.circle", output=self.output, coordinates=(15, 15), max=10, multiplier=2 + ) + + self.assertModule(module) + + self.assertRasterExists(self.output) + + self.assertRasterMinMax( + map=self.output, + refmin=0, + refmax=20, + msg="Circle should have distance values from 0 to 20", + ) + + +if __name__ == "__main__": + test() From 7fe3fa57ad6c122ff63956665648695a362e15e6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 8 Nov 2024 16:48:03 -0500 Subject: [PATCH 52/57] CI(deps): Update github/codeql-action action to v3.27.1 (#4675) --- .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 d98950b0818..a31f5176124 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@662472033e021d55d94146f66f6058822b0b39fd # v3.27.0 + uses: github/codeql-action/init@4f3212b61783c3c68e8309a0f18a699764811cda # v3.27.1 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@662472033e021d55d94146f66f6058822b0b39fd # v3.27.0 + uses: github/codeql-action/analyze@4f3212b61783c3c68e8309a0f18a699764811cda # v3.27.1 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/python-code-quality.yml b/.github/workflows/python-code-quality.yml index f7f741a7bb1..55a62f4cb7e 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@662472033e021d55d94146f66f6058822b0b39fd # v3.27.0 + uses: github/codeql-action/upload-sarif@4f3212b61783c3c68e8309a0f18a699764811cda # v3.27.1 with: sarif_file: bandit.sarif From 8dced26735eba9c385a2eebd1d31d97f2b808386 Mon Sep 17 00:00:00 2001 From: Mohan Yelugoti Date: Fri, 8 Nov 2024 17:53:42 -0500 Subject: [PATCH 53/57] r3.in.v5d, r3.out.v5d: Deprecate CRAY HW specific code (#4545) Currently, there is no sign either from GitHub issues or grass-dev archive that many people are using CRAY code which was introduced 25 years ago. As part of fixing a bug, we found that it was hard to find reference materials related to CRAY, due to it being old and not in usage anymore. For this reason, deprecate CRAY code and corresponding complexity that comes with it. Signed-off-by: Mohan Yelugoti --- raster3d/r3.in.v5d/binio.c | 312 ----------------------------------- raster3d/r3.in.v5d/binio.h | 5 - raster3d/r3.in.v5d/v5d.c | 81 ---------- raster3d/r3.in.v5d/v5d.h | 4 +- raster3d/r3.out.v5d/binio.c | 315 +----------------------------------- raster3d/r3.out.v5d/binio.h | 5 - raster3d/r3.out.v5d/v5d.c | 81 ---------- raster3d/r3.out.v5d/v5d.h | 4 +- 8 files changed, 5 insertions(+), 802 deletions(-) diff --git a/raster3d/r3.in.v5d/binio.c b/raster3d/r3.in.v5d/binio.c index b47723a2929..98cf70a9fdd 100644 --- a/raster3d/r3.in.v5d/binio.c +++ b/raster3d/r3.in.v5d/binio.c @@ -32,26 +32,11 @@ * If an ANSI compiler is used prototypes and ANSI function declarations * are used. Otherwise use K&R conventions. * - * If we're running on a CRAY (8-byte ints and floats), conversions will - * be done as needed. - */ - -/* - * Updates: - * - * April 13, 1995, brianp - * added cray_to_ieee and iee_to_cray array conversion functions. - * fixed potential cray bug in write_float4_array function. - * */ #include #include #include -#ifdef _CRAY -#include -#include -#endif #include "binio.h" /**********************************************************************/ @@ -94,132 +79,6 @@ void flip2(const unsigned short *src, unsigned short *dest, int n) } } -#ifdef _CRAY - -/***************************************************************************** - * - * The following source code is in the public domain. - * Specifically, we give to the public domain all rights for future licensing - * of the source code, all resale rights, and all publishing rights. - * - * We ask, but do not require, that the following message be included in all - * derived works: - * - * Portions developed at the National Center for Supercomputing Applications at - * the University of Illinois at Urbana-Champaign. - * - * THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE - * SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION, - * WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE - * - ****************************************************************************/ - -/** THESE ROUTINES MUST BE COMPILED ON THE CRAY ONLY SINCE THEY **/ - -/** REQUIRE 8-BYTES PER C-TYPE LONG **/ - -/* Cray to IEEE single precision */ -static void c_to_if(long *t, const long *f) -{ - if (*f != 0) { - *t = (((*f & 0x8000000000000000) | /* sign bit */ - ((((*f & 0x7fff000000000000) >> 48) - 16258) << 55)) + /* exp */ - (((*f & 0x00007fffff000000) + ((*f & 0x0000000000800000) << 1)) - << 8)); /* mantissa */ - } - else - *t = *f; -} - -#define C_TO_IF(T, F) \ - if (F != 0) { \ - T = (((F & 0x8000000000000000) | \ - ((((F & 0x7fff000000000000) >> 48) - 16258) << 55)) + \ - (((F & 0x00007fffff000000) + ((F & 0x0000000000800000) << 1)) \ - << 8)); \ - } \ - else { \ - T = F; \ - } - -/* IEEE single precision to Cray */ -static void if_to_c(long *t, const long *f) -{ - if (*f != 0) { - *t = (((*f & 0x8000000000000000) | - ((*f & 0x7f80000000000000) >> 7) + (16258L << 48)) | - (((*f & 0x007fffff00000000) >> 8) | (0x0000800000000000))); - if ((*f << 1) == 0) - *t = 0; - } - else - *t = *f; -} - -/* T and F must be longs! */ -#define IF_TO_C(T, F) \ - if (F != 0) { \ - T = (((F & 0x8000000000000000) | \ - ((F & 0x7f80000000000000) >> 7) + (16258L << 48)) | \ - (((F & 0x007fffff00000000) >> 8) | (0x0000800000000000))); \ - if ((F << 1) == 0) \ - T = 0; \ - } \ - else { \ - T = F; \ - } - -/* - * Convert an array of Cray 8-byte floats to an array of IEEE 4-byte floats. - */ -void cray_to_ieee_array(long *dest, const float *source, int n) -{ - long *dst; - const long *src; - long tmp1, tmp2; - int i; - - dst = dest; - src = (const long *)source; - - for (i = 0; i < n; i += 2) { /* add 1 in case n is odd */ - c_to_if(&tmp1, &src[i]); - c_to_if(&tmp2, &src[i + 1]); - *dst = (tmp1 & 0xffffffff00000000) | (tmp2 >> 32); - dst++; - } -} - -/* - * Convert an array of IEEE 4-byte floats to an array of 8-byte Cray floats. - */ -void ieee_to_cray_array(float *dest, const long *source, int n) -{ - long *dst; - const long *src; - int i; - long ieee; - - src = source; - dst = (long *)dest; - - for (i = 0; i < n; i++) { - /* most significant 4-bytes of ieee contain bit pattern to convert */ - if ((i & 1) == 0) { - /* get upper half */ - ieee = src[i / 2] & 0xffffffff00000000; - } - else { - /* get lower half */ - ieee = src[i / 2] << 32; - } - if_to_c(dst, &ieee); - dst++; - } -} - -#endif /*_CRAY*/ - /**********************************************************************/ /***** Read Functions *****/ @@ -247,25 +106,6 @@ int read_bytes(int f, void *b, int n) */ int read_int2_array(int f, short *iarray, int n) { -#ifdef _CRAY - int i; - signed char *buffer; - int nread; - - buffer = (signed char *)G_malloc(n * 2); - if (!buffer) - return 0; - nread = read(f, buffer, n * 2); - if (nread <= 0) - return 0; - nread /= 2; - for (i = 0; i < nread; i++) { - /* don't forget about sign extension! */ - iarray[i] = (buffer[i * 2] * 256) | buffer[i * 2 + 1]; - } - G_free(buffer); - return nread; -#else int nread = read(f, iarray, n * 2); if (nread <= 0) @@ -274,7 +114,6 @@ int read_int2_array(int f, short *iarray, int n) flip2((const unsigned short *)iarray, (unsigned short *)iarray, nread / 2); #endif return nread / 2; -#endif } /* @@ -286,24 +125,6 @@ int read_int2_array(int f, short *iarray, int n) */ int read_uint2_array(int f, unsigned short *iarray, int n) { -#ifdef _CRAY - int i; - unsigned char *buffer; - int nread; - - buffer = (unsigned char *)G_malloc(n * 2); - if (!buffer) - return 0; - nread = read(f, buffer, n * 2); - if (nread <= 0) - return 0; - nread /= 2; - for (i = 0; i < nread; i++) { - iarray[i] = (buffer[i * 2] << 8) | buffer[i * 2 + 1]; - } - G_free(buffer); - return nread; -#else int nread = read(f, iarray, n * 2); if (nread <= 0) @@ -312,7 +133,6 @@ int read_uint2_array(int f, unsigned short *iarray, int n) flip2(iarray, iarray, nread / 2); #endif return nread / 2; -#endif } /* @@ -336,9 +156,6 @@ int read_int4(int f, int *i) } #else if (read(f, i, 4) == 4) { -#ifdef _CRAY - *i = *i >> 32; -#endif return 1; } else { @@ -356,30 +173,6 @@ int read_int4(int f, int *i) */ int read_int4_array(int f, int *iarray, int n) { -#ifdef _CRAY - int j, nread; - int *buffer; - - buffer = (int *)G_malloc((n + 1) * 4); - if (!buffer) - return 0; - nread = read(f, buffer, 4 * n); - if (nread <= 0) { - return 0; - } - nread /= 4; - - for (j = 0; j < nread; j++) { - if ((j & 1) == 0) { - iarray[j] = buffer[j / 2] >> 32; - } - else { - iarray[j] = buffer[j / 2] & 0xffffffff; - } - } - G_free(buffer); - return nread; -#else int nread = read(f, iarray, 4 * n); if (nread <= 0) @@ -388,7 +181,6 @@ int read_int4_array(int f, int *iarray, int n) flip4((const unsigned int *)iarray, (unsigned int *)iarray, nread / 4); #endif return nread / 4; -#endif } /* @@ -399,16 +191,6 @@ int read_int4_array(int f, int *iarray, int n) */ int read_float4(int f, float *x) { -#ifdef _CRAY - long buffer = 0; - - if (read(f, &buffer, 4) == 4) { - /* convert IEEE float (buffer) to Cray float (x) */ - if_to_c((long *)x, &buffer); - return 1; - } - return 0; -#else #ifdef LITTLE unsigned int n, *iptr; @@ -428,7 +210,6 @@ int read_float4(int f, float *x) return 0; } #endif -#endif } /* @@ -440,22 +221,6 @@ int read_float4(int f, float *x) */ int read_float4_array(int f, float *x, int n) { -#ifdef _CRAY - /* read IEEE floats into buffer, then convert to Cray format */ - long *buffer; - int i, nread; - - buffer = (long *)G_malloc((n + 1) * 4); - if (!buffer) - return 0; - nread = read(f, buffer, n * 4); - if (nread <= 0) - return 0; - nread /= 4; - ieee_to_cray_array(x, buffer, nread); - G_free(buffer); - return nread; -#else int nread = read(f, x, 4 * n); if (nread <= 0) @@ -464,7 +229,6 @@ int read_float4_array(int f, float *x, int n) flip4((const unsigned int *)x, (unsigned int *)x, nread / 4); #endif return nread / 4; -#endif } /* @@ -541,10 +305,6 @@ int write_bytes(int f, const void *b, int n) */ int write_int2_array(int f, const short *iarray, int n) { -#ifdef _CRAY - printf("write_int2_array not implemented!\n"); - exit(1); -#else int nwritten; #ifdef LITTLE @@ -557,7 +317,6 @@ int write_int2_array(int f, const short *iarray, int n) if (nwritten <= 0) return 0; return nwritten / 2; -#endif } /* @@ -569,24 +328,6 @@ int write_int2_array(int f, const short *iarray, int n) */ int write_uint2_array(int f, const unsigned short *iarray, int n) { -#ifdef _CRAY - int i, nwritten; - unsigned char *buffer; - - buffer = (unsigned char *)G_malloc(2 * n); - if (!buffer) - return 0; - for (i = 0; i < n; i++) { - buffer[i * 2] = (iarray[i] >> 8) & 0xff; - buffer[i * 2 + 1] = iarray[i] & 0xff; - } - nwritten = write(f, buffer, 2 * n); - G_free(buffer); - if (nwritten <= 0) - return 0; - else - return nwritten / 2; -#else int nwritten; #ifdef LITTLE @@ -600,7 +341,6 @@ int write_uint2_array(int f, const unsigned short *iarray, int n) return 0; else return nwritten / 2; -#endif } /* @@ -611,15 +351,10 @@ int write_uint2_array(int f, const unsigned short *iarray, int n) */ int write_int4(int f, int i) { -#ifdef _CRAY - i = i << 32; - return write(f, &i, 4) > 0; -#else #ifdef LITTLE i = FLIP4(i); #endif return write(f, &i, 4) > 0; -#endif } /* @@ -631,28 +366,6 @@ int write_int4(int f, int i) */ int write_int4_array(int f, const int *i, int n) { -#ifdef _CRAY - int j, nwritten; - char *buf, *b, *ptr; - - b = buf = (char *)G_malloc(n * 4 + 8); - if (!b) - return 0; - ptr = (char *)i; - for (j = 0; j < n; j++) { - ptr += 4; /* skip upper 4 bytes */ - *b++ = *ptr++; - *b++ = *ptr++; - *b++ = *ptr++; - *b++ = *ptr++; - } - nwritten = write(f, buf, 4 * n); - G_free(buf); - if (nwritten <= 0) - return 0; - else - return nwritten / 4; -#else #ifdef LITTLE int nwritten; @@ -666,7 +379,6 @@ int write_int4_array(int f, const int *i, int n) #else return write(f, i, 4 * n) / 4; #endif -#endif } /* @@ -677,12 +389,6 @@ int write_int4_array(int f, const int *i, int n) */ int write_float4(int f, float x) { -#ifdef _CRAY - char buffer[8]; - - c_to_if((long *)buffer, (const long *)&x); - return write(f, buffer, 4) > 0; -#else #ifdef LITTLE float y; unsigned int *iptr = (unsigned int *)&y, temp; @@ -696,7 +402,6 @@ int write_float4(int f, float x) y = (float)x; return write(f, &y, 4) > 0; #endif -#endif } /* @@ -708,22 +413,6 @@ int write_float4(int f, float x) */ int write_float4_array(int f, const float *x, int n) { -#ifdef _CRAY - /* convert cray floats to IEEE and put into buffer */ - int nwritten; - long *buffer; - - buffer = (long *)G_malloc(n * 4 + 8); - if (!buffer) - return 0; - cray_to_ieee_array(buffer, x, n); - nwritten = write(f, buffer, 4 * n); - G_free(buffer); - if (nwritten <= 0) - return 0; - else - return nwritten / 4; -#else #ifdef LITTLE int nwritten; @@ -737,7 +426,6 @@ int write_float4_array(int f, const float *x, int n) #else return write(f, x, 4 * n) / 4; #endif -#endif } /* diff --git a/raster3d/r3.in.v5d/binio.h b/raster3d/r3.in.v5d/binio.h index f987e3cf64b..e6a80d8a9db 100644 --- a/raster3d/r3.in.v5d/binio.h +++ b/raster3d/r3.in.v5d/binio.h @@ -37,11 +37,6 @@ extern void flip4(const unsigned int *src, unsigned int *dest, int n); extern void flip2(const unsigned short *src, unsigned short *dest, int n); -#ifdef _CRAY -extern void cray_to_ieee_array(long *dest, const float *source, int n); -extern void ieee_to_cray_array(float *dest, const long *source, int n); -#endif - /**********************************************************************/ /***** Read Functions *****/ diff --git a/raster3d/r3.in.v5d/v5d.c b/raster3d/r3.in.v5d/v5d.c index 54f75f2361a..ef9f7487ae3 100644 --- a/raster3d/r3.in.v5d/v5d.c +++ b/raster3d/r3.in.v5d/v5d.c @@ -49,13 +49,6 @@ * values are in IEEE format. */ -/* - * Updates: - * - * April 13, 1995, brianp - * finished Cray support for 2-byte and 4-byte compress modes - */ - #include #include #include @@ -721,21 +714,6 @@ void v5dCompressGrid(int nr, int nc, int nl, int compressmode, else { one_over_a = 1.0 / ga[lev]; } -#ifdef _CRAY - /* this is tricky because sizeof(V5Dushort)==8, not 2 */ - for (i = 0; i < nrnc; i++, p++) { - V5Dushort compvalue; - - if (IS_MISSING(data[p])) { - compvalue = 65535; - } - else { - compvalue = (V5Dushort)(int)((data[p] - b) * one_over_a); - } - compdata1[p * 2 + 0] = compvalue >> 8; /* upper byte */ - compdata1[p * 2 + 1] = compvalue & 0xffu; /* lower byte */ - } -#else for (i = 0; i < nrnc; i++, p++) { if (IS_MISSING(data[p])) { compdata2[p] = 65535; @@ -745,20 +723,14 @@ void v5dCompressGrid(int nr, int nc, int nl, int compressmode, } } /* TODO: byte-swapping on little endian??? */ -#endif } } else { /* compressmode==4 */ -#ifdef _CRAY - cray_to_ieee_array(compdata, data, nrncnl); -#else - /* other machines: just copy 4-byte IEEE floats */ assert(sizeof(float) == 4); memcpy(compdata, data, nrncnl * 4); /* TODO: byte-swapping on little endian??? */ -#endif } } @@ -834,20 +806,6 @@ void v5dDecompressGrid(int nr, int nc, int nl, int compressmode, void *compdata, float a = ga[lev]; float b = gb[lev]; -#ifdef _CRAY - /* this is tricky because sizeof(V5Dushort)==8, not 2 */ - for (i = 0; i < nrnc; i++, p++) { - int compvalue; - - compvalue = (compdata1[p * 2] << 8) | compdata1[p * 2 + 1]; - if (compvalue == 65535) { - data[p] = MISSING; - } - else { - data[p] = (float)compvalue * a + b; - } - } -#else /* sizeof(V5Dushort)==2! */ for (i = 0; i < nrnc; i++, p++) { if (compdata2[p] == 65535) { @@ -857,19 +815,13 @@ void v5dDecompressGrid(int nr, int nc, int nl, int compressmode, void *compdata, data[p] = (float)(int)compdata2[p] * a + b; } } -#endif } } else { /* compressmode==4 */ -#ifdef _CRAY - ieee_to_cray_array(data, compdata, nrncnl); -#else - /* other machines: just copy 4-byte IEEE floats */ assert(sizeof(float) == 4); memcpy(data, compdata, nrncnl * 4); -#endif } } @@ -2720,11 +2672,7 @@ int v5dClose(void) #ifdef UNDERSCORE int v5dcreate_ #else -#ifdef _CRAY -int V5DCREATE -#else int v5dcreate -#endif #endif (const char *name, const int *numtimes, const int *numvars, const int *nr, @@ -2883,11 +2831,7 @@ int v5dcreate #ifdef UNDERSCORE int v5dcreatesimple_ #else -#ifdef _CRAY -int V5DCREATESIMPLE -#else int v5dcreatesimple -#endif #endif (const char *name, const int *numtimes, const int *numvars, const int *nr, @@ -2920,12 +2864,7 @@ int v5dcreatesimple #ifdef UNDERSCORE return v5dcreate_ #else -#ifdef _CRAY - return V5DCREATE -#else - return v5dcreate -#endif #endif (name, numtimes, numvars, nr, nc, varnl, varname, timestamp, datestamp, &compressmode, &projection, projarg, &vertical, vertarg); @@ -2939,11 +2878,7 @@ int v5dcreatesimple #ifdef UNDERSCORE int v5dsetlowlev_ #else -#ifdef _CRAY -int V5DSETLOWLEV -#else int v5dsetlowlev -#endif #endif (int *lowlev) { @@ -2959,11 +2894,7 @@ int v5dsetlowlev #ifdef UNDERSCORE int v5dsetunits_ #else -#ifdef _CRAY -int V5DSETUNITS -#else int v5dsetunits -#endif #endif (int *var, char *name) { @@ -2980,11 +2911,7 @@ int v5dsetunits #ifdef UNDERSCORE int v5dwrite_ #else -#ifdef _CRAY -int V5DWRITE -#else int v5dwrite -#endif #endif (const int *time, const int *var, const float *data) { @@ -3001,11 +2928,7 @@ int v5dwrite #ifdef UNDERSCORE int v5dmcfile_ #else -#ifdef _CRAY -int V5DMCFILE -#else int v5dmcfile -#endif #endif (const int *time, const int *var, const int *mcfile, const int *mcgrid) { @@ -3029,12 +2952,8 @@ int v5dmcfile #ifdef UNDERSCORE int v5dclose_(void) #else -#ifdef _CRAY -int V5DCLOSE(void) -#else int v5dclose(void) #endif -#endif { return v5dClose(); } diff --git a/raster3d/r3.in.v5d/v5d.h b/raster3d/r3.in.v5d/v5d.h index 49a604416fa..b2c985dca12 100644 --- a/raster3d/r3.in.v5d/v5d.h +++ b/raster3d/r3.in.v5d/v5d.h @@ -43,8 +43,8 @@ * Define our own 1 and 2-byte data types. We use these names to avoid * collisions with types defined by the OS include files. */ -typedef unsigned char V5Dubyte; /* Must be 1 byte, except for cray */ -typedef unsigned short V5Dushort; /* Must be 2 byte, except for cray */ +typedef unsigned char V5Dubyte; /* Must be 1 byte */ +typedef unsigned short V5Dushort; /* Must be 2 byte */ #define MISSING 1.0e35 #define IS_MISSING(X) ((X) >= 1.0e30) diff --git a/raster3d/r3.out.v5d/binio.c b/raster3d/r3.out.v5d/binio.c index f8582e97313..54b1d1a74e3 100644 --- a/raster3d/r3.out.v5d/binio.c +++ b/raster3d/r3.out.v5d/binio.c @@ -32,26 +32,11 @@ * If an ANSI compiler is used prototypes and ANSI function declarations * are used. Otherwise use K&R conventions. * - * If we're running on a CRAY (8-byte ints and floats), conversions will - * be done as needed. - */ - -/* - * Updates: - * - * April 13, 1995, brianp - * added cray_to_ieee and iee_to_cray array conversion functions. - * fixed potential cray bug in write_float4_array function. - * */ #include #include #include -#ifdef _CRAY -#include -#include -#endif #include "binio.h" /**********************************************************************/ @@ -94,132 +79,6 @@ void flip2(const unsigned short *src, unsigned short *dest, int n) } } -#ifdef _CRAY - -/***************************************************************************** - * - * The following source code is in the public domain. - * Specifically, we give to the public domain all rights for future licensing - * of the source code, all resale rights, and all publishing rights. - * - * We ask, but do not require, that the following message be included in all - * derived works: - * - * Portions developed at the National Center for Supercomputing Applications at - * the University of Illinois at Urbana-Champaign. - * - * THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE - * SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION, - * WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE - * - ****************************************************************************/ - -/** THESE ROUTINES MUST BE COMPILED ON THE CRAY ONLY SINCE THEY **/ - -/** REQUIRE 8-BYTES PER C-TYPE LONG **/ - -/* Cray to IEEE single precision */ -static void c_to_if(long *t, const long *f) -{ - if (*f != 0) { - *t = (((*f & 0x8000000000000000) | /* sign bit */ - ((((*f & 0x7fff000000000000) >> 48) - 16258) << 55)) + /* exp */ - (((*f & 0x00007fffff000000) + ((*f & 0x0000000000800000) << 1)) - << 8)); /* mantissa */ - } - else - *t = *f; -} - -#define C_TO_IF(T, F) \ - if (F != 0) { \ - T = (((F & 0x8000000000000000) | \ - ((((F & 0x7fff000000000000) >> 48) - 16258) << 55)) + \ - (((F & 0x00007fffff000000) + ((F & 0x0000000000800000) << 1)) \ - << 8)); \ - } \ - else { \ - T = F; \ - } - -/* IEEE single precision to Cray */ -static void if_to_c(long *t, const long *f) -{ - if (*f != 0) { - *t = (((*f & 0x8000000000000000) | - ((*f & 0x7f80000000000000) >> 7) + (16258 << 48)) | - (((*f & 0x007fffff00000000) >> 8) | (0x0000800000000000))); - if ((*f << 1) == 0) - *t = 0; - } - else - *t = *f; -} - -/* T and F must be longs! */ -#define IF_TO_C(T, F) \ - if (F != 0) { \ - T = (((F & 0x8000000000000000) | \ - ((F & 0x7f80000000000000) >> 7) + (16258 << 48)) | \ - (((F & 0x007fffff00000000) >> 8) | (0x0000800000000000))); \ - if ((F << 1) == 0) \ - T = 0; \ - } \ - else { \ - T = F; \ - } - -/* - * Convert an array of Cray 8-byte floats to an array of IEEE 4-byte floats. - */ -void cray_to_ieee_array(long *dest, const float *source, int n) -{ - long *dst; - const long *src; - long tmp1, tmp2; - int i; - - dst = dest; - src = (const long *)source; - - for (i = 0; i < n; i += 2) { /* add 1 in case n is odd */ - c_to_if(&tmp1, &src[i]); - c_to_if(&tmp2, &src[i + 1]); - *dst = (tmp1 & 0xffffffff00000000) | (tmp2 >> 32); - dst++; - } -} - -/* - * Convert an array of IEEE 4-byte floats to an array of 8-byte Cray floats. - */ -void ieee_to_cray_array(float *dest, const long *source, int n) -{ - long *dst; - const long *src; - int i; - long ieee; - - src = source; - dst = (long *)dest; - - for (i = 0; i < n; i++) { - /* most significant 4-bytes of ieee contain bit pattern to convert */ - if ((i & 1) == 0) { - /* get upper half */ - ieee = src[i / 2] & 0xffffffff00000000; - } - else { - /* get lower half */ - ieee = src[i / 2] << 32; - } - if_to_c(dst, &ieee); - dst++; - } -} - -#endif /*_CRAY*/ - /**********************************************************************/ /***** Read Functions *****/ @@ -247,25 +106,6 @@ int read_bytes(int f, void *b, int n) */ int read_int2_array(int f, short *iarray, int n) { -#ifdef _CRAY - int i; - signed char *buffer; - int nread; - - buffer = (signed char *)G_malloc(n * 2); - if (!buffer) - return 0; - nread = read(f, buffer, n * 2); - if (nread <= 0) - return 0; - nread /= 2; - for (i = 0; i < nread; i++) { - /* don't forget about sign extension! */ - iarray[i] = (buffer[i * 2] * 256) | buffer[i * 2 + 1]; - } - G_free(buffer); - return nread; -#else int nread = read(f, iarray, n * 2); if (nread <= 0) @@ -274,7 +114,6 @@ int read_int2_array(int f, short *iarray, int n) flip2((const unsigned short *)iarray, (unsigned short *)iarray, nread / 2); #endif return nread / 2; -#endif } /* @@ -286,24 +125,6 @@ int read_int2_array(int f, short *iarray, int n) */ int read_uint2_array(int f, unsigned short *iarray, int n) { -#ifdef _CRAY - int i; - unsigned char *buffer; - int nread; - - buffer = (unsigned char *)G_malloc(n * 2); - if (!buffer) - return 0; - nread = read(f, buffer, n * 2); - if (nread <= 0) - return 0; - nread /= 2; - for (i = 0; i < nread; i++) { - iarray[i] = (buffer[i * 2] << 8) | buffer[i * 2 + 1]; - } - G_free(buffer); - return nread; -#else int nread = read(f, iarray, n * 2); if (nread <= 0) @@ -312,7 +133,6 @@ int read_uint2_array(int f, unsigned short *iarray, int n) flip2(iarray, iarray, nread / 2); #endif return nread / 2; -#endif } /* @@ -336,9 +156,6 @@ int read_int4(int f, int *i) } #else if (read(f, i, 4) == 4) { -#ifdef _CRAY - *i = *i >> 32; -#endif return 1; } else { @@ -356,30 +173,6 @@ int read_int4(int f, int *i) */ int read_int4_array(int f, int *iarray, int n) { -#ifdef _CRAY - int j, nread; - int *buffer; - - buffer = (int *)G_malloc((n + 1) * 4); - if (!buffer) - return 0; - nread = read(f, buffer, 4 * n); - if (nread <= 0) { - return 0; - } - nread /= 4; - - for (j = 0; j < nread; j++) { - if ((j & 1) == 0) { - iarray[j] = buffer[j / 2] >> 32; - } - else { - iarray[j] = buffer[j / 2] & 0xffffffff; - } - } - G_free(buffer); - return nread; -#else int nread = read(f, iarray, 4 * n); if (nread <= 0) @@ -388,7 +181,6 @@ int read_int4_array(int f, int *iarray, int n) flip4((const unsigned int *)iarray, (unsigned int *)iarray, nread / 4); #endif return nread / 4; -#endif } /* @@ -399,16 +191,6 @@ int read_int4_array(int f, int *iarray, int n) */ int read_float4(int f, float *x) { -#ifdef _CRAY - long buffer = 0; - - if (read(f, &buffer, 4) == 4) { - /* convert IEEE float (buffer) to Cray float (x) */ - if_to_c((long *)x, &buffer); - return 1; - } - return 0; -#else #ifdef LITTLE unsigned int n, *iptr; @@ -420,15 +202,13 @@ int read_float4(int f, float *x) else { return 0; } -#else +#endif if (read(f, x, 4) == 4) { return 1; } else { return 0; } -#endif -#endif } /* @@ -440,22 +220,6 @@ int read_float4(int f, float *x) */ int read_float4_array(int f, float *x, int n) { -#ifdef _CRAY - /* read IEEE floats into buffer, then convert to Cray format */ - long *buffer; - int i, nread; - - buffer = (long *)G_malloc((n + 1) * 4); - if (!buffer) - return 0; - nread = read(f, buffer, n * 4); - if (nread <= 0) - return 0; - nread /= 4; - ieee_to_cray_array(x, buffer, nread); - G_free(buffer); - return nread; -#else int nread = read(f, x, 4 * n); if (nread <= 0) @@ -464,7 +228,6 @@ int read_float4_array(int f, float *x, int n) flip4((const unsigned int *)x, (unsigned int *)x, nread / 4); #endif return nread / 4; -#endif } /* @@ -541,10 +304,6 @@ int write_bytes(int f, const void *b, int n) */ int write_int2_array(int f, const short *iarray, int n) { -#ifdef _CRAY - printf("write_int2_array not implemented!\n"); - exit(1); -#else int nwritten; #ifdef LITTLE @@ -557,7 +316,6 @@ int write_int2_array(int f, const short *iarray, int n) if (nwritten <= 0) return 0; return nwritten / 2; -#endif } /* @@ -569,24 +327,6 @@ int write_int2_array(int f, const short *iarray, int n) */ int write_uint2_array(int f, const unsigned short *iarray, int n) { -#ifdef _CRAY - int i, nwritten; - unsigned char *buffer; - - buffer = (unsigned char *)G_malloc(2 * n); - if (!buffer) - return 0; - for (i = 0; i < n; i++) { - buffer[i * 2] = (iarray[i] >> 8) & 0xff; - buffer[i * 2 + 1] = iarray[i] & 0xff; - } - nwritten = write(f, buffer, 2 * n); - G_free(buffer); - if (nwritten <= 0) - return 0; - else - return nwritten / 2; -#else int nwritten; #ifdef LITTLE @@ -600,7 +340,6 @@ int write_uint2_array(int f, const unsigned short *iarray, int n) return 0; else return nwritten / 2; -#endif } /* @@ -611,15 +350,10 @@ int write_uint2_array(int f, const unsigned short *iarray, int n) */ int write_int4(int f, int i) { -#ifdef _CRAY - i = i << 32; - return write(f, &i, 4) > 0; -#else #ifdef LITTLE i = FLIP4(i); #endif return write(f, &i, 4) > 0; -#endif } /* @@ -631,28 +365,6 @@ int write_int4(int f, int i) */ int write_int4_array(int f, const int *i, int n) { -#ifdef _CRAY - int j, nwritten; - char *buf, *b, *ptr; - - b = buf = (char *)G_malloc(n * 4 + 8); - if (!b) - return 0; - ptr = (char *)i; - for (j = 0; j < n; j++) { - ptr += 4; /* skip upper 4 bytes */ - *b++ = *ptr++; - *b++ = *ptr++; - *b++ = *ptr++; - *b++ = *ptr++; - } - nwritten = write(f, buf, 4 * n); - G_free(buf); - if (nwritten <= 0) - return 0; - else - return nwritten / 4; -#else #ifdef LITTLE int nwritten; @@ -666,7 +378,6 @@ int write_int4_array(int f, const int *i, int n) #else return write(f, i, 4 * n) / 4; #endif -#endif } /* @@ -677,12 +388,6 @@ int write_int4_array(int f, const int *i, int n) */ int write_float4(int f, float x) { -#ifdef _CRAY - char buffer[8]; - - c_to_if((long *)buffer, (const long *)&x); - return write(f, buffer, 4) > 0; -#else #ifdef LITTLE float y; unsigned int *iptr = (unsigned int *)&y, temp; @@ -696,7 +401,6 @@ int write_float4(int f, float x) y = (float)x; return write(f, &y, 4) > 0; #endif -#endif } /* @@ -708,22 +412,6 @@ int write_float4(int f, float x) */ int write_float4_array(int f, const float *x, int n) { -#ifdef _CRAY - /* convert cray floats to IEEE and put into buffer */ - int nwritten; - long *buffer; - - buffer = (long *)G_malloc(n * 4 + 8); - if (!buffer) - return 0; - cray_to_ieee_array(buffer, x, n); - nwritten = write(f, buffer, 4 * n); - G_free(buffer); - if (nwritten <= 0) - return 0; - else - return nwritten / 4; -#else #ifdef LITTLE int nwritten; @@ -737,7 +425,6 @@ int write_float4_array(int f, const float *x, int n) #else return write(f, x, 4 * n) / 4; #endif -#endif } /* diff --git a/raster3d/r3.out.v5d/binio.h b/raster3d/r3.out.v5d/binio.h index f987e3cf64b..e6a80d8a9db 100644 --- a/raster3d/r3.out.v5d/binio.h +++ b/raster3d/r3.out.v5d/binio.h @@ -37,11 +37,6 @@ extern void flip4(const unsigned int *src, unsigned int *dest, int n); extern void flip2(const unsigned short *src, unsigned short *dest, int n); -#ifdef _CRAY -extern void cray_to_ieee_array(long *dest, const float *source, int n); -extern void ieee_to_cray_array(float *dest, const long *source, int n); -#endif - /**********************************************************************/ /***** Read Functions *****/ diff --git a/raster3d/r3.out.v5d/v5d.c b/raster3d/r3.out.v5d/v5d.c index a68fe75928e..f44bbc1a86a 100644 --- a/raster3d/r3.out.v5d/v5d.c +++ b/raster3d/r3.out.v5d/v5d.c @@ -49,13 +49,6 @@ * values are in IEEE format. */ -/* - * Updates: - * - * April 13, 1995, brianp - * finished Cray support for 2-byte and 4-byte compress modes - */ - #include #include #include @@ -719,21 +712,6 @@ void v5dCompressGrid(int nr, int nc, int nl, int compressmode, else { one_over_a = 1.0 / ga[lev]; } -#ifdef _CRAY - /* this is tricky because sizeof(V5Dushort)==8, not 2 */ - for (i = 0; i < nrnc; i++, p++) { - V5Dushort compvalue; - - if (IS_MISSING(data[p])) { - compvalue = 65535; - } - else { - compvalue = (V5Dushort)(int)((data[p] - b) * one_over_a); - } - compdata1[p * 2 + 0] = compvalue >> 8; /* upper byte */ - compdata1[p * 2 + 1] = compvalue & 0xffu; /* lower byte */ - } -#else for (i = 0; i < nrnc; i++, p++) { if (IS_MISSING(data[p])) { compdata2[p] = 65535; @@ -743,20 +721,14 @@ void v5dCompressGrid(int nr, int nc, int nl, int compressmode, } } /* TODO: byte-swapping on little endian??? */ -#endif } } else { /* compressmode==4 */ -#ifdef _CRAY - cray_to_ieee_array(compdata, data, nrncnl); -#else - /* other machines: just copy 4-byte IEEE floats */ assert(sizeof(float) == 4); memcpy(compdata, data, nrncnl * 4); /* TODO: byte-swapping on little endian??? */ -#endif } } @@ -832,20 +804,6 @@ void v5dDecompressGrid(int nr, int nc, int nl, int compressmode, void *compdata, float a = ga[lev]; float b = gb[lev]; -#ifdef _CRAY - /* this is tricky because sizeof(V5Dushort)==8, not 2 */ - for (i = 0; i < nrnc; i++, p++) { - int compvalue; - - compvalue = (compdata1[p * 2] << 8) | compdata1[p * 2 + 1]; - if (compvalue == 65535) { - data[p] = MISSING; - } - else { - data[p] = (float)compvalue * a + b; - } - } -#else /* sizeof(V5Dushort)==2! */ for (i = 0; i < nrnc; i++, p++) { if (compdata2[p] == 65535) { @@ -855,19 +813,13 @@ void v5dDecompressGrid(int nr, int nc, int nl, int compressmode, void *compdata, data[p] = (float)(int)compdata2[p] * a + b; } } -#endif } } else { /* compressmode==4 */ -#ifdef _CRAY - ieee_to_cray_array(data, compdata, nrncnl); -#else - /* other machines: just copy 4-byte IEEE floats */ assert(sizeof(float) == 4); memcpy(data, compdata, nrncnl * 4); -#endif } } @@ -2687,11 +2639,7 @@ int v5dClose(void) #ifdef UNDERSCORE int v5dcreate_ #else -#ifdef _CRAY -int V5DCREATE -#else int v5dcreate -#endif #endif (const char *name, const int *numtimes, const int *numvars, const int *nr, @@ -2850,11 +2798,7 @@ int v5dcreate #ifdef UNDERSCORE int v5dcreatesimple_ #else -#ifdef _CRAY -int V5DCREATESIMPLE -#else int v5dcreatesimple -#endif #endif (const char *name, const int *numtimes, const int *numvars, const int *nr, @@ -2887,12 +2831,7 @@ int v5dcreatesimple #ifdef UNDERSCORE return v5dcreate_ #else -#ifdef _CRAY - return V5DCREATE -#else - return v5dcreate -#endif #endif (name, numtimes, numvars, nr, nc, varnl, varname, timestamp, datestamp, &compressmode, &projection, projarg, &vertical, vertarg); @@ -2906,11 +2845,7 @@ int v5dcreatesimple #ifdef UNDERSCORE int v5dsetlowlev_ #else -#ifdef _CRAY -int V5DSETLOWLEV -#else int v5dsetlowlev -#endif #endif (int *lowlev) { @@ -2926,11 +2861,7 @@ int v5dsetlowlev #ifdef UNDERSCORE int v5dsetunits_ #else -#ifdef _CRAY -int V5DSETUNITS -#else int v5dsetunits -#endif #endif (int *var, char *name) { @@ -2947,11 +2878,7 @@ int v5dsetunits #ifdef UNDERSCORE int v5dwrite_ #else -#ifdef _CRAY -int V5DWRITE -#else int v5dwrite -#endif #endif (const int *time, const int *var, const float *data) { @@ -2968,11 +2895,7 @@ int v5dwrite #ifdef UNDERSCORE int v5dmcfile_ #else -#ifdef _CRAY -int V5DMCFILE -#else int v5dmcfile -#endif #endif (const int *time, const int *var, const int *mcfile, const int *mcgrid) { @@ -2996,12 +2919,8 @@ int v5dmcfile #ifdef UNDERSCORE int v5dclose_(void) #else -#ifdef _CRAY -int V5DCLOSE(void) -#else int v5dclose(void) #endif -#endif { return v5dClose(); } diff --git a/raster3d/r3.out.v5d/v5d.h b/raster3d/r3.out.v5d/v5d.h index b7675d8b501..d027d85011d 100644 --- a/raster3d/r3.out.v5d/v5d.h +++ b/raster3d/r3.out.v5d/v5d.h @@ -43,8 +43,8 @@ * Define our own 1 and 2-byte data types. We use these names to avoid * collisions with types defined by the OS include files. */ -typedef unsigned char V5Dubyte; /* Must be 1 byte, except for cray */ -typedef unsigned short V5Dushort; /* Must be 2 byte, except for cray */ +typedef unsigned char V5Dubyte; /* Must be 1 byte */ +typedef unsigned short V5Dushort; /* Must be 2 byte */ #define MISSING 1.0e35 #define IS_MISSING(X) ((X) >= 1.0e30) From 8c4f244c9533b64b7be5101cd7c4da0d496e89a5 Mon Sep 17 00:00:00 2001 From: Nicklas Larsson Date: Sat, 9 Nov 2024 13:49:28 +0100 Subject: [PATCH 54/57] r3.out.v5d: fix broken LITTLE ifdef-else macro in read_float4() (#4676) Fix regression introduced by 8dced26735eba9c385a2eebd1d31d97f2b808386. --- raster3d/r3.out.v5d/binio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/raster3d/r3.out.v5d/binio.c b/raster3d/r3.out.v5d/binio.c index 54b1d1a74e3..98cf70a9fdd 100644 --- a/raster3d/r3.out.v5d/binio.c +++ b/raster3d/r3.out.v5d/binio.c @@ -202,13 +202,14 @@ int read_float4(int f, float *x) else { return 0; } -#endif +#else if (read(f, x, 4) == 4) { return 1; } else { return 0; } +#endif } /* From 66aae0a5a0acd20dba989fcbc4337fbe8b301079 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 11 Nov 2024 03:10:58 +0000 Subject: [PATCH 55/57] CI(deps): Update ruff to v0.7.3 (#4672) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * CI(deps): Update ruff to v0.7.3 * style: Ignore PYI066 on non-stub files. Doesn't seem idiomatic and not understood by Pyright. * style: Fix split-static-string (SIM905) Ruff rule: https://docs.astral.sh/ruff/rules/split-static-string/ * style: Ignore subclass-builtin (FURB189) in two files, as expected change is not guaranteed to be equivalent --------- 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 +- pyproject.toml | 4 +++- scripts/d.correlate/d.correlate.py | 2 +- scripts/db.dropcolumn/db.dropcolumn.py | 3 ++- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/python-code-quality.yml b/.github/workflows/python-code-quality.yml index 55a62f4cb7e..e1676d179fa 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.7.2" + RUFF_VERSION: "0.7.3" runs-on: ${{ matrix.os }} permissions: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fd6d6c67f50..712342dc83a 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.7.2 + rev: v0.7.3 hooks: # Run the linter. - id: ruff diff --git a/pyproject.toml b/pyproject.toml index d739653809e..c9f621a679f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -261,6 +261,7 @@ ignore = [ # "A005", # builtin-module-shadowing # "PLW0108", # unnecessary-lambda # Ignore `E402` (import violations) in all `__init__.py` files +"**.py" = ["PYI066"] "*/testsuite/**.py" = ["PT009", "PT027"] "__init__.py" = ["E402"] "display/d.mon/render_cmd.py" = ["SIM115"] @@ -317,6 +318,7 @@ ignore = [ "python/grass/pygrass/modules/grid/testsuite/test_*_modules_grid_doctests.py" = ["F401"] "python/grass/pygrass/modules/interface/env.py" = ["SIM115"] "python/grass/pygrass/modules/testsuite/test_pygrass_modules_doctests.py" = ["F401"] +"python/grass/pygrass/raster/category.py" = ["FURB189"] "python/grass/pygrass/raster/segment.py" = ["SIM115"] "python/grass/pygrass/tests/*.py" = ["SIM115"] "python/grass/pygrass/vector/geometry.py" = ["PYI024"] @@ -326,7 +328,7 @@ ignore = [ "python/grass/script/core.py" = ["SIM115"] "python/grass/script/db.py" = ["SIM115"] "python/grass/script/raster.py" = ["SIM115"] -"python/grass/script/utils.py" = ["SIM115"] +"python/grass/script/utils.py" = ["FURB189", "SIM115"] "python/grass/temporal/aggregation.py" = ["SIM115"] "python/grass/temporal/register.py" = ["SIM115"] "python/grass/temporal/stds_export.py" = ["SIM115"] diff --git a/scripts/d.correlate/d.correlate.py b/scripts/d.correlate/d.correlate.py index 1068733a11b..af0f1840356 100755 --- a/scripts/d.correlate/d.correlate.py +++ b/scripts/d.correlate/d.correlate.py @@ -54,7 +54,7 @@ def main(): os.environ["GRASS_RENDER_FILE_READ"] = "TRUE" - colors = "red black blue green gray violet".split() + colors = ["red", "black", "blue", "green", "gray", "violet"] line = 2 iloop = 0 jloop = 0 diff --git a/scripts/db.dropcolumn/db.dropcolumn.py b/scripts/db.dropcolumn/db.dropcolumn.py index 24681b18b23..e038deda38a 100755 --- a/scripts/db.dropcolumn/db.dropcolumn.py +++ b/scripts/db.dropcolumn/db.dropcolumn.py @@ -102,7 +102,8 @@ def main(): driver=driver, ).split(".")[0:2] - if [int(i) for i in sqlite3_version] >= [int(i) for i in "3.35".split(".")]: + # sqlite version 3.35 compared here + if [int(i) for i in sqlite3_version] >= [int(i) for i in ["3", "35"]]: sql = "ALTER TABLE %s DROP COLUMN %s" % (table, column) if column == "cat": sql = "DROP INDEX %s_%s; %s" % (table, column, sql) From 5046645d2f75a4130b5a118bcdb5e7ddcb888523 Mon Sep 17 00:00:00 2001 From: Arohan Ajit Date: Mon, 11 Nov 2024 11:08:42 -0500 Subject: [PATCH 56/57] temporal: Fix bare 'except' in temporal_raster_base_algebra (#4682) --- .flake8 | 4 +--- python/grass/temporal/temporal_raster_base_algebra.py | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.flake8 b/.flake8 index 45792c60cf7..13c2fefebbe 100644 --- a/.flake8 +++ b/.flake8 @@ -73,7 +73,6 @@ per-file-ignores = python/grass/temporal/spatial_topology_dataset_connector.py: E722 python/grass/temporal/temporal_algebra.py: E722 python/grass/temporal/temporal_granularity.py: E722 - python/grass/temporal/temporal_raster_base_algebra.py: E722 # 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, F821 @@ -88,9 +87,8 @@ per-file-ignores = python/grass/*/*/*/__init__.py: F403 # E402 module level import not at top of file scripts/r.semantic.label/r.semantic.label.py: E501 - scripts/db.out.ogr/db.out.ogr.py: F841 scripts/g.extension/g.extension.py: E501 - scripts/v.unpack/v.unpack.py: E501n + scripts/v.unpack/v.unpack.py: E501 scripts/v.import/v.import.py: E501 scripts/db.univar/db.univar.py: E501 scripts/i.pansharpen/i.pansharpen.py: E501 diff --git a/python/grass/temporal/temporal_raster_base_algebra.py b/python/grass/temporal/temporal_raster_base_algebra.py index bb58c8405f7..9340db5593d 100644 --- a/python/grass/temporal/temporal_raster_base_algebra.py +++ b/python/grass/temporal/temporal_raster_base_algebra.py @@ -387,7 +387,7 @@ def sub_cmdstring(map_i): else: try: map_sub = map_i.get_id() - except: + except AttributeError: map_sub = map_i return map_sub From f45038256a56ed2800de80d7ffc6f3f1bb83ac6f Mon Sep 17 00:00:00 2001 From: Arohan Ajit Date: Mon, 11 Nov 2024 11:11:42 -0500 Subject: [PATCH 57/57] wxGUI: Removed unused variable from rdigit/ (#4683) fixed 841 --- .flake8 | 1 - gui/wxpython/rdigit/g.gui.rdigit.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.flake8 b/.flake8 index 13c2fefebbe..0f8b1b8e2c9 100644 --- a/.flake8 +++ b/.flake8 @@ -29,7 +29,6 @@ per-file-ignores = gui/wxpython/animation/g.gui.animation.py: E501 gui/wxpython/tplot/frame.py: F841, E722 gui/wxpython/tplot/g.gui.tplot.py: E501 - gui/wxpython/rdigit/g.gui.rdigit.py: F841 gui/wxpython/iclass/digit.py: F405, F403 gui/wxpython/iclass/frame.py: F405, F403 gui/wxpython/iclass/g.gui.iclass.py: E501 diff --git a/gui/wxpython/rdigit/g.gui.rdigit.py b/gui/wxpython/rdigit/g.gui.rdigit.py index ae8d9ed41d8..5b38d858835 100755 --- a/gui/wxpython/rdigit/g.gui.rdigit.py +++ b/gui/wxpython/rdigit/g.gui.rdigit.py @@ -154,7 +154,7 @@ def _addLayer(self, name, ltype="raster"): :param str name: map name :param str ltype: layer type """ - mapLayer = self._mapObj.AddLayer( + self._mapObj.AddLayer( ltype=ltype, name=name, command=["d.rast", "map={}".format(name)],