__init__.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. # -*- coding: utf-8 -*-
  2. #!/usr/bin/env python2.7
  3. from __future__ import (nested_scopes, generators, division, absolute_import,
  4. with_statement, print_function, unicode_literals)
  5. from os import listdir
  6. from os.path import join, isdir
  7. import shutil
  8. import ctypes as ct
  9. import fnmatch
  10. from grass import script
  11. #from grass.script import setup
  12. #
  13. #
  14. #GISBASE = "/home/pietro/docdat/src/gis/grass/grass71/dist.x86_64-unknown-linux-gnu"
  15. #LOCATION = "nc_basic_spm_grass7'"
  16. #GISDBASE = "/home/pietro/docdat/gis"
  17. #MAPSET = "sqlite"
  18. #GUI = "wxpython"
  19. #
  20. #setup.init(GISBASE, GISDBASE, LOCATION, MAPSET)
  21. script.gisenv()
  22. import grass.lib.gis as libgis
  23. from grass.pygrass.functions import getenv
  24. from grass.pygrass.errors import GrassError
  25. #write dec to check if user have permissions or not
  26. ETYPE = {'rast': libgis.G_ELEMENT_RASTER,
  27. 'rast3d': libgis.G_ELEMENT_RASTER3D,
  28. 'vect': libgis.G_ELEMENT_VECTOR,
  29. 'oldvect': libgis.G_ELEMENT_OLDVECTOR,
  30. 'asciivect': libgis.G_ELEMENT_ASCIIVECTOR,
  31. 'icon': libgis.G_ELEMENT_ICON,
  32. 'labels': libgis.G_ELEMENT_LABEL,
  33. 'sites': libgis.G_ELEMENT_SITE,
  34. 'region': libgis.G_ELEMENT_REGION,
  35. 'region3d': libgis.G_ELEMENT_REGION3D,
  36. 'group': libgis.G_ELEMENT_GROUP,
  37. 'view3d': libgis.G_ELEMENT_3DVIEW}
  38. CHECK_IS = {"GISBASE": libgis.G_is_gisbase,
  39. "GISDBASE": lambda x: True,
  40. "LOCATION_NAME": libgis.G_is_location,
  41. "MAPSET": libgis.G_is_mapset}
  42. def _check(value, path, type):
  43. if value and CHECK_IS[type](join(path, value)):
  44. return value
  45. elif value is '':
  46. return getenv(type)
  47. else:
  48. raise GrassError("%s <%s> not found" % (type.title(),
  49. join(path, value)))
  50. def set_current_mapset(mapset, location=None, gisdbase=None):
  51. """Set the current mapset as working area
  52. """
  53. libgis.G_setenv('MAPSET', mapset)
  54. if location:
  55. libgis.G_setenv('LOCATION_NAME', location)
  56. if gisdbase:
  57. libgis.G_setenv('GISDBASE', gisdbase)
  58. def make_mapset(mapset, location=None, gisdbase=None):
  59. """Create a new mapset"""
  60. res = libgis.G_make_mapset(gisdbase, location, mapset)
  61. if res == -1:
  62. raise GrassError("Cannot create new mapset")
  63. elif res == -2:
  64. raise GrassError("Illegal name")
  65. class Gisdbase(object):
  66. """Return Gisdbase object. ::
  67. >>> from grass.script.core import gisenv
  68. >>> gisdbase = Gisdbase()
  69. >>> gisdbase.name == gisenv()['GISDBASE']
  70. True
  71. ..
  72. """
  73. def __init__(self, gisdbase=''):
  74. self.name = gisdbase
  75. def _get_name(self):
  76. return self._name
  77. def _set_name(self, name):
  78. self._name = _check(name, '', "GISDBASE")
  79. name = property(fget=_get_name, fset=_set_name,
  80. doc="Set or obtain the name of GISDBASE")
  81. def __str__(self):
  82. return self.name
  83. def __repr__(self):
  84. return 'Gisdbase(%s)' % self.name
  85. def __getitem__(self, location):
  86. """Return a Location object. ::
  87. >>> from grass.script.core import gisenv
  88. >>> loc_env = gisenv()['LOCATION_NAME']
  89. >>> gisdbase = Gisdbase()
  90. >>> loc_py = gisdbase[loc_env]
  91. >>> loc_env == loc_py.name
  92. True
  93. ..
  94. """
  95. if location in self.locations():
  96. return Location(location, self.name)
  97. else:
  98. raise KeyError('Location: %s does not exist' % location)
  99. def __iter__(self):
  100. for loc in self.locations():
  101. yield Location(loc, self.name)
  102. # TODO remove or complete this function
  103. def new_location(self):
  104. if libgis.G__make_location() != 0:
  105. raise GrassError("Cannot create new location")
  106. def locations(self):
  107. """Return a list of locations that are available in the gisdbase: ::
  108. >>> gisdbase = Gisdbase()
  109. >>> gisdbase.locations() # doctest: +ELLIPSIS
  110. [...]
  111. ..
  112. """
  113. locations = []
  114. for loc in listdir(self.name):
  115. if libgis.G_is_location(join(self.name, loc)):
  116. locations.append(loc)
  117. locations.sort()
  118. return locations
  119. class Location(object):
  120. """Location object ::
  121. >>> from grass.script.core import gisenv
  122. >>> location = Location()
  123. >>> location # doctest: +ELLIPSIS
  124. Location(...)
  125. >>> location.gisdbase == gisenv()['GISDBASE']
  126. True
  127. >>> location.name == gisenv()['LOCATION_NAME']
  128. True
  129. ..
  130. """
  131. def __init__(self, location='', gisdbase=''):
  132. self.gisdbase = gisdbase
  133. self.name = location
  134. def _get_gisdb(self):
  135. return self._gisdb
  136. def _set_gisdb(self, gisdb):
  137. self._gisdb = _check(gisdb, '', "GISDBASE")
  138. gisdbase = property(fget=_get_gisdb, fset=_set_gisdb,
  139. doc="Set or obtain the name of GISDBASE")
  140. def _get_name(self):
  141. return self._name
  142. def _set_name(self, name):
  143. self._name = _check(name, self._gisdb, "LOCATION_NAME")
  144. name = property(fget=_get_name, fset=_set_name,
  145. doc="Set or obtain the name of LOCATION")
  146. def __getitem__(self, mapset):
  147. if mapset in self.mapsets():
  148. return Mapset(mapset)
  149. else:
  150. raise KeyError('Mapset: %s does not exist' % mapset)
  151. def __iter__(self):
  152. lpath = self.path()
  153. return (m for m in listdir(lpath)
  154. if (isdir(join(lpath, m)) and _check(m, lpath, "MAPSET")))
  155. def __len__(self):
  156. return len(self.mapsets())
  157. def __str__(self):
  158. return self.name
  159. def __repr__(self):
  160. return 'Location(%r)' % self.name
  161. def mapsets(self, pattern=None, permissions=True):
  162. """Return a list of the available mapsets.
  163. :param pattern: the pattern to filter the result
  164. :type pattern: str
  165. :param permissions: check the permission of mapset
  166. :type permissions: bool
  167. :returns: a list of mapset's names
  168. ::
  169. >>> location = Location()
  170. >>> location.mapsets()
  171. ['PERMANENT', 'user1']
  172. ..
  173. """
  174. mapsets = [mapset for mapset in self]
  175. if permissions:
  176. mapsets = [mapset for mapset in mapsets
  177. if libgis.G__mapset_permissions(mapset)]
  178. if pattern:
  179. return fnmatch.filter(mapsets, pattern)
  180. return mapsets
  181. def path(self):
  182. return join(self.gisdbase, self.name)
  183. class Mapset(object):
  184. """Mapset ::
  185. >>> mapset = Mapset()
  186. >>> mapset
  187. Mapset('user1')
  188. >>> mapset.gisdbase # doctest: +ELLIPSIS
  189. '/home/...'
  190. >>> mapset.location
  191. 'nc_basic_spm_grass7'
  192. >>> mapset.name
  193. 'user1'
  194. ..
  195. """
  196. def __init__(self, mapset='', location='', gisdbase=''):
  197. self.gisdbase = gisdbase
  198. self.location = location
  199. self.name = mapset
  200. self.visible = VisibleMapset(self.name, self.location, self.gisdbase)
  201. def _get_gisdb(self):
  202. return self._gisdb
  203. def _set_gisdb(self, gisdb):
  204. self._gisdb = _check(gisdb, '', "GISDBASE")
  205. gisdbase = property(fget=_get_gisdb, fset=_set_gisdb,
  206. doc="Set or obtain the name of GISDBASE")
  207. def _get_loc(self):
  208. return self._loc
  209. def _set_loc(self, loc):
  210. self._loc = _check(loc, self._gisdb, "LOCATION_NAME")
  211. location = property(fget=_get_loc, fset=_set_loc,
  212. doc="Set or obtain the name of LOCATION")
  213. def _get_name(self):
  214. return self._name
  215. def _set_name(self, name):
  216. self._name = _check(name, join(self._gisdb, self._loc), "MAPSET")
  217. name = property(fget=_get_name, fset=_set_name,
  218. doc="Set or obtain the name of MAPSET")
  219. def __str__(self):
  220. return self.name
  221. def __repr__(self):
  222. return 'Mapset(%r)' % self.name
  223. def glist(self, type, pattern=None):
  224. """Return a list of grass types like:
  225. * 'asciivect',
  226. * 'group',
  227. * 'icon',
  228. * 'labels',
  229. * 'oldvect',
  230. * 'rast',
  231. * 'rast3d',
  232. * 'region',
  233. * 'region3d',
  234. * 'sites',
  235. * 'vect',
  236. * 'view3d'
  237. :param type: the type of element to query
  238. :type type: str
  239. :param pattern: the pattern to filter the result
  240. :type pattern: str
  241. ::
  242. >>> mapset = Mapset('PERMANENT')
  243. >>> rast = mapset.glist('rast')
  244. >>> rast.sort()
  245. >>> rast # doctest: +ELLIPSIS
  246. ['basins', 'elevation', ...]
  247. >>> mapset.glist('rast', pattern='el*')
  248. ['elevation_shade', 'elevation']
  249. ..
  250. """
  251. if type not in ETYPE:
  252. str_err = "Type %s is not valid, valid types are: %s."
  253. raise TypeError(str_err % (type, ', '.join(ETYPE.keys())))
  254. clist = libgis.G_list(ETYPE[type], self.gisdbase,
  255. self.location, self.name)
  256. elist = []
  257. for el in clist:
  258. el_name = ct.cast(el, ct.c_char_p).value
  259. if el_name:
  260. elist.append(el_name)
  261. else:
  262. if pattern:
  263. return fnmatch.filter(elist, pattern)
  264. return elist
  265. def is_current(self):
  266. """Check if the MAPSET is the working MAPSET"""
  267. return (self.name == libgis.G_getenv('MAPSET') and
  268. self.location == libgis.G_getenv('LOCATION_NAME') and
  269. self.gisdbase == libgis.G_getenv('GISDBASE'))
  270. def current(self):
  271. """Set the mapset as current"""
  272. set_current_mapset(self.name, self.location, self.gisdbase)
  273. def delete(self):
  274. """Delete the mapset"""
  275. if self.is_current():
  276. raise GrassError('The mapset is in use.')
  277. shutil.rmtree(self.path())
  278. def path(self):
  279. return join(self.gisdbase, self.location, self.name)
  280. class VisibleMapset(object):
  281. """VisibleMapset object::
  282. >>> mapset = VisibleMapset('user1')
  283. >>> mapset
  284. ['user1', 'PERMANENT']
  285. ..
  286. """
  287. def __init__(self, mapset, location='', gisdbase=''):
  288. self.mapset = mapset
  289. self.location = Location(location, gisdbase)
  290. self._list = []
  291. self.spath = join(self.location.path(), self.mapset, 'SEARCH_PATH')
  292. def __repr__(self):
  293. return repr(self.read())
  294. def __iter__(self):
  295. for mapset in self.read():
  296. yield mapset
  297. def read(self):
  298. """Return the mapsets in the search path"""
  299. with open(self.spath, "a+") as f:
  300. lines = f.readlines()
  301. #lines.remove('')
  302. if lines:
  303. return [l.strip() for l in lines]
  304. lns = ['PERMANENT', ]
  305. self.write(lns)
  306. return lns
  307. def _write(self, mapsets):
  308. """Write to SEARCH_PATH file the changes in the search path
  309. :param mapsets: a list of mapset's names
  310. :type mapsets: list
  311. """
  312. with open(self.spath, "w+") as f:
  313. ms = self.location.mapsets()
  314. f.write('%s' % '\n'.join([m for m in mapsets if m in ms]))
  315. def add(self, mapset):
  316. """Add a mapset to the search path
  317. :param mapset: a mapset's name
  318. :type mapset: str
  319. """
  320. if mapset not in self.read() and mapset in self.location:
  321. with open(self.spath, "a+") as f:
  322. f.write('\n%s' % mapset)
  323. else:
  324. raise TypeError('Mapset not found')
  325. def remove(self, mapset):
  326. """Remove mapset to the search path
  327. :param mapset: a mapset's name
  328. :type mapset: str
  329. """
  330. mapsets = self.read()
  331. mapsets.remove(mapset)
  332. self._write(mapsets)
  333. def extend(self, mapsets):
  334. """Add more mapsets to the search path
  335. :param mapsets: a list of mapset's names
  336. :type mapsets: list
  337. """
  338. ms = self.location.mapsets()
  339. final = self.read()
  340. final.extend([m for m in mapsets if m in ms and m not in final])
  341. self._write(final)
  342. def reset(self):
  343. """Reset to the original search path"""
  344. final = [self.mapset, 'PERMANENT']
  345. self._write(final)