For use in your UseThatApp Web Apps
Project description
Summary
Use this package with your UseThatApp WebApps to acquire user license info from UseThatApp.com.
Usage
Single Page Dash App
In a simple single page Dash-Plotly application.
from dash import Dash, dcc, html, Input, Output, ClientsideFunction
from usethatapp.webapps import get_product
app = Dash(__name__, external_scripts=[
"https://cdn.jsdelivr.net/gh/UseThatApp/cdn@latest/usethatapp.js"
])
app.layout = html.Div([
dcc.Location(id='url', refresh=False),
html.Div(id='content'),
dcc.Store(id='access-level-store', data=None, storage_type='memory'),
])
app.clientside_callback(
ClientsideFunction(namespace='clientside', function_name='requestAccessLevel'),
Output("access-level-store", "data"),
Input('url', 'pathname')
)
@app.callback(
Output('content', 'children'),
Input("access-level-store", "data")
)
def display_content_based_on_access(data):
try:
product = get_product(
data['message'],
public_key_path=r'/Path/To/File/Containing/UseThatApp_Public_Key',
private_key_path=r'/Path/To/File/Containing/My_UTA_Private_Key'
)
# display content based on licensed plan
if product == 'Pro':
return html.Div([html.H1(["Paid Content"])])
except Exception as e:
# If there's an error (e.g. clientside hasn't populated the store yet), fall back to free content
app.logger.exception("Error determining product: %s", e)
return html.Div([html.H1(["Free Content"])])
Mult-Page Dash App
In a multi-page Dash-Plotly application (using Dash Pages). The pattern below mirrors the single-page example: the main app registers a clientside callback that places the UseThatApp message into a dcc.Store, and each page reads that store (via a callback) and calls get_product to decide what to render.
app.py
import dash
from dash import Dash, html, dcc, Input, Output, ClientsideFunction
APP_TITLE = "Dash App"
app = Dash(
__name__,
title=APP_TITLE,
use_pages=True, # Allows us to register pages
external_scripts=["https://cdn.jsdelivr.net/gh/UseThatApp/cdn@latest/usethatapp.js"],
)
# Top-level layout includes Location, a Store for the access payload, and the page container
app.layout = html.Div([
dcc.Location(id='url', refresh=False),
dcc.Store(id='access-level-store', data=None, storage_type='memory'),
dash.page_container,
])
# Register the same clientside callback used in the single-page example to populate the store
app.clientside_callback(
ClientsideFunction(namespace='clientside', function_name='requestAccessLevel'),
Output('access-level-store', 'data'),
Input('url', 'pathname')
)
server = app.server
if __name__ == '__main__':
app.run_server(debug=True)
pages/home.py
from dash import html, register_page, Input, Output, dash
from usethatapp.webapps import get_product
register_page(
__name__,
name='Home',
path='/'
)
# Page layout is a placeholder container which we'll populate via a callback that
# listens to the shared `access-level-store` placed by the clientside JS.
def layout(**url_vars):
return html.Div(id='home-content')
# Use dash.callback (so the callback is registered on the global app when pages are loaded)
@dash.callback(Output('home-content', 'children'), Input('access-level-store', 'data'))
def display_content_based_on_access(data):
# Use the helper function to parse the message and determine the licensed product
try:
product = get_product(
data['message'],
public_key_path=r'/Path/To/File/Containing/UseThatApp_Public_Key',
private_key_path=r'/Path/To/File/Containing/My_UTA_Private_Key'
)
if product == 'Pro':
return html.Div([html.H1(["Paid Content"])])
except Exception as e:
# If there's an error (e.g. clientside hasn't populated the store yet), fall back to free content
dash.get_app().server.logger.exception("Error determining product: %s", e)
return html.Div([html.H1(["Free Content"])])
Change Log
Version 0.1.0 (03/19/2026)
- Initial release
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file usethatapp-0.1.0.tar.gz.
File metadata
- Download URL: usethatapp-0.1.0.tar.gz
- Upload date:
- Size: 5.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0abdf57b02339b890a6b5065e96040f07de0c0134d7d0c12ad32f4e6d3704a98
|
|
| MD5 |
73ec2f4d50e548b7aab9fc3afe801f36
|
|
| BLAKE2b-256 |
373a0c0419f8db8a78ecdd7874b5b36c80ef7298aba543cb6fed5e77feb5998d
|
File details
Details for the file usethatapp-0.1.0-py3-none-any.whl.
File metadata
- Download URL: usethatapp-0.1.0-py3-none-any.whl
- Upload date:
- Size: 5.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
885e1d0411b3111dceab53cf7dd422fdad0759c72a2617a811d0ecc93da3579c
|
|
| MD5 |
2f700d8f67b7ced94a056b5819f0c825
|
|
| BLAKE2b-256 |
872b1fcbfb3cf025a18fd651a48f99aee9d6360e70800f126789b85aa28bca26
|