AstraOS commited on
Commit
8621d18
·
verified ·
1 Parent(s): 5faeb27

Upload 173 files

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +57 -0
  2. .gitignore +163 -0
  3. .idea/pyscript-pwa-example.iml +25 -0
  4. README.md +26 -10
  5. app.py +50 -0
  6. readme-resources/screenshot.png +3 -0
  7. requirements.txt +1 -0
  8. static/css/site.css +121 -0
  9. static/images/icons/icon-128x128.png +0 -0
  10. static/images/icons/icon-144x144.png +0 -0
  11. static/images/icons/icon-152x152.png +0 -0
  12. static/images/icons/icon-192x192.png +0 -0
  13. static/images/icons/icon-384x384.png +0 -0
  14. static/images/icons/icon-512x512.png +0 -0
  15. static/images/icons/icon-72x72.png +0 -0
  16. static/images/icons/icon-96x96.png +0 -0
  17. static/images/weather/cloudy.png +0 -0
  18. static/images/weather/offline.png +0 -0
  19. static/images/weather/partlysunny.png +0 -0
  20. static/images/weather/rain.png +0 -0
  21. static/images/weather/sunny.png +0 -0
  22. static/js/pwa-scaffold.js +8 -0
  23. static/js/serviceWorker.js +52 -0
  24. static/js/site.js +0 -0
  25. static/manifest.json +43 -0
  26. static/pyodide/CLAPACK-3.2.1.zip +3 -0
  27. static/pyodide/Jinja2-3.1.1-py3-none-any.whl +3 -0
  28. static/pyodide/Logbook-1.5.3-cp310-cp310-emscripten_wasm32.whl +0 -0
  29. static/pyodide/MarkupSafe-2.1.1-cp310-cp310-emscripten_wasm32.whl +0 -0
  30. static/pyodide/PIL-9.1.0-cp310-cp310-emscripten_wasm32.whl +3 -0
  31. static/pyodide/Pygments-2.11.2-py3-none-any.whl +3 -0
  32. static/pyodide/asciitree-0.3.3-py3-none-any.whl +0 -0
  33. static/pyodide/astropy-5.0.4-cp310-cp310-emscripten_wasm32.whl +3 -0
  34. static/pyodide/atomicwrites-1.4.0-py2.py3-none-any.whl +0 -0
  35. static/pyodide/attrs-21.4.0-py2.py3-none-any.whl +0 -0
  36. static/pyodide/autograd-1.4-py3-none-any.whl +0 -0
  37. static/pyodide/autograd-tests.tar +3 -0
  38. static/pyodide/b2d-0.7.2-cp310-cp310-emscripten_wasm32.whl +3 -0
  39. static/pyodide/beautifulsoup4-4.11.0-py3-none-any.whl +0 -0
  40. static/pyodide/biopython-1.79-cp310-cp310-emscripten_wasm32.whl +3 -0
  41. static/pyodide/bleach-5.0.0-py3-none-any.whl +3 -0
  42. static/pyodide/bokeh-2.4.2-py3-none-any.whl +3 -0
  43. static/pyodide/boost_histogram-1.3.1-cp310-cp310-emscripten_wasm32.whl +3 -0
  44. static/pyodide/cffi-1.15.0-cp310-cp310-emscripten_wasm32.whl +3 -0
  45. static/pyodide/cffi_example-0.1-cp310-cp310-emscripten_wasm32.whl +3 -0
  46. static/pyodide/cloudpickle-2.0.0-py3-none-any.whl +0 -0
  47. static/pyodide/cmyt-1.0.4-py3-none-any.whl +0 -0
  48. static/pyodide/cmyt-tests.tar +3 -0
  49. static/pyodide/colorspacious-1.1.2-py2.py3-none-any.whl +0 -0
  50. static/pyodide/console.html +168 -0
