Skip to content

Commit ef348a4

Browse files
Make use of the validator decorator for data validation of single variables
1 parent 27e2422 commit ef348a4

File tree

5 files changed

+34
-27
lines changed

5 files changed

+34
-27
lines changed

mcproto/packets/status/status.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import json
44
from typing import Any, ClassVar, final
55

6-
from attrs import define, field
6+
from attrs import Attribute, define, field
77
from typing_extensions import Self, override
88

99
from mcproto.buffer import Buffer
@@ -43,7 +43,12 @@ class StatusResponse(ClientBoundPacket):
4343
PACKET_ID: ClassVar[int] = 0x00
4444
GAME_STATE: ClassVar[GameState] = GameState.STATUS
4545

46-
data: dict[str, Any] = field(validator=lambda self, _, value: json.dumps(value))
46+
data: dict[str, Any] = field()
47+
48+
@data.validator # pyright: ignore
49+
def _validate_data(self, _: Attribute[dict[str, Any]], value: dict[str, Any]) -> None:
50+
"""Dump the data as json to check if it's valid."""
51+
json.dumps(value)
4752

4853
@override
4954
def serialize_to(self, buf: Buffer) -> None:

mcproto/types/bitset.py

+14-14
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,18 @@ class FixedBitset(MCType):
2525

2626
__BIT_COUNT: ClassVar[int] = -1
2727

28-
@staticmethod
29-
def data_length_check(_self: FixedBitset, attribute: Attribute[bytearray], value: bytearray) -> None:
28+
data: bytearray = field()
29+
30+
@data.validator # pyright: ignore
31+
def _data_length_check(self: FixedBitset, attribute: Attribute[bytearray], value: bytearray) -> None:
3032
"""Check that the data length matches the bitset size.
3133
3234
:raises ValueError: If the data length doesn't match the bitset size.
3335
"""
34-
if _self.__BIT_COUNT == -1:
36+
if self.__BIT_COUNT == -1:
3537
raise ValueError("Bitset size is not defined.")
36-
if len(value) != math.ceil(_self.__BIT_COUNT / 8):
37-
raise ValueError(f"Bitset size is {_self.__BIT_COUNT}, but data length is {len(value)}.")
38-
39-
data: bytearray = field(validator=data_length_check.__get__(object))
38+
if len(value) != math.ceil(self.__BIT_COUNT / 8):
39+
raise ValueError(f"Bitset size is {self.__BIT_COUNT}, but data length is {len(value)}.")
4040

4141
@override
4242
def serialize_to(self, buf: Buffer) -> None:
@@ -127,17 +127,17 @@ class Bitset(MCType):
127127
:param data: The bits of the bitset.
128128
"""
129129

130-
@staticmethod
131-
def data_length_check(_self: Bitset, attribute: Attribute[list[int]], value: list[int]) -> None:
130+
size: int = field(validator=validators.gt(0))
131+
data: list[int] = field()
132+
133+
@data.validator # pyright: ignore
134+
def _data_length_check(self: Bitset, attribute: Attribute[list[int]], value: list[int]) -> None:
132135
"""Check that the data length matches the bitset size.
133136
134137
:raises ValueError: If the data length doesn't match the bitset size.
135138
"""
136-
if len(value) != _self.size:
137-
raise ValueError(f"Bitset size is {_self.size}, but data length is {len(value)}.")
138-
139-
size: int = field(validator=validators.gt(0))
140-
data: list[int] = field(validator=data_length_check.__get__(object))
139+
if len(value) != self.size:
140+
raise ValueError(f"Bitset size is {self.size}, but data length is {len(value)}.")
141141

142142
@override
143143
def serialize_to(self, buf: Buffer) -> None:

mcproto/types/block_entity.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,19 @@ class BlockEntity(MCType):
2828
.. note:: This class is used in the :class:`~mcproto.packets.play.ChunkData` packet.
2929
"""
3030

31-
@staticmethod
32-
def check_position(_self: BlockEntity, attribute: Attribute[Position], value: Position) -> None:
31+
position: Position = field()
32+
block_type: int = field()
33+
nbt: CompoundNBT = field()
34+
35+
@position.validator # pyright: ignore
36+
def _check_position(self: BlockEntity, attribute: Attribute[Position], value: Position) -> None:
3337
"""Check that the position is within the chunk.
3438
3539
:raises ValueError: If the position is not within the chunk.
3640
"""
3741
if not (0 <= value.x < 16 and 0 <= value.z < 16):
3842
raise ValueError("Position must be within the chunk")
3943

40-
position: Position = field(validator=check_position.__get__(object))
41-
block_type: int = field()
42-
nbt: CompoundNBT = field()
43-
4444
@override
4545
def serialize_to(self, buf: Buffer) -> None:
4646
x, y, z = int(self.position.x), int(self.position.y), int(self.position.z)

mcproto/types/chat.py

+2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ def check_raw(_self: JSONTextComponent, _: Attribute[RawTextComponent], value: R
4747
4848
:raises AttributeError: If the `raw` attribute is not a valid JSON chat message (missing fields).
4949
:raises TypeError: If the `raw` attribute is not a valid JSON chat message (wrong type).
50+
51+
.. note:: This is a separate method to be able to use the isinstance check for the type.
5052
"""
5153
if isinstance(value, dict): # We want to keep it this way for readability
5254
if "text" not in value and "extra" not in value:

mcproto/types/recipe.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,15 @@ class Ingredient(MCType):
2727
.. note:: Each item in the list has to have a count of 1.
2828
"""
2929

30-
@staticmethod
31-
def check_quantity(instance: Ingredient, attribute: Attribute[set[Slot]], value: set[Slot]) -> None:
30+
count: int = field(validator=validators.ge(1))
31+
items: set[Slot] = field()
32+
33+
@items.validator # pyright: ignore
34+
def _check_quantity(self, attribute: Attribute[set[Slot]], value: set[Slot]) -> None:
3235
"""Check that each ingredient is valid."""
3336
if any(item.data is None or item.data.num != 1 for item in value):
3437
raise ValueError("Each item in the list has to have a count of 1.")
3538

36-
count: int = field(validator=validators.ge(1))
37-
items: set[Slot] = field(validator=check_quantity.__get__(object))
38-
3939
@override
4040
def serialize_to(self, buf: Buffer) -> None:
4141
buf.write_varint(self.count)

0 commit comments

Comments
 (0)