Skip to content

Commit 74a2e38

Browse files
committed
Deprecated HistoricalRecords.thread
`HistoricalRecords.context` was added in favor of it a few years ago, and since it has always been undocumented, it's time to properly deprecate it. 4.0 would have been the natural version to remove it if it were documented as part of the publicly exposed API, but since it's not, 3.10 seems like a reasonable choice. Also removed importing `threading.local` in case `asgiref.local.Local` is not available, as the latter should always be installed now that all our supported Django versions use it as a requirement.
1 parent 7fdebc8 commit 74a2e38

File tree

3 files changed

+55
-8
lines changed

3 files changed

+55
-8
lines changed

CHANGES.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,19 @@ Changes
44
Unreleased
55
----------
66

7+
**What's new:**
8+
79
- Made ``skip_history_when_saving`` work when creating an object - not just when
810
updating an object (gh-1262)
11+
12+
**Deprecations:**
13+
14+
- Deprecated the undocumented ``HistoricalRecords.thread`` - use
15+
``HistoricalRecords.context`` instead. The former attribute will be removed in
16+
version 3.10 (gh-1387)
17+
18+
**Fixes and improvements:**
19+
920
- Improved performance of the ``latest_of_each()`` history manager method (gh-1360)
1021

1122
3.7.0 (2024-05-29)

simple_history/models.py

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,20 @@
44
import warnings
55
from dataclasses import dataclass
66
from functools import partial
7-
from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Sequence, Type, Union
7+
from typing import (
8+
TYPE_CHECKING,
9+
Any,
10+
ClassVar,
11+
Dict,
12+
Iterable,
13+
List,
14+
Sequence,
15+
Type,
16+
Union,
17+
)
818

919
import django
20+
from asgiref.local import Local
1021
from django.apps import apps
1122
from django.conf import settings
1223
from django.contrib import admin
@@ -45,11 +56,6 @@
4556
pre_create_historical_record,
4657
)
4758

48-
try:
49-
from asgiref.local import Local as LocalContext
50-
except ImportError:
51-
from threading import local as LocalContext
52-
5359
if TYPE_CHECKING:
5460
ModelTypeHint = models.Model
5561
else:
@@ -83,9 +89,20 @@ def _history_user_setter(historical_instance, user):
8389
class HistoricalRecords:
8490
DEFAULT_MODEL_NAME_PREFIX = "Historical"
8591

86-
thread = context = LocalContext() # retain thread for backwards compatibility
92+
context: ClassVar = Local()
8793
m2m_models = {}
8894

95+
class _DeprecatedThreadDescriptor:
96+
def __get__(self, *args, **kwargs):
97+
warnings.warn(
98+
"Use 'HistoricalRecords.context' instead."
99+
" The 'thread' attribute will be removed in version 3.10.",
100+
DeprecationWarning,
101+
)
102+
return HistoricalRecords.context
103+
104+
thread: ClassVar = _DeprecatedThreadDescriptor()
105+
89106
def __init__(
90107
self,
91108
verbose_name=None,
Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,32 @@
11
import unittest
22

33
from simple_history import __version__
4+
from simple_history.models import HistoricalRecords
45
from simple_history.templatetags.simple_history_admin_list import display_list
56

67

78
class DeprecationWarningTest(unittest.TestCase):
8-
def test__display_list__warns_deprecation_and_is_yet_to_be_removed(self):
9+
def test__display_list__warns_deprecation(self):
910
with self.assertWarns(DeprecationWarning):
1011
display_list({})
1112
# DEV: `display_list()` (and the file `simple_history_admin_list.py`) should be
1213
# removed when 3.8 is released
1314
self.assertLess(__version__, "3.8")
15+
16+
def test__HistoricalRecords_thread__warns_deprecation(self):
17+
with self.assertWarns(DeprecationWarning):
18+
context = HistoricalRecords.thread
19+
self.assertIs(context, HistoricalRecords.context)
20+
with self.assertWarns(DeprecationWarning):
21+
context = getattr(HistoricalRecords, "thread")
22+
self.assertIs(context, HistoricalRecords.context)
23+
with self.assertWarns(DeprecationWarning):
24+
context = HistoricalRecords().thread
25+
self.assertIs(context, HistoricalRecords.context)
26+
with self.assertWarns(DeprecationWarning):
27+
context = getattr(HistoricalRecords(), "thread")
28+
self.assertIs(context, HistoricalRecords.context)
29+
30+
# DEV: `_DeprecatedThreadDescriptor` and the `thread` attribute of
31+
# `HistoricalRecords` should be removed when 3.10 is released
32+
self.assertLess(__version__, "3.10")

0 commit comments

Comments
 (0)