Skip to content

Commit

Permalink
Make it possible to use dot notation for setting context in reflex
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jonathan-s committed Jul 27, 2021
1 parent 23f5bf4 commit a9bff7d
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 4 deletions.
8 changes: 8 additions & 0 deletions sockpuppet/consumer.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,14 @@ def render_page(self, reflex):
reflex_context = {key: getattr(reflex, key) for key in instance_variables}
reflex_context["stimulus_reflex"] = True

if not reflex.context._attr_data:
msg = (
"Setting context through instance variables is deprecated, "
'please use reflex.context.context_variable = "my_data"'
)
logger.warning(msg)
reflex_context.update(reflex.context)

original_context_data = view.view_class.get_context_data
reflex.get_context_data(**reflex_context)
# monkey patch context method
Expand Down
43 changes: 39 additions & 4 deletions sockpuppet/reflex.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,65 @@
from collections import UserDict
from django.urls import resolve
from urllib.parse import urlparse

from django.test import RequestFactory

PROTECTED_VARIABLES = [
"consumer",
"context",
"element",
"params",
"selectors",
"session",
"url",
]


class Context(UserDict):
"""
A dictionary that keeps track of whether it's been used as dictionary
or if values has been set with dot notation. We expect things to be set
in dot notation so a warning is issued until next major version (1.0)
"""

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._attr_data = {}

def __getitem__(self, key):
if not self.data.get(key) and not self._attr_data.get(key):
raise KeyError(key)
return self.data.get(key) or self._attr_data.get(key)

def __getattr__(self, key):
if not self.data.get(key) and not self._attr_data.get(key):
raise AttributeError(key)
return self.data.get(key) or self._attr_data.get(key)

def __setattr__(self, key, value):
self._attr_data[key] = value


class Reflex:
def __init__(self, consumer, url, element, selectors, params):
self.consumer = consumer
self.url = url
self.context = Context()
self.element = element
self.params = params
self.selectors = selectors
self.session = consumer.scope["session"]
self.params = params
self.context = {}
self.url = url

self._init_run = True

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

def __setattr__(self, name, value):
if name in PROTECTED_VARIABLES and getattr(self, "_init_run", None):
raise ValueError("This instance variable is used by the reflex.")
super().__setattr__(name, value)

def get_context_data(self, *args, **kwargs):
if self.context:
self.context.update(**kwargs)
Expand All @@ -45,7 +80,7 @@ def get_context_data(self, *args, **kwargs):

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

self.context = context
self.context.update(context)
self.context.update(**kwargs)
return self.context

Expand Down

0 comments on commit a9bff7d

Please sign in to comment.