#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import (nested_scopes, generators, division, absolute_import,
with_statement, print_function, unicode_literals)
from os import listdir
from os.path import join, isdir
import shutil
import ctypes as ct
import fnmatch
import grass.lib.gis as libgis
from grass.pygrass.errors import GrassError
libgis.G_gisinit('')
ETYPE = {'raster': libgis.G_ELEMENT_RASTER,
'raster_3d': libgis.G_ELEMENT_RASTER3D,
'vector': libgis.G_ELEMENT_VECTOR,
'label': libgis.G_ELEMENT_LABEL,
'region': libgis.G_ELEMENT_REGION,
'group': libgis.G_ELEMENT_GROUP}
CHECK_IS = {"GISBASE": libgis.G_is_gisbase,
"GISDBASE": lambda x: True,
"LOCATION_NAME": libgis.G_is_location,
"MAPSET": libgis.G_is_mapset}
[docs]def is_valid(value, path, type):
"""Private function to check the correctness of a value.
:param value: Name of the directory
:type value: str
:param path: Path where the directory is located
:type path: path
:param type: it is a string defining the type that will e checked,
valid types are: GISBASE, GISDBASE, LOCATION_NAME, MAPSET
:type type: str
:return: True if valid else False
:rtype: str
"""
return bool(CHECK_IS[type](join(path, value)))
def _check_raise(value, path, type):
"""Private function to check the correctness of a value.
:param value: Name of the directory
:type value: str
:param path: Path where the directory is located
:type path: path
:param type: it is a string defining the type that will e checked,
valid types are: GISBASE, GISDBASE, LOCATION_NAME, MAPSET
:type type: str
:return: the value if verify else None and
if value is empty return environmental variable
:rtype: str
"""
if value is '':
from grass.pygrass.utils import getenv
return getenv(type)
if is_valid(value, path, type):
return value
raise GrassError("%s <%s> not found" % (type.title(), join(path, value)))
[docs]def set_current_mapset(mapset, location=None, gisdbase=None):
"""Set the current mapset as working area
:param mapset: Name of the mapset
:type value: str
:param location: Name of the location
:type location: str
:param gisdbase: Name of the gisdbase
:type gisdbase: str
"""
libgis.G_setenv('MAPSET', mapset)
if location:
libgis.G_setenv('LOCATION_NAME', location)
if gisdbase:
libgis.G_setenv('GISDBASE', gisdbase)
[docs]def make_mapset(mapset, location=None, gisdbase=None):
"""Create a new mapset
:param mapset: Name of the mapset
:type value: str
:param location: Name of the location
:type location: str
:param gisdbase: Name of the gisdbase
:type gisdbase: str"""
res = libgis.G_make_mapset(gisdbase, location, mapset)
if res == -1:
raise GrassError("Cannot create new mapset")
elif res == -2:
raise GrassError("Illegal name")
[docs]class Gisdbase(object):
"""Return Gisdbase object. ::
>>> from grass.script.core import gisenv
>>> gisdbase = Gisdbase()
>>> gisdbase.name == gisenv()['GISDBASE']
True
..
"""
def __init__(self, gisdbase=''):
self.name = gisdbase
def _get_name(self):
return self._name
def _set_name(self, name):
self._name = _check_raise(name, '', "GISDBASE")
name = property(fget=_get_name, fset=_set_name,
doc="Set or obtain the name of GISDBASE")
def __str__(self):
return self.name
def __repr__(self):
return 'Gisdbase(%s)' % self.name
def __getitem__(self, location):
"""Return a Location object. ::
>>> from grass.script.core import gisenv
>>> loc_env = gisenv()['LOCATION_NAME']
>>> gisdbase = Gisdbase()
>>> loc_py = gisdbase[loc_env]
>>> loc_env == loc_py.name
True
..
"""
if location in self.locations():
return Location(location, self.name)
else:
raise KeyError('Location: %s does not exist' % location)
def __iter__(self):
for loc in self.locations():
yield Location(loc, self.name)
# TODO remove or complete this function
[docs] def new_location(self):
if libgis.G_make_location() != 0:
raise GrassError("Cannot create new location")
[docs] def locations(self):
"""Return a list of locations that are available in the gisdbase: ::
>>> gisdbase = Gisdbase()
>>> gisdbase.locations() # doctest: +ELLIPSIS
[...]
..
"""
return sorted([loc for loc in listdir(self.name)
if libgis.G_is_location(join(self.name, loc))])
[docs]class Location(object):
"""Location object ::
>>> from grass.script.core import gisenv
>>> location = Location()
>>> location # doctest: +ELLIPSIS
Location(...)
>>> location.gisdbase == gisenv()['GISDBASE']
True
>>> location.name == gisenv()['LOCATION_NAME']
True
..
"""
def __init__(self, location='', gisdbase=''):
self.gisdbase = gisdbase
self.name = location
def _get_gisdb(self):
return self._gisdb
def _set_gisdb(self, gisdb):
self._gisdb = _check_raise(gisdb, '', "GISDBASE")
gisdbase = property(fget=_get_gisdb, fset=_set_gisdb,
doc="Set or obtain the name of GISDBASE")
def _get_name(self):
return self._name
def _set_name(self, name):
self._name = _check_raise(name, self._gisdb, "LOCATION_NAME")
name = property(fget=_get_name, fset=_set_name,
doc="Set or obtain the name of LOCATION")
def __getitem__(self, mapset):
if mapset in self.mapsets():
return Mapset(mapset)
else:
raise KeyError('Mapset: %s does not exist' % mapset)
def __iter__(self):
lpath = self.path()
return (m for m in listdir(lpath)
if (isdir(join(lpath, m)) and is_valid(m, lpath, "MAPSET")))
def __len__(self):
return len(self.mapsets())
def __str__(self):
return self.name
def __repr__(self):
return 'Location(%r)' % self.name
[docs] def mapsets(self, pattern=None, permissions=True):
"""Return a list of the available mapsets.
:param pattern: the pattern to filter the result
:type pattern: str
:param permissions: check the permission of mapset
:type permissions: bool
:return: a list of mapset's names
:rtype: list of strings
::
>>> location = Location()
>>> sorted(location.mapsets()) # doctest: +ELLIPSIS
[...]
"""
mapsets = [mapset for mapset in self]
if permissions:
mapsets = [mapset for mapset in mapsets
if libgis.G_mapset_permissions(mapset)]
if pattern:
return fnmatch.filter(mapsets, pattern)
return mapsets
[docs] def path(self):
"""Return the complete path of the location"""
return join(self.gisdbase, self.name)
[docs]class Mapset(object):
"""Mapset ::
>>> from grass.script.core import gisenv
>>> genv = gisenv()
>>> mapset = Mapset()
>>> mapset # doctest: +ELLIPSIS
Mapset(...)
>>> mapset.gisdbase == genv['GISDBASE']
True
>>> mapset.location == genv['LOCATION_NAME']
True
>>> mapset.name == genv['MAPSET']
True
..
"""
def __init__(self, mapset='', location='', gisdbase=''):
self.gisdbase = gisdbase
self.location = location
self.name = mapset
self.visible = VisibleMapset(self.name, self.location, self.gisdbase)
def _get_gisdb(self):
return self._gisdb
def _set_gisdb(self, gisdb):
self._gisdb = _check_raise(gisdb, '', "GISDBASE")
gisdbase = property(fget=_get_gisdb, fset=_set_gisdb,
doc="Set or obtain the name of GISDBASE")
def _get_loc(self):
return self._loc
def _set_loc(self, loc):
self._loc = _check_raise(loc, self._gisdb, "LOCATION_NAME")
location = property(fget=_get_loc, fset=_set_loc,
doc="Set or obtain the name of LOCATION")
def _get_name(self):
return self._name
def _set_name(self, name):
self._name = _check_raise(name, join(self._gisdb, self._loc), "MAPSET")
name = property(fget=_get_name, fset=_set_name,
doc="Set or obtain the name of MAPSET")
def __str__(self):
return self.name
def __repr__(self):
return 'Mapset(%r)' % self.name
[docs] def glist(self, type, pattern=None):
"""Return a list of grass types like:
* 'group',
* 'label',
* 'raster',
* 'raster_3d',
* 'region',
* 'vector',
:param type: the type of element to query
:type type: str
:param pattern: the pattern to filter the result
:type pattern: str
::
>>> mapset = Mapset()
>>> mapset.current()
>>> rast = mapset.glist('raster')
>>> test_raster_name in rast
True
>>> vect = mapset.glist('vector')
>>> test_vector_name in vect
True
..
"""
if type not in ETYPE:
str_err = "Type %s is not valid, valid types are: %s."
raise TypeError(str_err % (type, ', '.join(ETYPE.keys())))
clist = libgis.G_list(ETYPE[type], self.gisdbase,
self.location, self.name)
elist = []
for el in clist:
el_name = ct.cast(el, ct.c_char_p).value
if el_name:
elist.append(el_name)
else:
if pattern:
return fnmatch.filter(elist, pattern)
return elist
[docs] def is_current(self):
"""Check if the MAPSET is the working MAPSET"""
return (self.name == libgis.G_getenv('MAPSET') and
self.location == libgis.G_getenv('LOCATION_NAME') and
self.gisdbase == libgis.G_getenv('GISDBASE'))
[docs] def current(self):
"""Set the mapset as current"""
set_current_mapset(self.name, self.location, self.gisdbase)
[docs] def delete(self):
"""Delete the mapset"""
if self.is_current():
raise GrassError('The mapset is in use.')
shutil.rmtree(self.path())
[docs] def path(self):
"""Return the complete path of the mapset"""
return join(self.gisdbase, self.location, self.name)
[docs]class VisibleMapset(object):
"""VisibleMapset object
"""
def __init__(self, mapset, location='', gisdbase=''):
self.mapset = mapset
self.location = Location(location, gisdbase)
self._list = []
self.spath = join(self.location.path(), self.mapset, 'SEARCH_PATH')
def __repr__(self):
return repr(self.read())
def __iter__(self):
for mapset in self.read():
yield mapset
[docs] def read(self):
"""Return the mapsets in the search path"""
with open(self.spath, "a+") as f:
lines = f.readlines()
if lines:
return [l.strip() for l in lines]
lns = ['PERMANENT', ]
self._write(lns)
return lns
def _write(self, mapsets):
"""Write to SEARCH_PATH file the changes in the search path
:param mapsets: a list of mapset's names
:type mapsets: list
"""
with open(self.spath, "w+") as f:
ms = self.location.mapsets()
f.write('%s' % '\n'.join([m for m in mapsets if m in ms]))
[docs] def add(self, mapset):
"""Add a mapset to the search path
:param mapset: a mapset's name
:type mapset: str
"""
if mapset not in self.read() and mapset in self.location:
with open(self.spath, "a+") as f:
f.write('\n%s' % mapset)
else:
raise TypeError('Mapset not found')
[docs] def remove(self, mapset):
"""Remove mapset to the search path
:param mapset: a mapset's name
:type mapset: str
"""
mapsets = self.read()
mapsets.remove(mapset)
self._write(mapsets)
[docs] def extend(self, mapsets):
"""Add more mapsets to the search path
:param mapsets: a list of mapset's names
:type mapsets: list
"""
ms = self.location.mapsets()
final = self.read()
final.extend([m for m in mapsets if m in ms and m not in final])
self._write(final)
[docs] def reset(self):
"""Reset to the original search path"""
final = [self.mapset, 'PERMANENT']
self._write(final)
if __name__ == "__main__":
import doctest
from grass.pygrass import utils
from grass.script.core import run_command
test_vector_name = "Gis_test_vector"
test_raster_name = "Gis_test_raster"
utils.create_test_vector_map(test_vector_name)
run_command("g.region", n=50, s=0, e=60, w=0, res=1)
run_command("r.mapcalc", expression="%s = 1" % (test_raster_name),
overwrite=True)
run_command("g.region", n=40, s=0, e=40, w=0, res=2)
doctest.testmod()
# Remove the generated vector map, if exist
mset = utils.get_mapset_vector(test_vector_name, mapset='')
if mset:
run_command("g.remove", flags='f', type='vector',
name=test_vector_name)
mset = utils.get_mapset_raster(test_raster_name, mapset='')
if mset:
run_command("g.remove", flags='f', type='raster',
name=test_raster_name)
Help Index | Topics Index | Keywords Index | Full Index
© 2003-2020 GRASS Development Team, GRASS GIS 7.4.5dev Reference Manual