Skip to content

Commit 20ae626

Browse files
committed
Separate ApiStructArray
1 parent 42078e3 commit 20ae626

3 files changed

Lines changed: 73 additions & 31 deletions

File tree

kafka/protocol/new/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# These need to get registered before ApiMessage metaclass starts building classes
22
from .field_basic import FieldBasicType
3-
from .api_array import ApiArray
43
from .api_struct import ApiStruct
4+
from .api_array import ApiArray
5+
from .api_struct_array import ApiStructArray
56

67
from .api_message import ApiMessage
78
from .api_header import ApiHeader, RequestHeader, ResponseHeader

kafka/protocol/new/api_array.py

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from .field import Field
2+
from .field_basic import FieldBasicType
23
from ..types import (
34
Array, CompactArray,
45
UnsignedVarInt32, Int32,
@@ -7,44 +8,37 @@
78

89
class ApiArray(Field):
910
@classmethod
10-
def parse_json(cls, json):
11+
def parse_inner_type(cls, json):
12+
if 'fields' in json:
13+
return
14+
type_str = cls.parse_array_type(json)
15+
if type_str is not None:
16+
inner_json = {**json, 'type': type_str}
17+
return FieldBasicType.parse_json(inner_json)
18+
19+
@classmethod
20+
def parse_array_type(cls, json):
1121
if json['type'].startswith('[]'):
12-
inner_type_str = json['type'][2:]
13-
if inner_type_str.startswith('[]'): # this would be strange...
14-
return None
15-
inner_json = {**json, 'type': inner_type_str}
16-
inner_type = super().parse_json(inner_json)
17-
if inner_type is not None:
18-
return cls(json, array_of=inner_type)
22+
type_str = json['type'][2:]
23+
assert not type_str.startswith('[]'), 'Unexpected double-array type: %s' % json['type']
24+
return type_str
25+
26+
@classmethod
27+
def parse_json(cls, json):
28+
inner_type = cls.parse_inner_type(json)
29+
if inner_type is not None:
30+
return cls(json, array_of=inner_type)
1931

2032
def __init__(self, json, array_of=None):
33+
if array_of is None:
34+
array_of = self.parse_inner_type(json)
35+
assert array_of is not None, 'json does not contain a (simple) Array!'
2136
super().__init__(json)
22-
self.array_of = array_of # Field (ApiStruct or FieldBasicType)
37+
self.array_of = array_of # FieldBasicType
2338

2439
def is_array(self):
2540
return True
2641

27-
def is_struct_array(self):
28-
return self.array_of.is_struct()
29-
30-
@property
31-
def fields(self):
32-
if self.is_struct_array():
33-
return self.array_of.fields
34-
35-
def has_data_class(self):
36-
return self.is_struct_array()
37-
38-
@property
39-
def data_class(self):
40-
if self.has_data_class():
41-
return self.array_of.data_class
42-
else:
43-
raise ValueError('Non-struct field does not have a data_class!')
44-
45-
def __call__(self, *args, **kw):
46-
return self.data_class(*args, **kw) # pylint: disable=E1102
47-
4842
def to_schema(self, version, compact=False, tagged=False):
4943
if not self.for_version_q(version) or self.tagged_field_q(version):
5044
return None
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
from .api_array import ApiArray
2+
from .api_struct import ApiStruct
3+
4+
5+
class ApiStructArray(ApiArray):
6+
@classmethod
7+
def parse_inner_type(cls, json):
8+
# ApiStructArray requires non-empty fields
9+
if 'fields' not in json:
10+
return
11+
assert len(json['fields']) > 0, 'Unexpected empty fields in json'
12+
type_str = cls.parse_array_type(json)
13+
if type_str is None:
14+
return
15+
inner_json = {**json, 'type': type_str}
16+
return ApiStruct.parse_json(inner_json)
17+
18+
@classmethod
19+
def parse_json(cls, json):
20+
inner_type = cls.parse_inner_type(json)
21+
if inner_type is not None:
22+
return cls(json, array_of=inner_type)
23+
24+
def __init__(self, json, array_of=None):
25+
if array_of is None:
26+
array_of = self.parse_inner_type(json)
27+
assert array_of is not None, 'json does not contain a StructArray!'
28+
super().__init__(json, array_of=array_of)
29+
# map_key will be (idx, field) of the mapKey field if found
30+
self.map_key = next(lambda i, field: field._json.get('mapKey'), enumerate(self._fields), None)
31+
32+
def is_struct_array(self):
33+
return True
34+
35+
@property
36+
def fields(self):
37+
return self.array_of.fields
38+
39+
def has_data_class(self):
40+
return True
41+
42+
@property
43+
def data_class(self):
44+
return self.array_of.data_class
45+
46+
def __call__(self, *args, **kw):
47+
return self.data_class(*args, **kw) # pylint: disable=E1102

0 commit comments

Comments
 (0)