Skip to content

Commit f4f698d

Browse files
committed
add cookbook chapter in doc
1 parent 2068356 commit f4f698d

File tree

9 files changed

+205
-6
lines changed

9 files changed

+205
-6
lines changed

.drone.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@ steps:
2626
- >
2727
docker run --restart=always --name=pywebio-demos -v $PWD:/app_tmp
2828
--label="traefik.http.services.pywebiodemos.loadbalancer.server.port=80"
29-
-d python:3 bash -c "cp -r /app_tmp /app && cd /app && pip3 install . && python3 -m demos --port=80"
29+
-d python:3 bash -c "cp -r /app_tmp /app && cd /app && pip3 install . && pip3 install -r requirements.txt && python3 -m demos --port=80"
3030
- sleep 5 # wait container start

.github/workflows/lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
- name: Install dependencies
2121
run: |
2222
python -m pip install --upgrade pip
23-
pip install -r requirements.txt
23+
pip install -e ".[all]"
2424
- name: Lint with flake8
2525
run: |
2626
pip install flake8

.github/workflows/sync_repo.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ jobs:
2626
- name: Build doc demos
2727
run: |
2828
pip3 install -e ".[all]"
29-
cd docs && CODE_EXPORT_PATH=../demos/doc_demos make clean text
29+
pip3 install -r requirements.txt
30+
cd docs && CODE_EXPORT_PATH=../demos/doc_demos make clean html
3031
- name: Set dev version
3132
run: python3 tools/build_dev_version.py
3233
- name: Push

docs/conf.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@
3333
"sphinx.ext.viewcode",
3434
'sphinx_tabs.tabs',
3535
'sphinx.ext.extlinks',
36-
'codeblock'
36+
'codeblock',
37+
'sphinx_toolbox.collapse',
3738
]
3839

3940
primary_domain = "py"

docs/cookbook.rst

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
Cookbook
2+
==========================
3+
4+
.. contents::
5+
:local:
6+
7+
Interaction related
8+
----------------------------------------------------------------------------------------------
9+
10+
Equivalent to "Press any key to continue"
11+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
.. exportable-codeblock::
14+
:name: cookbook-press-anykey-continue
15+
:summary: Press any key to continue
16+
17+
actions(buttons=["Continue"])
18+
put_text("Go next") # ..demo-only
19+
20+
21+
Output pandas dataframe
22+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
23+
24+
.. exportable-codeblock::
25+
:name: cookbook-pandas-df
26+
:summary: Output pandas dataframe
27+
28+
import numpy as np
29+
import pandas as pd
30+
31+
df = pd.DataFrame(np.random.randn(6, 4), columns=list("ABCD"))
32+
put_html(df.to_html(border=0))
33+
34+
.. seealso:: `pandas.DataFrame.to_html — pandas documentation <https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_html.html#pandas-dataframe-to-html>`_
35+
36+
Output Matplotlib figure
37+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
38+
39+
Simply do not call ``matplotlib.pyplot.show``, directly save the figure to in-memory buffer and output the buffer
40+
via :func:`pywebio.output.put_image`:
41+
42+
.. exportable-codeblock::
43+
:name: cookbook-matplotlib
44+
:summary: Output Matplotlib plot
45+
46+
import matplotlib
47+
import matplotlib.pyplot as plt
48+
import io
49+
import pywebio
50+
51+
matplotlib.use('agg') # required, use a non-interactive backend
52+
53+
fig, ax = plt.subplots() # Create a figure containing a single axes.
54+
ax.plot([1, 2, 3, 4], [1, 4, 2, 3]) # Plot some data on the axes.
55+
56+
buf = io.BytesIO()
57+
fig.savefig(buf)
58+
pywebio.output.put_image(buf.getvalue())
59+
60+
The ``matplotlib.use('agg')`` is required so that the server does not try to create (and then destroy) GUI windows
61+
that will never be seen.
62+
63+
When using Matplotlib in a web server (multiple threads environment), pyplot may cause some conflicts in some cases,
64+
read the following articles for more information:
65+
66+
* `Multi Threading in Python and Pyplot | by Ranjitha Korrapati | Medium <https://medium.com/@ranjitha.korrapati/multi-threading-in-python-and-pyplot-46f325e6a9d0>`_
67+
68+
* `Embedding in a web application server (Flask) — Matplotlib documentation <https://matplotlib.org/stable/gallery/user_interfaces/web_application_server_sgskip.html>`_
69+
70+
71+
Blocking confirm model
72+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
73+
74+
.. collapse:: Code
75+
76+
.. exportable-codeblock::
77+
:name: cookbook-confirm-model
78+
:summary: Blocking confirm model
79+
80+
import threading
81+
from pywebio import output
82+
83+
def confirm(title, content=None, timeout=None):
84+
"""Show a confirm model.
85+
86+
:param str title: Model title.
87+
:param list/put_xxx() content: Model content.
88+
:param None/float timeout: Seconds for operation time out.
89+
:return: Return `True` when the "CONFIRM" button is clicked,
90+
return `False` when the "CANCEL" button is clicked,
91+
return `None` when a timeout is given and the operation times out.
92+
"""
93+
if not isinstance(content, list):
94+
content = [content]
95+
96+
event = threading.Event()
97+
result = None
98+
99+
def onclick(val):
100+
nonlocal result
101+
result = val
102+
event.set()
103+
104+
content.append(output.put_buttons([
105+
{'label': 'CONFIRM', 'value': True},
106+
{'label': 'CANCEL', 'value': False, 'color': 'danger'},
107+
], onclick=onclick))
108+
output.popup(title=title, content=content, closable=False)
109+
110+
event.wait(timeout=timeout) # wait the model buttons are clicked
111+
output.close_popup()
112+
return result
113+
114+
115+
res = confirm('Confirm', 'You have 5 seconds to make s choice', timeout=5)
116+
output.put_text("Your choice is:", res)
117+
118+
119+
120+
Web application related
121+
----------------------------------------------------------------------------------------------
122+
123+
Get URL parameters of current page
124+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
125+
126+
You can use URL parameter (known also as "query strings" or "URL query parameters") to pass information to your web
127+
application. In PyWebIO application, you can use the following code to get the URL parameters as a Python dict.
128+
129+
.. exportable-codeblock::
130+
:name: cookbook-url-query
131+
:summary: Get URL parameters of current page
132+
133+
# `query` is a dict
134+
query = eval_js("Object.fromEntries(new URLSearchParams(window.location.search))")
135+
put_text(query)
136+
137+
138+
Add Google AdSense/Analytics code
139+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
140+
141+
When you setup Google AdSense/Analytics, you will get a javascript file and a piece of code that needs to be inserted
142+
into your application page, you can use :func:`pywebio.config()` to inject js file and code to your PyWebIO application::
143+
144+
from pywebio import start_server, output, config
145+
146+
js_file = "https://www.googletagmanager.com/gtag/js?id=G-xxxxxxx"
147+
js_code = """
148+
window.dataLayer = window.dataLayer || [];
149+
function gtag(){dataLayer.push(arguments);}
150+
gtag('js', new Date());
151+
152+
gtag('config', 'G-xxxxxxx');
153+
"""
154+
155+
@config(js_file=js_file, js_code=js_code)
156+
def main():
157+
output.put_text("hello world")
158+
159+
start_server(main, port=8080)
160+
161+
162+
Refresh page on connection lost
163+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
164+
165+
Add the following code to the beginning of your PyWebIO application main function::
166+
167+
session.run_js('WebIO._state.CurrentSession.on_session_close(()=>{setTimeout(()=>location.reload(), 4000})')
168+

