Skip to content

Commit

Permalink
New Format.__deltiem__ and expanding __setitem__.
Browse files Browse the repository at this point in the history
  • Loading branch information
scott-griffiths committed Jan 27, 2025
1 parent 96acff8 commit 0496fab
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 6 deletions.
34 changes: 28 additions & 6 deletions bitformat/_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ def __getitem__(self, key: slice | str | int) -> Any:
except KeyError:
raise KeyError(f"Field with name '{key}' not found.")

def __setitem__(self, name: str, value: str | FieldType) -> None:
def __setitem__(self, key: slice | str | int, value: str | FieldType) -> None:
if isinstance(value, str):
try:
field = FieldType.from_string(value)
Expand All @@ -310,11 +310,33 @@ def __setitem__(self, name: str, value: str | FieldType) -> None:
field = value
else:
raise ValueError(f"Can't create and set field from type '{type(value)}'.")
for i in range(len(self._fields)):
if self._fields[i].name == name:
self._fields[i] = field
return
raise KeyError(f"Field with name '{name}' not found.")
if isinstance(key, int):
self._fields[key] = field
elif isinstance(key, slice):
self._fields[key] = field
elif isinstance(key, str):
for i in range(len(self._fields)):
if self._fields[i].name == key:
self._fields[i] = field
return
raise KeyError(f"Field with name '{key}' not found.")
else:
raise TypeError(f"Invalid key type {type(key)}.")

def __delitem__(self, key: slice | int | str):
if isinstance(key, int):
del self._fields[key]
elif isinstance(key, slice):
del self._fields[key]
elif isinstance(key, str):
for i in range(len(self._fields)):
# TODO: Can we use _field_names here?
if self._fields[i].name == key:
del self._fields[i]
return
raise KeyError(f"Field with name '{key}' not found.")
else:
raise TypeError(f"Invalid key type {type(key)}.")

@override
def _str(self, indent: Indenter) -> str:
Expand Down
36 changes: 36 additions & 0 deletions tests/test_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -644,3 +644,39 @@ def test_wrong_arguments():
with pytest.raises(TypeError):
f.pack(1)
f.pack([1])

def test_slicing_fields():
f = Format.from_string("x = (u8, u7, u6, u5, u4, u3, u2, u1)")
f.pack([8, 7, 6, 5, 4, 3, 2, 1])
assert f[0].value == 8
assert f[-1].value == 1
assert f[:2].value == [8, 7]
assert f[2::-1].value == [6, 7, 8]
assert f[::2].value == [8, 6, 4, 2]
f2 = f[::2]
assert f2[1].dtype == Dtype("u6")
assert f2[1].value == 6
f2[1].value = 7
assert f2[1].value == 7
assert f[2].value == 6
with pytest.raises(IndexError):
_ = f[8]
for field in f:
assert field.value == field.dtype.bit_length

def test_deleting_fields():
f = Format.from_params(["x: u8", "y: u8", "z: u8"])
del f[1]
assert len(f) == 2
assert f[1].name == "z"

def test_setting_fields():
f = Format.from_params(["x: u8", "y: u8", "z: u8", "q:i4"])
g = Format.from_params(["a: u8", "b: u8", "c: u8"])
f[2] = Field("u15 = 5")
assert f[2].value == 5
f[0:2] = g[:]
assert f[0].name == "a"
assert len(f) == 5


0 comments on commit 0496fab

Please # to comment.