2014-04-19 15:53:43 +02:00
# -*- coding: utf-8 -*-
"""
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
GrassUtils . py
- - - - - - - - - - - - - - - - - - - - -
2015-02-07 21:53:30 +01:00
Date : February 2015
Copyright : ( C ) 2014 - 2015 by Victor Olaya
2014-04-19 15:53:43 +02:00
Email : volayaf at gmail dot com
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* This program is free software ; you can redistribute it and / or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation ; either version 2 of the License , or *
* ( at your option ) any later version . *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
"""
__author__ = ' Victor Olaya '
2015-02-07 21:53:30 +01:00
__date__ = ' February 2015 '
__copyright__ = ' (C) 2014-2015, Victor Olaya '
2014-04-19 15:53:43 +02:00
import stat
import shutil
2017-10-26 16:09:46 +02:00
import shlex
2014-04-19 15:53:43 +02:00
import subprocess
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
import os
2019-03-05 09:53:56 +10:00
import sys
2017-04-24 14:35:50 +10:00
2018-02-05 22:11:34 -04:00
from qgis . core import ( Qgis ,
QgsApplication ,
2017-04-24 14:35:50 +10:00
QgsProcessingUtils ,
QgsMessageLog )
2016-04-22 10:38:48 +02:00
from qgis . PyQt . QtCore import QCoreApplication
2014-04-19 15:53:43 +02:00
from processing . core . ProcessingConfig import ProcessingConfig
2017-06-21 18:23:45 +10:00
from processing . tools . system import userFolder , isWindows , isMac , mkdir
2014-04-19 15:53:43 +02:00
from processing . tests . TestData import points
2017-11-05 13:18:24 +01:00
from processing . algs . gdal . GdalUtils import GdalUtils
2014-04-19 15:53:43 +02:00
2017-11-27 13:23:49 +02:00
class Grass7Utils :
2014-04-19 15:53:43 +02:00
2014-04-19 17:36:14 +02:00
GRASS_REGION_XMIN = ' GRASS7_REGION_XMIN '
GRASS_REGION_YMIN = ' GRASS7_REGION_YMIN '
GRASS_REGION_XMAX = ' GRASS7_REGION_XMAX '
GRASS_REGION_YMAX = ' GRASS7_REGION_YMAX '
GRASS_REGION_CELLSIZE = ' GRASS7_REGION_CELLSIZE '
2014-04-19 15:53:43 +02:00
GRASS_FOLDER = ' GRASS7_FOLDER '
2014-04-19 17:36:14 +02:00
GRASS_LOG_COMMANDS = ' GRASS7_LOG_COMMANDS '
GRASS_LOG_CONSOLE = ' GRASS7_LOG_CONSOLE '
2017-01-09 15:32:42 +02:00
GRASS_HELP_PATH = ' GRASS_HELP_PATH '
2017-10-22 10:25:09 +02:00
GRASS_USE_VEXTERNAL = ' GRASS_USE_VEXTERNAL '
2014-04-19 15:53:43 +02:00
2017-11-05 13:18:24 +01:00
# TODO Review all default options formats
GRASS_RASTER_FORMATS_CREATEOPTS = {
' GTiff ' : ' TFW=YES,COMPRESS=LZW ' ,
' PNG ' : ' ZLEVEL=9 ' ,
' WEBP ' : ' QUALITY=85 '
}
2014-04-19 15:53:43 +02:00
sessionRunning = False
sessionLayers = { }
projectionSet = False
2017-10-26 16:09:46 +02:00
isGrassInstalled = False
2014-04-19 15:53:43 +02:00
2016-12-29 15:16:37 +02:00
version = None
2017-10-26 16:09:46 +02:00
path = None
2017-04-04 13:56:26 +10:00
command = None
2014-04-19 15:53:43 +02:00
@staticmethod
def grassBatchJobFilename ( ) :
2017-10-26 16:09:46 +02:00
"""
The Batch file is executed by GRASS binary .
On GNU / Linux and MacOSX it will be executed by a shell .
On MS - Windows , it will be executed by cmd . exe .
"""
gisdbase = Grass7Utils . grassDataFolder ( )
if isWindows ( ) :
batchFile = os . path . join ( gisdbase , ' grass_batch_job.cmd ' )
else :
batchFile = os . path . join ( gisdbase , ' grass_batch_job.sh ' )
return batchFile
2014-04-19 15:53:43 +02:00
@staticmethod
2016-12-29 15:16:37 +02:00
def installedVersion ( run = False ) :
2017-10-26 16:09:46 +02:00
"""
Returns the installed version of GRASS by
launching the GRASS command with - v parameter .
"""
if Grass7Utils . isGrassInstalled and not run :
2016-12-29 15:16:37 +02:00
return Grass7Utils . version
2017-10-26 16:09:46 +02:00
if Grass7Utils . grassBin ( ) is None :
2016-12-29 15:16:37 +02:00
return None
2017-10-26 16:09:46 +02:00
# Launch GRASS command with -v parameter
# For MS-Windows, hide the console
if isWindows ( ) :
si = subprocess . STARTUPINFO ( )
si . dwFlags | = subprocess . STARTF_USESHOWWINDOW
si . wShowWindow = subprocess . SW_HIDE
with subprocess . Popen (
[ Grass7Utils . command , ' -v ' ] ,
2018-10-31 20:55:56 -05:00
shell = False ,
2017-01-25 00:49:55 +01:00
stdout = subprocess . PIPE ,
stdin = subprocess . DEVNULL ,
stderr = subprocess . STDOUT ,
universal_newlines = True ,
2017-10-26 16:09:46 +02:00
startupinfo = si if isWindows ( ) else None
) as proc :
try :
lines = proc . stdout . readlines ( )
for line in lines :
if " GRASS GIS " in line :
line = line . split ( " " ) [ - 1 ] . strip ( )
if line . startswith ( " 7. " ) :
Grass7Utils . version = line
return Grass7Utils . version
except :
pass
2017-01-25 00:49:55 +01:00
return None
2017-10-26 16:09:46 +02:00
@staticmethod
def grassBin ( ) :
"""
Find GRASS binary path on the operating system .
Sets global variable Grass7Utils . command
"""
def searchFolder ( folder ) :
"""
Inline function to search for grass binaries into a folder
with os . walk
"""
if os . path . exists ( folder ) :
for root , dirs , files in os . walk ( folder ) :
for cmd in cmdList :
if cmd in files :
2018-03-26 16:22:44 +10:00
return os . path . join ( root , cmd )
return None
2017-10-26 16:09:46 +02:00
if Grass7Utils . command :
return Grass7Utils . command
path = Grass7Utils . grassPath ( )
command = None
2019-01-29 21:33:48 +01:00
vn = os . path . join ( path , " etc " , " VERSIONNUMBER " )
if os . path . isfile ( vn ) :
with open ( vn , " r " ) as f :
major , minor , patch = f . readlines ( ) [ 0 ] . split ( ' ' ) [ 0 ] . split ( ' . ' )
if patch != ' svn ' :
patch = ' '
cmdList = [
" grass {} {} {} " . format ( major , minor , patch ) ,
" grass " ,
" grass {} {} {} .sh " . format ( major , minor , patch ) ,
" grass.sh "
]
else :
cmdList = [
" grass76 " , " grass74 " , " grass72 " , " grass70 " , " grass " ,
" grass76.sh " , " grass74.sh " , " grass72.sh " , " grass70.sh " , " grass.sh "
]
2017-10-26 16:09:46 +02:00
# For MS-Windows there is a difference between GRASS Path and GRASS binary
if isWindows ( ) :
# If nothing found, use OSGEO4W or QgsPrefix:
if " OSGEO4W_ROOT " in os . environ :
testFolder = str ( os . environ [ ' OSGEO4W_ROOT ' ] )
else :
testFolder = str ( QgsApplication . prefixPath ( ) )
testFolder = os . path . join ( testFolder , ' bin ' )
command = searchFolder ( testFolder )
elif isMac ( ) :
# Search in grassPath
command = searchFolder ( path )
2019-01-29 21:33:48 +01:00
# If everything has failed, use shutil
2017-10-26 16:09:46 +02:00
if not command :
for cmd in cmdList :
testBin = shutil . which ( cmd )
if testBin :
command = os . path . abspath ( testBin )
break
if command :
Grass7Utils . command = command
if path is ' ' :
Grass7Utils . path = os . path . dirname ( command )
return command
2014-04-19 15:53:43 +02:00
@staticmethod
def grassPath ( ) :
2017-10-26 16:09:46 +02:00
"""
Find GRASS path on the operating system .
Sets global variable Grass7Utils . path
"""
if Grass7Utils . path is not None :
return Grass7Utils . path
2014-04-19 15:53:43 +02:00
if not isWindows ( ) and not isMac ( ) :
return ' '
2017-10-22 10:25:09 +02:00
2018-11-10 16:28:22 +01:00
if isMac ( ) :
folder = ProcessingConfig . getSetting ( Grass7Utils . GRASS_FOLDER ) or ' '
if not os . path . exists ( folder ) :
folder = None
else :
2016-04-04 13:23:45 +02:00
folder = None
2017-10-22 10:25:09 +02:00
2014-04-19 15:53:43 +02:00
if folder is None :
2017-10-26 16:09:46 +02:00
# Under MS-Windows, we use OSGEO4W or QGIS Path for folder
2014-04-19 15:53:43 +02:00
if isWindows ( ) :
2019-01-29 21:33:48 +01:00
if " GISBASE " in os . environ :
folder = os . environ [ " GISBASE " ]
2016-03-31 22:51:35 +02:00
else :
2019-02-24 23:01:18 +01:00
testfolder = os . path . join ( os . path . dirname ( QgsApplication . prefixPath ( ) ) , ' grass ' )
2019-01-29 21:33:48 +01:00
if os . path . isdir ( testfolder ) :
grassfolders = sorted ( [ f for f in os . listdir ( testfolder ) if f . startswith ( " grass-7. " ) and os . path . isdir ( os . path . join ( testfolder , f ) ) ] , reverse = True , key = lambda x : [ int ( v ) for v in x [ len ( " grass- " ) : ] . split ( ' . ' ) if v != ' svn ' ] )
if grassfolders :
folder = os . path . join ( testfolder , grassfolders [ 0 ] )
2017-10-26 16:09:46 +02:00
elif isMac ( ) :
# For MacOSX, we scan some well-known directories
# Start with QGIS bundle
2019-02-19 08:59:29 +02:00
for version in [ ' ' , ' 7 ' , ' 76 ' , ' 74 ' , ' 72 ' , ' 71 ' , ' 70 ' ] :
2017-10-26 16:09:46 +02:00
testfolder = os . path . join ( str ( QgsApplication . prefixPath ( ) ) ,
' grass {} ' . format ( version ) )
if os . path . isdir ( testfolder ) :
folder = testfolder
2017-09-04 16:31:31 +02:00
break
2017-10-26 16:09:46 +02:00
# If nothing found, try standalone GRASS installation
if folder is None :
2019-02-19 08:59:29 +02:00
for version in [ ' 6 ' , ' 4 ' , ' 2 ' , ' 1 ' , ' 0 ' ] :
2017-10-26 16:09:46 +02:00
testfolder = ' /Applications/GRASS-7. {} .app/Contents/MacOS ' . format ( version )
if os . path . isdir ( testfolder ) :
folder = testfolder
break
if folder is not None :
Grass7Utils . path = folder
2014-04-19 15:53:43 +02:00
2016-03-31 23:02:06 +02:00
return folder or ' '
2014-04-19 15:53:43 +02:00
@staticmethod
def grassDescriptionPath ( ) :
return os . path . join ( os . path . dirname ( __file__ ) , ' description ' )
@staticmethod
2017-10-26 16:09:46 +02:00
def getWindowsCodePage ( ) :
"""
Determines MS - Windows CMD . exe shell codepage .
Used into GRASS exec script under MS - Windows .
"""
from ctypes import cdll
return str ( cdll . kernel32 . GetACP ( ) )
2014-04-19 15:53:43 +02:00
@staticmethod
2017-10-26 16:09:46 +02:00
def createGrassBatchJobFileFromGrassCommands ( commands ) :
2016-07-02 14:06:53 +02:00
with open ( Grass7Utils . grassBatchJobFilename ( ) , ' w ' ) as fout :
2017-10-26 16:09:46 +02:00
if not isWindows ( ) :
fout . write ( ' #!/bin/sh \n ' )
else :
fout . write ( ' chcp {} >NUL \n ' . format ( Grass7Utils . getWindowsCodePage ( ) ) )
2016-07-02 14:06:53 +02:00
for command in commands :
Grass7Utils . writeCommand ( fout , command )
fout . write ( ' exit ' )
2014-04-19 15:53:43 +02:00
@staticmethod
def grassMapsetFolder ( ) :
2017-10-26 16:09:46 +02:00
"""
Creates and returns the GRASS temporary DB LOCATION directory .
"""
2014-04-19 15:53:43 +02:00
folder = os . path . join ( Grass7Utils . grassDataFolder ( ) , ' temp_location ' )
mkdir ( folder )
return folder
@staticmethod
def grassDataFolder ( ) :
2017-10-26 16:09:46 +02:00
"""
Creates and returns the GRASS temporary DB directory .
"""
tempfolder = os . path . normpath (
os . path . join ( QgsProcessingUtils . tempFolder ( ) , ' grassdata ' ) )
2014-04-19 15:53:43 +02:00
mkdir ( tempfolder )
return tempfolder
@staticmethod
def createTempMapset ( ) :
2017-10-26 16:09:46 +02:00
"""
Creates a temporary location and mapset ( s ) for GRASS data
2014-04-19 15:53:43 +02:00
processing . A minimal set of folders and files is created in the
system ' s default temporary directory. The settings files are
written with sane defaults , so GRASS can do its work . The mapset
projection will be set later , based on the projection of the first
input image or vector
2017-10-26 16:09:46 +02:00
"""
2014-04-19 15:53:43 +02:00
folder = Grass7Utils . grassMapsetFolder ( )
mkdir ( os . path . join ( folder , ' PERMANENT ' ) )
mkdir ( os . path . join ( folder , ' PERMANENT ' , ' .tmp ' ) )
2017-10-26 16:09:46 +02:00
Grass7Utils . writeGrassWindow ( os . path . join ( folder , ' PERMANENT ' , ' DEFAULT_WIND ' ) )
2016-11-07 10:35:15 +10:00
with open ( os . path . join ( folder , ' PERMANENT ' , ' MYNAME ' ) , ' w ' ) as outfile :
outfile . write (
' QGIS GRASS GIS 7 interface: temporary data processing location. \n ' )
2014-04-19 15:53:43 +02:00
2017-10-26 16:09:46 +02:00
Grass7Utils . writeGrassWindow ( os . path . join ( folder , ' PERMANENT ' , ' WIND ' ) )
2015-02-07 23:35:35 +01:00
mkdir ( os . path . join ( folder , ' PERMANENT ' , ' sqlite ' ) )
2016-11-07 10:35:15 +10:00
with open ( os . path . join ( folder , ' PERMANENT ' , ' VAR ' ) , ' w ' ) as outfile :
outfile . write ( ' DB_DRIVER: sqlite \n ' )
outfile . write ( ' DB_DATABASE: $GISDBASE/$LOCATION_NAME/$MAPSET/sqlite/sqlite.db \n ' )
2014-04-19 15:53:43 +02:00
@staticmethod
2017-10-26 16:09:46 +02:00
def writeGrassWindow ( filename ) :
"""
Creates the GRASS Window file
"""
2016-11-07 10:35:15 +10:00
with open ( filename , ' w ' ) as out :
out . write ( ' proj: 0 \n ' )
out . write ( ' zone: 0 \n ' )
out . write ( ' north: 1 \n ' )
out . write ( ' south: 0 \n ' )
out . write ( ' east: 1 \n ' )
out . write ( ' west: 0 \n ' )
out . write ( ' cols: 1 \n ' )
out . write ( ' rows: 1 \n ' )
out . write ( ' e-w resol: 1 \n ' )
out . write ( ' n-s resol: 1 \n ' )
out . write ( ' top: 1 \n ' )
out . write ( ' bottom: 0 \n ' )
out . write ( ' cols3: 1 \n ' )
out . write ( ' rows3: 1 \n ' )
out . write ( ' depths: 1 \n ' )
out . write ( ' e-w resol3: 1 \n ' )
out . write ( ' n-s resol3: 1 \n ' )
out . write ( ' t-b resol: 1 \n ' )
2014-04-19 15:53:43 +02:00
@staticmethod
2017-10-26 16:09:46 +02:00
def prepareGrassExecution ( commands ) :
"""
Prepare GRASS batch job in a script and
returns it as a command ready for subprocess .
"""
2018-09-13 17:15:21 +02:00
if Grass7Utils . command is None :
Grass7Utils . grassBin ( )
2015-08-20 01:10:43 +02:00
env = os . environ . copy ( )
2017-10-26 16:09:46 +02:00
env [ ' GRASS_MESSAGE_FORMAT ' ] = ' plain '
if ' GISBASE ' in env :
del env [ ' GISBASE ' ]
Grass7Utils . createGrassBatchJobFileFromGrassCommands ( commands )
os . chmod ( Grass7Utils . grassBatchJobFilename ( ) , stat . S_IEXEC | stat . S_IREAD | stat . S_IWRITE )
command = [ Grass7Utils . command ,
os . path . join ( Grass7Utils . grassMapsetFolder ( ) , ' PERMANENT ' ) ,
' --exec ' , Grass7Utils . grassBatchJobFilename ( ) ]
2014-04-19 15:53:43 +02:00
2015-08-20 01:10:43 +02:00
return command , env
2014-04-19 15:53:43 +02:00
@staticmethod
2017-10-26 16:09:46 +02:00
def executeGrass ( commands , feedback , outputCommands = None ) :
2014-04-19 15:53:43 +02:00
loglines = [ ]
2015-01-16 15:56:05 +02:00
loglines . append ( Grass7Utils . tr ( ' GRASS GIS 7 execution console output ' ) )
2014-04-19 15:53:43 +02:00
grassOutDone = False
2017-10-26 16:09:46 +02:00
command , grassenv = Grass7Utils . prepareGrassExecution ( commands )
2018-11-11 01:24:09 +01:00
# QgsMessageLog.logMessage('exec: {}'.format(command), 'DEBUG', Qgis.Info)
2017-10-26 16:09:46 +02:00
# For MS-Windows, we need to hide the console window.
2019-03-05 09:53:56 +10:00
kw = { }
2017-10-26 16:09:46 +02:00
if isWindows ( ) :
si = subprocess . STARTUPINFO ( )
si . dwFlags | = subprocess . STARTF_USESHOWWINDOW
si . wShowWindow = subprocess . SW_HIDE
2019-03-05 09:53:56 +10:00
kw [ ' startupinfo ' ] = si
if sys . version_info > = ( 3 , 6 ) :
kw [ ' encoding ' ] = " cp {} " . format ( Grass7Utils . getWindowsCodePage ( ) )
2017-10-26 16:09:46 +02:00
2016-11-23 21:58:58 +01:00
with subprocess . Popen (
2017-10-26 16:09:46 +02:00
command ,
2018-10-31 20:55:56 -05:00
shell = False ,
2017-10-26 16:09:46 +02:00
stdout = subprocess . PIPE ,
stdin = subprocess . DEVNULL ,
stderr = subprocess . STDOUT ,
universal_newlines = True ,
env = grassenv ,
2019-03-05 09:53:56 +10:00
* * kw
2016-11-23 21:58:58 +01:00
) as proc :
for line in iter ( proc . stdout . readline , ' ' ) :
if ' GRASS_INFO_PERCENT ' in line :
try :
2017-01-06 20:04:00 +10:00
feedback . setProgress ( int ( line [ len ( ' GRASS_INFO_PERCENT ' ) + 2 : ] ) )
2016-11-23 21:58:58 +01:00
except :
pass
else :
if ' r.out ' in line or ' v.out ' in line :
grassOutDone = True
loglines . append ( line )
2018-11-01 07:25:44 +10:00
if any ( [ l in line for l in [ ' WARNING ' , ' ERROR ' ] ] ) :
feedback . reportError ( line . strip ( ) )
elif ' Segmentation fault ' in line :
feedback . reportError ( line . strip ( ) )
feedback . reportError ( ' \n ' + Grass7Utils . tr ( ' GRASS command crashed :( Try a different set of input parameters and consult the GRASS algorithm manual for more information. ' ) + ' \n ' )
if ProcessingConfig . getSetting ( Grass7Utils . GRASS_USE_VEXTERNAL ) :
feedback . reportError ( Grass7Utils . tr (
' Suggest disabling the experimental " use v.external " option from the Processing GRASS Provider options. ' ) + ' \n ' )
elif line . strip ( ) :
feedback . pushConsoleInfo ( line . strip ( ) )
2014-04-19 15:53:43 +02:00
# Some GRASS scripts, like r.mapcalculator or r.fillnulls, call
# other GRASS scripts during execution. This may override any
# commands that are still to be executed by the subprocess, which
# are usually the output ones. If that is the case runs the output
# commands again.
if not grassOutDone and outputCommands :
2017-10-26 16:09:46 +02:00
command , grassenv = Grass7Utils . prepareGrassExecution ( outputCommands )
2018-11-27 10:17:02 +01:00
# For MS-Windows, we need to hide the console window.
2019-03-05 09:53:56 +10:00
kw = { }
2018-11-27 10:17:02 +01:00
if isWindows ( ) :
si = subprocess . STARTUPINFO ( )
si . dwFlags | = subprocess . STARTF_USESHOWWINDOW
si . wShowWindow = subprocess . SW_HIDE
2019-03-05 09:53:56 +10:00
kw [ ' startupinfo ' ] = si
if sys . version_info > = ( 3 , 6 ) :
kw [ ' encoding ' ] = " cp {} " . format ( Grass7Utils . getWindowsCodePage ( ) )
2016-11-23 21:58:58 +01:00
with subprocess . Popen (
2017-10-26 16:09:46 +02:00
command ,
2018-10-31 20:55:56 -05:00
shell = False ,
2017-10-26 16:09:46 +02:00
stdout = subprocess . PIPE ,
stdin = subprocess . DEVNULL ,
stderr = subprocess . STDOUT ,
universal_newlines = True ,
env = grassenv ,
2019-03-05 09:53:56 +10:00
* * kw
2016-11-23 21:58:58 +01:00
) as proc :
for line in iter ( proc . stdout . readline , ' ' ) :
if ' GRASS_INFO_PERCENT ' in line :
try :
2017-01-06 20:04:00 +10:00
feedback . setProgress ( int (
2016-11-23 21:58:58 +01:00
line [ len ( ' GRASS_INFO_PERCENT ' ) + 2 : ] ) )
except :
pass
2018-11-01 07:25:44 +10:00
if any ( [ l in line for l in [ ' WARNING ' , ' ERROR ' ] ] ) :
loglines . append ( line . strip ( ) )
feedback . reportError ( line . strip ( ) )
elif line . strip ( ) :
loglines . append ( line . strip ( ) )
feedback . pushConsoleInfo ( line . strip ( ) )
2014-04-19 15:53:43 +02:00
if ProcessingConfig . getSetting ( Grass7Utils . GRASS_LOG_CONSOLE ) :
2018-02-05 22:11:34 -04:00
QgsMessageLog . logMessage ( ' \n ' . join ( loglines ) , ' Processing ' , Qgis . Info )
2014-04-19 15:53:43 +02:00
# GRASS session is used to hold the layers already exported or
# produced in GRASS between multiple calls to GRASS algorithms.
# This way they don't have to be loaded multiple times and
# following algorithms can use the results of the previous ones.
# Starting a session just involves creating the temp mapset
# structure
@staticmethod
2017-10-26 16:09:46 +02:00
def startGrassSession ( ) :
2014-04-19 15:53:43 +02:00
if not Grass7Utils . sessionRunning :
Grass7Utils . createTempMapset ( )
Grass7Utils . sessionRunning = True
# End session by removing the temporary GRASS mapset and all
# the layers.
@staticmethod
2017-10-26 16:09:46 +02:00
def endGrassSession ( ) :
#shutil.rmtree(Grass7Utils.grassMapsetFolder(), True)
2014-04-19 15:53:43 +02:00
Grass7Utils . sessionRunning = False
Grass7Utils . sessionLayers = { }
Grass7Utils . projectionSet = False
@staticmethod
def getSessionLayers ( ) :
return Grass7Utils . sessionLayers
@staticmethod
def addSessionLayers ( exportedLayers ) :
fix python pep8 warnings and fix some revealed errors
pep8 --ignore=E111,E128,E201,E202,E203,E211,E221,E222,E225,E226,E227,E231,E241,E261,E265,E272,E302,E303,E501,E701 \
--exclude="ui_*.py,debian/*,python/ext-libs/*" \
.
2015-02-01 14:15:42 +01:00
Grass7Utils . sessionLayers = dict (
2017-03-04 19:41:23 +01:00
list ( Grass7Utils . sessionLayers . items ( ) ) +
list ( exportedLayers . items ( ) ) )
2014-04-19 15:53:43 +02:00
@staticmethod
2017-10-26 16:09:46 +02:00
def checkGrassIsInstalled ( ignorePreviousState = False ) :
2014-04-19 15:53:43 +02:00
if not ignorePreviousState :
2017-10-26 16:09:46 +02:00
if Grass7Utils . isGrassInstalled :
2014-04-19 15:53:43 +02:00
return
2017-10-22 19:39:59 +02:00
# We check the version of Grass7
if Grass7Utils . installedVersion ( ) is not None :
2017-10-26 16:09:46 +02:00
# For Ms-Windows, we check GRASS binaries
if isWindows ( ) :
cmdpath = os . path . join ( Grass7Utils . path , ' bin ' , ' r.out.gdal.exe ' )
2017-10-22 19:39:59 +02:00
if not os . path . exists ( cmdpath ) :
return Grass7Utils . tr (
' The specified GRASS 7 folder " {} " does not contain '
' a valid set of GRASS 7 modules. \n Please, go to the '
' Processing settings dialog, and check that the '
2018-01-24 16:27:27 +10:00
' GRASS 7 \n folder is correctly configured ' . format ( os . path . join ( Grass7Utils . path , ' bin ' ) ) )
2017-10-26 16:09:46 +02:00
Grass7Utils . isGrassInstalled = True
return
# Return error messages
else :
# MS-Windows or MacOSX
if isWindows ( ) or isMac ( ) :
if Grass7Utils . path is None :
return Grass7Utils . tr (
' GRASS GIS 7 folder is not configured. Please configure '
' it before running GRASS GIS 7 algorithms. ' )
if Grass7Utils . command is None :
return Grass7Utils . tr (
2017-11-12 21:55:23 +01:00
' GRASS GIS 7 binary {0} can \' t be found on this system from a shell. '
2017-10-26 16:09:46 +02:00
' Please install it or configure your PATH {1} environment variable. ' . format (
' (grass.bat) ' if isWindows ( ) else ' (grass.sh) ' ,
' or OSGEO4W_ROOT ' if isWindows ( ) else ' ' ) )
# GNU/Linux
else :
return Grass7Utils . tr (
2017-11-12 21:55:23 +01:00
' GRASS 7 can \' t be found on this system from a shell. '
2017-10-26 16:09:46 +02:00
' Please install it or configure your PATH environment variable. ' )
2014-04-19 15:53:43 +02:00
2015-01-16 15:56:05 +02:00
@staticmethod
def tr ( string , context = ' ' ) :
if context == ' ' :
context = ' Grass7Utils '
return QCoreApplication . translate ( context , string )
2016-07-02 14:06:53 +02:00
@staticmethod
def writeCommand ( output , command ) :
try :
# Python 2
output . write ( command . encode ( ' utf8 ' ) + ' \n ' )
except TypeError :
# Python 3
output . write ( command + ' \n ' )
2017-01-09 15:32:42 +02:00
@staticmethod
def grassHelpPath ( ) :
helpPath = ProcessingConfig . getSetting ( Grass7Utils . GRASS_HELP_PATH )
if helpPath is None :
2017-10-26 16:09:46 +02:00
if isWindows ( ) or isMac ( ) :
2017-11-23 14:36:17 +02:00
if Grass7Utils . path is not None :
localPath = os . path . join ( Grass7Utils . path , ' docs/html ' )
if os . path . exists ( localPath ) :
helpPath = os . path . abspath ( localPath )
2017-01-09 15:32:42 +02:00
else :
searchPaths = [ ' /usr/share/doc/grass-doc/html ' ,
' /opt/grass/docs/html ' ,
' /usr/share/doc/grass/docs/html ' ]
for path in searchPaths :
if os . path . exists ( path ) :
helpPath = os . path . abspath ( path )
break
2017-04-04 13:56:26 +10:00
if helpPath is not None :
return helpPath
2017-10-26 16:09:46 +02:00
elif Grass7Utils . version :
version = Grass7Utils . version . replace ( ' . ' , ' ' ) [ : 2 ]
return ' https://grass.osgeo.org/grass {} /manuals/ ' . format ( version )
2017-04-04 13:56:26 +10:00
else :
2017-10-26 16:09:46 +02:00
# GRASS not available!
2019-01-19 22:08:28 +01:00
return ' https://grass.osgeo.org/grass76/manuals/ '
2017-11-05 13:18:24 +01:00
@staticmethod
def getSupportedOutputRasterExtensions ( ) :
# We use the same extensions than GDAL because:
# - GRASS is also using GDAL for raster imports.
# - Chances that GRASS is compiled with another version of
# GDAL than QGIS are very limited!
return GdalUtils . getSupportedOutputRasterExtensions ( )
@staticmethod
def getRasterFormatFromFilename ( filename ) :
"""
Returns Raster format name from a raster filename .
: param filename : The name with extension of the raster .
: return : The Gdal short format name for extension .
"""
ext = os . path . splitext ( filename ) [ 1 ] . lower ( )
ext = ext . lstrip ( ' . ' )
2017-12-27 17:41:05 +01:00
if ext :
supported = GdalUtils . getSupportedRasters ( )
for name in list ( supported . keys ( ) ) :
exts = supported [ name ]
if ext in exts :
return name
2017-11-05 13:18:24 +01:00
return ' GTiff '