.gitattributes CHANGED
@@ -33,3 +33,60 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ readme-resources/screenshot.png filter=lfs diff=lfs merge=lfs -text
37
+ static/pyodide/astropy-5.0.4-cp310-cp310-emscripten_wasm32.whl filter=lfs diff=lfs merge=lfs -text
38
+ static/pyodide/b2d-0.7.2-cp310-cp310-emscripten_wasm32.whl filter=lfs diff=lfs merge=lfs -text
39
+ static/pyodide/biopython-1.79-cp310-cp310-emscripten_wasm32.whl filter=lfs diff=lfs merge=lfs -text
40
+ static/pyodide/bleach-5.0.0-py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
41
+ static/pyodide/bokeh-2.4.2-py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
42
+ static/pyodide/boost_histogram-1.3.1-cp310-cp310-emscripten_wasm32.whl filter=lfs diff=lfs merge=lfs -text
43
+ static/pyodide/cffi_example-0.1-cp310-cp310-emscripten_wasm32.whl filter=lfs diff=lfs merge=lfs -text
44
+ static/pyodide/cffi-1.15.0-cp310-cp310-emscripten_wasm32.whl filter=lfs diff=lfs merge=lfs -text
45
+ static/pyodide/cryptography-3.4.8-cp310-cp310-emscripten_wasm32.whl filter=lfs diff=lfs merge=lfs -text
46
+ static/pyodide/cytoolz-0.11.2-cp310-cp310-emscripten_wasm32.whl filter=lfs diff=lfs merge=lfs -text
47
+ static/pyodide/distlib-0.3.4-py2.py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
48
+ static/pyodide/docutils-0.18.1-py2.py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
49
+ static/pyodide/fonts/DejaVuSans-Bold.ttf filter=lfs diff=lfs merge=lfs -text
50
+ static/pyodide/fonts/DejaVuSans-BoldOblique.ttf filter=lfs diff=lfs merge=lfs -text
51
+ static/pyodide/fonts/DejaVuSans-Oblique.ttf filter=lfs diff=lfs merge=lfs -text
52
+ static/pyodide/fonts/DejaVuSans.ttf filter=lfs diff=lfs merge=lfs -text
53
+ static/pyodide/fonts/DejaVuSansMono-Bold.ttf filter=lfs diff=lfs merge=lfs -text
54
+ static/pyodide/fonts/DejaVuSansMono-BoldOblique.ttf filter=lfs diff=lfs merge=lfs -text
55
+ static/pyodide/fonts/DejaVuSansMono-Oblique.ttf filter=lfs diff=lfs merge=lfs -text
56
+ static/pyodide/fonts/DejaVuSansMono.ttf filter=lfs diff=lfs merge=lfs -text
57
+ static/pyodide/fonts/DejaVuSerif-Bold.ttf filter=lfs diff=lfs merge=lfs -text
58
+ static/pyodide/fonts/DejaVuSerif-BoldItalic.ttf filter=lfs diff=lfs merge=lfs -text
59
+ static/pyodide/fonts/DejaVuSerif-Italic.ttf filter=lfs diff=lfs merge=lfs -text
60
+ static/pyodide/fonts/DejaVuSerif.ttf filter=lfs diff=lfs merge=lfs -text
61
+ static/pyodide/fonts/STIXGeneral.ttf filter=lfs diff=lfs merge=lfs -text
62
+ static/pyodide/fonts/STIXGeneralBol.ttf filter=lfs diff=lfs merge=lfs -text
63
+ static/pyodide/fonts/STIXGeneralBolIta.ttf filter=lfs diff=lfs merge=lfs -text
64
+ static/pyodide/fonts/STIXGeneralItalic.ttf filter=lfs diff=lfs merge=lfs -text
65
+ static/pyodide/fonttools-4.32.0-py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
66
+ static/pyodide/freesasa-2.1.0-cp310-cp310-emscripten_wasm32.whl filter=lfs diff=lfs merge=lfs -text
67
+ static/pyodide/future-0.18.2-py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
68
+ static/pyodide/html5lib-1.1-py2.py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
69
+ static/pyodide/imageio-2.16.1-py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
70
+ static/pyodide/jedi-0.18.1-py2.py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
71
+ static/pyodide/Jinja2-3.1.1-py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
72
+ static/pyodide/joblib-1.1.0-py2.py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
73
+ static/pyodide/lxml-4.8.0-cp310-cp310-emscripten_wasm32.whl filter=lfs diff=lfs merge=lfs -text
74
+ static/pyodide/matplotlib-3.5.1-cp310-cp310-emscripten_wasm32.whl filter=lfs diff=lfs merge=lfs -text
75
+ static/pyodide/mne-1.0.0-py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
76
+ static/pyodide/mpmath-1.2.1-py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
77
+ static/pyodide/networkx-2.7.1-py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
78
+ static/pyodide/nlopt-2.7.0-cp310-cp310-emscripten_wasm32.whl filter=lfs diff=lfs merge=lfs -text
79
+ static/pyodide/nltk-3.7-py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
80
+ static/pyodide/nose-1.3.7-py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
81
+ static/pyodide/numcodecs-0.9.1-cp310-cp310-emscripten_wasm32.whl filter=lfs diff=lfs merge=lfs -text
82
+ static/pyodide/numpy-1.22.3-cp310-cp310-emscripten_wasm32.whl filter=lfs diff=lfs merge=lfs -text
83
+ static/pyodide/pandas-1.4.2-cp310-cp310-emscripten_wasm32.whl filter=lfs diff=lfs merge=lfs -text
84
+ static/pyodide/parso-0.8.3-py2.py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
85
+ static/pyodide/patsy-0.5.2-py2.py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
86
+ static/pyodide/PIL-9.1.0-cp310-cp310-emscripten_wasm32.whl filter=lfs diff=lfs merge=lfs -text
87
+ static/pyodide/pycparser-2.21-py2.py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
88
+ static/pyodide/pydantic-1.9.0-py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
89
+ static/pyodide/pyerfa-2.0.0.1-cp310-cp310-emscripten_wasm32.whl filter=lfs diff=lfs merge=lfs -text
90
+ static/pyodide/Pygments-2.11.2-py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
91
+ static/pyodide/pyodide.asm.data filter=lfs diff=lfs merge=lfs -text
92
+ static/pyodide/pytest-7.1.1-py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py,cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # poetry
98
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
102
+ #poetry.lock
103
+
104
+ # pdm
105
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
106
+ #pdm.lock
107
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
108
+ # in version control.
109
+ # https://pdm.fming.dev/#use-with-ide
110
+ .pdm.toml
111
+
112
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
113
+ __pypackages__/
114
+
115
+ # Celery stuff
116
+ celerybeat-schedule
117
+ celerybeat.pid
118
+
119
+ # SageMath parsed files
120
+ *.sage.py
121
+
122
+ # Environments
123
+ .env
124
+ .venv
125
+ env/
126
+ venv/
127
+ ENV/
128
+ env.bak/
129
+ venv.bak/
130
+
131
+ # Spyder project settings
132
+ .spyderproject
133
+ .spyproject
134
+
135
+ # Rope project settings
136
+ .ropeproject
137
+
138
+ # mkdocs documentation
139
+ /site
140
+
141
+ # mypy
142
+ .mypy_cache/
143
+ .dmypy.json
144
+ dmypy.json
145
+
146
+ # Pyre type checker
147
+ .pyre/
148
+
149
+ # pytype static type analyzer
150
+ .pytype/
151
+
152
+ # Cython debug symbols
153
+ cython_debug/
154
+
155
+ # PyCharm
156
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
157
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
158
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
159
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
160
+ #.idea/
161
+
162
+ unused-wheels/
163
+ /.idea/workspace.xml
.idea/pyscript-pwa-example.iml ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="PYTHON_MODULE" version="4">
3
+ <component name="Flask">
4
+ <option name="enabled" value="true" />
5
+ </component>
6
+ <component name="NewModuleRootManager">
7
+ <content url="file://$MODULE_DIR$">
8
+ <excludeFolder url="file://$MODULE_DIR$/venv" />
9
+ </content>
10
+ <orderEntry type="inheritedJdk" />
11
+ <orderEntry type="sourceFolder" forTests="false" />
12
+ </component>
13
+ <component name="PyDocumentationSettings">
14
+ <option name="format" value="PLAIN" />
15
+ <option name="myDocStringFormat" value="Plain" />
16
+ </component>
17
+ <component name="TemplatesService">
18
+ <option name="TEMPLATE_CONFIGURATION" value="Jinja2" />
19
+ <option name="TEMPLATE_FOLDERS">
20
+ <list>
21
+ <option value="$MODULE_DIR$/templates" />
22
+ </list>
23
+ </option>
24
+ </component>
25
+ </module>
README.md CHANGED
@@ -1,10 +1,26 @@
1
- ---
2
- title: Pyscript
3
- emoji: 👀
4
- colorFrom: gray
5
- colorTo: blue
6
- sdk: docker
7
- pinned: false
8
- ---
9
-
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # pyscript PWA Example
2
+
3
+ This app shows how using a PWA (Progressive Web App) along with [pyscript](https://pyscript.net)
4
+ allows us to create Python-based web applications that install like regular applications and
5
+ (mostly) don't suffer from the large file downloads needed for Python's WebAssembly runtime.
6
+
7
+ ![](readme-resources/screenshot.png)
8
+
9
+ To run the app, just start it as a Flask application (keep the app running for the web weather API).
10
+
11
+ ```bash
12
+
13
+ python3 -m venv venv
14
+ . /venv/bin/activate
15
+ pip install -r requirements.txt
16
+ flask run
17
+
18
+ ```
19
+
20
+ Then open 127.0.0.1:5000 and choose "install PWA". See
21
+ [these steps for Chrome](https://www.howtogeek.com/fyi/how-to-install-progressive-web-apps-pwas-in-chrome/),
22
+ google the actions if you are new to this in your browser.
23
+
24
+ Unfortunately, Mozilla gave up on this feature for Firefox browser.
25
+
26
+ If you have improvements for the PWA side of things, please open a PR. It's very bare-bones.
app.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import random
2
+ from pathlib import Path
3
+
4
+ import flask
5
+
6
+ app = flask.Flask(__name__)
7
+
8
+
9
+ @app.get('/')
10
+ def index():
11
+ return flask.render_template('index.html')
12
+
13
+
14
+ @app.get('/weather/data')
15
+ def weather_data():
16
+ data = get_random_report()
17
+ return flask.jsonify(data)
18
+
19
+
20
+ @app.get('/serviceWorker.js')
21
+ def worker():
22
+ js = Path(__file__).parent / 'static' / 'js' / 'serviceWorker.js'
23
+ text = js.read_text()
24
+ resp = flask.make_response(text)
25
+ resp.content_type = 'application/javascript'
26
+ resp.headers['Service-Worker-Allowed'] = '/'
27
+
28
+ return resp
29
+
30
+
31
+ def get_random_report() -> dict:
32
+ reports = [
33
+ {
34
+ 'report': 'Clear and beautify skies today.',
35
+ 'sky': 'sunny',
36
+ 'temp': random.randint(65, 88),
37
+ },
38
+ {
39
+ 'report': 'Cloudy and a bit cool today.',
40
+ 'sky': 'cloudy',
41
+ 'temp': random.randint(48, 60),
42
+ },
43
+ {
44
+ 'report': 'Are those icicles falling from the sky? Get inside.',
45
+ 'sky': 'rain',
46
+ 'temp': random.randint(33, 40),
47
+ }
48
+ ]
49
+
50
+ return random.choice(reports)
readme-resources/screenshot.png ADDED

Git LFS Details

  • SHA256: 234e042e3a8da978a536d12ed119ed3862e0f05e64930c99dc0cc4af5901f80a
  • Pointer size: 131 Bytes
  • Size of remote file: 150 kB
requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ flask
static/css/site.css ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ * {
2
+ margin: 0;
3
+ padding: 0;
4
+ box-sizing: border-box;
5
+ }
6
+
7
+ body {
8
+ background: #fdfdfd;
9
+ font-family: "Nunito", sans-serif;
10
+ font-size: 1rem;
11
+ overflow: hidden;
12
+ }
13
+
14
+ html, body {
15
+ height: 100%;
16
+ min-height: 100%;
17
+ }
18
+
19
+ main {
20
+ max-width: 900px;
21
+ margin: auto;
22
+ padding: 0.5rem;
23
+ text-align: center;
24
+ height: 80%;
25
+ }
26
+
27
+ nav {
28
+ display: flex;
29
+ justify-content: space-between;
30
+ align-items: center;
31
+ }
32
+
33
+ ul {
34
+ list-style: none;
35
+ display: flex;
36
+ }
37
+
38
+ li {
39
+ margin-right: 1rem;
40
+ }
41
+
42
+ h1 {
43
+ margin-bottom: 0.5rem;
44
+ }
45
+
46
+
47
+ .container {
48
+ display: grid;
49
+ grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
50
+ grid-gap: 1rem;
51
+ justify-content: center;
52
+ align-items: center;
53
+ margin: auto;
54
+ padding: 1rem 0;
55
+ }
56
+
57
+
58
+ body.sunny {
59
+ background: #69caf8;
60
+ }
61
+
62
+ body.cloudy {
63
+ background: #cbcaca;
64
+ }
65
+
66
+ body.rain {
67
+ background: #607280;
68
+ color: white;
69
+ }
70
+ body.offline {
71
+ background: #e37f7f;
72
+ color: black;
73
+ }
74
+
75
+ #weather {
76
+ margin-top: 100px;
77
+ }
78
+
79
+ #weather #image-container {
80
+ float: left;
81
+ }
82
+
83
+ #weather #image {
84
+ width: 350px;
85
+ }
86
+
87
+ #weather #temp {
88
+ padding-top: 70px;
89
+ font-size: 100px;
90
+ font-weight: bold;
91
+ }
92
+
93
+ #weather #forecast {
94
+
95
+ }
96
+
97
+ footer {
98
+ text-align: center;
99
+ height: 20%;
100
+ background-color: #444;
101
+ color: #aaa;
102
+ }
103
+
104
+ .footer-content {
105
+ padding-top: 40px;
106
+ }
107
+
108
+
109
+ a {
110
+ cursor: pointer;
111
+ font-weight: bold;
112
+ text-decoration: none;
113
+ }
114
+
115
+ a:hover {
116
+ text-decoration: underline;
117
+ }
118
+
119
+ .hidden {
120
+ display: none;
121
+ }
static/images/icons/icon-128x128.png ADDED
static/images/icons/icon-144x144.png ADDED
static/images/icons/icon-152x152.png ADDED
static/images/icons/icon-192x192.png ADDED
static/images/icons/icon-384x384.png ADDED
static/images/icons/icon-512x512.png ADDED
static/images/icons/icon-72x72.png ADDED
static/images/icons/icon-96x96.png ADDED
static/images/weather/cloudy.png ADDED
static/images/weather/offline.png ADDED
static/images/weather/partlysunny.png ADDED
static/images/weather/rain.png ADDED
static/images/weather/sunny.png ADDED
static/js/pwa-scaffold.js ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ if ("serviceWorker" in navigator) {
2
+ window.addEventListener("load", function () {
3
+ navigator.serviceWorker
4
+ .register("/serviceWorker.js")
5
+ .then(res => console.log("service worker registered", res))
6
+ .catch(err => console.log("service worker not registered", err))
7
+ })
8
+ }
static/js/serviceWorker.js ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const staticPyPWA = "dev-pypwa-v4"
2
+ const assets = [
3
+ // "",
4
+ // "/",
5
+ "/static/css/site.css",
6
+ "/static/js/site.js",
7
+ "/static/js/pwa-scaffold.js",
8
+
9
+ "/static/python/client.py",
10
+ "/static/python/weather_api.py",
11
+
12
+ "/static/pyscript/pyscript.css",
13
+ "/static/pyscript/pyscript.js",
14
+ "/static/pyscript/pyscript.py",
15
+
16
+ "/static/images/weather/cloudy.png",
17
+ "/static/images/weather/rain.png",
18
+ "/static/images/weather/offline.png",
19
+ "/static/images/weather/sunny.png",
20
+
21
+ "/static/pyodide/pyodide.js",
22
+ "/static/pyodide/packages.json",
23
+ "/static/pyodide/pyodide_py.tar",
24
+ "/static/pyodide/pyodide.asm.js",
25
+ "/static/pyodide/pyodide.asm.data",
26
+ "/static/pyodide/pyodide.asm.wasm",
27
+ "/static/pyodide/micropip-0.1-py3-none-any.whl",
28
+ "/static/pyodide/pyparsing-3.0.7-py3-none-any.whl",
29
+ "/static/pyodide/packaging-21.3-py3-none-any.whl",
30
+ "/static/pyodide/distutils.tar",
31
+
32
+ "/static/images/icons/icon-144x144.png",
33
+ ]
34
+
35
+ self.addEventListener("install", installEvent => {
36
+ installEvent.waitUntil(
37
+ caches.open(staticPyPWA).then(cache => {
38
+ cache.addAll(assets).then(r => {
39
+ console.log("Cache assets downloaded");
40
+ }).catch(err => console.log("Error caching item", err))
41
+ console.log(`Cache ${staticPyPWA} opened.`);
42
+ }).catch(err => console.log("Error opening cache", err))
43
+ )
44
+ })
45
+
46
+ self.addEventListener("fetch", fetchEvent => {
47
+ fetchEvent.respondWith(
48
+ caches.match(fetchEvent.request).then(res => {
49
+ return res || fetch(fetchEvent.request)
50
+ }).catch(err => console.log("Cache fetch error: ", err))
51
+ )
52
+ })
static/js/site.js ADDED
File without changes
static/manifest.json ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "PyPWA Weather",
3
+ "short_name": "PyPWA Weather",
4
+ "start_url": "/",
5
+ "display": "standalone",
6
+ "background_color": "#69caf8",
7
+ "theme_color": "#444444",
8
+ "orientation": "portrait-primary",
9
+ "icons": [
10
+ {
11
+ "src": "/static/images/icons/icon-72x72.png",
12
+ "type": "image/png", "sizes": "72x72"
13
+ },
14
+ {
15
+ "src": "/static/images/icons/icon-96x96.png",
16
+ "type": "image/png", "sizes": "96x96"
17
+ },
18
+ {
19
+ "src": "/static/images/icons/icon-128x128.png",
20
+ "type": "image/png","sizes": "128x128"
21
+ },
22
+ {
23
+ "src": "/static/images/icons/icon-144x144.png",
24
+ "type": "image/png", "sizes": "144x144"
25
+ },
26
+ {
27
+ "src": "/static/images/icons/icon-152x152.png",
28
+ "type": "image/png", "sizes": "152x152"
29
+ },
30
+ {
31
+ "src": "/static/images/icons/icon-192x192.png",
32
+ "type": "image/png", "sizes": "192x192"
33
+ },
34
+ {
35
+ "src": "/static/images/icons/icon-384x384.png",
36
+ "type": "image/png", "sizes": "384x384"
37
+ },
38
+ {
39
+ "src": "/static/images/icons/icon-512x512.png",
40
+ "type": "image/png", "sizes": "512x512"
41
+ }
42
+ ]
43
+ }
static/pyodide/CLAPACK-3.2.1.zip ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2662f266d19c2e684a0c7d67c045d3f0767447fe5c0eed3509bbd31a25e6ca31
3
+ size 1277110
static/pyodide/Jinja2-3.1.1-py3-none-any.whl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:63992624b74ec0ebe62b1c10b44aff5e6a85b0b84a8668d6b681a2478fd11cf7
3
+ size 132603
static/pyodide/Logbook-1.5.3-cp310-cp310-emscripten_wasm32.whl ADDED
Binary file (93.3 kB). View file
 
