[GRASS-dev] [GRASS GIS] #3637: Use the system temporary directory for all GUI rendering files

#3637: Use the system temporary directory for all GUI rendering files
-------------------------------------------------+-------------------------
Reporter: wenzeslaus | Owner: grass-dev@…
     Type: defect | Status: assigned
Priority: minor | Milestone: 8.0.0
Component: wxGUI | Version: svn-trunk
Keywords: rendering PPM g.pnmcomp tempfile | CPU: Unspecified
  NamedTemporaryFile |
Platform: Unspecified |
-------------------------------------------------+-------------------------
wxGUI uses standard Python `tempfile.NamedTemporaryFile` for rendering a
single layer (`GRASS_RENDER_FILE`):

{{{
             mapfile = tempfile.NamedTemporaryFile(
                 suffix=tempfile_sfx, delete=False)
             # we don't want it open, we just need the name
             self.mapfile = mapfile.name
             mapfile.close()
             os.remove(self.mapfile) # remove empty file

         self.maskfile = self.mapfile.rsplit(".", 1)[0] + ".pgm"
}}}

However, it uses GRASS GIS `grass.script.tempfile` for vector legend files
and `g.pnmcomp` output:

{{{
         if self.type in ('vector', 'thememap'):
             self._legrow = grass.tempfile(create=True)
...
         # generated file for g.pnmcomp output for rendering the map
         self.legfile = grass.tempfile(create=False) + '.leg'
         self.tmpdir = os.path.dirname(self.legfile) # looks unused (?)
         self.mapfile = grass.tempfile(create=False) + '.ppm'
}}}

source:grass/trunk/gui/wxpython/core/render.py

The render command (from WX_DEBUG, edited):

{{{
GUI D1/5: RenderLayerMgr.Render(d.rast
map=boundary_county_500m@PERMANENT):
           force=1 img=/tmp/grass7-vpetras-23526/tmpNqGsdb.ppm

GUI D1/5: gcmd.RunCommand(): g.pnmcomp --o opacity=1.0 width=823
           mask=/tmp/grass7-$USER-23526/tmpNqGsdb.pgm
           height=502 bgcolor=255:255:255:255
           input=/tmp/grass7-$USER-23526/tmpNqGsdb.ppm
output=/home/$USER/grassdata/nc_spm/a1/.tmp/$HOSTNAME/24140.0.ppm
}}}

`tempfile.NamedTemporaryFile` refers to `tempfile.TemporaryFile` which
refers to `tempfile.mkstemp` which says:

> The default directory is chosen from a platform-dependent list, but the
user of the application can control the directory location by setting the
`TMPDIR`, `TEMP` or `TMP` environment variables.

The order is not explicitly guaranteed in the documentation, but the
behavior on Linux with Python 2.7 is that `TMPDIR` is picked over `TMP`
which is the behavior we want. If that would change, but we wanted to
preserve the same behavior, there is a `dir` parameter which specified the
directory.

My intention is to use `tempfile.NamedTemporaryFile` for everything.

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/3637&gt;
GRASS GIS <https://grass.osgeo.org>

#3637: Use the system temporary directory for all GUI rendering files
-------------------------+-------------------------------------------------
  Reporter: wenzeslaus | Owner: grass-dev@…
      Type: defect | Status: closed
  Priority: minor | Milestone: 8.0.0
Component: wxGUI | Version: svn-trunk
Resolution: fixed | Keywords: rendering PPM g.pnmcomp tempfile
       CPU: | NamedTemporaryFile
  Unspecified | Platform: Unspecified
-------------------------+-------------------------------------------------
Changes (by wenzeslaus):

* status: assigned => closed
* resolution: => fixed

Comment:

In [changeset:"73334" 73334]:
{{{
#!CommitTicketReference repository="" revision="73334"
wxGUI/core: replace grass.script.tempfile by tempfile.NamedTemporaryFile
(fixes #3637)

Switches from mapset temporary directory to system temporary
directory which was previously set up for the session for
all GUI rendering files.

This also refactors and unifies handling of the temporary files related
to rendering, although on error and when removing/deleting the layers
removing of the files happens in the same way as before.

All files are now using NamedTemporaryFile instead of some using
g.tempfile and some NamedTemporaryFile. This means that when mapset
is switched, files are present in the (correct) session directory,
not incorrect mapset directory and then not deleted later.
(Deleting these files could cause rendering errors, while not deleting
them would lead to accumulating of files in mapset temporary directory).

See also:
  * r28605 which adds glob for one delete when core.utils.GetTempfile(),
    i.e., g.tempfile was still used (the glob part is still there)
  * r56444 which adds mkstemp() for some of the files
  * r60947 attempt to fix cleaning of deleting temporary files (#560)
    which changes mkstemp to NamedTemporaryFile (still used now)
  * r69085 which checked legend row file (legrow) name of last character
    being digit (isdigit()) which was true for files from g.tempfile
    but does not seem to have a reason (removed now)
  * #3635 which investigates a suspicious cleanups of mapset temporary
    directory which at this point seemed to be cleaning rendering files
    from GUI (r37863, r21048)
}}}

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/3637#comment:1&gt;
GRASS GIS <https://grass.osgeo.org>

#3637: Use the system temporary directory for all GUI rendering files
-------------------------+-------------------------------------------------
  Reporter: wenzeslaus | Owner: grass-dev@…
      Type: defect | Status: closed
  Priority: minor | Milestone: 8.0.0
Component: wxGUI | Version: svn-trunk
Resolution: fixed | Keywords: rendering PPM g.pnmcomp tempfile
       CPU: | NamedTemporaryFile
  Unspecified | Platform: Unspecified
-------------------------+-------------------------------------------------

Comment (by wenzeslaus):

I tested the rendering with rasters, vectors and vector legend and it
works including checking and unchecking. A debug output (WX_DEBUG=5,
edited) after pressing ''Render map'' button is below showing only files
in the session temporary directory which is in the system temporary
directory (here /tmp).

{{{
GUI D3/5: Layer.Render(): type=overlay, name=vectleg,
           file=/tmp/grass7-$USER-11834/tmp0v6vpY.png
GUI D1/5: RenderLayerMgr.Render(d.legend.vect at=20.0,80.0):
           force=0 img=/tmp/grass7-$USER-11834/tmp0v6vpY.png
GUI D3/5: Layer.Render(): type=raster, name=aspect@PERMANENT,
           file=/tmp/grass7-$USER-11834/tmpmpjTAK.ppm
GUI D1/5: RenderLayerMgr.Render(d.rast map=aspect@PERMANENT):
           force=0 img=/tmp/grass7-$USER-11834/tmpmpjTAK.ppm
GUI D3/5: Layer.Render(): type=vector, name=bridges@PERMANENT,
           file=/tmp/grass7-$USER-11834/tmpY1Ns6j.ppm
GUI D1/5: RenderLayerMgr.Render(d.vect map=bridges@PERMANENT width=1):
           force=0 img=/tmp/grass7-$USER-11834/tmpY1Ns6j.ppm
...
GUI D1/5: gcmd.RunCommand(): g.pnmcomp --o opacity=1.0,1.0 width=825
mask=/tmp/grass7-$USER-11834/tmpmpjTAK.pgm,/tmp/grass7-$USER-11834/tmpY1Ns6j.pgm
           height=572 bgcolor=255:255:255
input=/tmp/grass7-$USER-11834/tmpmpjTAK.ppm,/tmp/grass7-$USER-11834/tmpY1Ns6j.ppm
           output=/tmp/grass7-$USER-11834/tmpSwtqYx.ppm
}}}

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/3637#comment:2&gt;
GRASS GIS <https://grass.osgeo.org>