docs/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ This documentation is also available in `PDF and Epub formats <https://readthedo
9494
.. toctree::
9595
:titlesonly:
9696

97-
FAQ
97+
cookbook
9898
releases
9999

100100
.. toctree::

docs/static/pywebio.css

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,16 @@ td .line-block {
4444
top: 4px;
4545
padding-left: 0px;
4646
background-color: #f8f8f8;
47+
}
48+
49+
details {
50+
margin-bottom: 24px;
51+
}
52+
53+
/*Adjust ``.. contents::`` style */
54+
.contents li>p{
55+
margin-bottom: 0px!important;
56+
}
57+
.contents ul{
58+
margin-bottom: 8px!important;
4759
}

pywebio/input.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,18 @@ def file_upload(label='', accept=None, name=None, placeholder='Choose file', mul
590590
:func:`path_deploy() <pywebio.platform.path_deploy>` to start the PyWebIO application,
591591
the maximum file size to be uploaded allowed by the web framework can be set through the ``max_payload_size`` parameter.
592592
593+
.. exportable-codeblock::
594+
:name: file_upload_example
595+
:summary: `file_upload()` example
596+
597+
# Upload a file and save to server # ..doc-only
598+
f = input.file_upload("Upload a file") # ..doc-only
599+
open('asset/'+f['filename'], 'wb').write(f['content']) # ..doc-only
600+
601+
imgs = file_upload("Select some pictures:", accept="image/*", multiple=True)
602+
for img in imgs:
603+
put_image(img['content'])
604+
593605
"""
594606
item_spec, valid_func, onchange_func = _parse_args(locals())
595607
item_spec['type'] = 'file'

requirements.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,9 @@ coverage
2323
# doc building requirements
2424
sphinx==3.*
2525
sphinx-tabs
26-
sphinx-rtd-theme==0.4.*
26+
sphinx-rtd-theme==0.4.*
27+
sphinx-toolbox==2.15.0
28+
29+
# demo running requirements
30+
numpy
31+
matplotlib

0 commit comments

Comments
 (0)