[Bug] grass.pygrass: Cats.delete(0) deletes all layer categories instead of category 0
Maintainers usually reply within 1 day
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 82/100
Research direction
Start with Cats.delete() and CatsList.from_array() in the pygrass vector basic module (python/grass/pygrass/vector/basic.py in the GRASS repo). In delete, test cat is None instead of truthiness so that 0 goes through Vect_field_cat_del. In from_array, convert the input to a ctypes int array before the call. Done when the reproduction leaves [1, 2] after deleting 0, raises ValueError when category 0 is absent, and from_array([1, 2, 3]) populates the list.
Written by the indexing model from the issue text.
Description
Describe the bug
In grass.pygrass.vector.basic, Cats.delete() and CatsList.from_array() contain significant bugs:
1. Cats.delete(0) deletes all categories in the layer instead of category 0
In Cats.delete():
def delete(self, cat=None, layer=1):
if cat:
self.n_del = libvect.Vect_field_cat_del(self.c_cats, layer, cat)
err_msg = "Layer(%d)/category(%d) number does not exist" % (layer, cat)
else:
self.n_del = libvect.Vect_cat_del(self.c_cats, layer)
err_msg = "Layer: %r does not exist" % layer
if self.n_del == 0:
raise ValueError(err_msg)
In GRASS GIS vector architecture, category numbers are non-negative integers (cat >= 0), and category 0 is a valid category number.
However, if cat: checks the truthiness of cat. When cat = 0:
bool(0)evaluates toFalse.- The code falls through to the
else:branch and callslibvect.Vect_cat_del(self.c_cats, layer). Vect_cat_deldeletes all categories in the given layer rather than deleting category 0.
Furthermore, if category 0 is not present in the layer (for instance, the layer contains category 1), calling cats.delete(0, layer=1) should raise ValueError("Layer(1)/category(0) number does not exist"). Instead, it wipes out category 1 and returns successfully without raising any error, causing silent data loss.
2. CatsList.from_array() crashes with ctypes.ArgumentError
In CatsList.from_array():
def from_array(self, array):
# Vect_array_to_cat_list(const int *vals, int nvals, ***)
# TODO: it's not working
libvect.Vect_array_to_cat_list(array, len(array), self.c_cat_list)
libvect.Vect_array_to_cat_list requires a POINTER(c_int). Passing a Python list or array directly raises:
ctypes.ArgumentError: argument 1: TypeError: expected LP_c_long instance instead of list
To reproduce
from grass.pygrass.vector.basic import Cats, CatsList
# 1. Cats.delete(0) wipes out all categories
cats = Cats()
cats.set(0, layer=1)
cats.set(1, layer=1)
cats.set(2, layer=1)
print(cats.cat) # [0, 1, 2]
# Attempt to delete only category 0:
cats.delete(0, layer=1)
print(cats.cat) # [] -> All categories were deleted! Expected [1, 2].
# 2. CatsList.from_array raises ctypes.ArgumentError
cats_list = CatsList()
cats_list.from_array([1, 2, 3])
# ctypes.ArgumentError: argument 1: TypeError: expected LP_c_long instance instead of list
Expected behavior
cats.delete(0, layer=1)should only delete category 0 from layer 1 viaVect_field_cat_del, leaving other categories intact.- If category 0 does not exist in the layer,
cats.delete(0, layer=1)should raiseValueError. cats.delete(cat=None, layer=1)should continue to delete all categories in the layer whencat is None.cats_list.from_array(array)should convert the integer iterable to a ctypes integer array and successfully populatecat_list.
System description
- Operating System: All platforms (Linux, macOS, Windows)
- GRASS version: main (development branch)
- Python: 3.10+
- Dominant language
- C
- Stars
- 1.2k
- Forks
- 447
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 108
Getting set up
- Ships a Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from OSGeo/grass
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
Maintainers usually reply within 1 day
-
[Bug] Unhandled ValueError terminates watchdog thread when GISRC value contains multiple colonsOpenbug
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Maintainers usually reply within 1 day
-
[Bug] macOS: Startup crashes with StopIteration when ~/Documents is not readable (macOS privacy protection)Possibly taken @NIne-WIngEd claimed this 9 days ago. Openbug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
OSGeo/grass#8027 · 3 comments ·
Maintainers usually reply within 1 day
-
[Bug] Specify the test project namePossibly taken A pull request linked to this issue is open or already merged. Openbug
Difficulty 1/5 Under an hour Newbie friendliness 65/100
OSGeo/grass#7860 · 1 comment ·
Maintainers usually reply within 1 day
-
bug GUI macOS
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
OSGeo/grass#6012 · 3 comments ·
Maintainers usually reply within 1 day
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
Difficulty 1/5 Under an hour Newbie friendliness 93/100
webarkit/WebARKitLib#107 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
polhenarejos/pico-fido#302 ·
-
[BUG] Out-of-range negative slice end returns the whole stringPossibly taken @Don-Yin claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 67/100
fastfetch-cli/fastfetch#2668 ·
Maintainers usually reply within 1 day