static/pyodide/MarkupSafe-2.1.1-cp310-cp310-emscripten_wasm32.whl ADDED
Binary file (12 kB). View file
 
static/pyodide/PIL-9.1.0-cp310-cp310-emscripten_wasm32.whl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:38d692b74bb4c0614796f1e2c9beb931f5a6a79853611d0d2a205445957752f2
3
+ size 852898
static/pyodide/Pygments-2.11.2-py3-none-any.whl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e735d55ccda6306fe3e36dc6c1867b97a45cf8aa20c4907b24df5eaa9dc63b24
3
+ size 1063665
static/pyodide/asciitree-0.3.3-py3-none-any.whl ADDED
Binary file (5.05 kB). View file
 
static/pyodide/astropy-5.0.4-cp310-cp310-emscripten_wasm32.whl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:78f779cfda0210401459497cf8eb20077b720dea9eb27bd74b5dffc10a4da75b
3
+ size 6121279
static/pyodide/atomicwrites-1.4.0-py2.py3-none-any.whl ADDED
Binary file (6.79 kB). View file
 
static/pyodide/attrs-21.4.0-py2.py3-none-any.whl ADDED
Binary file (60.6 kB). View file
 
static/pyodide/autograd-1.4-py3-none-any.whl ADDED
Binary file (47.6 kB). View file
 
