data.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. """Provides functions for the main GRASS GIS executable
  2. (C) 2020 by Vaclav Petras and the GRASS Development Team
  3. This program is free software under the GNU General Public
  4. License (>=v2). Read the file COPYING that comes with GRASS
  5. for details.
  6. .. sectionauthor:: Vaclav Petras <wenzeslaus gmail com>
  7. .. sectionauthor:: Linda Kladivova <l.kladivova seznam cz>
  8. This is not a stable part of the API. Use at your own risk.
  9. """
  10. import os
  11. import tempfile
  12. import getpass
  13. import sys
  14. from shutil import copytree, ignore_patterns
  15. import grass.grassdb.config as cfg
  16. from grass.grassdb.checks import is_location_valid
  17. def get_possible_database_path():
  18. """Looks for directory 'grassdata' (case-insensitive) in standard
  19. locations to detect existing GRASS Database.
  20. Returns the path as a string or None if nothing was found.
  21. """
  22. home = os.path.expanduser("~")
  23. # try some common directories for grassdata
  24. candidates = [
  25. home,
  26. os.path.join(home, "Documents"),
  27. ]
  28. # find possible database path
  29. for candidate in candidates:
  30. if os.path.exists(candidate):
  31. for subdir in next(os.walk(candidate))[1]:
  32. if "grassdata" in subdir.lower():
  33. return os.path.join(candidate, subdir)
  34. return None
  35. def create_database_directory():
  36. """Creates the standard GRASS GIS directory.
  37. Creates database directory named grassdata in the standard location
  38. according to the platform.
  39. Returns the new path as a string or None if nothing was found or created.
  40. """
  41. home = os.path.expanduser("~")
  42. # Determine the standard path according to the platform
  43. if sys.platform == "win32":
  44. path = os.path.join(home, "Documents", "grassdata")
  45. else:
  46. path = os.path.join(home, "grassdata")
  47. # Create "grassdata" directory
  48. try:
  49. os.mkdir(path)
  50. return path
  51. except OSError:
  52. pass
  53. # Create a temporary "grassdata" directory if GRASS is running
  54. # in some special environment and the standard directories
  55. # cannot be created which might be the case in some "try out GRASS"
  56. # use cases.
  57. path = os.path.join(tempfile.gettempdir(), "grassdata_{}".format(getpass.getuser()))
  58. # The created tmp is not cleaned by GRASS, so we are relying on
  59. # the system to do it at some point. The positive outcome is that
  60. # another GRASS instance will find the data created by the first
  61. # one which is desired in the "try out GRASS" use case we are
  62. # aiming towards."
  63. if os.path.exists(path):
  64. return path
  65. try:
  66. os.mkdir(path)
  67. return path
  68. except OSError:
  69. pass
  70. return None
  71. def _get_startup_location_in_distribution():
  72. """Check for startup location directory in distribution.
  73. Returns startup location if found or None if nothing was found.
  74. """
  75. gisbase = os.getenv("GISBASE")
  76. startup_location = os.path.join(gisbase, "demolocation")
  77. # Find out if startup location exists
  78. if os.path.exists(startup_location):
  79. return startup_location
  80. return None
  81. def _copy_startup_location(startup_location, location_in_grassdb):
  82. """Copy the simple startup_location with some data to GRASS database.
  83. Returns True if successfully copied or False
  84. when an error was encountered.
  85. """
  86. # Copy source startup location into GRASS database
  87. try:
  88. copytree(
  89. startup_location,
  90. location_in_grassdb,
  91. ignore=ignore_patterns("*.tmpl", "Makefile*"),
  92. )
  93. return True
  94. except (IOError, OSError):
  95. pass
  96. return False
  97. def create_startup_location_in_grassdb(grassdatabase, startup_location_name):
  98. """Create a new startup location in the given GRASS database.
  99. Returns True if a new startup location successfully created
  100. in the given GRASS database.
  101. Returns False if there is no location to copy in the installation
  102. or copying failed.
  103. """
  104. # Find out if startup location exists
  105. startup_location = _get_startup_location_in_distribution()
  106. if not startup_location:
  107. return False
  108. # Copy the simple startup_location with some data to GRASS database
  109. location_in_grassdb = os.path.join(grassdatabase, startup_location_name)
  110. if _copy_startup_location(startup_location, location_in_grassdb):
  111. return True
  112. return False
  113. def ensure_default_data_hierarchy():
  114. """Ensure that default gisdbase, location and mapset exist.
  115. Creates database directory based on the default path determined
  116. according to OS if needed. Creates location if needed.
  117. Returns the db, loc, mapset, mapset_path"""
  118. gisdbase = get_possible_database_path()
  119. location = cfg.default_location
  120. mapset = cfg.permanent_mapset
  121. # If nothing found, try to create GRASS directory
  122. if not gisdbase:
  123. gisdbase = create_database_directory()
  124. if not is_location_valid(gisdbase, location):
  125. # If not valid, copy startup loc
  126. create_startup_location_in_grassdb(gisdbase, location)
  127. mapset_path = os.path.join(gisdbase, location, mapset)
  128. return gisdbase, location, mapset, mapset_path