Skip to content
This repository has been archived by the owner on Dec 10, 2018. It is now read-only.

Support implicit field keys #319

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
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
9 changes: 9 additions & 0 deletions tests/parser-cases/implicit_field_keys.thrift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
exception NetworkError {
string message,
i32 http_code,
}

service Service {
bool send(i64 id, string message)
throws (NetworkError network_error)
}
23 changes: 23 additions & 0 deletions tests/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,3 +281,26 @@ def test_doubles():
def test_annotations():
load('parser-cases/annotations.thrift')
load('parser-cases/issue_252.thrift')


def test_implicit_field_keys():
thrift = load('parser-cases/implicit_field_keys.thrift')
assert thrift.NetworkError.thrift_spec == {
-1: (TType.STRING, 'message', False),
-2: (TType.I32, 'http_code', False),
}
assert thrift.Service.thrift_services == ['send']
assert thrift.Service.send_args.thrift_spec == {
-1: (TType.I64, 'id', False),
-2: (TType.STRING, 'message', False),
}
assert thrift.Service.send_args.default_spec == [
('id', None), ('message', None)
]
assert thrift.Service.send_result.thrift_spec == {
0: (TType.BOOL, 'success', False),
-1: (TType.STRUCT, 'network_error', thrift.NetworkError, False)
}
assert thrift.Service.send_result.default_spec == [
('success', None), ('network_error', None)
]
31 changes: 24 additions & 7 deletions thriftpy/parser/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,21 +332,29 @@ def p_field_seq(p):


def p_simple_field(p):
'''simple_field : field_id field_req field_type IDENTIFIER
| field_id field_req field_type IDENTIFIER '=' const_value
'''
'''simple_field : field_req field_type IDENTIFIER
| field_req field_type IDENTIFIER '=' const_value
| field_id field_req field_type IDENTIFIER
| field_id field_req field_type IDENTIFIER '=' const_value
'''
if len(p) == 5 or len(p) == 7:
field_id = p[1]
field_req, field_type, identifier = p[2:5]
else:
field_id = None
field_req, field_type, identifier = p[1:4]

if len(p) == 7:
if len(p) >= 6:
try:
val = _cast(p[3])(p[6])
val = _cast(field_type)(p.slice[-1].value)
except AssertionError:
raise ThriftParserError(
'Type error for field %s '
'at line %d' % (p[4], p.lineno(4)))
'at line %d' % (identifier, p.lineno(4)))
else:
val = None

p[0] = [p[1], p[2], p[3], p[4], val]
p[0] = [field_id, field_req, field_type, identifier, val]


def p_field(p):
Expand Down Expand Up @@ -816,7 +824,16 @@ def _fill_in_struct(cls, fields, _gen_init=True):
default_spec = []
_tspec = {}

# Fields without explicit keys are automatically assigned starting from -1
# and working their way down. Implicit field keys are deprecated by Apache
# Thrift, but we support them for greater Thrift IDL compatibility.
next_implicit_id = -1

for field in fields:
if field[0] is None:
field[0] = next_implicit_id
next_implicit_id -= 1

if field[0] in thrift_spec or field[3] in _tspec:
raise ThriftGrammerError(('\'%d:%s\' field identifier/name has '
'already been used') % (field[0],
Expand Down