Skip to content

Commit 4257c9b

Browse files
committed
PB-1920: Fix AttributeError: '_thread._local' object has no attribute 'data'
1 parent f643e26 commit 4257c9b

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

logging_utilities/context/thread_context.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,42 @@ class ThreadMappingContext(BaseContext):
1414

1515
def __init__(self):
1616
self.__local = threading.local()
17-
self.__local.data = {}
17+
self.ensure_data()
18+
19+
def ensure_data(self):
20+
if not hasattr(self.__local, 'data'):
21+
self.__local.data = {}
1822

1923
def __str__(self):
24+
self.ensure_data()
2025
return str(self.__local.data)
2126

2227
def __getitem__(self, __key):
28+
self.ensure_data()
2329
return self.__local.data[__key]
2430

2531
def __setitem__(self, __key, __value):
32+
self.ensure_data()
2633
self.__local.data[__key] = __value
2734

2835
def __delitem__(self, __key):
36+
self.ensure_data()
2937
del self.__local.data[__key]
3038

3139
def __len__(self):
40+
self.ensure_data()
3241
return len(self.__local.data)
3342

3443
def __iter__(self):
44+
self.ensure_data()
3545
return self.__local.data.__iter__()
3646

3747
def __contains__(self, __o):
48+
self.ensure_data()
3849
return self.__local.data.__contains__(__o)
3950

4051
def init(self, data=None):
52+
self.ensure_data()
4153
if data is None:
4254
self.__local.data = {}
4355
else:
@@ -46,18 +58,23 @@ def init(self, data=None):
4658
self.__local.data = data
4759

4860
def get(self, key, default=None):
61+
self.ensure_data()
4962
return self.__local.data.get(key, default)
5063

5164
def pop(self, key, default=__marker):
65+
self.ensure_data()
5266
if default == self.__marker:
5367
return self.__local.data.pop(key)
5468
return self.__local.data.pop(key, default)
5569

5670
def set(self, key, value):
71+
self.ensure_data()
5772
self.__local.data[key] = value
5873

5974
def delete(self, key):
75+
self.ensure_data()
6076
del self.__local.data[key]
6177

6278
def clear(self):
79+
self.ensure_data()
6380
self.__local.data = {}

tests/test_logging_context.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import unittest
33
from concurrent.futures import ThreadPoolExecutor
44
from concurrent.futures import as_completed
5+
from threading import Thread
56

67
from logging_utilities.context import get_logging_context
78
from logging_utilities.context import remove_logging_context
@@ -125,6 +126,21 @@ def test_thread_context_str(self):
125126
ctx.init({'a': 1, 'b': 2, 'c': 'my string'})
126127
self.assertEqual(str(ctx), "{'a': 1, 'b': 2, 'c': 'my string'}")
127128

129+
def test_thread_context_local_data(self):
130+
ctx = ThreadMappingContext()
131+
ctx['thread'] = 'main'
132+
results = {}
133+
134+
def worker():
135+
assert 'thread' not in ctx
136+
ctx['thread'] = 'worker'
137+
138+
t = Thread(target=worker)
139+
t.start()
140+
t.join()
141+
142+
assert ctx['thread'] == 'main'
143+
128144

129145
class LoggingContextTest(unittest.TestCase):
130146

0 commit comments

Comments
 (0)