source: grass/trunk/lib/init/grass.py@ 65348

Last change on this file since 65348 was 65348, checked in by martinl, 9 years ago

make GRASS data TMPDIR configurable (GRASS_TMPDIR_MAPSET && TMPDIR)
changes in API (new fns): G_file_name_tmp(), G_make_mapset_element_tmp(), G_recursive_remove()
change GRASS_VECTOR_TEMPORARY to support various modes (delete, keep, and move)
update GIS/Raster/Vector API to support this feature
update initialization script to allow defining TMPDIR

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-python
File size: 63.8 KB
RevLine 
[37863]1#!/usr/bin/env python
2#############################################################################
3#
[57584]4# MODULE: GRASS initialization script
[51403]5# AUTHOR(S): Original author unknown - probably CERL
[45576]6# Andreas Lange <andreas.lange rhein-main.de>
[51403]7# Huidae Cho <grass4u gmail.com>
8# Justin Hickey <jhickey hpcc.nectec.or.th>
9# Markus Neteler <neteler osgeo.org>
[57584]10# Hamish Bowman <hamish_b yahoo.com>
11#
12# GRASS 7: converted to Python (based on init.sh shell
13# script from GRASS 6) by Glynn Clements
[45576]14# Martin Landa <landa.martin gmail.com>
[57584]15# Luca Delucchi <lucadeluge gmail.com>
[65284]16# Vaclav Petras <wenzeslaus gmail.com> (refactoring and exec)
[56828]17# PURPOSE: Sets up environment variables, parses any remaining
[45576]18# command line options for setting the GISDBASE, LOCATION,
[56828]19# and/or MAPSET. Finally it starts GRASS with the appropriate
20# user interface and cleans up after it is finished.
[64361]21# COPYRIGHT: (C) 2000-2015 by the GRASS Development Team
[37863]22#
[41563]23# This program is free software under the GNU General
[51403]24# Public License (>=v2). Read the file COPYING that
25# comes with GRASS for details.
[37863]26#
27#############################################################################
28
[65288]29"""
30Script to run GRASS session.
31
32Some of the functions could be used separately but import from this module
33is not safe, i.e. it has side effects (this should be changed in the future).
34"""
35
36# we allow for long file because we want to avoid imports if possible
37# (this makes it more stable since we have to set up paths first)
38# pylint: disable=too-many-lines
39
[37863]40import sys
41import os
42import atexit
43import string
44import subprocess
[41652]45import re
[42621]46import platform
[54467]47import tempfile
[37863]48
49# Variables substituted during build process
[56828]50if 'GISBASE' in os.environ:
[45576]51 gisbase = os.environ['GISBASE']
52else:
53 gisbase = "@GISBASE@"
[37863]54cmd_name = "@START_UP@"
55grass_version = "@GRASS_VERSION_NUMBER@"
56ld_library_path_var = '@LD_LIBRARY_PATH_VAR@'
[56828]57if 'GRASS_PROJSHARE' in os.environ:
[45576]58 config_projshare = os.environ['GRASS_PROJSHARE']
59else:
60 config_projshare = "@CONFIG_PROJSHARE@"
[37863]61
[37873]62gisbase = os.path.normpath(gisbase)
63
[45576]64# i18N
[41856]65import gettext
[65284]66# TODO: is this needed or even desirable when we have set_language()?
[64366]67gettext.install('grasslibs', os.path.join(gisbase, 'locale'))
[41856]68
[37863]69
[43817]70def warning(text):
71 sys.stderr.write(_("WARNING") + ': ' + text + os.linesep)
72
[56828]73
[37863]74def try_remove(path):
75 try:
[51403]76 os.remove(path)
[37863]77 except:
[51403]78 pass
[37863]79
[56828]80
[37863]81def try_rmdir(path):
82 try:
[51403]83 os.rmdir(path)
[37863]84 except:
[51403]85 pass
[37863]86
[56828]87
[65241]88def clean_env(gisrc):
89 env_curr = read_gisrc(gisrc)
[56828]90 env_new = {}
[46985]91 for k,v in env_curr.iteritems():
92 if 'MONITOR' not in k:
93 env_new[k] = v
[56828]94
[65241]95 write_gisrc(env_new, gisrc)
[46985]96
[56828]97
[45576]98def cleanup_dir(path):
99 if not path:
[51403]100 return
[56828]101
102 for root, dirs, files in os.walk(path, topdown=False):
[51403]103 for name in files:
[45576]104 try_remove(os.path.join(root, name))
[51403]105 for name in dirs:
[45576]106 try_rmdir(os.path.join(root, name))
[56828]107
[65284]108
109class Cleaner(object): # pylint: disable=R0903
110 """Holds directories and files which needs to be cleaned or deleted"""
[65277]111 def __init__(self):
112 self.mapset_path = None
113 self.lockfile = None
114 self.tmpdir = None
[56828]115
[65277]116 def cleanup(self):
[65284]117 """This can be registered with atexit
118
119 Object can then still change and add or remove directories to clean"""
[65277]120 # all exits after setting up tmp dirs (system/location) should
121 # also tidy it up
122 cleanup_dir(self.tmpdir)
123 try_rmdir(self.tmpdir)
124 if self.mapset_path:
125 tmpdir_mapset = os.path.join(self.mapset_path, ".tmp")
126 cleanup_dir(tmpdir_mapset)
127 try_rmdir(tmpdir_mapset)
128 # remove lock-file if requested
129 if self.lockfile:
130 try_remove(self.lockfile)
[56828]131
132
[37863]133def fatal(msg):
[59379]134 sys.stderr.write("%s: " % _('ERROR') + msg + os.linesep)
[57693]135 sys.exit(_("Exiting..."))
[37863]136
[56828]137
[37863]138def message(msg):
139 sys.stderr.write(msg + "\n")
[42357]140 sys.stderr.flush()
[45576]141
[56828]142
[65250]143# mechanism meant for debugging this script (only)
144# private global to store if we are debugging
145_DEBUG = None
146
147
148def is_debug():
149 """Returns True if we are in debug mode
150
151 For debug messages use ``debug()``.
152 """
153 global _DEBUG
154 if _DEBUG is not None:
155 return _DEBUG
156 _DEBUG = os.getenv('GRASS_DEBUG')
157 # translate to bool (no or empty variable means false)
158 if _DEBUG:
159 _DEBUG = True
160 else:
161 _DEBUG = False
162 return _DEBUG
163
164
165def debug(msg):
166 """Print a debug message if in debug mode
167
168 Do not use translatable strings for debug messages.
169 """
170 if is_debug():
171 sys.stderr.write("DEBUG: %s\n" % msg)
172 sys.stderr.flush()
173
174
[37863]175def readfile(path):
[58224]176 f = open(path, 'r')
[37863]177 s = f.read()
178 f.close()
179 return s
180
[56828]181
[37863]182def writefile(path, s):
[58224]183 f = open(path, 'w')
[37863]184 f.write(s)
185 f.close()
186
[56828]187
[37863]188def call(cmd, **kwargs):
[65288]189 """Wrapper for subprocess.call to deal with platform-specific issues"""
[37863]190 if windows:
[51403]191 kwargs['shell'] = True
[37863]192 return subprocess.call(cmd, **kwargs)
193
[56828]194
[65288]195def Popen(cmd, **kwargs): # pylint: disable=C0103
196 """Wrapper for subprocess.Popen to deal with platform-specific issues"""
[42357]197 if windows:
[51403]198 kwargs['shell'] = True
[42357]199 return subprocess.Popen(cmd, **kwargs)
200
[56828]201
[65251]202def gpath(*args):
[65267]203 """Costruct path to file or directory in GRASS GIS installation
204
205 Can be called only after gisbase was set.
206 """
[37863]207 return os.path.join(gisbase, *args)
208
[65248]209
[65267]210# for wxpath
211_WXPYTHON_BASE = None
212
213
[65248]214def wxpath(*args):
[65267]215 """Costruct path to file or directory in GRASS wxGUI
[65248]216
[65267]217 Can be called only after gisbase was set.
[65248]218
[65267]219 This function does not check if the directories exist or if GUI works
220 this must be done by the caller if needed.
221 """
222 global _WXPYTHON_BASE
223 if not _WXPYTHON_BASE:
224 # this can be called only after gisbase was set
225 _WXPYTHON_BASE = gpath("gui", "wxpython")
226 return os.path.join(_WXPYTHON_BASE, *args)
227
228
[65268]229# using format for most but leaving usage of template for the dynamic ones
230# two different methods are easy way to implement two phase construction
231help_text = r"""GRASS GIS $VERSION_NUMBER
[55186]232Geographic Resources Analysis Support System (GRASS GIS).
233
[65268]234{usage}:
[65269]235 $CMD_NAME [-h | -help | --help | --h] [-v | --version]
236 [-c | -c geofile | -c EPSG:code[:datum_trans]]
237 [-e] [-f] [-text | -gtext | -gui] [--config param]
238 [[[GISDBASE/]LOCATION_NAME/]MAPSET]
[65294]239 $CMD_NAME [FLAG]... GISDBASE/LOCATION_NAME/MAPSET --exec EXECUTABLE [EPARAM]...
[37863]240
[65268]241{flags}:
[65269]242 -h or -help or --help or --h {help_flag}
[65268]243 -v or --version {version_flag}
244 -c {create}
245 -e {exit_after}
246 -f {force_removal}
247 -text {text}
248 {text_detail}
249 -gtext {gtext}
250 {gtext_detail}
251 -gui {gui}
252 {gui_detail}
253 --config {config}
254 {config_detail}
[65294]255 --exec EXECUTABLE {exec_}
[65269]256 {exec_detail}
[37863]257
[65268]258{params}:
259 GISDBASE {gisdbase}
[65269]260 {gisdbase_detail}
[65268]261 LOCATION_NAME {location}
[65269]262 {location_detail}
[65268]263 MAPSET {mapset}
[37863]264
[65268]265 GISDBASE/LOCATION_NAME/MAPSET {full_mapset}
[37863]266
[65294]267 EXECUTABLE {executable}
268 EPARAM {executable_params}
269 FLAG {standard_flags}
270
[65268]271{env_vars}:
272 GRASS_GUI {gui_var}
273 GRASS_HTML_BROWSER {html_var}
274 GRASS_ADDON_PATH {addon_path_var}
275 GRASS_ADDON_BASE {addon_base_var}
276 GRASS_BATCH_JOB {batch_var}
277 GRASS_PYTHON {python_var}
278""".format(
279 usage=_("Usage"),
280 flags=_("Flags"),
281 help_flag=_("print this help message"),
282 version_flag=_("show version information and exit"),
283 create=_("create given database, location or mapset if it doesn't exist"),
284 exit_after=_("exit after creation of location or mapset. Only with -c flag"),
285 force_removal=_("force removal of .gislock if exists (use with care!). Only with -text flag"),
286 text=_("use text based interface (skip welcome screen)"),
287 text_detail=_("and set as default"),
288 gtext=_("use text based interface (show welcome screen)"),
289 gtext_detail=_("and set as default"),
290 gui=_("use $DEFAULT_GUI graphical user interface"),
291 gui_detail=_("and set as default"),
292 config=_("print GRASS configuration parameters"),
293 config_detail=_("options: arch,build,compiler,path,revision"),
294 params=_("Parameters"),
[65269]295 gisdbase=_("initial GRASS GIS database directory"),
296 gisdbase_detail=_("directory containing Locations"),
297 location=_("initial GRASS Location"),
298 location_detail=_("directory containing Mapsets with one common coordinate system (projection)"),
299 mapset=_("initial GRASS Mapset"),
300 full_mapset=_("fully qualified initial Mapset directory"),
[65268]301 env_vars=_("Environment variables relevant for startup"),
[65269]302 gui_var=_("select GUI (text, gui, gtext)"),
[65268]303 html_var=_("set html web browser for help pages"),
304 addon_path_var=_("set additional path(s) to local GRASS modules or user scripts"),
305 addon_base_var=_("set additional GISBASE for locally installed GRASS Addons"),
306 batch_var=_("shell script to be processed as batch job"),
[65269]307 python_var=_("set python shell name to override 'python'"),
308 exec_=_("execute GRASS module or script"),
[65294]309 exec_detail=_("provided executable will be executed in GRASS session"),
310 executable=_("GRASS module, script or any other executable"),
311 executable_params=_("parameters of the executable"),
312 standard_flags=_("standard flags"),
[65268]313 )
[37863]314
[41856]315
[65284]316def help_message(default_gui):
[37863]317 t = string.Template(help_text)
[65268]318 s = t.substitute(CMD_NAME=cmd_name, DEFAULT_GUI=default_gui,
319 VERSION_NUMBER=grass_version)
[37863]320 sys.stderr.write(s)
321
[56828]322
[65284]323def get_grass_config_dir():
324 """Get configuration directory
325
[65288]326 Determines path of GRASS GIS user configuration directory and creates
327 it if it does not exist.
328
329 Configuration directory is for example used for grass env file
330 (the one which caries mapset settings from session to session).
[65284]331 """
332 if sys.platform == 'win32':
333 grass_config_dirname = "GRASS7"
[65288]334 directory = os.path.join(os.getenv('APPDATA'), grass_config_dirname)
[65284]335 else:
336 grass_config_dirname = ".grass7"
[65288]337 directory = os.path.join(os.getenv('HOME'), grass_config_dirname)
338 if not os.path.exists(directory):
339 os.mkdir(directory)
340 return directory
[65284]341
342
[65267]343def create_tmp(user, gis_lock):
344 """Create temporary directory
345
346 :param user: user name to be used in the directory name
347 :param gis_lock: session lock filename to be used in the directory name
348 """
349 # use $TMPDIR if it exists, then $TEMP, otherwise /tmp
[37863]350 tmp = os.getenv('TMPDIR')
351 if not tmp:
[51403]352 tmp = os.getenv('TEMP')
[37863]353 if not tmp:
[56673]354 tmp = os.getenv('TMP')
355 if not tmp:
[54467]356 tmp = tempfile.gettempdir()
[65267]357
[56673]358 if tmp:
[56828]359 tmpdir = os.path.join(tmp, "grass7-%(user)s-%(lock)s" % {'user': user,
360 'lock': gis_lock})
[56673]361 try:
362 os.mkdir(tmpdir, 0700)
363 except:
364 tmp = None
[65267]365
[54467]366 if not tmp:
[56673]367 for ttmp in ("/tmp", "/var/tmp", "/usr/tmp"):
368 tmp = ttmp
[56828]369 tmpdir = os.path.join(tmp, "grass7-%(user)s-%(lock)s" % {
370 'user': user, 'lock': gis_lock})
[56673]371 try:
372 os.mkdir(tmpdir, 0700)
373 except:
374 tmp = None
375 if tmp:
[56828]376 break
[65267]377
[56673]378 if not tmp:
[65253]379 fatal(_("Unable to create temporary directory <grass7-%(user)s-"
[56828]380 "%(lock)s>! Exiting.") % {'user': user, 'lock': gis_lock})
[65267]381
382 # promoting the variable even if it was not defined before
[65256]383 os.environ['TMPDIR'] = tmpdir
[65267]384
[65277]385 debug("Tmp directory '{tmpdir}' created for user '{user}'".format(
386 tmpdir=tmpdir, user=user))
[65241]387 return tmpdir
[37863]388
[65253]389
[65284]390def get_gisrc_from_config_dir(grass_config_dir, batch_job):
391 """Set the global grassrc file (aka grassrcrc)"""
392 if batch_job:
393 # use individual GISRCRC files when in batch mode (r33174)
394 filename = os.path.join(grass_config_dir, "rc.%s" % platform.node())
395 if os.access(filename, os.R_OK):
396 return filename
397 # use standard file if in normal mode or the special file is not available
398 return os.path.join(grass_config_dir, "rc")
399
400
[65241]401def create_gisrc(tmpdir, gisrcrc):
[37863]402 # Set the session grassrc file
403 gisrc = os.path.join(tmpdir, "gisrc")
[58224]404 os.environ['GISRC'] = gisrc
[56828]405
[37863]406 # remove invalid GISRC file to avoid disturbing error messages:
407 try:
[51403]408 s = readfile(gisrcrc)
409 if "UNKNOWN" in s:
410 try_remove(gisrcrc)
411 s = None
[37863]412 except:
[51403]413 s = None
[56828]414
[37863]415 # Copy the global grassrc file to the session grassrc file
416 if s:
[51403]417 writefile(gisrc, s)
[65241]418 return gisrc
[56828]419
420
[65241]421def read_gisrc(filename):
[37863]422 kv = {}
[49910]423 try:
[65241]424 f = open(filename, 'r')
[49910]425 except IOError:
426 return kv
[56828]427
[37863]428 for line in f:
[64690]429 try:
430 k, v = line.split(':', 1)
431 except ValueError as e:
[65253]432 warning(_("Invalid line in RC file ({file}):"
433 " '{line}' ({error})\n").format(
434 line=line, error=e, file=filename))
[64690]435 continue
[51403]436 kv[k.strip()] = v.strip()
[37863]437 f.close()
[56828]438
[37863]439 return kv
440
[56828]441
[49910]442def read_env_file(path):
[49670]443 kv = {}
[58224]444 f = open(path, 'r')
[49670]445 for line in f:
446 k, v = line.split(':', 1)
447 kv[k.strip()] = v.strip()
448 f.close()
449 return kv
450
[56828]451
[65241]452def write_gisrc(kv, filename):
453 f = open(filename, 'w')
[37863]454 for k, v in kv.iteritems():
[51403]455 f.write("%s: %s\n" % (k, v))
[37863]456 f.close()
457
[56828]458
[65284]459def read_gui(gisrc, default_gui):
[65246]460 grass_gui = None
[37863]461 # At this point the GRASS user interface variable has been set from the
[65288]462 # command line, been set from an external environment variable,
463 # or is not set. So we check if it is not set
[65246]464 # Check for a reference to the GRASS user interface in the grassrc file
465 if os.access(gisrc, os.R_OK):
466 kv = read_gisrc(gisrc)
467 if 'GRASS_GUI' in os.environ:
468 grass_gui = os.environ['GRASS_GUI']
469 elif 'GUI' in kv:
470 grass_gui = kv['GUI']
471 elif 'GRASS_GUI' in kv:
472 # For backward compatibility (GRASS_GUI renamed to GUI)
473 grass_gui = kv['GRASS_GUI']
474 else:
475 # Set the GRASS user interface to the default if needed
476 grass_gui = default_gui
[56828]477
[37873]478 if not grass_gui:
[51403]479 grass_gui = default_gui
[56828]480
[37863]481 if grass_gui == 'gui':
[51403]482 grass_gui = default_gui
[56828]483
[65253]484 # FIXME oldtcltk, gis.m, d.m no longer exist (remove this around 7.2)
[37863]485 if grass_gui in ['d.m', 'gis.m', 'oldtcltk', 'tcltk']:
[49904]486 warning(_("GUI <%s> not supported in this version") % grass_gui)
[51403]487 grass_gui = default_gui
[56828]488
[65246]489 return grass_gui
[56828]490
[65246]491
[65288]492def path_prepend(directory, var):
[37863]493 path = os.getenv(var)
494 if path:
[65288]495 path = directory + os.pathsep + path
[37863]496 else:
[65288]497 path = directory
[37863]498 os.environ[var] = path
499
[56828]500
[65288]501def path_append(directory, var):
[37863]502 path = os.getenv(var)
503 if path:
[65288]504 path = path + os.pathsep + directory
[37863]505 else:
[65288]506 path = directory
[37863]507 os.environ[var] = path
508
[56828]509
[65284]510def set_paths(grass_config_dir):
[49904]511 # addons (path)
[37863]512 addon_path = os.getenv('GRASS_ADDON_PATH')
[49904]513 if addon_path:
[49910]514 for path in addon_path.split(os.pathsep):
[49904]515 path_prepend(addon_path, 'PATH')
[56828]516
[49904]517 # addons (base)
518 addon_base = os.getenv('GRASS_ADDON_BASE')
519 if not addon_base:
520 addon_base = os.path.join(grass_config_dir, 'addons')
521 os.environ['GRASS_ADDON_BASE'] = addon_base
[61142]522 if not windows:
523 path_prepend(os.path.join(addon_base, 'scripts'), 'PATH')
[49913]524 path_prepend(os.path.join(addon_base, 'bin'), 'PATH')
[65288]525
[49904]526 # standard installation
[61142]527 if not windows:
[65251]528 path_prepend(gpath('scripts'), 'PATH')
529 path_prepend(gpath('bin'), 'PATH')
[56828]530
[37863]531 # Set PYTHONPATH to find GRASS Python modules
[65251]532 if os.path.exists(gpath('gui', 'wxpython')):
533 path_prepend(gpath('gui', 'wxpython'), 'PYTHONPATH')
534 if os.path.exists(gpath('etc', 'python')):
535 path_prepend(gpath('etc', 'python'), 'PYTHONPATH')
[56828]536
[50825]537 # set path for the GRASS man pages
[65251]538 grass_man_path = gpath('docs', 'man')
[51404]539 addons_man_path = os.path.join(addon_base, 'docs', 'man')
[50825]540 man_path = os.getenv('MANPATH')
[56663]541 sys_man_path = None
[50825]542 if man_path:
[51404]543 path_prepend(addons_man_path, 'MANPATH')
[51403]544 path_prepend(grass_man_path, 'MANPATH')
[50825]545 else:
[51403]546 try:
[53743]547 nul = open(os.devnull, 'w')
[56828]548 p = Popen(['manpath'], stdout=subprocess.PIPE, stderr=nul)
[53743]549 nul.close()
[51403]550 s = p.stdout.read()
551 p.wait()
552 sys_man_path = s.strip()
553 except:
554 pass
[56828]555
[51403]556 if sys_man_path:
557 os.environ['MANPATH'] = sys_man_path
[51404]558 path_prepend(addons_man_path, 'MANPATH')
[51403]559 path_prepend(grass_man_path, 'MANPATH')
560 else:
[51404]561 os.environ['MANPATH'] = addons_man_path
[51523]562 path_prepend(grass_man_path, 'MANPATH')
[56828]563
[65278]564 # Set LD_LIBRARY_PATH (etc) to find GRASS shared libraries
565 # this works for subprocesses but won't affect the current process
566 path_prepend(gpath("lib"), ld_library_path_var)
[56828]567
[65278]568
[37863]569def find_exe(pgm):
[65288]570 for directory in os.getenv('PATH').split(os.pathsep):
571 path = os.path.join(directory, pgm)
[51403]572 if os.access(path, os.X_OK):
573 return path
[37863]574 return None
575
[56828]576
[37863]577def set_defaults():
578 # GRASS_PAGER
579 if not os.getenv('GRASS_PAGER'):
[51403]580 if find_exe("more"):
581 pager = "more"
582 elif find_exe("less"):
583 pager = "less"
584 elif windows:
585 pager = "more"
586 else:
587 pager = "cat"
588 os.environ['GRASS_PAGER'] = pager
[56828]589
[37863]590 # GRASS_PYTHON
591 if not os.getenv('GRASS_PYTHON'):
[51403]592 if windows:
593 os.environ['GRASS_PYTHON'] = "python.exe"
594 else:
595 os.environ['GRASS_PYTHON'] = "python"
[56828]596
[37863]597 # GRASS_GNUPLOT
598 if not os.getenv('GRASS_GNUPLOT'):
[51403]599 os.environ['GRASS_GNUPLOT'] = "gnuplot -persist"
[56828]600
[37863]601 # GRASS_PROJSHARE
602 if not os.getenv('GRASS_PROJSHARE'):
[51403]603 os.environ['GRASS_PROJSHARE'] = config_projshare
[56828]604
[65284]605
606def set_display_defaults():
607 """ Predefine monitor size for certain architectures"""
608 if os.getenv('HOSTTYPE') == 'arm':
609 # small monitor on ARM (iPAQ, zaurus... etc)
610 os.environ['GRASS_RENDER_HEIGHT'] = "320"
611 os.environ['GRASS_RENDER_WIDTH'] = "240"
612
613
[37863]614def set_browser():
615 # GRASS_HTML_BROWSER
616 browser = os.getenv('GRASS_HTML_BROWSER')
617 if not browser:
[51403]618 if macosx:
[56828]619 # OSX doesn't execute browsers from the shell PATH - route thru a
620 # script
[65251]621 browser = gpath('etc', "html_browser_mac.sh")
[51403]622 os.environ['GRASS_HTML_BROWSER_MACOSX'] = "-b com.apple.helpviewer"
[56828]623
[65180]624 if windows:
625 browser = "start"
626 elif cygwin:
[51403]627 browser = "explorer"
628 else:
629 # the usual suspects
[64608]630 browsers = ["xdg-open", "x-www-browser", "htmlview", "konqueror", "mozilla",
[56828]631 "mozilla-firefox", "firefox", "iceweasel", "opera",
632 "netscape", "dillo", "lynx", "links", "w3c"]
[51403]633 for b in browsers:
634 if find_exe(b):
635 browser = b
636 break
[56828]637
[42145]638 elif macosx:
[56828]639 # OSX doesn't execute browsers from the shell PATH - route thru a
640 # script
[51403]641 os.environ['GRASS_HTML_BROWSER_MACOSX'] = "-b %s" % browser
[65251]642 browser = gpath('etc', "html_browser_mac.sh")
[56828]643
[37863]644 if not browser:
[51403]645 warning(_("Searched for a web browser, but none found"))
646 # even so we set konqueror to make lib/gis/parser.c happy:
[65253]647 # TODO: perhaps something more probable would be better, e.g. xdg-open
[51403]648 browser = "konqueror"
[56828]649
[37863]650 os.environ['GRASS_HTML_BROWSER'] = browser
651
[56828]652
[65284]653def ensure_home():
654 """Set HOME if not set on MS Windows"""
655 if windows and not os.getenv('HOME'):
656 os.environ['HOME'] = os.path.join(os.getenv('HOMEDRIVE'),
657 os.getenv('HOMEPATH'))
658
[65246]659def create_initial_gisrc(filename):
[64408]660 # for convenience, define GISDBASE as pwd:
[37863]661 s = r"""GISDBASE: %s
662LOCATION_NAME: <UNKNOWN>
663MAPSET: <UNKNOWN>
664""" % os.getcwd()
[65246]665 writefile(filename, s)
[37863]666
[56828]667
[65246]668def check_gui(expected_gui):
669 grass_gui = expected_gui
[37863]670 # Check if we are running X windows by checking the DISPLAY variable
[57536]671 if os.getenv('DISPLAY') or windows or macosx:
[51403]672 # Check if python is working properly
[65246]673 if expected_gui in ('wxpython', 'gtext'):
[51403]674 nul = open(os.devnull, 'w')
[56828]675 p = Popen([os.environ['GRASS_PYTHON']], stdin=subprocess.PIPE,
676 stdout=nul, stderr=nul)
[51403]677 nul.close()
678 p.stdin.write("variable=True")
679 p.stdin.close()
680 p.wait()
[65267]681 if p.returncode != 0:
[51403]682 # Python was not found - switch to text interface mode
683 warning(_("The python command does not work as expected!\n"
[41856]684 "Please check your GRASS_PYTHON environment variable.\n"
685 "Use the -help option for details.\n"
686 "Switching to text based interface mode.\n\n"
687 "Hit RETURN to continue.\n"))
[51403]688 sys.stdin.readline()
689 grass_gui = 'text'
[56828]690
[37863]691 else:
[51403]692 # Display a message if a graphical interface was expected
[65246]693 if expected_gui != 'text':
[51403]694 # Set the interface mode to text
695 warning(_("It appears that the X Windows system is not active.\n"
[41856]696 "A graphical based user interface is not supported.\n"
[65246]697 "(DISPLAY variable is not set.)\n"
[41856]698 "Switching to text based interface mode.\n\n"
[65246]699 "Hit RETURN to continue.\n"))
[51403]700 sys.stdin.readline()
701 grass_gui = 'text'
[65246]702 return grass_gui
[56828]703
[65246]704
705def save_gui(gisrc, grass_gui):
[65288]706 """Save the user interface variable in the grassrc file"""
[37863]707 if os.access(gisrc, os.F_OK):
[65241]708 kv = read_gisrc(gisrc)
[51403]709 kv['GUI'] = grass_gui
[65241]710 write_gisrc(kv, gisrc)
[37863]711
[56828]712
[65274]713def create_location(gisdbase, location, geostring):
714 """Create GRASS Location using georeferenced file or EPSG
715
716 EPSG code format is ``EPSG:code`` or ``EPSG:code:datum_trans``.
717
718 :param gisdbase: Path to GRASS GIS database directory
719 :param location: name of new Location
720 :param geostring: path to a georeferenced file or EPSG code
721 """
722 if gpath('etc', 'python') not in sys.path:
723 sys.path.append(gpath('etc', 'python'))
724 from grass.script import core as gcore # pylint: disable=E0611
725
726 try:
727 if geostring and geostring.upper().find('EPSG:') > -1:
728 # create location using EPSG code
729 epsg = geostring.split(':', 1)[1]
730 if ':' in epsg:
731 epsg, datum_trans = epsg.split(':', 1)
732 else:
733 datum_trans = None
734 gcore.create_location(gisdbase, location,
735 epsg=epsg, datum_trans=datum_trans)
736 else:
737 # create location using georeferenced file
738 gcore.create_location(gisdbase, location,
739 filename=geostring)
[65288]740 except gcore.ScriptError as err:
741 fatal(err.value.strip('"').strip("'").replace('\\n', os.linesep))
[65274]742
743
744# interface created according to the current usage
745def is_mapset_valid(full_mapset):
746 """Return True if GRASS Mapset is valid"""
747 return os.access(os.path.join(full_mapset, "WIND"), os.R_OK)
748
749
750def is_location_valid(gisdbase, location):
751 """Return True if GRASS Location is valid
752
753 :param gisdbase: Path to GRASS GIS database directory
754 :param location: name of a Location
755 """
756 return os.access(os.path.join(gisdbase, location,
[65288]757 "PERMANENT", "DEFAULT_WIND"), os.F_OK)
[65274]758
759
760# basically checking location, possibly split into two functions
761# (mapset one can call location one)
762def get_mapset_invalid_reason(gisdbase, location, mapset):
763 """Returns a message describing what is wrong with the Mapset
764
765 :param gisdbase: Path to GRASS GIS database directory
766 :param location: name of a Location
767 :param mapset: name of a Mapset
768 :returns: translated message
769 """
770 full_location = os.path.join(gisdbase, location)
771 if not os.path.exists(full_location):
772 return _("Location <%s> doesn't exist") % full_location
773 elif 'PERMANENT' not in os.listdir(full_location):
774 return _("<%s> is not a valid GRASS Location"
775 " because PERMANENT Mapset is missing") % full_location
776 elif not os.path.isdir(os.path.join(full_location, 'PERMANENT')):
777 return _("<%s> is not a valid GRASS Location"
778 " because PERMANENT is not a directory") % full_location
779 elif not os.path.isfile((os.path.join(full_location,
780 'PERMANENT', 'DEFAULT_WIND'))):
781 return _("<%s> is not a valid GRASS Location"
782 " because PERMANENT Mapset does not have a DEFAULT_WIND file"
783 " (default computational region)") % full_location
784 else:
785 return _("Mapset <{mapset}> doesn't exist in GRASS Location <{loc}>. "
786 "A new mapset can be created by '-c' switch.").format(
787 mapset=mapset, loc=location)
788
789
[65284]790def set_mapset(gisrc, arg, geofile=None, create_new=False):
[65275]791 """Selected Location and Mapset are checked and created if requested
792
[65288]793 The gisrc (GRASS environment file) is written at the end
794 (nothing is returned).
[65275]795 """
[37863]796 l = None
[56828]797
[37863]798 if arg == '-':
[65288]799 # TODO: repair or remove behavior env vars + `grass71 -` (see doc)
800 # this is broken for some time (before refactoring, e.g. r65235)
801 # is some code is added, it should be a separate function, probably
802 # called here
803 # older comment for global vars:
804 # TODO: it does not seem that these would be ever set before calling this
805 # function, so we may just delete them here (the globals are set from
806 # the gisrc later on). But where is setting from environmental variables?
807 # the following probable means if env var defined, use it
808 # originates from r37863 (Convert grass70 script to Python) but even
809 # there it seems that it will never succeed
810 # it would have to be defined also for other vars
811 # if location:
812 # l = location
813 pass
[37863]814 else:
[51403]815 l = arg
[56828]816
[37863]817 if l:
[51403]818 if l == '.':
819 l = os.getcwd()
820 elif not os.path.isabs(l):
821 l = os.path.abspath(l)
[56828]822
[51403]823 l, mapset = os.path.split(l)
824 if not mapset:
825 l, mapset = os.path.split(l)
826 l, location_name = os.path.split(l)
827 gisdbase = l
[65288]828
[37863]829 if gisdbase and location_name and mapset:
[51403]830 location = os.path.join(gisdbase, location_name, mapset)
[56828]831
[57693]832 # check if 'location' is a valid GRASS location/mapset
[65274]833 if not is_mapset_valid(location):
[57693]834 if not create_new:
835 # 'location' is not valid, check if 'location_name' is
836 # a valid GRASS location
[65274]837 fatal(get_mapset_invalid_reason(gisdbase, location_name, mapset))
[51403]838 else:
[57693]839 # 'location' is not valid, the user wants to create
840 # mapset on the fly
[65274]841 if not is_location_valid(gisdbase, location_name):
[57693]842 # 'location_name' is not a valid GRASS location,
843 # create new location and 'PERMANENT' mapset
844 gisdbase = os.path.join(gisdbase, location_name)
845 location_name = mapset
846 mapset = "PERMANENT"
[65274]847 if is_location_valid(gisdbase, location_name):
[57693]848 fatal(_("Failed to create new location. "
849 "The location <%s> already exists." % location_name))
[65274]850 create_location(gisdbase, location_name, geofile)
[51403]851 else:
[57693]852 # 'location_name' is a valid GRASS location,
853 # create new mapset
854 os.mkdir(location)
855 # copy PERMANENT/DEFAULT_WIND to <mapset>/WIND
856 s = readfile(os.path.join(gisdbase, location_name,
857 "PERMANENT", "DEFAULT_WIND"))
858 writefile(os.path.join(location, "WIND"), s)
859 message(_("Missing WIND file fixed"))
[56828]860
[51403]861 if os.access(gisrc, os.R_OK):
[65241]862 kv = read_gisrc(gisrc)
[51403]863 else:
864 kv = {}
[56828]865
[51403]866 kv['GISDBASE'] = gisdbase
867 kv['LOCATION_NAME'] = location_name
868 kv['MAPSET'] = mapset
[65241]869 write_gisrc(kv, gisrc)
[37863]870 else:
[57693]871 fatal(_("GISDBASE, LOCATION_NAME and MAPSET variables not set properly.\n"
872 "Interactive startup needed."))
[56828]873
874
[65275]875def set_mapset_interactive(grass_gui):
876 """User selects Location and Mapset in an interative way
877
878 The gisrc (GRASS environment file) is written at the end.
879 """
[65247]880 # Check for text interface
881 if grass_gui == 'text':
[65288]882 # TODO: maybe this should be removed and solved from outside
883 # this depends on what we expect from this function
884 # should gisrc be ok after running or is it allowed to be still not set
[65247]885 pass
886 # Check for GUI
887 elif grass_gui in ('gtext', 'wxpython'):
888 gui_startup(grass_gui)
889 else:
890 # Shouldn't need this but you never know
891 fatal(_("Invalid user interface specified - <%s>. "
892 "Use the --help option to see valid interface names.") % grass_gui)
[56828]893
894
[65247]895def gui_startup(grass_gui):
[65288]896 """Start GUI for startup (setting gisrc file)"""
[59379]897 if grass_gui in ('wxpython', 'gtext'):
[65248]898 ret = call([os.getenv('GRASS_PYTHON'), wxpath("gis_set.py")])
[56828]899
[59379]900 if ret == 0:
[51403]901 pass
[59379]902 elif ret == 1:
[51403]903 # The startup script printed an error message so wait
904 # for user to read it
905 message(_("Error in GUI startup. If necessary, please "
[41856]906 "report this error to the GRASS developers.\n"
907 "Switching to text mode now.\n\n"
908 "Hit RETURN to continue..."))
[51403]909 sys.stdin.readline()
[56828]910
[51403]911 os.execlp(cmd_name, "-text")
912 sys.exit(1)
[59379]913 elif ret == 2:
[51403]914 # User wants to exit from GRASS
915 message(_("Received EXIT message from GUI.\nGRASS is not started. Bye."))
916 sys.exit(0)
[37863]917 else:
[51403]918 fatal(_("Invalid return code from GUI startup script.\n"
[41856]919 "Please advise GRASS developers of this error."))
[56828]920
921
[65276]922# we don't follow the LOCATION_NAME legacy naming here but we have to still
923# translate to it, so always double check
924class MapsetSettings(object):
925 """Holds GRASS GIS database directory, Location and Mapset
926
927 Provides few convenient functions.
928 """
929 def __init__(self):
930 self.gisdbase = None
931 self.location = None
932 self.mapset = None
933 self._full_mapset = None
934
935 # TODO: perhaps full_mapset would be better as mapset_path
936 # TODO: works only when set for the first time
937 # this follows the current usage but we must invalidate when
938 # the others are changed (use properties for that)
939 @property
940 def full_mapset(self):
941 if self._full_mapset is None:
942 self._full_mapset = os.path.join(self.gisdbase, self.location,
943 self.mapset)
944 return self._full_mapset
945
[65288]946 # TODO: perhaps conversion to bool would be nicer
[65276]947 def is_valid(self):
948 return self.gisdbase and self.location and self.mapset
949
950
[65284]951# TODO: does it really makes sense to tell user about gisrcrc?
952# anything could have happened in between loading from gisrcrc and now
953# (we do e.g. GUI or creating loctation)
954def load_gisrc(gisrc, gisrcrc):
[65276]955 """Get the settings of Location and Mapset from the gisrc file
956
957 :returns: MapsetSettings object
958 """
959 mapset_settings = MapsetSettings()
[65241]960 kv = read_gisrc(gisrc)
[65276]961 mapset_settings.gisdbase = kv.get('GISDBASE')
962 mapset_settings.location = kv.get('LOCATION_NAME')
963 mapset_settings.mapset = kv.get('MAPSET')
964 if not mapset_settings.is_valid():
[51403]965 fatal(_("Error reading data path information from g.gisenv.\n"
[65276]966 "GISDBASE={gisbase}\n"
967 "LOCATION_NAME={location}\n"
968 "MAPSET={mapset}\n\n"
969 "Check the <{file}> file.").format(
970 gisbase=mapset_settings.gisdbase,
971 location=mapset_settings.location,
972 mapset=mapset_settings.mapset,
973 file=gisrcrc))
974 return mapset_settings
[56828]975
[37863]976
[53620]977# load environmental variables from grass_env_file
[65278]978def load_env(grass_env_file):
[53498]979 if not os.access(grass_env_file, os.R_OK):
[53620]980 return
[56828]981
[53498]982 for line in readfile(grass_env_file).split(os.linesep):
983 try:
984 k, v = map(lambda x: x.strip(), line.strip().split(' ', 1)[1].split('=', 1))
985 except:
986 continue
[65307]987
988 debug("Environmental variable set {}={}".format(k, v))
[61273]989 os.environ[k] = v
[65307]990
[57087]991 # Allow for mixed ISIS-GRASS Environment
992 if os.getenv('ISISROOT'):
[57089]993 isis = os.getenv('ISISROOT')
994 os.environ['ISIS_LIB'] = isis + os.sep + "lib"
995 os.environ['ISIS_3RDPARTY'] = isis + os.sep + "3rdParty" + os.sep + "lib"
996 os.environ['QT_PLUGIN_PATH'] = isis + os.sep + "3rdParty" + os.sep + "plugins"
[57087]997 #os.environ['ISIS3DATA'] = isis + "$ISIS3DATA"
[57089]998 libpath = os.getenv('LD_LIBRARY_PATH', '')
[57087]999 isislibpath = os.getenv('ISIS_LIB')
1000 isis3rdparty = os.getenv('ISIS_3RDPARTY')
[57089]1001 os.environ['LD_LIBRARY_PATH'] = libpath + os.pathsep + isislibpath + os.pathsep + isis3rdparty
[56828]1002
1003
[65284]1004def set_language(grass_config_dir):
[59163]1005 # This function is used to override system default language and locale
1006 # Such override can be requested only from wxGUI
1007 # An override if user has provided correct environmental variables as
1008 # LC_MESSAGES or LANG is not necessary.
1009 # Unfortunately currently a working solution for Windows is lacking
1010 # thus it always on Vista and XP will print an error.
1011 # See discussion for Windows not following its own documentation and
1012 # not accepting ISO codes as valid locale identifiers http://bugs.python.org/issue10466
[52517]1013 import locale
[65288]1014
[59215]1015 language = 'None' # Such string sometimes is present in wx file
[64364]1016 encoding = None
[65288]1017
[59163]1018 # Override value is stored in wxGUI preferences file.
1019 # As it's the only thing required, we'll just grep it out.
1020 try:
1021 fd = open(os.path.join(grass_config_dir, 'wx'), 'r')
1022 except:
[59215]1023 # Even if there is no override, we still need to set locale.
1024 pass
1025 else:
1026 for line in fd:
1027 if re.search('^language', line):
[59652]1028 line = line.rstrip(' %s' % os.linesep)
[59215]1029 language = ''.join(line.split(';')[-1:])
1030 break
1031 fd.close()
1032
1033 if language == 'None' or language == '' or not language:
[59163]1034 # Language override is disabled (system language specified)
[59211]1035 # As by default program runs with C locale, but users expect to
1036 # have their default locale, we'll just set default locale
[59655]1037 try:
1038 locale.setlocale(locale.LC_ALL, '')
[60218]1039 except locale.Error as e:
[59655]1040 # If we get here, system locale settings are terribly wrong
1041 # There is no point to continue as GRASS/Python will fail
1042 # in some other unpredictable way.
1043 print "System locale is not usable. It indicates misconfigured environment."
1044 print "Reported error message: %s" % e
1045 sys.exit("Fix system locale settings and then try again.")
[65288]1046
[59652]1047 language, encoding = locale.getdefaultlocale()
1048 if not language:
[64377]1049 warning(_("Default locale settings are missing. GRASS running with C locale."))
[59652]1050 return
[65288]1051
[59652]1052 else:
[65250]1053 debug("A language override has been requested."
1054 " Trying to switch GRASS into '%s'..." % language)
[59163]1055 try:
1056 locale.setlocale(locale.LC_ALL, language)
[60218]1057 except locale.Error as e:
[52517]1058 try:
[59652]1059 # Locale lang.encoding might be missing. Let's try
1060 # UTF-8 encoding before giving up as on Linux systems
1061 # lang.UTF-8 locales are more common than legacy
1062 # ISO-8859 ones.
1063 encoding = 'UTF-8'
1064 normalized = locale.normalize('%s.%s' % (language, encoding))
1065 locale.setlocale(locale.LC_ALL, normalized)
[60218]1066 except locale.Error as e:
[59652]1067 # The last attempt...
1068 try:
1069 encoding = locale.getpreferredencoding()
1070 normalized = locale.normalize('%s.%s' % (language, encoding))
1071 locale.setlocale(locale.LC_ALL, normalized)
[60218]1072 except locale.Error as e:
[59652]1073 # If we got so far, attempts to set up language and locale have failed
1074 # on this system
1075 sys.stderr.write("Failed to enforce user specified language '%s' with error: '%s'\n" % (language, e))
1076 sys.stderr.write("A LANGUAGE environmental variable has been set.\nPart of messages will be displayed in the requested language.\n")
1077 # Even if setting locale will fail, let's set LANG in a hope,
1078 # that UI will use it GRASS texts will be in selected language,
1079 # system messages (i.e. OK, Cancel etc.) - in system default
1080 # language
1081 os.environ['LANGUAGE'] = language
1082 return
[65288]1083
[53620]1084 # Set up environment for subprocesses
[59652]1085 os.environ['LANGUAGE'] = language
1086 os.environ['LANG'] = language
1087 if encoding:
1088 normalized = locale.normalize('%s.%s' % (language, encoding))
1089 else:
1090 normalized = language
[56828]1091 for lc in ('LC_CTYPE', 'LC_MESSAGES', 'LC_TIME', 'LC_COLLATE',
1092 'LC_MONETARY', 'LC_PAPER', 'LC_NAME', 'LC_ADDRESS',
1093 'LC_TELEPHONE', 'LC_MEASUREMENT', 'LC_IDENTIFICATION'):
[59652]1094 os.environ[lc] = normalized
[56828]1095
[53620]1096 # Some code in GRASS might not like other decimal separators than .
1097 # Other potential sources for problems are: LC_TIME LC_CTYPE
1098 locale.setlocale(locale.LC_NUMERIC, 'C')
1099 os.environ['LC_NUMERIC'] = 'C'
1100 if os.getenv('LC_ALL'):
[56828]1101 del os.environ['LC_ALL'] # Remove LC_ALL to not override LC_NUMERIC
[65288]1102
[59163]1103 # From now on enforce the new language
[59652]1104 if encoding:
[65251]1105 gettext.install('grasslibs', gpath('locale'), codeset=encoding)
[59652]1106 else:
[65251]1107 gettext.install('grasslibs', gpath('locale'))
[56828]1108
[65277]1109
[65288]1110# TODO: grass_gui parameter is a hack and should be removed, see below
1111def lock_mapset(mapset_path, force_gislock_removal, user, grass_gui):
1112 """Lock the mapset and return name of the lock file
1113
1114 Behavior on error must be changed somehow; now it fatals but GUI case is
1115 unresolved.
1116 """
[65277]1117 if not os.path.exists(mapset_path):
[65284]1118 fatal(_("Path '%s' doesn't exist") % mapset_path)
[37863]1119 # Check for concurrent use
[65284]1120 lockfile = os.path.join(mapset_path, ".gislock")
[65251]1121 ret = call([gpath("etc", "lock"), lockfile, "%d" % os.getpid()])
[63374]1122 msg = None
1123 if ret == 2:
1124 if not force_gislock_removal:
1125 msg = _("%(user)s is currently running GRASS in selected mapset (" \
1126 "file %(file)s found). Concurrent use not allowed.\nYou can force launching GRASS using -f flag " \
1127 "(note that you need permission for this operation). Have another look in the processor " \
1128 "manager just to be sure..." % {
1129 'user': user, 'file': lockfile})
1130 else:
1131 try_remove(lockfile)
1132 message(_("%(user)s is currently running GRASS in selected mapset (" \
1133 "file %(file)s found). Forcing to launch GRASS..." % {
1134 'user': user, 'file': lockfile}))
1135 elif ret != 0:
[51403]1136 msg = _("Unable to properly access '%s'.\n"
[46914]1137 "Please notify system personel.") % lockfile
[56828]1138
[65277]1139 # TODO: the gui decision should be done by the caller
1140 # this needs some change to the function interafce, return tupple or
1141 # use exceptions (better option)
[41740]1142 if msg:
1143 if grass_gui == "wxpython":
[65248]1144 call([os.getenv('GRASS_PYTHON'), wxpath("gis_set_error.py"), msg])
[65277]1145 # TODO: here we probably miss fatal or exit, needs to be added
[41740]1146 else:
1147 fatal(msg)
[65277]1148 debug("Mapset <{mapset}> locked using '{lockfile}'".format(
1149 mapset=mapset_path, lockfile=lockfile))
1150 return lockfile
[56828]1151
1152
[37863]1153def make_fontcap():
[65288]1154 # TODO: is GRASS_FONT_CAP ever defined? It seems it must be defined in system
[37863]1155 fc = os.getenv('GRASS_FONT_CAP')
1156 if fc and not os.access(fc, os.R_OK):
[51403]1157 message(_("Building user fontcap..."))
1158 call(["g.mkfontcap"])
[56828]1159
1160
[65277]1161def ensure_db_connected(mapset):
1162 """Predefine default driver if DB connection not defined
1163
1164 :param mapset: full path to the mapset
1165 """
1166 if not os.access(os.path.join(mapset, "VAR"), os.F_OK):
1167 call(['db.connect', '-c', '--quiet'])
1168
1169
[65278]1170def get_shell():
[65284]1171 # set SHELL on ms windowns
1172 # this was at the very beginning of the script but it can be anywhere
1173 if windows:
1174 if os.getenv('GRASS_SH'):
1175 os.environ['SHELL'] = os.getenv('GRASS_SH')
1176 if not os.getenv('SHELL'):
1177 os.environ['SHELL'] = os.getenv('COMSPEC', 'cmd.exe')
1178
[37863]1179 # cygwin has many problems with the shell setup
1180 # below, so i hardcoded everything here.
[61705]1181 if sys.platform == 'cygwin':
[37863]1182 sh = "cygwin"
1183 shellname = "GNU Bash (Cygwin)"
[51403]1184 os.environ['SHELL'] = "/usr/bin/bash.exe"
[37863]1185 os.environ['OSTYPE'] = "cygwin"
1186 else:
[64684]1187 # in docker the 'SHELL' variable may not be
1188 # visible in a Python session
1189 try:
1190 sh = os.path.basename(os.getenv('SHELL'))
1191 except:
1192 sh = 'sh'
[64688]1193 os.environ['SHELL'] = sh
[65288]1194
[56175]1195 if windows and sh:
1196 sh = os.path.splitext(sh)[0]
[65288]1197
[51403]1198 if sh == "ksh":
1199 shellname = "Korn Shell"
[37863]1200 elif sh == "csh":
[56828]1201 shellname = "C Shell"
[37863]1202 elif sh == "tcsh":
[56828]1203 shellname = "TC Shell"
[37863]1204 elif sh == "bash":
[56828]1205 shellname = "Bash Shell"
[37863]1206 elif sh == "sh":
[51403]1207 shellname = "Bourne Shell"
[55897]1208 elif sh == "zsh":
1209 shellname = "Z Shell"
[56175]1210 elif sh == "cmd":
[55901]1211 shellname = "Command Shell"
[51403]1212 else:
1213 shellname = "shell"
[65278]1214 # check for SHELL
1215 if not os.getenv('SHELL'):
1216 fatal(_("The SHELL variable is not set"))
1217 return sh, shellname
[56828]1218
[65278]1219
1220def get_grass_env_file(sh, grass_config_dir):
[65288]1221 """Get name of the shell-specific GRASS environment (rc) file"""
[53498]1222 if sh in ['csh', 'tcsh']:
1223 grass_env_file = os.path.join(grass_config_dir, 'cshrc')
[56175]1224 elif sh in ['bash', 'msh', 'cygwin', 'sh']:
[53498]1225 grass_env_file = os.path.join(grass_config_dir, 'bashrc')
[55901]1226 elif sh == 'zsh':
[55897]1227 grass_env_file = os.path.join(grass_config_dir, 'zshrc')
[56175]1228 elif sh == 'cmd':
[55901]1229 grass_env_file = os.path.join(grass_config_dir, 'env.bat')
[55856]1230 else:
1231 grass_env_file = os.path.join(grass_config_dir, 'bashrc')
[65278]1232 warning(_("Unsupported shell <{sh}>: {env_file}").format(
1233 sh=sh, env_file=grass_env_file))
1234 return grass_env_file
[56828]1235
1236
[65278]1237def get_batch_job_from_env_variable():
[65288]1238 """Get script to execute from batch job variable if available
1239
1240 Fails with fatal if variable is set but content unusable.
1241 """
[37863]1242 # hack to process batch jobs:
[65278]1243 batch_job = os.getenv('GRASS_BATCH_JOB')
1244 # variable defined, but user might not have been careful enough
1245 if batch_job:
1246 if not os.access(batch_job, os.F_OK):
1247 # wrong file
1248 fatal(_("Job file <%s> has been defined in "
1249 "the 'GRASS_BATCH_JOB' variable but not found. Exiting."
1250 "\n\n"
1251 "Use 'unset GRASS_BATCH_JOB' to disable "
1252 "batch job processing.") % batch_job)
1253 elif not os.access(batch_job, os.X_OK):
1254 # right file, but ...
1255 fatal(_("Change file permission to 'executable' for <%s>")
1256 % batch_job)
1257 return batch_job
[56828]1258
1259
[65238]1260def run_batch_job(batch_job):
[65288]1261 """Runs script, module or any command
1262
1263 If *batch_job* is a string (insecure) shell=True is used for execution.
1264
1265 :param batch_job: executable and parameters in a list or a string
1266 """
[65252]1267 batch_job_string = batch_job
1268 if not isinstance(batch_job, basestring):
1269 batch_job_string = ' '.join(batch_job)
1270 message(_("Executing <%s> ...") % batch_job_string)
1271 if isinstance(batch_job, basestring):
1272 proc = Popen(batch_job, shell=True)
[65238]1273 else:
[65252]1274 try:
1275 proc = Popen(batch_job, shell=False)
1276 except OSError as error:
1277 fatal(_("Execution of <{cmd}> failed:\n"
1278 "{error}").format(cmd=batch_job_string, error=error))
1279 returncode = proc.wait()
1280 message(_("Execution of <%s> finished.") % batch_job_string)
1281 return returncode
[65238]1282
1283
[65246]1284def start_gui(grass_gui):
[65288]1285 """Start specified GUI
1286
1287 :param grass_gui: GUI name (allowed values: 'wxpython')
1288 """
[37863]1289 # Start the chosen GUI but ignore text
[65250]1290 debug("GRASS GUI should be <%s>" % grass_gui)
[56828]1291
[37863]1292 # Check for gui interface
1293 if grass_gui == "wxpython":
[65248]1294 Popen([os.getenv('GRASS_PYTHON'), wxpath("wxgui.py")])
[56828]1295
1296
[37863]1297def clear_screen():
[65288]1298 """Clear terminal"""
[37863]1299 if windows:
[51403]1300 pass
[37863]1301 # TODO: uncomment when PDCurses works.
[51403]1302 # cls
[37863]1303 else:
[65250]1304 if not is_debug():
[51403]1305 call(["tput", "clear"])
[56828]1306
1307
[37863]1308def show_banner():
[65288]1309 """Write GRASS GIS ASCII name to stderr"""
[37863]1310 sys.stderr.write(r"""
1311 __________ ___ __________ _______________
1312 / ____/ __ \/ | / ___/ ___/ / ____/ _/ ___/
1313 / / __/ /_/ / /| | \__ \\_ \ / / __ / / \__ \
1314 / /_/ / _, _/ ___ |___/ /__/ / / /_/ // / ___/ /
1315 \____/_/ |_/_/ |_/____/____/ \____/___//____/
1316
1317""")
1318
1319
1320def say_hello():
[65288]1321 """Write welcome to stderr including Subversion revision if in svn copy"""
[64361]1322 sys.stderr.write(_("Welcome to GRASS GIS %s") % grass_version)
[59851]1323 if grass_version.endswith('svn'):
1324 try:
[65251]1325 filerev = open(gpath('etc', 'VERSIONNUMBER'))
[59851]1326 linerev = filerev.readline().rstrip('\n')
1327 filerev.close()
[65288]1328
[59851]1329 revision = linerev.split(' ')[1]
1330 sys.stderr.write(' (' + revision + ')')
1331 except:
1332 pass
[65288]1333
1334
[65284]1335def show_info(shellname, grass_gui, default_gui):
[65288]1336 """Write basic infor about GRASS GIS and GRASS session to stderr"""
[37863]1337 sys.stderr.write(
1338r"""
[41856]1339%-41shttp://grass.osgeo.org
1340%-41s%s (%s)
1341%-41sg.manual -i
1342%-41sg.version -c
[64361]1343""" % (_("GRASS GIS homepage:"),
[41856]1344 _("This version running through:"),
1345 shellname, os.getenv('SHELL'),
1346 _("Help is available with the command:"),
1347 _("See the licence terms with:")))
[65288]1348
[37863]1349 if grass_gui == 'wxpython':
[41856]1350 message("%-41sg.gui wxpython" % _("If required, restart the GUI with:"))
[37863]1351 else:
[41856]1352 message("%-41sg.gui %s" % (_("Start the GUI with:"), default_gui))
[65288]1353
[41856]1354 message("%-41sexit" % _("When ready to quit enter:"))
[37863]1355 message("")
1356
[56828]1357
[65278]1358def csh_startup(location, location_name, mapset, grass_env_file):
[37863]1359 userhome = os.getenv('HOME') # save original home
1360 home = location
1361 os.environ['HOME'] = home
[56828]1362
[37863]1363 cshrc = os.path.join(home, ".cshrc")
1364 tcshrc = os.path.join(home, ".tcshrc")
1365 try_remove(cshrc)
1366 try_remove(tcshrc)
[56828]1367
[58224]1368 f = open(cshrc, 'w')
[53521]1369 f.write("set home = %s\n" % userhome)
1370 f.write("set history = 3000 savehist = 3000 noclobber ignoreeof\n")
[56828]1371 f.write("set histfile = %s\n" % os.path.join(os.getenv('HOME'),
1372 ".history"))
1373
[53521]1374 f.write("set prompt = '\\\n")
1375 f.write("Mapset <%s> in Location <%s> \\\n" % (mapset, location_name))
[64361]1376 f.write("GRASS GIS %s > '\n" % grass_version)
[53521]1377 f.write("set BOGUS=``;unset BOGUS\n")
[56828]1378
[53498]1379 path = os.path.join(userhome, ".grass.cshrc") # left for backward compatibility
[37863]1380 if os.access(path, os.R_OK):
[53498]1381 f.write(readfile(path) + '\n')
1382 if os.access(grass_env_file, os.R_OK):
1383 f.write(readfile(grass_env_file) + '\n')
[56828]1384
[37863]1385 mail_re = re.compile(r"^ *set *mail *= *")
[56828]1386
[37863]1387 for filename in [".cshrc", ".tcshrc", ".login"]:
[51403]1388 path = os.path.join(userhome, filename)
1389 if os.access(path, os.R_OK):
1390 s = readfile(path)
1391 lines = s.splitlines()
1392 for l in lines:
1393 if mail_re.match(l):
1394 f.write(l)
[56828]1395
[37863]1396 path = os.getenv('PATH').split(':')
[53521]1397 f.write("set path = ( %s ) \n" % ' '.join(path))
[56828]1398
[37863]1399 f.close()
1400 writefile(tcshrc, readfile(cshrc))
[56828]1401
[65251]1402 exit_val = call([gpath("etc", "run"), os.getenv('SHELL')])
[56828]1403
[37863]1404 os.environ['HOME'] = userhome
[65277]1405 return exit_val
[56828]1406
1407
[65278]1408def bash_startup(location, location_name, grass_env_file):
[37863]1409 # save command history in mapset dir and remember more
1410 os.environ['HISTFILE'] = os.path.join(location, ".bash_history")
1411 if not os.getenv('HISTSIZE') and not os.getenv('HISTFILESIZE'):
[51403]1412 os.environ['HISTSIZE'] = "3000"
[56828]1413
[37863]1414 # instead of changing $HOME, start bash with: --rcfile "$LOCATION/.bashrc" ?
1415 # if so, must care be taken to explicity call .grass.bashrc et al for
1416 # non-interactive bash batch jobs?
1417 userhome = os.getenv('HOME') # save original home
[51403]1418 home = location # save .bashrc in $LOCATION
[37863]1419 os.environ['HOME'] = home
[56828]1420
[37863]1421 bashrc = os.path.join(home, ".bashrc")
1422 try_remove(bashrc)
[56828]1423
[58224]1424 f = open(bashrc, 'w')
[37898]1425 f.write("test -r ~/.alias && . ~/.alias\n")
[57089]1426 if os.getenv('ISISROOT'):
[65347]1427 f.write("PS1='ISIS-GRASS %s (%s):\\w > '\n" % (grass_version, location_name))
[57089]1428 else:
[65347]1429 f.write("PS1='GRASS %s (%s):\\w > '\n" % (grass_version, location_name))
[65288]1430
[64364]1431 f.write("""grass_prompt() {
[63523]1432 LOCATION="`g.gisenv get=GISDBASE,LOCATION_NAME,MAPSET separator='/'`"
[60216]1433 if test -d "$LOCATION/grid3/G3D_MASK" && test -f "$LOCATION/cell/MASK" ; then
[60223]1434 echo [%s]
[60216]1435 elif test -f "$LOCATION/cell/MASK" ; then
[60223]1436 echo [%s]
[60216]1437 elif test -d "$LOCATION/grid3/G3D_MASK" ; then
[60223]1438 echo [%s]
[60216]1439 fi
1440}
[61049]1441PROMPT_COMMAND=grass_prompt\n""" % (_("2D and 3D raster MASKs present"),
[60223]1442 _("Raster MASK present"),
[64364]1443 _("3D raster MASK present")))
[56828]1444
[61273]1445 # read environmental variables
1446 path = os.path.join(userhome, ".grass.bashrc") # left for backward compatibility
[37863]1447 if os.access(path, os.R_OK):
[51403]1448 f.write(readfile(path) + '\n')
[65307]1449
[37898]1450 f.write("export PATH=\"%s\"\n" % os.getenv('PATH'))
1451 f.write("export HOME=\"%s\"\n" % userhome) # restore user home path
[56828]1452
[37863]1453 f.close()
[53498]1454
[65251]1455 exit_val = call([gpath("etc", "run"), os.getenv('SHELL')])
[56828]1456
[37863]1457 os.environ['HOME'] = userhome
[65277]1458 return exit_val
[37863]1459
[56828]1460
[65278]1461def default_startup(location, location_name):
[37863]1462 if windows:
[51403]1463 os.environ['PS1'] = "GRASS %s> " % (grass_version)
1464 # "$ETC/run" doesn't work at all???
[42357]1465 exit_val = subprocess.call([os.getenv('SHELL')])
[65277]1466 # TODO: is there a difference between this and clean_temp?
1467 # TODO: why this is missing in the other startups?
[51403]1468 cleanup_dir(os.path.join(location, ".tmp")) # remove GUI session files from .tmp
[37863]1469 else:
[65347]1470 os.environ['PS1'] = "GRASS %s (%s):\\w > " % (grass_version, location_name)
[65251]1471 exit_val = call([gpath("etc", "run"), os.getenv('SHELL')])
[56828]1472
[65277]1473 # TODO: this seems to be inconsistent, the other two are no fataling
[42357]1474 if exit_val != 0:
1475 fatal(_("Failed to start shell '%s'") % os.getenv('SHELL'))
[65277]1476 return exit_val
[56828]1477
1478
[37863]1479def done_message():
[65238]1480 # here was something for batch job but it was never called
1481 message(_("Done."))
1482 message("")
1483 message(_("Goodbye from GRASS GIS"))
1484 message("")
[56828]1485
1486
[37863]1487def clean_temp():
[41856]1488 message(_("Cleaning up temporary files..."))
[37863]1489 nul = open(os.devnull, 'w')
[65257]1490 call([gpath("etc", "clean_temp")], stdout=nul)
[37863]1491 nul.close()
[47557]1492
[56828]1493
[65288]1494def grep(pattern, lines):
1495 """Search lines (list of strings) and return them when beginning matches.
[47557]1496
[65288]1497 >>> grep("a", ['abc', 'cab', 'sdr', 'aaa', 'sss'])
1498 ['abc', 'aaa']
1499 """
1500 expr = re.compile(pattern)
1501 return [elem for elem in lines if expr.match(elem)]
[56828]1502
[65288]1503
[47557]1504def print_params():
[65288]1505 """Write compile flags and other configuration to stderr"""
[65251]1506 plat = gpath('include', 'Make', 'Platform.make')
[64840]1507 if not os.path.exists(plat):
[64843]1508 fatal(_("Please install the GRASS GIS development package"))
[58224]1509 fileplat = open(plat)
[47570]1510 linesplat = fileplat.readlines()
1511 fileplat.close()
[56828]1512
[47570]1513 params = sys.argv[2:]
1514 if not params:
[48310]1515 params = ['arch', 'build', 'compiler', 'path', 'revision']
[65288]1516
[47570]1517 for arg in params:
1518 if arg == 'path':
1519 sys.stdout.write("%s\n" % gisbase)
1520 elif arg == 'arch':
1521 val = grep('ARCH',linesplat)
1522 sys.stdout.write("%s\n" % val[0].split('=')[1].strip())
1523 elif arg == 'build':
[65251]1524 build = gpath('include', 'grass', 'confparms.h')
[58224]1525 filebuild = open(build)
[47570]1526 val = filebuild.readline()
[48310]1527 filebuild.close()
[47570]1528 sys.stdout.write("%s\n" % val.strip().strip('"').strip())
1529 elif arg == 'compiler':
1530 val = grep('CC',linesplat)
1531 sys.stdout.write("%s\n" % val[0].split('=')[1].strip())
[48310]1532 elif arg == 'revision':
[65251]1533 rev = gpath('include', 'grass', 'gis.h')
[58224]1534 filerev = open(rev)
[48310]1535 linesrev = filerev.readlines()
1536 val = grep('#define GIS_H_VERSION', linesrev)
1537 filerev.close()
1538 sys.stdout.write("%s\n" % val[0].split(':')[1].rstrip('$"\n').strip())
[47570]1539 else:
[47571]1540 message(_("Parameter <%s> not supported") % arg)
[56828]1541
1542
[37863]1543def get_username():
[65267]1544 """Get name of the current user"""
[37863]1545 if windows:
[51403]1546 user = os.getenv('USERNAME')
1547 if not user:
1548 user = "user_name"
[37863]1549 else:
[51403]1550 user = os.getenv('USER')
1551 if not user:
1552 user = os.getenv('LOGNAME')
1553 if not user:
1554 try:
1555 p = Popen(['whoami'], stdout = subprocess.PIPE)
1556 s = p.stdout.read()
1557 p.wait()
1558 user = s.strip()
1559 except:
1560 pass
1561 if not user:
1562 user = "user_%d" % os.getuid()
[65267]1563 return user
[56828]1564
1565
[65288]1566class Parameters(object):
1567 """Structure to hold standard part of command line parameters"""
[65274]1568 # we don't need to define any methods
1569 # pylint: disable=R0903
[65271]1570 def __init__(self):
1571 self.grass_gui = None
1572 self.create_new = None
1573 self.exit_grass = None
1574 self.force_gislock_removal = None
1575 self.mapset = None
1576 self.geofile = None
1577
1578
[65284]1579def parse_cmdline(argv, default_gui):
[65288]1580 """Parse the standard part of command line parameters"""
[65271]1581 params = Parameters()
[37863]1582 args = []
[65252]1583 for i in argv:
[51403]1584 # Check if the user asked for the version
1585 if i in ["-v", "--version"]:
[64361]1586 message("GRASS GIS %s" % grass_version)
[65251]1587 message('\n' + readfile(gpath("etc", "license")))
[51403]1588 sys.exit()
1589 # Check if the user asked for help
[65253]1590 elif i in ["help", "-h", "-help", "--help", "--h"]:
[65284]1591 help_message(default_gui=default_gui)
[51403]1592 sys.exit()
1593 # Check if the -text flag was given
1594 elif i in ["-text", "--text"]:
[65271]1595 params.grass_gui = 'text'
[59379]1596 # Check if the -gtext flag was given
1597 elif i in ["-gtext", "--gtext"]:
[65271]1598 params.grass_gui = 'gtext'
[51403]1599 # Check if the -gui flag was given
1600 elif i in ["-gui", "--gui"]:
[65271]1601 params.grass_gui = default_gui
[51403]1602 # Check if the -wxpython flag was given
1603 elif i in ["-wxpython", "-wx", "--wxpython", "--wx"]:
[65271]1604 params.grass_gui = 'wxpython'
[51403]1605 # Check if the user wants to create a new mapset
1606 elif i == "-c":
[65271]1607 params.create_new = True
[60146]1608 elif i == "-e":
[65271]1609 params.exit_grass = True
[63374]1610 elif i == "-f":
[65271]1611 params.force_gislock_removal = True
[51403]1612 elif i == "--config":
[47557]1613 print_params()
1614 sys.exit()
[51403]1615 else:
1616 args.append(i)
[65271]1617 if len(args) > 1:
1618 params.mapset = args[1]
1619 params.geofile = args[0]
[65275]1620 elif len(args) == 1:
1621 params.mapset = args[0]
[65271]1622 else:
[65275]1623 params.mapset = None
[65271]1624 return params
[37863]1625
[65252]1626
[37863]1627### MAIN script starts here
1628
1629# Get the system name
1630windows = sys.platform == 'win32'
1631cygwin = "cygwin" in sys.platform
1632macosx = "darwin" in sys.platform
1633
[65284]1634# TODO: it is OK to remove this?
1635# at the beginning of this file were are happily getting GISBASE
1636# from the environment and we don't care about inconsistencies it might cause
[59220]1637### commented-out: broken winGRASS
1638# if 'GISBASE' in os.environ:
1639# sys.exit(_("ERROR: GRASS GIS is already running "
1640# "(environmental variable GISBASE found)"))
[65253]1641# this is not really an issue, we should be able to overpower another session
[59210]1642
[37863]1643# Set GISBASE
1644os.environ['GISBASE'] = gisbase
1645
1646
[65288]1647def main():
1648 """The main function which does the whole setup and run procedure
[37863]1649
[65288]1650 Only few things are set on the module level.
1651 """
1652 # Set default GUI
1653 default_gui = "wxpython"
[37863]1654
[65288]1655 # explain what is happening in debug mode (visible only in debug mode)
1656 debug("GRASS_DEBUG environmental variable is set. It is meant to be"
1657 " an internal variable for debugging only this script.\n"
1658 " Use 'g.gisenv set=\"DEBUG=[0-5]\"'"
1659 " to turn GRASS GIS debug mode on if you wish to do so.")
[37863]1660
[65288]1661 # Set GRASS version number for R interface etc
1662 # (must be an env var for MS Windows)
1663 os.environ['GRASS_VERSION'] = grass_version
[59106]1664
[65288]1665 # Set the GIS_LOCK variable to current process id
1666 gis_lock = str(os.getpid())
1667 os.environ['GIS_LOCK'] = gis_lock
[65238]1668
[65288]1669 grass_config_dir = get_grass_config_dir()
[37863]1670
[65288]1671 batch_job = get_batch_job_from_env_variable()
[37863]1672
[65288]1673 # Parse the command-line options and set several global variables
[65294]1674 batch_exec_param = '--exec'
[65288]1675 try:
1676 # raises ValueError when not found
[65294]1677 index = sys.argv.index(batch_exec_param)
[65288]1678 batch_job = sys.argv[index + 1:]
1679 clean_argv = sys.argv[1:index]
1680 params = parse_cmdline(clean_argv, default_gui=default_gui)
1681 except ValueError:
1682 params = parse_cmdline(sys.argv[1:], default_gui=default_gui)
1683 if params.exit_grass and not params.create_new:
1684 fatal(_("Flag -e requires also flag -c"))
[65252]1685
[65288]1686 grass_gui = params.grass_gui # put it to variable, it is used a lot
[65284]1687
[65288]1688 gisrcrc = get_gisrc_from_config_dir(grass_config_dir, batch_job)
[65284]1689
[65288]1690 # Set the username
1691 user = get_username()
[65252]1692
[65288]1693 # TODO: this might need to be moved before processing of parameters and getting batch job
1694 # Set language
1695 # This has to be called before any _() function call!
1696 # Subsequent functions are using _() calls and
1697 # thus must be called only after Language has been set.
1698 set_language(grass_config_dir)
[59163]1699
[65348]1700 # Set shell (needs to be called before load_env())
1701 sh, shellname = get_shell()
1702 grass_env_file = get_grass_env_file(sh, grass_config_dir)
1703
1704 # Load environmental variables from the file (needs to be called
1705 # before create_tmp())
1706 load_env(grass_env_file)
1707
[65288]1708 # Create the temporary directory and session grassrc file
1709 tmpdir = create_tmp(user, gis_lock)
[37863]1710
[65288]1711 cleaner = Cleaner()
1712 cleaner.tmpdir = tmpdir
1713 # object is not destroyed when its method is registered
1714 atexit.register(cleaner.cleanup)
[65277]1715
[65288]1716 # Create the session grassrc file
1717 gisrc = create_gisrc(tmpdir, gisrcrc)
[37863]1718
[65288]1719 ensure_home()
1720 # Set PATH, PYTHONPATH, ...
1721 set_paths(grass_config_dir=grass_config_dir)
1722 # Set GRASS_PAGER, GRASS_PYTHON, GRASS_GNUPLOT, GRASS_PROJSHARE
1723 set_defaults()
1724 set_display_defaults()
1725 # Set GRASS_HTML_BROWSER
1726 set_browser()
[37863]1727
[65288]1728 # First time user - GISRC is defined in the GRASS script
1729 if not os.access(gisrc, os.F_OK):
1730 if grass_gui == 'text' and not params.mapset:
1731 fatal(_("Unable to start GRASS GIS. You have the choice to:\n"
1732 " - Launch the GRASS GIS interface with"
1733 " the '-gui' switch (`{cmd_name} -gui`)\n"
1734 " - Launch GRASS GIS directly with path to "
1735 "the location/mapset as an argument"
1736 " (`{cmd_name} /path/to/location/mapset`)\n"
1737 " - Create manually the GISRC file ({gisrcrc})").format(
1738 cmd_name=cmd_name, gisrcrc=gisrcrc))
1739 create_initial_gisrc(gisrc)
1740 else:
1741 # clean only for user who is no first time
1742 # (measured by presence of rc file)
1743 clean_temp()
[37863]1744
[65288]1745 if params.create_new:
1746 message(_("Creating new GRASS GIS location/mapset..."))
1747 else:
1748 message(_("Starting GRASS GIS..."))
[37863]1749
[65288]1750 # Ensure GUI is set
1751 if batch_job:
1752 grass_gui = 'text'
1753 else:
1754 if not grass_gui:
1755 # if GUI was not set previously (e.g. command line),
1756 # get it from rc file or env variable
1757 grass_gui = read_gui(gisrc, default_gui)
1758 # check that the GUI works but only if not doing a batch job
1759 grass_gui = check_gui(expected_gui=grass_gui)
1760 # save GUI only if we are not doibg batch job
1761 save_gui(gisrc, grass_gui)
[37863]1762
[65288]1763 # Parsing argument to get LOCATION
1764 if not params.mapset:
1765 # Try interactive startup
1766 # User selects LOCATION and MAPSET if not set
1767 set_mapset_interactive(grass_gui)
[46463]1768 else:
[65288]1769 # Try non-interactive start up
1770 if params.create_new and params.geofile:
1771 set_mapset(gisrc=gisrc, arg=params.mapset,
1772 geofile=params.geofile, create_new=True)
1773 else:
1774 set_mapset(gisrc=gisrc, arg=params.mapset,
1775 create_new=params.create_new)
[37863]1776
[65288]1777 # Set GISDBASE, LOCATION_NAME, MAPSET, LOCATION from $GISRC
1778 # e.g. wxGUI startup screen writes to the gisrc file,
1779 # so loading it is the only universal way to obtain the values
1780 # this suppose that both programs share the right path to gisrc file
1781 # TODO: perhaps gisrcrc should be removed from here
1782 # alternatively, we can check validity here with all the info we have
1783 # about what was used to create gisrc
1784 mapset_settings = load_gisrc(gisrc, gisrcrc=gisrcrc)
[37863]1785
[65288]1786 location = mapset_settings.full_mapset
[65276]1787
[65288]1788 # TODO: it seems that we are claiming mapset's tmp before locking
1789 # (this is what the original code did but it is probably wrong)
1790 cleaner.mapset_path = mapset_settings.full_mapset
[37863]1791
[65288]1792 # check and create .gislock file
1793 cleaner.lockfile = lock_mapset(
1794 mapset_settings.full_mapset, user=user,
1795 force_gislock_removal=params.force_gislock_removal,
1796 grass_gui=grass_gui)
[65277]1797
[65288]1798 # build user fontcap if specified but not present
1799 make_fontcap()
[37863]1800
[65288]1801 # TODO: is this really needed? Modules should call this when/if required.
1802 ensure_db_connected(location)
[37863]1803
[65288]1804 # Display the version and license info
1805 # only non-error, interactive version continues from here
1806 if batch_job:
1807 returncode = run_batch_job(batch_job)
1808 clean_temp()
1809 sys.exit(returncode)
1810 elif params.exit_grass:
1811 clean_temp()
1812 sys.exit(0)
[65278]1813 else:
[65288]1814 start_gui(grass_gui)
1815 clear_screen()
1816 show_banner()
1817 say_hello()
1818 show_info(shellname=shellname,
1819 grass_gui=grass_gui, default_gui=default_gui)
1820 if grass_gui == "wxpython":
1821 message(_("Launching <%s> GUI in the background, please wait...")
1822 % grass_gui)
1823 if sh in ['csh', 'tcsh']:
1824 csh_startup(mapset_settings.full_mapset, mapset_settings.location,
1825 mapset_settings.mapset, grass_env_file)
1826 elif sh in ['bash', 'msh', 'cygwin']:
1827 bash_startup(mapset_settings.full_mapset, mapset_settings.location,
1828 grass_env_file)
1829 else:
1830 default_startup(mapset_settings.full_mapset,
1831 mapset_settings.location)
1832 # here we are at the end of grass session
1833 clear_screen()
1834 # TODO: can we just register this atexit?
1835 # TODO: and what is difference to deleting .tmp which we do?
1836 clean_temp()
1837 # save 'last used' GISRC after removing variables which shouldn't
1838 # be saved, e.g. d.mon related
1839 clean_env(gisrc)
1840 writefile(gisrcrc, readfile(gisrc))
1841 # After this point no more grass modules may be called
1842 done_message()
1843
1844if __name__ == '__main__':
1845 main()
Note: See TracBrowser for help on using the repository browser.