Skip to content

Commit b1778e1

Browse files
committed
Make it possible to use dot notation for setting context in reflex
In an effort to improve the api for setting the context that is used in the final context in the reflex we introduce a dot notation for setting the context. Ie `reflex.context.my_context = 'value'`. For the old way of setting the context in instance variables you now also prevented to set an instance variable that is already used by the reflex.
1 parent 23f5bf4 commit b1778e1

File tree

2 files changed

+48
-4
lines changed

2 files changed

+48
-4
lines changed

sockpuppet/consumer.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,14 @@ def render_page(self, reflex):
235235
reflex_context = {key: getattr(reflex, key) for key in instance_variables}
236236
reflex_context["stimulus_reflex"] = True
237237

238+
if not reflex.context._attr_data:
239+
msg = (
240+
"Setting context through instance variables is deprecated, "
241+
'please use reflex.context.context_variable = "my_data"'
242+
)
243+
logger.warning(msg)
244+
reflex_context.update(reflex.context)
245+
238246
original_context_data = view.view_class.get_context_data
239247
reflex.get_context_data(**reflex_context)
240248
# monkey patch context method

sockpuppet/reflex.py

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,66 @@
1+
from collections import UserDict
12
from django.urls import resolve
23
from urllib.parse import urlparse
34

45
from django.test import RequestFactory
56

67
PROTECTED_VARIABLES = [
78
"consumer",
9+
"context",
810
"element",
11+
"params",
912
"selectors",
1013
"session",
1114
"url",
1215
]
1316

1417

18+
class Context(UserDict):
19+
"""
20+
A dictionary that keeps track of whether it's been used as dictionary
21+
or if values has been set with dot notation. We expect things to be set
22+
in dot notation so a warning is issued until next major version (1.0)
23+
"""
24+
25+
def __init__(self, *args, **kwargs):
26+
super().__init__(*args, **kwargs)
27+
self._attr_data = {}
28+
29+
def _getitem(self, key):
30+
if not self.data.get(key) and not self._attr_data.get(key):
31+
raise KeyError(key)
32+
return self.data.get(key) or self._attr_data.get(key)
33+
34+
def __getitem__(self, key):
35+
return self._getitem(key)
36+
37+
def __getattr__(self, key):
38+
return self._getitem(key)
39+
40+
def __setattr__(self, key, value):
41+
self._attr_data[key] = value
42+
43+
1544
class Reflex:
1645
def __init__(self, consumer, url, element, selectors, params):
1746
self.consumer = consumer
18-
self.url = url
47+
self.context = Context()
1948
self.element = element
49+
self.params = params
2050
self.selectors = selectors
2151
self.session = consumer.scope["session"]
22-
self.params = params
23-
self.context = {}
52+
self.url = url
53+
54+
self._init_run = True
2455

2556
def __repr__(self):
2657
return f"<Reflex url: {self.url}, session: {self.get_channel_id()}>"
2758

59+
def __setattr__(self, name, value):
60+
if name in PROTECTED_VARIABLES and getattr(self, "_init_run", None):
61+
raise ValueError("This instance variable is used by the reflex.")
62+
super().__setattr__(name, value)
63+
2864
def get_context_data(self, *args, **kwargs):
2965
if self.context:
3066
self.context.update(**kwargs)
@@ -45,7 +81,7 @@ def get_context_data(self, *args, **kwargs):
4581

4682
context = view.get_context_data(**{"stimulus_reflex": True})
4783

48-
self.context = context
84+
self.context.update(context)
4985
self.context.update(**kwargs)
5086
return self.context
5187

0 commit comments

Comments
 (0)