static/pyodide/autograd-tests.tar ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:785d04b1a0b7288fcd318bda0343e418898aa12d42e9b5aff3dd3a1d67f76144
3
+ size 10240
static/pyodide/b2d-0.7.2-cp310-cp310-emscripten_wasm32.whl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:73317f7d55dd2e307db75cae21d27307ca57847b1b12547356fdf8e3422c8e69
3
+ size 308974
static/pyodide/beautifulsoup4-4.11.0-py3-none-any.whl ADDED
Binary file (72 kB). View file
 
static/pyodide/biopython-1.79-cp310-cp310-emscripten_wasm32.whl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ed44cdce7d9b05e123a9cf9bea1defc9003257626cc2ad6e4ff5da0dbdcb8782
3
+ size 2203790
static/pyodide/bleach-5.0.0-py3-none-any.whl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8335829b36ae9ef324ff8f66b7191683e0bc962cf82d0cf5c2db5d300354e547
3
+ size 160294
static/pyodide/bokeh-2.4.2-py3-none-any.whl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:bfd2e2ff2cf64b10dfaa48ef2fd9e57622c8a7fec3d86cf737dbefac96c2a1f7
3
+ size 18470310
static/pyodide/boost_histogram-1.3.1-cp310-cp310-emscripten_wasm32.whl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7aafa2d98e202ae65cfa0d6f91965e262268f4e3c976c5aff04214dc10fc5efc
3
+ size 936253
static/pyodide/cffi-1.15.0-cp310-cp310-emscripten_wasm32.whl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8a78d2f60271ce07f3516c2247df10782376b88149c5608bc41367b3f257bba2
3
+ size 148396
static/pyodide/cffi_example-0.1-cp310-cp310-emscripten_wasm32.whl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:740611eac17de512fc711fad332e9146670e4244fd7ac8665af57e328d477eba
3
+ size 262492
static/pyodide/cloudpickle-2.0.0-py3-none-any.whl ADDED
Binary file (25.7 kB). View file
 
