Skip to content

Commit

Permalink
Merge pull request #2800 from bagerard/bug_no_deref_thread_local
Browse files Browse the repository at this point in the history
Fix bug in mutable thread local related with no_dereference ctx manager
  • Loading branch information
bagerard authored Mar 4, 2024
2 parents 5e0a678 + 7b23027 commit 79dfcdb
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 4 deletions.
4 changes: 4 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ Development
===========
- (Fill this out as you fix issues and develop your features).

Changes in 0.28.1
=================
- Fix bug related with recent updates to no_dereference context manager #2799

Changes in 0.28.0
=================
- Fix for uuidRepresentation not read when provided in URI #2741
Expand Down
2 changes: 1 addition & 1 deletion mongoengine/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
)


VERSION = (0, 28, 0)
VERSION = (0, 28, 1)


def get_version():
Expand Down
8 changes: 6 additions & 2 deletions mongoengine/context_managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@
)


thread_locals = threading.local()
thread_locals.no_dereferencing_class = {}
class MyThreadLocals(threading.local):
def __init__(self):
self.no_dereferencing_class = {}


thread_locals = MyThreadLocals()


def no_dereferencing_active_for_class(cls):
Expand Down
42 changes: 41 additions & 1 deletion tests/test_context_managers.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import random
import time
import unittest
from threading import Thread

import pytest
from bson import DBRef
Expand All @@ -18,6 +21,29 @@
from tests.utils import MongoDBTestCase


class TestableThread(Thread):
"""
Wrapper around `threading.Thread` that propagates exceptions.
REF: https://gist.github.com/sbrugman/59b3535ebcd5aa0e2598293cfa58b6ab
"""

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.exc = None

def run(self):
try:
super().run()
except BaseException as e:
self.exc = e

def join(self, timeout=None):
super().join(timeout)
if self.exc:
raise self.exc


class TestContextManagers(MongoDBTestCase):
def test_set_write_concern(self):
class User(Document):
Expand Down Expand Up @@ -172,13 +198,27 @@ class Group(Document):
group = Group.objects.first()
assert isinstance(group.ref, DBRef)

# make sure its still off here
# make sure it's still off here
group = Group.objects.first()
assert isinstance(group.ref, DBRef)

group = Group.objects.first()
assert isinstance(group.ref, User)

def run_in_thread(id):
time.sleep(random.uniform(0.1, 0.5)) # Force desync of threads
if id % 2 == 0:
with no_dereference(Group):
group = Group.objects.first()
assert isinstance(group.ref, DBRef)
else:
group = Group.objects.first()
assert isinstance(group.ref, User)

threads = [TestableThread(target=run_in_thread, args=(id,)) for id in range(10)]
_ = [th.start() for th in threads]
_ = [th.join() for th in threads]

def test_no_dereference_context_manager_dbref(self):
"""Ensure that DBRef items in ListFields aren't dereferenced"""

Expand Down

0 comments on commit 79dfcdb

Please sign in to comment.