Skip to content

Commit 1e9e1e6

Browse files
delsimGibbsConsulting
authored andcommitted
Add an extra hook for locating and loading stateless apps (#168)
* Add an extra hook for locating and loading stateless apps * Fix typo in test * Update prerelease version number * Update test for dash app sideloading
1 parent 55ddc50 commit 1e9e1e6

File tree

7 files changed

+71
-5
lines changed

7 files changed

+71
-5
lines changed

demo/demo/scaffold.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
'Test harness code'
2+
3+
from django_plotly_dash import DjangoDash
4+
from django.utils.module_loading import import_string
5+
6+
def stateless_app_loader(app_name):
7+
8+
# Load a stateless app
9+
return import_string("demo.scaffold." + app_name)
10+
11+
demo_app = DjangoDash(name="name_of_demo_app")
12+

demo/demo/settings.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@
141141
"cache_arguments" : True, # True for cache, False for session-based argument propagation
142142

143143
#"serve_locally" : True, # True to serve assets locally, False to use their unadulterated urls (eg a CDN)
144+
145+
"stateless_loader" : "demo.scaffold.stateless_app_loader",
144146
}
145147

146148
# Static files (CSS, JavaScript, Images)

demo/demo/tests/test_demo_app.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,18 @@ def test_app_callbacks():
8787
assert liveOut
8888

8989
# TODO need something to trigger callbacks
90+
91+
def test_stateless_lookup():
92+
'Test side loading of stateless apps'
93+
94+
from django_plotly_dash.util import stateless_app_lookup_hook
95+
lh_hook = stateless_app_lookup_hook()
96+
97+
with pytest.raises(ImportError):
98+
lh_hook("not a real app name")
99+
100+
demo_app = lh_hook('demo_app')
101+
102+
assert demo_app is not None
103+
assert demo_app._uid == 'name_of_demo_app'
104+

django_plotly_dash/dash_wrapper.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,14 @@
4141

4242
from .util import static_asset_path
4343
from .util import serve_locally as serve_locally_setting
44+
from .util import stateless_app_lookup_hook
4445

4546
uid_counter = 0
4647

4748
usable_apps = {}
4849

50+
_stateless_app_lookup_func = None
51+
4952
def add_usable_app(name, app):
5053
'Add app to local registry by name'
5154
name = slugify(name)
@@ -62,12 +65,24 @@ def get_local_stateless_by_name(name):
6265
Locate a registered dash app by name, and return a DjangoDash instance encapsulating the app.
6366
'''
6467
name = slugify(name)
65-
# TODO wrap this in raising a 404 if not found
66-
try:
67-
return usable_apps[name]
68-
except:
68+
69+
sa = usable_apps.get(name, None)
70+
71+
if not sa:
72+
73+
global _stateless_app_lookup_func # pylint: disable=global-statement
74+
75+
if _stateless_app_lookup_func is None:
76+
_stateless_app_lookup_func = stateless_app_lookup_hook()
77+
78+
sa = stateless_app_lookup_func(name)
79+
80+
if not sa:
81+
# TODO wrap this in raising a 404 if not found
6982
raise KeyError("Unable to find stateless DjangoApp called %s"%name)
7083

84+
return sa
85+
7186
class Holder:
7287
'Helper class for holding configuration options'
7388
def __init__(self):

django_plotly_dash/tests.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,16 @@ def test_argument_settings(settings, client):
253253
assert store_initial_arguments(client, None) is None
254254
assert get_initial_arguments(client, None) is None
255255

256+
def test_stateless_lookup_noop():
257+
'Test no-op stateless lookup'
258+
259+
from django_plotly_dash.util import stateless_app_lookup_hook
260+
lh_hook = stateless_app_lookup_hook()
261+
262+
assert lh_hook is not None
263+
with pytest.raises(ImportError):
264+
lh_hook("not an app")
265+
256266
def test_middleware_artifacts():
257267
'Import and vaguely exercise middleware objects'
258268

django_plotly_dash/util.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
from django.conf import settings
2929
from django.core.cache import cache
30+
from django.utils.module_loading import import_string
3031

3132
def _get_settings():
3233
try:
@@ -117,3 +118,14 @@ def static_path(relative_path):
117118
except:
118119
static_url = '/static/'
119120
return "%s%s" %(static_url, relative_path)
121+
122+
def stateless_app_lookup_hook():
123+
'Return a function that performs lookup for aa stateless app, given its name, or returns None'
124+
125+
func_name = _get_settings().get('stateless_loader', None)
126+
if func_name:
127+
func = import_string(func_name)
128+
return func
129+
130+
# Default is no additional lookup
131+
return lambda _: None

django_plotly_dash/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@
2323
2424
'''
2525

26-
__version__ = "0.9.13"
26+
__version__ = "0.9.14"

0 commit comments

Comments
 (0)