static/pyodide/cmyt-1.0.4-py3-none-any.whl ADDED
Binary file (28.9 kB). View file
 
static/pyodide/cmyt-tests.tar ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a7a5efd425ceced01b7d33b72be12548b944c63fb48b572ed77768db8c7ea476
3
+ size 20480
static/pyodide/colorspacious-1.1.2-py2.py3-none-any.whl ADDED
Binary file (37.7 kB). View file
 
static/pyodide/console.html ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <script src="https://cdn.jsdelivr.net/npm/jquery"></script>
6
+ <script src="https://cdn.jsdelivr.net/npm/jquery.terminal@2.32.0/js/jquery.terminal.min.js"></script>
7
+ <script src="https://cdn.jsdelivr.net/npm/jquery.terminal@2.23.0/js/unix_formatting.min.js"></script>
8
+ <link
9
+ href="https://cdn.jsdelivr.net/npm/jquery.terminal@2.32.0/css/jquery.terminal.min.css"
10
+ rel="stylesheet"
11
+ />
12
+ <script src="./pyodide.js"></script>
13
+ <style>
14
+ .terminal {
15
+ --size: 1.5;
16
+ --color: rgba(255, 255, 255, 0.8);
17
+ }
18
+ </style>
19
+ </head>
20
+ <body>
21
+ <script>
22
+ "use strict";
23
+ function sleep(s) {
24
+ return new Promise((resolve) => setTimeout(resolve, s));
25
+ }
26
+
27
+ async function main() {
28
+ globalThis.pyodide = await loadPyodide();
29
+ let namespace = pyodide.globals.get("dict")();
30
+ pyodide.runPython(
31
+ `
32
+ import sys
33
+ from pyodide import to_js
34
+ from pyodide.console import PyodideConsole, repr_shorten, BANNER
35
+ import __main__
36
+ BANNER = "Welcome to the Pyodide terminal emulator 🐍\\n" + BANNER
37
+ pyconsole = PyodideConsole(__main__.__dict__)
38
+ import builtins
39
+ async def await_fut(fut):
40
+ res = await fut
41
+ if res is not None:
42
+ builtins._ = res
43
+ return to_js([res], depth=1)
44
+ def clear_console():
45
+ pyconsole.buffer = []
46
+ `,
47
+ { globals: namespace }
48
+ );
49
+ let repr_shorten = namespace.get("repr_shorten");
50
+ let banner = namespace.get("BANNER");
51
+ let await_fut = namespace.get("await_fut");
52
+ let pyconsole = namespace.get("pyconsole");
53
+ let clear_console = namespace.get("clear_console");
54
+ namespace.destroy();
55
+
56
+ let ps1 = ">>> ",
57
+ ps2 = "... ";
58
+
59
+ async function lock() {
60
+ let resolve;
61
+ let ready = term.ready;
62
+ term.ready = new Promise((res) => (resolve = res));
63
+ await ready;
64
+ return resolve;
65
+ }
66
+
67
+ async function interpreter(command) {
68
+ let unlock = await lock();
69
+ term.pause();
70
+ // multiline should be split (useful when pasting)
71
+ for (const c of command.split("\n")) {
72
+ let fut = pyconsole.push(c);
73
+ term.set_prompt(fut.syntax_check === "incomplete" ? ps2 : ps1);
74
+ switch (fut.syntax_check) {
75
+ case "syntax-error":
76
+ term.error(fut.formatted_error.trimEnd());
77
+ continue;
78
+ case "incomplete":
79
+ continue;
80
+ case "complete":
81
+ break;
82
+ default:
83
+ throw new Error(`Unexpected type ${ty}`);
84
+ }
85
+ // In JavaScript, await automatically also awaits any results of
86
+ // awaits, so if an async function returns a future, it will await
87
+ // the inner future too. This is not what we want so we
88
+ // temporarily put it into a list to protect it.
89
+ let wrapped = await_fut(fut);
90
+ // complete case, get result / error and print it.
91
+ try {
92
+ let [value] = await wrapped;
93
+ if (value !== undefined) {
94
+ term.echo(
95
+ repr_shorten.callKwargs(value, {
96
+ separator: "\n[[;orange;]<long output truncated>]\n",
97
+ })
98
+ );
99
+ }
100
+ if (pyodide.isPyProxy(value)) {
101
+ value.destroy();
102
+ }
103
+ } catch (e) {
104
+ if (e.constructor.name === "PythonError") {
105
+ const message = fut.formatted_error || e.message;
106
+ term.error(message.trimEnd());
107
+ } else {
108
+ throw e;
109
+ }
110
+ } finally {
111
+ fut.destroy();
112
+ wrapped.destroy();
113
+ }
114
+ }
115
+ term.resume();
116
+ await sleep(10);
117
+ unlock();
118
+ }
119
+
120
+ let term = $("body").terminal(interpreter, {
121
+ greetings: banner,
122
+ prompt: ps1,
123
+ completionEscape: false,
124
+ completion: function (command, callback) {
125
+ callback(pyconsole.complete(command).toJs()[0]);
126
+ },
127
+ keymap: {
128
+ "CTRL+C": async function (event, original) {
129
+ clear_console();
130
+ term.enter();
131
+ term.echo("KeyboardInterrupt");
132
+ term.set_command("");
133
+ term.set_prompt(ps1);
134
+ },
135
+ TAB: (event, original) => {
136
+ const command = term.before_cursor();
137
+ // Disable completion for whitespaces.
138
+ if (command.trim() === "") {
139
+ term.insert("\t");
140
+ return false;
141
+ }
142
+ return original(event);
143
+ },
144
+ },
145
+ });
146
+ window.term = term;
147
+ pyconsole.stdout_callback = (s) => term.echo(s, { newline: false });
148
+ pyconsole.stderr_callback = (s) => {
149
+ term.error(s.trimEnd());
150
+ };
151
+ term.ready = Promise.resolve();
152
+ pyodide._api.on_fatal = async (e) => {
153
+ term.error(
154
+ "Pyodide has suffered a fatal error. Please report this to the Pyodide maintainers."
155
+ );
156
+ term.error("The cause of the fatal error was:");
157
+ term.error(e);
158
+ term.error("Look in the browser console for more details.");
159
+ await term.ready;
160
+ term.pause();
161
+ await sleep(15);
162
+ term.pause();
163
+ };
164
+ }
165
+ window.console_ready = main();
166
+ </script>
167
+ </body>
168
+ </html>