diff --git a/gui/wxpython/animation/temporal_manager.py b/gui/wxpython/animation/temporal_manager.py index 814a48fcac1..d121d59e13a 100644 --- a/gui/wxpython/animation/temporal_manager.py +++ b/gui/wxpython/animation/temporal_manager.py @@ -19,6 +19,7 @@ import datetime from operator import itemgetter +from pathlib import Path import grass.script as gs import grass.temporal as tgis @@ -411,8 +412,7 @@ def createAbsoluteInterval(): gs.mapcalc(exp="temp_6 = rand(0, 650)", overwrite=True) n1 = gs.read_command("g.tempfile", pid=1, flags="d").strip() - fd = open(n1, "w") - fd.write( + Path(n1).write_text( "prec_1|2001-01-01|2001-02-01\n" "prec_2|2001-04-01|2001-05-01\n" "prec_3|2001-05-01|2001-09-01\n" @@ -420,11 +420,9 @@ def createAbsoluteInterval(): "prec_5|2002-01-01|2002-05-01\n" "prec_6|2002-05-01|2002-07-01\n" ) - fd.close() n2 = gs.read_command("g.tempfile", pid=2, flags="d").strip() - fd = open(n2, "w") - fd.write( + Path(n2).write_text( "temp_1|2000-10-01|2001-01-01\n" "temp_2|2001-04-01|2001-05-01\n" "temp_3|2001-05-01|2001-09-01\n" @@ -432,7 +430,6 @@ def createAbsoluteInterval(): "temp_5|2002-01-01|2002-05-01\n" "temp_6|2002-05-01|2002-07-01\n" ) - fd.close() name1 = "absinterval1" name2 = "absinterval2" gs.run_command( @@ -486,8 +483,7 @@ def createRelativeInterval(): gs.mapcalc(exp="temp_6 = rand(0, 650)", overwrite=True) n1 = gs.read_command("g.tempfile", pid=1, flags="d").strip() - fd = open(n1, "w") - fd.write( + Path(n1).write_text( "prec_1|1|4\n" "prec_2|6|7\n" "prec_3|7|10\n" @@ -495,11 +491,9 @@ def createRelativeInterval(): "prec_5|11|14\n" "prec_6|14|17\n" ) - fd.close() n2 = gs.read_command("g.tempfile", pid=2, flags="d").strip() - fd = open(n2, "w") - fd.write( + Path(n2).write_text( "temp_1|5|6\n" "temp_2|6|7\n" "temp_3|7|10\n" @@ -507,7 +501,6 @@ def createRelativeInterval(): "temp_5|11|18\n" "temp_6|19|22\n" ) - fd.close() name1 = "relinterval1" name2 = "relinterval2" gs.run_command( @@ -560,8 +553,7 @@ def createAbsolutePoint(): gs.mapcalc(exp="prec_6 = rand(0, 650)", overwrite=True) n1 = gs.read_command("g.tempfile", pid=1, flags="d").strip() - fd = open(n1, "w") - fd.write( + Path(n1).write_text( "prec_1|2001-01-01\n" "prec_2|2001-03-01\n" "prec_3|2001-04-01\n" @@ -569,7 +561,6 @@ def createAbsolutePoint(): "prec_5|2001-08-01\n" "prec_6|2001-09-01\n" ) - fd.close() name = "abspoint" gs.run_command( "t.create", @@ -608,9 +599,9 @@ def createRelativePoint(): gs.mapcalc(exp="prec_6 = rand(0, 650)", overwrite=True) n1 = gs.read_command("g.tempfile", pid=1, flags="d").strip() - fd = open(n1, "w") - fd.write("prec_1|1\nprec_2|3\nprec_3|5\nprec_4|7\nprec_5|11\nprec_6|13\n") - fd.close() + Path(n1).write_text( + "prec_1|1\nprec_2|3\nprec_3|5\nprec_4|7\nprec_5|11\nprec_6|13\n" + ) name = "relpoint" gs.run_command( "t.create", diff --git a/gui/wxpython/core/render.py b/gui/wxpython/core/render.py index 26a984990e7..67e7561c4e7 100644 --- a/gui/wxpython/core/render.py +++ b/gui/wxpython/core/render.py @@ -51,10 +51,10 @@ def get_tempfile_name(suffix, create=False): # which may mitigate problems (like not cleaning files) in case we # go little beyond what is in the documentation in terms of opening # closing and removing the tmp file - tmp = tempfile.NamedTemporaryFile(suffix=suffix, delete=False) - # we don't want it open, we just need the name - name = tmp.name - tmp.close() + with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as tmp: + # we don't want it open, we just need the name + name = tmp.name + if not create: # remove empty file to have a clean state later os.remove(name) diff --git a/gui/wxpython/core/toolboxes.py b/gui/wxpython/core/toolboxes.py index d3b50cb1ea5..76c1094e2ba 100644 --- a/gui/wxpython/core/toolboxes.py +++ b/gui/wxpython/core/toolboxes.py @@ -205,9 +205,7 @@ def getMenudataFile(userRootFile, newFile, fallback): try: xml = _getXMLString(tree.getroot()) - fh = open(menudataFile, "w") - fh.write(xml) - fh.close() + Path(menudataFile).write_text(xml) return menudataFile except Exception: _debug( diff --git a/gui/wxpython/dbmgr/base.py b/gui/wxpython/dbmgr/base.py index 20ddbc47f25..348e4555641 100644 --- a/gui/wxpython/dbmgr/base.py +++ b/gui/wxpython/dbmgr/base.py @@ -4008,17 +4008,18 @@ def Update(self, driver, database, table, column): return fd, sqlFilePath = tempfile.mkstemp(text=True) - sqlFile = open(sqlFilePath, "w") stats = ["count", "min", "max", "avg", "sum", "null"] - for fn in stats: - if fn == "null": - sqlFile.write( - "select count(*) from %s where %s is null;%s" - % (table, column, "\n") - ) - else: - sqlFile.write("select %s(%s) from %s;%s" % (fn, column, table, "\n")) - sqlFile.close() + with open(sqlFilePath, "w") as sqlFile: + for fn in stats: + if fn == "null": + sqlFile.write( + "select count(*) from %s where %s is null;%s" + % (table, column, "\n") + ) + else: + sqlFile.write( + "select %s(%s) from %s;%s" % (fn, column, table, "\n") + ) dataStr = RunCommand( "db.select", diff --git a/gui/wxpython/gcp/manager.py b/gui/wxpython/gcp/manager.py index ddeb19c7302..53aee173473 100644 --- a/gui/wxpython/gcp/manager.py +++ b/gui/wxpython/gcp/manager.py @@ -86,22 +86,13 @@ def getSmallUpArrowImage(): - stream = open(os.path.join(globalvar.IMGDIR, "small_up_arrow.png"), "rb") - try: - img = wx.Image(stream) - finally: - stream.close() - return img + with open(os.path.join(globalvar.IMGDIR, "small_up_arrow.png"), "rb") as stream: + return wx.Image(stream) def getSmallDnArrowImage(): - stream = open(os.path.join(globalvar.IMGDIR, "small_down_arrow.png"), "rb") - try: - img = wx.Image(stream) - finally: - stream.close() - stream.close() - return img + with open(os.path.join(globalvar.IMGDIR, "small_down_arrow.png"), "rb") as stream: + return wx.Image(stream) class GCPWizard: @@ -123,16 +114,13 @@ def __init__(self, parent, giface): # self.target_gisrc = os.environ["GISRC"] self.gisrc_dict = {} - try: - f = open(self.target_gisrc) + with open(self.target_gisrc) as f: for line in f: line = line.replace("\n", "").strip() if len(line) < 1: continue key, value = line.split(":", 1) self.gisrc_dict[key.strip()] = value.strip() - finally: - f.close() self.currentlocation = self.gisrc_dict["LOCATION_NAME"] self.currentmapset = self.gisrc_dict["MAPSET"] @@ -345,14 +333,10 @@ def SetSrcEnv(self, location, mapset): self.source_gisrc = utils.GetTempfile() - try: - f = open(self.source_gisrc, mode="w") + with open(self.source_gisrc, mode="w") as f: f.writelines( line[0] + ": " + line[1] + "\n" for line in self.gisrc_dict.items() ) - finally: - f.close() - return True def SwitchEnv(self, grc): @@ -1516,41 +1500,41 @@ def SaveGCPs(self, event): """ self.GCPcount = 0 try: - f = open(self.file["points"], mode="w") - # use os.linesep or '\n' here ??? - f.write("# Ground Control Points File\n") - f.write("# \n") - f.write("# target location: " + self.currentlocation + "\n") - f.write("# target mapset: " + self.currentmapset + "\n") - f.write("#\tsource\t\ttarget\t\tstatus\n") - f.write("#\teast\tnorth\teast\tnorth\t(1=ok, 0=ignore)\n") - f.write( - "#----------------------- ----------------------- ---------------\n" # noqa: E501 - ) - - for index in range(self.list.GetItemCount()): - if self.list.IsItemChecked(index): - check = "1" - self.GCPcount += 1 - else: - check = "0" - coord0 = self.list.GetItem(index, 1).GetText() - coord1 = self.list.GetItem(index, 2).GetText() - coord2 = self.list.GetItem(index, 3).GetText() - coord3 = self.list.GetItem(index, 4).GetText() + with open(self.file["points"], mode="w") as f: + # use os.linesep or '\n' here ??? + f.write("# Ground Control Points File\n") + f.write("# \n") + f.write("# target location: " + self.currentlocation + "\n") + f.write("# target mapset: " + self.currentmapset + "\n") + f.write("#\tsource\t\ttarget\t\tstatus\n") + f.write("#\teast\tnorth\teast\tnorth\t(1=ok, 0=ignore)\n") f.write( - coord0 - + " " - + coord1 - + " " - + coord2 - + " " - + coord3 - + " " - + check - + "\n" + "#----------------------- ----------------------- ---------------\n" # noqa: E501 ) + for index in range(self.list.GetItemCount()): + if self.list.IsItemChecked(index): + check = "1" + self.GCPcount += 1 + else: + check = "0" + coord0 = self.list.GetItem(index, 1).GetText() + coord1 = self.list.GetItem(index, 2).GetText() + coord2 = self.list.GetItem(index, 3).GetText() + coord3 = self.list.GetItem(index, 4).GetText() + f.write( + coord0 + + " " + + coord1 + + " " + + coord2 + + " " + + coord3 + + " " + + check + + "\n" + ) + except OSError as err: GError( parent=self, @@ -1564,8 +1548,6 @@ def SaveGCPs(self, event): ) return - f.close() - # if event != None save also to backup file if event: shutil.copy(self.file["points"], self.file["points_bak"]) @@ -1589,27 +1571,26 @@ def ReadGCPs(self): GError(parent=self, message=_("target mapwin not defined")) try: - f = open(self.file["points"]) GCPcnt = 0 + with open(self.file["points"]) as f: + for line in f: + if line[0] == "#" or line == "": + continue + line = line.replace("\n", "").strip() + coords = list(map(float, line.split())) + if coords[4] == 1: + check = True + self.GCPcount += 1 + else: + check = False - for line in f: - if line[0] == "#" or line == "": - continue - line = line.replace("\n", "").strip() - coords = list(map(float, line.split())) - if coords[4] == 1: - check = True - self.GCPcount += 1 - else: - check = False - - self.AddGCP(event=None) - self.SetGCPData("source", (coords[0], coords[1]), sourceMapWin) - self.SetGCPData("target", (coords[2], coords[3]), targetMapWin) - index = self.list.GetSelected() - if index != wx.NOT_FOUND: - self.list.CheckItem(index, check) - GCPcnt += 1 + self.AddGCP(event=None) + self.SetGCPData("source", (coords[0], coords[1]), sourceMapWin) + self.SetGCPData("target", (coords[2], coords[3]), targetMapWin) + index = self.list.GetSelected() + if index != wx.NOT_FOUND: + self.list.CheckItem(index, check) + GCPcnt += 1 except OSError as err: GError( @@ -1624,8 +1605,6 @@ def ReadGCPs(self): ) return - f.close() - if GCPcnt == 0: # 3 gcp is minimum for i in range(3): @@ -1831,16 +1810,13 @@ def OnGeorect(self, event): self.grwiz.SwitchEnv("source") # make list of vectors to georectify from VREF - f = open(self.file["vgrp"]) vectlist = [] - try: + with open(self.file["vgrp"]) as f: for vect in f: vect = vect.strip("\n") if len(vect) < 1: continue vectlist.append(vect) - finally: - f.close() # georectify each vector in VREF using v.rectify for vect in vectlist: @@ -2119,8 +2095,7 @@ def GetNewExtent(self, region, map=None): "w": 0.0, } - try: - f = open(coord_file, mode="w") + with open(coord_file, mode="w") as f: # NW corner f.write(str(region["e"]) + " " + str(region["n"]) + "\n") # NE corner @@ -2129,8 +2104,6 @@ def GetNewExtent(self, region, map=None): f.write(str(region["w"]) + " " + str(region["n"]) + "\n") # SE corner f.write(str(region["w"]) + " " + str(region["s"]) + "\n") - finally: - f.close() # save GCPs to points file to make sure that all checked GCPs are used self.SaveGCPs(None) @@ -2694,8 +2667,7 @@ def __init__( self.listMap = CheckListBox(parent=self, id=wx.ID_ANY, choices=vectlist) if os.path.isfile(self.vgrpfile): - f = open(self.vgrpfile) - try: + with open(self.vgrpfile) as f: checked = [] for line in f: line = line.replace("\n", "") @@ -2703,8 +2675,6 @@ def __init__( continue checked.append(line.split("@")[0]) self.listMap.SetCheckedStrings(checked) - finally: - f.close() line = wx.StaticLine( parent=self, id=wx.ID_ANY, size=(20, -1), style=wx.LI_HORIZONTAL @@ -2768,11 +2738,8 @@ def MakeVGroup(self): if not os.path.exists(dirname): os.makedirs(dirname) - f = open(self.vgrpfile, mode="w") - try: + with open(self.vgrpfile, mode="w") as f: f.writelines(vect + "\n" for vect in vgrouplist) - finally: - f.close() class EditGCP(wx.Dialog): diff --git a/gui/wxpython/gmodeler/model.py b/gui/wxpython/gmodeler/model.py index 1f85af66ded..75795b92fe2 100644 --- a/gui/wxpython/gmodeler/model.py +++ b/gui/wxpython/gmodeler/model.py @@ -39,6 +39,7 @@ import time import xml.etree.ElementTree as ET +from pathlib import Path from xml.sax import saxutils import wx @@ -542,11 +543,8 @@ def _substituteFile(self, item, params=None, checkOnly=False): for finput in self.fileInput: # read lines - fd = open(finput) - try: - data = self.fileInput[finput] = fd.read() - finally: - fd.close() + data = Path(finput).read_text() + self.fileInput[finput] = data # substitute variables write = False @@ -579,11 +577,7 @@ def _substituteFile(self, item, params=None, checkOnly=False): if not checkOnly: if write: - fd = open(finput, "w") - try: - fd.write(data) - finally: - fd.close() + Path(finput).write_text(data) else: self.fileInput[finput] = None diff --git a/gui/wxpython/gmodeler/panels.py b/gui/wxpython/gmodeler/panels.py index e567706cd19..c05ce041047 100644 --- a/gui/wxpython/gmodeler/panels.py +++ b/gui/wxpython/gmodeler/panels.py @@ -401,11 +401,7 @@ def OnModelDone(self, event): if not data: continue - fd = open(finput, "w") - try: - fd.write(data) - finally: - fd.close() + Path(finput).write_text(data) del self.model.fileInput # delete intermediate data @@ -671,30 +667,27 @@ def WriteModelFile(self, filename): :return: False on failure """ self.ModelChanged(False) - tmpfile = tempfile.TemporaryFile(mode="w+") - try: - WriteModelFile(fd=tmpfile, model=self.model) - except Exception: - GError( - parent=self, message=_("Writing current settings to model file failed.") - ) - return False - - try: - mfile = open(filename, "w") - tmpfile.seek(0) - mfile.writelines(tmpfile.readlines()) - except OSError: - wx.MessageBox( - parent=self, - message=_("Unable to open file <%s> for writing.") % filename, - caption=_("Error"), - style=wx.OK | wx.ICON_ERROR | wx.CENTRE, - ) - return False - - mfile.close() - + with tempfile.TemporaryFile(mode="w+") as tmpfile: + try: + WriteModelFile(fd=tmpfile, model=self.model) + except Exception: + GError( + parent=self, + message=_("Writing current settings to model file failed."), + ) + return False + try: + with open(filename, "w") as mfile: + tmpfile.seek(0) + mfile.writelines(tmpfile.readlines()) + except OSError: + wx.MessageBox( + parent=self, + message=_("Unable to open file <%s> for writing.") % filename, + caption=_("Error"), + style=wx.OK | wx.ICON_ERROR | wx.CENTRE, + ) + return False return True def DefineLoop(self, loop): @@ -1701,17 +1694,15 @@ def RefreshScript(self): if ret == wx.ID_NO: return False - fd = tempfile.TemporaryFile(mode="r+") grassAPI = UserSettings.Get(group="modeler", key="grassAPI", subkey="selection") - self.write_object( - fd, - self.parent.GetModel(), - grassAPI="script" if grassAPI == 0 else "pygrass", - ) - - fd.seek(0) - self.body.SetText(fd.read()) - fd.close() + with tempfile.TemporaryFile(mode="r+") as fd: + self.write_object( + fd, + self.parent.GetModel(), + grassAPI="script" if grassAPI == 0 else "pygrass", + ) + fd.seek(0) + self.body.SetText(fd.read()) self.body.modified = False @@ -1764,18 +1755,13 @@ def SaveAs(self, force=False): dlg.Destroy() - fd = open(filename, "w") - try: + with open(filename, "w") as fd: if force: self.write_object(fd, self.parent.GetModel()) else: fd.write(self.body.GetText()) - finally: - fd.close() - # executable file os.chmod(filename, stat.S_IRWXU | stat.S_IWUSR) - return filename def OnRun(self, event): diff --git a/gui/wxpython/gui_core/ghelp.py b/gui/wxpython/gui_core/ghelp.py index 0c4f6cdadfb..b2a0d0500e9 100644 --- a/gui/wxpython/gui_core/ghelp.py +++ b/gui/wxpython/gui_core/ghelp.py @@ -23,6 +23,9 @@ import re import textwrap import sys + +from pathlib import Path + import wx from wx.html import HtmlWindow from operator import itemgetter @@ -274,9 +277,7 @@ def _pageCopyright(self): """Copyright information""" copyfile = os.path.join(os.getenv("GISBASE"), "COPYING") if os.path.exists(copyfile): - copyrightFile = open(copyfile) - copytext = copyrightFile.read() - copyrightFile.close() + copytext = Path(copyfile).read_text() else: copytext = _("%s file missing") % "COPYING" @@ -303,9 +304,8 @@ def _pageLicense(self): """Licence about""" licfile = os.path.join(os.getenv("GISBASE"), "GPL.TXT") if os.path.exists(licfile): - licenceFile = open(licfile) - license = "".join(licenceFile.readlines()) - licenceFile.close() + with open(licfile) as licenceFile: + license = "".join(licenceFile.readlines()) else: license = _("%s file missing") % "GPL.TXT" # put text into a scrolling panel @@ -384,33 +384,31 @@ def _pageContributors(self, extra=False): else: contribfile = os.path.join(os.getenv("GISBASE"), "contributors.csv") if os.path.exists(contribfile): - contribFile = codecs.open(contribfile, encoding="utf-8", mode="r") contribs = [] errLines = [] - for line in contribFile.readlines()[1:]: - line = line.rstrip("\n") - try: + with codecs.open(contribfile, encoding="utf-8", mode="r") as contribFile: + for line in contribFile.readlines()[1:]: + line = line.rstrip("\n") + try: + if extra: + name, email, country, rfc2_agreed = line.split(",") + else: + ( + cvs_id, + name, + email, + country, + osgeo_id, + rfc2_agreed, + orcid, + ) = line.split(",") + except ValueError: + errLines.append(line) + continue if extra: - name, email, country, rfc2_agreed = line.split(",") + contribs.append((name, email, country)) else: - ( - cvs_id, - name, - email, - country, - osgeo_id, - rfc2_agreed, - orcid, - ) = line.split(",") - except ValueError: - errLines.append(line) - continue - if extra: - contribs.append((name, email, country)) - else: - contribs.append((name, email, country, osgeo_id, orcid)) - - contribFile.close() + contribs.append((name, email, country, osgeo_id, orcid)) if errLines: GError( @@ -469,21 +467,20 @@ def _pageTranslators(self): """Translators info""" translatorsfile = os.path.join(os.getenv("GISBASE"), "translators.csv") if os.path.exists(translatorsfile): - translatorsFile = codecs.open(translatorsfile, encoding="utf-8", mode="r") translators = {} errLines = [] - for line in translatorsFile.readlines()[1:]: - line = line.rstrip("\n") - try: - name, email, languages = line.split(",") - except ValueError: - errLines.append(line) - continue - for language in languages.split(" "): - if language not in translators: - translators[language] = [] - translators[language].append((name, email)) - translatorsFile.close() + with codecs.open(translatorsfile, encoding="utf-8", mode="r") as fd: + for line in fd.readlines()[1:]: + line = line.rstrip("\n") + try: + name, email, languages = line.split(",") + except ValueError: + errLines.append(line) + continue + for language in languages.split(" "): + if language not in translators: + translators[language] = [] + translators[language].append((name, email)) if errLines: GError( @@ -650,10 +647,10 @@ def _pageStats(self): fname = "translation_status.json" statsfile = os.path.join(os.getenv("GISBASE"), fname) if os.path.exists(statsfile): - statsFile = open(statsfile) import json - jsStats = json.load(statsFile) + with open(statsfile) as statsFile: + jsStats = json.load(statsFile) else: jsStats = None self.statswin = ScrolledPanel(self.aboutNotebook) @@ -810,38 +807,39 @@ def fillContentsFromFile(self, htmlFile, skipDescription=True): try: contents = [] skip = False - for line in open(htmlFile, "rb"): - if "DESCRIPTION" in line: - skip = False - if not skip: - # do skip the options description if requested - if "SYNOPSIS" in line: - skip = skipDescription - else: - # FIXME: find only first item - findALink = aLink.search(line) - if findALink is not None: - contents.append( - aLink.sub( - findALink.group(1) - + self.fspath - + findALink.group(2), - line, + with open(htmlFile, "rb") as fd: + for line in fd: + if "DESCRIPTION" in line: + skip = False + if not skip: + # do skip the options description if requested + if "SYNOPSIS" in line: + skip = skipDescription + else: + # FIXME: find only first item + findALink = aLink.search(line) + if findALink is not None: + contents.append( + aLink.sub( + findALink.group(1) + + self.fspath + + findALink.group(2), + line, + ) ) - ) - findImgLink = imgLink.search(line) - if findImgLink is not None: - contents.append( - imgLink.sub( - findImgLink.group(1) - + self.fspath - + findImgLink.group(2), - line, + findImgLink = imgLink.search(line) + if findImgLink is not None: + contents.append( + imgLink.sub( + findImgLink.group(1) + + self.fspath + + findImgLink.group(2), + line, + ) ) - ) - if findALink is None and findImgLink is None: - contents.append(line) + if findALink is None and findImgLink is None: + contents.append(line) self.SetPage("".join(contents)) self.loaded = True except Exception: # The Manual file was not found diff --git a/gui/wxpython/gui_core/gselect.py b/gui/wxpython/gui_core/gselect.py index 248d40de073..729f38a5d30 100644 --- a/gui/wxpython/gui_core/gselect.py +++ b/gui/wxpython/gui_core/gselect.py @@ -832,17 +832,15 @@ def __init__(self, map): def _CheckDBConnection(self): """Check DB connection""" - nuldev = open(os.devnull, "w+") - # if map is not defined (happens with vnet initialization) or it - # doesn't exist - try: - self.layers = gs.vector_db(map=self.map, stderr=nuldev) - except CalledModuleError: - return False - finally: # always close nuldev - nuldev.close() + with open(os.devnull, "w+") as nuldev: + # if map is not defined (happens with vnet initialization) or it + # doesn't exist + try: + self.layers = gs.vector_db(map=self.map, stderr=nuldev) + except CalledModuleError: + return False - return bool(len(self.layers.keys()) > 0) + return bool(len(self.layers.keys()) > 0) def _DescribeTables(self): """Describe linked tables""" diff --git a/gui/wxpython/gui_core/widgets.py b/gui/wxpython/gui_core/widgets.py index 40c9e6c5e19..47bd3a1957c 100644 --- a/gui/wxpython/gui_core/widgets.py +++ b/gui/wxpython/gui_core/widgets.py @@ -1520,30 +1520,29 @@ def _writeSettings(self): :return: -1 on failure """ try: - fd = open(self.settingsFile, "w") - fd.write("format_version=2.0\n") - for key, values in self._settings.items(): - first = True - for v in values: - # escaping characters - for e_ch in self.esc_chars: - v = v.replace(e_ch, self.esc_chars[self.e_char_i] + e_ch) - if first: + with open(self.settingsFile, "w") as fd: + fd.write("format_version=2.0\n") + for key, values in self._settings.items(): + first = True + for v in values: # escaping characters for e_ch in self.esc_chars: - key = key.replace( - e_ch, self.esc_chars[self.e_char_i] + e_ch - ) - fd.write("%s;%s;" % (key, v)) - first = False - else: - fd.write("%s;" % (v)) - fd.write("\n") + v = v.replace(e_ch, self.esc_chars[self.e_char_i] + e_ch) + if first: + # escaping characters + for e_ch in self.esc_chars: + key = key.replace( + e_ch, self.esc_chars[self.e_char_i] + e_ch + ) + fd.write("%s;%s;" % (key, v)) + first = False + else: + fd.write("%s;" % (v)) + fd.write("\n") except OSError: GError(parent=self, message=_("Unable to save settings")) return -1 - fd.close() return 0 diff --git a/gui/wxpython/image2target/ii2t_gis_set.py b/gui/wxpython/image2target/ii2t_gis_set.py index 0329516e04a..dcc8744f469 100644 --- a/gui/wxpython/image2target/ii2t_gis_set.py +++ b/gui/wxpython/image2target/ii2t_gis_set.py @@ -104,9 +104,8 @@ def __init__(self, parent=None, id=wx.ID_ANY, style=wx.DEFAULT_FRAME_STYLE): # labels # crashes when LOCATION doesn't exist # get version & revision - versionFile = open(os.path.join(globalvar.ETCDIR, "VERSIONNUMBER")) - versionLine = versionFile.readline().rstrip("\n") - versionFile.close() + with open(os.path.join(globalvar.ETCDIR, "VERSIONNUMBER")) as versionFile: + versionLine = versionFile.readline().rstrip("\n") try: grassVersion, grassRevision = versionLine.split(" ", 1) if grassVersion.endswith("dev"): @@ -542,8 +541,7 @@ def _readGisRC(self): gisrc = os.getenv("GISRC") if gisrc and os.path.isfile(gisrc): - try: - rc = open(gisrc) + with open(gisrc) as rc: for line in rc: try: key, val = line.split(":", 1) @@ -552,8 +550,6 @@ def _readGisRC(self): _("Invalid line in GISRC file (%s):%s\n") % (e, line) ) grassrc[key.strip()] = DecodeString(val.strip()) - finally: - rc.close() return grassrc diff --git a/gui/wxpython/image2target/ii2t_manager.py b/gui/wxpython/image2target/ii2t_manager.py index a658897a5fb..52f7fd88d10 100644 --- a/gui/wxpython/image2target/ii2t_manager.py +++ b/gui/wxpython/image2target/ii2t_manager.py @@ -90,22 +90,13 @@ def getSmallUpArrowImage(): - stream = open(os.path.join(globalvar.IMGDIR, "small_up_arrow.png"), "rb") - try: - img = wx.Image(stream) - finally: - stream.close() - return img + with open(os.path.join(globalvar.IMGDIR, "small_up_arrow.png"), "rb") as stream: + return wx.Image(stream) def getSmallDnArrowImage(): - stream = open(os.path.join(globalvar.IMGDIR, "small_down_arrow.png"), "rb") - try: - img = wx.Image(stream) - finally: - stream.close() - stream.close() - return img + with open(os.path.join(globalvar.IMGDIR, "small_down_arrow.png"), "rb") as stream: + return wx.Image(stream) class GCPWizard: @@ -950,15 +941,12 @@ def OnEnterPage(self, event: WizardEvent | None = None) -> None: "VREF", ) - f = open(vgrpfile) - try: + with open(vgrpfile) as f: for vect in f: vect = vect.strip("\n") if len(vect) < 1: continue self.parent.src_maps.append(vect) - finally: - f.close() if len(self.parent.src_maps) < 1: GError( @@ -1783,16 +1771,13 @@ def OnGeorect(self, event): self.grwiz.SwitchEnv("source") # make list of vectors to georectify from VREF - f = open(self.file["vgrp"]) vectlist = [] - try: + with open(self.file["vgrp"]) as f: for vect in f: vect = vect.strip("\n") if len(vect) < 1: continue vectlist.append(vect) - finally: - f.close() # georectify each vector in VREF using v.rectify for vect in vectlist: @@ -2639,8 +2624,7 @@ def __init__( self.listMap = CheckListBox(parent=self, id=wx.ID_ANY, choices=vectlist) if os.path.isfile(self.vgrpfile): - f = open(self.vgrpfile) - try: + with open(self.vgrpfile) as f: checked = [] for line in f: line = line.replace("\n", "") @@ -2648,8 +2632,6 @@ def __init__( continue checked.append(line) self.listMap.SetCheckedStrings(checked) - finally: - f.close() line = wx.StaticLine( parent=self, id=wx.ID_ANY, size=(20, -1), style=wx.LI_HORIZONTAL @@ -2708,11 +2690,8 @@ def MakeVGroup(self): continue vgrouplist.append(self.listMap.GetString(item) + "@" + self.xymapset) - f = open(self.vgrpfile, mode="w") - try: + with open(self.vgrpfile, mode="w") as f: f.writelines(vect + "\n" for vect in vgrouplist) - finally: - f.close() class EditGCP(wx.Dialog): diff --git a/gui/wxpython/lmgr/workspace.py b/gui/wxpython/lmgr/workspace.py index 6bad27d7674..7971e3c4064 100644 --- a/gui/wxpython/lmgr/workspace.py +++ b/gui/wxpython/lmgr/workspace.py @@ -431,35 +431,30 @@ def SaveToFile(self, filename): """Save layer tree layout to workspace file :return: True on success, False on error """ - tmpfile = tempfile.TemporaryFile(mode="w+b") - try: - WriteWorkspaceFile(lmgr=self.lmgr, file=tmpfile) - except Exception as e: - GError( - parent=self.lmgr, - message=_( - "Writing current settings to workspace file <%s> failed.\n" - "Error details: %s" + with tempfile.TemporaryFile(mode="w+b") as tmpfile: + try: + WriteWorkspaceFile(lmgr=self.lmgr, file=tmpfile) + except Exception as e: + GError( + parent=self.lmgr, + message=_( + "Writing current settings to workspace file <%s> failed.\n" + "Error details: %s" + ) + % (tmpfile, str(e)), ) - % (tmpfile, str(e)), - ) - return False - - try: - mfile = open(filename, "wb") - tmpfile.seek(0) - mfile.writelines(tmpfile.readlines()) - except OSError: - GError( - parent=self.lmgr, - message=_("Unable to open file <%s> for writing.") % filename, - ) - return False - - mfile.close() - + return False + try: + with open(filename, "wb") as mfile: + tmpfile.seek(0) + mfile.writelines(tmpfile.readlines()) + except OSError: + GError( + parent=self.lmgr, + message=_("Unable to open file <%s> for writing.") % filename, + ) + return False self.AddFileToHistory(file_path=filename) - return True def CanClosePage(self, caption): diff --git a/gui/wxpython/location_wizard/wizard.py b/gui/wxpython/location_wizard/wizard.py index 52b8a87270d..885b80a26a5 100644 --- a/gui/wxpython/location_wizard/wizard.py +++ b/gui/wxpython/location_wizard/wizard.py @@ -2540,89 +2540,86 @@ def __readData(self): """Get georeferencing information from tables in $GISBASE/etc/proj""" # read projection and parameters - f = open(os.path.join(globalvar.ETCDIR, "proj", "parms.table")) self.projections = {} self.projdesc = {} - for line in f: - line = line.strip() - try: - proj, projdesc, params = line.split(":") - paramslist = params.split(";") - plist = [] - for p in paramslist: - if p == "": - continue - p1, pdefault = p.split(",") - pterm, pask = p1.split("=") - p = [pterm.strip(), pask.strip(), pdefault.strip()] - plist.append(p) - self.projections[proj.lower().strip()] = (projdesc.strip(), plist) - self.projdesc[proj.lower().strip()] = projdesc.strip() - except (ValueError, IndexError): - continue - f.close() + with open(os.path.join(globalvar.ETCDIR, "proj", "parms.table")) as f: + for line in f: + line = line.strip() + try: + proj, projdesc, params = line.split(":") + paramslist = params.split(";") + plist = [] + for p in paramslist: + if p == "": + continue + p1, pdefault = p.split(",") + pterm, pask = p1.split("=") + p = [pterm.strip(), pask.strip(), pdefault.strip()] + plist.append(p) + self.projections[proj.lower().strip()] = (projdesc.strip(), plist) + self.projdesc[proj.lower().strip()] = projdesc.strip() + except (ValueError, IndexError): + continue # read datum definitions - f = open(os.path.join(globalvar.ETCDIR, "proj", "datum.table")) self.datums = {} paramslist = [] - for line in f: - line = line.expandtabs(1) - line = line.strip() - if line == "" or line[0] == "#": - continue - datum, info = line.split(" ", 1) - info = info.strip() - datumdesc, params = info.split(" ", 1) - datumdesc = datumdesc.strip('"') - paramlist = params.split() - ellipsoid = paramlist.pop(0) - self.datums[datum] = (ellipsoid, datumdesc.replace("_", " "), paramlist) - f.close() + with open(os.path.join(globalvar.ETCDIR, "proj", "datum.table")) as f: + for line in f: + line = line.expandtabs(1) + line = line.strip() + if line == "" or line[0] == "#": + continue + datum, info = line.split(" ", 1) + info = info.strip() + datumdesc, params = info.split(" ", 1) + datumdesc = datumdesc.strip('"') + paramlist = params.split() + ellipsoid = paramlist.pop(0) + self.datums[datum] = (ellipsoid, datumdesc.replace("_", " "), paramlist) # read Earth-based ellipsiod definitions - f = open(os.path.join(globalvar.ETCDIR, "proj", "ellipse.table")) self.ellipsoids = {} - for line in f: - line = line.expandtabs(1) - line = line.strip() - if line == "" or line[0] == "#": - continue - ellipse, rest = line.split(" ", 1) - rest = rest.strip('" ') - desc, params = rest.split('"', 1) - desc = desc.strip('" ') - paramslist = params.split() - self.ellipsoids[ellipse] = (desc, paramslist) - f.close() + with open(os.path.join(globalvar.ETCDIR, "proj", "ellipse.table")) as f: + for line in f: + line = line.expandtabs(1) + line = line.strip() + if line == "" or line[0] == "#": + continue + ellipse, rest = line.split(" ", 1) + rest = rest.strip('" ') + desc, params = rest.split('"', 1) + desc = desc.strip('" ') + paramslist = params.split() + self.ellipsoids[ellipse] = (desc, paramslist) # read Planetary ellipsiod definitions - f = open(os.path.join(globalvar.ETCDIR, "proj", "ellipse.table.solar.system")) self.planetary_ellipsoids = {} - for line in f: - line = line.expandtabs(1) - line = line.strip() - if line == "" or line[0] == "#": - continue - ellipse, rest = line.split(" ", 1) - rest = rest.strip('" ') - desc, params = rest.split('"', 1) - desc = desc.strip('" ') - paramslist = params.split() - self.planetary_ellipsoids[ellipse] = (desc, paramslist) - f.close() + with open( + os.path.join(globalvar.ETCDIR, "proj", "ellipse.table.solar.system") + ) as f: + for line in f: + line = line.expandtabs(1) + line = line.strip() + if line == "" or line[0] == "#": + continue + ellipse, rest = line.split(" ", 1) + rest = rest.strip('" ') + desc, params = rest.split('"', 1) + desc = desc.strip('" ') + paramslist = params.split() + self.planetary_ellipsoids[ellipse] = (desc, paramslist) # read projection parameter description and parsing table - f = open(os.path.join(globalvar.ETCDIR, "proj", "desc.table")) self.paramdesc = {} - for line in f: - line = line.strip() - try: - pparam, datatype, proj4term, desc = line.split(":") - self.paramdesc[pparam] = (datatype, proj4term, desc) - except ValueError: - continue - f.close() + with open(os.path.join(globalvar.ETCDIR, "proj", "desc.table")) as f: + for line in f: + line = line.strip() + try: + pparam, datatype, proj4term, desc = line.split(":") + self.paramdesc[pparam] = (datatype, proj4term, desc) + except ValueError: + continue def OnWizFinished(self): """Wizard finished, create new location diff --git a/gui/wxpython/mapdisp/main.py b/gui/wxpython/mapdisp/main.py index a19c79b5780..76ae6218d5a 100644 --- a/gui/wxpython/mapdisp/main.py +++ b/gui/wxpython/mapdisp/main.py @@ -123,9 +123,8 @@ def GetLayersFromCmdFile(self): nlayers = 0 try: - fd = open(self.cmdfile) - lines = fd.readlines() - fd.close() + with open(self.cmdfile) as fd: + lines = fd.readlines() # detect d.out.file, delete the line from the cmd file and export # graphics if len(lines) > 0: @@ -133,9 +132,8 @@ def GetLayersFromCmdFile(self): "d.to.rast" ): dCmd = lines[-1].strip() - fd = open(self.cmdfile, "w") - fd.writelines(lines[:-1]) - fd.close() + with open(self.cmdfile, "w") as fd: + fd.writelines(lines[:-1]) if lines[-1].startswith("d.out.file"): self.saveToFile.emit(cmd=utils.split(dCmd)) else: @@ -143,9 +141,8 @@ def GetLayersFromCmdFile(self): return if lines[-1].startswith("d.what"): dWhatCmd = lines[-1].strip() - fd = open(self.cmdfile, "w") - fd.writelines(lines[:-1]) - fd.close() + with open(self.cmdfile, "w") as fd: + fd.writelines(lines[:-1]) if "=" in utils.split(dWhatCmd)[1]: maps = utils.split(dWhatCmd)[1].split("=")[1].split(",") else: @@ -655,11 +652,10 @@ def GetMapDisplay(self): # create pid file pidFile = os.path.join(monPath, "pid") - fd = open(pidFile, "w") - if not fd: - grass.fatal(_("Unable to create file <%s>") % pidFile) - fd.write("%s\n" % os.getpid()) - fd.close() + with open(pidFile, "w") as fd: + if not fd: + grass.fatal(_("Unable to create file <%s>") % pidFile) + fd.write("%s\n" % os.getpid()) RunCommand("g.gisenv", set="MONITOR_%s_PID=%d" % (monName.upper(), os.getpid())) diff --git a/gui/wxpython/modules/colorrules.py b/gui/wxpython/modules/colorrules.py index d5d74eaf08e..b222c08091e 100644 --- a/gui/wxpython/modules/colorrules.py +++ b/gui/wxpython/modules/colorrules.py @@ -687,9 +687,7 @@ def OnSaveRulesFile(self, event): GMessage(message=_("Nothing to save."), parent=self) return - fd = open(path, "w") - fd.write(rulestxt) - fd.close() + Path(path).write_text(rulestxt) def OnLoadRulesFile(self, event): """Load color table from file""" @@ -698,10 +696,7 @@ def OnLoadRulesFile(self, event): return self.rulesPanel.Clear() - - fd = open(path) - self.ReadColorTable(ctable=fd.read()) - fd.close() + self.ReadColorTable(ctable=Path(path).read_text()) def ReadColorTable(self, ctable): """Read color table @@ -801,11 +796,7 @@ def CreateColorTable(self, tmp=False) -> bool: return False gtemp = utils.GetTempfile() - output = open(gtemp, "w") - try: - output.write(rulestxt) - finally: - output.close() + Path(gtemp).write_text(rulestxt) cmd = [ "%s.colors" % self.mapType[0], # r.colors/v.colors @@ -1826,11 +1817,7 @@ def UpdateColorColumn(self, tmp): return False gtemp = utils.GetTempfile() - output = open(gtemp, "w") - try: - output.write(rulestxt) - finally: - output.close() + Path(gtemp).write_text(rulestxt) RunCommand("db.execute", parent=self, input=gtemp) return True diff --git a/gui/wxpython/modules/mcalc_builder.py b/gui/wxpython/modules/mcalc_builder.py index 4294a9730de..5567d6bd66d 100644 --- a/gui/wxpython/modules/mcalc_builder.py +++ b/gui/wxpython/modules/mcalc_builder.py @@ -18,6 +18,7 @@ import os import re +from pathlib import Path import wx import grass.script as gs @@ -733,11 +734,7 @@ def OnSaveExpression(self, event): dlg.Destroy() return - try: - fobj = open(path, "w") - fobj.write(mctxt) - finally: - fobj.close() + Path(path).write_text(mctxt) dlg.Destroy() @@ -755,11 +752,7 @@ def OnLoadExpression(self, event): dlg.Destroy() return - try: - fobj = open(path) - mctxt = fobj.read() - finally: - fobj.close() + mctxt = Path(path).read_text() try: result, exp = mctxt.split("=", 1) diff --git a/gui/wxpython/photo2image/ip2i_manager.py b/gui/wxpython/photo2image/ip2i_manager.py index 9f78d717fee..7e985101a06 100644 --- a/gui/wxpython/photo2image/ip2i_manager.py +++ b/gui/wxpython/photo2image/ip2i_manager.py @@ -67,22 +67,13 @@ def getSmallUpArrowImage(): - stream = open(os.path.join(globalvar.IMGDIR, "small_up_arrow.png"), "rb") - try: - img = wx.Image(stream) - finally: - stream.close() - return img + with open(os.path.join(globalvar.IMGDIR, "small_up_arrow.png"), "rb") as stream: + return wx.Image(stream) def getSmallDnArrowImage(): - stream = open(os.path.join(globalvar.IMGDIR, "small_down_arrow.png"), "rb") - try: - img = wx.Image(stream) - finally: - stream.close() - stream.close() - return img + with open(os.path.join(globalvar.IMGDIR, "small_down_arrow.png"), "rb") as stream: + return wx.Image(stream) class GCPWizard: diff --git a/gui/wxpython/psmap/frame.py b/gui/wxpython/psmap/frame.py index bb71fd856a5..bd0c484b757 100644 --- a/gui/wxpython/psmap/frame.py +++ b/gui/wxpython/psmap/frame.py @@ -19,6 +19,7 @@ import queue as Queue import sys from math import cos, pi, sin, sqrt +from pathlib import Path import wx @@ -358,13 +359,12 @@ def OnPreview(self, event): def PSFile(self, filename=None, pdf=False): """Create temporary instructions file and run ps.map with output = filename""" instrFile = gs.tempfile() - instrFileFd = open(instrFile, mode="wb") - content = self.InstructionFile() - if not content: - return - instrFileFd.write(content) - instrFileFd.flush() - instrFileFd.close() + with open(instrFile, mode="wb") as instrFileFd: + content = self.InstructionFile() + if not content: + return + instrFileFd.write(content) + instrFileFd.flush() temp = False regOld = gs.region(env=self.env) @@ -598,12 +598,10 @@ def OnInstructionFile(self, event): wildcard="*.psmap|*.psmap|Text file(*.txt)|*.txt|All files(*.*)|*.*" ) if filename: - instrFile = open(filename, "wb") content = self.InstructionFile() if not content: return - instrFile.write(content) - instrFile.close() + Path(filename).write_bytes(content) def OnLoadFile(self, event): """Launch file dialog and load selected file""" @@ -1068,13 +1066,12 @@ def getInitMap(self): """Create default map frame when no map is selected, needed for coordinates in map units""" instrFile = gs.tempfile() - instrFileFd = open(instrFile, mode="wb") - content = self.InstructionFile() - if not content: - return - instrFileFd.write(content) - instrFileFd.flush() - instrFileFd.close() + with open(instrFile, mode="wb") as instrFileFd: + content = self.InstructionFile() + if not content: + return + instrFileFd.write(content) + instrFileFd.flush() page = self.instruction.FindInstructionByType("page") mapInitRect = GetMapBounds( diff --git a/gui/wxpython/rdigit/controller.py b/gui/wxpython/rdigit/controller.py index 9b70a2cc468..9617e1d5178 100644 --- a/gui/wxpython/rdigit/controller.py +++ b/gui/wxpython/rdigit/controller.py @@ -648,9 +648,8 @@ def _rasterize(self, text, bufferDist, mapType, tempRaster): :return: output raster map name as a result of digitization """ output = "x" + str(uuid.uuid4())[:8] - asciiFile = tempfile.NamedTemporaryFile(mode="w", delete=False) - asciiFile.write("\n".join(text)) - asciiFile.close() + with tempfile.NamedTemporaryFile(mode="w", delete=False) as asciiFile: + asciiFile.write("\n".join(text)) if bufferDist: bufferDist /= 2.0 diff --git a/gui/wxpython/rlisetup/frame.py b/gui/wxpython/rlisetup/frame.py index dd93e607cea..3563590d561 100644 --- a/gui/wxpython/rlisetup/frame.py +++ b/gui/wxpython/rlisetup/frame.py @@ -48,9 +48,8 @@ def __init__( parent=self.panel, id=wx.ID_ANY, style=wx.TE_MULTILINE, size=(-1, 75) ) self.textCtrl.Bind(wx.EVT_TEXT, self.OnFileText) - f = open(self.pathfile) - self.textCtrl.SetValue("".join(f.readlines())) - f.close() + with open(self.pathfile) as f: + self.textCtrl.SetValue("".join(f.readlines())) # BUTTONS #definition self.btn_close = Button(parent=self, id=wx.ID_EXIT) self.btn_ok = Button(parent=self, id=wx.ID_SAVE) @@ -107,11 +106,10 @@ def OnOk(self, event): ) if dlg.ShowModal() == wx.ID_YES: - f = codecs.open( + with codecs.open( self.pathfile, encoding=self.enc, mode="w", errors="replace" - ) - f.write(self.text + os.linesep) - f.close() + ) as f: + f.write(self.text + os.linesep) dlg.Destroy() self.Destroy() diff --git a/gui/wxpython/rlisetup/sampling_frame.py b/gui/wxpython/rlisetup/sampling_frame.py index bc6f71f16c5..e62737449e6 100644 --- a/gui/wxpython/rlisetup/sampling_frame.py +++ b/gui/wxpython/rlisetup/sampling_frame.py @@ -255,18 +255,16 @@ def nextRegion(self, next=True, area=None): ) def writeArea(self, coords, rasterName): - polyfile = tempfile.NamedTemporaryFile(delete=False) - polyfile.write("AREA\n") - for coor in coords: - east, north = coor - point = " %s %s\n" % (east, north) - polyfile.write(point) - - catbuf = "=%d a\n" % self.catId - polyfile.write(catbuf) - self.catId += 1 - - polyfile.close() + with tempfile.NamedTemporaryFile(delete=False) as polyfile: + polyfile.write("AREA\n") + for coor in coords: + east, north = coor + point = " %s %s\n" % (east, north) + polyfile.write(point) + catbuf = "=%d a\n" % self.catId + polyfile.write(catbuf) + self.catId += 1 + region_settings = grass.parse_command("g.region", flags="p", delimiter=":") pname = polyfile.name.split("/")[-1] tmpraster = "rast_" + pname diff --git a/gui/wxpython/rlisetup/wizard.py b/gui/wxpython/rlisetup/wizard.py index fb23affbd25..46c7f3eae6a 100644 --- a/gui/wxpython/rlisetup/wizard.py +++ b/gui/wxpython/rlisetup/wizard.py @@ -158,11 +158,10 @@ def __init__(self, parent): def _write_confile(self): """Write the configuration file""" - f = open(os.path.join(self.rlipath, self.startpage.conf_name), "w") - self.rasterinfo = grast.raster_info(self.startpage.rast) - self._write_region(f) - self._write_area(f) - f.close() + with open(os.path.join(self.rlipath, self.startpage.conf_name), "w") as f: + self.rasterinfo = grast.raster_info(self.startpage.rast) + self._write_region(f) + self._write_area(f) def _temp_region(self): # save current settings: diff --git a/gui/wxpython/tools/update_menudata.py b/gui/wxpython/tools/update_menudata.py index 18c542c71f2..2c42f618c10 100644 --- a/gui/wxpython/tools/update_menudata.py +++ b/gui/wxpython/tools/update_menudata.py @@ -22,8 +22,8 @@ import os import sys import tempfile - import xml.etree.ElementTree as ET +from subprocess import DEVNULL from grass.script import core as grass from grass.script import task as gtask @@ -140,9 +140,8 @@ def main(argv=None): print(sys.stderr, __doc__, file=sys.stderr) return 1 - nuldev = open(os.devnull, "w+") grass.info("Step 1: running make...") - grass.call(["make"], stderr=nuldev) + grass.call(["make"], stderr=DEVNULL) grass.info("Step 2: parsing modules...") modules = {} modules = parseModules() @@ -152,14 +151,13 @@ def main(argv=None): updateData(data, modules) if printDiff: - tempFile = tempfile.NamedTemporaryFile() - grass.info("Step 5: diff menu data...") - writeData(data, tempFile.name) - - grass.call( - ["diff", "-u", os.path.join("xml", "menudata.xml"), tempFile.name], - stderr=nuldev, - ) + with tempfile.NamedTemporaryFile() as tempFile: + grass.info("Step 5: diff menu data...") + writeData(data, tempFile.name) + grass.call( + ["diff", "-u", os.path.join("xml", "menudata.xml"), tempFile.name], + stderr=DEVNULL, + ) else: grass.info("Step 5: writing menu data (menudata.xml)...") writeData(data) diff --git a/gui/wxpython/vdigit/mapwindow.py b/gui/wxpython/vdigit/mapwindow.py index 7abe3f4405d..81421027feb 100644 --- a/gui/wxpython/vdigit/mapwindow.py +++ b/gui/wxpython/vdigit/mapwindow.py @@ -394,40 +394,37 @@ def _geomAttrbUpdate(self, fids): return dbInfo = gselect.VectorDBInfo(vectorName) - sqlfile = tempfile.NamedTemporaryFile(mode="w") - for fid in fids: - for layer, cats in self.digit.GetLineCats(fid).items(): - table = dbInfo.GetTable(layer) - for attrb, item in vdigit["geomAttr"].items(): - val = -1 - if attrb == "length": - val = self.digit.GetLineLength(fid) - type = attrb - elif attrb == "area": - val = self.digit.GetAreaSize(fid) - type = attrb - elif attrb == "perimeter": - val = self.digit.GetAreaPerimeter(fid) - type = "length" - - if val < 0: - continue - val = UnitsConvertValue(val, type, item["units"]) - - for cat in cats: - sqlfile.write( - "UPDATE %s SET %s = %f WHERE %s = %d;\n" - % ( - table, - item["column"], - val, - dbInfo.GetKeyColumn(layer), - cat, + with tempfile.NamedTemporaryFile(mode="w") as sqlfile: + for fid in fids: + for layer, cats in self.digit.GetLineCats(fid).items(): + table = dbInfo.GetTable(layer) + for attrb, item in vdigit["geomAttr"].items(): + val = -1 + if attrb == "length": + val = self.digit.GetLineLength(fid) + type = attrb + elif attrb == "area": + val = self.digit.GetAreaSize(fid) + type = attrb + elif attrb == "perimeter": + val = self.digit.GetAreaPerimeter(fid) + type = "length" + if val < 0: + continue + val = UnitsConvertValue(val, type, item["units"]) + for cat in cats: + sqlfile.write( + "UPDATE %s SET %s = %f WHERE %s = %d;\n" + % ( + table, + item["column"], + val, + dbInfo.GetKeyColumn(layer), + cat, + ) ) - ) - - sqlfile.file.flush() - RunCommand("db.execute", parent=True, quiet=True, input=sqlfile.name) + sqlfile.file.flush() + RunCommand("db.execute", parent=True, quiet=True, input=sqlfile.name) def _updateATM(self): """Update open Attribute Table Manager diff --git a/gui/wxpython/vnet/vnet_core.py b/gui/wxpython/vnet/vnet_core.py index b019256bb75..cb1df07441d 100644 --- a/gui/wxpython/vnet/vnet_core.py +++ b/gui/wxpython/vnet/vnet_core.py @@ -20,6 +20,8 @@ """ import math +from pathlib import Path + from grass.script.utils import try_remove from grass.script import core as grass from grass.script.task import cmdlist_to_tuple @@ -449,9 +451,7 @@ def _vnetPathRunAn(self, analysis, output, params, flags, catPts): ) self.coordsTmpFile = grass.tempfile() - coordsTmpFileOpened = open(self.coordsTmpFile, "w") - coordsTmpFileOpened.write(inpPoints) - coordsTmpFileOpened.close() + Path(self.coordsTmpFile).write_text(inpPoints) if flags["t"]: cmdParams.append("-t") @@ -579,28 +579,26 @@ def _updateTtbByGlobalCosts(self, vectMapName, tlayer): driver, database = dbInfo.GetDbSettings(tlayer) sqlFile = grass.tempfile() - sqlFile_f = open(sqlFile, "w") - - for ival in intervals: - from_angle = ival[0] - to_angle = ival[1] - cost = ival[2] - - if to_angle < from_angle: - to_angle = math.pi * 2 + to_angle - # if angle < from_angle: - # angle = math.pi * 2 + angle - - where = ( - " WHERE (((angle < {0}) AND ({2} + angle >= {0} AND {2} + angle < {1}))" - " OR ((angle >= {0}) AND (angle >= {0} AND angle < {1})))" - " AND cost==0.0 " - ).format(str(from_angle), str(to_angle), str(math.pi * 2)) - - stm = ("UPDATE %s SET cost=%f " % (table, cost)) + where + ";\n" - sqlFile_f.write(stm) - - sqlFile_f.close() + with open(sqlFile, "w") as sqlFile_f: + for ival in intervals: + from_angle = ival[0] + to_angle = ival[1] + cost = ival[2] + + if to_angle < from_angle: + to_angle = math.pi * 2 + to_angle + # if angle < from_angle: + # angle = math.pi * 2 + angle + + where = ( + " WHERE" + " (((angle < {0}) AND ({2} + angle >= {0} AND {2} + angle < {1}))" + " OR ((angle >= {0}) AND (angle >= {0} AND angle < {1})))" + " AND cost==0.0 " + ).format(str(from_angle), str(to_angle), str(math.pi * 2)) + + stm = ("UPDATE %s SET cost=%f " % (table, cost)) + where + ";\n" + sqlFile_f.write(stm) # TODO improve parser and run in thread @@ -671,9 +669,7 @@ def _runAn(self, analysis, output, params, flags, catPts): # TODO better tmp files cleanup (make class for managing tmp files) self.tmpPtsAsciiFile = grass.tempfile() - tmpPtsAsciiFileOpened = open(self.tmpPtsAsciiFile, "w") - tmpPtsAsciiFileOpened.write(pt_ascii) - tmpPtsAsciiFileOpened.close() + Path(self.tmpPtsAsciiFile).write_text(pt_ascii) self.tmpInPts = AddTmpMapAnalysisMsg("vnet_tmp_in_pts", self.tmp_maps) if not self.tmpInPts: diff --git a/gui/wxpython/vnet/vnet_data.py b/gui/wxpython/vnet/vnet_data.py index 9dd1bff4f66..e8e05839e70 100644 --- a/gui/wxpython/vnet/vnet_data.py +++ b/gui/wxpython/vnet/vnet_data.py @@ -1144,15 +1144,11 @@ def SaveHistStep(self): self.currHistStep = 0 newHistFile = grass.tempfile() - newHist = open(newHistFile, "w") + with open(newHistFile, "w") as newHist: + self._saveNewHistStep(newHist) + with open(self.histFile) as oldHist: + removedHistData = self._savePreviousHist(newHist, oldHist) - self._saveNewHistStep(newHist) - - oldHist = open(self.histFile) - removedHistData = self._savePreviousHist(newHist, oldHist) - - oldHist.close() - newHist.close() try_remove(self.histFile) self.histFile = newHistFile @@ -1275,27 +1271,25 @@ def _castValue(self, value): def _getHistStepData(self, histStep): """Load data saved in history step""" - hist = open(self.histFile) histStepData = {} - newHistStep = False isSearchedHistStep = False - for line in hist: - if not line.strip() and isSearchedHistStep: - break - if not line.strip(): - newHistStep = True - continue - if isSearchedHistStep: - self._parseLine(line, histStepData) + with open(self.histFile) as hist: + for line in hist: + if not line.strip() and isSearchedHistStep: + break + if not line.strip(): + newHistStep = True + continue + if isSearchedHistStep: + self._parseLine(line, histStepData) - if newHistStep: - line = line.split("=") - if int(line[1]) == histStep: - isSearchedHistStep = True - newHistStep = False + if newHistStep: + line = line.split("=") + if int(line[1]) == histStep: + isSearchedHistStep = True + newHistStep = False - hist.close() return histStepData def _parseLine(self, line, histStepData): diff --git a/gui/wxpython/vnet/widgets.py b/gui/wxpython/vnet/widgets.py index d8926f96fae..d5a0964a5ac 100644 --- a/gui/wxpython/vnet/widgets.py +++ b/gui/wxpython/vnet/widgets.py @@ -439,21 +439,15 @@ def OnItemSelected(self, event): def getSmallUpArrowImage(self): """Get arrow up symbol for indication of sorting""" - stream = open(os.path.join(globalvar.IMGDIR, "small_up_arrow.png"), "rb") - try: - img = wx.Image(stream) - finally: - stream.close() - return img + with open(os.path.join(globalvar.IMGDIR, "small_up_arrow.png"), "rb") as stream: + return wx.Image(stream) def getSmallDnArrowImage(self): """Get arrow down symbol for indication of sorting""" - stream = open(os.path.join(globalvar.IMGDIR, "small_down_arrow.png"), "rb") - try: - img = wx.Image(stream) - finally: - stream.close() - return img + with open( + os.path.join(globalvar.IMGDIR, "small_down_arrow.png"), "rb" + ) as stream: + return wx.Image(stream) def _getColumnNum(self, colName): """Get position of column among showed columns diff --git a/pyproject.toml b/pyproject.toml index 1df103b1bad..dc37688511e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -269,41 +269,35 @@ ignore = [ "**.py" = ["PYI066"] "*/testsuite/**.py" = ["PT009", "PT027"] "display/d.mon/render_cmd.py" = ["SIM115"] -"gui/wxpython/animation/temporal_manager.py" = ["SIM115"] -"gui/wxpython/core/*.py" = ["SIM115"] "gui/wxpython/core/globalvar.py" = ["PTH208"] -"gui/wxpython/core/settings.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", "SIM115"] -"gui/wxpython/gmodeler/*.py" = ["SIM115"] -"gui/wxpython/gui_core/*.py" = ["SIM115"] +"gui/wxpython/gcp/manager.py" = ["PTH208"] +"gui/wxpython/gmodeler/panels.py" = ["SIM115"] "gui/wxpython/gui_core/dialogs.py" = ["PTH208"] +"gui/wxpython/gui_core/forms.py" = ["SIM115"] +"gui/wxpython/gui_core/goutput.py" = ["SIM115"] +"gui/wxpython/gui_core/widgets.py" = ["SIM115"] "gui/wxpython/iclass/frame.py" = ["FLY002", "SIM115"] "gui/wxpython/iclass/statistics.py" = ["A005"] "gui/wxpython/icons/grass_icons.py" = ["PTH208"] -"gui/wxpython/image2target/*.py" = ["SIM115"] -"gui/wxpython/image2target/ii2t_manager.py" = ["PTH208"] -"gui/wxpython/lmgr/workspace.py" = ["SIM115"] -"gui/wxpython/location_wizard/wizard.py" = ["SIM115"] +"gui/wxpython/image2target/ii2t_manager.py" = ["PTH208", "SIM115"] "gui/wxpython/mapdisp/main.py" = ["SIM115"] "gui/wxpython/modules/colorrules.py" = ["SIM115"] "gui/wxpython/modules/mcalc_builder.py" = ["SIM115"] "gui/wxpython/photo2image/ip2i_manager.py" = ["SIM115"] "gui/wxpython/psmap/dialogs.py" = ["PTH208"] -"gui/wxpython/psmap/frame.py" = ["SIM115"] "gui/wxpython/psmap/instructions.py" = ["SIM115"] "gui/wxpython/psmap/utils.py" = ["PGH004"] -"gui/wxpython/rdigit/controller.py" = ["SIM115"] -"gui/wxpython/rlisetup/*.py" = ["SIM115"] "gui/wxpython/rlisetup/frame.py" = ["PTH208"] "gui/wxpython/timeline/frame.py" = ["FLY002"] "gui/wxpython/tools/update_menudata.py" = ["SIM115"] "gui/wxpython/tplot/frame.py" = ["FLY002"] -"gui/wxpython/vdigit/mapwindow.py" = ["SIM115"] -"gui/wxpython/vnet/vnet_core.py" = ["SIM115"] "gui/wxpython/vnet/vnet_data.py" = ["SIM115"] -"gui/wxpython/vnet/widgets.py" = ["SIM115"] "gui/wxpython/web_services/dialogs.py" = ["SIM115"] "gui/wxpython/wxplot/profile.py" = ["A005", "SIM115"] "imagery/i.atcorr/create_iwave.py" = ["SIM115"]