Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .gunittest.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@
# but it includes mainly tests which can (and should) be fixed.
exclude =
gui/wxpython/core/testsuite/toolboxes.sh
python/grass/gunittest/testsuite/test_gunitest_doctests.py
python/grass/pygrass/raster/testsuite/test_pygrass_raster_doctests.py
python/grass/pygrass/rpc/testsuite/test_pygrass_rpc_doctests.py
python/grass/temporal/testsuite/unittests_temporal_raster_algebra_equal_ts.py
python/grass/temporal/testsuite/unittests_temporal_raster_conditionals_complement_else.py
raster/r.in.lidar/testsuite/test_base_resolution.sh
Expand Down
28 changes: 22 additions & 6 deletions python/grass/pygrass/modules/grid/grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from grass.pygrass.gis import Mapset, Location
from grass.pygrass.gis.region import Region
from grass.pygrass.modules import Module
from grass.pygrass.utils import get_mapset_raster, findmaps
from grass.pygrass.utils import findmaps, get_mapset_raster, get_mapset_vector

from grass.pygrass.modules.grid.split import (
split_region_tiles,
Expand Down Expand Up @@ -650,11 +650,27 @@ def get_works(self):
def define_mapset_inputs(self):
"""Add the mapset information to the input maps"""
for inmap in self.module.inputs:
inm = self.module.inputs[inmap]
if inm.type in {"raster", "vector"} and inm.value:
if "@" not in inm.value:
mset = get_mapset_raster(inm.value)
inm.value += "@%s" % mset
param = self.module.inputs[inmap]
if param.typedesc == "raster":
get_mapset = get_mapset_raster
elif param.typedesc == "vector":
get_mapset = get_mapset_vector
else:
continue
if not param.value:
continue

if isinstance(param.value, list):
param.value = [self._with_mapset(n, get_mapset) for n in param.value]
else:
param.value = self._with_mapset(param.value, get_mapset)

@staticmethod
def _with_mapset(name, get_mapset):
"""Return the map name qualified with its mapset, e.g. ``name@mapset``"""
if "@" in name:
return name
return "%s@%s" % (name, get_mapset(name))

def run(self, patch=True, clean=True):
"""Run the GRASS command
Expand Down
10 changes: 7 additions & 3 deletions python/grass/pygrass/raster/buffer.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,16 @@ def __array_finalize__(self, obj):
self.pointer_type = getattr(obj, "pointer_type", None)
self.p = getattr(obj, "p", None)

def __array_wrap__(self, out_arr, context=None):
def __array_wrap__(self, out_arr, context=None, *args):
"""See:
https://numpy.org/doc/stable/user/basics.subclassing.html#array-wrap-for-ufuncs-and-other-functions
"""
if out_arr.dtype == bool:
# there is not support for boolean maps, so convert into integer
out_arr = out_arr.astype(np.int32)
out_arr.p = out_arr.ctypes.data_as(out_arr.pointer_type)
return np.ndarray.__array_wrap__(self, out_arr, context)
# NumPy 2 passes a plain ndarray (and an additional return_scalar
# argument), so the pointer can be set only after wrapping into Buffer.
wrapped = np.ndarray.__array_wrap__(self, out_arr, context, *args)
if isinstance(wrapped, Buffer):
wrapped.p = wrapped.ctypes.data_as(wrapped.pointer_type)
return wrapped
13 changes: 9 additions & 4 deletions python/grass/pygrass/raster/rowio.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,25 @@
from grass.pygrass.raster.raster_type import TYPE as RTYPE


CMPFUNC = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_void_p, ctypes.c_int)
# Rowio_setup() takes a callback which reads one row into a buffer. The
# generated binding declares the type of that callback (a ctypes function
# prototype with the arguments fd, buffer, row and length). The functions below
# have to be wrapped with this exact type: a prototype made here with
# ctypes.CFUNCTYPE() is a different class, and ctypes rejects it as an argument.
CMPFUNC = librowio.Rowio_setup.argtypes[4]


def getmaprow_CELL(fd, buf, row):
def getmaprow_CELL(fd, buf, row, length):
librast.Rast_get_c_row(fd, ctypes.cast(buf, ctypes.POINTER(librast.CELL)), row)
return 1


def getmaprow_FCELL(fd, buf, row):
def getmaprow_FCELL(fd, buf, row, length):
librast.Rast_get_f_row(fd, ctypes.cast(buf, ctypes.POINTER(librast.FCELL)), row)
return 1


def getmaprow_DCELL(fd, buf, row):
def getmaprow_DCELL(fd, buf, row, length):
librast.Rast_get_d_row(fd, ctypes.cast(buf, ctypes.POINTER(librast.DCELL)), row)
return 1

Expand Down
9 changes: 7 additions & 2 deletions python/grass/pygrass/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,9 +278,14 @@ def get_raster_for_points(poi_vector, raster, column=None, region=None):

>>> l = get_raster_for_points(vect, ele, region=region)
>>> l[0] # doctest: +ELLIPSIS
(1, 10.0, 6.0, 1)
(1, 10.0, 6.0, ...)
>>> l[1] # doctest: +ELLIPSIS
(2, 12.0, 6.0, 1)
(2, 12.0, 6.0, ...)

The function opened the vector map because it was not open. Close it
again, since a map which is still open cannot be removed on Windows.

>>> vect.close()

Add a new column and sample again

Expand Down
21 changes: 21 additions & 0 deletions python/grass/pygrass/vector/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,27 @@ def __init__(self, tname, connection, key="cat"):
self.odict = None
self.update_odict()

def __getstate__(self):
"""Return the state for pickling without the database connection

The connection cannot be pickled, so an unpickled object is a snapshot
of the columns which can be read but not updated.

>>> import pickle
>>> import sqlite3
>>> from grass.pygrass.vector.table import get_path
>>> path = "$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite/sqlite.db"
>>> cols = Columns(test_vector_name, sqlite3.connect(get_path(path)))
>>> copy = pickle.loads(pickle.dumps(cols))
>>> copy == cols
True
>>> copy.conn is None
True
"""
state = self.__dict__.copy()
state["conn"] = None
return state

def __contains__(self, item):
return item in self.names()

Expand Down
Loading