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

try to fix problem of inlcude files with same name in different path #275

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
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
66 changes: 42 additions & 24 deletions thriftpy/parser/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,20 @@ def p_header_unit(p):
def p_include(p):
'''include : INCLUDE LITERAL'''
thrift = thrift_stack[-1]

if thrift.__thrift_file__ is None:
raise ThriftParserError('Unexcepted include statement while loading'
'from file like object.')

for include_dir in include_dirs_:
replace_include_dirs = [os.path.dirname(thrift.__thrift_file__)] \
+ include_dirs_
for include_dir in replace_include_dirs:
path = os.path.join(include_dir, p[2])
if os.path.exists(path):
child = parse(path)
setattr(thrift, child.__name__, child)
child_list = getattr(thrift, child.__name__, None)
if child_list is None:
child_list = []
child_list.append(child)
setattr(thrift, child.__name__, child_list) # modified
_add_thrift_meta('includes', child)
return
raise ThriftParserError(('Couldn\'t include thrift %s in any '
Expand Down Expand Up @@ -153,20 +157,21 @@ def p_const_map_item(p):
def p_const_ref(p):
'''const_ref : IDENTIFIER'''
child = thrift_stack[-1]

for name in p[1].split('.'):
father = child
child = getattr(child, name, None)
if child is None:
child_list = getattr(child, name, None)
if child_list is None:
raise ThriftParserError('Cann\'t find name %r at line %d'
% (p[1], p.lineno(1)))

if _get_ttype(child) is None or _get_ttype(father) == TType.I32:
# child is a constant or enum value
p[0] = child
else:
raise ThriftParserError('No enum value or constant found '
'named %r' % p[1])
for child in child_list:
if _get_ttype(child) is None or _get_ttype(father) == TType.I32:
# child is a constant or enum value
p[0] = child
break
else:
raise ThriftParserError('No enum value or constant found '
'named %r' % p[1])


def p_ttype(p):
Expand Down Expand Up @@ -249,7 +254,15 @@ def p_service(p):
if len(p) == 8:
extends = thrift
for name in p[4].split('.'):
extends = getattr(extends, name, None)
if isinstance(extends, list):
for e in extends:
temp = getattr(e, name, None)
if temp:
extends = temp
break
else:
extends = getattr(extends, name, None)

if extends is None:
raise ThriftParserError('Can\'t find service %r for '
'service %r to extend' %
Expand Down Expand Up @@ -359,10 +372,19 @@ def p_ref_type(p):
ref_type = thrift_stack[-1]

for name in p[1].split('.'):
ref_type = getattr(ref_type, name, None)
if ref_type is None:
raise ThriftParserError('No type found: %r, at line %d' %
(p[1], p.lineno(1)))
if isinstance(ref_type, list):
for r in ref_type:
temp = getattr(r, name, None)
if temp:
ref_type = temp
break
else:
ref_type = getattr(ref_type, name, None)

if ref_type is None:
raise ThriftParserError('No type found: %r, at line %d' %
(p[1], p.lineno(1)))


if hasattr(ref_type, '_ttype'):
p[0] = getattr(ref_type, '_ttype'), ref_type
Expand Down Expand Up @@ -433,11 +455,9 @@ def p_definition_type(p):
def parse(path, module_name=None, include_dirs=None, include_dir=None,
lexer=None, parser=None, enable_cache=True):
"""Parse a single thrift file to module object, e.g.::

>>> from thriftpy.parser.parser import parse
>>> note_thrift = parse("path/to/note.thrift")
<module 'note_thrift' (built-in)>

:param path: file path to parse, should be a string ending with '.thrift'.
:param module_name: the name for parsed module, the default is the basename
without extension of `path`.
Expand Down Expand Up @@ -509,12 +529,10 @@ def parse(path, module_name=None, include_dirs=None, include_dir=None,

def parse_fp(source, module_name, lexer=None, parser=None, enable_cache=True):
"""Parse a file-like object to thrift module object, e.g.::

>>> from thriftpy.parser.parser import parse_fp
>>> with open("path/to/note.thrift") as fp:
parse_fp(fp, "note_thrift")
<module 'note_thrift' (built-in)>

:param source: file-like object, expected to have a method named `read`.
:param module_name: the name for parsed module, shoule be endswith
'_thrift'.
Expand Down Expand Up @@ -609,7 +627,7 @@ def _cast_bool(v):


def _cast_byte(v):
assert isinstance(v, str)
assert isinstance(v, int)
return v


Expand Down Expand Up @@ -817,4 +835,4 @@ def _ttype_spec(ttype, name, required=False):
def _get_ttype(inst, default_ttype=None):
if hasattr(inst, '__dict__') and '_ttype' in inst.__dict__:
return inst.__dict__['_ttype']
return default_ttype
return default_ttype