Skip to content

Commit

Permalink
Initialize parser's threadlocal in parse_fp (#284)
Browse files Browse the repository at this point in the history
  • Loading branch information
aisk authored Jun 28, 2024
1 parent 1bd814a commit e4baaf5
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 1 deletion.
30 changes: 29 additions & 1 deletion tests/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import threading

import pytest

from thriftpy2.thrift import TType
from thriftpy2.parser import load, load_fp
from thriftpy2.parser.exc import ThriftParserError, ThriftGrammarError
Expand Down Expand Up @@ -43,7 +44,23 @@ def test_cpp_include():
load('parser-cases/cpp_include.thrift')


def test_load_in_sub_thread(reraise):
@pytest.fixture
def reset_parser_threadlocal():
def delattr_no_error(o, name):
try:
delattr(o, name)
except AttributeError:
pass

from thriftpy2.parser.parser import threadlocal
delattr_no_error(threadlocal, 'thrift_stack')
delattr_no_error(threadlocal, 'include_dirs_')
delattr_no_error(threadlocal, 'thrift_cache')
delattr_no_error(threadlocal, 'incomplete_type')
delattr_no_error(threadlocal, 'initialized')


def test_load_in_sub_thread(reraise, reset_parser_threadlocal):
@reraise.wrap
def f():
load('addressbook.thrift')
Expand All @@ -53,6 +70,17 @@ def f():
t.join()


def test_load_fp_in_sub_thread(reraise, reset_parser_threadlocal):
@reraise.wrap
def f():
with open('container.thrift') as fp:
load_fp(fp, 'container_thrift')

t = threading.Thread(target=f)
t.start()
t.join()


def test_tutorial():
thrift = load('parser-cases/tutorial.thrift', include_dirs=[
'./parser-cases'])
Expand Down
9 changes: 9 additions & 0 deletions thriftpy2/parser/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,15 @@ def parse_fp(source, module_name, lexer=None, parser=None, enable_cache=True):
:param enable_cache: if this is set to be `True`, parsed module will be
cached by `module_name`, this is enabled by default.
"""
# threadlocal should be initialized in every threads
initialized = getattr(threadlocal, 'initialized', None)
if initialized is None:
threadlocal.thrift_stack = []
threadlocal.include_dirs_ = ['.']
threadlocal.thrift_cache = {}
threadlocal.incomplete_type = CurrentIncompleteType()
threadlocal.initialized = True

if not module_name.endswith('_thrift'):
raise ThriftParserError('thriftpy2 can only generate module with '
'\'_thrift\' suffix')
Expand Down

0 comments on commit e4baaf5

Please sign in to comment.