diff --git a/display/d.vect.chart/plot.c b/display/d.vect.chart/plot.c index 68ef37dcea1..73dcaf08c78 100644 --- a/display/d.vect.chart/plot.c +++ b/display/d.vect.chart/plot.c @@ -27,8 +27,6 @@ int plot(int ctype, struct Map_info *Map, int type, int field, char *columns, dbTable *table; dbColumn *column; - Points = Vect_new_line_struct(); - Cats = Vect_new_cats_struct(); db_init_string(&sql); Fi = Vect_get_field(Map, field); @@ -40,8 +38,11 @@ int plot(int ctype, struct Map_info *Map, int type, int field, char *columns, if (driver == NULL) { G_warning(_("Unable to open database <%s> by driver <%s>"), Fi->database, Fi->driver); + Vect_destroy_field_info(Fi); return 1; } + Points = Vect_new_line_struct(); + Cats = Vect_new_cats_struct(); db_set_error_handler_driver(driver); val = @@ -134,6 +135,8 @@ int plot(int ctype, struct Map_info *Map, int type, int field, char *columns, db_close_database_shutdown_driver(driver); Vect_destroy_line_struct(Points); Vect_destroy_cats_struct(Cats); + Vect_destroy_field_info(Fi); + G_free(val); return 0; } diff --git a/general/g.setproj/g.setproj.html b/general/g.setproj/g.setproj.html index eb39ccb4010..8db06bc6880 100644 --- a/general/g.setproj/g.setproj.html +++ b/general/g.setproj/g.setproj.html @@ -1,32 +1,8 @@ - - - -g.setproj - GRASS GIS manual - - - - - - - -GRASS logo
- -

NAME

+

DESCRIPTION

-g.setproj allows the user to create the PROJ_INFO and the +g.setproj allows the user to create the PROJ_INFO and the PROJ_UNITS files to record the coordinate reference system (CRS) information associated with a current project (previously called location). -
- -

SYNOPSIS

- -g.setproj - -

DESCRIPTION

- -Allows a user to create a PROJ_INFO file in the PERMANENT mapset of the -current project. PROJ_INFO file is used to record the CRS information -associated with the specified project.

NOTES

@@ -82,11 +58,6 @@

SEE ALSO

AUTHORS

-Irina Kosinovsky, -U.S. Army Construction Engineering -Research Laboratory
+Irina Kosinovsky, U.S. Army Construction Engineering Research Laboratory
Morten Hulden, morten at untamo.net - rewrote module and added 121 projections
Andreas Lange, andreas.lange at rhein-main.de - added prelimnary map datum support - - - diff --git a/gui/wxpython/animation/data.py b/gui/wxpython/animation/data.py index ec33ce082d2..a627ce00865 100644 --- a/gui/wxpython/animation/data.py +++ b/gui/wxpython/animation/data.py @@ -21,6 +21,7 @@ from grass.script.utils import parse_key_val from grass.script import core as gcore +from grass.exceptions import ScriptError from core.gcmd import GException from animation.nviztask import NvizTask @@ -299,7 +300,7 @@ def SetName(self, name): try: name = validateTimeseriesName(name, self._mapType) self._maps = getRegisteredMaps(name, self._mapType) - except (GException, gcore.ScriptError) as e: + except (GException, ScriptError) as e: raise ValueError(str(e)) else: self._maps = validateMapNames(name.split(","), self._mapType) diff --git a/gui/wxpython/animation/dialogs.py b/gui/wxpython/animation/dialogs.py index 5a634b3bb16..1ee8d01c174 100644 --- a/gui/wxpython/animation/dialogs.py +++ b/gui/wxpython/animation/dialogs.py @@ -37,6 +37,7 @@ from wx import HyperlinkCtrl from core.gcmd import GMessage, GError, GException +from grass.exceptions import ScriptError from core import globalvar from gui_core.dialogs import MapLayersDialog, GetImageHandlers from gui_core.preferences import PreferencesBaseDialog @@ -727,10 +728,9 @@ def _update(self): if isStart: self.animationData.startRegion = isStart else: - if isStart: - self.animationData.startRegion = isStart - else: + if not isStart: raise GException(_("Region information is not complete")) + self.animationData.startRegion = isStart if isEnd: self.animationData.endRegion = self.endRegion.GetValue() self.animationData.zoomRegionValue = None @@ -1785,7 +1785,7 @@ def _createDefaultCommand(self): if maps: mapName, mapLayer = getNameAndLayer(maps[0]) cmd.append("map={name}".format(name=mapName)) - except gcore.ScriptError as e: + except ScriptError as e: GError(parent=self, message=str(e), showTraceback=False) return None return cmd @@ -1838,7 +1838,7 @@ def _onOK(self, event): self.layer.name = self._name self.layer.cmd = self._cmd event.Skip() - except (GException, gcore.ScriptError) as e: + except (GException, ScriptError) as e: GError(parent=self, message=str(e)) def GetLayer(self): diff --git a/gui/wxpython/animation/nviztask.py b/gui/wxpython/animation/nviztask.py index 5dbb1d3e982..caa02553db4 100644 --- a/gui/wxpython/animation/nviztask.py +++ b/gui/wxpython/animation/nviztask.py @@ -299,12 +299,10 @@ def GetCommandSeries(self, layerList, paramName): if len(layerList) > 1: raise GException(_("Please add only one layer in the list.")) - return layer = layerList[0] - if hasattr(layer, "maps"): - series = layer.maps - else: + if not hasattr(layer, "maps"): raise GException(_("No map series nor space-time dataset is added.")) + series = layer.maps for value in series: self.task.set_param(paramName, value) diff --git a/gui/wxpython/animation/provider.py b/gui/wxpython/animation/provider.py index 08d1c083cb8..0be21a2ed94 100644 --- a/gui/wxpython/animation/provider.py +++ b/gui/wxpython/animation/provider.py @@ -758,14 +758,15 @@ def Clear(self): Debug.msg(4, "MapFilesPool.Clear") for key in list(self.dictionary.keys()): - if self.referenceCount[key] <= 0: - name, ext = os.path.splitext(self.dictionary[key]) - os.remove(self.dictionary[key]) - if ext == ".ppm": - os.remove(name + ".pgm") - del self.dictionary[key] - del self.referenceCount[key] - del self.size[key] + if self.referenceCount[key] > 0: + continue + name, ext = os.path.splitext(self.dictionary[key]) + os.remove(self.dictionary[key]) + if ext == ".ppm": + os.remove(name + ".pgm") + del self.dictionary[key] + del self.referenceCount[key] + del self.size[key] class BitmapPool(DictRefCounter): diff --git a/gui/wxpython/animation/utils.py b/gui/wxpython/animation/utils.py index 54aafa3532f..cf49e3fd974 100644 --- a/gui/wxpython/animation/utils.py +++ b/gui/wxpython/animation/utils.py @@ -92,18 +92,18 @@ def validateMapNames(names, etype): for name in names: if name.find("@") >= 0: nameShort, mapset = name.split("@", 1) - if nameShort in mapDict[mapset]: - newNames.append(name) - else: - raise GException(_("Map <%s> not found.") % name) - else: - found = False - for mapset, mapNames in mapDict.items(): - if name in mapNames: - found = True - newNames.append(name + "@" + mapset) - if not found: + if nameShort not in mapDict[mapset]: raise GException(_("Map <%s> not found.") % name) + newNames.append(name) + + continue + found = False + for mapset, mapNames in mapDict.items(): + if name in mapNames: + found = True + newNames.append(name + "@" + mapset) + if not found: + raise GException(_("Map <%s> not found.") % name) return newNames @@ -331,21 +331,22 @@ def layerListToCmdsMatrix(layerList): continue if hasattr(layer, "maps"): for i, part in enumerate(layer.cmd): - if part.startswith("map="): - cmd = layer.cmd[:] - cmds = [] - for map_ in layer.maps: - # check if dataset uses layers instead of maps - mapName, mapLayer = getNameAndLayer(map_) - cmd[i] = "map={name}".format(name=mapName) - if mapLayer: - try: - idx = cmd.index("layer") - cmd[idx] = "layer={layer}".format(layer=mapLayer) - except ValueError: - cmd.append("layer={layer}".format(layer=mapLayer)) - cmds.append(cmd[:]) - cmdsForComposition.append(cmds) + if not part.startswith("map="): + continue + cmd = layer.cmd[:] + cmds = [] + for map_ in layer.maps: + # check if dataset uses layers instead of maps + mapName, mapLayer = getNameAndLayer(map_) + cmd[i] = "map={name}".format(name=mapName) + if mapLayer: + try: + idx = cmd.index("layer") + cmd[idx] = "layer={layer}".format(layer=mapLayer) + except ValueError: + cmd.append("layer={layer}".format(layer=mapLayer)) + cmds.append(cmd[:]) + cmdsForComposition.append(cmds) else: cmdsForComposition.append([layer.cmd] * count) diff --git a/gui/wxpython/core/gcmd.py b/gui/wxpython/core/gcmd.py index 0b8d57fe2fe..08a95c0aa7e 100644 --- a/gui/wxpython/core/gcmd.py +++ b/gui/wxpython/core/gcmd.py @@ -180,25 +180,25 @@ def __init__(self, args, **kwargs): # "^" must be the first character in the list to avoid double # escaping. for c in ("^", "|", "&", "<", ">"): - if c in args[i]: - if "=" in args[i]: - a = args[i].split("=") - k = a[0] + "=" - v = "=".join(a[1 : len(a)]) - else: - k = "" - v = args[i] - - # If there are spaces, the argument was already - # esscaped with double quotes, so don't escape it - # again. - if c in v and " " not in v: - # Here, we escape each ^ in ^^^ with ^^ and a - # with ^ + , - # so we need 7 carets. - - v = v.replace(c, "^^^^^^^" + c) - args[i] = k + v + if c not in args[i]: + continue + if "=" in args[i]: + a = args[i].split("=") + k = a[0] + "=" + v = "=".join(a[1 : len(a)]) + else: + k = "" + v = args[i] + + # If there are spaces, the argument was already + # escaped with double quotes, so don't escape it + # again. + if c in v and " " not in v: + # Here, we escape each ^ in ^^^ with ^^ and a + # with ^ + , + # so we need 7 carets. + v = v.replace(c, "^^^^^^^" + c) + args[i] = k + v subprocess.Popen.__init__(self, args, **kwargs) diff --git a/gui/wxpython/core/globalvar.py b/gui/wxpython/core/globalvar.py index a5ce362f8c8..a3c8b50de79 100644 --- a/gui/wxpython/core/globalvar.py +++ b/gui/wxpython/core/globalvar.py @@ -23,6 +23,7 @@ from grass.script.core import get_commands from core.debug import Debug +from pathlib import Path # path to python scripts ETCDIR = os.path.join(os.getenv("GISBASE"), "etc") @@ -206,7 +207,8 @@ def UpdateGRASSAddOnCommands(eList=None): if pathList and path not in pathList: os.environ["PATH"] = path + os.pathsep + os.environ["PATH"] - for fname in os.listdir(path): + for file_path in Path(path).iterdir(): + fname = file_path.name if fname in {"docs", "modules.xml"}: continue if grassScripts: # win32 diff --git a/gui/wxpython/core/render.py b/gui/wxpython/core/render.py index 67e7561c4e7..631298afa1a 100644 --- a/gui/wxpython/core/render.py +++ b/gui/wxpython/core/render.py @@ -217,15 +217,12 @@ def GetCmd(self, string=False): :return: command list/string """ - if string: - if self.type == "command": - scmd = [] - for c in self.cmd: - scmd.append(utils.GetCmdString(c)) - - return ";".join(scmd) - return utils.GetCmdString(self.cmd) - return self.cmd + if not string: + return self.cmd + if self.type == "command": + scmd = [utils.GetCmdString(c) for c in self.cmd] + return ";".join(scmd) + return utils.GetCmdString(self.cmd) def GetType(self): """Get map layer type""" @@ -883,25 +880,24 @@ def GetWindow(self): env["GISDBASE"], env["LOCATION_NAME"], env["MAPSET"], "WIND" ) try: - windfile = open(filename) + with open(filename) as windfile: + for line in windfile: + line = line.strip() + try: + key, value = line.split(":", 1) + except ValueError as e: + sys.stderr.write( + _("\nERROR: Unable to read WIND file: %s\n") % e + ) + return None + + self.wind[key.strip()] = value.strip() except OSError as e: sys.exit( _("Error: Unable to open '%(file)s'. Reason: %(ret)s. wxGUI exited.\n") % {"file": filename, "ret": e} ) - for line in windfile: - line = line.strip() - try: - key, value = line.split(":", 1) - except ValueError as e: - sys.stderr.write(_("\nERROR: Unable to read WIND file: %s\n") % e) - return None - - self.wind[key.strip()] = value.strip() - - windfile.close() - return self.wind def AdjustRegion(self): @@ -1406,29 +1402,28 @@ def DeleteLayer(self, layer, overlay=False): list_ = self.overlays if overlay else self.layers - if layer in list_: - if layer.mapfile: - base, mapfile = os.path.split(layer.mapfile) - tempbase = mapfile.split(".")[0] - if base == "" or tempbase == "": - return None - basefile = os.path.join(base, tempbase) + r".*" - # this comes all the way from r28605, so leaving - # it as it is, although it does not really fit with the - # new system (but probably works well enough) - for f in glob.glob(basefile): - os.remove(f) - - if layer.GetType() in {"vector", "thememap"}: - if os.path.isfile(layer._legrow): - os.remove(layer._legrow) - - list_.remove(layer) - - self.layerRemoved.emit(layer=layer) - return layer + if layer not in list_: + return None + if layer.mapfile: + base, mapfile = os.path.split(layer.mapfile) + tempbase = mapfile.split(".")[0] + if base == "" or tempbase == "": + return None + basefile = os.path.join(base, tempbase) + r".*" + # this comes all the way from r28605, so leaving + # it as it is, although it does not really fit with the + # new system (but probably works well enough) + for f in glob.glob(basefile): + os.remove(f) - return None + if layer.GetType() in {"vector", "thememap"}: + if os.path.isfile(layer._legrow): + os.remove(layer._legrow) + + list_.remove(layer) + + self.layerRemoved.emit(layer=layer) + return layer def SetLayers(self, layers): self.layers = layers @@ -1653,12 +1648,11 @@ def GetOverlay(self, id, list=False): """ ovl = [overlay for overlay in self.overlays if overlay.id == id] - if not list: - if len(ovl) != 1: - return None - return ovl[0] - - return ovl + if list: + return ovl + if len(ovl) != 1: + return None + return ovl[0] def DeleteOverlay(self, overlay): """Delete overlay diff --git a/gui/wxpython/core/settings.py b/gui/wxpython/core/settings.py index f65664a5e9b..783464ac99f 100644 --- a/gui/wxpython/core/settings.py +++ b/gui/wxpython/core/settings.py @@ -29,6 +29,7 @@ from core import globalvar from core.gcmd import GException, GError from core.utils import GetSettingsPath, PathJoin, rgb2str +from pathlib import Path class SettingsJSONEncoder(json.JSONEncoder): @@ -104,7 +105,8 @@ def __init__(self): def _generateLocale(self): """Generate locales""" try: - self.locs = os.listdir(os.path.join(os.environ["GISBASE"], "locale")) + locale_path = Path(os.environ["GISBASE"]) / "locale" + self.locs = [p.name for p in locale_path.iterdir() if p.is_dir()] self.locs.append("en") # GRASS doesn't ship EN po files self.locs.sort() # Add a default choice to not override system locale @@ -941,30 +943,28 @@ def _readLegacyFile(self, settings=None): settings = self.userSettings try: - fd = open(self.legacyFilePath) + with open(self.legacyFilePath) as fd: + line = "" + for line in fd: + line = line.rstrip("%s" % os.linesep) + group, key = line.split(self.sep)[0:2] + kv = line.split(self.sep)[2:] + subkeyMaster = None + if len(kv) % 2 != 0: # multiple (e.g. nviz) + subkeyMaster = kv[0] + del kv[0] + idx = 0 + while idx < len(kv): + subkey = [subkeyMaster, kv[idx]] if subkeyMaster else kv[idx] + value = kv[idx + 1] + value = self._parseValue(value, read=True) + self.Append(settings, group, key, subkey, value) + idx += 2 except OSError: sys.stderr.write( _("Unable to read settings file <%s>\n") % self.legacyFilePath ) return - - try: - line = "" - for line in fd: - line = line.rstrip("%s" % os.linesep) - group, key = line.split(self.sep)[0:2] - kv = line.split(self.sep)[2:] - subkeyMaster = None - if len(kv) % 2 != 0: # multiple (e.g. nviz) - subkeyMaster = kv[0] - del kv[0] - idx = 0 - while idx < len(kv): - subkey = [subkeyMaster, kv[idx]] if subkeyMaster else kv[idx] - value = kv[idx + 1] - value = self._parseValue(value, read=True) - self.Append(settings, group, key, subkey, value) - idx += 2 except ValueError as e: print( _( @@ -975,9 +975,6 @@ def _readLegacyFile(self, settings=None): % {"file": self.legacyFilePath, "detail": e, "line": line}, file=sys.stderr, ) - fd.close() - - fd.close() def SaveToFile(self, settings=None): """Save settings to the file""" diff --git a/gui/wxpython/core/toolboxes.py b/gui/wxpython/core/toolboxes.py index da4a516e83c..0bfac9d6b9f 100644 --- a/gui/wxpython/core/toolboxes.py +++ b/gui/wxpython/core/toolboxes.py @@ -124,101 +124,94 @@ def getMenudataFile(userRootFile, newFile, fallback): # always create toolboxes directory if does not exist yet tbDir = _setupToolboxes() - if tbDir: - menudataFile = os.path.join(tbDir, newFile) - generateNew = False - # when any of main_menu.xml or toolboxes.xml are changed, - # generate new menudata.xml - - if os.path.exists(menudataFile): - # remove menu file when there is no main_menu and toolboxes - if not _getUserToolboxesFile() and not userRootFile: - os.remove(menudataFile) - _debug( - 2, - ( - "toolboxes.getMenudataFile: no user defined files, " - "menudata deleted" - ), - ) - return fallback - - if bool(_getUserToolboxesFile()) != bool(userRootFile): - # always generate new because we don't know if there has been - # any change - generateNew = True - _debug( - 2, - ("toolboxes.getMenudataFile: only one of the user defined files"), - ) - else: - # if newer files -> generate new - menudataTime = os.path.getmtime(menudataFile) - if _getUserToolboxesFile(): - if os.path.getmtime(_getUserToolboxesFile()) > menudataTime: - _debug( - 2, - ( - "toolboxes.getMenudataFile: user toolboxes is newer " - "than menudata" - ), - ) - generateNew = True - if userRootFile: - if os.path.getmtime(userRootFile) > menudataTime: - _debug( - 2, - ( - "toolboxes.getMenudataFile: user root file is " - "newer than menudata" - ), - ) - generateNew = True - elif _getUserToolboxesFile() or userRootFile: - _debug(2, "toolboxes.getMenudataFile: no menudata") - generateNew = True - else: - _debug(2, "toolboxes.getMenudataFile: no user defined files") + if not tbDir: + _debug(2, "toolboxes.getMenudataFile: returning menudata fallback file") + return fallback + + menudataFile = os.path.join(tbDir, newFile) + generateNew = False + # when any of main_menu.xml or toolboxes.xml are changed, + # generate new menudata.xml + + if os.path.exists(menudataFile): + # remove menu file when there is no main_menu and toolboxes + if not _getUserToolboxesFile() and (not userRootFile): + os.remove(menudataFile) + _debug( + 2, + ("toolboxes.getMenudataFile: no user defined files, menudata deleted"), + ) return fallback - if generateNew: - try: - # The case when user does not have custom root - # file but has toolboxes requires regeneration. - # Unfortunately, this is the case can be often: defined - # toolboxes but undefined module tree file. - _debug(2, "toolboxes.getMenudataFile: creating a tree") - tree = createTree( - distributionRootFile=distributionRootFile, userRootFile=userRootFile - ) - except ETREE_EXCEPTIONS: - _warning( - _( - "Unable to parse user toolboxes XML files. " - "Default files will be loaded." - ) - ) - return fallback - - try: - xml = _getXMLString(tree.getroot()) - Path(menudataFile).write_text(xml) - return menudataFile - except Exception: - _debug( - 2, - ( - "toolboxes.getMenudataFile: writing menudata failed, " - "returning fallback file" - ), - ) - return fallback + if bool(_getUserToolboxesFile()) != bool(userRootFile): + # always generate new because we don't know if there has been + # any change + generateNew = True + _debug( + 2, + ("toolboxes.getMenudataFile: only one of the user defined files"), + ) else: - return menudataFile + # if newer files -> generate new + menudataTime = os.path.getmtime(menudataFile) + if _getUserToolboxesFile(): + if os.path.getmtime(_getUserToolboxesFile()) > menudataTime: + _debug( + 2, + ( + "toolboxes.getMenudataFile: user toolboxes is newer " + "than menudata" + ), + ) + generateNew = True + if userRootFile: + if os.path.getmtime(userRootFile) > menudataTime: + _debug( + 2, + ( + "toolboxes.getMenudataFile: user root file is " + "newer than menudata" + ), + ) + generateNew = True + elif _getUserToolboxesFile() or userRootFile: + _debug(2, "toolboxes.getMenudataFile: no menudata") + generateNew = True else: - _debug(2, "toolboxes.getMenudataFile: returning menudata fallback file") + _debug(2, "toolboxes.getMenudataFile: no user defined files") return fallback + if not generateNew: + return menudataFile + try: + # The case when user does not have custom root + # file but has toolboxes requires regeneration. + # Unfortunately, this is the case can be often: defined + # toolboxes but undefined module tree file. + _debug(2, "toolboxes.getMenudataFile: creating a tree") + tree = createTree( + distributionRootFile=distributionRootFile, userRootFile=userRootFile + ) + except ETREE_EXCEPTIONS: + _warning( + _("Unable to parse user toolboxes XML files. Default files will be loaded.") + ) + return fallback + + try: + xml = _getXMLString(tree.getroot()) + Path(menudataFile).write_text(xml) + return menudataFile + except Exception: + _debug( + 2, + ( + "toolboxes.getMenudataFile: writing menudata failed, " + "returning fallback file" + ), + ) + return fallback + def _setupToolboxes(): """Create 'toolboxes' directory if doesn't exist.""" @@ -611,21 +604,23 @@ def _expandRuntimeModules(node, loadMetadata=True): n = ET.SubElement(module, "module") n.text = name - if module.find("description") is None: - if loadMetadata: - # not all modules are always compiled (e.g., r.in.lidar) - if shutil.which(name): - desc, keywords = _loadMetadata(name) - if not desc: - hasErrors = True - else: - desc, keywords = _("Module not installed"), "" + if module.find("description") is not None: + continue + + if loadMetadata: + # not all modules are always compiled (e.g., r.in.lidar) + if shutil.which(name): + desc, keywords = _loadMetadata(name) + if not desc: + hasErrors = True else: - desc, keywords = "", "" - n = ET.SubElement(module, "description") - n.text = _escapeXML(desc) - n = ET.SubElement(module, "keywords") - n.text = _escapeXML(",".join(keywords)) + desc, keywords = (_("Module not installed"), "") + else: + desc, keywords = ("", "") + n = ET.SubElement(module, "description") + n.text = _escapeXML(desc) + n = ET.SubElement(module, "keywords") + n.text = _escapeXML(",".join(keywords)) if hasErrors: # not translatable until toolboxes compilation on Mac is fixed diff --git a/gui/wxpython/core/utils.py b/gui/wxpython/core/utils.py index a1722fec64b..72423756460 100644 --- a/gui/wxpython/core/utils.py +++ b/gui/wxpython/core/utils.py @@ -146,18 +146,18 @@ def GetLayerNameFromCmd(dcmd, fullyQualified=False, param=None, layerType=None): params.append((idx, p, v)) if len(params) < 1: - if len(dcmd) > 1: - i = 1 - while i < len(dcmd): - if "=" not in dcmd[i] and not dcmd[i].startswith("-"): - task = gtask.parse_interface(dcmd[0]) - # this expects the first parameter to be the right one - p = task.get_options()["params"][0].get("name", "") - params.append((i, p, dcmd[i])) - break - i += 1 - else: - return mapname, False + if len(dcmd) <= 1: + return (mapname, False) + + i = 1 + while i < len(dcmd): + if "=" not in dcmd[i] and (not dcmd[i].startswith("-")): + task = gtask.parse_interface(dcmd[0]) + # this expects the first parameter to be the right one + p = task.get_options()["params"][0].get("name", "") + params.append((i, p, dcmd[i])) + break + i += 1 if len(params) < 1: return mapname, False @@ -267,10 +267,9 @@ def ListOfCatsToRange(cats): next = 0 j = i + 1 while j < len(cats): - if cats[i + next] == cats[j] - 1: - next += 1 - else: + if cats[i + next] != cats[j] - 1: break + next += 1 j += 1 if next > 1: @@ -302,22 +301,21 @@ def ListOfMapsets(get="ordered"): if get == "all": return mapsets_all - if get in {"accessible", "ordered"}: - ret = RunCommand("g.mapsets", read=True, quiet=True, flags="p", sep="newline") - if not ret: - return [] - mapsets_accessible = ret.splitlines() - if get == "accessible": - return mapsets_accessible - - mapsets_ordered = mapsets_accessible.copy() - for mapset in mapsets_all: - if mapset not in mapsets_accessible: - mapsets_ordered.append(mapset) - return mapsets_ordered + if get not in {"accessible", "ordered"}: + msg = "Invalid value for 'get' parameter of ListOfMapsets()" + raise ValueError(msg) + ret = RunCommand("g.mapsets", read=True, quiet=True, flags="p", sep="newline") + if not ret: + return [] + mapsets_accessible = ret.splitlines() + if get == "accessible": + return mapsets_accessible - msg = "Invalid value for 'get' parameter of ListOfMapsets()" - raise ValueError(msg) + mapsets_ordered = mapsets_accessible.copy() + for mapset in mapsets_all: + if mapset not in mapsets_accessible: + mapsets_ordered.append(mapset) + return mapsets_ordered def ListSortLower(list): @@ -828,7 +826,21 @@ def StoreEnvVariable(key, value=None, envFile=None): lineSkipped = [] if os.path.exists(envFile): try: - fd = open(envFile) + with open(envFile) as fd: + for line in fd: + line = line.rstrip(os.linesep) + try: + k, v = (x.strip() for x in line.split(" ", 1)[1].split("=", 1)) + except Exception as e: + sys.stderr.write( + _("%s: line skipped - unable to parse '%s'\nReason: %s\n") + % (envFile, line, e) + ) + lineSkipped.append(line) + continue + if k in environ: + sys.stderr.write(_("Duplicated key: %s\n") % k) + environ[k] = v except OSError as error: sys.stderr.write( _("Unable to open file '{name}': {error}\n").format( @@ -836,22 +848,6 @@ def StoreEnvVariable(key, value=None, envFile=None): ) ) return - for line in fd: - line = line.rstrip(os.linesep) - try: - k, v = (x.strip() for x in line.split(" ", 1)[1].split("=", 1)) - except Exception as e: - sys.stderr.write( - _("%s: line skipped - unable to parse '%s'\nReason: %s\n") - % (envFile, line, e) - ) - lineSkipped.append(line) - continue - if k in environ: - sys.stderr.write(_("Duplicated key: %s\n") % k) - environ[k] = v - - fd.close() # update environmental variables if value is None: @@ -861,7 +857,15 @@ def StoreEnvVariable(key, value=None, envFile=None): # write update env file try: - fd = open(envFile, "w") + with open(envFile, "w") as fd: + expCmd = "set" if windows else "export" + + fd.writelines( + "%s %s=%s\n" % (expCmd, key, value) for key, value in environ.items() + ) + + # write also skipped lines + fd.writelines(line + os.linesep for line in lineSkipped) except OSError as error: sys.stderr.write( _("Unable to create file '{name}': {error}\n").format( @@ -869,14 +873,6 @@ def StoreEnvVariable(key, value=None, envFile=None): ) ) return - expCmd = "set" if windows else "export" - - fd.writelines("%s %s=%s\n" % (expCmd, key, value) for key, value in environ.items()) - - # write also skipped lines - fd.writelines(line + os.linesep for line in lineSkipped) - - fd.close() def SetAddOnPath(addonPath=None, key="PATH"): diff --git a/gui/wxpython/core/workspace.py b/gui/wxpython/core/workspace.py index bd09a9354a6..300e9993f5e 100644 --- a/gui/wxpython/core/workspace.py +++ b/gui/wxpython/core/workspace.py @@ -1730,7 +1730,11 @@ def read(self, parent): :return: list of map layers """ try: - file = open(self.filename) + with open(self.filename) as file: # Changed to context manager + line_id = 1 + for line in file: + self.process_line(line.rstrip("\n"), line_id) + line_id += 1 except OSError: wx.MessageBox( parent=parent, @@ -1740,13 +1744,6 @@ def read(self, parent): ) return [] - line_id = 1 - for line in file: - self.process_line(line.rstrip("\n"), line_id) - line_id += 1 - - file.close() - if self.num_error > 0: wx.MessageBox( parent=parent, diff --git a/gui/wxpython/datacatalog/catalog.py b/gui/wxpython/datacatalog/catalog.py index 4835061d968..c8b02422e1b 100644 --- a/gui/wxpython/datacatalog/catalog.py +++ b/gui/wxpython/datacatalog/catalog.py @@ -17,7 +17,6 @@ """ import wx -import os from pathlib import Path @@ -212,7 +211,7 @@ def OnAddGrassDB(self, event): grassdb_node = self.tree.InsertGrassDb(name=grassdatabase) # Offer to create a new location - if grassdb_node and not os.listdir(grassdatabase): + if grassdb_node and not any(Path(grassdatabase).iterdir()): message = _( "Do you want to create a new project (also known as location)?" ) diff --git a/gui/wxpython/dbmgr/vinfo.py b/gui/wxpython/dbmgr/vinfo.py index 94dda140406..b3c9273e0eb 100644 --- a/gui/wxpython/dbmgr/vinfo.py +++ b/gui/wxpython/dbmgr/vinfo.py @@ -23,6 +23,7 @@ from core.gcmd import RunCommand, GError from core.settings import UserSettings import grass.script as gs +from grass.exceptions import ScriptError def GetUnicodeValue(value): @@ -45,10 +46,9 @@ def GetDbEncoding(): then env variable), if not assumes unicode.""" enc = UserSettings.Get(group="atm", key="encoding", subkey="value") if not enc and "GRASS_DB_ENCODING" in os.environ: - enc = os.environ["GRASS_DB_ENCODING"] - else: - enc = "utf-8" # assuming UTF-8 - return enc + return os.environ["GRASS_DB_ENCODING"] + # assuming UTF-8 + return "utf-8" def CreateDbInfoDesc(panel, mapDBInfo, layer): @@ -107,7 +107,7 @@ def SelectByPoint(self, queryCoords, qdist): coord=(float(queryCoords[0]), float(queryCoords[1])), distance=float(qdist), ) - except gs.ScriptError: + except ScriptError: GError( parent=None, message=_( diff --git a/gui/wxpython/gcp/manager.py b/gui/wxpython/gcp/manager.py index 6761cead483..6353f7de0c8 100644 --- a/gui/wxpython/gcp/manager.py +++ b/gui/wxpython/gcp/manager.py @@ -901,9 +901,7 @@ def OnEnterPage(self, event: WizardEvent | None = None) -> None: flags="g", ) - if ret: - self.parent.src_maps = ret.splitlines() - else: + if not ret: GError( parent=self, message=_( @@ -913,6 +911,7 @@ def OnEnterPage(self, event: WizardEvent | None = None) -> None: % self.parent.grouppage.xygroup, ) return + self.parent.src_maps = ret.splitlines() elif maptype == "vector": grassdatabase = self.parent.grassdatabase @@ -1670,7 +1669,7 @@ def OnRMS(self, event): targetMapWin = self.TgtMapWindow targetMapWin.UpdateMap(render=False, renderVector=False) - def CheckGCPcount(self, msg=False): + def CheckGCPcount(self, msg: bool = False) -> bool: """ Checks to make sure that the minimum number of GCPs have been defined and are active for the selected transformation order @@ -1692,9 +1691,10 @@ def CheckGCPcount(self, msg=False): ) % self.gr_order, ) - return False - else: - return True + + return False + + return True def _getOverWriteDialog(self, maptype, overwrite): """Get overwrite confirm dialog @@ -2011,9 +2011,7 @@ def RMSError(self, xygroup, order): self.grwiz.SwitchEnv("target") - if ret: - errlist = ret.splitlines() - else: + if not ret: GError( parent=self, message=_( @@ -2021,6 +2019,7 @@ def RMSError(self, xygroup, order): ), ) return + errlist = ret.splitlines() # insert error values into GCP list for checked items sdfactor = float(UserSettings.Get(group="gcpman", key="rms", subkey="sdfactor")) @@ -2051,12 +2050,13 @@ def RMSError(self, xygroup, order): sumsq_bkw_err += float(bkw_err) ** 2 sum_fwd_err += float(fwd_err) GCPcount += 1 - else: - self.list.SetItem(index, 5, "") - self.list.SetItem(index, 6, "") - self.mapcoordlist[key][5] = 0.0 - self.mapcoordlist[key][6] = 0.0 - self.list.SetItemTextColour(index, wx.BLACK) + continue + + self.list.SetItem(index, 5, "") + self.list.SetItem(index, 6, "") + self.mapcoordlist[key][5] = 0.0 + self.mapcoordlist[key][6] = 0.0 + self.list.SetItemTextColour(index, wx.BLACK) # SD if GCPcount > 0: @@ -2143,9 +2143,7 @@ def GetNewExtent(self, region, map=None): self.grwiz.SwitchEnv("target") - if ret: - errlist = ret.splitlines() - else: + if not ret: GError( parent=self, message=_( @@ -2153,6 +2151,7 @@ def GetNewExtent(self, region, map=None): ), ) return + errlist = ret.splitlines() # fist corner e, n = errlist[0].split() diff --git a/gui/wxpython/gmodeler/model.py b/gui/wxpython/gmodeler/model.py index ee846c62653..c5b2d8b93d2 100644 --- a/gui/wxpython/gmodeler/model.py +++ b/gui/wxpython/gmodeler/model.py @@ -495,25 +495,25 @@ def Validate(self): continue key, value = opt.split("=", 1) sval = pattern.search(value) - if sval: - var = sval.group(2).strip()[1:] # strip '%' from beginning - found = False - for v in variables: - if var.startswith(v): - found = True - break - if not found: - report = True - for item in filter( - lambda x: isinstance(x, ModelLoop), action.GetBlock() - ): - if var in item.GetLabel(): - report = False - break - if report: - errList.append( - cmd[0] + ": " + _("undefined variable '%s'") % var - ) + if not sval: + continue + var = sval.group(2).strip()[1:] # strip '%' from beginning + found = False + for v in variables: + if var.startswith(v): + found = True + break + if found: + continue + report = True + for item in filter( + lambda x: isinstance(x, ModelLoop), action.GetBlock() + ): + if var in item.GetLabel(): + report = False + break + if report: + errList.append(cmd[0] + ": " + _("undefined variable '%s'") % var) # TODO: check variables in file only optionally # errList += self._substituteFile(action, checkOnly = True) @@ -702,24 +702,24 @@ def Run(self, log, onDone, parent=None): variables = self.GetVariables() for variable in variables: pattern = re.compile("%" + variable) - if pattern.search(cond): - value = "" - if params and "variables" in params: - for p in params["variables"]["params"]: - if variable == p.get("name", ""): - value = p.get("value", "") - break - - if not value: - value = variables[variable].get("value", "") - - if not value: - continue + if not pattern.search(cond): + continue + value = "" + if params and "variables" in params: + for p in params["variables"]["params"]: + if variable == p.get("name", ""): + value = p.get("value", "") + break + + if not value: + value = variables[variable].get("value", "") - vtype = variables[variable].get("type", "string") - if vtype == "string": - value = '"' + value + '"' - cond = pattern.sub(value, cond) + if not value: + continue + vtype = variables[variable].get("type", "string") + if vtype == "string": + value = '"' + value + '"' + cond = pattern.sub(value, cond) # split condition # TODO: this part needs some better solution @@ -1211,12 +1211,11 @@ def GetLog(self, string=True, substitute=None): cmd[idx] = pattern.sub(value, cmd[idx]) idx += 1 - if string: - if cmd is None: - return "" - return " ".join(cmd) - - return cmd + if not string: + return cmd + if cmd is None: + return "" + return " ".join(cmd) def GetLabel(self): """Get name""" @@ -1975,12 +1974,11 @@ def _filterValue(self, value): def _getNodeText(self, node, tag, default=""): """Get node text""" p = node.find(tag) - if p is not None: - if p.text: - return utils.normalize_whitespace(p.text) - return "" - - return default + if p is None: + return default + if p.text: + return utils.normalize_whitespace(p.text) + return "" def _processWindow(self): """Process window properties""" @@ -2780,22 +2778,23 @@ def _getPythonActionCmd(self, item, task, cmdIndent, variables={}): name = p.get("name", None) value = p.get("value", None) - if (name and value) or (name in parameterizedParams): - if name in parameterizedParams: - parameterizedParam = self._getParamName(name, item) - default_val = p.get("value", "") + if (not name or not value) and name not in parameterizedParams: + continue - if len(default_val) > 0: - parameterizedParam += f"|default({default_val})" + if name in parameterizedParams: + parameterizedParam = self._getParamName(name, item) + default_val = p.get("value", "") - value = f"{{{{ {parameterizedParam} }}}}" + if len(default_val) > 0: + parameterizedParam += f"|default({default_val})" + value = f"{{{{ {parameterizedParam} }}}}" - param_string = f'{{"param": "{name}", "value": "{value}"}}' - age = p.get("age", "old") - if age == "new": - outputs.append(param_string) - else: - inputs.append(param_string) + param_string = f'{{"param": "{name}", "value": "{value}"}}' + age = p.get("age", "old") + if age == "new": + outputs.append(param_string) + else: + inputs.append(param_string) ret += f'{" " * self.indent * 4}"module": "{task.get_name()}",\n' ret += f'{" " * self.indent * 4}"id": "{self._getModuleNickname(item)}",\n' @@ -2996,19 +2995,20 @@ def _write_input_outputs(self, item, intermediates): # ComplexOutput if: outputting a new non-intermediate layer and # either not empty or parameterized if ( - age == "new" - and not any(value in i for i in intermediates) - and (value != "" or param in item.GetParameterizedParams()["params"]) - ): - io_data = "outputs" - object_type = "ComplexOutput" - format_spec = self._getSupportedFormats(param["prompt"]) - - self._write_input_output_object( - io_data, object_type, param["name"], item, desc, format_spec, "" + age != "new" + or any(value in i for i in intermediates) + or ( + value == "" and param not in item.GetParameterizedParams()["params"] ) - - self.fd.write("\n") + ): + continue + io_data = "outputs" + object_type = "ComplexOutput" + format_spec = self._getSupportedFormats(param["prompt"]) + self._write_input_output_object( + io_data, object_type, param["name"], item, desc, format_spec, "" + ) + self.fd.write("\n") def _write_input_output_object( self, @@ -3060,45 +3060,49 @@ def _writePythonAction(self, item, variables={}, intermediates=None): # output if: outputting a new non-intermediate layer and # either not empty or parameterized if ( - age == "new" - and not any(value in i for i in intermediates) - and (value != "" or param in item.GetParameterizedParams()["params"]) + age != "new" + or any(value in i for i in intermediates) + or ( + value == "" and param not in item.GetParameterizedParams()["params"] + ) ): - if param["prompt"] == "vector": - command = "v.out.ogr" - format = '"GML"' - extension = ".gml" - elif param["prompt"] == "raster": - command = "r.out.gdal" - format = '"GTiff"' - extension = ".tif" - else: - # TODO: Support 3D - command = "WRITE YOUR EXPORT COMMAND" - format = '"WRITE YOUR EXPORT FORMAT"' - extension = "WRITE YOUR EXPORT EXTENSION" + continue - n = param.get("name", None) - param_name = self._getParamName(n, item) + if param["prompt"] == "vector": + command = "v.out.ogr" + format = '"GML"' + extension = ".gml" + elif param["prompt"] == "raster": + command = "r.out.gdal" + format = '"GTiff"' + extension = ".tif" + else: + # TODO: Support 3D + command = "WRITE YOUR EXPORT COMMAND" + format = '"WRITE YOUR EXPORT FORMAT"' + extension = "WRITE YOUR EXPORT EXTENSION" - keys = param.keys() - if "parameterized" in keys and param["parameterized"] is True: - param_request = 'request.inputs["{}"][0].data'.format(param_name) - else: - param_request = '"{}"'.format(param["value"]) + n = param.get("name", None) + param_name = self._getParamName(n, item) - # if True, write the overwrite parameter to the model command - overwrite = self.model.GetProperties().get("overwrite", False) - if overwrite is True: - overwrite_string = ",\n{}overwrite=True".format( - " " * (self.indent + 12) - ) - else: - overwrite_string = "" + keys = param.keys() + if "parameterized" in keys and param["parameterized"] is True: + param_request = 'request.inputs["{}"][0].data'.format(param_name) + else: + param_request = '"{}"'.format(param["value"]) - strcmd_len = len(strcmd.strip()) - self.fd.write( - """ + # if True, write the overwrite parameter to the model command + overwrite = self.model.GetProperties().get("overwrite", False) + if overwrite is True: + overwrite_string = ",\n{}overwrite=True".format( + " " * (self.indent + 12) + ) + else: + overwrite_string = "" + + strcmd_len = len(strcmd.strip()) + self.fd.write( + """ {run_command}"{cmd}", {indent1}input={input}, {indent2}output=os.path.join( @@ -3106,37 +3110,35 @@ def _writePythonAction(self, item, variables={}, intermediates=None): {indent4}{out} + "{format_ext}"), {indent5}format={format}{overwrite_string}) """.format( - run_command=strcmd, - cmd=command, - indent1=" " * (self.indent + strcmd_len), - input=param_request, - indent2=" " * (self.indent + strcmd_len), - indent3=" " * (self.indent * 2 + strcmd_len), - indent4=" " * (self.indent * 2 + strcmd_len), - out=param_request, - format_ext=extension, - indent5=" " * (self.indent + strcmd_len), - format=format, - overwrite_string=overwrite_string, - ) + run_command=strcmd, + cmd=command, + indent1=" " * (self.indent + strcmd_len), + input=param_request, + indent2=" " * (self.indent + strcmd_len), + indent3=" " * (self.indent * 2 + strcmd_len), + indent4=" " * (self.indent * 2 + strcmd_len), + out=param_request, + format_ext=extension, + indent5=" " * (self.indent + strcmd_len), + format=format, + overwrite_string=overwrite_string, ) + ) - left_side_out = 'response.outputs["{}"].file'.format(param_name) - right_side_out = ( - "os.path.join(\n{indent1}" - 'tempfile.gettempdir(),\n{indent2}{out} + "' - '{format_ext}")'.format( - indent1=" " * (self.indent + 4), - indent2=" " * (self.indent + 4), - out=param_request, - format_ext=extension, - ) - ) - self.fd.write( - "\n{}{} = {}".format( - " " * self.indent, left_side_out, right_side_out - ) + left_side_out = 'response.outputs["{}"].file'.format(param_name) + right_side_out = ( + "os.path.join(\n{indent1}" + 'tempfile.gettempdir(),\n{indent2}{out} + "' + '{format_ext}")'.format( + indent1=" " * (self.indent + 4), + indent2=" " * (self.indent + 4), + out=param_request, + format_ext=extension, ) + ) + self.fd.write( + "\n{}{} = {}".format(" " * self.indent, left_side_out, right_side_out) + ) def _getPythonActionCmd(self, item, task, cmdIndent, variables={}): opts = task.get_options() @@ -3154,25 +3156,26 @@ def _getPythonActionCmd(self, item, task, cmdIndent, variables={}): name = p.get("name", None) value = p.get("value", None) - if (name and value) or (name in parameterizedParams): - ptype = p.get("type", "string") - foundVar = False + if (not name or not value) and name not in parameterizedParams: + continue - if name in parameterizedParams: - foundVar = True - if "input" in name: - value = 'request.inputs["{}"][0].file'.format( - self._getParamName(name, item) - ) - else: - value = 'request.inputs["{}"][0].data'.format( - self._getParamName(name, item) - ) + ptype = p.get("type", "string") + foundVar = False - if foundVar or ptype != "string": - params.append("{}={}".format(name, value)) + if name in parameterizedParams: + foundVar = True + if "input" in name: + value = 'request.inputs["{}"][0].file'.format( + self._getParamName(name, item) + ) else: - params.append('{}="{}"'.format(name, value)) + value = 'request.inputs["{}"][0].data'.format( + self._getParamName(name, item) + ) + if foundVar or ptype != "string": + params.append("{}={}".format(name, value)) + else: + params.append('{}="{}"'.format(name, value)) ret += '"%s"' % task.get_name() if flags: @@ -3541,28 +3544,29 @@ def _getPythonActionCmd(self, item, task, cmdIndent, variables={}): elif ptype == "float": value = list(map(float, value)) - if (name and value) or (name in parameterizedParams): - if isinstance(value, list): - foundVar = False - for idx in range(len(value)): - foundVar_, value[idx] = self._substitutePythonParamValue( - value[idx], name, parameterizedParams, variables, item - ) - if foundVar_ is True: - foundVar = True - else: - foundVar, value = self._substitutePythonParamValue( - value, name, parameterizedParams, variables, item - ) + if (not name or not value) and name not in parameterizedParams: + continue - if ( - foundVar - or isinstance(value, list) - or (ptype != "string" and len(p.get("key_desc", [])) < 2) - ): - params.append("{}={}".format(name, value)) - else: - params.append('{}="{}"'.format(name, value)) + if isinstance(value, list): + foundVar = False + for idx in range(len(value)): + foundVar_, value[idx] = self._substitutePythonParamValue( + value[idx], name, parameterizedParams, variables, item + ) + if foundVar_ is True: + foundVar = True + else: + foundVar, value = self._substitutePythonParamValue( + value, name, parameterizedParams, variables, item + ) + if ( + foundVar + or isinstance(value, list) + or (ptype != "string" and len(p.get("key_desc", [])) < 2) + ): + params.append("{}={}".format(name, value)) + else: + params.append('{}="{}"'.format(name, value)) ret += '"%s"' % task.get_name() if flags: diff --git a/gui/wxpython/gmodeler/panels.py b/gui/wxpython/gmodeler/panels.py index c05ce041047..509da20a1b8 100644 --- a/gui/wxpython/gmodeler/panels.py +++ b/gui/wxpython/gmodeler/panels.py @@ -530,16 +530,18 @@ def GetOptData(self, dcmd, layer, params, propwin): data.Update() # remove dead data items - if not p.get("value", ""): - data = layer.FindData(p.get("name", "")) - if data: - remList, upList = self.model.RemoveItem(data, layer) - for item in remList: - self.canvas.diagram.RemoveShape(item) - item.__del__() # noqa: PLC2801, C2801 + if p.get("value", ""): + continue + data = layer.FindData(p.get("name", "")) + if not data: + continue + remList, upList = self.model.RemoveItem(data, layer) + for item in remList: + self.canvas.diagram.RemoveShape(item) + item.__del__() # noqa: PLC2801, C2801 - for item in upList: - item.Update() + for item in upList: + item.Update() # valid / parameterized ? layer.SetValid(params) diff --git a/gui/wxpython/gui_core/dialogs.py b/gui/wxpython/gui_core/dialogs.py index f79578c47a6..c0f369244c4 100644 --- a/gui/wxpython/gui_core/dialogs.py +++ b/gui/wxpython/gui_core/dialogs.py @@ -280,12 +280,11 @@ def GetName(self, full=False): :param full: True to get fully qualified name """ name = self.element.GetValue() - if full: - if "@" in name: - return name - return name + "@" + grass.gisenv()["MAPSET"] - - return name.split("@", 1)[0] + if not full: + return name.split("@", 1)[0] + if "@" in name: + return name + return name + "@" + grass.gisenv()["MAPSET"] class NewVectorDialog(VectorDialog): @@ -532,12 +531,11 @@ def CreateNewVector( caption=_("Overwrite?"), style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION, ) - if dlgOw.ShowModal() == wx.ID_YES: - overwrite = True - else: + if dlgOw.ShowModal() != wx.ID_YES: dlgOw.Destroy() dlg.Destroy() return None + overwrite = True if UserSettings.Get(group="cmd", key="overwrite", subkey="enabled"): overwrite = True diff --git a/gui/wxpython/gui_core/forms.py b/gui/wxpython/gui_core/forms.py index 14d87728057..4034e6a0f93 100644 --- a/gui/wxpython/gui_core/forms.py +++ b/gui/wxpython/gui_core/forms.py @@ -83,6 +83,7 @@ from grass.script import core as grass from grass.script import task as gtask +from grass.exceptions import ScriptError from core import globalvar from gui_core.widgets import ( @@ -2408,9 +2409,15 @@ def OnCheckItem(index=None, flag=None, event=None): pSqlWhere.append(p) # collect ids - pColumnIds = [p["wxId"] for p in pColumn] - pLayerIds = [p["wxId"] for p in pLayer] - pSqlWhereIds = [p["wxId"] for p in pSqlWhere] + pColumnIds = [] + for p in pColumn: + pColumnIds += p["wxId"] + pLayerIds = [] + for p in pLayer: + pLayerIds += p["wxId"] + pSqlWhereIds = [] + for p in pSqlWhere: + pSqlWhereIds += p["wxId"] # set wxId-bindings if pMap: @@ -2773,38 +2780,43 @@ def _switchPage(self, notification): def OnColorChange(self, event): myId = event.GetId() for p in self.task.params: - if "wxId" in p and myId in p["wxId"]: - multiple = p["wxId"][1] is not None # multiple colors - hasTansp = p["wxId"][2] is not None - if multiple: - # selected color is added at the end of textCtrl - colorchooser = wx.FindWindowById(p["wxId"][0]) - new_color = colorchooser.GetValue()[:] - new_label = utils.rgb2str.get( - new_color, ":".join(list(map(str, new_color))) - ) - textCtrl = wx.FindWindowById(p["wxId"][1]) - val = textCtrl.GetValue() - sep = "," - if val and val[-1] != sep: - val += sep - val += new_label - textCtrl.SetValue(val) - p["value"] = val - elif hasTansp and wx.FindWindowById(p["wxId"][2]).GetValue(): - p["value"] = "none" - else: - colorchooser = wx.FindWindowById(p["wxId"][0]) - new_color = colorchooser.GetValue()[:] - # This is weird: new_color is a 4-tuple and new_color[:] is - # a 3-tuple under wx2.8.1 - new_label = utils.rgb2str.get( - new_color, ":".join(list(map(str, new_color))) - ) - colorchooser.SetLabel(new_label) - colorchooser.SetColour(new_color) - colorchooser.Refresh() - p["value"] = colorchooser.GetLabel() + if "wxId" not in p or myId not in p["wxId"]: + continue + + multiple = p["wxId"][1] is not None # multiple colors + hasTansp = p["wxId"][2] is not None + if multiple: + # selected color is added at the end of textCtrl + colorchooser = wx.FindWindowById(p["wxId"][0]) + new_color = colorchooser.GetValue()[:] + new_label = utils.rgb2str.get( + new_color, ":".join(list(map(str, new_color))) + ) + textCtrl = wx.FindWindowById(p["wxId"][1]) + val = textCtrl.GetValue() + sep = "," + if val and val[-1] != sep: + val += sep + val += new_label + textCtrl.SetValue(val) + p["value"] = val + + continue + if hasTansp and wx.FindWindowById(p["wxId"][2]).GetValue(): + p["value"] = "none" + continue + + colorchooser = wx.FindWindowById(p["wxId"][0]) + new_color = colorchooser.GetValue()[:] + # This is weird: new_color is a 4-tuple and new_color[:] is + # a 3-tuple under wx2.8.1 + new_label = utils.rgb2str.get( + new_color, ":".join(list(map(str, new_color))) + ) + colorchooser.SetLabel(new_label) + colorchooser.SetColour(new_color) + colorchooser.Refresh() + p["value"] = colorchooser.GetLabel() self.OnUpdateValues() def OnUpdateValues(self, event=None): @@ -2896,25 +2908,24 @@ def OnSetSymbol(self, event): myId = event.GetId() for p in self.task.params: - if "wxId" in p and myId in p["wxId"]: - from gui_core.dialogs import SymbolDialog - - dlg = SymbolDialog( - self, symbolPath=globalvar.SYMBDIR, currentSymbol=p["value"] - ) - if dlg.ShowModal() == wx.ID_OK: - img = dlg.GetSelectedSymbolPath() - p["value"] = dlg.GetSelectedSymbolName() - - bitmapButton = wx.FindWindowById(p["wxId"][0]) - label = wx.FindWindowById(p["wxId"][1]) + if "wxId" not in p or myId not in p["wxId"]: + continue + from gui_core.dialogs import SymbolDialog - bitmapButton.SetBitmapLabel(wx.Bitmap(img + ".png")) - label.SetLabel(p["value"]) + dlg = SymbolDialog( + self, symbolPath=globalvar.SYMBDIR, currentSymbol=p["value"] + ) + if dlg.ShowModal() == wx.ID_OK: + img = dlg.GetSelectedSymbolPath() + p["value"] = dlg.GetSelectedSymbolName() + bitmapButton = wx.FindWindowById(p["wxId"][0]) + label = wx.FindWindowById(p["wxId"][1]) + bitmapButton.SetBitmapLabel(wx.Bitmap(img + ".png")) + label.SetLabel(p["value"]) - self.OnUpdateValues(event) + self.OnUpdateValues(event) - dlg.Destroy() + dlg.Destroy() def OnTimelineTool(self, event): """Show Timeline Tool with dataset(s) from gselect. @@ -2925,35 +2936,37 @@ def OnTimelineTool(self, event): myId = event.GetId() for p in self.task.params: - if "wxId" in p and myId in p["wxId"]: - select = self.FindWindowById(p["wxId"][0]) - if not select.GetValue(): - gcmd.GMessage(parent=self, message=_("No dataset given.")) - return - datasets = select.GetValue().split(",") - from timeline import frame + if "wxId" not in p or myId not in p["wxId"]: + continue + select = self.FindWindowById(p["wxId"][0]) + if not select.GetValue(): + gcmd.GMessage(parent=self, message=_("No dataset given.")) + return + datasets = select.GetValue().split(",") + from timeline import frame - frame.run(parent=self, datasets=datasets) + frame.run(parent=self, datasets=datasets) def OnSelectFont(self, event): """Select font using font dialog""" myId = event.GetId() for p in self.task.params: - if "wxId" in p and myId in p["wxId"]: - from gui_core.dialogs import DefaultFontDialog - - dlg = DefaultFontDialog( - parent=self, - title=_("Select font"), - style=wx.DEFAULT_DIALOG_STYLE, - type="font", - ) - if dlg.ShowModal() == wx.ID_OK: - if dlg.font: - p["value"] = dlg.font - self.FindWindowById(p["wxId"][1]).SetValue(dlg.font) - self.OnUpdateValues(event) - dlg.Destroy() + if "wxId" not in p or myId not in p["wxId"]: + continue + from gui_core.dialogs import DefaultFontDialog + + dlg = DefaultFontDialog( + parent=self, + title=_("Select font"), + style=wx.DEFAULT_DIALOG_STYLE, + type="font", + ) + if dlg.ShowModal() == wx.ID_OK: + if dlg.font: + p["value"] = dlg.font + self.FindWindowById(p["wxId"][1]).SetValue(dlg.font) + self.OnUpdateValues(event) + dlg.Destroy() def OnUpdateSelection(self, event): """Update dialog (layers, tables, columns, etc.)""" @@ -3076,7 +3089,7 @@ def ParseCommand(self, cmd, completed=None): try: global _blackList self.grass_task = gtask.parse_interface(cmd[0], blackList=_blackList) - except (grass.ScriptError, ValueError) as e: + except (ScriptError, ValueError) as e: raise gcmd.GException(e.value) # if layer parameters previously set, re-insert them into dialog @@ -3102,32 +3115,34 @@ def ParseCommand(self, cmd, completed=None): else: self.grass_task.set_flag(option[1], True) cmd_validated.append(option) - else: # parameter - try: - key, value = option.split("=", 1) - except ValueError: - if self.grass_task.firstParam: - if i == 0: # add key name of first parameter if not given - key = self.grass_task.firstParam - value = option - else: - raise gcmd.GException( - _("Unable to parse command '%s'") % " ".join(cmd) - ) - else: - continue + continue - task = self.grass_task.get_param(key, raiseError=False) - if not task: - err.append( - _("%(cmd)s: parameter '%(key)s' not available") - % {"cmd": cmd[0], "key": key} - ) + # parameter + try: + key, value = option.split("=", 1) + except ValueError: + if self.grass_task.firstParam: + if i == 0: # add key name of first parameter if not given + key = self.grass_task.firstParam + value = option + else: + raise gcmd.GException( + _("Unable to parse command '%s'") % " ".join(cmd) + ) + else: continue - self.grass_task.set_param(key, value) - cmd_validated.append(key + "=" + value) - i += 1 + task = self.grass_task.get_param(key, raiseError=False) + if not task: + err.append( + _("%(cmd)s: parameter '%(key)s' not available") + % {"cmd": cmd[0], "key": key} + ) + continue + + self.grass_task.set_param(key, value) + cmd_validated.append(key + "=" + value) + i += 1 # update original command list cmd = cmd_validated @@ -3179,16 +3194,17 @@ def GetCommandInputMapParamKey(self, cmd): self.grass_task = gtask.processTask(tree).get_task() for p in self.grass_task.params: - if p.get("name", "") in {"input", "map"}: - age = p.get("age", "") - prompt = p.get("prompt", "") - element = p.get("element", "") - if ( - age == "old" - and element in {"cell", "grid3", "vector"} - and prompt in {"raster", "raster_3d", "vector"} - ): - return p.get("name", None) + if p.get("name", "") not in {"input", "map"}: + continue + age = p.get("age", "") + prompt = p.get("prompt", "") + element = p.get("element", "") + if ( + age == "old" + and (element in {"cell", "grid3", "vector"}) + and (prompt in {"raster", "raster_3d", "vector"}) + ): + return p.get("name", None) return None diff --git a/gui/wxpython/gui_core/goutput.py b/gui/wxpython/gui_core/goutput.py index 6676eb69935..75a1edb8fea 100644 --- a/gui/wxpython/gui_core/goutput.py +++ b/gui/wxpython/gui_core/goutput.py @@ -619,12 +619,13 @@ def AddStyledMessage(self, message, style=None): for c in message: if c == "\b": self.linePos -= 1 - else: - self.SetCurrentPos(self.linePos) - self.ReplaceSelection(c) - self.linePos = self.GetCurrentPos() - if c != " ": - last_c = c + continue + + self.SetCurrentPos(self.linePos) + self.ReplaceSelection(c) + self.linePos = self.GetCurrentPos() + if c != " ": + last_c = c if last_c not in (digits): self.AddTextWrapped("\n", wrap=None) self.linePos = -1 diff --git a/gui/wxpython/gui_core/gselect.py b/gui/wxpython/gui_core/gselect.py index bcb744d8562..5f6689974f2 100644 --- a/gui/wxpython/gui_core/gselect.py +++ b/gui/wxpython/gui_core/gselect.py @@ -596,30 +596,32 @@ def _getElementList(self, element, mapsets=None, elements=None, exclude=False): sys.stderr.write(_("GSelect: invalid item: %s") % e) continue - if self.seltree.ItemHasChildren(mapset_node): - sel = UserSettings.Get( - group="appearance", key="elementListExpand", subkey="selection" - ) - collapse = True - - if sel == 0: # collapse all except PERMANENT and current - if mapset in {"PERMANENT", curr_mapset}: - collapse = False - elif sel == 1: # collapse all except PERMANENT - if mapset == "PERMANENT": - collapse = False - elif sel == 2: # collapse all except current - if mapset == curr_mapset: - collapse = False - elif sel == 3: # collapse all - pass - elif sel == 4: # expand all + if not self.seltree.ItemHasChildren(mapset_node): + continue + + sel = UserSettings.Get( + group="appearance", key="elementListExpand", subkey="selection" + ) + collapse = True + + if sel == 0: # collapse all except PERMANENT and current + if mapset in {"PERMANENT", curr_mapset}: + collapse = False + elif sel == 1: # collapse all except PERMANENT + if mapset == "PERMANENT": collapse = False + elif sel == 2: # collapse all except current + if mapset == curr_mapset: + collapse = False + elif sel == 3: # collapse all + pass + elif sel == 4: # expand all + collapse = False - if collapse: - self.seltree.CollapseAllChildren(mapset_node) - else: - self.seltree.ExpandAllChildren(mapset_node) + if collapse: + self.seltree.CollapseAllChildren(mapset_node) + else: + self.seltree.ExpandAllChildren(mapset_node) if first_mapset: # select first mapset (MSW hack) @@ -637,22 +639,24 @@ def _addItems(self, elist, elements, mapset, exclude, node): """ elist = gs.naturally_sorted(elist) for elem in elist: - if elem != "": - fullqElem = elem + "@" + mapset - if self.filterItems and fullqElem not in self.filterItems: - continue # skip items missed in self.filterItems - - if elements is not None: - if (exclude and fullqElem in elements) or ( - not exclude and fullqElem not in elements - ): - continue + if elem == "": + continue - if self.filterElements: - if self.filterElements(fullqElem): - self.AddItem(elem, mapset=mapset, node=False, parent=node) - else: + fullqElem = elem + "@" + mapset + if self.filterItems and fullqElem not in self.filterItems: + continue # skip items missed in self.filterItems + + if elements is not None: + if (exclude and fullqElem in elements) or ( + not exclude and fullqElem not in elements + ): + continue + + if self.filterElements: + if self.filterElements(fullqElem): self.AddItem(elem, mapset=mapset, node=False, parent=node) + else: + self.AddItem(elem, mapset=mapset, node=False, parent=node) def AddItem(self, value, mapset=None, node=True, parent=None): if not parent: @@ -2091,20 +2095,21 @@ def GetDsn(self): connection_string = None for conn in ret.splitlines(): db_login = conn.split("|") - if db_login[0] == "pg": - user, password, host, port = db_login[2:] - connection_string = ( - f"PG:dbname={self.dbWidgets['choice'].GetStringSelection()}" - ) - if user: - connection_string += f" user={user}" - if password: - connection_string += f" password={password}" - if host: - connection_string += f" host={host}" - if port: - connection_string += f" port={port}" - return connection_string + if db_login[0] != "pg": + continue + user, password, host, port = db_login[2:] + connection_string = ( + f"PG:dbname={self.dbWidgets['choice'].GetStringSelection()}" + ) + if user: + connection_string += f" user={user}" + if password: + connection_string += f" password={password}" + if host: + connection_string += f" host={host}" + if port: + connection_string += f" port={port}" + return connection_string if not connection_string: GError(parent=self, message=message) return @@ -2968,26 +2973,26 @@ def _isMapSelected(self): def _chckMap(self): """Check if selected map in 'input' widget is the same as selected map in lmgr""" - if self._isMapSelected(): - layerList = self.giface.GetLayerList() - layerSelected = layerList.GetSelectedLayer() - # d.vect module - inputName = self.task.get_param(value="map", raiseError=False) - if not inputName: - inputName = self.task.get_param("input") - if inputName["value"] != str(layerSelected): - if inputName["value"] == "" or inputName["value"] is None: - GWarning(_("Input vector map is not selected")) - return False - GWarning( - _( - "Input vector map <%s> and selected map <%s> in layer manager " - "are different. Operation canceled." - ) - % (inputName["value"], str(layerSelected)) - ) - return False + if not self._isMapSelected(): + return False + layerList = self.giface.GetLayerList() + layerSelected = layerList.GetSelectedLayer() + # d.vect module + inputName = self.task.get_param(value="map", raiseError=False) + if not inputName: + inputName = self.task.get_param("input") + if inputName["value"] == str(layerSelected): return True + if inputName["value"] == "" or inputName["value"] is None: + GWarning(_("Input vector map is not selected")) + return False + GWarning( + _( + "Input vector map <%s> and selected map <%s> in layer manager " + "are different. Operation canceled." + ) + % (inputName["value"], str(layerSelected)) + ) return False def _onClick(self, evt=None): diff --git a/gui/wxpython/gui_core/menu.py b/gui/wxpython/gui_core/menu.py index a512b6eea19..2f462625dbd 100644 --- a/gui/wxpython/gui_core/menu.py +++ b/gui/wxpython/gui_core/menu.py @@ -62,11 +62,11 @@ def _createMenu(self, node): label = child.label subMenu = self._createMenu(child) menu.AppendMenu(wx.ID_ANY, label, subMenu) - else: - data = child.data.copy() - data.pop("label") + continue + data = child.data.copy() + data.pop("label") - self._createMenuItem(menu, label=child.label, **data) + self._createMenuItem(menu, label=child.label, **data) return menu diff --git a/gui/wxpython/gui_core/vselect.py b/gui/wxpython/gui_core/vselect.py index 206c1dbb43e..cded2aa9be7 100644 --- a/gui/wxpython/gui_core/vselect.py +++ b/gui/wxpython/gui_core/vselect.py @@ -30,6 +30,7 @@ from gui_core.wrap import Button, ListCtrl import grass.script as gs +from grass.exceptions import ScriptError from grass.pydispatch.signal import Signal @@ -302,7 +303,7 @@ def QuerySelectedMap(self): distance=threshold, skip_attributes=True, ) - except gs.ScriptError: + except ScriptError: GError( parent=self, message=_("Failed to query vector map(s) <%s>.") % self.map ) diff --git a/gui/wxpython/gui_core/widgets.py b/gui/wxpython/gui_core/widgets.py index 47bd3a1957c..3c84af4ecbc 100644 --- a/gui/wxpython/gui_core/widgets.py +++ b/gui/wxpython/gui_core/widgets.py @@ -183,12 +183,12 @@ def DeletePage(self, page): :return bool: True if page was deleted, False if not exists """ delPageIndex = self.GetPageIndexByName(page) - if delPageIndex != -1: - ret = self.classObject.DeletePage(self.widget, delPageIndex) - if ret: - del self.notebookPages[page] - return ret - return False + if delPageIndex == -1: + return False + ret = self.classObject.DeletePage(self.widget, delPageIndex) + if ret: + del self.notebookPages[page] + return ret def RemovePage(self, page): """Delete page without deleting the associated window. @@ -197,12 +197,12 @@ def RemovePage(self, page): :return: True if page was deleted, False if not exists """ delPageIndex = self.GetPageIndexByName(page) - if delPageIndex != -1: - ret = self.classObject.RemovePage(self.widget, delPageIndex) - if ret: - del self.notebookPages[page] - return ret - return False + if delPageIndex == -1: + return False + ret = self.classObject.RemovePage(self.widget, delPageIndex) + if ret: + del self.notebookPages[page] + return ret def SetSelectionByName(self, page): """Set active notebook page. diff --git a/gui/wxpython/iclass/frame.py b/gui/wxpython/iclass/frame.py index 4bb9e66b6c4..9901ccf3322 100644 --- a/gui/wxpython/iclass/frame.py +++ b/gui/wxpython/iclass/frame.py @@ -792,25 +792,25 @@ def ImportClasses(self, vector): for cat in cats: listCtrl.AddCategory(cat=cat, name="class_%d" % cat, color="0:0:0") + + return + # connection, table and columns exists - else: - columns = ["cat", "class", "color"] - ret = RunCommand( - "v.db.select", - quiet=True, - parent=self, - flags="c", - map=vector, - layer=1, - columns=",".join(columns), - read=True, - ) - records = ret.strip().splitlines() - for record in records: - record = record.split("|") - listCtrl.AddCategory( - cat=int(record[0]), name=record[1], color=record[2] - ) + columns = ["cat", "class", "color"] + ret = RunCommand( + "v.db.select", + quiet=True, + parent=self, + flags="c", + map=vector, + layer=1, + columns=",".join(columns), + read=True, + ) + records = ret.strip().splitlines() + for record in records: + record = record.split("|") + listCtrl.AddCategory(cat=int(record[0]), name=record[1], color=record[2]) def OnExportAreas(self, event): """Export training areas""" diff --git a/gui/wxpython/image2target/ii2t_gis_set.py b/gui/wxpython/image2target/ii2t_gis_set.py index 1022ef2c9b5..e2b3da9e60d 100644 --- a/gui/wxpython/image2target/ii2t_gis_set.py +++ b/gui/wxpython/image2target/ii2t_gis_set.py @@ -345,12 +345,11 @@ def _set_properties(self, version, revision): sys.stderr.write( _("ERROR: Location <%s> not found\n") % self.GetRCValue("LOCATION_NAME") ) - if len(self.listOfLocations) > 0: - self.lblocations.SetSelection(0, force=True) - self.lblocations.EnsureVisible(0) - location = self.listOfLocations[0] - else: + if len(self.listOfLocations) <= 0: return + self.lblocations.SetSelection(0, force=True) + self.lblocations.EnsureVisible(0) + location = self.listOfLocations[0] # list of mapsets self.UpdateMapsets(os.path.join(self.gisdbase, location)) @@ -1111,34 +1110,32 @@ def OnStart(self, event): ret = dlg.ShowModal() dlg.Destroy() - if ret == wx.ID_YES: - dlg1 = wx.MessageDialog( - parent=self, - message=_( - "ARE YOU REALLY SURE?\n\n" - "If you really are running another GRASS session doing this " - "could corrupt your data. Have another look in the processor " - "manager just to be sure..." - ), - caption=_("Lock file found"), - style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION | wx.CENTRE, - ) + if ret != wx.ID_YES: + return - ret = dlg1.ShowModal() - dlg1.Destroy() + dlg1 = wx.MessageDialog( + parent=self, + message=_( + "ARE YOU REALLY SURE?\n\n" + "If you really are running another GRASS session doing this " + "could corrupt your data. Have another look in the processor " + "manager just to be sure..." + ), + caption=_("Lock file found"), + style=wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION | wx.CENTRE, + ) + ret = dlg1.ShowModal() + dlg1.Destroy() - if ret == wx.ID_YES: - try: - os.remove(lockfile) - except OSError as e: - GError( - _("Unable to remove '%(lock)s'.\n\nDetails: %(reason)s") - % {"lock": lockfile, "reason": e} - ) - else: - return - else: + if ret != wx.ID_YES: return + try: + os.remove(lockfile) + except OSError as e: + GError( + _("Unable to remove '%(lock)s'.\n\nDetails: %(reason)s") + % {"lock": lockfile, "reason": e} + ) self.SetLocation(dbase, location, mapset) self.ExitSuccessfully() diff --git a/gui/wxpython/image2target/ii2t_manager.py b/gui/wxpython/image2target/ii2t_manager.py index 97d528bcf7d..183537519e0 100644 --- a/gui/wxpython/image2target/ii2t_manager.py +++ b/gui/wxpython/image2target/ii2t_manager.py @@ -910,9 +910,7 @@ def OnEnterPage(self, event: WizardEvent | None = None) -> None: flags="g", ) - if ret: - self.parent.src_maps = ret.splitlines() - else: + if not ret: GError( parent=self, message=_( @@ -922,6 +920,7 @@ def OnEnterPage(self, event: WizardEvent | None = None) -> None: % self.parent.grouppage.xygroup, ) return + self.parent.src_maps = ret.splitlines() elif maptype == "vector": grassdatabase = self.parent.grassdatabase @@ -1703,7 +1702,7 @@ def OnRMS(self, event): targetMapWin = self.TgtMapWindow targetMapWin.UpdateMap(render=False, renderVector=False) - def CheckGCPcount(self, msg=False): + def CheckGCPcount(self, msg: bool = False) -> bool: """ Checks to make sure that the minimum number of GCPs have been defined and are active for the selected transformation order @@ -1725,9 +1724,10 @@ def CheckGCPcount(self, msg=False): ) % self.gr_order, ) - return False - else: - return True + + return False + + return True def OnGeorect(self, event): """ @@ -1959,9 +1959,7 @@ def RMSError(self, xygroup, order): self.grwiz.SwitchEnv("target") - if ret: - errlist = ret.splitlines() - else: + if not ret: GError( parent=self, message=_( @@ -1970,6 +1968,7 @@ def RMSError(self, xygroup, order): ), ) return + errlist = ret.splitlines() # insert error values into GCP list for checked items sdfactor = float(UserSettings.Get(group="gcpman", key="rms", subkey="sdfactor")) @@ -2000,12 +1999,13 @@ def RMSError(self, xygroup, order): sumsq_bkw_err += float(bkw_err) ** 2 sum_fwd_err += float(fwd_err) GCPcount += 1 - else: - self.list.SetItem(index, 7, "") - self.list.SetItem(index, 8, "") - self.mapcoordlist[key][7] = 0.0 - self.mapcoordlist[key][8] = 0.0 - self.list.SetItemTextColour(index, wx.BLACK) + continue + + self.list.SetItem(index, 7, "") + self.list.SetItem(index, 8, "") + self.mapcoordlist[key][7] = 0.0 + self.mapcoordlist[key][8] = 0.0 + self.list.SetItemTextColour(index, wx.BLACK) # SD if GCPcount > 0: @@ -2093,9 +2093,7 @@ def GetNewExtent(self, region, map=None): self.grwiz.SwitchEnv("target") - if ret: - errlist = ret.splitlines() - else: + if not ret: GError( parent=self, message=_( @@ -2104,6 +2102,7 @@ def GetNewExtent(self, region, map=None): ), ) return + errlist = ret.splitlines() # fist corner e, n = errlist[0].split() diff --git a/gui/wxpython/iscatt/controllers.py b/gui/wxpython/iscatt/controllers.py index f87569b2698..873ddf02071 100644 --- a/gui/wxpython/iscatt/controllers.py +++ b/gui/wxpython/iscatt/controllers.py @@ -957,16 +957,15 @@ def SetData(self): bands = [] while True: - if dlg.ShowModal() == wx.ID_OK: - bands = dlg.GetGroupBandsErr(parent=self.scatt_mgr.guiparent) - if bands: - name, s = dlg.GetData() - group = gs.find_file(name=name, element="group") - self.set_g["group"] = group["name"] - self.set_g["subg"] = s - - break - else: + if dlg.ShowModal() != wx.ID_OK: + break + bands = dlg.GetGroupBandsErr(parent=self.scatt_mgr.guiparent) + if bands: + name, s = dlg.GetData() + group = gs.find_file(name=name, element="group") + self.set_g["group"] = group["name"] + self.set_g["subg"] = s + break dlg.Destroy() diff --git a/gui/wxpython/iscatt/frame.py b/gui/wxpython/iscatt/frame.py index 542d8acc2c3..46a4f1c6547 100644 --- a/gui/wxpython/iscatt/frame.py +++ b/gui/wxpython/iscatt/frame.py @@ -694,16 +694,15 @@ def OnRename(self, event): dlg.CentreOnParent() while True: - if dlg.ShowModal() == wx.ID_OK: - name = dlg.GetNewName().strip() - if not name: - GMessage(parent=self, message=_("Empty name was inserted.")) - else: - self.cats_mgr.SetCategoryAttrs(cat_id, {"name": name}) - break - else: + if dlg.ShowModal() != wx.ID_OK: break + name = dlg.GetNewName().strip() + if name: + self.cats_mgr.SetCategoryAttrs(cat_id, {"name": name}) + break + GMessage(parent=self, message=_("Empty name was inserted.")) + dlg.Destroy() def _setCatAttrs(self, cat_id, attrs): diff --git a/gui/wxpython/lmgr/workspace.py b/gui/wxpython/lmgr/workspace.py index 7971e3c4064..395fd0b61a5 100644 --- a/gui/wxpython/lmgr/workspace.py +++ b/gui/wxpython/lmgr/workspace.py @@ -317,35 +317,37 @@ def Load(self, filename): for overlay in gxwXml.overlays: # overlay["cmd"][0] name of command e.g. d.barscale, d.legend # overlay["cmd"][1:] parameters and flags - if overlay["display"] == i: - if overlay["cmd"][0] == "d.legend.vect": - mapdisplay[i].AddLegendVect(overlay["cmd"]) - if overlay["cmd"][0] == "d.legend": - mapdisplay[i].AddLegendRast(overlay["cmd"]) - if overlay["cmd"][0] == "d.barscale": - mapdisplay[i].AddBarscale(overlay["cmd"]) - if overlay["cmd"][0] == "d.northarrow": - mapdisplay[i].AddArrow(overlay["cmd"]) - if overlay["cmd"][0] == "d.text": - mapdisplay[i].AddDtext(overlay["cmd"]) + if overlay["display"] != i: + continue + if overlay["cmd"][0] == "d.legend.vect": + mapdisplay[i].AddLegendVect(overlay["cmd"]) + if overlay["cmd"][0] == "d.legend": + mapdisplay[i].AddLegendRast(overlay["cmd"]) + if overlay["cmd"][0] == "d.barscale": + mapdisplay[i].AddBarscale(overlay["cmd"]) + if overlay["cmd"][0] == "d.northarrow": + mapdisplay[i].AddArrow(overlay["cmd"]) + if overlay["cmd"][0] == "d.text": + mapdisplay[i].AddDtext(overlay["cmd"]) # avoid double-rendering when loading workspace # mdisp.MapWindow2D.UpdateMap() # nviz - if gxwXml.displays[i]["viewMode"] == "3d": - mapdisplay[i].AddNviz() - self.lmgr.nvizUpdateState( - view=gxwXml.nviz_state["view"], - iview=gxwXml.nviz_state["iview"], - light=gxwXml.nviz_state["light"], - ) - mapdisplay[i].MapWindow3D.constants = gxwXml.nviz_state["constants"] - for idx, constant in enumerate(mapdisplay[i].MapWindow3D.constants): - mapdisplay[i].MapWindow3D.AddConstant(constant, i + 1) - for page in ("view", "light", "fringe", "constant", "cplane"): - self.lmgr.nvizUpdatePage(page) - self.lmgr.nvizUpdateSettings() - mapdisplay[i].toolbars["map"].combo.SetSelection(1) + if gxwXml.displays[i]["viewMode"] != "3d": + continue + mapdisplay[i].AddNviz() + self.lmgr.nvizUpdateState( + view=gxwXml.nviz_state["view"], + iview=gxwXml.nviz_state["iview"], + light=gxwXml.nviz_state["light"], + ) + mapdisplay[i].MapWindow3D.constants = gxwXml.nviz_state["constants"] + for idx, constant in enumerate(mapdisplay[i].MapWindow3D.constants): + mapdisplay[i].MapWindow3D.AddConstant(constant, i + 1) + for page in ("view", "light", "fringe", "constant", "cplane"): + self.lmgr.nvizUpdatePage(page) + self.lmgr.nvizUpdateSettings() + mapdisplay[i].toolbars["map"].combo.SetSelection(1) # # load layout diff --git a/gui/wxpython/location_wizard/dialogs.py b/gui/wxpython/location_wizard/dialogs.py index 74a59cca525..6573aeb717a 100644 --- a/gui/wxpython/location_wizard/dialogs.py +++ b/gui/wxpython/location_wizard/dialogs.py @@ -50,9 +50,7 @@ def __init__( self.parent = parent self.location = location - # # default values - # # 2D self.north = 1.0 self.south = 0.0 @@ -67,9 +65,7 @@ def __init__( # self.ewres3 = 1.0 self.tbres = 1.0 - # # inputs - # # 2D self.tnorth = self.MakeTextCtrl( text=str(self.north), size=(150, -1), parent=panel @@ -80,43 +76,26 @@ def __init__( self.tnsres = self.MakeTextCtrl(str(self.nsres), size=(150, -1), parent=panel) self.tewres = self.MakeTextCtrl(str(self.ewres), size=(150, -1), parent=panel) - # # labels - # self.lrows = self.MakeLabel(parent=panel) self.lcols = self.MakeLabel(parent=panel) self.lcells = self.MakeLabel(parent=panel) - # # buttons - # self.bset = self.MakeButton(text=_("&Set region"), id=wx.ID_OK, parent=panel) self.bcancel = Button(panel, id=wx.ID_CANCEL) self.bset.SetDefault() - # # image - # self.img = wx.Image( os.path.join(globalvar.IMGDIR, "qgis_world.png"), wx.BITMAP_TYPE_PNG ).ConvertToBitmap() - # # set current working environment to PERMANENT mapset # in selected location in order to set default region (WIND) - # envval = {} ret = RunCommand("g.gisenv", read=True) - if ret: - for line in ret.splitlines(): - key, val = line.split("=") - envval[key] = val - self.currlocation = envval["LOCATION_NAME"].strip("';") - self.currmapset = envval["MAPSET"].strip("';") - if self.currlocation != self.location or self.currmapset != "PERMANENT": - RunCommand("g.gisenv", set="LOCATION_NAME=%s" % self.location) - RunCommand("g.gisenv", set="MAPSET=PERMANENT") - else: + if not ret: dlg = wx.MessageBox( parent=self, message=_("Invalid location selected."), @@ -124,17 +103,19 @@ def __init__( style=wx.ID_OK | wx.ICON_ERROR, ) return + for line in ret.splitlines(): + key, val = line.split("=") + envval[key] = val + self.currlocation = envval["LOCATION_NAME"].strip("';") + self.currmapset = envval["MAPSET"].strip("';") + if self.currlocation != self.location or self.currmapset != "PERMANENT": + RunCommand("g.gisenv", set="LOCATION_NAME=%s" % self.location) + RunCommand("g.gisenv", set="MAPSET=PERMANENT") - # # get current region settings - # region = {} ret = RunCommand("g.region", read=True, flags="gp3") - if ret: - for line in ret.splitlines(): - key, val = line.split("=") - region[key] = float(val) - else: + if not ret: dlg = wx.MessageBox( parent=self, message=_("Invalid region"), @@ -144,8 +125,10 @@ def __init__( dlg.ShowModal() dlg.Destroy() return + for line in ret.splitlines(): + key, val = line.split("=") + region[key] = float(val) - # # update values # 2D self.north = float(region["n"]) @@ -166,9 +149,7 @@ def __init__( self.depth = int(region["depths"]) self.cells3 = int(region["cells3"]) - # # 3D box collapsible - # self.infoCollapseLabelExp = _("Click here to show 3D settings") self.infoCollapseLabelCol = _("Click here to hide 3D settings") self.settings3D = wx.CollapsiblePane( @@ -184,9 +165,7 @@ def __init__( self.settings3D, ) - # # set current region settings - # self.tnorth.SetValue(str(self.north)) self.tsouth.SetValue(str(self.south)) self.twest.SetValue(str(self.west)) @@ -202,9 +181,7 @@ def __init__( self.lcols.SetLabel(_("Cols: %d") % self.cols) self.lcells.SetLabel(_("Cells: %d") % self.cells) - # # bindings - # self.Bind(wx.EVT_BUTTON, self.OnSetButton, self.bset) self.Bind(wx.EVT_BUTTON, self.OnCancel, self.bcancel) self.tnorth.Bind(wx.EVT_TEXT, self.OnValue) diff --git a/gui/wxpython/location_wizard/wizard.py b/gui/wxpython/location_wizard/wizard.py index 885b80a26a5..39d1bf7fea4 100644 --- a/gui/wxpython/location_wizard/wizard.py +++ b/gui/wxpython/location_wizard/wizard.py @@ -73,7 +73,7 @@ ) from location_wizard.dialogs import SelectTransformDialog -from grass.exceptions import OpenError +from grass.exceptions import OpenError, ScriptError from grass.grassdb.checks import location_exists from grass.script import core as grass from grass.script import decode @@ -2739,7 +2739,7 @@ def OnWizFinished(self): desc=self.startpage.locTitle, ) - except grass.ScriptError as e: + except ScriptError as e: return e.value return None diff --git a/gui/wxpython/mapdisp/frame.py b/gui/wxpython/mapdisp/frame.py index 52eae9f6224..45dd4f52109 100644 --- a/gui/wxpython/mapdisp/frame.py +++ b/gui/wxpython/mapdisp/frame.py @@ -64,6 +64,7 @@ import grass.script as gs from grass.pydispatch.signal import Signal +from grass.exceptions import ScriptError if TYPE_CHECKING: import lmgr.frame @@ -1103,7 +1104,7 @@ def QueryMap(self, east, north, qdist, rast, vect): encoding=encoding, multiple=True, ) - except gs.ScriptError: + except ScriptError: GError( parent=self, message=_( @@ -1216,23 +1217,23 @@ def AddTmpVectorMapLayer( cmd[-1].append("layer=%d" % layer) cmd[-1].append("cats=%s" % ListOfCatsToRange(lcats)) - if addLayer: - args = {} - if useId: - args["ltype"] = "vector" - else: - args["ltype"] = "command" - - return self.Map.AddLayer( - name=globalvar.QUERYLAYER, - command=cmd, - active=True, - hidden=True, - opacity=1.0, - render=True, - **args, - ) - return cmd + if not addLayer: + return cmd + + args = {} + if useId: + args["ltype"] = "vector" + else: + args["ltype"] = "command" + return self.Map.AddLayer( + name=globalvar.QUERYLAYER, + command=cmd, + active=True, + hidden=True, + opacity=1.0, + render=True, + **args, + ) def OnMeasureDistance(self, event): self._onMeasure(MeasureDistanceController) diff --git a/gui/wxpython/mapdisp/main.py b/gui/wxpython/mapdisp/main.py index 76ae6218d5a..42f47e2dfd8 100644 --- a/gui/wxpython/mapdisp/main.py +++ b/gui/wxpython/mapdisp/main.py @@ -216,24 +216,26 @@ def GetLayersFromCmdFile(self): exists = False for i, layer in enumerate(existingLayers): - if layer.GetCmd(string=True) == utils.GetCmdString( + if layer.GetCmd(string=True) != utils.GetCmdString( cmdlist_to_tuple(cmd) ): - exists = True - - if layersOrder[i] == -1: - layersOrder[i] = next_layer - next_layer += 1 - # layer must be put higher in render order (same cmd was - # insered more times) - # TODO delete rendurant cmds from cmd file? - else: - for j, l_order in enumerate(layersOrder): - if l_order > layersOrder[i]: - layersOrder[j] -= 1 - layersOrder[i] = next_layer - 1 - - break + continue + + exists = True + + if layersOrder[i] == -1: + layersOrder[i] = next_layer + next_layer += 1 + # layer must be put higher in render order (same cmd was + # insered more times) + # TODO delete rendurant cmds from cmd file? + else: + for j, l_order in enumerate(layersOrder): + if l_order > layersOrder[i]: + layersOrder[j] -= 1 + layersOrder[i] = next_layer - 1 + + break if exists: continue diff --git a/gui/wxpython/mapdisp/statusbar.py b/gui/wxpython/mapdisp/statusbar.py index 7e60e762281..ae0b3b832d0 100644 --- a/gui/wxpython/mapdisp/statusbar.py +++ b/gui/wxpython/mapdisp/statusbar.py @@ -626,11 +626,11 @@ def GetCenterString(self, map): projOut=projection, flags="d", ) - if coord: - if proj in {"ll", "latlong", "longlat"} and format == "DMS": - return "%s" % utils.Deg2DMS(coord[0], coord[1], precision=precision) - return "%.*f; %.*f" % (precision, coord[0], precision, coord[1]) - raise SbException(_("Error in projection (check the settings)")) + if not coord: + raise SbException(_("Error in projection (check the settings)")) + if proj in {"ll", "latlong", "longlat"} and format == "DMS": + return "%s" % utils.Deg2DMS(coord[0], coord[1], precision=precision) + return "%.*f; %.*f" % (precision, coord[0], precision, coord[1]) if self.mapFrame.GetMap().projinfo["proj"] == "ll" and format == "DMS": return "%s" % utils.Deg2DMS( region["center_easting"], @@ -786,23 +786,21 @@ def ReprojectENFromMap(self, e, n, useDefinedProjection, precision, format): @throws SbException if useDefinedProjection is True and projection is not defined in UserSettings """ - if useDefinedProjection: - settings = UserSettings.Get( - group="projection", key="statusbar", subkey="proj4" - ) - if not settings: - raise SbException(_("Projection not defined (check the settings)")) - # reproject values - proj, coord = utils.ReprojectCoordinates( - coord=(e, n), projOut=settings, flags="d" - ) - if coord: - e, n = coord - if proj in {"ll", "latlong", "longlat"} and format == "DMS": - return utils.Deg2DMS(e, n, precision=precision) - return "%.*f; %.*f" % (precision, e, precision, n) + if not useDefinedProjection: + if self.mapFrame.GetMap().projinfo["proj"] == "ll" and format == "DMS": + return utils.Deg2DMS(e, n, precision=precision) + return "%.*f; %.*f" % (precision, e, precision, n) + settings = UserSettings.Get(group="projection", key="statusbar", subkey="proj4") + if not settings: + raise SbException(_("Projection not defined (check the settings)")) + # reproject values + proj, coord = utils.ReprojectCoordinates( + coord=(e, n), projOut=settings, flags="d" + ) + if not coord: raise SbException(_("Error in projection (check the settings)")) - if self.mapFrame.GetMap().projinfo["proj"] == "ll" and format == "DMS": + e, n = coord + if proj in {"ll", "latlong", "longlat"} and format == "DMS": return utils.Deg2DMS(e, n, precision=precision) return "%.*f; %.*f" % (precision, e, precision, n) diff --git a/gui/wxpython/mapwin/buffered.py b/gui/wxpython/mapwin/buffered.py index a808875f2a8..bdeeaf1314c 100644 --- a/gui/wxpython/mapwin/buffered.py +++ b/gui/wxpython/mapwin/buffered.py @@ -797,18 +797,19 @@ def GetOverlay(self): imgs = [] for overlay in self.Map.GetListOfLayers(ltype="overlay", active=True): if ( - overlay.mapfile is not None - and os.path.isfile(overlay.mapfile) - and os.path.getsize(overlay.mapfile) + overlay.mapfile is None + or not os.path.isfile(overlay.mapfile) + or (not os.path.getsize(overlay.mapfile)) ): - img = utils.autoCropImageFromFile(overlay.mapfile) + continue + img = utils.autoCropImageFromFile(overlay.mapfile) - for key in list(self.imagedict.keys()): - if self.imagedict[key]["id"] == overlay.id: - del self.imagedict[key] + for key in list(self.imagedict.keys()): + if self.imagedict[key]["id"] == overlay.id: + del self.imagedict[key] - self.imagedict[img] = {"id": overlay.id, "layer": overlay} - imgs.append(img) + self.imagedict[img] = {"id": overlay.id, "layer": overlay} + imgs.append(img) return imgs @@ -1214,23 +1215,17 @@ def DrawLines(self, pdc=None, polycoords=None): if not polycoords: polycoords = self.polycoords - if len(polycoords) > 0: - self.plineid = wx.ID_NEW + 1 - # convert from EN to XY - coords = [] - for p in polycoords: - coords.append(self.Cell2Pixel(p)) - - self.Draw(pdc, drawid=self.plineid, pdctype="polyline", coords=coords) - - Debug.msg( - 4, - "BufferedWindow.DrawLines(): coords=%s, id=%s" % (coords, self.plineid), - ) - - return self.plineid - - return -1 + if len(polycoords) <= 0: + return -1 + self.plineid = wx.ID_NEW + 1 + # convert from EN to XY + coords = [self.Cell2Pixel(p) for p in polycoords] + self.Draw(pdc, drawid=self.plineid, pdctype="polyline", coords=coords) + Debug.msg( + 4, + "BufferedWindow.DrawLines(): coords=%s, id=%s" % (coords, self.plineid), + ) + return self.plineid def DrawPolylines(self, pdc, coords, pen, drawid=None): """Draw polyline in PseudoDC. diff --git a/gui/wxpython/modules/extensions.py b/gui/wxpython/modules/extensions.py index 7837a92589d..9d65b8431a3 100644 --- a/gui/wxpython/modules/extensions.py +++ b/gui/wxpython/modules/extensions.py @@ -383,23 +383,25 @@ def Load(self, url, full=True): currentNode.data = {"command": value} elif currentNode is not None: currentNode.data[key] = value - else: - try: - prefix, name = line.strip().split(".", 1) - except ValueError: - prefix = "" - name = line.strip() - - if self._expandPrefix(prefix) == prefix: - prefix = "" - module = prefix + "." + name - mainNode = self.mainNodes[self._expandPrefix(prefix)] - currentNode = self.model.AppendNode(parent=mainNode, label=module) - currentNode.data = { - "command": module, - "keywords": "", - "description": "", - } + + continue + + try: + prefix, name = line.strip().split(".", 1) + except ValueError: + prefix = "" + name = line.strip() + + if self._expandPrefix(prefix) == prefix: + prefix = "" + module = prefix + "." + name + mainNode = self.mainNodes[self._expandPrefix(prefix)] + currentNode = self.model.AppendNode(parent=mainNode, label=module) + currentNode.data = { + "command": module, + "keywords": "", + "description": "", + } class ManageExtensionWindow(wx.Frame): diff --git a/gui/wxpython/modules/import_export.py b/gui/wxpython/modules/import_export.py index d83d468facf..2c160830689 100644 --- a/gui/wxpython/modules/import_export.py +++ b/gui/wxpython/modules/import_export.py @@ -398,13 +398,12 @@ def _getLayersToReprojetion(self, projMatch_idx, grassName_idx): ret = dlg.ShowModal() - if ret == wx.ID_OK: - # do not import unchecked layers - for itm in reversed(list(dlg.GetData(checked=False))): - idx = itm[-1] - layers.pop(idx) - else: + if ret != wx.ID_OK: return None + # do not import unchecked layers + for itm in reversed(list(dlg.GetData(checked=False))): + idx = itm[-1] + layers.pop(idx) return layers diff --git a/gui/wxpython/nviz/animation.py b/gui/wxpython/nviz/animation.py index 1eeb8d1aea8..fbc4bbed761 100644 --- a/gui/wxpython/nviz/animation.py +++ b/gui/wxpython/nviz/animation.py @@ -196,26 +196,25 @@ def SaveAnimationFile(self, path, prefix, format): self.currentFrame = 0 self.mode = "save" for params in self.animationList: - if not self.stopSaving: - self.UpdateView(params) - number = ("{frame" + formatter + "}").format(frame=self.currentFrame) - filename = "{prefix}_{number}.{ext}".format( - prefix=prefix, number=number, ext=self.formats[format] - ) - filepath = os.path.join(path, filename) - self.mapWindow.SaveToFile( - FileName=filepath, - FileType=self.formats[format], - width=size[0], - height=size[1], - ) - self.currentFrame += 1 - - wx.GetApp().Yield() - toolWin.UpdateFrameIndex(index=self.currentFrame, goToFrame=False) - else: + if self.stopSaving: self.stopSaving = False break + self.UpdateView(params) + number = ("{frame" + formatter + "}").format(frame=self.currentFrame) + filename = "{prefix}_{number}.{ext}".format( + prefix=prefix, number=number, ext=self.formats[format] + ) + filepath = os.path.join(path, filename) + self.mapWindow.SaveToFile( + FileName=filepath, + FileType=self.formats[format], + width=size[0], + height=size[1], + ) + self.currentFrame += 1 + + wx.GetApp().Yield() + toolWin.UpdateFrameIndex(index=self.currentFrame, goToFrame=False) self.animationSaved = True self.PostFinishedEvent() diff --git a/gui/wxpython/nviz/mapwindow.py b/gui/wxpython/nviz/mapwindow.py index b3f05ed6f04..2b716ef2131 100644 --- a/gui/wxpython/nviz/mapwindow.py +++ b/gui/wxpython/nviz/mapwindow.py @@ -2595,16 +2595,18 @@ def NvizCmdCommand(self): cmdLColor += "%s," % nvizData["lines"]["color"]["value"] cmdLMode += "%s," % nvizData["lines"]["mode"]["type"] cmdLPos += "0,0,%d," % nvizData["lines"]["height"]["value"] - if (vInfo["points"] + vInfo["centroids"]) > 0: - cmdPoints += ( - "%s," % self.tree.GetLayerInfo(vector, key="maplayer").GetName() - ) - cmdPWidth += "%d," % nvizData["points"]["width"]["value"] - cmdPSize += "%d," % nvizData["points"]["size"]["value"] - cmdPColor += "%s," % nvizData["points"]["color"]["value"] - cmdPMarker += "%s," % markers[nvizData["points"]["marker"]["value"]] - cmdPPos += "0,0,%d," % nvizData["points"]["height"]["value"] - cmdPLayer += "1,1," + if vInfo["points"] + vInfo["centroids"] <= 0: + continue + cmdPoints += ( + "%s," % self.tree.GetLayerInfo(vector, key="maplayer").GetName() + ) + cmdPWidth += "%d," % nvizData["points"]["width"]["value"] + cmdPSize += "%d," % nvizData["points"]["size"]["value"] + cmdPColor += "%s," % nvizData["points"]["color"]["value"] + cmdPMarker += "%s," % markers[nvizData["points"]["marker"]["value"]] + cmdPPos += "0,0,%d," % nvizData["points"]["height"]["value"] + cmdPLayer += "1,1," + if cmdLines: cmd += "vline=" + cmdLines.strip(",") + " " cmd += "vline_width=" + cmdLWidth.strip(",") + " " diff --git a/gui/wxpython/nviz/tools.py b/gui/wxpython/nviz/tools.py index f43de80944d..e398000ac00 100644 --- a/gui/wxpython/nviz/tools.py +++ b/gui/wxpython/nviz/tools.py @@ -5457,18 +5457,19 @@ def UpdateVectorPage(self, layer, data, updateName=True): display.SetSelection(1) else: display.SetSelection(0) - if data[vtype]["mode"]["type"] == "surface": - rasters = self.mapWindow.GetLayerNames("raster") - constants = self.mapWindow.GetLayerNames("constant") - surfaces = rasters + constants - surfaceWin = self.FindWindowById(self.win["vector"][vtype]["surface"]) - surfaceWin.SetItems(surfaces) - for idx, surface in enumerate(surfaces): - try: # TODO fix this mess - selected = data[vtype]["mode"]["surface"]["show"][idx] - except (TypeError, IndexError, KeyError): - selected = False - surfaceWin.Check(idx, selected) + if data[vtype]["mode"]["type"] != "surface": + continue + rasters = self.mapWindow.GetLayerNames("raster") + constants = self.mapWindow.GetLayerNames("constant") + surfaces = rasters + constants + surfaceWin = self.FindWindowById(self.win["vector"][vtype]["surface"]) + surfaceWin.SetItems(surfaces) + for idx, surface in enumerate(surfaces): + try: # TODO fix this mess + selected = data[vtype]["mode"]["surface"]["show"][idx] + except (TypeError, IndexError, KeyError): + selected = False + surfaceWin.Check(idx, selected) for type in ("slider", "text"): win = self.FindWindowById(self.win["vector"]["lines"]["height"][type]) diff --git a/gui/wxpython/nviz/wxnviz.py b/gui/wxpython/nviz/wxnviz.py index d4875212343..0c52eb14c15 100644 --- a/gui/wxpython/nviz/wxnviz.py +++ b/gui/wxpython/nviz/wxnviz.py @@ -467,13 +467,13 @@ def GetFocus( ) -> tuple[float, float, float] | tuple[Literal[-1], Literal[-1], Literal[-1]]: """Get focus""" Debug.msg(3, "Nviz::GetFocus()") - if Nviz_has_focus(self.data): - x = c_float() - y = c_float() - z = c_float() - Nviz_get_focus(self.data, byref(x), byref(y), byref(z)) - return x.value, y.value, z.value - return (-1, -1, -1) + if not Nviz_has_focus(self.data): + return (-1, -1, -1) + x = c_float() + y = c_float() + z = c_float() + Nviz_get_focus(self.data, byref(x), byref(y), byref(z)) + return (x.value, y.value, z.value) def SetFocus(self, x: float, y: float, z: float) -> None: """Set focus""" diff --git a/gui/wxpython/photo2image/ip2i_manager.py b/gui/wxpython/photo2image/ip2i_manager.py index f7a43bbcf6b..1c5206de67a 100644 --- a/gui/wxpython/photo2image/ip2i_manager.py +++ b/gui/wxpython/photo2image/ip2i_manager.py @@ -1048,7 +1048,7 @@ def OnRMS(self, event): targetMapWin = self.TgtMapWindow targetMapWin.UpdateMap(render=False) - def CheckGCPcount(self, msg=False): + def CheckGCPcount(self, msg: bool = False) -> bool: """ Checks to make sure that the minimum number of GCPs have been defined and are active for the selected transformation order @@ -1070,9 +1070,10 @@ def CheckGCPcount(self, msg=False): ) % self.gr_order, ) - return False - else: - return True + + return False + + return True def OnGeorect(self, event): """ @@ -1266,9 +1267,7 @@ def RMSError(self, xygroup, order): self.grwiz.SwitchEnv("target") - if ret: - errlist = ret.splitlines() - else: + if not ret: GError( parent=self, message=_( @@ -1276,6 +1275,7 @@ def RMSError(self, xygroup, order): ), ) return + errlist = ret.splitlines() # insert error values into GCP list for checked items sdfactor = float(UserSettings.Get(group="gcpman", key="rms", subkey="sdfactor")) @@ -1306,12 +1306,13 @@ def RMSError(self, xygroup, order): sumsq_bkw_err += float(bkw_err) ** 2 sum_fwd_err += float(fwd_err) GCPcount += 1 - else: - self.list.SetItem(index, 5, "") - self.list.SetItem(index, 6, "") - self.mapcoordlist[key][5] = 0.0 - self.mapcoordlist[key][6] = 0.0 - self.list.SetItemTextColour(index, wx.BLACK) + + continue + self.list.SetItem(index, 5, "") + self.list.SetItem(index, 6, "") + self.mapcoordlist[key][5] = 0.0 + self.mapcoordlist[key][6] = 0.0 + self.list.SetItemTextColour(index, wx.BLACK) # SD if GCPcount > 0: @@ -1401,9 +1402,7 @@ def GetNewExtent(self, region, map=None): self.grwiz.SwitchEnv("target") - if ret: - errlist = ret.splitlines() - else: + if not ret: GError( parent=self, message=_( @@ -1411,6 +1410,7 @@ def GetNewExtent(self, region, map=None): ), ) return + errlist = ret.splitlines() # fist corner e, n = errlist[0].split() diff --git a/gui/wxpython/psmap/dialogs.py b/gui/wxpython/psmap/dialogs.py index 41ae0bbceb7..bb76213b2bf 100644 --- a/gui/wxpython/psmap/dialogs.py +++ b/gui/wxpython/psmap/dialogs.py @@ -51,6 +51,7 @@ from wx import PyValidator as Validator import grass.script as gs +from grass.exceptions import ScriptError from core.gcmd import GError, GMessage, RunCommand from core.utils import PilImageToWxImage, cmp from dbmgr.vinfo import VectorDBInfo @@ -1394,138 +1395,114 @@ def update(self): mapFrameDict["scaleType"] = scaleType if mapFrameDict["scaleType"] == 0: - if self.select.GetValue(): - mapFrameDict["drawMap"] = self.drawMap.GetValue() - mapFrameDict["map"] = self.select.GetValue() - mapFrameDict["mapType"] = self.mapType - mapFrameDict["region"] = None - - if mapFrameDict["drawMap"]: - if mapFrameDict["mapType"] == "raster": - mapFile = gs.find_file(mapFrameDict["map"], element="cell") - if mapFile["file"] == "": - GMessage("Raster %s not found" % mapFrameDict["map"]) - return False - raster = self.instruction.FindInstructionByType("raster") - if raster: - raster["raster"] = mapFrameDict["map"] - else: - raster = Raster(NewId(), env=self.env) - raster["raster"] = mapFrameDict["map"] - raster["isRaster"] = True - self.instruction.AddInstruction(raster) - - elif mapFrameDict["mapType"] == "vector": - mapFile = gs.find_file(mapFrameDict["map"], element="vector") - if mapFile["file"] == "": - GMessage("Vector %s not found" % mapFrameDict["map"]) - return False - - vector = self.instruction.FindInstructionByType("vector") - isAdded = False - if vector: - for each in vector["list"]: - if each[0] == mapFrameDict["map"]: - isAdded = True - if not isAdded: - topoInfo = gs.vector_info_topo(map=mapFrameDict["map"]) - if topoInfo: - if bool(topoInfo["areas"]): - topoType = "areas" - elif bool(topoInfo["lines"]): - topoType = "lines" - else: - topoType = "points" - label = "(".join(mapFrameDict["map"].split("@")) + ")" - - if not vector: - vector = Vector(NewId(), env=self.env) - vector["list"] = [] - self.instruction.AddInstruction(vector) - id = NewId() - vector["list"].insert( - 0, [mapFrameDict["map"], topoType, id, 1, label] - ) - vProp = VProperties(id, topoType, env=self.env) - vProp["name"], vProp["label"], vProp["lpos"] = ( - mapFrameDict["map"], - label, - 1, - ) - self.instruction.AddInstruction(vProp) - else: - return False - - self.scale[0], self.center[0], self.rectAdjusted = AutoAdjust( - self, - scaleType=0, - map=mapFrameDict["map"], - env=self.env, - mapType=self.mapType, - rect=self.mapFrameDict["rect"], + if not self.select.GetValue(): + wx.MessageBox( + message=_("No map selected!"), + caption=_("Invalid input"), + style=wx.OK | wx.ICON_ERROR, ) + return False - if self.rectAdjusted: - mapFrameDict["rect"] = self.rectAdjusted - else: - mapFrameDict["rect"] = self.mapFrameDict["rect"] - - mapFrameDict["scale"] = self.scale[0] + mapFrameDict["drawMap"] = self.drawMap.GetValue() + mapFrameDict["map"] = self.select.GetValue() + mapFrameDict["mapType"] = self.mapType + mapFrameDict["region"] = None - mapFrameDict["center"] = self.center[0] - # set region - if self.mapType == "raster": - self.env["GRASS_REGION"] = gs.region_env( - raster=mapFrameDict["map"], env=self.env - ) - if self.mapType == "vector": + if mapFrameDict["drawMap"]: + if mapFrameDict["mapType"] == "raster": + mapFile = gs.find_file(mapFrameDict["map"], element="cell") + if mapFile["file"] == "": + GMessage("Raster %s not found" % mapFrameDict["map"]) + return False raster = self.instruction.FindInstructionByType("raster") - rasterId = raster.id if raster else None - - if rasterId: - self.env["GRASS_REGION"] = gs.region_env( - vector=mapFrameDict["map"], - raster=self.instruction[rasterId]["raster"], - env=self.env, - ) + if raster: + raster["raster"] = mapFrameDict["map"] else: - self.env["GRASS_REGION"] = gs.region_env( - vector=mapFrameDict["map"], env=self.env - ) + raster = Raster(NewId(), env=self.env) + raster["raster"] = mapFrameDict["map"] + raster["isRaster"] = True + self.instruction.AddInstruction(raster) + + elif mapFrameDict["mapType"] == "vector": + mapFile = gs.find_file(mapFrameDict["map"], element="vector") + if mapFile["file"] == "": + GMessage("Vector %s not found" % mapFrameDict["map"]) + return False + + vector = self.instruction.FindInstructionByType("vector") + isAdded = False + if vector: + for each in vector["list"]: + if each[0] == mapFrameDict["map"]: + isAdded = True + if not isAdded: + topoInfo = gs.vector_info_topo(map=mapFrameDict["map"]) + if topoInfo: + if bool(topoInfo["areas"]): + topoType = "areas" + elif bool(topoInfo["lines"]): + topoType = "lines" + else: + topoType = "points" + label = "(".join(mapFrameDict["map"].split("@")) + ")" + + if not vector: + vector = Vector(NewId(), env=self.env) + vector["list"] = [] + self.instruction.AddInstruction(vector) + id = NewId() + vector["list"].insert( + 0, [mapFrameDict["map"], topoType, id, 1, label] + ) + vProp = VProperties(id, topoType, env=self.env) + vProp["name"], vProp["label"], vProp["lpos"] = ( + mapFrameDict["map"], + label, + 1, + ) + self.instruction.AddInstruction(vProp) + else: + return False + + self.scale[0], self.center[0], self.rectAdjusted = AutoAdjust( + self, + scaleType=0, + map=mapFrameDict["map"], + env=self.env, + mapType=self.mapType, + rect=self.mapFrameDict["rect"], + ) + if self.rectAdjusted: + mapFrameDict["rect"] = self.rectAdjusted else: - wx.MessageBox( - message=_("No map selected!"), - caption=_("Invalid input"), - style=wx.OK | wx.ICON_ERROR, - ) - return False + mapFrameDict["rect"] = self.mapFrameDict["rect"] - elif mapFrameDict["scaleType"] == 1: - if self.select.GetValue(): - mapFrameDict["drawMap"] = False - mapFrameDict["map"] = None - mapFrameDict["mapType"] = None - mapFrameDict["region"] = self.select.GetValue() - self.scale[1], self.center[1], self.rectAdjusted = AutoAdjust( - self, - scaleType=1, - region=mapFrameDict["region"], - rect=self.mapFrameDict["rect"], - env=self.env, - ) - if self.rectAdjusted: - mapFrameDict["rect"] = self.rectAdjusted - else: - mapFrameDict["rect"] = self.mapFrameDict["rect"] + mapFrameDict["scale"] = self.scale[0] - mapFrameDict["scale"] = self.scale[1] - mapFrameDict["center"] = self.center[1] - # set region + mapFrameDict["center"] = self.center[0] + # set region + if self.mapType == "raster": self.env["GRASS_REGION"] = gs.region_env( - region=mapFrameDict["region"], env=self.env + raster=mapFrameDict["map"], env=self.env ) - else: + if self.mapType == "vector": + raster = self.instruction.FindInstructionByType("raster") + rasterId = raster.id if raster else None + + if rasterId: + self.env["GRASS_REGION"] = gs.region_env( + vector=mapFrameDict["map"], + raster=self.instruction[rasterId]["raster"], + env=self.env, + ) + else: + self.env["GRASS_REGION"] = gs.region_env( + vector=mapFrameDict["map"], env=self.env + ) + + elif mapFrameDict["scaleType"] == 1: + if not self.select.GetValue(): wx.MessageBox( message=_("No region selected!"), caption=_("Invalid input"), @@ -1533,6 +1510,29 @@ def update(self): ) return False + mapFrameDict["drawMap"] = False + mapFrameDict["map"] = None + mapFrameDict["mapType"] = None + mapFrameDict["region"] = self.select.GetValue() + self.scale[1], self.center[1], self.rectAdjusted = AutoAdjust( + self, + scaleType=1, + region=mapFrameDict["region"], + rect=self.mapFrameDict["rect"], + env=self.env, + ) + if self.rectAdjusted: + mapFrameDict["rect"] = self.rectAdjusted + else: + mapFrameDict["rect"] = self.mapFrameDict["rect"] + + mapFrameDict["scale"] = self.scale[1] + mapFrameDict["center"] = self.center[1] + # set region + self.env["GRASS_REGION"] = gs.region_env( + region=mapFrameDict["region"], env=self.env + ) + elif scaleType == 2: mapFrameDict["drawMap"] = False mapFrameDict["map"] = None @@ -2193,7 +2193,7 @@ def __init__(self, parent, id, vectors, tmpSettings): try: self.mapDBInfo = VectorDBInfo(self.vectorName) self.layers = self.mapDBInfo.layers.keys() - except gs.ScriptError: + except ScriptError: self.connection = False self.layers = [] if not self.layers: diff --git a/gui/wxpython/psmap/frame.py b/gui/wxpython/psmap/frame.py index 41536cd921d..2ad6a38a15a 100644 --- a/gui/wxpython/psmap/frame.py +++ b/gui/wxpython/psmap/frame.py @@ -1298,26 +1298,26 @@ def DialogDataChanged(self, id): else: self.deleteObject(id) - if itype == "vectorLegend": - if not self.instruction.FindInstructionByType("vector"): - self.deleteObject(id) - elif self.instruction[id]["vLegend"]: - self.canvas.UpdateLabel(itype=itype, id=id) - drawRectangle = self.canvas.CanvasPaperCoordinates( - rect=self.instruction[id]["rect"], canvasToPaper=False - ) - self.canvas.Draw( - pen=self.pen[itype], - brush=self.brush[itype], - pdc=self.canvas.pdcObj, - drawid=id, - pdctype="rectText", - bb=drawRectangle, - ) - self.canvas.RedrawSelectBox(id) - - else: - self.deleteObject(id) + if itype != "vectorLegend": + continue + if not self.instruction.FindInstructionByType("vector"): + self.deleteObject(id) + elif self.instruction[id]["vLegend"]: + self.canvas.UpdateLabel(itype=itype, id=id) + drawRectangle = self.canvas.CanvasPaperCoordinates( + rect=self.instruction[id]["rect"], canvasToPaper=False + ) + self.canvas.Draw( + pen=self.pen[itype], + brush=self.brush[itype], + pdc=self.canvas.pdcObj, + drawid=id, + pdctype="rectText", + bb=drawRectangle, + ) + self.canvas.RedrawSelectBox(id) + else: + self.deleteObject(id) def OnPageChanged(self, event): """GNotebook page has changed""" diff --git a/gui/wxpython/psmap/instructions.py b/gui/wxpython/psmap/instructions.py index 4528e0a0d93..6281eeb96cb 100644 --- a/gui/wxpython/psmap/instructions.py +++ b/gui/wxpython/psmap/instructions.py @@ -43,6 +43,7 @@ from core.utils import GetCmdString from dbmgr.vinfo import VectorDBInfo from grass.script.task import cmdlist_to_tuple +from grass.exceptions import ScriptError from gui_core.wrap import NewId as wxNewId from psmap.utils import ( # Add any additional required names from psmap.utils here @@ -101,21 +102,22 @@ def __contains__(self, id): def __delitem__(self, id): """Delete instruction""" for each in self.instruction: - if each.id == id: - if each.type == "map": - # must remove raster, vector layers, labels too - vektor = self.FindInstructionByType("vector", list=True) - vProperties = self.FindInstructionByType("vProperties", list=True) - raster = self.FindInstructionByType("raster", list=True) - labels = self.FindInstructionByType("labels", list=True) - for item in vektor + vProperties + raster + labels: - if item in self.instruction: - self.instruction.remove(item) - - self.instruction.remove(each) - if id in self.objectsToDraw: - self.objectsToDraw.remove(id) - return + if each.id != id: + continue + if each.type == "map": + # must remove raster, vector layers, labels too + vektor = self.FindInstructionByType("vector", list=True) + vProperties = self.FindInstructionByType("vProperties", list=True) + raster = self.FindInstructionByType("raster", list=True) + labels = self.FindInstructionByType("labels", list=True) + for item in vektor + vProperties + raster + labels: + if item in self.instruction: + self.instruction.remove(item) + + self.instruction.remove(each) + if id in self.objectsToDraw: + self.objectsToDraw.remove(id) + return def AddInstruction(self, instruction): """Add instruction""" @@ -532,7 +534,7 @@ def SetRegion(self, regionInstruction): try: self.env["GRASS_REGION"] = gs.region_env(env=self.env, **cmd[1]) - except gs.ScriptError as e: + except ScriptError as e: GError(_("Region cannot be set\n%s") % e) return False @@ -1212,21 +1214,21 @@ def GetImageOrigSize(self, imagePath): If eps, size is read from image header. """ fileName = os.path.split(imagePath)[1] + if os.path.splitext(fileName)[1].lower() != ".eps": + # we can use wx.Image + img = wx.Image(fileName, type=wx.BITMAP_TYPE_ANY) + return (img.GetWidth(), img.GetHeight()) + # if eps, read info from header - if os.path.splitext(fileName)[1].lower() == ".eps": - bbInfo = "%%BoundingBox" - file = open(imagePath) - w = h = 0 + bbInfo = "%%BoundingBox" + w = h = 0 + with open(imagePath) as file: while file: line = file.readline() if line.find(bbInfo) == 0: w, h = line.split()[3:5] break - file.close() - return float(w), float(h) - # we can use wx.Image - img = wx.Image(fileName, type=wx.BITMAP_TYPE_ANY) - return img.GetWidth(), img.GetHeight() + return (float(w), float(h)) class NorthArrow(Image): @@ -1909,7 +1911,7 @@ def Read(self, instruction, text): return False try: info = gs.find_file(map, element="cell") - except gs.ScriptError as e: + except ScriptError as e: GError(message=e.value) return False instr["raster"] = info["fullname"] @@ -1937,29 +1939,30 @@ def Read(self, instruction, text, **kwargs): instr = {} for line in text: - if line.startswith(("vpoints", "vlines", "vareas")): - # subtype - if line.startswith("vpoints"): - subType = "points" - elif line.startswith("vlines"): - subType = "lines" - elif line.startswith("vareas"): - subType = "areas" - # name of vector map - vmap = line.split()[1] - try: - info = gs.find_file(vmap, element="vector") - except gs.ScriptError as e: - GError(message=e.value) - return False - vmap = info["fullname"] - # id - id = kwargs["id"] - # lpos - lpos = kwargs["vectorMapNumber"] - # label - label = "(".join(vmap.split("@")) + ")" - break + if not line.startswith(("vpoints", "vlines", "vareas")): + continue + # subtype + if line.startswith("vpoints"): + subType = "points" + elif line.startswith("vlines"): + subType = "lines" + elif line.startswith("vareas"): + subType = "areas" + # name of vector map + vmap = line.split()[1] + try: + info = gs.find_file(vmap, element="vector") + except ScriptError as e: + GError(message=e.value) + return False + vmap = info["fullname"] + # id + id = kwargs["id"] + # lpos + lpos = kwargs["vectorMapNumber"] + # label + label = "(".join(vmap.split("@")) + ")" + break instr = [vmap, subType, id, lpos, label] if not self.instruction["list"]: self.instruction["list"] = [] @@ -2121,7 +2124,7 @@ def Read(self, instruction, text, **kwargs): instr = {} try: info = gs.find_file(name=text[0].split()[1], element="vector") - except gs.ScriptError as e: + except ScriptError as e: GError(message=e.value) return False instr["name"] = info["fullname"] diff --git a/gui/wxpython/psmap/utils.py b/gui/wxpython/psmap/utils.py index 10b10f96297..5da20ff61a6 100644 --- a/gui/wxpython/psmap/utils.py +++ b/gui/wxpython/psmap/utils.py @@ -25,6 +25,7 @@ from core.gcmd import GError, RunCommand import grass.script as gs +from grass.exceptions import ScriptError try: from PIL import Image as PILImage # noqa @@ -195,26 +196,24 @@ def PaperMapCoordinates(mapInstr, x, y, paperToMap=True, env=None): mapWidthEN = region["e"] - region["w"] mapHeightEN = region["n"] - region["s"] - if paperToMap: - diffX = x - mapInstr["rect"].GetX() - diffY = y - mapInstr["rect"].GetY() - diffEW = diffX * mapWidthEN / mapWidthPaper - diffNS = diffY * mapHeightEN / mapHeightPaper - e = region["w"] + diffEW - n = region["n"] - diffNS - - if projInfo()["proj"] == "ll": - return e, n - return int(e), int(n) - - diffEW = x - region["w"] - diffNS = region["n"] - y - diffX = mapWidthPaper * diffEW / mapWidthEN - diffY = mapHeightPaper * diffNS / mapHeightEN - xPaper = mapInstr["rect"].GetX() + diffX - yPaper = mapInstr["rect"].GetY() + diffY - - return xPaper, yPaper + if not paperToMap: + diffEW = x - region["w"] + diffNS = region["n"] - y + diffX = mapWidthPaper * diffEW / mapWidthEN + diffY = mapHeightPaper * diffNS / mapHeightEN + xPaper = mapInstr["rect"].GetX() + diffX + yPaper = mapInstr["rect"].GetY() + diffY + return (xPaper, yPaper) + + diffX = x - mapInstr["rect"].GetX() + diffY = y - mapInstr["rect"].GetY() + diffEW = diffX * mapWidthEN / mapWidthPaper + diffNS = diffY * mapHeightEN / mapHeightPaper + e = region["w"] + diffEW + n = region["n"] - diffNS + if projInfo()["proj"] == "ll": + return (e, n) + return (int(e), int(n)) def AutoAdjust(self, scaleType, rect, env, map=None, mapType=None, region=None): @@ -228,7 +227,7 @@ def AutoAdjust(self, scaleType, rect, env, map=None, mapType=None, region=None): if mapType == "raster": try: res = gs.read_command("g.region", flags="gu", raster=map, env=env) - except gs.ScriptError: + except ScriptError: pass elif mapType == "vector": res = gs.read_command("g.region", flags="gu", vector=map, env=env) @@ -242,7 +241,7 @@ def AutoAdjust(self, scaleType, rect, env, map=None, mapType=None, region=None): else: return None, None, None # fails after switching location - except (gs.ScriptError, gs.CalledModuleError): + except (ScriptError, gs.CalledModuleError): pass if not currRegionDict: @@ -392,7 +391,7 @@ def GetMapBounds(filename, env, portrait=True): .split(","), ) ) - except (gs.ScriptError, IndexError): + except (ScriptError, IndexError): GError(message=_("Unable to run `ps.map -b`")) return None return Rect2D(bb[0], bb[3], bb[2] - bb[0], bb[1] - bb[3]) diff --git a/gui/wxpython/rlisetup/sampling_frame.py b/gui/wxpython/rlisetup/sampling_frame.py index e62737449e6..bc61ef4f109 100644 --- a/gui/wxpython/rlisetup/sampling_frame.py +++ b/gui/wxpython/rlisetup/sampling_frame.py @@ -216,28 +216,26 @@ def createRegion(self): ) ret = dlg.ShowModal() while True: - if ret == wx.ID_OK: - raster = dlg.GetValue() - if checkMapExists(raster): - GMessage( - parent=self, - message=_( - "The raster file %s already exists, please change name" - ) - % raster, - ) - ret = dlg.ShowModal() - else: - dlg.Destroy() - marea = self.writeArea( - self._registeredGraphics.GetItem(0).GetCoords(), raster - ) - self.nextRegion(next=True, area=marea) - break - else: + if ret != wx.ID_OK: self.nextRegion(next=False) break + raster = dlg.GetValue() + if not checkMapExists(raster): + dlg.Destroy() + marea = self.writeArea( + self._registeredGraphics.GetItem(0).GetCoords(), raster + ) + self.nextRegion(next=True, area=marea) + break + + GMessage( + parent=self, + message=_("The raster file %s already exists, please change name") + % raster, + ) + ret = dlg.ShowModal() + def nextRegion(self, next=True, area=None): self.mapWindow.ClearLines() item = self._registeredGraphics.GetItem(0) @@ -336,26 +334,24 @@ def createCircle(self, c): ) ret = dlg.ShowModal() while True: - if ret == wx.ID_OK: - raster = dlg.GetValue() - if checkMapExists(raster): - GMessage( - parent=self, - message=_( - "The raster file %s already exists, please change name" - ) - % raster, - ) - ret = dlg.ShowModal() - else: - dlg.Destroy() - circle = self.writeCircle(c, raster) - self.nextCircle(next=True, circle=circle) - break - else: + if ret != wx.ID_OK: self.nextCircle(next=False) break + raster = dlg.GetValue() + if not checkMapExists(raster): + dlg.Destroy() + circle = self.writeCircle(c, raster) + self.nextCircle(next=True, circle=circle) + break + + GMessage( + parent=self, + message=_("The raster file %s already exists, please change name") + % raster, + ) + ret = dlg.ShowModal() + def nextCircle(self, next=True, circle=None): self.mapWindow.ClearLines() item = self._registeredGraphics.GetItem(0) diff --git a/gui/wxpython/startup/guiutils.py b/gui/wxpython/startup/guiutils.py index bb5cbc88d0d..135714d779f 100644 --- a/gui/wxpython/startup/guiutils.py +++ b/gui/wxpython/startup/guiutils.py @@ -199,11 +199,9 @@ def create_location_interactively(guiparent, grassdb): ) # Returns database and location created by user # and a mapset user may want to switch to - gWizard_output = (gWizard.grassdatabase, gWizard.location, mapset) - else: - # Returns PERMANENT mapset when user mapset not defined - gWizard_output = (gWizard.grassdatabase, gWizard.location, "PERMANENT") - return gWizard_output + return (gWizard.grassdatabase, gWizard.location, mapset) + # Returns PERMANENT mapset when user mapset not defined + return (gWizard.grassdatabase, gWizard.location, "PERMANENT") def rename_mapset_interactively(guiparent, grassdb, location, mapset): diff --git a/gui/wxpython/tplot/frame.py b/gui/wxpython/tplot/frame.py index 21fe822cf4a..b624b16b5ba 100755 --- a/gui/wxpython/tplot/frame.py +++ b/gui/wxpython/tplot/frame.py @@ -632,67 +632,64 @@ def _getSTVDData(self, timeseries): for i in range(len(rows)): row = rows[i] values = out[i] - if str(row["layer"]) == str(values["Layer"]): - lay = "{map}_{layer}".format( - map=row["name"], layer=values["Layer"] - ) - self.timeDataV[name][lay] = {} - self.timeDataV[name][lay]["start_datetime"] = row["start_time"] - self.timeDataV[name][lay]["end_datetime"] = row["start_time"] - self.timeDataV[name][lay]["value"] = values["Attributes"][ - attribute - ] - else: - wherequery = "" - cats = self._getExistingCategories(rows[0]["name"], cats) - totcat = len(cats) - ncat = 1 - for cat in cats: - if ncat == 1 and totcat != 1: - wherequery += "{k}={c} or".format(c=cat, k="{key}") - elif ncat == 1 and totcat == 1: - wherequery += "{k}={c}".format(c=cat, k="{key}") - elif ncat == totcat: - wherequery += " {k}={c}".format(c=cat, k="{key}") - else: - wherequery += " {k}={c} or".format(c=cat, k="{key}") + if str(row["layer"]) != str(values["Layer"]): + continue + lay = "{map}_{layer}".format(map=row["name"], layer=values["Layer"]) + self.timeDataV[name][lay] = {} + self.timeDataV[name][lay]["start_datetime"] = row["start_time"] + self.timeDataV[name][lay]["end_datetime"] = row["start_time"] + self.timeDataV[name][lay]["value"] = values["Attributes"][attribute] - catn = "cat{num}".format(num=cat) - self.plotNameListV.append("{na}+{cat}".format(na=name, cat=catn)) - self.timeDataV[name][catn] = OrderedDict() - ncat += 1 - for row in rows: - lay = int(row["layer"]) - catkey = self._parseVDbConn(row["name"], lay) - if not catkey: - GError( - parent=self, - showTraceback=False, - message=_( - "No connection between vector map {vmap} and layer {la}" - ).format(vmap=row["name"], la=lay), - ) - return - vals = gs.vector_db_select( - map=row["name"], - layer=lay, - where=wherequery.format(key=catkey), - columns=attribute, + continue + + wherequery = "" + cats = self._getExistingCategories(rows[0]["name"], cats) + totcat = len(cats) + ncat = 1 + for cat in cats: + if ncat == 1 and totcat != 1: + wherequery += "{k}={c} or".format(c=cat, k="{key}") + elif ncat == 1 and totcat == 1: + wherequery += "{k}={c}".format(c=cat, k="{key}") + elif ncat == totcat: + wherequery += " {k}={c}".format(c=cat, k="{key}") + else: + wherequery += " {k}={c} or".format(c=cat, k="{key}") + + catn = "cat{num}".format(num=cat) + self.plotNameListV.append("{na}+{cat}".format(na=name, cat=catn)) + self.timeDataV[name][catn] = OrderedDict() + ncat += 1 + for row in rows: + lay = int(row["layer"]) + catkey = self._parseVDbConn(row["name"], lay) + if not catkey: + GError( + parent=self, + showTraceback=False, + message=_( + "No connection between vector map {vmap} and layer {la}" + ).format(vmap=row["name"], la=lay), ) - layn = "lay{num}".format(num=lay) - for cat in cats: - catn = "cat{num}".format(num=cat) - if layn not in self.timeDataV[name][catn].keys(): - self.timeDataV[name][catn][layn] = {} - self.timeDataV[name][catn][layn]["start_datetime"] = row[ - "start_time" - ] - self.timeDataV[name][catn][layn]["end_datetime"] = row[ - "end_time" - ] - self.timeDataV[name][catn][layn]["value"] = vals["values"][ - int(cat) - ][0] + return + vals = gs.vector_db_select( + map=row["name"], + layer=lay, + where=wherequery.format(key=catkey), + columns=attribute, + ) + layn = "lay{num}".format(num=lay) + for cat in cats: + catn = "cat{num}".format(num=cat) + if layn not in self.timeDataV[name][catn].keys(): + self.timeDataV[name][catn][layn] = {} + self.timeDataV[name][catn][layn]["start_datetime"] = row[ + "start_time" + ] + self.timeDataV[name][catn][layn]["end_datetime"] = row["end_time"] + self.timeDataV[name][catn][layn]["value"] = vals["values"][ + int(cat) + ][0] self.unit = unit self.temporalType = mode return diff --git a/gui/wxpython/vdigit/dialogs.py b/gui/wxpython/vdigit/dialogs.py index 369855c94fc..8d617f62d8b 100644 --- a/gui/wxpython/vdigit/dialogs.py +++ b/gui/wxpython/vdigit/dialogs.py @@ -426,29 +426,31 @@ def ApplyChanges(self, fid): for cat in catsCurr[0][layer]: if layer not in catsCurr[1].keys() or cat not in catsCurr[1][layer]: catList.append(cat) - if catList != []: - add = action == "catadd" - - newfid = self.digit.SetLineCats(fid, layer, catList, add) - if len(self.cats.keys()) == 1: - self.fidText.SetLabel("%d" % newfid) - else: - choices = self.fidMulti.GetItems() - choices[choices.index(str(fid))] = str(newfid) - self.fidMulti.SetItems(choices) - self.fidMulti.SetStringSelection(str(newfid)) - - self.cats[newfid] = self.cats[fid] - del self.cats[fid] - - fid = newfid - if self.fid < 0: - wx.MessageBox( - parent=self, - message=_("Unable to update vector map."), - caption=_("Error"), - style=wx.OK | wx.ICON_ERROR, - ) + + if catList == []: + continue + + add = action == "catadd" + newfid = self.digit.SetLineCats(fid, layer, catList, add) + if len(self.cats.keys()) == 1: + self.fidText.SetLabel("%d" % newfid) + else: + choices = self.fidMulti.GetItems() + choices[choices.index(str(fid))] = str(newfid) + self.fidMulti.SetItems(choices) + self.fidMulti.SetStringSelection(str(newfid)) + + self.cats[newfid] = self.cats[fid] + del self.cats[fid] + + fid = newfid + if self.fid < 0: + wx.MessageBox( + parent=self, + message=_("Unable to update vector map."), + caption=_("Error"), + style=wx.OK | wx.ICON_ERROR, + ) self.cats_orig[fid] = copy.deepcopy(cats) diff --git a/gui/wxpython/vdigit/toolbars.py b/gui/wxpython/vdigit/toolbars.py index e3fc9657a51..9e0e66b70a8 100644 --- a/gui/wxpython/vdigit/toolbars.py +++ b/gui/wxpython/vdigit/toolbars.py @@ -995,31 +995,32 @@ def OnSelectMap(self, event): disableAdd=True, ) - if dlg and dlg.GetName(): - # add layer to map layer tree/map display - mapName = dlg.GetName() + "@" + gs.gisenv()["MAPSET"] - self._giface.GetLayerList().AddLayer( - ltype="vector", - name=mapName, - checked=True, - cmd=["d.vect", "map=%s" % mapName], - ) - - vectLayers = self.UpdateListOfLayers(updateTool=True) - selection = vectLayers.index(mapName) - - # create table ? - if dlg.IsChecked("table"): - # TODO: starting of tools such as atm, iclass, - # plots etc. should be handled in some better way - # than starting randomly from mapdisp and lmgr - self.openATM.emit(selection="table") - dlg.Destroy() - else: + if not dlg or not dlg.GetName(): self.combo.SetValue(_("Select vector map")) if dlg: dlg.Destroy() return + + # add layer to map layer tree/map display + mapName = dlg.GetName() + "@" + gs.gisenv()["MAPSET"] + self._giface.GetLayerList().AddLayer( + ltype="vector", + name=mapName, + checked=True, + cmd=["d.vect", "map=%s" % mapName], + ) + + vectLayers = self.UpdateListOfLayers(updateTool=True) + selection = vectLayers.index(mapName) + + # create table ? + if dlg.IsChecked("table"): + # TODO: starting of tools such as atm, iclass, + # plots etc. should be handled in some better way + # than starting randomly from mapdisp and lmgr + self.openATM.emit(selection="table") + dlg.Destroy() + else: selection = event.GetSelection() - 1 # first option is 'New vector map' @@ -1058,10 +1059,9 @@ def StartEditing(self, mapLayer): caption=_("Digitizer error"), style=wx.YES_NO | wx.YES_DEFAULT | wx.ICON_QUESTION | wx.CENTRE, ) - if dlg.ShowModal() == wx.ID_YES: - RunCommand("v.build", map=mapLayer.GetName()) - else: + if dlg.ShowModal() != wx.ID_YES: return + RunCommand("v.build", map=mapLayer.GetName()) # deactivate layer self.Map.ChangeLayerActive(mapLayer, False) diff --git a/gui/wxpython/vdigit/wxdigit.py b/gui/wxpython/vdigit/wxdigit.py index 8f486e27005..712d2961f7f 100644 --- a/gui/wxpython/vdigit/wxdigit.py +++ b/gui/wxpython/vdigit/wxdigit.py @@ -421,11 +421,11 @@ def _getSnapMode(self): :return: snap mode """ threshold = self._display.GetThreshold() - if threshold > 0.0: - if UserSettings.Get(group="vdigit", key="snapToVertex", subkey="enabled"): - return SNAPVERTEX - return SNAP - return NO_SNAP + if threshold <= 0.0: + return NO_SNAP + if UserSettings.Get(group="vdigit", key="snapToVertex", subkey="enabled"): + return SNAPVERTEX + return SNAP def _getNewFeaturesLayer(self): """Returns layer of new feature (from settings)""" @@ -868,13 +868,14 @@ def _getLineAreasCategories(self, ln_id): areas = [left.value, right.value] for i, a in enumerate(areas): - if a > 0: - centroid = Vect_get_area_centroid(self.poMapInfo, a) - if centroid <= 0: - continue - c = self._getCategories(centroid) - if c: - cats[i] = c + if a <= 0: + continue + centroid = Vect_get_area_centroid(self.poMapInfo, a) + if centroid <= 0: + continue + c = self._getCategories(centroid) + if c: + cats[i] = c return cats @@ -1399,95 +1400,94 @@ def CopyCats(self, fromId, toId, copyAttrb=False): if not copyAttrb: # duplicate category cat = catsFrom.cat[i] - else: - # duplicate attributes - cat = self.cats[catsFrom.field[i]] + 1 - self.cats[catsFrom.field[i]] = cat - poFi = Vect_get_field(self.poMapInfo, catsFrom.field[i]) - if not poFi: - self._error.DbLink(i) - return -1 + continue - fi = poFi.contents - driver = db_start_driver(fi.driver) - if not driver: - self._error.Driver(fi.driver) - return -1 + # duplicate attributes + cat = self.cats[catsFrom.field[i]] + 1 + self.cats[catsFrom.field[i]] = cat + poFi = Vect_get_field(self.poMapInfo, catsFrom.field[i]) + if not poFi: + self._error.DbLink(i) + return -1 - handle = dbHandle() - db_init_handle(byref(handle)) - db_set_handle(byref(handle), fi.database, None) - if db_open_database(driver, byref(handle)) != DB_OK: - db_shutdown_driver(driver) - self._error.Database(fi.driver, fi.database) - return -1 + fi = poFi.contents + driver = db_start_driver(fi.driver) + if not driver: + self._error.Driver(fi.driver) + return -1 - stmt = dbString() - db_init_string(byref(stmt)) - db_set_string( - byref(stmt), - "SELECT * FROM %s WHERE %s=%d" - % (fi.table, fi.key, catsFrom.cat[i]), + handle = dbHandle() + db_init_handle(byref(handle)) + db_set_handle(byref(handle), fi.database, None) + if db_open_database(driver, byref(handle)) != DB_OK: + db_shutdown_driver(driver) + self._error.Database(fi.driver, fi.database) + return -1 + + stmt = dbString() + db_init_string(byref(stmt)) + db_set_string( + byref(stmt), + "SELECT * FROM %s WHERE %s=%d" + % (fi.table, fi.key, catsFrom.cat[i]), + ) + + cursor = dbCursor() + if ( + db_open_select_cursor( + driver, byref(stmt), byref(cursor), DB_SEQUENTIAL ) + != DB_OK + ): + db_close_database_shutdown_driver(driver) + return -1 - cursor = dbCursor() - if ( - db_open_select_cursor( - driver, byref(stmt), byref(cursor), DB_SEQUENTIAL - ) - != DB_OK - ): + table = db_get_cursor_table(byref(cursor)) + ncols = db_get_table_number_of_columns(table) + + sql = "INSERT INTO %s VALUES (" % fi.table + # fetch the data + more = c_int() + while True: + if db_fetch(byref(cursor), DB_NEXT, byref(more)) != DB_OK: db_close_database_shutdown_driver(driver) return -1 - - table = db_get_cursor_table(byref(cursor)) - ncols = db_get_table_number_of_columns(table) - - sql = "INSERT INTO %s VALUES (" % fi.table - # fetch the data - more = c_int() - while True: - if db_fetch(byref(cursor), DB_NEXT, byref(more)) != DB_OK: - db_close_database_shutdown_driver(driver) - return -1 - if not more.value: - break - - value_string = dbString() - for col in range(ncols): - if col > 0: - sql += "," - - column = db_get_table_column(table, col) - if db_get_column_name(column) == fi.key: - sql += "%d" % cat - continue - - value = db_get_column_value(column) - db_convert_column_value_to_string( - column, byref(value_string) + if not more.value: + break + + value_string = dbString() + for col in range(ncols): + if col > 0: + sql += "," + + column = db_get_table_column(table, col) + if db_get_column_name(column) == fi.key: + sql += "%d" % cat + continue + + value = db_get_column_value(column) + db_convert_column_value_to_string( + column, byref(value_string) + ) + if db_test_value_isnull(value): + sql += "NULL" + else: + ctype = db_sqltype_to_Ctype( + db_get_column_sqltype(column) ) - if db_test_value_isnull(value): - sql += "NULL" + if ctype != DB_C_TYPE_STRING: + sql += db_get_string(byref(value_string)) else: - ctype = db_sqltype_to_Ctype( - db_get_column_sqltype(column) - ) - if ctype != DB_C_TYPE_STRING: - sql += db_get_string(byref(value_string)) - else: - sql += "'%s'" % db_get_string( - byref(value_string) - ) - - sql += ")" - db_set_string(byref(stmt), sql) - if db_execute_immediate(driver, byref(stmt)) != DB_OK: - db_close_database_shutdown_driver(driver) - return -1 + sql += "'%s'" % db_get_string(byref(value_string)) + sql += ")" + db_set_string(byref(stmt), sql) + if db_execute_immediate(driver, byref(stmt)) != DB_OK: db_close_database_shutdown_driver(driver) - G_free(poFi) + return -1 + + db_close_database_shutdown_driver(driver) + G_free(poFi) if Vect_cat_set(poCatsTo, catsFrom.field[i], cat) < 1: continue diff --git a/gui/wxpython/vdigit/wxdisplay.py b/gui/wxpython/vdigit/wxdisplay.py index f7381fe763f..156397e6266 100644 --- a/gui/wxpython/vdigit/wxdisplay.py +++ b/gui/wxpython/vdigit/wxdisplay.py @@ -1225,14 +1225,15 @@ def GetDuplicates(self): Vect_read_line(self.poMapInfo, BPoints, None, line2) - if Vect_line_check_duplicate(APoints, BPoints, WITHOUT_Z): - if i not in ids: - ids[i] = [] - ids[i].append((line1, self._getCatString(line1))) - self.selected["idsDupl"].append(line1) - - ids[i].append((line2, self._getCatString(line2))) - self.selected["idsDupl"].append(line2) + if not Vect_line_check_duplicate(APoints, BPoints, WITHOUT_Z): + continue + if i not in ids: + ids[i] = [] + ids[i].append((line1, self._getCatString(line1))) + self.selected["idsDupl"].append(line1) + + ids[i].append((line2, self._getCatString(line2))) + self.selected["idsDupl"].append(line2) Vect_destroy_line_struct(APoints) Vect_destroy_line_struct(BPoints) diff --git a/gui/wxpython/vnet/dialogs.py b/gui/wxpython/vnet/dialogs.py index ca928a6b164..19d8e6c8a93 100644 --- a/gui/wxpython/vnet/dialogs.py +++ b/gui/wxpython/vnet/dialogs.py @@ -1189,15 +1189,16 @@ def SetData(self, key, data): self.CheckItem(idx, True) elif not v and self.IsItemChecked(idx): self.CheckItem(idx, False) - else: - found = 0 - for col in self.colsData: - if k == col[0]: - found = 1 - break - - if found: - self.EditCellKey(key, k, v) + continue + + found = 0 + for col in self.colsData: + if k == col[0]: + found = 1 + break + + if found: + self.EditCellKey(key, k, v) def OnItemSelected(self, event): """Item selected""" diff --git a/gui/wxpython/vnet/vnet_core.py b/gui/wxpython/vnet/vnet_core.py index cb1df07441d..eaf4874c86f 100644 --- a/gui/wxpython/vnet/vnet_core.py +++ b/gui/wxpython/vnet/vnet_core.py @@ -1092,42 +1092,40 @@ def ComputeNodes(self, activate): inpName, mapSet = inpFullName.split("@") computeNodes = True - if "inputMap" not in self.snapData: - pass - elif inpFullName != self.snapData["inputMap"].GetVectMapName(): - self.snapData["inputMap"] = VectMap(None, inpFullName) - elif self.snapData["inputMap"].VectMapState() == 1: - computeNodes = False + if "inputMap" in self.snapData: + if inpFullName != self.snapData["inputMap"].GetVectMapName(): + self.snapData["inputMap"] = VectMap(None, inpFullName) + elif self.snapData["inputMap"].VectMapState() == 1: + computeNodes = False + + if not computeNodes: + # map is already created and up to date for input data + self.snapPts.AddRenderLayer() + self.giface.updateMap.emit(render=True, renderVector=True) + self.snapping.emit(evt="computing_points_done") + return 1 # new map needed - if computeNodes: - if "cmdThread" not in self.snapData: - self.snapData["cmdThread"] = CmdThread(self) - else: - self.snapData["cmdThread"].abort() - - cmd = [ - "v.to.points", - "input=" + params["input"], - "output=" + self.snapPts.GetVectMapName(), - "use=node", - "--overwrite", - ] - # process GRASS command with argument - self.snapData["inputMap"] = VectMap(None, inpFullName) - self.snapData["inputMap"].SaveVectMapState() - - self.Bind(EVT_CMD_DONE, self._onNodesDone) - self.snapData["cmdThread"].RunCmd(cmd) + if "cmdThread" not in self.snapData: + self.snapData["cmdThread"] = CmdThread(self) + else: + self.snapData["cmdThread"].abort() + cmd = [ + "v.to.points", + "input=" + params["input"], + "output=" + self.snapPts.GetVectMapName(), + "use=node", + "--overwrite", + ] + # process GRASS command with argument + self.snapData["inputMap"] = VectMap(None, inpFullName) + self.snapData["inputMap"].SaveVectMapState() - self.snapping.emit(evt="computing_points") + self.Bind(EVT_CMD_DONE, self._onNodesDone) + self.snapData["cmdThread"].RunCmd(cmd) + self.snapping.emit(evt="computing_points") - return 0 - # map is already created and up to date for input data - self.snapPts.AddRenderLayer() - self.giface.updateMap.emit(render=True, renderVector=True) - self.snapping.emit(evt="computing_points_done") - return 1 + return 0 def _onNodesDone(self, event): """Update map window, when map with nodes to snap is created""" diff --git a/gui/wxpython/vnet/vnet_data.py b/gui/wxpython/vnet/vnet_data.py index e8e05839e70..137840879c8 100644 --- a/gui/wxpython/vnet/vnet_data.py +++ b/gui/wxpython/vnet/vnet_data.py @@ -928,14 +928,12 @@ def DeleteTmpMap(self, vectMap): :return: True if was removed :return: False if does not contain the map """ - if vectMap: - vectMap.DeleteRenderLayer() - RunCommand( - "g.remove", flags="f", type="vector", name=vectMap.GetVectMapName() - ) - self.RemoveFromTmpMaps(vectMap) - return True - return False + if not vectMap: + return False + vectMap.DeleteRenderLayer() + RunCommand("g.remove", flags="f", type="vector", name=vectMap.GetVectMapName()) + self.RemoveFromTmpMaps(vectMap) + return True def DeleteAllTmpMaps(self): """Delete all temporary maps in the class""" diff --git a/gui/wxpython/vnet/vnet_utils.py b/gui/wxpython/vnet/vnet_utils.py index 7157ac8a20e..2f32fd2b94d 100644 --- a/gui/wxpython/vnet/vnet_utils.py +++ b/gui/wxpython/vnet/vnet_utils.py @@ -73,15 +73,14 @@ def SnapToNode(e, n, tresh, vectMap): vectlib.WITHOUT_Z, ) - if nodeNum > 0: - e = c_double(0) - n = c_double(0) - vectlib.Vect_get_node_coor(openedMap, nodeNum, byref(e), byref(n), None) # z - e = e.value - n = n.value - else: + if nodeNum <= 0: vectlib.Vect_close(openedMap) return False + e = c_double(0) + n = c_double(0) + vectlib.Vect_get_node_coor(openedMap, nodeNum, byref(e), byref(n), None) + e = e.value + n = n.value return e, n @@ -110,15 +109,14 @@ def GetNearestNodeCat(e, n, layer, tresh, vectMap): vectlib.WITHOUT_Z, ) - if nodeNum > 0: - e = c_double(0) - n = c_double(0) - vectlib.Vect_get_node_coor(openedMap, nodeNum, byref(e), byref(n), None) # z - e = e.value - n = n.value - else: + if nodeNum <= 0: vectlib.Vect_close(openedMap) return -1 + e = c_double(0) + n = c_double(0) + vectlib.Vect_get_node_coor(openedMap, nodeNum, byref(e), byref(n), None) + e = e.value + n = n.value box = vectlib.bound_box() List = POINTER(vectlib.boxlist) diff --git a/gui/wxpython/vnet/widgets.py b/gui/wxpython/vnet/widgets.py index d5a0964a5ac..d05519be772 100644 --- a/gui/wxpython/vnet/widgets.py +++ b/gui/wxpython/vnet/widgets.py @@ -507,22 +507,19 @@ def ShowColumn(self, colName, pos): """ if pos < 0 or pos >= self.GetColumnCount(): return False - if colName in self.hiddenCols: - col = self.hiddenCols[colName] - - for item in enumerate(self.itemDataMap): - item[1].insert(pos, col["itemDataMap"][item[0]]) - for item in enumerate(self.selIdxs): - item[1].insert(pos, col["selIdxs"][item[0]]) - - self.colsData.insert(pos, col["colsData"]) - - self.InsertColumnItem(pos, col["wxCol"]) - self.ResizeColumns() - del self.hiddenCols[colName] - return True - - return False + if colName not in self.hiddenCols: + return False + col = self.hiddenCols[colName] + + for item in enumerate(self.itemDataMap): + item[1].insert(pos, col["itemDataMap"][item[0]]) + for item in enumerate(self.selIdxs): + item[1].insert(pos, col["selIdxs"][item[0]]) + self.colsData.insert(pos, col["colsData"]) + self.InsertColumnItem(pos, col["wxCol"]) + self.ResizeColumns() + del self.hiddenCols[colName] + return True def IsShown(self, colName) -> bool: """Is column shown diff --git a/gui/wxpython/wxplot/base.py b/gui/wxpython/wxplot/base.py index 057894c0250..21d4a442a77 100755 --- a/gui/wxpython/wxplot/base.py +++ b/gui/wxpython/wxplot/base.py @@ -247,11 +247,12 @@ def InitRasterOpts(self, rasterList, plottype): rdict[r]["pcolor"] = self.colorDict[self.colorList[idx]] else: rdict[r]["pcolor"] = self.colorDict[self.colorList[idx]] - else: - r = randint(0, 255) - b = randint(0, 255) - g = randint(0, 255) - rdict[r]["pcolor"] = (r, g, b, 255) + continue + + r = randint(0, 255) + b = randint(0, 255) + g = randint(0, 255) + rdict[r]["pcolor"] = (r, g, b, 255) return rdict @@ -322,11 +323,12 @@ def InitRasterPairs(self, rasterList, plottype): if idx <= len(self.colorList): rdict[rpair]["pcolor"] = self.colorDict[self.colorList[idx]] - else: - r = randint(0, 255) - b = randint(0, 255) - g = randint(0, 255) - rdict[rpair]["pcolor"] = (r, g, b, 255) + continue + + r = randint(0, 255) + b = randint(0, 255) + g = randint(0, 255) + rdict[rpair]["pcolor"] = (r, g, b, 255) return rdict diff --git a/gui/wxpython/wxplot/profile.py b/gui/wxpython/wxplot/profile.py index 5b63f3cabab..37185c7409d 100644 --- a/gui/wxpython/wxplot/profile.py +++ b/gui/wxpython/wxplot/profile.py @@ -262,16 +262,18 @@ def SetupProfile(self): for r in self.raster.keys(): self.raster[r]["datalist"] = [] datalist = self.CreateDatalist(r, self.coordstr) - if len(datalist) > 0: - self.raster[r]["datalist"] = datalist + if len(datalist) <= 0: + continue + + self.raster[r]["datalist"] = datalist - # update ylabel to match units if they exist - if self.raster[r]["units"] != "": - self.ylabel += "%s (%d)," % (self.raster[r]["units"], i) - i += 1 + # update ylabel to match units if they exist + if self.raster[r]["units"] != "": + self.ylabel += "%s (%d)," % (self.raster[r]["units"], i) + i += 1 - # update title - self.ptitle += " %s ," % r.split("@")[0] + # update title + self.ptitle += " %s ," % r.split("@")[0] self.ptitle = self.ptitle.rstrip(",") diff --git a/imagery/i.atcorr/create_iwave.py b/imagery/i.atcorr/create_iwave.py index 27c1e8e1e42..6aab9ccd065 100644 --- a/imagery/i.atcorr/create_iwave.py +++ b/imagery/i.atcorr/create_iwave.py @@ -255,72 +255,79 @@ def get_max_wavelength(c, rthresh, fi): print(" %s (%inm - %inm)" % (bands[b], min_wavelength, max_wavelength)) # writing... - outfile = open(os.path.join(folder, sensor + "_cpp_template.txt"), "w") - outfile.write("/* Following filter function created using create_iwave.py */\n\n") - - # single band case - if len(bands) == 1: - outfile.write("void IWave::%s()\n{\n\n" % (sensor.lower())) - outfile.write(" /* %s of %s */\n" % (bands[0], sensor)) - outfile.write(" static const float sr[%i] = {" % (len(filter_f))) - filter_text = pretty_print(filter_f) - outfile.write(filter_text) - - # calculate wl slot for band start - # slots range from 250 to 4000 at 2.5 increments (total 1500) - s_start = int((limits[0] * 1000 - 250) / 2.5) - - outfile.write("\n") - outfile.write(" ffu.wlinf = %.4ff;\n" % (limits[0])) - outfile.write(" ffu.wlsup = %.4ff;\n" % (limits[1])) - outfile.write(" int i = 0;\n") - outfile.write(" for(i = 0; i < %i; i++)\tffu.s[i] = 0;\n" % (s_start)) - outfile.write( - " for(i = 0; i < %i; i++)\tffu.s[%i+i] = sr[i];\n" - % (len(filter_f), s_start) - ) + outpath = os.path.join(folder, sensor + "_cpp_template.txt") + with open(outpath, "w") as outfile: outfile.write( - " for(i = %i; i < 1501; i++)\tffu.s[i] = 0;\n" - % (s_start + len(filter_f)) + "/* Following filter function created using create_iwave.py */\n\n" ) - outfile.write("}\n") - else: # more than 1 band - outfile.write("void IWave::%s(int iwa)\n{\n\n" % (sensor.lower())) - # writing bands - for b in range(len(bands)): - outfile.write(" /* %s of %s */\n" % (bands[b], sensor)) + # single band case + if len(bands) == 1: + outfile.write("void IWave::%s()\n{\n\n" % (sensor.lower())) + outfile.write(" /* %s of %s */\n" % (bands[0], sensor)) + outfile.write(" static const float sr[%i] = {" % (len(filter_f))) + filter_text = pretty_print(filter_f) + outfile.write(filter_text) + + # calculate wl slot for band start + # slots range from 250 to 4000 at 2.5 increments (total 1500) + s_start = int((limits[0] * 1000 - 250) / 2.5) + + outfile.write("\n") + outfile.write(" ffu.wlinf = %.4ff;\n" % (limits[0])) + outfile.write(" ffu.wlsup = %.4ff;\n" % (limits[1])) + outfile.write(" int i = 0;\n") + outfile.write(" for(i = 0; i < %i; i++)\tffu.s[i] = 0;\n" % (s_start)) outfile.write( - " static const float sr%i[%i] = {\n" % (b + 1, len(filter_f[b])) + " for(i = 0; i < %i; i++)\tffu.s[%i+i] = sr[i];\n" + % (len(filter_f), s_start) ) - filter_text = pretty_print(filter_f[b]) - outfile.write(filter_text + "\n };\n\t\n") - - # writing band limits - inf = ", ".join(["%.4f" % i[0] for i in limits]) - sup = ", ".join(["%.4f" % i[1] for i in limits]) + outfile.write( + " for(i = %i; i < 1501; i++)\tffu.s[i] = 0;\n" + % (s_start + len(filter_f)) + ) + outfile.write("}\n") + + else: # more than 1 band + outfile.write("void IWave::%s(int iwa)\n{\n\n" % (sensor.lower())) + # writing bands + for b in range(len(bands)): + outfile.write(" /* %s of %s */\n" % (bands[b], sensor)) + outfile.write( + " static const float sr%i[%i] = {\n" % (b + 1, len(filter_f[b])) + ) + filter_text = pretty_print(filter_f[b]) + outfile.write(filter_text + "\n };\n\t\n") + + # writing band limits + inf = ", ".join(["%.4f" % i[0] for i in limits]) + sup = ", ".join(["%.4f" % i[1] for i in limits]) - outfile.write(" static const float wli[%i] = {%s};\n" % (len(bands), inf)) - outfile.write(" static const float wls[%i] = {%s};\n" % (len(bands), sup)) + outfile.write( + " static const float wli[%i] = {%s};\n" % (len(bands), inf) + ) + outfile.write( + " static const float wls[%i] = {%s};\n" % (len(bands), sup) + ) - outfile.write("\n") - outfile.write(" ffu.wlinf = (float)wli[iwa-1];\n") - outfile.write(" ffu.wlsup = (float)wls[iwa-1];\n\n") + outfile.write("\n") + outfile.write(" ffu.wlinf = (float)wli[iwa-1];\n") + outfile.write(" ffu.wlsup = (float)wls[iwa-1];\n\n") - outfile.write(" int i;\n") - outfile.write(" for(i = 0; i < 1501; i++) ffu.s[i] = 0;\n\n") + outfile.write(" int i;\n") + outfile.write(" for(i = 0; i < 1501; i++) ffu.s[i] = 0;\n\n") - outfile.write(" switch(iwa)\n {\n") + outfile.write(" switch(iwa)\n {\n") - # now start of case part... - for b in range(len(bands)): - s_start = int((limits[b][0] * 1000 - 250) / 2.5) - outfile.write( - " case %i: for(i = 0; i < %i; i++) ffu.s[%i+i] = sr%i[i];\n" - % ((b + 1), len(filter_f[b]), s_start, (b + 1)) - ) - outfile.write(" break;\n") - outfile.write(" }\n}\n") + # now start of case part... + for b in range(len(bands)): + s_start = int((limits[b][0] * 1000 - 250) / 2.5) + outfile.write( + " case %i: for(i = 0; i < %i; i++) ffu.s[%i+i] = sr%i[i];\n" + % ((b + 1), len(filter_f[b]), s_start, (b + 1)) + ) + outfile.write(" break;\n") + outfile.write(" }\n}\n") def main(): diff --git a/lib/nviz/exag.c b/lib/nviz/exag.c index b13897bd963..088ac97e9e2 100644 --- a/lib/nviz/exag.c +++ b/lib/nviz/exag.c @@ -29,7 +29,8 @@ int Nviz_get_exag_height(double *val, double *min, double *max) { float longdim, exag, texag, hmin, hmax, fmin, fmax; - int nsurfs, i, *surf_list; + int nsurfs, i; + int *surf_list = NULL; surf_list = GS_get_surf_list(&nsurfs); if (nsurfs) { @@ -63,6 +64,7 @@ int Nviz_get_exag_height(double *val, double *min, double *max) G_debug(1, "Nviz_get_exag_height(): value = %f min = %f max = %f", *val, min ? *min : 0.0, max ? *max : 0.0); + G_free(surf_list); return 1; } @@ -77,7 +79,8 @@ int Nviz_get_exag_height(double *val, double *min, double *max) double Nviz_get_exag(void) { float exag, texag; - int nsurfs, i, *surf_list; + int nsurfs, i; + int *surf_list = NULL; surf_list = GS_get_surf_list(&nsurfs); @@ -91,9 +94,7 @@ double Nviz_get_exag(void) if (exag == 0.0) exag = 1.0; - - if (nsurfs > 0) - G_free(surf_list); + G_free(surf_list); G_debug(1, "Nviz_get_exag(): value = %f", exag); return exag; diff --git a/lib/vector/Vlib/open_ogr.c b/lib/vector/Vlib/open_ogr.c index 894a2cfc11c..a085bcca31c 100644 --- a/lib/vector/Vlib/open_ogr.c +++ b/lib/vector/Vlib/open_ogr.c @@ -150,8 +150,10 @@ int V2_open_old_ogr(struct Map_info *Map) Map->mapset); if (Vect_open_fidx(Map, &(Map->fInfo.ogr.offset)) != 0) { + const char *map_name = Vect_get_full_name(Map); G_warning(_("Unable to open feature index file for vector map <%s>"), - Vect_get_full_name(Map)); + map_name); + G_free((void *)map_name); G_zero(&(Map->fInfo.ogr.offset), sizeof(struct Format_info_offset)); } @@ -268,14 +270,17 @@ int Vect_open_fidx(struct Map_info *Map, struct Format_info_offset *offset) dig_file_init(&fp); fp.file = G_fopen_old(elem, GV_FIDX_ELEMENT, Map->mapset); if (fp.file == NULL) { - G_debug(1, "unable to open fidx file for vector map <%s>", - Vect_get_full_name(Map)); + const char *map_name = Vect_get_full_name(Map); + G_debug(1, "unable to open fidx file for vector map <%s>", map_name); + G_free((void *)map_name); return -1; } /* Header */ - if (0 >= dig__fread_port_C(buf, 5, &fp)) + if (0 >= dig__fread_port_C(buf, 5, &fp)) { + fclose(fp.file); return -1; + } Version_Major = buf[0]; Version_Minor = buf[1]; Back_Major = buf[2]; @@ -302,23 +307,29 @@ int Vect_open_fidx(struct Map_info *Map, struct Format_info_offset *offset) /* Body */ /* bytes 6 - 9 : header size */ - if (0 >= dig__fread_port_L(&length, 1, &fp)) + if (0 >= dig__fread_port_L(&length, 1, &fp)) { + fclose(fp.file); return -1; + } G_debug(4, " header size %ld", length); G_fseek(fp.file, length, SEEK_SET); /* number of records */ - if (0 >= dig__fread_port_I(&(offset->array_num), 1, &fp)) + if (0 >= dig__fread_port_I(&(offset->array_num), 1, &fp)) { + fclose(fp.file); return -1; + } /* alloc space */ offset->array = (int *)G_malloc(offset->array_num * sizeof(int)); offset->array_alloc = offset->array_num; /* offsets */ - if (0 >= dig__fread_port_I(offset->array, offset->array_num, &fp)) + if (0 >= dig__fread_port_I(offset->array, offset->array_num, &fp)) { + fclose(fp.file); return -1; + } fclose(fp.file); diff --git a/pyproject.toml b/pyproject.toml index b3bdd21a8d5..b1758030f21 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -268,12 +268,6 @@ ignore = [ # Other ignores: "**.py" = ["PYI066"] "*/testsuite/**.py" = ["PT009", "PT027"] -"gui/wxpython/core/globalvar.py" = ["PTH208"] -"gui/wxpython/core/render.py" = ["SIM115"] -"gui/wxpython/core/settings.py" = ["PTH208", "SIM115"] -"gui/wxpython/core/utils.py" = ["SIM115"] -"gui/wxpython/core/workspace.py" = ["SIM115"] -"gui/wxpython/datacatalog/catalog.py" = ["PTH208"] "gui/wxpython/dbmgr/base.py" = ["SIM115"] "gui/wxpython/gcp/manager.py" = ["PTH208"] "gui/wxpython/gmodeler/panels.py" = ["SIM115"] @@ -299,7 +293,6 @@ ignore = [ "gui/wxpython/vnet/vnet_data.py" = ["SIM115"] "gui/wxpython/web_services/dialogs.py" = ["SIM115"] "gui/wxpython/wxplot/profile.py" = ["A005", "SIM115"] -"imagery/i.atcorr/create_iwave.py" = ["SIM115"] "lib/imagery/testsuite/test_imagery_signature_management.py" = ["SIM115"] "lib/imagery/testsuite/test_imagery_sigsetfile.py" = ["FURB152"] "lib/init/grass.py" = ["SIM115"] @@ -380,9 +373,6 @@ ignore = [ "temporal/t.register/testsuite/test_t_register_raster.py" = ["FLY002"] "temporal/t.register/testsuite/test_t_register_raster_file.py" = ["FLY002"] "temporal/t.remove/t.remove.py" = ["SIM115"] -"utils/generate_release_notes.py" = ["PGH004"] -"utils/gitlog2changelog.py" = ["SIM115"] -"utils/thumbnails.py" = ["PTH208"] "vector/v.fill.holes/examples.ipynb" = ["PTH201"] [tool.ruff.lint.flake8-import-conventions.extend-aliases] diff --git a/python/grass/grassdb/checks.py b/python/grass/grassdb/checks.py index 052addac248..a458ad71432 100644 --- a/python/grass/grassdb/checks.py +++ b/python/grass/grassdb/checks.py @@ -20,7 +20,6 @@ import grass.grassdb.config as cfg import grass.script as gs from grass.script import gisenv -from itertools import starmap def mapset_exists(path: str | os.PathLike[str], location=None, mapset=None) -> bool: @@ -525,7 +524,10 @@ def get_reasons_locations_not_removable(locations): Returns messages as list if there were any failed checks, otherwise empty list. """ - return list(starmap(get_reasons_location_not_removable, locations)) + messages = [] + for grassdb, location in locations: + messages += get_reasons_location_not_removable(grassdb, location) + return messages def get_reasons_location_not_removable(grassdb, location): @@ -556,7 +558,9 @@ def get_reasons_location_not_removable(grassdb, location): ) # Append to the list of tuples - mapsets = [(grassdb, location, g_mapset) for g_mapset in g_mapsets] + mapsets = [] + for g_mapset in g_mapsets: + mapsets.append((grassdb, location, g_mapset)) # Concentenate both checks messages += get_reasons_mapsets_not_removable(mapsets, check_permanent=False) @@ -585,7 +589,9 @@ def get_reasons_grassdb_not_removable(grassdb): g_locations = get_list_of_locations(grassdb) # Append to the list of tuples - locations = [(grassdb, g_location) for g_location in g_locations] + locations = [] + for g_location in g_locations: + locations.append((grassdb, g_location)) return get_reasons_locations_not_removable(locations) @@ -596,11 +602,12 @@ def get_list_of_locations(dbase): :return: list of locations (sorted) """ - locations = [ - os.path.basename(location) - for location in glob.glob(os.path.join(dbase, "*")) - if os.path.join(location, "PERMANENT") in glob.glob(os.path.join(location, "*")) - ] + locations = [] + for location in glob.glob(os.path.join(dbase, "*")): + if os.path.join(location, "PERMANENT") in glob.glob( + os.path.join(location, "*") + ): + locations.append(os.path.basename(location)) locations.sort(key=lambda x: x.lower()) diff --git a/raster/r.geomorphon/r.geomorphon.html b/raster/r.geomorphon/r.geomorphon.html index 36b85ce51fd..20338fa0315 100644 --- a/raster/r.geomorphon/r.geomorphon.html +++ b/raster/r.geomorphon/r.geomorphon.html @@ -33,9 +33,9 @@

What is geomorphon:

different from the horizon. Two lines-of-sight are necessary due to zenith LOS only, does not detect positive forms correctly. -

There are 3**8 = 6561 possible ternary patterns (8-tuples). However by -eliminating all patterns that are results of either rotation or reflection -of other patterns we get a set of 498 patterns remain referred as geomorphons. +

There are 3**8 = 6561 possible ternary patterns (8-tuples). By removing +all patterns that are the result of either rotation or reflection of other +patterns, a set of 498 patterns remains, referred to as geomorphons. This is a comprehensive and exhaustive set of idealized landforms that are independent of the size, relief, and orientation of the actual landform. diff --git a/raster/r.li/r.li.html b/raster/r.li/r.li.html index 37e40d6cfc7..ca38ef92ce0 100644 --- a/raster/r.li/r.li.html +++ b/raster/r.li/r.li.html @@ -1,4 +1,6 @@ - + + +

DESCRIPTION

The r.li suite is a toolset for multiscale analysis of diff --git a/raster/r.resamp.stats/main.c b/raster/r.resamp.stats/main.c index efa2c67cbf3..f329eea856f 100644 --- a/raster/r.resamp.stats/main.c +++ b/raster/r.resamp.stats/main.c @@ -149,6 +149,9 @@ static void resamp_unweighted(void) Rast_put_d_row(outfile, outbuf); } + G_free(row_map); + G_free(col_map); + G_free(values); } static void resamp_weighted(void) @@ -233,6 +236,9 @@ static void resamp_weighted(void) Rast_put_d_row(outfile, outbuf); } + G_free(row_map); + G_free(col_map); + G_free(values); } int main(int argc, char *argv[]) diff --git a/raster/r.sim/r.sim.sediment/main.c b/raster/r.sim/r.sim.sediment/main.c index f49fa8fb880..5f84843acb8 100644 --- a/raster/r.sim/r.sim.sediment/main.c +++ b/raster/r.sim/r.sim.sediment/main.c @@ -388,15 +388,15 @@ int main(int argc, char *argv[]) threads, abs(threads)); threads = abs(threads); } + if (threads > 1 && Rast_mask_is_present()) { + G_warning(_("Parallel processing disabled due to active mask.")); + threads = 1; + } #if defined(_OPENMP) omp_set_num_threads(threads); #else threads = 1; #endif - if (threads > 1 && Rast_mask_is_present()) { - G_warning(_("Parallel processing disabled due to active mask.")); - threads = 1; - } G_message(_("Number of threads: %d"), threads); /* sscanf(parm.nwalk->answer, "%d", &wp.maxwa); */ diff --git a/raster/r.sim/r.sim.water/main.c b/raster/r.sim/r.sim.water/main.c index d4a545172a5..82a5152ff7b 100644 --- a/raster/r.sim/r.sim.water/main.c +++ b/raster/r.sim/r.sim.water/main.c @@ -416,15 +416,15 @@ int main(int argc, char *argv[]) threads, abs(threads)); threads = abs(threads); } + if (threads > 1 && Rast_mask_is_present()) { + G_warning(_("Parallel processing disabled due to active mask.")); + threads = 1; + } #if defined(_OPENMP) omp_set_num_threads(threads); #else threads = 1; #endif - if (threads > 1 && Rast_mask_is_present()) { - G_warning(_("Parallel processing disabled due to active mask.")); - threads = 1; - } G_message(_("Number of threads: %d"), threads); /* if no rain map input, then: */ diff --git a/utils/generate_release_notes.py b/utils/generate_release_notes.py index 4ad19fdb060..8c6c79043fa 100755 --- a/utils/generate_release_notes.py +++ b/utils/generate_release_notes.py @@ -125,7 +125,7 @@ def print_by_category(changes, categories, file=None): def binder_badge(tag): """Get mybinder Binder badge from a given tag, hash, or branch""" binder_image_url = "https://mybinder.org/badge_logo.svg" - binder_url = f"https://mybinder.org/v2/gh/OSGeo/grass/{tag}?urlpath=lab%2Ftree%2Fdoc%2Fexamples%2Fnotebooks%2Fjupyter_example.ipynb" # noqa + binder_url = f"https://mybinder.org/v2/gh/OSGeo/grass/{tag}?urlpath=lab%2Ftree%2Fdoc%2Fexamples%2Fnotebooks%2Fjupyter_example.ipynb" return f"[![Binder]({binder_image_url})]({binder_url})" diff --git a/utils/gitlog2changelog.py b/utils/gitlog2changelog.py index f878041ca83..9b60f7c54fb 100755 --- a/utils/gitlog2changelog.py +++ b/utils/gitlog2changelog.py @@ -30,9 +30,6 @@ process = subprocess.Popen(git_command, stdout=subprocess.PIPE, encoding="utf8") fin = process.stdout -# Create a ChangeLog file in the current directory. -fout = open("ChangeLog", "w") - # Set up the loop variables in order to locate the blocks we want authorFound = False dateFound = False @@ -45,101 +42,101 @@ wrapper = TextWrapper(initial_indent="\t", subsequent_indent="\t ") -# The main part of the loop -for line in fin: - # The commit line marks the start of a new commit object. - if line.startswith("commit"): - # Start all over again... - authorFound = False - dateFound = False - messageFound = False - messageNL = False - message = "" - filesFound = False - files = "" - continue - # Match the author line and extract the part we want - # (Don't use startswith to allow Author override inside commit message.) - elif "Author:" in line: - authorList = re.split(r": ", line, 1) - try: - author = authorList[1] - author = author[0 : len(author) - 1] - authorFound = True - except Exception as e: - print(f"Could not parse authorList = '{line}'. Error: {e!s}") +with open("ChangeLog", "w") as fout: + # The main part of the loop + for line in fin: + # The commit line marks the start of a new commit object. + if line.startswith("commit"): + # Start all over again... + authorFound = False + dateFound = False + messageFound = False + messageNL = False + message = "" + filesFound = False + files = "" + continue + # Match the author line and extract the part we want + # (Don't use startswith to allow Author override inside commit message.) + elif "Author:" in line: + authorList = re.split(r": ", line, 1) + try: + author = authorList[1] + author = author[0 : len(author) - 1] + authorFound = True + except Exception as e: + print(f"Could not parse authorList = '{line}'. Error: {e!s}") - # Match the date line - elif line.startswith("Date:"): - dateList = re.split(r": ", line, 1) - try: - date = dateList[1] - date = date[0 : len(date) - 1] - dateFound = True - except Exception as e: - print(f"Could not parse dateList = '{line}'. Error: {e!s}") - # The Fossil-IDs, svn-id, ad sign off lines are ignored: - elif ( - line.startswith((" Fossil-ID:", " [[SVN:")) - or " git-svn-id:" in line - or "Signed-off-by" in line - ): - continue - # Extract the actual commit message for this commit - elif authorFound & dateFound & messageFound is False: - # Find the commit message if we can - if len(line) == 1: - if messageNL: + # Match the date line + elif line.startswith("Date:"): + dateList = re.split(r": ", line, 1) + try: + date = dateList[1] + date = date[0 : len(date) - 1] + dateFound = True + except Exception as e: + print(f"Could not parse dateList = '{line}'. Error: {e!s}") + # The Fossil-IDs, svn-id, ad sign off lines are ignored: + elif ( + line.startswith((" Fossil-ID:", " [[SVN:")) + or " git-svn-id:" in line + or "Signed-off-by" in line + ): + continue + # Extract the actual commit message for this commit + elif authorFound & dateFound & messageFound is False: + # Find the commit message if we can + if len(line) == 1: + if messageNL: + messageFound = True + else: + messageNL = True + elif len(line) == 4: messageFound = True + elif len(message) == 0: + message += line.strip() else: - messageNL = True - elif len(line) == 4: - messageFound = True - elif len(message) == 0: - message += line.strip() - else: - message = message + " " + line.strip() - # If this line is hit all of the files have been stored for this commit - elif re.search(r"files? changed", line): - filesFound = True - continue - # Collect the files for this commit. FIXME: Still need to add +/- to files - elif authorFound & dateFound & messageFound: - fileList = re.split(r" \| ", line, 2) - if len(fileList) > 1: - if len(files) > 0: - files = files + ", " + fileList[0].strip() + message = message + " " + line.strip() + # If this line is hit all of the files have been stored for this commit + elif re.search(r"files? changed", line): + filesFound = True + continue + # Collect the files for this commit. FIXME: Still need to add +/- to files + elif authorFound & dateFound & messageFound: + fileList = re.split(r" \| ", line, 2) + if len(fileList) > 1: + if len(files) > 0: + files = files + ", " + fileList[0].strip() + else: + files = fileList[0].strip() + # All of the parts of the commit have been found - write out the entry + if authorFound & dateFound & messageFound & filesFound: + # First the author line, only outputted if it is the first for that + # author on this day + authorLine = date + " " + author + if len(prevAuthorLine) == 0: + fout.write(authorLine + "\n\n") + elif authorLine == prevAuthorLine: + pass else: - files = fileList[0].strip() - # All of the parts of the commit have been found - write out the entry - if authorFound & dateFound & messageFound & filesFound: - # First the author line, only outputted if it is the first for that - # author on this day - authorLine = date + " " + author - if len(prevAuthorLine) == 0: - fout.write(authorLine + "\n\n") - elif authorLine == prevAuthorLine: - pass - else: - fout.write("\n" + authorLine + "\n\n") + fout.write("\n" + authorLine + "\n\n") - # Assemble the actual commit message line(s) and limit the line length - # to 80 characters. - commitLine = "* " + files + ": " + message + # Assemble the actual commit message line(s) and limit the line length + # to 80 characters. + commitLine = "* " + files + ": " + message - # Write out the commit line - fout.write(wrapper.fill(commitLine) + "\n") + # Write out the commit line + fout.write(wrapper.fill(commitLine) + "\n") - # Now reset all the variables ready for a new commit block. - authorFound = False - dateFound = False - messageFound = False - messageNL = False - message = "" - filesFound = False - files = "" - prevAuthorLine = authorLine + # Now reset all the variables ready for a new commit block. + authorFound = False + dateFound = False + messageFound = False + messageNL = False + message = "" + filesFound = False + files = "" + prevAuthorLine = authorLine # Close the input and output lines now that we are finished. fin.close() -fout.close() diff --git a/utils/grass_html2md.sh b/utils/grass_html2md.sh new file mode 100755 index 00000000000..9ac2e548ae1 --- /dev/null +++ b/utils/grass_html2md.sh @@ -0,0 +1,69 @@ +#!/bin/bash +set -eu + +############################################################################### +# Convert recursively all .html files to .md (GitHub flavoured Markdown) +# +# Dependencies: +# pandoc +# wget +# +# Author(s): +# Martin Landa, Markus Neteler +# +# Usage: +# If you have "pandoc" in PATH, execute for HTML file conversion in +# current directory and subdirectories: +# ./utils/grass_html2md.sh +# +# COPYRIGHT: (C) 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. +# +############################################################################### + +# cleanup at user break +cleanup() +{ + rm -f "${f%%.html}_tmp.html" +} + +# what to do in case of user break: +exitprocedure() +{ + echo "User break!" + cleanup + exit 1 +} +# shell check for user break (signal list: trap -l) +trap "exitprocedure" 2 3 15 + +# path to LUA file (./utils/pandoc_codeblock.lua) +UTILSPATH="utils" + +# run recursively: HTML to MD +for f in $(find . -name *.html); do + echo "${f}" + + # HTML: Process the tmp file to selectively replace .html with .md only in relative URLs + sed -E ' + # Step 1: Preserve http/https links with .html (and optional anchors) + s|(|\1_KEEPHTML\2">|g; + # Step 2: Replace .html with .md for local links (with or without anchors) + s|(|\1\2.md\3">|g; + # Step 3: Restore preserved http/https links with .html + s|_KEEPHTML||g; +' "${f%%.html}.html" > "${f%%.html}_tmp.html" + + cat "${f%%.html}_tmp.html" | \ + sed 's#
#
#g' | \
+        sed 's#
##g' | \ + pandoc --from=html --to=markdown -t gfm \ + --lua-filter "${UTILSPATH}/pandoc_codeblock.lua" | \ + sed 's+ \\\$+ \$+g' | sed 's+%20+-+g' > "${f%%.html}.md" + + rm -f "${f%%.html}_tmp.html" + +done diff --git a/utils/pandoc_codeblock.lua b/utils/pandoc_codeblock.lua new file mode 100644 index 00000000000..e2a0a54910f --- /dev/null +++ b/utils/pandoc_codeblock.lua @@ -0,0 +1,8 @@ +-- Pandoc Lua filter to handle code blocks +-- Test cases +-- raster/r.sun/r.sun.html + +-- Function to convert code blocks to markdown +function CodeBlock (cb) + return pandoc.RawBlock('markdown', '```shell\n' .. cb.text .. '\n```\n') +end diff --git a/utils/thumbnails.py b/utils/thumbnails.py index 2eab7319f52..b0197b712df 100755 --- a/utils/thumbnails.py +++ b/utils/thumbnails.py @@ -200,9 +200,10 @@ def main(): gs.mapcalc("$grad = float(col())", grad=tmp_grad_rel, quiet=True) - for table in os.listdir(color_dir): - path = os.path.join(color_dir, table) - grad = make_gradient(path) + color_dir_path = Path(color_dir) + for table_path in color_dir_path.iterdir(): + table = table_path.name + grad = make_gradient(table_path) make_image(output_dir, table, grad, height=height, width=width) gs.mapcalc("$grad = col()", grad=tmp_grad_abs, quiet=True) diff --git a/vector/v.lrs/lrs.html b/vector/v.lrs/lrs.html index 63d99b6c1fd..e3a7ec789be 100644 --- a/vector/v.lrs/lrs.html +++ b/vector/v.lrs/lrs.html @@ -1,4 +1,6 @@ - + + +

DESCRIPTION

A Linear Referencing System (LRS) is a system diff --git a/vector/v.to.3d/trans3.c b/vector/v.to.3d/trans3.c index 854c9bc329b..ec6edce8381 100644 --- a/vector/v.to.3d/trans3.c +++ b/vector/v.to.3d/trans3.c @@ -148,6 +148,7 @@ void trans3d(struct Map_info *In, struct Map_info *Out, int type, Vect_destroy_line_struct(Points); Vect_destroy_cats_struct(Cats); + Vect_destroy_field_info(Fi); } int srch(const void *pa, const void *pb)