├── .gitattributes ├── .gitignore ├── .isort.cfg ├── .pylintrc ├── .vscode └── settings.json ├── DEVELOPER_GUIDE.md ├── LICENSE ├── MANIFEST.in ├── README.md ├── VERSION ├── assets └── images │ ├── examples │ └── SketchApp.gif │ ├── panel-logo.png │ ├── panel-sketch-basic-example.png │ ├── panel-sketch-binder.gif │ └── panel-sketch-logo.png ├── binder ├── jupyter-examples-server │ ├── __init__.py │ ├── examples-icon.svg │ ├── jupyter_examples_server.py │ └── setup.py └── requirements.txt ├── docker └── Dockerfile.pip ├── examples ├── Sketch.ipynb └── pyp5js │ ├── __init__.py │ └── gallery │ ├── gallery.py │ ├── sketch_000.py │ ├── sketch_001.py │ ├── sketch_002.py │ ├── sketch_004.py │ ├── sketch_005.py │ ├── sketch_006.py │ ├── sketch_007.py │ ├── sketch_008.py │ └── sketch_010.py ├── mypy.ini ├── panel_sketch ├── .bokeh ├── __init__.py ├── bokeh.ext.json ├── config.py ├── dist │ ├── panel_sketch.js │ ├── panel_sketch.js.map │ ├── panel_sketch.json │ └── panel_sketch.min.js ├── index.ts ├── models │ ├── __init__.py │ ├── index.ts │ ├── sketch.py │ └── sketch.ts ├── package-lock.json ├── package.json ├── sketch.py ├── sketch_base.py ├── sketch_compiler │ ├── __init__.py │ ├── assets │ │ └── js │ │ │ └── transcrypt │ │ │ ├── org.transcrypt.__runtime__.js │ │ │ ├── org.transcrypt.__runtime__.map │ │ │ ├── org.transcrypt.__runtime__.py │ │ │ ├── pyp5js.js │ │ │ ├── pyp5js.map │ │ │ ├── pyp5js.py │ │ │ ├── pyp5js.python_functions.js │ │ │ ├── pyp5js.python_functions.map │ │ │ └── pyp5js.python_functions.py │ ├── template_pyodide_basic.js │ ├── template_pyodide_pyp5js.js │ ├── template_transcrypt_basic.py │ └── template_transcrypt_pyp5js.py ├── sketch_editor.py ├── sketch_viewer.py └── tsconfig.json ├── pyproject.toml ├── pytest.ini ├── setup.py ├── tasks ├── __init__.py └── test.py └── tests ├── __init__.py ├── models ├── __init__.py └── test_sketch.py ├── test_pyodide_compiler.py ├── test_sketch.py ├── test_sketch_base.py ├── test_sketch_compiler.py ├── test_sketch_editor.py ├── test_sketch_viewer.py └── test_transcrypt_compiler.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Line Endings configuration file for Git 2 | # See https://docs.github.com/en/free-pro-team@latest/github/using-git/configuring-git-to-handle-line-endings 3 | # Set the default behavior, in case people don't have or can't have core.autocrlf set. 4 | * text=auto 5 | 6 | # Explicitly declare text files you want to always be normalized and converted 7 | # to native line endings on checkout. 8 | *.py text 9 | *.js text 10 | *.html text 11 | *.css text 12 | *.yml text 13 | *.md text 14 | 15 | # Denote all files that are truly binary and should not be modified. 16 | *.png binary 17 | *.jpg binary 18 | *.gif binary -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 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 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 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 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | # Custom ignore 132 | panel_sketch/node_modules 133 | test_results 134 | !panel_sketch/dist -------------------------------------------------------------------------------- /.isort.cfg: -------------------------------------------------------------------------------- 1 | [settings] 2 | -------------------------------------------------------------------------------- /.pylintrc: -------------------------------------------------------------------------------- 1 | [MASTER] 2 | load-plugins=pylint.extensions.mccabe 3 | extension-pkg-whitelist: cx_Oracle 4 | 5 | [FORMAT] 6 | max-line-length=100 7 | 8 | [MESSAGES CONTROL] 9 | # bad-continuation: Pylint cannot handle valid indendation created by Black 10 | # duplicate-code: The _current_event and _past_event have some similar code. But it's ok. 11 | disable=bad-continuation,duplicate-code 12 | 13 | 14 | [DESIGN] 15 | max-attributes=12 16 | max-parents=13 17 | 18 | [TYPECHECK] 19 | generated-members=REQUEST,acl_users,aq_parent,"[a-zA-Z]+_set{1,2}",save,delete 20 | ignored-modules=winreg 21 | 22 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.pythonPath": ".venv\\Scripts\\python.exe" 3 | } -------------------------------------------------------------------------------- /DEVELOPER_GUIDE.md: -------------------------------------------------------------------------------- 1 | # For Contributers 2 | 3 | ## Prerequisites 4 | 5 | - Python 6 | - Node >= 14 7 | 8 | ## Installation 9 | 10 | ```bash 11 | git clone https://github.com/marcskovmadsen/panel-sketch 12 | cd panel-sketch 13 | ``` 14 | 15 | Create your virtual environment. 16 | 17 | ```bash 18 | python -m venv .venv 19 | ``` 20 | 21 | Activate your virtual environment. On Windows with Git Bash it can be done via 22 | 23 | ```bash 24 | source .venv/Scripts/activate 25 | ``` 26 | 27 | Install the `panel-sketch` package for editing 28 | 29 | ```bash 30 | pip install -e .[all] 31 | ``` 32 | 33 | ## Bokeh Models build 34 | 35 | ```bash 36 | panel build panel_sketch 37 | ``` 38 | 39 | ## Tests 40 | 41 | ```bash 42 | invoke test.all 43 | ``` 44 | 45 | will run `isort`, `autoflake`, `black`, `pylint`, `mypy` and `pytest`. It should look like 46 | 47 | ```bash 48 | $ invoke test.all 49 | 50 | Running isort the Python code import sorter 51 | =========================================== 52 | 53 | isort . 54 | Skipped 7 files 55 | 56 | Running autoflake to remove unused imports on all .py files recursively 57 | ======================================================================= 58 | 59 | autoflake --imports=pytest,pandas,numpy,plotly,dash,urllib3 --in-place --recur 60 | sive . 61 | 62 | Running Black the Python code formatter 63 | ======================================= 64 | 65 | black . 66 | All done! \u2728 \U0001f370 \u2728 67 | 16 files left unchanged. 68 | 69 | Running pylint. 70 | Pylint looks for programming errors, helps enforcing a coding standard, 71 | sniffs for code smells and offers simple refactoring suggestions. 72 | ======================================================================= 73 | 74 | pylint setup.py tasks panel_sketch tests 75 | 76 | -------------------------------------------------------------------- 77 | Your code has been rated at 10.00/10 (previous run: 10.00/10, +0.00) 78 | 79 | 80 | Running mypy for identifying python type errors 81 | =============================================== 82 | 83 | mypy setup.py tasks panel_sketch tests 84 | Success: no issues found in 16 source files 85 | 86 | Running pytest the test framework 87 | ================================= 88 | 89 | pytest tests --doctest-modules --cov=panel_sketch -m "not functionaltest a 90 | nd not integrationtest" --cov-report html:test_results/cov_html 91 | ============================= test session starts ============================= 92 | platform win32 -- Python 3.8.4, pytest-6.2.2, py-1.10.0, pluggy-0.13.1 93 | rootdir: C:\repos\private\panel-sketch, configfile: pytest.ini, testpaths: tests 94 | plugins: anyio-2.2.0, cov-2.11.1 95 | collected 6 items 96 | 97 | tests\test_config.py . [ 16%] 98 | tests\test_highchart.py ... [ 66%] 99 | tests\models\test_highchart.py .. [100%] 100 | 101 | ----------- coverage: platform win32, python 3.8.4-final-0 ----------- 102 | Coverage HTML written to dir test_results/cov_html 103 | 104 | 105 | ============================== 6 passed in 2.07s ============================== 106 | 107 | All Tests Passed Successfully 108 | ============================= 109 | ``` 110 | 111 | ## Package build 112 | 113 | In the `VERSION` file update the `version` number and then run 114 | 115 | ```bash 116 | python setup.py sdist bdist_wheel 117 | ``` 118 | 119 | ## Package Deploy 120 | 121 | to production 122 | 123 | ```bash 124 | python -m twine upload dist/*20210411.1* 125 | ``` 126 | 127 | or to test 128 | 129 | ```bash 130 | python -m twine upload --repository testpypi dist/*20210403.1.4* 131 | ``` 132 | 133 | Have binder build the new image: [binder](https://mybinder.org/v2/gh/MarcSkovMadsen/panel-sketch/HEAD?filepath=examples) 134 | 135 | ## Build and Run Binder Image Locally 136 | 137 | In order to test the Binder Image you can install repo2docker 138 | 139 | ```python 140 | python -m pip install jupyter-repo2docker 141 | ``` 142 | 143 | You can then run 144 | 145 | ```python 146 | jupyter-repo2docker https://github.com/MarcSkovMadsen/panel-sketch 147 | ``` 148 | 149 | Note: Does not work on Windows. 150 | 151 | ## Open Binder 152 | 153 | Open Binder to rebuild the package 154 | 155 | [Open Binder](https://mybinder.org/v2/gh/MarcSkovMadsen/panel-sketch/HEAD?filepath=examples) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Marc Skov Madsen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | graft panel_sketch/dist 2 | include panel_sketch/*.json 3 | include panel_sketch/models/*.ts 4 | include panel_sketch/index.ts 5 | include README.md 6 | global-exclude *.ipynb_checkpoints/* 7 | global-exclude *.py[co] 8 | global-exclude *~ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Panel Sketch Logo](https://raw.githubusercontent.com/MarcSkovMadsen/panel-sketch/main/assets/images/panel-sketch-logo.png) 2 | 3 | # ✏ ️ Panel Sketch 4 | 5 | THIS IS APLHA SOFTWARE AND YOU MAY EXPERIENCE API CHANGES AND ROUGH EDGES. 6 | 7 | The purpose of the `panel-sketch` package is to make it easy for Pythonistas to quickly sketch interactive visualizations and other applications running in 8 | 9 | - The browser - also without a Python backend 10 | - The Jupyter Notebook. 11 | - Your favorite editor or IDE. 12 | 13 | It is heavily inspired by [p5js](https://p5js.org/get-started/), [p5js sketches](https://editor.p5js.org/p5/sketches) and [pyp5js](https://github.com/berinhard/pyp5js) ❤️ It is not limited to the p5js universe though. 14 | 15 | You can also think of it as a [Code Sandbox](https://codesandbox.io/) or [JS Fiddle](https://jsfiddle.net/) but for #Python, #PyData and #PyViz 🐍. 16 | 17 | [![Panel Sketch Reference Example](https://github.com/MarcSkovMadsen/panel-sketch/blob/main/assets/images/panel-sketch-binder.gif?raw=true)](https://mybinder.org/v2/gh/marcskovmadsen/panel-sketch/HEAD?urlpath=lab/tree/examples/Sketch.ipynb) 18 | 19 | It leverages the powerful `Python` to `Javascript` frameworks [Pyodide](https://github.com/pyodide/pyodide) and [Transcrypt](https://www.transcrypt.org/) 💪. Potentially [Brython](https://brython.info/) and other could be added in the future. 20 | 21 | Check out the `panel-sketch` examples on **Binder** 22 | 23 | | Jupyter Notebook | Jupyter Labs | Panel Apps | 24 | | - | - | - | 25 | | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/marcskovmadsen/panel-sketch/HEAD?filepath=examples) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/marcskovmadsen/panel-sketch/HEAD?urlpath=lab/tree/examples) | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/marcskovmadsen/panel-sketch/HEAD?urlpath=panel) | 26 | 27 | ## License 28 | 29 | The `panel-sketch` python package and repository is open source and free to use (MIT License). 30 | 31 | ## Installation 32 | 33 | With `pip` 34 | 35 | ```bash 36 | pip install panel-sketch 37 | ``` 38 | 39 | ## Usage 40 | 41 | ```python 42 | from panel_sketch import Sketch 43 | 44 | import panel as pn 45 | pn.config.sizing_mode="stretch_width" 46 | 47 | args={"r": 10, "g": 200, "b": 40} # This will give us the color for our sketch 48 | 49 | sketch_python = """ 50 | # https://p5js.org/examples/interaction-wavemaker.html 51 | 52 | 53 | from pyp5js import * 54 | 55 | t = 0 56 | 57 | 58 | def setup(): 59 | createCanvas(600, 600) 60 | stroke(250) 61 | strokeWeight(3) 62 | fill(window.args.r, window.args.g, window.args.b) 63 | 64 | 65 | def draw(): 66 | global t 67 | background(10, 10) 68 | fill(window.args.r, window.args.g, window.args.b) 69 | 70 | xAngle = map(mouseX, 0, width, -4 * PI, 4 * PI, True) 71 | yAngle = map(mouseY, 0, height, -4 * PI, 4 * PI, True) 72 | for x in range(0, width, 30): 73 | for y in range(0, height, 30): 74 | 75 | angle = xAngle * (x / width) + yAngle * (y / height) 76 | 77 | myX = x + 20 * cos(2 * PI * t + angle) 78 | myY = y + 20 * sin(2 * TWO_PI * t + angle) 79 | 80 | ellipse(myX, myY, 10) 81 | 82 | t = t + 0.01 83 | """ 84 | 85 | sketch = Sketch(object=sketch_python, template="pyp5js", compiler="pyodide", args=args) 86 | sketch.viewer.view.servable() 87 | ``` 88 | 89 | ![Basic Example](https://github.com/MarcSkovMadsen/panel-sketch/blob/main/assets/images/panel-sketch-basic-example.png?raw=true) 90 | 91 | ## Reference Guides 92 | 93 | ### [Sketch Reference Example](https://github.com/MarcSkovMadsen/panel-sketch/blob/main/examples/Sketch.ipynb) 94 | 95 | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/marcskovmadsen/panel-sketch/HEAD?urlpath=lab/tree/examples/Sketch.ipynb) 96 | 97 | ## Examples 98 | 99 | ### [Gallery App](https://github.com/MarcSkovMadsen/panel-sketch/blob/main/examples/pyp5js/gallery/gallery.py) 100 | 101 | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/marcskovmadsen/panel-sketch/HEAD?urlpath=lab/tree/examples/pyp5js/gallery/gallery.py) 102 | 103 | ## Additional Resources 104 | 105 | You can find more inspiration via the links below. 106 | 107 | - [p5js](https://p5js.org/get-started/) and [p5js sketches](https://editor.p5js.org/p5/sketches) 108 | - [pyp5js](https://github.com/berinhard/pyp5js) 109 | - [Pyodide](https://github.com/pyodide/pyodide) 110 | - [Transcrypt](https://www.transcrypt.org/) 111 | - [Brython](https://brython.info/) 112 | - [Panel](https://panel.holoviz.org) 113 | - [Awesome Panel](https://awesome-panel.org) 114 | 115 | ## Roadmap 116 | 117 | When I get the time I would like to 118 | 119 | - add example using basic template to Sketch Reference Example 120 | - Add `basic` template examples. 121 | - Enable using the content of notebook cells instead of a string to instantite `Sketch`. 122 | - Add more notebook examples 123 | - Enable easy import and export of sketches 124 | - Find out how I can serve the target js modules in notebook (Enable Transcrypt in Notebook). 125 | - Support [alternatives](https://www.slant.co/options/147/alternatives/~p5-js-alternatives) to p5js like [three.js](https://threejs.org/) 126 | - change `window.args` to `args` reference. 127 | - change `Sketch.viewer.view` to `Sketch.viewer`. Similarly for `Sketch.editor`. 128 | - (re-)align with pyp5js 129 | - Add example app to [Awesome Panel](https://awesome-panel.org). 130 | - Support extensions to p5js like [m5.js](https://ml5js.org/) 131 | - Create youtube tutorial video 132 | - Add badges for 100% test coverage etc. 133 | - Distribute as conda package 134 | 135 | ## Change Log 136 | 137 | - 20210410: First Release to PyPi. -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 20210411.2 -------------------------------------------------------------------------------- /assets/images/examples/SketchApp.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcSkovMadsen/panel-sketch/518cb177e2e8d1899b58f3a3f4d80d26c82ec760/assets/images/examples/SketchApp.gif -------------------------------------------------------------------------------- /assets/images/panel-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcSkovMadsen/panel-sketch/518cb177e2e8d1899b58f3a3f4d80d26c82ec760/assets/images/panel-logo.png -------------------------------------------------------------------------------- /assets/images/panel-sketch-basic-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcSkovMadsen/panel-sketch/518cb177e2e8d1899b58f3a3f4d80d26c82ec760/assets/images/panel-sketch-basic-example.png -------------------------------------------------------------------------------- /assets/images/panel-sketch-binder.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcSkovMadsen/panel-sketch/518cb177e2e8d1899b58f3a3f4d80d26c82ec760/assets/images/panel-sketch-binder.gif -------------------------------------------------------------------------------- /assets/images/panel-sketch-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcSkovMadsen/panel-sketch/518cb177e2e8d1899b58f3a3f4d80d26c82ec760/assets/images/panel-sketch-logo.png -------------------------------------------------------------------------------- /binder/jupyter-examples-server/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcSkovMadsen/panel-sketch/518cb177e2e8d1899b58f3a3f4d80d26c82ec760/binder/jupyter-examples-server/__init__.py -------------------------------------------------------------------------------- /binder/jupyter-examples-server/examples-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /binder/jupyter-examples-server/jupyter_examples_server.py: -------------------------------------------------------------------------------- 1 | """ 2 | Function to configure serving the panel example apps via jupyter-server-proxy. 3 | """ 4 | import pathlib 5 | from glob import glob 6 | 7 | ICON_PATH = str((pathlib.Path(__file__).parent / "examples-icon.svg").absolute()) 8 | 9 | 10 | def panel_serve_examples(): 11 | """Returns the jupyter-server-proxy configuration for serving the example notebooks as Panel 12 | apps. 13 | 14 | Returns: 15 | Dict: The configuration dictionary 16 | """ 17 | # See: 18 | # https://jupyter-server-proxy.readthedocs.io/en/latest/server-process.html 19 | # https://github.com/holoviz/jupyter-panel-proxy/blob/master/panel_server/__init__.py 20 | return { 21 | "command": [ 22 | "panel", 23 | "serve", 24 | *glob("examples/*.ipynb"), 25 | "examples/pyp5js/gallery/gallery.py", 26 | "--allow-websocket-origin=*", 27 | "--port", 28 | "{port}", 29 | "--prefix", 30 | "{base_url}panel", 31 | "--static-dirs", 32 | "transcrypt=panel_sketch/sketch_compiler/assets/js/transcrypt/", 33 | ], 34 | "absolute_url": True, 35 | "timeout": 360, 36 | "launcher_entry": { 37 | "enabled": True, 38 | "title": "Panel Sketch Apps", 39 | "icon_path": ICON_PATH, 40 | }, 41 | } 42 | -------------------------------------------------------------------------------- /binder/jupyter-examples-server/setup.py: -------------------------------------------------------------------------------- 1 | """This setup.py will install a package that configures the jupyter-server-proxy to 2 | panel serve the example notebooks.""" 3 | import setuptools 4 | 5 | setuptools.setup( 6 | name="jupyter-panel-examples-server", 7 | py_modules=["jupyter_examples_server"], 8 | entry_points={ 9 | "jupyter_serverproxy_servers": [ 10 | "panel = jupyter_examples_server:panel_serve_examples", 11 | ] 12 | }, 13 | install_requires=["jupyter-server-proxy", "panel"], 14 | ) 15 | -------------------------------------------------------------------------------- /binder/requirements.txt: -------------------------------------------------------------------------------- 1 | -e . 2 | -e binder/jupyter-examples-server/. 3 | jupyter-server-proxy 4 | transcrypt==3.7.16 -------------------------------------------------------------------------------- /docker/Dockerfile.pip: -------------------------------------------------------------------------------- 1 | FROM python:3.8.9-slim-buster 2 | 3 | RUN pip install pip --upgrade 4 | RUN pip install panel-sketch 5 | 6 | ENTRYPOINT ["bash"] -------------------------------------------------------------------------------- /examples/Sketch.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "adb7a7ff-8f09-4536-999a-7cacf69bce58", 6 | "metadata": {}, 7 | "source": [ 8 | "![Panel Sketch Logo](https://raw.githubusercontent.com/MarcSkovMadsen/panel-sketch/main/assets/images/panel-sketch-logo.png)" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "id": "preliminary-frontier", 14 | "metadata": {}, 15 | "source": [ 16 | "# ✏️ Panel Sketch Pane\n", 17 | "\n", 18 | "**This is PRE-ALPHA and you may experience api changes and rough edges!**\n", 19 | "\n", 20 | "The purpose of the `panel-sketch` package is to make it easy for Pythonistas to quickly sketch interactive visualizations and other analytics apps **running in The browser without a Python backend**.\n", 21 | "\n", 22 | "You can use it from your Jupyter Notebook or your favorite editor or IDE.\n", 23 | "\n", 24 | "It is heavily inspired by [p5js](https://p5js.org/get-started/), [p5js sketches](https://editor.p5js.org/p5/sketches) and [pyp5js](https://github.com/berinhard/pyp5js) ❤️ It is not limited to the p5js universe though.\n", 25 | "\n", 26 | "You can also think of it as a [Code Sandbox](https://codesandbox.io/) or [JS Fiddle](https://jsfiddle.net/) but for #Python, #PyData and #PyViz 🐍.\n", 27 | "\n", 28 | "It leverages the powerful `Python` to `Javascript` frameworks [Pyodide](https://github.com/pyodide/pyodide) and [Transcrypt](https://www.transcrypt.org/) 💪." 29 | ] 30 | }, 31 | { 32 | "cell_type": "markdown", 33 | "id": "9c77feaa-7485-4444-94b4-4618288b4f00", 34 | "metadata": {}, 35 | "source": [ 36 | "## Parameters:\n", 37 | "\n", 38 | "For layout and styling related parameters see the [Panel Customization Guide](https://panel.holoviz.org/user_guide/Customization.html).\n", 39 | "\n", 40 | "* **``object``** (string): A Python script. It is transpiled to javascript ([Transcrypt](https://www.transcrypt.org/)) or run directly in javascript ([Pyodide](https://github.com/pyodide/pyodide)).\n", 41 | "* **``html``** (string) A HTML string to mark up the Sketch. Default is `
`. \n", 42 | "* **``css``** (string): A CSS String to style the Sketch. You can style the HTML div via the `#sketch-element` reference.\n", 43 | "* **``javascript``** (string): The result of the compilation of the python script.\n", 44 | "\n", 45 | "* **``args``** (dict): A Dictionary of keys and values that can be reference via (currently) `window.args` in the python script.\n", 46 | "\n", 47 | "* **``template``** (string): The template to use for compilation. One of 'basic' or 'pyp5js'. Default is (currently) 'pyp5js'.\n", 48 | "* **``compiler``** (string): The compiler to use for compilation. One of 'transcrypt' or 'pyodide'. Default is 'pyodide'.\n", 49 | "\n", 50 | "* **``loading``** (bool): Whether or not the Sketch is loading. For example during compilation.\n", 51 | "\n", 52 | "## Properties\n", 53 | "\n", 54 | "* **``viewer``** (SketchViewer): A Viewer that makes viewing the Sketch a joy. Use it (currently) via `Sketch.viewer.view`.\n", 55 | "* **``editor``** (SketchEditor): An Editor that makes editing the Sketch a joy. Use it (currently) via `Sketch.editor.view`.\n", 56 | "\n", 57 | "## The sketch-element and sketchElement\n", 58 | "\n", 59 | "- The `sketch-element` id is a reserved keyword and replaced in Python, HTML and CSS when viewed in the `Sketch.viewer`.\n", 60 | " - You can reference the `div` element via `sketchElement` in Python.\n", 61 | " - You can style the HTML div via the `#sketch-element` reference.\n", 62 | "___\n", 63 | "\n", 64 | "# Usage\n", 65 | "\n", 66 | "## Imports" 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "execution_count": null, 72 | "id": "005268b9-4cfc-42a3-b3e3-add9a274a801", 73 | "metadata": {}, 74 | "outputs": [], 75 | "source": [ 76 | "from panel_sketch import Sketch\n", 77 | "\n", 78 | "import panel as pn\n", 79 | "pn.config.sizing_mode=\"stretch_width\"\n", 80 | "pn.extension()" 81 | ] 82 | }, 83 | { 84 | "cell_type": "markdown", 85 | "id": "95176896-a6ec-48a5-b6ff-164d7dea4242", 86 | "metadata": {}, 87 | "source": [ 88 | "# Example using pyp5js template and pyodide compiler\n", 89 | "\n", 90 | "Simple but beautiful Sketch based on the awesome [pyp5js](https://github.com/berinhard/pyp5js) template and compiled using just the just as awesome [Pyodide](https://github.com/pyodide/pyodide) compiler.\n", 91 | "\n", 92 | "You can find a gallery of pyp5js examples [here](https://berinhard.github.io/pyp5js/examples/)." 93 | ] 94 | }, 95 | { 96 | "cell_type": "code", 97 | "execution_count": null, 98 | "id": "30cca610-b007-4daf-b0c9-8f7ae1d72fc2", 99 | "metadata": {}, 100 | "outputs": [], 101 | "source": [ 102 | "args={\"r\": 10, \"g\": 200, \"b\": 40} # This will give us the color for our sketch" 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": null, 108 | "id": "599689b4-420f-4afe-bdd1-04c2011e62a2", 109 | "metadata": {}, 110 | "outputs": [], 111 | "source": [ 112 | "sketch_python = \"\"\"\n", 113 | "# https://p5js.org/examples/interaction-wavemaker.html\n", 114 | "\n", 115 | "\n", 116 | "from pyp5js import *\n", 117 | "\n", 118 | "t = 0\n", 119 | "\n", 120 | "\n", 121 | "def setup():\n", 122 | " createCanvas(600, 600)\n", 123 | " stroke(250)\n", 124 | " strokeWeight(3)\n", 125 | " fill(window.args.r, window.args.g, window.args.b)\n", 126 | "\n", 127 | "\n", 128 | "def draw():\n", 129 | " global t\n", 130 | " background(10, 10)\n", 131 | " fill(window.args.r, window.args.g, window.args.b)\n", 132 | "\n", 133 | " xAngle = map(mouseX, 0, width, -4 * PI, 4 * PI, True)\n", 134 | " yAngle = map(mouseY, 0, height, -4 * PI, 4 * PI, True)\n", 135 | " for x in range(0, width, 30):\n", 136 | " for y in range(0, height, 30):\n", 137 | "\n", 138 | " angle = xAngle * (x / width) + yAngle * (y / height)\n", 139 | "\n", 140 | " myX = x + 20 * cos(2 * PI * t + angle)\n", 141 | " myY = y + 20 * sin(2 * TWO_PI * t + angle)\n", 142 | "\n", 143 | " ellipse(myX, myY, 10)\n", 144 | "\n", 145 | " t = t + 0.01\n", 146 | "\"\"\"" 147 | ] 148 | }, 149 | { 150 | "cell_type": "code", 151 | "execution_count": null, 152 | "id": "8c252f91-c842-4e35-a978-01bd4e93c63a", 153 | "metadata": {}, 154 | "outputs": [], 155 | "source": [ 156 | "sketch = Sketch(object=sketch_python, template=\"pyp5js\", compiler=\"pyodide\", args=args)\n", 157 | "sketch.viewer.view" 158 | ] 159 | }, 160 | { 161 | "cell_type": "code", 162 | "execution_count": null, 163 | "id": "240da151-8a5f-4044-862b-3505caf4e90e", 164 | "metadata": {}, 165 | "outputs": [], 166 | "source": [ 167 | "slider = pn.widgets.IntSlider(name=\"Green\", value=200, start=0, end=255, step=1)\n", 168 | "@pn.depends(value=slider, watch=True)\n", 169 | "def _update_value(value):\n", 170 | " sketch.args = {\"r\": 10, \"g\": value, \"b\": 40}\n", 171 | "slider" 172 | ] 173 | }, 174 | { 175 | "cell_type": "markdown", 176 | "id": "careful-bottle", 177 | "metadata": {}, 178 | "source": [ 179 | "# App\n", 180 | "\n", 181 | "Let's wrap it up as an app in a nice template." 182 | ] 183 | }, 184 | { 185 | "cell_type": "code", 186 | "execution_count": null, 187 | "id": "recovered-marsh", 188 | "metadata": {}, 189 | "outputs": [], 190 | "source": [ 191 | "app = pn.template.FastListTemplate(\n", 192 | " site=\"Panel Sketch\", \n", 193 | " title=\"Reference Example\", \n", 194 | " main=[\n", 195 | " pn.pane.Markdown(\"Thanks **p5js** and **pyp5js** ❤️\"),\n", 196 | " sketch.viewer.view,\n", 197 | " ], \n", 198 | " sidebar=[slider]\n", 199 | ").servable()" 200 | ] 201 | }, 202 | { 203 | "cell_type": "markdown", 204 | "id": "forty-reaction", 205 | "metadata": {}, 206 | "source": [ 207 | "Serve the app with `panel serve Sketch.ipynb` and add something like `--static-dirs transcrypt=panel_sketch/sketch_compiler/assets/js/transcrypt/` (hack for now) and explore it at http://localhost:5006/Sketch.\n", 208 | "\n", 209 | "![Sketch App](https://raw.githubusercontent.com/MarcSkovMadsen/panel-sketch/main/assets/images/examples/SketchApp.gif)" 210 | ] 211 | }, 212 | { 213 | "cell_type": "markdown", 214 | "id": "bb9a0878-df08-4f26-b7c2-2d6569266295", 215 | "metadata": {}, 216 | "source": [ 217 | "**That's all. Happy coding 👍**" 218 | ] 219 | } 220 | ], 221 | "metadata": { 222 | "kernelspec": { 223 | "display_name": "Python 3", 224 | "language": "python", 225 | "name": "python3" 226 | }, 227 | "language_info": { 228 | "codemirror_mode": { 229 | "name": "ipython", 230 | "version": 3 231 | }, 232 | "file_extension": ".py", 233 | "mimetype": "text/x-python", 234 | "name": "python", 235 | "nbconvert_exporter": "python", 236 | "pygments_lexer": "ipython3", 237 | "version": "3.8.4" 238 | } 239 | }, 240 | "nbformat": 4, 241 | "nbformat_minor": 5 242 | } 243 | -------------------------------------------------------------------------------- /examples/pyp5js/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcSkovMadsen/panel-sketch/518cb177e2e8d1899b58f3a3f4d80d26c82ec760/examples/pyp5js/__init__.py -------------------------------------------------------------------------------- /examples/pyp5js/gallery/gallery.py: -------------------------------------------------------------------------------- 1 | import pathlib 2 | 3 | import panel as pn 4 | import param 5 | 6 | from panel_sketch import Sketch 7 | 8 | pn.config.sizing_mode = "stretch_width" 9 | pn.extension("ace") 10 | 11 | ROOT = pathlib.Path(__file__).parent 12 | EXAMPLES = { 13 | "PyP5JS - Basic": "sketch_000.py", 14 | "PyP5JS - Angles and mouse coordinates": "sketch_001.py", 15 | "PyP5JS - Move Eye": "sketch_002.py", 16 | # "PyP5JS - Boids": "sketch_004.py", Does not work with pyodide 17 | "PyP5JS - Globals variables (HSB and CENTER)": "sketch_005.py", 18 | # "PyP5JS - Registering event functions such as keyPressed": "sketch_006.py", 19 | "PyP5JS - p5.Vector static methods": "sketch_007.py", 20 | "PyP5JS - p5.dom.js usage": "sketch_008.py", 21 | # "PyP5JS - Working with images": "sketch_008.py", # Need to serve assets 22 | "PyP5JS - Complex Shapes": "sketch_010.py", 23 | } 24 | EXAMPLE = list(EXAMPLES.keys())[0] 25 | 26 | 27 | class Gallery(param.Parameterized): 28 | example = param.ObjectSelector(EXAMPLE, objects=list(EXAMPLES.keys())) 29 | sketch = param.ClassSelector(class_=Sketch) 30 | 31 | def __init__(self, **params): 32 | super().__init__(**params) 33 | 34 | self.sketch = Sketch() 35 | self._update_sketch_object() 36 | 37 | @param.depends("example", watch=True) 38 | def _update_sketch_object(self): 39 | self.sketch.html = self.sketch.param.html.default 40 | self.sketch.css = self.sketch.param.css.default 41 | self.sketch.object = (ROOT / EXAMPLES[self.example]).read_text() 42 | 43 | 44 | pn.config.sizing_mode = "stretch_width" 45 | gallery = Gallery() 46 | 47 | template = pn.template.FastListTemplate( 48 | site="Panel Sketch", title="Examples", main_max_width="1200px" 49 | ) 50 | template.sidebar[:] = [ 51 | gallery.sketch.param.template, 52 | gallery.param.example, 53 | gallery.sketch.param.compiler, 54 | ] 55 | template.main[:] = [ 56 | pn.Column( 57 | pn.pane.Markdown("# ✏️ Sketch"), 58 | pn.layout.Divider(sizing_mode="stretch_width"), 59 | gallery.sketch.viewer.view, 60 | ), 61 | gallery.sketch.editor.view, 62 | ] 63 | 64 | template.servable() 65 | -------------------------------------------------------------------------------- /examples/pyp5js/gallery/sketch_000.py: -------------------------------------------------------------------------------- 1 | def setup(): 2 | 3 | createCanvas(200, 200) 4 | 5 | background(160) 6 | 7 | 8 | def draw(): 9 | 10 | fill("blue") 11 | 12 | background(200) 13 | 14 | radius = sin(frameCount / 60) * 50 + 50 15 | 16 | ellipse(100, 100, radius, radius) 17 | -------------------------------------------------------------------------------- /examples/pyp5js/gallery/sketch_001.py: -------------------------------------------------------------------------------- 1 | # https://p5js.org/examples/interaction-wavemaker.html 2 | 3 | 4 | from pyp5js import * 5 | 6 | t = 0 7 | 8 | 9 | def setup(): 10 | createCanvas(600, 600) 11 | stroke(250) 12 | strokeWeight(3) 13 | fill(40, 200, 40) 14 | 15 | 16 | def draw(): 17 | global t 18 | background(10, 10) 19 | 20 | xAngle = map(mouseX, 0, width, -4 * PI, 4 * PI, True) 21 | yAngle = map(mouseY, 0, height, -4 * PI, 4 * PI, True) 22 | for x in range(0, width, 30): 23 | for y in range(0, height, 30): 24 | 25 | angle = xAngle * (x / width) + yAngle * (y / height) 26 | 27 | myX = x + 20 * cos(2 * PI * t + angle) 28 | myY = y + 20 * sin(2 * TWO_PI * t + angle) 29 | 30 | ellipse(myX, myY, 10) 31 | 32 | t = t + 0.01 33 | -------------------------------------------------------------------------------- /examples/pyp5js/gallery/sketch_002.py: -------------------------------------------------------------------------------- 1 | """ 2 | * Move Eye. 3 | * by Simon Greenwold. 4 | * 5 | * The camera lifts up (controlled by mouseY) while looking at the same point. 6 | """ 7 | from pyp5js import * 8 | 9 | 10 | def setup(): 11 | createCanvas(640, 360, _P5_INSTANCE.WEBGL) 12 | fill(204) 13 | 14 | 15 | def draw(): 16 | ambientLight(50) 17 | directionalLight(255, 0, 0, 0.25, 0.25, 0) 18 | background(0) 19 | 20 | # Change height of the camera with mouseY 21 | camera( 22 | 30.0, 23 | mouseY, 24 | 220.0, # eyeX, eyeY, eyeZ 25 | 0.0, 26 | 0.0, 27 | 0.0, # centerX, centerY, centerZ 28 | 0.0, 29 | 1.0, 30 | 0.0, 31 | ) # upX, upY, upZ 32 | 33 | noStroke() 34 | box(90) 35 | stroke(255) 36 | line(-100, 0, 0, 100, 0, 0) 37 | line(0, -100, 0, 0, 100, 0) 38 | line(0, 0, -100, 0, 0, 100) 39 | -------------------------------------------------------------------------------- /examples/pyp5js/gallery/sketch_004.py: -------------------------------------------------------------------------------- 1 | # From Prof. Claudio Esperança examples for BrythonIDE 2 | # https://github.com/esperanc/brythonide/blob/master/demoSketches/boids.py 3 | 4 | from pyp5js import * 5 | 6 | boids = [] 7 | 8 | 9 | def setup(): 10 | createCanvas(720, 400) 11 | 12 | # Add an initial set of boids into the system 13 | for i in range(40): 14 | boids.append(Boid(random(720), random(400))) 15 | 16 | 17 | def draw(): 18 | background(51) 19 | # Run all the boids 20 | for boid in boids: 21 | boid.run(boids) 22 | 23 | 24 | # Boid class 25 | # Methods for Separation, Cohesion, Alignment added 26 | class Boid(object): 27 | def __init__(self, x, y): 28 | self.acceleration = createVector(0, 0) 29 | self.velocity = p5.Vector.random2D() 30 | self.position = createVector(x, y) 31 | self.r = 3.0 32 | self.maxspeed = 3 # Maximum speed 33 | self.maxforce = 0.05 # Maximum steering force 34 | 35 | def run(self, boids): 36 | self.flock(boids) 37 | self.update() 38 | self.borders() 39 | self.render() 40 | 41 | # Forces go into acceleration 42 | def applyForce(self, force): 43 | self.acceleration.add(force) 44 | 45 | # We accumulate a new acceleration each time based on three rules 46 | def flock(self, boids): 47 | sep = self.separate(boids) # Separation 48 | ali = self.align(boids) # Alignment 49 | coh = self.cohesion(boids) # Cohesion 50 | # Arbitrarily weight these forces 51 | sep.mult(2.5) 52 | ali.mult(1.0) 53 | coh.mult(1.0) 54 | # Add the force vectors to acceleration 55 | self.applyForce(sep) 56 | self.applyForce(ali) 57 | self.applyForce(coh) 58 | 59 | # Method to update location 60 | def update(self): 61 | # Update velocity 62 | self.velocity.add(self.acceleration) 63 | # Limit speed 64 | self.velocity.limit(self.maxspeed) 65 | self.position.add(self.velocity) 66 | # Reset acceleration to 0 each cycle 67 | self.acceleration.mult(0) 68 | 69 | # A method that calculates and applies a steering force towards a target 70 | # STEER = DESIRED MINUS VELOCITY 71 | def seek(self, target): 72 | desired = p5.Vector.sub( 73 | target, self.position 74 | ) # A vector pointing from the location to the target 75 | # Normalize desired and scale to maximum speed 76 | desired.normalize() 77 | desired.mult(self.maxspeed) 78 | # Steering = Desired minus Velocity 79 | steer = p5.Vector.sub(desired, self.velocity) 80 | steer.limit(self.maxforce) # Limit to maximum steering force 81 | return steer 82 | 83 | # Draw boid as a circle 84 | def render(self): 85 | fill(127, 127) 86 | stroke(200) 87 | ellipse(self.position.x, self.position.y, 16, 16) 88 | 89 | # Wraparound 90 | def borders(self): 91 | if self.position.x < -self.r: 92 | self.position.x = width + self.r 93 | if self.position.y < -self.r: 94 | self.position.y = height + self.r 95 | if self.position.x > width + self.r: 96 | self.position.x = -self.r 97 | if self.position.y > height + self.r: 98 | self.position.y = -self.r 99 | 100 | # Separation 101 | # Method checks for nearby boids and steers away 102 | def separate(self, boids): 103 | desiredseparation = 25.0 104 | steer = createVector(0, 0) 105 | count = 0 106 | # For every boid in the system, check if it's too close 107 | for i in range(len(boids)): 108 | d = p5.Vector.dist(self.position, boids[i].position) 109 | # If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself) 110 | if (d > 0) and (d < desiredseparation): 111 | # Calculate vector pointing away from neighbor 112 | diff = p5.Vector.sub(self.position, boids[i].position) 113 | diff.normalize() 114 | diff.div(d) # Weight by distance 115 | steer.add(diff) 116 | count += 1 # Keep track of how many 117 | # Average -- divide by how many 118 | if count > 0: 119 | steer.div(count) 120 | 121 | # As long as the vector is greater than 0 122 | if steer.mag() > 0: 123 | # Implement Reynolds: Steering = Desired - Velocity 124 | steer.normalize() 125 | steer.mult(self.maxspeed) 126 | steer.sub(self.velocity) 127 | steer.limit(self.maxforce) 128 | 129 | return steer 130 | 131 | # Alignment 132 | # For every nearby boid in the system, calculate the average velocity 133 | def align(self, boids): 134 | neighbordist = 50 135 | sum = createVector(0, 0) 136 | count = 0 137 | for i in range(len(boids)): 138 | d = p5.Vector.dist(self.position, boids[i].position) 139 | if (d > 0) and (d < neighbordist): 140 | sum.add(boids[i].velocity) 141 | count += 1 142 | 143 | if count > 0: 144 | sum.div(count) 145 | sum.normalize() 146 | sum.mult(self.maxspeed) 147 | steer = p5.Vector.sub(sum, self.velocity) 148 | steer.limit(self.maxforce) 149 | return steer 150 | else: 151 | return createVector(0, 0) 152 | 153 | # Cohesion 154 | # For the average location (i.e. center) of all nearby boids, calculate steering vector towards that location 155 | def cohesion(self, boids): 156 | neighbordist = 50 157 | sum = createVector(0, 0) # Start with empty vector to accumulate all locations 158 | count = 0 159 | for i in range(len(boids)): 160 | d = p5.Vector.dist(self.position, boids[i].position) 161 | if (d > 0) and (d < neighbordist): 162 | sum.add(boids[i].position) # Add location 163 | count += 1 164 | 165 | if count > 0: 166 | sum.div(count) 167 | return self.seek(sum) # Steer towards the location 168 | else: 169 | return createVector(0, 0) 170 | -------------------------------------------------------------------------------- /examples/pyp5js/gallery/sketch_005.py: -------------------------------------------------------------------------------- 1 | from pyp5js import * 2 | 3 | 4 | def setup(): 5 | createCanvas(600, 600) 6 | noStroke() 7 | rectMode(CENTER) 8 | 9 | 10 | def draw(): 11 | colorMode(HSB, 100) 12 | h = map(mouseY, 0, 600, 0, 100) 13 | background(h, 100, 100) 14 | fill(100 - h, 100, 100) 15 | rect(300, 300, mouseX + 1, mouseX + 1) 16 | -------------------------------------------------------------------------------- /examples/pyp5js/gallery/sketch_006.py: -------------------------------------------------------------------------------- 1 | from pyp5js import * 2 | 3 | r = None 4 | 5 | 6 | def setup(): 7 | global r 8 | 9 | createCanvas(900, 900) 10 | r = random(100, 700) 11 | noFill() 12 | 13 | 14 | def draw(): 15 | x, y = 100, 100 16 | rect(x, y, r, r) 17 | 18 | 19 | def keyPressed(): 20 | console.log("Key pressed event") 21 | 22 | if key == "n": 23 | global r 24 | r = random(100, 700) 25 | redraw() 26 | 27 | 28 | def mouseDragged(): 29 | global r 30 | r = random(100, 700) 31 | redraw() 32 | -------------------------------------------------------------------------------- /examples/pyp5js/gallery/sketch_007.py: -------------------------------------------------------------------------------- 1 | from pyp5js import * 2 | 3 | 4 | def setup(): 5 | createCanvas(900, 900) 6 | stroke(27, 27, 27, 10) 7 | strokeWeight(2) 8 | 9 | 10 | def draw(): 11 | push() 12 | 13 | translate(width / 2, height / 2) 14 | v = p5.Vector.random2D() 15 | v.normalize() 16 | v.mult(random(100, 400)) 17 | line(0, 0, v.x, v.y) 18 | 19 | pop() 20 | -------------------------------------------------------------------------------- /examples/pyp5js/gallery/sketch_008.py: -------------------------------------------------------------------------------- 1 | from pyp5js import * 2 | 3 | rect_base_size = 30 4 | positions = [] 5 | rect_size = None 6 | 7 | 8 | def setup(): 9 | global rect_size 10 | 11 | createP("Hi! This is an example of how to use p5.dom.js with pyp5js") 12 | 13 | # creates a container div 14 | slider_div = createDiv() 15 | slider_div.style("display", "block") 16 | 17 | # creates the slider 18 | rect_size = createSlider(0, 600, 100) 19 | rect_size.style("width", "50%") 20 | 21 | # adds the slider to the container div 22 | slider_div.child(rect_size) 23 | 24 | createCanvas(600, 600) 25 | 26 | for x in range(-rect_base_size, width + rect_base_size, rect_base_size): 27 | for y in range(-rect_base_size, height + rect_base_size, rect_base_size): 28 | positions.append((x, y)) 29 | 30 | noFill() 31 | strokeWeight(2) 32 | rectMode(CENTER) 33 | 34 | 35 | def draw(): 36 | background(255) 37 | size = rect_size.value() 38 | for x, y in positions: 39 | rect(x, y, size, size) 40 | -------------------------------------------------------------------------------- /examples/pyp5js/gallery/sketch_010.py: -------------------------------------------------------------------------------- 1 | from pyp5js import * 2 | 3 | add_library("p5.dom.js") 4 | 5 | 6 | MY_POINTS = [ 7 | (100, 50), 8 | (300, 100), 9 | (200, 300), 10 | (100, 300), 11 | ] 12 | FRAME_IDX = 0 13 | POINT_SIZE = 10 14 | CNV = None 15 | 16 | 17 | def setup(): 18 | global CNV 19 | CNV = createCanvas(400, 400) 20 | 21 | BUTTON_PREV = createButton("Previous frame") 22 | BUTTON_PREV.position(CNV.position().x, CNV.height + CNV.position().y) 23 | BUTTON_PREV.mousePressed(prev_frame) 24 | 25 | BUTTON_NEXT = createButton("Next frame") 26 | BUTTON_NEXT.position(CNV.position().x + BUTTON_PREV.size().width, BUTTON_PREV.position().y) 27 | BUTTON_NEXT.mousePressed(next_frame) 28 | 29 | background(190) 30 | draw_labels(MY_POINTS) 31 | 32 | 33 | def draw(): 34 | background(190) 35 | draw_closed_curve_vertex(MY_POINTS, FRAME_IDX) 36 | draw_labels(MY_POINTS) 37 | 38 | 39 | def mouseClicked(): 40 | global FRAME_IDX 41 | global MY_POINTS 42 | if is_point_in_canvas(mouseX, mouseY): 43 | i = get_point_index(mouseX, mouseY) 44 | if i != None: 45 | MY_POINTS.pop(i) 46 | if FRAME_IDX >= len(MY_POINTS): 47 | # cap i if it exceeds maximum length now. 48 | FRAME_IDX = len(MY_POINTS) - 1 49 | else: 50 | MY_POINTS.append((mouseX, mouseY)) 51 | 52 | 53 | def get_point_index(x, y): 54 | for idx, (p_x, p_y) in enumerate(MY_POINTS): 55 | if (p_x - POINT_SIZE < x and x < p_x + POINT_SIZE) and ( 56 | p_y - POINT_SIZE < y and y < p_y + POINT_SIZE 57 | ): 58 | return idx 59 | 60 | 61 | def is_point_in_canvas(x, y): 62 | if (x < 0 or x > CNV.width) or (y < 0 or y > CNV.height): 63 | return False 64 | return True 65 | 66 | 67 | def next_frame(): 68 | global FRAME_IDX 69 | if FRAME_IDX < len(MY_POINTS) - 1: 70 | FRAME_IDX += 1 71 | 72 | 73 | def prev_frame(): 74 | global FRAME_IDX 75 | if FRAME_IDX > 0: 76 | FRAME_IDX -= 1 77 | 78 | 79 | def draw_closed_curve_vertex(points, max_idx): 80 | if len(points) < 2: 81 | return 82 | used_points = [] 83 | beginShape() 84 | 85 | # start by using the last point as the initial control point 86 | idx = len(points) - 1 87 | curveVertex(*points[idx]) 88 | used_points.append(idx) 89 | 90 | # add each point to the curve 91 | for idx, p in enumerate(points): 92 | if idx > max_idx: 93 | break 94 | curveVertex(*p) 95 | used_points.append(idx) 96 | 97 | # to close the curve, we need to create the last curve. 98 | # for that, we must go to the first point 99 | idx = 0 100 | curveVertex(*points[idx]) 101 | used_points.append(idx) 102 | 103 | # and use the next point as a control point. 104 | idx = 1 105 | curveVertex(*points[idx]) 106 | used_points.append(idx) 107 | endShape() 108 | 109 | textSize(10) 110 | noStroke() 111 | text( 112 | "Points used to draw this curve (first and last are control points only)", 113 | 5, 114 | CNV.height - 30, 115 | ) 116 | 117 | textSize(20) 118 | text(", ".join(used_points), 10, CNV.height - 10) 119 | stroke(0) 120 | 121 | for i in range(len(used_points) - 1): 122 | draw_dotted_line(points[used_points[i]], points[used_points[i + 1]]) 123 | 124 | 125 | def draw_labels(points): 126 | strokeWeight(POINT_SIZE) 127 | for idx, p in enumerate(points): 128 | ts = 32 129 | textSize(ts) 130 | textY = p[1] - ts / 2 131 | 132 | if p[1] > CNV.height / 2: 133 | textY = p[1] + ts 134 | 135 | noStroke() 136 | text(idx, p[0], textY) 137 | stroke(0) 138 | point(*p) 139 | 140 | strokeWeight(1) 141 | 142 | 143 | def draw_dotted_line(p1, p2): 144 | stroke(100) 145 | strokeWeight(3) 146 | for i in range(11): 147 | x = lerp(p1[0], p2[0], i / 10) 148 | y = lerp(p1[1], p2[1], i / 10) 149 | point(x, y) 150 | 151 | stroke(0) 152 | strokeWeight(1) 153 | -------------------------------------------------------------------------------- /mypy.ini: -------------------------------------------------------------------------------- 1 | [mypy] 2 | [mypy-sqlalchemy.orm] 3 | ignore_missing_imports=True 4 | [mypy-isodate] 5 | ignore_missing_imports=True 6 | [mypy-sqlalchemy] 7 | ignore_missing_imports=True 8 | [mypy-blpapi] 9 | ignore_missing_imports=True 10 | [mypy-setuptools.*] 11 | ignore_missing_imports=True 12 | [mypy-invoke.*] 13 | ignore_missing_imports=True 14 | [mypy-cx_Oracle.*] 15 | ignore_missing_imports = True 16 | [mypy-factory] 17 | ignore_missing_imports = True 18 | [mypy-freezegun] 19 | ignore_missing_imports = True 20 | [mypy-numpy] 21 | ignore_missing_imports = True 22 | [mypy-pandas.*] 23 | ignore_missing_imports = True 24 | [mypy-pytest] 25 | ignore_missing_imports = True 26 | [mypy-rest_framework.*] 27 | ignore_missing_imports = True 28 | [mypy-rest_pandas.*] 29 | ignore_missing_imports = True 30 | [mypy-django_filters.*] 31 | ignore_missing_imports = True 32 | [mypy-jsonfield.*] 33 | ignore_missing_imports = True 34 | [mypy-pyomo.*] 35 | ignore_missing_imports = True 36 | [mypy-pyutilib.*] 37 | ignore_missing_imports = True 38 | [mypy-networkx.*] 39 | ignore_missing_imports = True 40 | [mypy-matplotlib.*] 41 | ignore_missing_imports = True 42 | [mypy-sklearn.*] 43 | ignore_missing_imports = True 44 | [mypy-plotly.graph_objs.*] 45 | ignore_missing_imports = True 46 | [mypy-plotly.*] 47 | ignore_missing_imports = True 48 | [mypy-bokeh.*] 49 | ignore_missing_imports = True 50 | [mypy-sqlalchemy.*] 51 | ignore_missing_imports = True 52 | [mypy-winreg.*] 53 | ignore_missing_imports = True 54 | [mypy-selenium.*] 55 | ignore_missing_imports = True 56 | [mypy-holoviews.*] 57 | ignore_missing_imports = True 58 | [mypy-hvplot.*] 59 | ignore_missing_imports = True 60 | [mypy-panel.*] 61 | ignore_missing_imports = True 62 | [mypy-param.*] 63 | ignore_missing_imports = True 64 | [mypy-trading_analytics.utils.services.pandas_io.*] 65 | ignore_missing_imports = True 66 | [mypy-pyodbc.*] 67 | ignore_missing_imports = True 68 | [mypy-odlenv.*] 69 | ignore_missing_imports = True 70 | [mypy-odltransform.*] 71 | ignore_missing_imports = True 72 | [mypy-tqdm.*] 73 | ignore_missing_imports = True 74 | [mypy-awesome_panel_extensions.*] 75 | ignore_missing_imports = True 76 | [mypy-kubernetes.*] 77 | ignore_missing_imports = True 78 | [mypy-paramiko.*] 79 | ignore_missing_imports = True 80 | [mypy-dash.*] 81 | ignore_missing_imports = True 82 | [mypy-dash_bootstrap_components.*] 83 | ignore_missing_imports = True 84 | [mypy-dash_core_components.*] 85 | ignore_missing_imports = True 86 | [mypy-dash_table.*] 87 | ignore_missing_imports = True 88 | [mypy-dash_html_components.*] 89 | ignore_missing_imports = True 90 | [mypy-pypsa.*] 91 | ignore_missing_imports = True 92 | [mypy-entsoe.*] 93 | ignore_missing_imports = True 94 | [mypy-pyviz_comms.*] 95 | ignore_missing_imports = True -------------------------------------------------------------------------------- /panel_sketch/.bokeh: -------------------------------------------------------------------------------- 1 | {"bokeh_version":"2.3.1","signatures":{"package.json":"feff06f34b7bac4390b35764271b0fed0f9c7d772ee10846a055a2c6e2feec88","package-lock.json":"06a7684b967bd03d95bc5dffeb939ab89b481b59644740afb0bfa03887e306cc","tsconfig.json":"87a823f0ef7885d0f8a99f845fc9b04922e05517668df9ba4dec17527eadeb41"}} -------------------------------------------------------------------------------- /panel_sketch/__init__.py: -------------------------------------------------------------------------------- 1 | """Use 2 | 3 | - panel_sketch.config.js_files to define which Highcharts js files to include 4 | - the HighChart pane to use the Highcharts Chart in Panel. 5 | """ 6 | from . import config 7 | from .sketch import Sketch 8 | -------------------------------------------------------------------------------- /panel_sketch/bokeh.ext.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /panel_sketch/config.py: -------------------------------------------------------------------------------- 1 | """Configures Panel.extension""" 2 | from panel import extension 3 | 4 | # Enables using pn.extension("sketch", ...) 5 | # pylint: disable=protected-access 6 | extension._imports["sketch"] = "panel_sketch.models.sketch" 7 | # pylint: enable=protected-access 8 | -------------------------------------------------------------------------------- /panel_sketch/dist/panel_sketch.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright (c) 2012 - 2021, Anaconda, Inc., and Bokeh Contributors 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * Neither the name of Anaconda nor the names of any contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 29 | * THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | (function(root, factory) { 32 | factory(root["Bokeh"], undefined); 33 | })(this, function(Bokeh, version) { 34 | var define; 35 | return (function(modules, entry, aliases, externals) { 36 | const bokeh = typeof Bokeh !== "undefined" && (version != null ? Bokeh[version] : Bokeh); 37 | if (bokeh != null) { 38 | return bokeh.register_plugin(modules, entry, aliases); 39 | } else { 40 | throw new Error("Cannot find Bokeh " + version + ". You have to load it prior to loading plugins."); 41 | } 42 | }) 43 | ({ 44 | "a6a4fae5e8": /* index.js */ function _(require, module, exports, __esModule, __esExport) { 45 | __esModule(); 46 | const tslib_1 = require("tslib"); 47 | const SketchExtensions = tslib_1.__importStar(require("8fbb31f6e4") /* ./models/ */); 48 | exports.SketchExtensions = SketchExtensions; 49 | const base_1 = require("@bokehjs/base"); 50 | base_1.register_models(SketchExtensions); 51 | }, 52 | "8fbb31f6e4": /* models\index.js */ function _(require, module, exports, __esModule, __esExport) { 53 | __esModule(); 54 | var sketch_1 = require("b09786f089") /* ./sketch */; 55 | __esExport("Sketch", sketch_1.Sketch); 56 | }, 57 | "b09786f089": /* models\sketch.js */ function _(require, module, exports, __esModule, __esExport) { 58 | __esModule(); 59 | // See https://docs.bokeh.org/en/latest/docs/reference/models/layouts.html 60 | const html_box_1 = require("@bokehjs/models/layouts/html_box"); 61 | // The view of the Bokeh extension/ HTML element 62 | // Here you can define how to render the model as well as react to model changes or View events. 63 | class SketchView extends html_box_1.HTMLBoxView { 64 | connect_signals() { 65 | super.connect_signals(); 66 | this.connect(this.model.properties.value.change, () => { 67 | this.render(); 68 | }); 69 | } 70 | render() { 71 | console.log("render"); 72 | console.log(this.model); 73 | super.render(); 74 | this.el.innerHTML = this.model.value; 75 | this.valueElement = this.el.firstElementChild; 76 | this.valueElement.addEventListener("click", () => { this.model.clicks += 1; }, false); 77 | } 78 | } 79 | exports.SketchView = SketchView; 80 | SketchView.__name__ = "SketchView"; 81 | // The Bokeh .ts model corresponding to the Bokeh .py model 82 | class Sketch extends html_box_1.HTMLBox { 83 | constructor(attrs) { 84 | super(attrs); 85 | } 86 | static init_Sketch() { 87 | this.prototype.default_view = SketchView; 88 | this.define(({ String, Int }) => ({ 89 | value: [String, ""], 90 | clicks: [Int, 0], 91 | })); 92 | } 93 | } 94 | exports.Sketch = Sketch; 95 | Sketch.__name__ = "Sketch"; 96 | Sketch.__module__ = "panel_sketch.models.sketch"; 97 | Sketch.init_Sketch(); 98 | }, 99 | }, "a6a4fae5e8", {"index":"a6a4fae5e8","models/index":"8fbb31f6e4","models/sketch":"b09786f089"}, {});}); 100 | //# sourceMappingURL=panel_sketch.js.map 101 | -------------------------------------------------------------------------------- /panel_sketch/dist/panel_sketch.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["@@\\panel_sketch\\dist\\lib\\index.js","@@\\panel_sketch\\dist\\lib\\models\\index.js","@@\\panel_sketch\\dist\\lib\\models\\sketch.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACRA;AACA;AACA;AACA;AACA;AACA,ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"generated.js","sourceRoot":"","sourcesContent":["/* index.js */ function _(require, module, exports, __esModule, __esExport) {\r\n __esModule();\r\n const tslib_1 = require(\"tslib\");\r\n const SketchExtensions = tslib_1.__importStar(require(\"8fbb31f6e4\") /* ./models/ */);\r\n exports.SketchExtensions = SketchExtensions;\r\n const base_1 = require(\"@bokehjs/base\");\r\n base_1.register_models(SketchExtensions);\r\n}\r\n","/* models\\index.js */ function _(require, module, exports, __esModule, __esExport) {\r\n __esModule();\r\n var sketch_1 = require(\"b09786f089\") /* ./sketch */;\r\n __esExport(\"Sketch\", sketch_1.Sketch);\r\n}\r\n","/* models\\sketch.js */ function _(require, module, exports, __esModule, __esExport) {\r\n __esModule();\r\n // See https://docs.bokeh.org/en/latest/docs/reference/models/layouts.html\r\n const html_box_1 = require(\"@bokehjs/models/layouts/html_box\");\r\n // The view of the Bokeh extension/ HTML element\r\n // Here you can define how to render the model as well as react to model changes or View events.\r\n class SketchView extends html_box_1.HTMLBoxView {\r\n connect_signals() {\r\n super.connect_signals();\r\n this.connect(this.model.properties.value.change, () => {\r\n this.render();\r\n });\r\n }\r\n render() {\r\n console.log(\"render\");\r\n console.log(this.model);\r\n super.render();\r\n this.el.innerHTML = this.model.value;\r\n this.valueElement = this.el.firstElementChild;\r\n this.valueElement.addEventListener(\"click\", () => { this.model.clicks += 1; }, false);\r\n }\r\n }\r\n exports.SketchView = SketchView;\r\n SketchView.__name__ = \"SketchView\";\r\n // The Bokeh .ts model corresponding to the Bokeh .py model\r\n class Sketch extends html_box_1.HTMLBox {\r\n constructor(attrs) {\r\n super(attrs);\r\n }\r\n static init_Sketch() {\r\n this.prototype.default_view = SketchView;\r\n this.define(({ String, Int }) => ({\r\n value: [String, \"\"],\r\n clicks: [Int, 0],\r\n }));\r\n }\r\n }\r\n exports.Sketch = Sketch;\r\n Sketch.__name__ = \"Sketch\";\r\n Sketch.__module__ = \"panel_sketch.models.sketch\";\r\n Sketch.init_Sketch();\r\n}\r\n"]} -------------------------------------------------------------------------------- /panel_sketch/dist/panel_sketch.json: -------------------------------------------------------------------------------- 1 | {"version":4,"artifacts":[{"module":{"file":"C:\\repos\\private\\panel-sketch\\panel_sketch\\dist\\lib\\index.js","base":"C:\\repos\\private\\panel-sketch\\panel_sketch\\dist\\lib","base_path":"index.js","canonical":"index","resolution":"ESM","id":"a6a4fae5e8","hash":"a6a4fae5e8621dbe0faff153de10809af162bc8ce2f58d15ef68d93238557bfb","source":"\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.SketchExtensions = void 0;\r\nconst tslib_1 = require(\"tslib\");\r\nconst SketchExtensions = tslib_1.__importStar(require(\"./models/\"));\r\nexports.SketchExtensions = SketchExtensions;\r\nconst base_1 = require(\"@bokehjs/base\");\r\nbase_1.register_models(SketchExtensions);\r\n//# sourceMappingURL=index.js.map\r\n","type":"js","dependency_paths":[["./models/","C:\\repos\\private\\panel-sketch\\panel_sketch\\dist\\lib\\models\\index.js"]],"dependency_map":[],"exported":[],"externals":[],"shims":[]},"code":{"source":"/* index.js */ function _(require, module, exports, __esModule, __esExport) {\r\n __esModule();\r\n const tslib_1 = require(\"tslib\");\r\n const SketchExtensions = tslib_1.__importStar(require(\"8fbb31f6e4\") /* ./models/ */);\r\n exports.SketchExtensions = SketchExtensions;\r\n const base_1 = require(\"@bokehjs/base\");\r\n base_1.register_models(SketchExtensions);\r\n}\r\n","min_source":"function _(e,s,t,o,b){o();const i=e(\"tslib\").__importStar(e(\"8fbb31f6e4\"));t.SketchExtensions=i;e(\"@bokehjs/base\").register_models(i)}\n//# sourceMappingURL=index.min.js.map","min_map":"{\"version\":3,\"sources\":[\"0\"],\"names\":[\"_\",\"require\",\"module\",\"exports\",\"__esModule\",\"__esExport\",\"SketchExtensions\",\"__importStar\",\"register_models\"],\"mappings\":\"AAAe,SAASA,EAAEC,EAASC,EAAQC,EAASC,EAAYC,GAC5DD,IACA,MACME,EADUL,EAAQ,SACSM,aAAaN,EAAQ,eACtDE,EAAQG,iBAAmBA,EACZL,EAAQ,iBAChBO,gBAAgBF\",\"file\":\"index.min.js\"}"}},{"module":{"file":"C:\\repos\\private\\panel-sketch\\panel_sketch\\dist\\lib\\models\\index.js","base":"C:\\repos\\private\\panel-sketch\\panel_sketch\\dist\\lib","base_path":"models\\index.js","canonical":"models/index","resolution":"ESM","id":"8fbb31f6e4","hash":"8fbb31f6e442028bf00b351a45ad9b19d3417bca2668596cad1a956f9e9e2339","source":"\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.Sketch = void 0;\r\nvar sketch_1 = require(\"./sketch\");\r\nObject.defineProperty(exports, \"Sketch\", { enumerable: true, get: function () { return sketch_1.Sketch; } });\r\n//# sourceMappingURL=index.js.map\r\n","type":"js","dependency_paths":[["./sketch","C:\\repos\\private\\panel-sketch\\panel_sketch\\dist\\lib\\models\\sketch.js"]],"dependency_map":[],"exported":[{"type":"bindings","bindings":[[null,"Sketch"]],"module":"./sketch"}],"externals":[],"shims":[]},"code":{"source":"/* models\\index.js */ function _(require, module, exports, __esModule, __esExport) {\r\n __esModule();\r\n var sketch_1 = require(\"b09786f089\") /* ./sketch */;\r\n __esExport(\"Sketch\", sketch_1.Sketch);\r\n}\r\n","min_source":"function _(c,t,e,f,h){f(),h(\"Sketch\",c(\"b09786f089\").Sketch)}\n//# sourceMappingURL=index.min.js.map","min_map":"{\"version\":3,\"sources\":[\"0\"],\"names\":[\"_\",\"require\",\"module\",\"exports\",\"__esModule\",\"__esExport\",\"Sketch\"],\"mappings\":\"AAAsB,SAASA,EAAEC,EAASC,EAAQC,EAASC,EAAYC,GACnED,IAEAC,EAAW,SADIJ,EAAQ,cACOK\",\"file\":\"index.min.js\"}"}},{"module":{"file":"C:\\repos\\private\\panel-sketch\\panel_sketch\\dist\\lib\\models\\sketch.js","base":"C:\\repos\\private\\panel-sketch\\panel_sketch\\dist\\lib","base_path":"models\\sketch.js","canonical":"models/sketch","resolution":"ESM","id":"b09786f089","hash":"b09786f0896bc50755f36069bab84014cab67a8d00dc90ec1e4b3a1e08f15d98","source":"\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nexports.Sketch = exports.SketchView = void 0;\r\n// See https://docs.bokeh.org/en/latest/docs/reference/models/layouts.html\r\nconst html_box_1 = require(\"@bokehjs/models/layouts/html_box\");\r\n// The view of the Bokeh extension/ HTML element\r\n// Here you can define how to render the model as well as react to model changes or View events.\r\nclass SketchView extends html_box_1.HTMLBoxView {\r\n connect_signals() {\r\n super.connect_signals();\r\n this.connect(this.model.properties.value.change, () => {\r\n this.render();\r\n });\r\n }\r\n render() {\r\n console.log(\"render\");\r\n console.log(this.model);\r\n super.render();\r\n this.el.innerHTML = this.model.value;\r\n this.valueElement = this.el.firstElementChild;\r\n this.valueElement.addEventListener(\"click\", () => { this.model.clicks += 1; }, false);\r\n }\r\n}\r\nexports.SketchView = SketchView;\r\nSketchView.__name__ = \"SketchView\";\r\n// The Bokeh .ts model corresponding to the Bokeh .py model\r\nclass Sketch extends html_box_1.HTMLBox {\r\n constructor(attrs) {\r\n super(attrs);\r\n }\r\n static init_Sketch() {\r\n this.prototype.default_view = SketchView;\r\n this.define(({ String, Int }) => ({\r\n value: [String, \"\"],\r\n clicks: [Int, 0],\r\n }));\r\n }\r\n}\r\nexports.Sketch = Sketch;\r\nSketch.__name__ = \"Sketch\";\r\nSketch.__module__ = \"panel_sketch.models.sketch\";\r\nSketch.init_Sketch();\r\n//# sourceMappingURL=sketch.js.map\r\n","type":"js","dependency_paths":[],"dependency_map":[],"exported":[{"type":"named","name":"SketchView"},{"type":"named","name":"Sketch"}],"externals":[],"shims":[]},"code":{"source":"/* models\\sketch.js */ function _(require, module, exports, __esModule, __esExport) {\r\n __esModule();\r\n // See https://docs.bokeh.org/en/latest/docs/reference/models/layouts.html\r\n const html_box_1 = require(\"@bokehjs/models/layouts/html_box\");\r\n // The view of the Bokeh extension/ HTML element\r\n // Here you can define how to render the model as well as react to model changes or View events.\r\n class SketchView extends html_box_1.HTMLBoxView {\r\n connect_signals() {\r\n super.connect_signals();\r\n this.connect(this.model.properties.value.change, () => {\r\n this.render();\r\n });\r\n }\r\n render() {\r\n console.log(\"render\");\r\n console.log(this.model);\r\n super.render();\r\n this.el.innerHTML = this.model.value;\r\n this.valueElement = this.el.firstElementChild;\r\n this.valueElement.addEventListener(\"click\", () => { this.model.clicks += 1; }, false);\r\n }\r\n }\r\n exports.SketchView = SketchView;\r\n SketchView.__name__ = \"SketchView\";\r\n // The Bokeh .ts model corresponding to the Bokeh .py model\r\n class Sketch extends html_box_1.HTMLBox {\r\n constructor(attrs) {\r\n super(attrs);\r\n }\r\n static init_Sketch() {\r\n this.prototype.default_view = SketchView;\r\n this.define(({ String, Int }) => ({\r\n value: [String, \"\"],\r\n clicks: [Int, 0],\r\n }));\r\n }\r\n }\r\n exports.Sketch = Sketch;\r\n Sketch.__name__ = \"Sketch\";\r\n Sketch.__module__ = \"panel_sketch.models.sketch\";\r\n Sketch.init_Sketch();\r\n}\r\n","min_source":"function _(e,t,s,n,i){n();const l=e(\"@bokehjs/models/layouts/html_box\");class c extends l.HTMLBoxView{connect_signals(){super.connect_signals(),this.connect(this.model.properties.value.change,(()=>{this.render()}))}render(){console.log(\"render\"),console.log(this.model),super.render(),this.el.innerHTML=this.model.value,this.valueElement=this.el.firstElementChild,this.valueElement.addEventListener(\"click\",(()=>{this.model.clicks+=1}),!1)}}s.SketchView=c,c.__name__=\"SketchView\";class o extends l.HTMLBox{constructor(e){super(e)}static init_Sketch(){this.prototype.default_view=c,this.define((({String:e,Int:t})=>({value:[e,\"\"],clicks:[t,0]})))}}s.Sketch=o,o.__name__=\"Sketch\",o.__module__=\"panel_sketch.models.sketch\",o.init_Sketch()}\n//# sourceMappingURL=sketch.min.js.map","min_map":"{\"version\":3,\"sources\":[\"0\"],\"names\":[\"_\",\"require\",\"module\",\"exports\",\"__esModule\",\"__esExport\",\"html_box_1\",\"SketchView\",\"HTMLBoxView\",\"[object Object]\",\"super\",\"connect_signals\",\"this\",\"connect\",\"model\",\"properties\",\"value\",\"change\",\"render\",\"console\",\"log\",\"el\",\"innerHTML\",\"valueElement\",\"firstElementChild\",\"addEventListener\",\"clicks\",\"__name__\",\"Sketch\",\"HTMLBox\",\"attrs\",\"prototype\",\"default_view\",\"define\",\"String\",\"Int\",\"__module__\",\"init_Sketch\"],\"mappings\":\"AAAuB,SAASA,EAAEC,EAASC,EAAQC,EAASC,EAAYC,GACpED,IAEA,MAAME,EAAaL,EAAQ,oCAG3B,MAAMM,UAAmBD,EAAWE,YAChCC,kBACIC,MAAMC,kBACNC,KAAKC,QAAQD,KAAKE,MAAMC,WAAWC,MAAMC,QAAQ,KAC7CL,KAAKM,YAGbT,SACIU,QAAQC,IAAI,UACZD,QAAQC,IAAIR,KAAKE,OACjBJ,MAAMQ,SACNN,KAAKS,GAAGC,UAAYV,KAAKE,MAAME,MAC/BJ,KAAKW,aAAeX,KAAKS,GAAGG,kBAC5BZ,KAAKW,aAAaE,iBAAiB,SAAS,KAAQb,KAAKE,MAAMY,QAAU,KAAM,IAGvFvB,EAAQI,WAAaA,EACrBA,EAAWoB,SAAW,aAEtB,MAAMC,UAAetB,EAAWuB,QAC5BpB,YAAYqB,GACRpB,MAAMoB,GAEVrB,qBACIG,KAAKmB,UAAUC,aAAezB,EAC9BK,KAAKqB,QAAO,EAAGC,OAAAA,EAAQC,IAAAA,MAAU,CAC7BnB,MAAO,CAACkB,EAAQ,gDAChBR,OAAQ,CAACS,EAAK,QAI1BhC,EAAQyB,OAASA,EACjBA,EAAOD,SAAW,SAClBC,EAAOQ,WAAa,6BACpBR,EAAOS\",\"file\":\"sketch.min.js\"}"}}]} -------------------------------------------------------------------------------- /panel_sketch/dist/panel_sketch.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Copyright (c) 2012 - 2021, Anaconda, Inc., and Bokeh Contributors 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * Neither the name of Anaconda nor the names of any contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 29 | * THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | (function(root, factory) { 32 | factory(root["Bokeh"], undefined); 33 | })(this, function(Bokeh, version) { 34 | var define; 35 | return (function(modules, entry, aliases, externals) { 36 | const bokeh = typeof Bokeh !== "undefined" && (version != null ? Bokeh[version] : Bokeh); 37 | if (bokeh != null) { 38 | return bokeh.register_plugin(modules, entry, aliases); 39 | } else { 40 | throw new Error("Cannot find Bokeh " + version + ". You have to load it prior to loading plugins."); 41 | } 42 | }) 43 | ({ 44 | "a6a4fae5e8": function _(e,s,t,o,b){o();const i=e("tslib").__importStar(e("8fbb31f6e4"));t.SketchExtensions=i;e("@bokehjs/base").register_models(i)}, 45 | "8fbb31f6e4": function _(c,t,e,f,h){f(),h("Sketch",c("b09786f089").Sketch)}, 46 | "b09786f089": function _(e,t,s,n,i){n();const l=e("@bokehjs/models/layouts/html_box");class c extends l.HTMLBoxView{connect_signals(){super.connect_signals(),this.connect(this.model.properties.value.change,(()=>{this.render()}))}render(){console.log("render"),console.log(this.model),super.render(),this.el.innerHTML=this.model.value,this.valueElement=this.el.firstElementChild,this.valueElement.addEventListener("click",(()=>{this.model.clicks+=1}),!1)}}s.SketchView=c,c.__name__="SketchView";class o extends l.HTMLBox{constructor(e){super(e)}static init_Sketch(){this.prototype.default_view=c,this.define((({String:e,Int:t})=>({value:[e,""],clicks:[t,0]})))}}s.Sketch=o,o.__name__="Sketch",o.__module__="panel_sketch.models.sketch",o.init_Sketch()}, 47 | }, "a6a4fae5e8", {"index":"a6a4fae5e8","models/index":"8fbb31f6e4","models/sketch":"b09786f089"}, {});}); 48 | -------------------------------------------------------------------------------- /panel_sketch/index.ts: -------------------------------------------------------------------------------- 1 | import * as SketchExtensions from "./models/" 2 | export {SketchExtensions} 3 | 4 | import {register_models} from "@bokehjs/base" 5 | register_models(SketchExtensions as any) -------------------------------------------------------------------------------- /panel_sketch/models/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcSkovMadsen/panel-sketch/518cb177e2e8d1899b58f3a3f4d80d26c82ec760/panel_sketch/models/__init__.py -------------------------------------------------------------------------------- /panel_sketch/models/index.ts: -------------------------------------------------------------------------------- 1 | export {Sketch} from "./sketch" -------------------------------------------------------------------------------- /panel_sketch/models/sketch.py: -------------------------------------------------------------------------------- 1 | """Sketch Bokeh Model""" 2 | from bokeh.core.properties import Int, String 3 | from bokeh.models import HTMLBox 4 | 5 | DEFAULT_OBJECT = "" 6 | 7 | 8 | class Sketch(HTMLBox): 9 | """Example implementation of a Custom Bokeh Model""" 10 | 11 | value = String(default=DEFAULT_OBJECT) 12 | clicks = Int(default=0) 13 | -------------------------------------------------------------------------------- /panel_sketch/models/sketch.ts: -------------------------------------------------------------------------------- 1 | // See https://docs.bokeh.org/en/latest/docs/reference/models/layouts.html 2 | import { HTMLBox, HTMLBoxView } from "@bokehjs/models/layouts/html_box" 3 | 4 | // See https://docs.bokeh.org/en/latest/docs/reference/core/properties.html 5 | import * as p from "@bokehjs/core/properties" 6 | 7 | // The view of the Bokeh extension/ HTML element 8 | // Here you can define how to render the model as well as react to model changes or View events. 9 | export class SketchView extends HTMLBoxView { 10 | model: Sketch 11 | valueElement: any // Element 12 | 13 | connect_signals(): void { 14 | super.connect_signals() 15 | 16 | this.connect(this.model.properties.value.change, () => { 17 | this.render(); 18 | }) 19 | } 20 | 21 | render(): void { 22 | console.log("render") 23 | console.log(this.model) 24 | super.render() 25 | this.el.innerHTML = this.model.value 26 | this.valueElement = this.el.firstElementChild 27 | 28 | this.valueElement.addEventListener("click", () => {this.model.clicks+=1;}, false) 29 | } 30 | } 31 | 32 | export namespace Sketch { 33 | export type Attrs = p.AttrsOf 34 | export type Props = HTMLBox.Props & { 35 | value: p.Property, 36 | clicks: p.Property, 37 | } 38 | } 39 | 40 | export interface Sketch extends Sketch.Attrs { } 41 | 42 | // The Bokeh .ts model corresponding to the Bokeh .py model 43 | export class Sketch extends HTMLBox { 44 | properties: Sketch.Props 45 | 46 | constructor(attrs?: Partial) { 47 | super(attrs) 48 | } 49 | 50 | static __module__ = "panel_sketch.models.sketch" 51 | 52 | static init_Sketch(): void { 53 | this.prototype.default_view = SketchView; 54 | 55 | this.define(({String, Int}) => ({ 56 | value: [String, ""], 57 | clicks: [Int, 0], 58 | })) 59 | } 60 | } -------------------------------------------------------------------------------- /panel_sketch/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "panel_sketch", 3 | "version": "0.0.1", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "version": "0.0.1", 9 | "license": "BSD-3-Clause", 10 | "dependencies": { 11 | "@bokeh/bokehjs": "^2.3.0" 12 | }, 13 | "devDependencies": {} 14 | }, 15 | "node_modules/@bokeh/bokehjs": { 16 | "version": "2.3.0", 17 | "resolved": "https://registry.npmjs.org/@bokeh/bokehjs/-/bokehjs-2.3.0.tgz", 18 | "integrity": "sha512-geKBhYUVJ5IaY0UNk9k2P0yiYLCj+DOeNjdDneuTJ8K5R9fs0Rpp4iiaQKUGr1yUyQHGHLU8sk4CFZ+Bd5ZILg==", 19 | "dependencies": { 20 | "@bokeh/numbro": "^1.6.2", 21 | "@bokeh/slickgrid": "~2.4.2701", 22 | "choices.js": "^9.0.1", 23 | "es5-ext": "^0.10.53", 24 | "es6-map": "^0.1.5", 25 | "es6-promise": "4.2.8", 26 | "es6-set": "^0.1.5", 27 | "es6-symbol": "^3.1.3", 28 | "es6-weak-map": "^2.0.2", 29 | "flatbush": "^3.2.1", 30 | "flatpickr": "^4.6.6", 31 | "hammerjs": "^2.0.4", 32 | "nouislider": "^14.6.3", 33 | "proj4": "^2.6.3", 34 | "sprintf-js": "^1.1.2", 35 | "timezone": "^1.0.23", 36 | "tslib": "^2.0.3", 37 | "underscore.template": "^0.1.7" 38 | }, 39 | "engines": { 40 | "node": ">=14", 41 | "npm": ">=7.4" 42 | } 43 | }, 44 | "node_modules/@bokeh/numbro": { 45 | "version": "1.6.2", 46 | "resolved": "https://registry.npmjs.org/@bokeh/numbro/-/numbro-1.6.2.tgz", 47 | "integrity": "sha512-owIECPc3T3QXHCb2v5Ez+/uE9SIxI7N4nd9iFlWnfBrOelr0/omvFn09VisRn37AAFAY39sJiCVgECwryHWUPA==", 48 | "engines": { 49 | "node": "*" 50 | } 51 | }, 52 | "node_modules/@bokeh/slickgrid": { 53 | "version": "2.4.2702", 54 | "resolved": "https://registry.npmjs.org/@bokeh/slickgrid/-/slickgrid-2.4.2702.tgz", 55 | "integrity": "sha512-W9tm8Qdw5BrylbZbaVWaQMgLfW/klesnj6J3FnyWpo18hCCOFApccUD8iOnRv7bF6PHlgWk84mW3JT5RSzYKjA==", 56 | "dependencies": { 57 | "@types/slickgrid": "^2.1.30", 58 | "jquery": ">=3.4.0", 59 | "jquery-ui": ">=1.8.0", 60 | "tslib": "^1.10.0" 61 | } 62 | }, 63 | "node_modules/@bokeh/slickgrid/node_modules/tslib": { 64 | "version": "1.14.1", 65 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", 66 | "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" 67 | }, 68 | "node_modules/@types/jquery": { 69 | "version": "3.5.5", 70 | "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.5.tgz", 71 | "integrity": "sha512-6RXU9Xzpc6vxNrS6FPPapN1SxSHgQ336WC6Jj/N8q30OiaBZ00l1GBgeP7usjVZPivSkGUfL1z/WW6TX989M+w==", 72 | "dependencies": { 73 | "@types/sizzle": "*" 74 | } 75 | }, 76 | "node_modules/@types/sizzle": { 77 | "version": "2.3.2", 78 | "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz", 79 | "integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==" 80 | }, 81 | "node_modules/@types/slickgrid": { 82 | "version": "2.1.30", 83 | "resolved": "https://registry.npmjs.org/@types/slickgrid/-/slickgrid-2.1.30.tgz", 84 | "integrity": "sha512-9nTqNWD3BtEVK0CP+G+mBtvSrKTfQy3Dg5/al+GdTSVMHFm37UxsHJ1eURwPg7rYu6vc7xU95fGTCKMZbxsD5w==", 85 | "dependencies": { 86 | "@types/jquery": "*" 87 | } 88 | }, 89 | "node_modules/choices.js": { 90 | "version": "9.0.1", 91 | "resolved": "https://registry.npmjs.org/choices.js/-/choices.js-9.0.1.tgz", 92 | "integrity": "sha512-JgpeDY0Tmg7tqY6jaW/druSklJSt7W68tXFJIw0GSGWmO37SDAL8o60eICNGbzIODjj02VNNtf5h6TgoHDtCsA==", 93 | "dependencies": { 94 | "deepmerge": "^4.2.0", 95 | "fuse.js": "^3.4.5", 96 | "redux": "^4.0.4" 97 | } 98 | }, 99 | "node_modules/d": { 100 | "version": "1.0.1", 101 | "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", 102 | "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", 103 | "dependencies": { 104 | "es5-ext": "^0.10.50", 105 | "type": "^1.0.1" 106 | } 107 | }, 108 | "node_modules/deepmerge": { 109 | "version": "4.2.2", 110 | "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", 111 | "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", 112 | "engines": { 113 | "node": ">=0.10.0" 114 | } 115 | }, 116 | "node_modules/es5-ext": { 117 | "version": "0.10.53", 118 | "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", 119 | "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", 120 | "dependencies": { 121 | "es6-iterator": "~2.0.3", 122 | "es6-symbol": "~3.1.3", 123 | "next-tick": "~1.0.0" 124 | } 125 | }, 126 | "node_modules/es6-iterator": { 127 | "version": "2.0.3", 128 | "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", 129 | "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", 130 | "dependencies": { 131 | "d": "1", 132 | "es5-ext": "^0.10.35", 133 | "es6-symbol": "^3.1.1" 134 | } 135 | }, 136 | "node_modules/es6-map": { 137 | "version": "0.1.5", 138 | "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", 139 | "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", 140 | "dependencies": { 141 | "d": "1", 142 | "es5-ext": "~0.10.14", 143 | "es6-iterator": "~2.0.1", 144 | "es6-set": "~0.1.5", 145 | "es6-symbol": "~3.1.1", 146 | "event-emitter": "~0.3.5" 147 | } 148 | }, 149 | "node_modules/es6-promise": { 150 | "version": "4.2.8", 151 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", 152 | "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" 153 | }, 154 | "node_modules/es6-set": { 155 | "version": "0.1.5", 156 | "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", 157 | "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", 158 | "dependencies": { 159 | "d": "1", 160 | "es5-ext": "~0.10.14", 161 | "es6-iterator": "~2.0.1", 162 | "es6-symbol": "3.1.1", 163 | "event-emitter": "~0.3.5" 164 | } 165 | }, 166 | "node_modules/es6-set/node_modules/es6-symbol": { 167 | "version": "3.1.1", 168 | "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", 169 | "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", 170 | "dependencies": { 171 | "d": "1", 172 | "es5-ext": "~0.10.14" 173 | } 174 | }, 175 | "node_modules/es6-symbol": { 176 | "version": "3.1.3", 177 | "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", 178 | "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", 179 | "dependencies": { 180 | "d": "^1.0.1", 181 | "ext": "^1.1.2" 182 | } 183 | }, 184 | "node_modules/es6-weak-map": { 185 | "version": "2.0.3", 186 | "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", 187 | "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", 188 | "dependencies": { 189 | "d": "1", 190 | "es5-ext": "^0.10.46", 191 | "es6-iterator": "^2.0.3", 192 | "es6-symbol": "^3.1.1" 193 | } 194 | }, 195 | "node_modules/event-emitter": { 196 | "version": "0.3.5", 197 | "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", 198 | "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", 199 | "dependencies": { 200 | "d": "1", 201 | "es5-ext": "~0.10.14" 202 | } 203 | }, 204 | "node_modules/ext": { 205 | "version": "1.4.0", 206 | "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", 207 | "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", 208 | "dependencies": { 209 | "type": "^2.0.0" 210 | } 211 | }, 212 | "node_modules/ext/node_modules/type": { 213 | "version": "2.5.0", 214 | "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", 215 | "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==" 216 | }, 217 | "node_modules/flatbush": { 218 | "version": "3.3.0", 219 | "resolved": "https://registry.npmjs.org/flatbush/-/flatbush-3.3.0.tgz", 220 | "integrity": "sha512-F3EzQvKpdmXUbFwWxLKBpytOFEGYQMCTBLuqZ4GEajFOEAvnOIBiyxW3OFSZXIOtpCS8teN6bFEpNZtnVXuDQA==", 221 | "dependencies": { 222 | "flatqueue": "^1.2.0" 223 | } 224 | }, 225 | "node_modules/flatpickr": { 226 | "version": "4.6.9", 227 | "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.9.tgz", 228 | "integrity": "sha512-F0azNNi8foVWKSF+8X+ZJzz8r9sE1G4hl06RyceIaLvyltKvDl6vqk9Lm/6AUUCi5HWaIjiUbk7UpeE/fOXOpw==" 229 | }, 230 | "node_modules/flatqueue": { 231 | "version": "1.2.1", 232 | "resolved": "https://registry.npmjs.org/flatqueue/-/flatqueue-1.2.1.tgz", 233 | "integrity": "sha512-X86TpWS1rGuY7m382HuA9vngLeDuWA9lJvhEG+GfgKMV5onSvx5a71cl7GMbXzhWtlN9dGfqOBrpfqeOtUfGYQ==" 234 | }, 235 | "node_modules/fuse.js": { 236 | "version": "3.6.1", 237 | "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-3.6.1.tgz", 238 | "integrity": "sha512-hT9yh/tiinkmirKrlv4KWOjztdoZo1mx9Qh4KvWqC7isoXwdUY3PNWUxceF4/qO9R6riA2C29jdTOeQOIROjgw==", 239 | "engines": { 240 | "node": ">=6" 241 | } 242 | }, 243 | "node_modules/hammerjs": { 244 | "version": "2.0.8", 245 | "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz", 246 | "integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE=", 247 | "engines": { 248 | "node": ">=0.8.0" 249 | } 250 | }, 251 | "node_modules/jquery": { 252 | "version": "3.6.0", 253 | "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz", 254 | "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==" 255 | }, 256 | "node_modules/jquery-ui": { 257 | "version": "1.12.1", 258 | "resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.12.1.tgz", 259 | "integrity": "sha1-vLQEXI3QU5wTS8FIjN0+dop6nlE=" 260 | }, 261 | "node_modules/js-tokens": { 262 | "version": "4.0.0", 263 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 264 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" 265 | }, 266 | "node_modules/loose-envify": { 267 | "version": "1.4.0", 268 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", 269 | "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", 270 | "dependencies": { 271 | "js-tokens": "^3.0.0 || ^4.0.0" 272 | }, 273 | "bin": { 274 | "loose-envify": "cli.js" 275 | } 276 | }, 277 | "node_modules/mgrs": { 278 | "version": "1.0.0", 279 | "resolved": "https://registry.npmjs.org/mgrs/-/mgrs-1.0.0.tgz", 280 | "integrity": "sha1-+5FYjnjJACVnI5XLQLJffNatGCk=" 281 | }, 282 | "node_modules/next-tick": { 283 | "version": "1.0.0", 284 | "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", 285 | "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" 286 | }, 287 | "node_modules/nouislider": { 288 | "version": "14.6.4", 289 | "resolved": "https://registry.npmjs.org/nouislider/-/nouislider-14.6.4.tgz", 290 | "integrity": "sha512-PVCGYl+aC7/nVEbW61ypJWfuW3UCpvctz/luxpt4byxxli1FFyjBX9NIiy4Yak9AaO6a5BkPGfFYMCW4eg3eeQ==" 291 | }, 292 | "node_modules/proj4": { 293 | "version": "2.7.2", 294 | "resolved": "https://registry.npmjs.org/proj4/-/proj4-2.7.2.tgz", 295 | "integrity": "sha512-x/EboBmIq48a9FED0Z9zWCXkd8VIpXHLsyEXljGtsnzeztC41bFjPjJ0S//wBbNLDnDYRe0e6c3FSSiqMCebDA==", 296 | "dependencies": { 297 | "mgrs": "1.0.0", 298 | "wkt-parser": "^1.2.4" 299 | } 300 | }, 301 | "node_modules/redux": { 302 | "version": "4.0.5", 303 | "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz", 304 | "integrity": "sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==", 305 | "dependencies": { 306 | "loose-envify": "^1.4.0", 307 | "symbol-observable": "^1.2.0" 308 | } 309 | }, 310 | "node_modules/sprintf-js": { 311 | "version": "1.1.2", 312 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", 313 | "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" 314 | }, 315 | "node_modules/symbol-observable": { 316 | "version": "1.2.0", 317 | "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", 318 | "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", 319 | "engines": { 320 | "node": ">=0.10.0" 321 | } 322 | }, 323 | "node_modules/timezone": { 324 | "version": "1.0.23", 325 | "resolved": "https://registry.npmjs.org/timezone/-/timezone-1.0.23.tgz", 326 | "integrity": "sha512-yhQgk6qmSLB+TF8HGmApZAVI5bfzR1CoKUGr+WMZWmx75ED1uDewAZA8QMGCQ70TEv4GmM8pDB9jrHuxdaQ1PA==" 327 | }, 328 | "node_modules/tslib": { 329 | "version": "2.1.0", 330 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", 331 | "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" 332 | }, 333 | "node_modules/type": { 334 | "version": "1.2.0", 335 | "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", 336 | "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" 337 | }, 338 | "node_modules/underscore.template": { 339 | "version": "0.1.7", 340 | "resolved": "https://registry.npmjs.org/underscore.template/-/underscore.template-0.1.7.tgz", 341 | "integrity": "sha1-MBPg6hgXVjBvFgnpWcr7xyKts+k=" 342 | }, 343 | "node_modules/wkt-parser": { 344 | "version": "1.2.4", 345 | "resolved": "https://registry.npmjs.org/wkt-parser/-/wkt-parser-1.2.4.tgz", 346 | "integrity": "sha512-ZzKnc7ml/91fOPh5bANBL4vUlWPIYYv11waCtWTkl2TRN+LEmBg60Q1MA8gqV4hEp4MGfSj9JiHz91zw/gTDXg==" 347 | } 348 | }, 349 | "dependencies": { 350 | "@bokeh/bokehjs": { 351 | "version": "2.3.0", 352 | "resolved": "https://registry.npmjs.org/@bokeh/bokehjs/-/bokehjs-2.3.0.tgz", 353 | "integrity": "sha512-geKBhYUVJ5IaY0UNk9k2P0yiYLCj+DOeNjdDneuTJ8K5R9fs0Rpp4iiaQKUGr1yUyQHGHLU8sk4CFZ+Bd5ZILg==", 354 | "requires": { 355 | "@bokeh/numbro": "^1.6.2", 356 | "@bokeh/slickgrid": "~2.4.2701", 357 | "choices.js": "^9.0.1", 358 | "es5-ext": "^0.10.53", 359 | "es6-map": "^0.1.5", 360 | "es6-promise": "4.2.8", 361 | "es6-set": "^0.1.5", 362 | "es6-symbol": "^3.1.3", 363 | "es6-weak-map": "^2.0.2", 364 | "flatbush": "^3.2.1", 365 | "flatpickr": "^4.6.6", 366 | "hammerjs": "^2.0.4", 367 | "nouislider": "^14.6.3", 368 | "proj4": "^2.6.3", 369 | "sprintf-js": "^1.1.2", 370 | "timezone": "^1.0.23", 371 | "tslib": "^2.0.3", 372 | "underscore.template": "^0.1.7" 373 | } 374 | }, 375 | "@bokeh/numbro": { 376 | "version": "1.6.2", 377 | "resolved": "https://registry.npmjs.org/@bokeh/numbro/-/numbro-1.6.2.tgz", 378 | "integrity": "sha512-owIECPc3T3QXHCb2v5Ez+/uE9SIxI7N4nd9iFlWnfBrOelr0/omvFn09VisRn37AAFAY39sJiCVgECwryHWUPA==" 379 | }, 380 | "@bokeh/slickgrid": { 381 | "version": "2.4.2702", 382 | "resolved": "https://registry.npmjs.org/@bokeh/slickgrid/-/slickgrid-2.4.2702.tgz", 383 | "integrity": "sha512-W9tm8Qdw5BrylbZbaVWaQMgLfW/klesnj6J3FnyWpo18hCCOFApccUD8iOnRv7bF6PHlgWk84mW3JT5RSzYKjA==", 384 | "requires": { 385 | "@types/slickgrid": "^2.1.30", 386 | "jquery": ">=3.4.0", 387 | "jquery-ui": ">=1.8.0", 388 | "tslib": "^1.10.0" 389 | }, 390 | "dependencies": { 391 | "tslib": { 392 | "version": "1.14.1", 393 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", 394 | "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" 395 | } 396 | } 397 | }, 398 | "@types/jquery": { 399 | "version": "3.5.5", 400 | "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.5.tgz", 401 | "integrity": "sha512-6RXU9Xzpc6vxNrS6FPPapN1SxSHgQ336WC6Jj/N8q30OiaBZ00l1GBgeP7usjVZPivSkGUfL1z/WW6TX989M+w==", 402 | "requires": { 403 | "@types/sizzle": "*" 404 | } 405 | }, 406 | "@types/sizzle": { 407 | "version": "2.3.2", 408 | "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz", 409 | "integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==" 410 | }, 411 | "@types/slickgrid": { 412 | "version": "2.1.30", 413 | "resolved": "https://registry.npmjs.org/@types/slickgrid/-/slickgrid-2.1.30.tgz", 414 | "integrity": "sha512-9nTqNWD3BtEVK0CP+G+mBtvSrKTfQy3Dg5/al+GdTSVMHFm37UxsHJ1eURwPg7rYu6vc7xU95fGTCKMZbxsD5w==", 415 | "requires": { 416 | "@types/jquery": "*" 417 | } 418 | }, 419 | "choices.js": { 420 | "version": "9.0.1", 421 | "resolved": "https://registry.npmjs.org/choices.js/-/choices.js-9.0.1.tgz", 422 | "integrity": "sha512-JgpeDY0Tmg7tqY6jaW/druSklJSt7W68tXFJIw0GSGWmO37SDAL8o60eICNGbzIODjj02VNNtf5h6TgoHDtCsA==", 423 | "requires": { 424 | "deepmerge": "^4.2.0", 425 | "fuse.js": "^3.4.5", 426 | "redux": "^4.0.4" 427 | } 428 | }, 429 | "d": { 430 | "version": "1.0.1", 431 | "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", 432 | "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", 433 | "requires": { 434 | "es5-ext": "^0.10.50", 435 | "type": "^1.0.1" 436 | } 437 | }, 438 | "deepmerge": { 439 | "version": "4.2.2", 440 | "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", 441 | "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" 442 | }, 443 | "es5-ext": { 444 | "version": "0.10.53", 445 | "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", 446 | "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", 447 | "requires": { 448 | "es6-iterator": "~2.0.3", 449 | "es6-symbol": "~3.1.3", 450 | "next-tick": "~1.0.0" 451 | } 452 | }, 453 | "es6-iterator": { 454 | "version": "2.0.3", 455 | "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", 456 | "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", 457 | "requires": { 458 | "d": "1", 459 | "es5-ext": "^0.10.35", 460 | "es6-symbol": "^3.1.1" 461 | } 462 | }, 463 | "es6-map": { 464 | "version": "0.1.5", 465 | "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", 466 | "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", 467 | "requires": { 468 | "d": "1", 469 | "es5-ext": "~0.10.14", 470 | "es6-iterator": "~2.0.1", 471 | "es6-set": "~0.1.5", 472 | "es6-symbol": "~3.1.1", 473 | "event-emitter": "~0.3.5" 474 | } 475 | }, 476 | "es6-promise": { 477 | "version": "4.2.8", 478 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", 479 | "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" 480 | }, 481 | "es6-set": { 482 | "version": "0.1.5", 483 | "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", 484 | "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", 485 | "requires": { 486 | "d": "1", 487 | "es5-ext": "~0.10.14", 488 | "es6-iterator": "~2.0.1", 489 | "es6-symbol": "3.1.1", 490 | "event-emitter": "~0.3.5" 491 | }, 492 | "dependencies": { 493 | "es6-symbol": { 494 | "version": "3.1.1", 495 | "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", 496 | "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", 497 | "requires": { 498 | "d": "1", 499 | "es5-ext": "~0.10.14" 500 | } 501 | } 502 | } 503 | }, 504 | "es6-symbol": { 505 | "version": "3.1.3", 506 | "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", 507 | "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", 508 | "requires": { 509 | "d": "^1.0.1", 510 | "ext": "^1.1.2" 511 | } 512 | }, 513 | "es6-weak-map": { 514 | "version": "2.0.3", 515 | "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", 516 | "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", 517 | "requires": { 518 | "d": "1", 519 | "es5-ext": "^0.10.46", 520 | "es6-iterator": "^2.0.3", 521 | "es6-symbol": "^3.1.1" 522 | } 523 | }, 524 | "event-emitter": { 525 | "version": "0.3.5", 526 | "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", 527 | "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", 528 | "requires": { 529 | "d": "1", 530 | "es5-ext": "~0.10.14" 531 | } 532 | }, 533 | "ext": { 534 | "version": "1.4.0", 535 | "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", 536 | "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", 537 | "requires": { 538 | "type": "^2.0.0" 539 | }, 540 | "dependencies": { 541 | "type": { 542 | "version": "2.5.0", 543 | "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", 544 | "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==" 545 | } 546 | } 547 | }, 548 | "flatbush": { 549 | "version": "3.3.0", 550 | "resolved": "https://registry.npmjs.org/flatbush/-/flatbush-3.3.0.tgz", 551 | "integrity": "sha512-F3EzQvKpdmXUbFwWxLKBpytOFEGYQMCTBLuqZ4GEajFOEAvnOIBiyxW3OFSZXIOtpCS8teN6bFEpNZtnVXuDQA==", 552 | "requires": { 553 | "flatqueue": "^1.2.0" 554 | } 555 | }, 556 | "flatpickr": { 557 | "version": "4.6.9", 558 | "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.9.tgz", 559 | "integrity": "sha512-F0azNNi8foVWKSF+8X+ZJzz8r9sE1G4hl06RyceIaLvyltKvDl6vqk9Lm/6AUUCi5HWaIjiUbk7UpeE/fOXOpw==" 560 | }, 561 | "flatqueue": { 562 | "version": "1.2.1", 563 | "resolved": "https://registry.npmjs.org/flatqueue/-/flatqueue-1.2.1.tgz", 564 | "integrity": "sha512-X86TpWS1rGuY7m382HuA9vngLeDuWA9lJvhEG+GfgKMV5onSvx5a71cl7GMbXzhWtlN9dGfqOBrpfqeOtUfGYQ==" 565 | }, 566 | "fuse.js": { 567 | "version": "3.6.1", 568 | "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-3.6.1.tgz", 569 | "integrity": "sha512-hT9yh/tiinkmirKrlv4KWOjztdoZo1mx9Qh4KvWqC7isoXwdUY3PNWUxceF4/qO9R6riA2C29jdTOeQOIROjgw==" 570 | }, 571 | "hammerjs": { 572 | "version": "2.0.8", 573 | "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz", 574 | "integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE=" 575 | }, 576 | "jquery": { 577 | "version": "3.6.0", 578 | "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz", 579 | "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==" 580 | }, 581 | "jquery-ui": { 582 | "version": "1.12.1", 583 | "resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.12.1.tgz", 584 | "integrity": "sha1-vLQEXI3QU5wTS8FIjN0+dop6nlE=" 585 | }, 586 | "js-tokens": { 587 | "version": "4.0.0", 588 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 589 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" 590 | }, 591 | "loose-envify": { 592 | "version": "1.4.0", 593 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", 594 | "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", 595 | "requires": { 596 | "js-tokens": "^3.0.0 || ^4.0.0" 597 | } 598 | }, 599 | "mgrs": { 600 | "version": "1.0.0", 601 | "resolved": "https://registry.npmjs.org/mgrs/-/mgrs-1.0.0.tgz", 602 | "integrity": "sha1-+5FYjnjJACVnI5XLQLJffNatGCk=" 603 | }, 604 | "next-tick": { 605 | "version": "1.0.0", 606 | "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", 607 | "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" 608 | }, 609 | "nouislider": { 610 | "version": "14.6.4", 611 | "resolved": "https://registry.npmjs.org/nouislider/-/nouislider-14.6.4.tgz", 612 | "integrity": "sha512-PVCGYl+aC7/nVEbW61ypJWfuW3UCpvctz/luxpt4byxxli1FFyjBX9NIiy4Yak9AaO6a5BkPGfFYMCW4eg3eeQ==" 613 | }, 614 | "proj4": { 615 | "version": "2.7.2", 616 | "resolved": "https://registry.npmjs.org/proj4/-/proj4-2.7.2.tgz", 617 | "integrity": "sha512-x/EboBmIq48a9FED0Z9zWCXkd8VIpXHLsyEXljGtsnzeztC41bFjPjJ0S//wBbNLDnDYRe0e6c3FSSiqMCebDA==", 618 | "requires": { 619 | "mgrs": "1.0.0", 620 | "wkt-parser": "^1.2.4" 621 | } 622 | }, 623 | "redux": { 624 | "version": "4.0.5", 625 | "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz", 626 | "integrity": "sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==", 627 | "requires": { 628 | "loose-envify": "^1.4.0", 629 | "symbol-observable": "^1.2.0" 630 | } 631 | }, 632 | "sprintf-js": { 633 | "version": "1.1.2", 634 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", 635 | "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" 636 | }, 637 | "symbol-observable": { 638 | "version": "1.2.0", 639 | "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", 640 | "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" 641 | }, 642 | "timezone": { 643 | "version": "1.0.23", 644 | "resolved": "https://registry.npmjs.org/timezone/-/timezone-1.0.23.tgz", 645 | "integrity": "sha512-yhQgk6qmSLB+TF8HGmApZAVI5bfzR1CoKUGr+WMZWmx75ED1uDewAZA8QMGCQ70TEv4GmM8pDB9jrHuxdaQ1PA==" 646 | }, 647 | "tslib": { 648 | "version": "2.1.0", 649 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", 650 | "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" 651 | }, 652 | "type": { 653 | "version": "1.2.0", 654 | "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", 655 | "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" 656 | }, 657 | "underscore.template": { 658 | "version": "0.1.7", 659 | "resolved": "https://registry.npmjs.org/underscore.template/-/underscore.template-0.1.7.tgz", 660 | "integrity": "sha1-MBPg6hgXVjBvFgnpWcr7xyKts+k=" 661 | }, 662 | "wkt-parser": { 663 | "version": "1.2.4", 664 | "resolved": "https://registry.npmjs.org/wkt-parser/-/wkt-parser-1.2.4.tgz", 665 | "integrity": "sha512-ZzKnc7ml/91fOPh5bANBL4vUlWPIYYv11waCtWTkl2TRN+LEmBg60Q1MA8gqV4hEp4MGfSj9JiHz91zw/gTDXg==" 666 | } 667 | } 668 | } 669 | -------------------------------------------------------------------------------- /panel_sketch/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "panel_sketch", 3 | "version": "0.0.1", 4 | "description": "HighCharts extensions for Panel", 5 | "license": "BSD-3-Clause", 6 | "keywords": [], 7 | "repository": {}, 8 | "dependencies": { 9 | "@bokeh/bokehjs": "^2.3.0" 10 | }, 11 | "devDependencies": {} 12 | } 13 | -------------------------------------------------------------------------------- /panel_sketch/sketch.py: -------------------------------------------------------------------------------- 1 | """Sketch makes it easy for Pythonistas to quickly sketch interactive visualizations and other 2 | applications running in. 3 | 4 | - the browser. Potentially without a Python backend 5 | - the Jupyter Notebook. 6 | - your favorite editor or IDE. 7 | 8 | It is heavily inspired by [p5js](https://p5js.org/get-started/), 9 | [p5js sketches](https://editor.p5js.org/p5/sketches) and 10 | [pyp5js](https://github.com/berinhard/pyp5js) but not limited to the p5js universe. You can also 11 | think of it as a [Code Sandbox](https://codesandbox.io/) or 12 | [JS Fiddle](https://jsfiddle.net/) but for #Python 🐍 and data science. 13 | """ 14 | 15 | import panel as pn 16 | import param 17 | 18 | from .sketch_base import SketchBase 19 | from .sketch_compiler import COMPILERS 20 | from .sketch_editor import SketchEditor 21 | from .sketch_viewer import SketchViewer 22 | 23 | pn.config.js_files["p5"] = "https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.js" 24 | pn.config.js_files["pyodide"] = "https://pyodide-cdn2.iodide.io/v0.15.0/full/pyodide.js" 25 | 26 | 27 | class Sketch(SketchBase): # pylint: disable=too-many-instance-attributes 28 | """Sketch makes it easy for Pythonistas to quickly sketch interactive visualizations and other 29 | applications running in. 30 | 31 | - the browser. Potentially without a Python backend 32 | - the Jupyter Notebook. 33 | - your favorite editor or IDE. 34 | 35 | It is heavily inspired by [p5js](https://p5js.org/get-started/), 36 | [p5js sketches](https://editor.p5js.org/p5/sketches) and 37 | [pyp5js](https://github.com/berinhard/pyp5js) but not limited to the p5js universe. You can also 38 | think of it as a [Code Sandbox](https://codesandbox.io/) or 39 | [JS Fiddle](https://jsfiddle.net/) but for #Python 🐍 and data science.""" 40 | 41 | def __init__(self, **params): 42 | params["args"] = params.get("args", {}) 43 | 44 | super().__init__(**params) 45 | 46 | self._viewer = None 47 | self._editor = None 48 | self._compilers = {} 49 | 50 | self._compile_object() 51 | 52 | @property 53 | def viewer(self): 54 | """A Viewer that makes viewing the Sketch a joy""" 55 | if not self._viewer: 56 | self._viewer = SketchViewer(sketch=self) 57 | return self._viewer 58 | 59 | @property 60 | def editor(self): 61 | """An Editor that makes editing the Sketch a joy""" 62 | if not self._editor: 63 | self._editor = SketchEditor(sketch=self) 64 | return self._editor 65 | 66 | @property 67 | def _compiler(self): 68 | """A Compiler that makes compiling the Sketch a joy""" 69 | if self.compiler not in self._compilers: 70 | self._compilers[self.compiler] = COMPILERS[self.compiler](sketch=self) 71 | return self._compilers[self.compiler] 72 | 73 | @param.depends("object", watch=True) 74 | def _compile_object(self): 75 | self._compiler.run() 76 | -------------------------------------------------------------------------------- /panel_sketch/sketch_base.py: -------------------------------------------------------------------------------- 1 | """SketchBase is the basic Data Model of a Sketch""" 2 | import param 3 | 4 | DEFAULT_SKETCH = """ 5 | def setup(): 6 | 7 | createCanvas(200, 200) 8 | 9 | background(160) 10 | 11 | def draw(): 12 | 13 | fill("blue") 14 | 15 | background(200) 16 | 17 | radius = sin(frameCount / 60) * 50 + 50 18 | 19 | ellipse(100, 100, radius, radius) 20 | """ 21 | 22 | TEMPLATES = ["basic", "pyp5js"] 23 | DEFAULT_TEMPLATE = "pyp5js" 24 | 25 | COMPILERS = ["pyodide", "transcrypt"] 26 | DEFAULT_COMPILER = "pyodide" 27 | 28 | 29 | class SketchBase(param.Parameterized): 30 | """SketchBase is the basic Data Model of a Sketch""" 31 | 32 | object = param.String( 33 | default=DEFAULT_SKETCH, 34 | doc="""A Python script. It is transpiled to javascript (Transcript) or run directly in javascript (Pyodide). You can reference the `div` element via `sketchElement` in Python""", 35 | ) 36 | html = param.String( 37 | default="""
""", 38 | doc="""A HTML String to mark up the Sketch.""", 39 | ) 40 | css = param.String( 41 | default="", 42 | doc="""A CSS String to style the Sketch. You can style the HTML div via the `#sketch-element` reference.""", 43 | ) 44 | javascript = param.String( 45 | default="", doc="""The result of the compilation of the python object.""" 46 | ) 47 | 48 | args = param.Dict( 49 | doc="""A Dictionary of keys and values that can be reference via `window.args` in the python script.""" 50 | ) 51 | 52 | template = param.ObjectSelector( 53 | DEFAULT_TEMPLATE, 54 | objects=TEMPLATES, 55 | doc="""The template to use for compilation. One of 'basic', 'pyp5js'. Default is (currently) 'pyp5js'.""", 56 | ) 57 | compiler = param.ObjectSelector(DEFAULT_COMPILER, objects=COMPILERS) 58 | 59 | loading = param.Boolean( 60 | doc="""Whether or not the Sketch is loading. For example during compilation.""" 61 | ) 62 | 63 | def __init__(self, **params): 64 | if "args" not in params: 65 | params["args"] = {} 66 | 67 | super().__init__(**params) 68 | -------------------------------------------------------------------------------- /panel_sketch/sketch_compiler/__init__.py: -------------------------------------------------------------------------------- 1 | """The Sketch Compilers makes it easy to compiles a Sketch""" 2 | import pathlib 3 | import subprocess 4 | import tempfile 5 | from textwrap import dedent 6 | from typing import Dict, List 7 | 8 | import param 9 | 10 | from ..sketch_base import SketchBase 11 | 12 | ROOT = pathlib.Path(__file__).parent 13 | 14 | PYODIDE_TEMPLATE_STRINGS = { 15 | "basic": (ROOT / "template_pyodide_basic.js").read_text(), 16 | "pyp5js": (ROOT / "template_pyodide_pyp5js.js").read_text(), 17 | } 18 | 19 | TRANSCRYPT_TEMPLATE_STRINGS = { 20 | "basic": (ROOT / "template_transcrypt_basic.py").read_text(), 21 | "pyp5js": (ROOT / "template_transcrypt_pyp5js.py").read_text(), 22 | } 23 | 24 | OBJECT_PREFIX = "sketchElement = document.getElementById('sketch-element')\n" 25 | 26 | TRANSCRYPT_DIR = str(ROOT / "assets" / "js" / "transcrypt").replace("\\", "/") + "/" 27 | 28 | print(f""" 29 | Warning: Remember to add --static-dirs transcrypt={TRANSCRYPT_DIR} when running panel serve""" 30 | ) 31 | 32 | 33 | class SketchCompilerBase(param.Parameterized): 34 | """The SketchCompilerBase should be inherited by child classes""" 35 | 36 | run = param.Action(constant=True) 37 | 38 | sketch = param.ClassSelector(class_=SketchBase, precedence=-1, constant=True) 39 | 40 | _TEMPLATE_STRINGS: Dict[str, str] = {} 41 | 42 | def __init__(self, **params): 43 | super().__init__(**params) 44 | 45 | with param.edit_constant(self): 46 | self.run = self._run_compiler 47 | 48 | def _run_compiler(self): 49 | # pylint: disable=no-member 50 | self.sketch.loading=True 51 | 52 | python = OBJECT_PREFIX + self.sketch.object 53 | self.sketch.javascript = self._compile(python, self._template_string) 54 | 55 | self.sketch.loading=False 56 | 57 | @classmethod 58 | def _compile(cls, sketch_object, template_string): 59 | raise NotImplementedError("Implement this is child classes") 60 | 61 | @property 62 | def _template_string(self): 63 | # pylint: disable=no-member 64 | return self._TEMPLATE_STRINGS[self.sketch.template] 65 | 66 | 67 | class TranscryptCompiler(SketchCompilerBase): 68 | """The TranscryptCompiler uses the Transcrypt Python library""" 69 | 70 | arguments = param.List( 71 | default=["transcrypt", "-b", "-n", "-m"], 72 | constant=True, 73 | doc="""The arguments to transpile from sketch.py to sketch.js""", 74 | ) 75 | 76 | _TEMPLATE_STRINGS: Dict[str, str] = TRANSCRYPT_TEMPLATE_STRINGS 77 | 78 | @classmethod 79 | def _compile(cls, sketch_object, template_string): 80 | if "from pyp5js import *" in template_string: 81 | template_name = "pyp5js" 82 | else: 83 | template_name = "basic" 84 | with tempfile.TemporaryDirectory(prefix="panel_sketch_transcrypt") as tmpdir: 85 | root = pathlib.Path(tmpdir) 86 | sketch_py = root / "sketch.py" 87 | sketch_py.write_text(template_string.replace("{{sketch_object}}", sketch_object)) 88 | 89 | if template_name == "pyp5js": 90 | arguments = [ 91 | "transcrypt", 92 | "-xp", 93 | "c:\\repos\\private\\panel-sketch\\.venv\\lib\\site-packages\\pyp5js", 94 | "-k", 95 | "-ks", 96 | "-b", 97 | "-m", 98 | "-n", 99 | str(sketch_py), 100 | ] 101 | else: 102 | arguments = ["transcrypt", "-b", "-n", "-m"] + [str(sketch_py)] 103 | print(" ".join(arguments)) 104 | subprocess.run( 105 | arguments, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, check=True 106 | ) 107 | 108 | # We should find a way to serve the transcrypt and p5 assets locally 109 | sketch_js = (root / "__target__/sketch.js").read_text().replace("from './", "from '../transcrypt/") 110 | # results.append(sketch_js) 111 | return sketch_js 112 | 113 | 114 | class PyodideCompiler(SketchCompilerBase): 115 | """The PyodideCompiler uses the Pyodide JS library""" 116 | 117 | run = param.Action(constant=True) 118 | 119 | sketch = param.ClassSelector(class_=SketchBase, precedence=-1, constant=True) 120 | 121 | _TEMPLATE_STRINGS: Dict[str, str] = PYODIDE_TEMPLATE_STRINGS 122 | 123 | @classmethod 124 | def _compile(cls, sketch_object, template_string): 125 | sketch_object = cls._clean_object(sketch_object) 126 | return template_string.replace("{{sketch_object}}", sketch_object) 127 | 128 | @staticmethod 129 | def _clean_object(value: str) -> str: 130 | clean = dedent(value) 131 | clean = clean.replace("from pyp5js import *\n", "") 132 | return clean 133 | 134 | 135 | COMPILERS = {"pyodide": PyodideCompiler, "transcrypt": TranscryptCompiler} 136 | -------------------------------------------------------------------------------- /panel_sketch/sketch_compiler/assets/js/transcrypt/org.transcrypt.__runtime__.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "file": "org.transcrypt.__runtime__.js", 4 | "sources": [ 5 | "org.transcrypt.__runtime__.py" 6 | ], 7 | "mappings": "AAAA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUA;AAAA;AAAA;AAGA;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AAAA;AAAA;AAEA;AAAA;AACA;AAEA;AACA;AACA;AAAA;AACA;AACA;AAAA;AACA;AACA;AAAA;AAAA;AAEA;AACA;AACA;AAAA;AACA;AACA;AAAA;AACA;AACA;AAAA;AAAA;AAAA;AAEA;AAAA;AACA;AACA;AAAA;AAAA;AAEA;AAAA;AACA;AACA;AAAA;AAAA;AAEA;AAAA;AACA;AACA;AAAA;AAAA;AAEA;AAAA;AACA;AACA;AAAA;AAAA;AAEA;AAAA;AACA;AACA;AACA;AAAA;AACA;AACA;AAAA;AAAA;AAAA;AAEA;AAAA;AACA;AACA;AAAA;AAAA;AAEA;AAAA;AACA;AACA;AAAA;AAAA;AAEA;AAAA;AACA;AACA;AAAA;AAAA;AAEA;AAAA;AACA;AACA;AAAA;AAAA;AAMA;AAAA;AAAA;AAKA;AAAA;AAAA;AAGA;AAAA;AAAA;AAGA;AAAA;AAAA;AAKA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AAAA;AAEA;AACA;AAAA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AAAA;AACA;AACA;AAAA;AAEA;AACA;AAAA;AAIA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA;AACA;AACA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA;AACA;AAAA;AA0GA;AAAA;AAUA;AACA;AAEA;AACA;AAAA;AAAA;AAEA;AAAA;AAEA;AACA;AACA;AACA;AACA;AAAA;AAEA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA;AACA;AACA;AAAA;AACA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AAEA;AAAA;AAEA;AAEA;AACA;AAAA" 8 | } -------------------------------------------------------------------------------- /panel_sketch/sketch_compiler/assets/js/transcrypt/org.transcrypt.__runtime__.py: -------------------------------------------------------------------------------- 1 | # Transcrypt runtime module 2 | 3 | # __pragma__ ('js', 'export var __envir__ = {{}};\n{}', __include__ ('org/transcrypt/__envir__.js')) 4 | # __pragma__ ('js', '{}', __include__ ('org/transcrypt/__core__.js')) 5 | # __pragma__ ('js', '{}', __include__ ('org/transcrypt/__builtin__.js')) 6 | 7 | # __pragma__ ('skip') 8 | copy = Math = __typeof__ = __repr__ = document = console = window = 0 9 | # __pragma__ ('noskip') 10 | 11 | # __pragma__ ('notconv') # !!! tconv gives a problem with __terminal__, needs investigation 12 | # __pragma__ ('nokwargs') 13 | # __pragma__ ('noalias', 'sort') 14 | 15 | 16 | class BaseException: 17 | pass 18 | 19 | 20 | class Exception(BaseException): 21 | # __pragma__ ('kwargs') 22 | def __init__(self, *args, **kwargs): 23 | self.__args__ = args 24 | try: 25 | self.stack = kwargs.error.stack # Integrate with JavaScript Error object 26 | except: 27 | self.stack = "No stack trace available" 28 | 29 | # __pragma__ ('nokwargs') 30 | 31 | def __repr__(self): 32 | if len(self.__args__) > 1: 33 | return "{}{}".format(self.__class__.__name__, repr(tuple(self.__args__))) 34 | elif len(self.__args__): 35 | return "{}({})".format(self.__class__.__name__, repr(self.__args__[0])) 36 | else: 37 | return "{}()".format(self.__class__.__name__) 38 | 39 | def __str__(self): 40 | if len(self.__args__) > 1: 41 | return str(tuple(self.__args__)) 42 | elif len(self.__args__): 43 | return str(self.__args__[0]) 44 | else: 45 | return "" 46 | 47 | 48 | class IterableError(Exception): 49 | def __init__(self, error): 50 | Exception.__init__(self, "Can't iterate over non-iterable", error=error) 51 | 52 | 53 | class StopIteration(Exception): 54 | def __init__(self, error): 55 | Exception.__init__(self, "Iterator exhausted", error=error) 56 | 57 | 58 | class ValueError(Exception): 59 | def __init__(self, message, error): 60 | Exception.__init__(self, message, error=error) 61 | 62 | 63 | class KeyError(Exception): 64 | def __init__(self, message, error): 65 | Exception.__init__(self, message, error=error) 66 | 67 | 68 | class AssertionError(Exception): 69 | def __init__(self, message, error): 70 | if message: 71 | Exception.__init__(self, message, error=error) 72 | else: 73 | Exception.__init__(self, error=error) 74 | 75 | 76 | class NotImplementedError(Exception): 77 | def __init__(self, message, error): 78 | Exception.__init__(self, message, error=error) 79 | 80 | 81 | class IndexError(Exception): 82 | def __init__(self, message, error): 83 | Exception.__init__(self, message, error=error) 84 | 85 | 86 | class AttributeError(Exception): 87 | def __init__(self, message, error): 88 | Exception.__init__(self, message, error=error) 89 | 90 | 91 | class TypeError(Exception): 92 | def __init__(self, message, error): 93 | Exception.__init__(self, message, error=error) 94 | 95 | 96 | # Warnings Exceptions 97 | # N.B. This is a limited subset of the warnings defined in 98 | # the cpython implementation to keep things small for now. 99 | 100 | 101 | class Warning(Exception): 102 | """Warning Base Class""" 103 | 104 | 105 | class UserWarning(Warning): 106 | pass 107 | 108 | 109 | class DeprecationWarning(Warning): 110 | pass 111 | 112 | 113 | class RuntimeWarning(Warning): 114 | pass 115 | 116 | 117 | # __pragma__ ('kwargs') 118 | 119 | 120 | def __sort__(iterable, key=None, reverse=False): # Used by py_sort, can deal with kwargs 121 | if key: 122 | iterable.sort( 123 | lambda a, b: 1 if key(a) > key(b) else -1 124 | ) # JavaScript sort, case '==' is irrelevant for sorting 125 | else: 126 | iterable.sort() # JavaScript sort 127 | 128 | if reverse: 129 | iterable.reverse() 130 | 131 | 132 | def sorted(iterable, key=None, reverse=False): 133 | if type(iterable) == dict: 134 | result = copy(iterable.keys()) 135 | else: 136 | result = copy(iterable) 137 | 138 | __sort__(result, key, reverse) 139 | return result 140 | 141 | 142 | # __pragma__ ('nokwargs') 143 | 144 | 145 | def map(func, iterable): 146 | return [func(item) for item in iterable] 147 | 148 | 149 | def filter(func, iterable): 150 | if func == None: 151 | func = bool 152 | return [item for item in iterable if func(item)] 153 | 154 | 155 | def divmod(n, d): 156 | return n // d, n % d 157 | 158 | 159 | # __pragma__ ('ifdef', '__complex__') 160 | 161 | 162 | class complex: 163 | def __init__(self, real, imag=None): 164 | if imag == None: 165 | if type(real) == complex: 166 | self.real = real.real 167 | self.imag = real.imag 168 | else: 169 | self.real = real 170 | self.imag = 0 171 | else: 172 | self.real = real 173 | self.imag = imag 174 | 175 | def __neg__(self): 176 | return complex(-self.real, -self.imag) 177 | 178 | def __exp__(self): 179 | modulus = Math.exp(self.real) 180 | return complex(modulus * Math.cos(self.imag), modulus * Math.sin(self.imag)) 181 | 182 | def __log__(self): 183 | return complex( 184 | Math.log(Math.sqrt(self.real * self.real + self.imag * self.imag)), 185 | Math.atan2(self.imag, self.real), 186 | ) 187 | 188 | def __pow__(self, other): # a ** b = exp (b log a) 189 | return (self.__log__().__mul__(other)).__exp__() 190 | 191 | def __rpow__(self, real): # real ** comp -> comp.__rpow__ (real) 192 | return self.__mul__(Math.log(real)).__exp__() 193 | 194 | def __mul__(self, other): 195 | if __typeof__(other) is "number": 196 | return complex(self.real * other, self.imag * other) 197 | else: 198 | return complex( 199 | self.real * other.real - self.imag * other.imag, 200 | self.real * other.imag + self.imag * other.real, 201 | ) 202 | 203 | def __rmul__(self, real): # real + comp -> comp.__rmul__ (real) 204 | return complex(self.real * real, self.imag * real) 205 | 206 | def __div__(self, other): 207 | if __typeof__(other) is "number": 208 | return complex(self.real / other, self.imag / other) 209 | else: 210 | denom = other.real * other.real + other.imag * other.imag 211 | return complex( 212 | (self.real * other.real + self.imag * other.imag) / denom, 213 | (self.imag * other.real - self.real * other.imag) / denom, 214 | ) 215 | 216 | def __rdiv__(self, real): # real / comp -> comp.__rdiv__ (real) 217 | denom = self.real * self.real 218 | return complex((real * self.real) / denom, (real * self.imag) / denom) 219 | 220 | def __add__(self, other): 221 | if __typeof__(other) is "number": 222 | return complex(self.real + other, self.imag) 223 | else: # Assume other is complex 224 | return complex(self.real + other.real, self.imag + other.imag) 225 | 226 | def __radd__(self, real): # real + comp -> comp.__radd__ (real) 227 | return complex(self.real + real, self.imag) 228 | 229 | def __sub__(self, other): 230 | if __typeof__(other) is "number": 231 | return complex(self.real - other, self.imag) 232 | else: 233 | return complex(self.real - other.real, self.imag - other.imag) 234 | 235 | def __rsub__(self, real): # real - comp -> comp.__rsub__ (real) 236 | return complex(real - self.real, -self.imag) 237 | 238 | def __repr__(self): 239 | return "({}{}{}j)".format(self.real, "+" if self.imag >= 0 else "", self.imag) 240 | 241 | def __str__(self): 242 | return __repr__(self)[1:-1] 243 | 244 | def __eq__(self, other): 245 | if __typeof__(other) is "number": 246 | return self.real == other 247 | else: 248 | return self.real == other.real and self.imag == other.imag 249 | 250 | def __ne__(self, other): 251 | if __typeof__(other) is "number": 252 | return self.real != other 253 | else: 254 | return self.real != other.real or self.imag != other.imag 255 | 256 | def conjugate(self): 257 | return complex(self.real, -self.imag) 258 | 259 | 260 | def __conj__(aNumber): 261 | if isinstance(aNumber, complex): 262 | return complex(aNumber.real, -aNumber.imag) 263 | else: 264 | return complex(aNumber, 0) 265 | 266 | 267 | # __pragma__ ('endif') 268 | 269 | 270 | class __Terminal__: 271 | """ 272 | Printing to either the console or to html happens async, but is blocked by calling window.prompt. 273 | So while all input and print statements are encountered in normal order, the print's exit immediately without yet having actually printed 274 | This means the next input takes control, blocking actual printing and so on indefinitely 275 | The effect is that everything's only printed after all inputs are done 276 | To prevent that, what's needed is to only execute the next window.prompt after actual printing has been done 277 | Since we've no way to find out when that is, a timeout is used. 278 | """ 279 | 280 | def __init__(self): 281 | self.buffer = "" 282 | 283 | try: 284 | self.element = document.getElementById("__terminal__") 285 | except: 286 | self.element = None 287 | 288 | if self.element: 289 | self.element.style.overflowX = "auto" 290 | self.element.style.boxSizing = "border-box" 291 | self.element.style.padding = "5px" 292 | self.element.innerHTML = "_" 293 | 294 | # __pragma__ ('kwargs') 295 | 296 | def print(self, *args, sep=" ", end="\n"): 297 | self.buffer = "{}{}{}".format(self.buffer, sep.join([str(arg) for arg in args]), end)[ 298 | -4096: 299 | ] 300 | 301 | if self.element: 302 | self.element.innerHTML = self.buffer.replace("\n", "
").replace(" ", " ") 303 | self.element.scrollTop = self.element.scrollHeight 304 | else: 305 | console.log(sep.join([str(arg) for arg in args])) 306 | 307 | def input(self, question): 308 | self.print("{}".format(question), end="") 309 | answer = window.prompt("\n".join(self.buffer.split("\n")[-8:])) 310 | self.print(answer) 311 | return answer 312 | 313 | # __pragma__ ('nokwargs') 314 | 315 | 316 | __terminal__ = __Terminal__() 317 | 318 | print = __terminal__.print 319 | input = __terminal__.input 320 | -------------------------------------------------------------------------------- /panel_sketch/sketch_compiler/assets/js/transcrypt/pyp5js.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "file": "pyp5js.js", 4 | "sources": [ 5 | "pyp5js.py" 6 | ], 7 | "mappings": "AAAA;AAAA;AAAA;AAAA;AAEA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA;AAEA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAGA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAKA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA;AAEA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA;AAEA;AAAA;AAEA;AACA;AACA;AAAA;AAGA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AAAA;AACA;AACA;AAAA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA;AAEA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AAAA;AACA;AACA;AAAA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AAAA;AACA;AACA;AAAA;AAAA;AAGA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAGA;AACA;AAEA;AAAA;AAGA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA;AAEA;AAAA;AAIA;AACA;AACA;AACA;AACA;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AAAA;AAGA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAKA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA;AACA;AAAA;AAGA;AAAA;AAGA;AAAA;AAGA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AAAA;AAGA;AAGA;AAQA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AAAA;AAAA;AAGA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAGA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA;AAEA;AAEA;AAEA;AACA;AACA;AACA;AAAA;AArsCA" 8 | } -------------------------------------------------------------------------------- /panel_sketch/sketch_compiler/assets/js/transcrypt/pyp5js.python_functions.js: -------------------------------------------------------------------------------- 1 | // Transcrypt'ed from Python, 2021-04-11 14:24:48 2 | import {AssertionError, AttributeError, BaseException, DeprecationWarning, Exception, IndexError, IterableError, KeyError, NotImplementedError, RuntimeWarning, StopIteration, UserWarning, ValueError, Warning, __JsIterator__, __PyIterator__, __Terminal__, __add__, __and__, __call__, __class__, __envir__, __eq__, __floordiv__, __ge__, __get__, __getcm__, __getitem__, __getslice__, __getsm__, __gt__, __i__, __iadd__, __iand__, __idiv__, __ijsmod__, __ilshift__, __imatmul__, __imod__, __imul__, __in__, __init__, __ior__, __ipow__, __irshift__, __isub__, __ixor__, __jsUsePyNext__, __jsmod__, __k__, __kwargtrans__, __le__, __lshift__, __lt__, __matmul__, __mergefields__, __mergekwargtrans__, __mod__, __mul__, __ne__, __neg__, __nest__, __or__, __pow__, __pragma__, __proxy__, __pyUseJsNext__, __rshift__, __setitem__, __setproperty__, __setslice__, __sort__, __specialattrib__, __sub__, __super__, __t__, __terminal__, __truediv__, __withblock__, __xor__, abs, all, any, assert, bool, bytearray, bytes, callable, chr, copy, deepcopy, delattr, dict, dir, divmod, enumerate, filter, float, getattr, hasattr, input, int, isinstance, issubclass, len, list, map, max, min, object, ord, pow, print, property, py_TypeError, py_iter, py_metatype, py_next, py_reversed, py_typeof, range, repr, round, set, setattr, sorted, str, sum, tuple, zip} from './org.transcrypt.__runtime__.js'; 3 | var __name__ = 'pyp5js.python_functions'; 4 | export var PythonFunctions = __class__ ('PythonFunctions', [object], { 5 | __module__: __name__, 6 | }); 7 | setattr (PythonFunctions, 'map', map); 8 | setattr (PythonFunctions, 'filter', filter); 9 | setattr (PythonFunctions, 'set', set); 10 | 11 | //# sourceMappingURL=pyp5js.python_functions.map -------------------------------------------------------------------------------- /panel_sketch/sketch_compiler/assets/js/transcrypt/pyp5js.python_functions.map: -------------------------------------------------------------------------------- 1 | { 2 | "version": 3, 3 | "file": "pyp5js.python_functions.js", 4 | "sources": [ 5 | "pyp5js.python_functions.py" 6 | ], 7 | "mappings": "AAAA;AAIA;AAJA;AAAA;AAAA;AAAA;AAEA;AACA;AACA;AAAA" 8 | } -------------------------------------------------------------------------------- /panel_sketch/sketch_compiler/assets/js/transcrypt/pyp5js.python_functions.py: -------------------------------------------------------------------------------- 1 | class PythonFunctions: 2 | pass 3 | 4 | 5 | setattr(PythonFunctions, "map", map) 6 | setattr(PythonFunctions, "filter", filter) 7 | setattr(PythonFunctions, "set", set) 8 | -------------------------------------------------------------------------------- /panel_sketch/sketch_compiler/template_pyodide_basic.js: -------------------------------------------------------------------------------- 1 | console.log("pyodide basic") 2 | let userCode = ` 3 | {{sketch_object}} 4 | `; 5 | 6 | function runCode() { 7 | let code = userCode 8 | 9 | if (window.instance) { 10 | window.instance.canvas.remove(); 11 | } 12 | 13 | console.log("Python execution output:"); 14 | pyodide.runPython(code); 15 | } 16 | 17 | languagePluginLoader.then(() => { 18 | pyodide.runPython(` 19 | import io, code, sys 20 | from js import pyodide, window, document 21 | print(sys.version) 22 | `) 23 | 24 | window.runSketchCode = (code) => { 25 | userCode = code; 26 | runCode(); 27 | } 28 | 29 | runCode(); 30 | }); -------------------------------------------------------------------------------- /panel_sketch/sketch_compiler/template_pyodide_pyp5js.js: -------------------------------------------------------------------------------- 1 | console.log("pyodide pyp5js") 2 | let wrapper_content = ` 3 | class PythonFunctions: pass 4 | 5 | setattr(PythonFunctions, 'map', map) 6 | setattr(PythonFunctions, 'filter', filter) 7 | setattr(PythonFunctions, 'set', set) 8 | 9 | 10 | _P5_INSTANCE = None 11 | 12 | _CTX_MIDDLE = None 13 | _DEFAULT_FILL = None 14 | _DEFAULT_LEADMULT = None 15 | _DEFAULT_STROKE = None 16 | _DEFAULT_TEXT_FILL = None 17 | 18 | ADD = None 19 | ALT = None 20 | ARROW = None 21 | AUDIO = None 22 | AUTO = None 23 | AXES = None 24 | BACKSPACE = None 25 | BASELINE = None 26 | BEVEL = None 27 | BEZIER = None 28 | BLEND = None 29 | BLUR = None 30 | BOLD = None 31 | BOLDITALIC = None 32 | BOTTOM = None 33 | BURN = None 34 | CENTER = None 35 | CHORD = None 36 | CLAMP = None 37 | CLOSE = None 38 | CONTROL = None 39 | CORNER = None 40 | CORNERS = None 41 | CROSS = None 42 | CURVE = None 43 | DARKEST = None 44 | DEG_TO_RAD = None 45 | DEGREES = None 46 | DELETE = None 47 | DIFFERENCE = None 48 | DILATE = None 49 | DODGE = None 50 | DOWN_ARROW = None 51 | ENTER = None 52 | ERODE = None 53 | ESCAPE = None 54 | EXCLUSION = None 55 | FILL = None 56 | GRAY = None 57 | GRID = None 58 | HALF_PI = None 59 | HAND = None 60 | HARD_LIGHT = None 61 | HSB = None 62 | HSL = None 63 | IMAGE = None 64 | IMMEDIATE = None 65 | INVERT = None 66 | ITALIC = None 67 | LANDSCAPE = None 68 | LEFT = None 69 | LEFT_ARROW = None 70 | LIGHTEST = None 71 | LINE_LOOP = None 72 | LINE_STRIP = None 73 | LINEAR = None 74 | LINES = None 75 | MIRROR = None 76 | MITER = None 77 | MOVE = None 78 | MULTIPLY = None 79 | NEAREST = None 80 | NORMAL = None 81 | OPAQUE = None 82 | OPEN = None 83 | OPTION = None 84 | OVERLAY = None 85 | PI = None 86 | PIE = None 87 | POINTS = None 88 | PORTRAIT = None 89 | POSTERIZE = None 90 | PROJECT = None 91 | QUAD_STRIP = None 92 | QUADRATIC = None 93 | QUADS = None 94 | QUARTER_PI = None 95 | RAD_TO_DEG = None 96 | RADIANS = None 97 | RADIUS = None 98 | REPEAT = None 99 | REPLACE = None 100 | RETURN = None 101 | RGB = None 102 | RIGHT = None 103 | RIGHT_ARROW = None 104 | ROUND = None 105 | SCREEN = None 106 | SHIFT = None 107 | SOFT_LIGHT = None 108 | SQUARE = None 109 | STROKE = None 110 | SUBTRACT = None 111 | TAB = None 112 | TAU = None 113 | TEXT = None 114 | TEXTURE = None 115 | THRESHOLD = None 116 | TOP = None 117 | TRIANGLE_FAN = None 118 | TRIANGLE_STRIP = None 119 | TRIANGLES = None 120 | TWO_PI = None 121 | UP_ARROW = None 122 | VIDEO = None 123 | WAIT = None 124 | WEBGL = None 125 | P2D = None 126 | PI = None 127 | 128 | frameCount = None 129 | focused = None 130 | displayWidth = None 131 | displayHeight = None 132 | windowWidth = None 133 | windowHeight = None 134 | width = None 135 | height = None 136 | deviceOrientation = None 137 | accelerationX = None 138 | accelerationY = None 139 | accelerationZ = None 140 | pAccelerationX = None 141 | pAccelerationY = None 142 | pAccelerationZ = None 143 | rotationX = None 144 | rotationY = None 145 | rotationZ = None 146 | pRotationX = None 147 | pRotationY = None 148 | pRotationZ = None 149 | turnAxis = None 150 | keyIsPressed = None 151 | key = None 152 | keyCode = None 153 | mouseX = None 154 | mouseY = None 155 | pmouseX = None 156 | pmouseY = None 157 | winMouseX = None 158 | winMouseY = None 159 | pwinMouseX = None 160 | pwinMouseY = None 161 | mouseButton = None 162 | mouseIsPressed = None 163 | touches = None 164 | pixels = None 165 | 166 | 167 | def alpha(*args): 168 | return _P5_INSTANCE.alpha(*args) 169 | 170 | def blue(*args): 171 | return _P5_INSTANCE.blue(*args) 172 | 173 | def brightness(*args): 174 | return _P5_INSTANCE.brightness(*args) 175 | 176 | def color(*args): 177 | return _P5_INSTANCE.color(*args) 178 | 179 | def green(*args): 180 | return _P5_INSTANCE.green(*args) 181 | 182 | def hue(*args): 183 | return _P5_INSTANCE.hue(*args) 184 | 185 | def lerpColor(*args): 186 | return _P5_INSTANCE.lerpColor(*args) 187 | 188 | def lightness(*args): 189 | return _P5_INSTANCE.lightness(*args) 190 | 191 | def red(*args): 192 | return _P5_INSTANCE.red(*args) 193 | 194 | def saturation(*args): 195 | return _P5_INSTANCE.saturation(*args) 196 | 197 | def background(*args): 198 | return _P5_INSTANCE.background(*args) 199 | 200 | def clear(*args): 201 | p5_clear = _P5_INSTANCE.clear(*args) 202 | return p5_clear 203 | 204 | def erase(*args): 205 | return _P5_INSTANCE.erase(*args) 206 | 207 | def noErase(*args): 208 | return _P5_INSTANCE.noErase(*args) 209 | 210 | def colorMode(*args): 211 | return _P5_INSTANCE.colorMode(*args) 212 | 213 | def fill(*args): 214 | return _P5_INSTANCE.fill(*args) 215 | 216 | def noFill(*args): 217 | return _P5_INSTANCE.noFill(*args) 218 | 219 | def noStroke(*args): 220 | return _P5_INSTANCE.noStroke(*args) 221 | 222 | def stroke(*args): 223 | return _P5_INSTANCE.stroke(*args) 224 | 225 | def arc(*args): 226 | return _P5_INSTANCE.arc(*args) 227 | 228 | def ellipse(*args): 229 | return _P5_INSTANCE.ellipse(*args) 230 | 231 | def circle(*args): 232 | return _P5_INSTANCE.circle(*args) 233 | 234 | def line(*args): 235 | return _P5_INSTANCE.line(*args) 236 | 237 | def point(*args): 238 | return _P5_INSTANCE.point(*args) 239 | 240 | def quad(*args): 241 | return _P5_INSTANCE.quad(*args) 242 | 243 | def rect(*args): 244 | return _P5_INSTANCE.rect(*args) 245 | 246 | def square(*args): 247 | return _P5_INSTANCE.square(*args) 248 | 249 | def triangle(*args): 250 | return _P5_INSTANCE.triangle(*args) 251 | 252 | def plane(*args): 253 | return _P5_INSTANCE.plane(*args) 254 | 255 | def box(*args): 256 | return _P5_INSTANCE.box(*args) 257 | 258 | def sphere(*args): 259 | return _P5_INSTANCE.sphere(*args) 260 | 261 | def cylinder(*args): 262 | return _P5_INSTANCE.cylinder(*args) 263 | 264 | def cone(*args): 265 | return _P5_INSTANCE.cone(*args) 266 | 267 | def ellipsoid(*args): 268 | return _P5_INSTANCE.ellipsoid(*args) 269 | 270 | def torus(*args): 271 | return _P5_INSTANCE.torus(*args) 272 | 273 | def loadModel(*args): 274 | return _P5_INSTANCE.loadModel(*args) 275 | 276 | def model(*args): 277 | return _P5_INSTANCE.model(*args) 278 | 279 | def ellipseMode(*args): 280 | return _P5_INSTANCE.ellipseMode(*args) 281 | 282 | def noSmooth(*args): 283 | return _P5_INSTANCE.noSmooth(*args) 284 | 285 | def rectMode(*args): 286 | return _P5_INSTANCE.rectMode(*args) 287 | 288 | def smooth(*args): 289 | return _P5_INSTANCE.smooth(*args) 290 | 291 | def strokeCap(*args): 292 | return _P5_INSTANCE.strokeCap(*args) 293 | 294 | def strokeJoin(*args): 295 | return _P5_INSTANCE.strokeJoin(*args) 296 | 297 | def strokeWeight(*args): 298 | return _P5_INSTANCE.strokeWeight(*args) 299 | 300 | def bezier(*args): 301 | return _P5_INSTANCE.bezier(*args) 302 | 303 | def bezierDetail(*args): 304 | return _P5_INSTANCE.bezierDetail(*args) 305 | 306 | def bezierPoint(*args): 307 | return _P5_INSTANCE.bezierPoint(*args) 308 | 309 | def bezierTangent(*args): 310 | return _P5_INSTANCE.bezierTangent(*args) 311 | 312 | def curve(*args): 313 | return _P5_INSTANCE.curve(*args) 314 | 315 | def curveDetail(*args): 316 | return _P5_INSTANCE.curveDetail(*args) 317 | 318 | def curveTightness(*args): 319 | return _P5_INSTANCE.curveTightness(*args) 320 | 321 | def curvePoint(*args): 322 | return _P5_INSTANCE.curvePoint(*args) 323 | 324 | def curveTangent(*args): 325 | return _P5_INSTANCE.curveTangent(*args) 326 | 327 | def beginContour(*args): 328 | return _P5_INSTANCE.beginContour(*args) 329 | 330 | def beginShape(*args): 331 | return _P5_INSTANCE.beginShape(*args) 332 | 333 | def bezierVertex(*args): 334 | return _P5_INSTANCE.bezierVertex(*args) 335 | 336 | def curveVertex(*args): 337 | return _P5_INSTANCE.curveVertex(*args) 338 | 339 | def endContour(*args): 340 | return _P5_INSTANCE.endContour(*args) 341 | 342 | def endShape(*args): 343 | return _P5_INSTANCE.endShape(*args) 344 | 345 | def quadraticVertex(*args): 346 | return _P5_INSTANCE.quadraticVertex(*args) 347 | 348 | def vertex(*args): 349 | return _P5_INSTANCE.vertex(*args) 350 | 351 | def cursor(*args): 352 | return _P5_INSTANCE.cursor(*args) 353 | 354 | def frameRate(*args): 355 | return _P5_INSTANCE.frameRate(*args) 356 | 357 | def noCursor(*args): 358 | return _P5_INSTANCE.noCursor(*args) 359 | 360 | def fullscreen(*args): 361 | return _P5_INSTANCE.fullscreen(*args) 362 | 363 | def pixelDensity(*args): 364 | return _P5_INSTANCE.pixelDensity(*args) 365 | 366 | def displayDensity(*args): 367 | return _P5_INSTANCE.displayDensity(*args) 368 | 369 | def getURL(*args): 370 | return _P5_INSTANCE.getURL(*args) 371 | 372 | def getURLPath(*args): 373 | return _P5_INSTANCE.getURLPath(*args) 374 | 375 | def getURLParams(*args): 376 | return _P5_INSTANCE.getURLParams(*args) 377 | 378 | def preload(*args): 379 | return _P5_INSTANCE.preload(*args) 380 | 381 | def remove(*args): 382 | return _P5_INSTANCE.remove(*args) 383 | 384 | def noLoop(*args): 385 | return _P5_INSTANCE.noLoop(*args) 386 | 387 | def loop(*args): 388 | return _P5_INSTANCE.loop(*args) 389 | 390 | def push(*args): 391 | return _P5_INSTANCE.push(*args) 392 | 393 | def redraw(*args): 394 | return _P5_INSTANCE.redraw(*args) 395 | 396 | def resizeCanvas(*args): 397 | return _P5_INSTANCE.resizeCanvas(*args) 398 | 399 | def noCanvas(*args): 400 | return _P5_INSTANCE.noCanvas(*args) 401 | 402 | def createGraphics(*args): 403 | return _P5_INSTANCE.createGraphics(*args) 404 | 405 | def blendMode(*args): 406 | return _P5_INSTANCE.blendMode(*args) 407 | 408 | def setAttributes(*args): 409 | return _P5_INSTANCE.setAttributes(*args) 410 | 411 | def applyMatrix(*args): 412 | return _P5_INSTANCE.applyMatrix(*args) 413 | 414 | def resetMatrix(*args): 415 | return _P5_INSTANCE.resetMatrix(*args) 416 | 417 | def rotate(*args): 418 | return _P5_INSTANCE.rotate(*args) 419 | 420 | def rotateX(*args): 421 | return _P5_INSTANCE.rotateX(*args) 422 | 423 | def rotateY(*args): 424 | return _P5_INSTANCE.rotateY(*args) 425 | 426 | def rotateZ(*args): 427 | return _P5_INSTANCE.rotateZ(*args) 428 | 429 | def scale(*args): 430 | return _P5_INSTANCE.scale(*args) 431 | 432 | def shearX(*args): 433 | return _P5_INSTANCE.shearX(*args) 434 | 435 | def shearY(*args): 436 | return _P5_INSTANCE.shearY(*args) 437 | 438 | def translate(*args): 439 | return _P5_INSTANCE.translate(*args) 440 | 441 | def createStringDict(*args): 442 | return _P5_INSTANCE.createStringDict(*args) 443 | 444 | def createNumberDict(*args): 445 | return _P5_INSTANCE.createNumberDict(*args) 446 | 447 | def append(*args): 448 | return _P5_INSTANCE.append(*args) 449 | 450 | def arrayCopy(*args): 451 | return _P5_INSTANCE.arrayCopy(*args) 452 | 453 | def concat(*args): 454 | return _P5_INSTANCE.concat(*args) 455 | 456 | def reverse(*args): 457 | return _P5_INSTANCE.reverse(*args) 458 | 459 | def shorten(*args): 460 | return _P5_INSTANCE.shorten(*args) 461 | 462 | def shuffle(*args): 463 | return _P5_INSTANCE.shuffle(*args) 464 | 465 | def sort(*args): 466 | return _P5_INSTANCE.sort(*args) 467 | 468 | def splice(*args): 469 | return _P5_INSTANCE.splice(*args) 470 | 471 | def subset(*args): 472 | return _P5_INSTANCE.subset(*args) 473 | 474 | def float(*args): 475 | return _P5_INSTANCE.float(*args) 476 | 477 | def int(*args): 478 | return _P5_INSTANCE.int(*args) 479 | 480 | def str(*args): 481 | return _P5_INSTANCE.str(*args) 482 | 483 | def boolean(*args): 484 | return _P5_INSTANCE.boolean(*args) 485 | 486 | def byte(*args): 487 | return _P5_INSTANCE.byte(*args) 488 | 489 | def char(*args): 490 | return _P5_INSTANCE.char(*args) 491 | 492 | def unchar(*args): 493 | return _P5_INSTANCE.unchar(*args) 494 | 495 | def hex(*args): 496 | return _P5_INSTANCE.hex(*args) 497 | 498 | def unhex(*args): 499 | return _P5_INSTANCE.unhex(*args) 500 | 501 | def join(*args): 502 | return _P5_INSTANCE.join(*args) 503 | 504 | def match(*args): 505 | return _P5_INSTANCE.match(*args) 506 | 507 | def matchAll(*args): 508 | return _P5_INSTANCE.matchAll(*args) 509 | 510 | def nf(*args): 511 | return _P5_INSTANCE.nf(*args) 512 | 513 | def nfc(*args): 514 | return _P5_INSTANCE.nfc(*args) 515 | 516 | def nfp(*args): 517 | return _P5_INSTANCE.nfp(*args) 518 | 519 | def nfs(*args): 520 | return _P5_INSTANCE.nfs(*args) 521 | 522 | def split(*args): 523 | return _P5_INSTANCE.split(*args) 524 | 525 | def splitTokens(*args): 526 | return _P5_INSTANCE.splitTokens(*args) 527 | 528 | def trim(*args): 529 | return _P5_INSTANCE.trim(*args) 530 | 531 | def setMoveThreshold(*args): 532 | return _P5_INSTANCE.setMoveThreshold(*args) 533 | 534 | def setShakeThreshold(*args): 535 | return _P5_INSTANCE.setShakeThreshold(*args) 536 | 537 | def keyIsDown(*args): 538 | return _P5_INSTANCE.keyIsDown(*args) 539 | 540 | def createImage(*args): 541 | return _P5_INSTANCE.createImage(*args) 542 | 543 | def saveCanvas(*args): 544 | return _P5_INSTANCE.saveCanvas(*args) 545 | 546 | def saveFrames(*args): 547 | return _P5_INSTANCE.saveFrames(*args) 548 | 549 | def loadImage(*args): 550 | return _P5_INSTANCE.loadImage(*args) 551 | 552 | def image(*args): 553 | return _P5_INSTANCE.image(*args) 554 | 555 | def tint(*args): 556 | return _P5_INSTANCE.tint(*args) 557 | 558 | def noTint(*args): 559 | return _P5_INSTANCE.noTint(*args) 560 | 561 | def imageMode(*args): 562 | return _P5_INSTANCE.imageMode(*args) 563 | 564 | def blend(*args): 565 | return _P5_INSTANCE.blend(*args) 566 | 567 | def copy(*args): 568 | return _P5_INSTANCE.copy(*args) 569 | 570 | def filter(*args): 571 | if len(args) > 1 and (args[0] is None or callable(args[0])): 572 | return PythonFunctions.filter(*args) 573 | else: 574 | return _P5_INSTANCE.filter(*args) 575 | 576 | def get(*args): 577 | return _P5_INSTANCE.get(*args) 578 | 579 | def loadPixels(*args): 580 | return _P5_INSTANCE.loadPixels(*args) 581 | 582 | def set(*args): 583 | if len(args) <= 1: 584 | return PythonFunctions.set(*args) 585 | else: 586 | return _P5_INSTANCE.set(*args) 587 | 588 | def updatePixels(*args): 589 | return _P5_INSTANCE.updatePixels(*args) 590 | 591 | def loadJSON(*args): 592 | return _P5_INSTANCE.loadJSON(*args) 593 | 594 | def loadStrings(*args): 595 | return _P5_INSTANCE.loadStrings(*args) 596 | 597 | def loadTable(*args): 598 | return _P5_INSTANCE.loadTable(*args) 599 | 600 | def loadXML(*args): 601 | return _P5_INSTANCE.loadXML(*args) 602 | 603 | def loadBytes(*args): 604 | return _P5_INSTANCE.loadBytes(*args) 605 | 606 | def httpGet(*args): 607 | return _P5_INSTANCE.httpGet(*args) 608 | 609 | def httpPost(*args): 610 | return _P5_INSTANCE.httpPost(*args) 611 | 612 | def httpDo(*args): 613 | return _P5_INSTANCE.httpDo(*args) 614 | 615 | def createWriter(*args): 616 | return _P5_INSTANCE.createWriter(*args) 617 | 618 | def save(*args): 619 | return _P5_INSTANCE.save(*args) 620 | 621 | def saveJSON(*args): 622 | return _P5_INSTANCE.saveJSON(*args) 623 | 624 | def saveStrings(*args): 625 | return _P5_INSTANCE.saveStrings(*args) 626 | 627 | def saveTable(*args): 628 | return _P5_INSTANCE.saveTable(*args) 629 | 630 | def day(*args): 631 | return _P5_INSTANCE.day(*args) 632 | 633 | def hour(*args): 634 | return _P5_INSTANCE.hour(*args) 635 | 636 | def minute(*args): 637 | return _P5_INSTANCE.minute(*args) 638 | 639 | def millis(*args): 640 | return _P5_INSTANCE.millis(*args) 641 | 642 | def month(*args): 643 | return _P5_INSTANCE.month(*args) 644 | 645 | def second(*args): 646 | return _P5_INSTANCE.second(*args) 647 | 648 | def year(*args): 649 | return _P5_INSTANCE.year(*args) 650 | 651 | def createVector(*args): 652 | return _P5_INSTANCE.createVector(*args) 653 | 654 | def abs(*args): 655 | return _P5_INSTANCE.abs(*args) 656 | 657 | def ceil(*args): 658 | return _P5_INSTANCE.ceil(*args) 659 | 660 | def constrain(*args): 661 | return _P5_INSTANCE.constrain(*args) 662 | 663 | def dist(*args): 664 | return _P5_INSTANCE.dist(*args) 665 | 666 | def exp(*args): 667 | return _P5_INSTANCE.exp(*args) 668 | 669 | def floor(*args): 670 | return _P5_INSTANCE.floor(*args) 671 | 672 | def lerp(*args): 673 | return _P5_INSTANCE.lerp(*args) 674 | 675 | def log(*args): 676 | return _P5_INSTANCE.log(*args) 677 | 678 | def mag(*args): 679 | return _P5_INSTANCE.mag(*args) 680 | 681 | def map(*args): 682 | if len(args) > 1 and callable(args[0]): 683 | return PythonFunctions.map(*args) 684 | else: 685 | return _P5_INSTANCE.map(*args) 686 | 687 | def max(*args): 688 | return _P5_INSTANCE.max(*args) 689 | 690 | def min(*args): 691 | return _P5_INSTANCE.min(*args) 692 | 693 | def norm(*args): 694 | return _P5_INSTANCE.norm(*args) 695 | 696 | def pow(*args): 697 | return _P5_INSTANCE.pow(*args) 698 | 699 | def round(*args): 700 | return _P5_INSTANCE.round(*args) 701 | 702 | def sq(*args): 703 | return _P5_INSTANCE.sq(*args) 704 | 705 | def sqrt(*args): 706 | return _P5_INSTANCE.sqrt(*args) 707 | 708 | def noise(*args): 709 | return _P5_INSTANCE.noise(*args) 710 | 711 | def noiseDetail(*args): 712 | return _P5_INSTANCE.noiseDetail(*args) 713 | 714 | def noiseSeed(*args): 715 | return _P5_INSTANCE.noiseSeed(*args) 716 | 717 | def randomSeed(*args): 718 | return _P5_INSTANCE.randomSeed(*args) 719 | 720 | def random(*args): 721 | return _P5_INSTANCE.random(*args) 722 | 723 | def randomGaussian(*args): 724 | return _P5_INSTANCE.randomGaussian(*args) 725 | 726 | def acos(*args): 727 | return _P5_INSTANCE.acos(*args) 728 | 729 | def asin(*args): 730 | return _P5_INSTANCE.asin(*args) 731 | 732 | def atan(*args): 733 | return _P5_INSTANCE.atan(*args) 734 | 735 | def atan2(*args): 736 | return _P5_INSTANCE.atan2(*args) 737 | 738 | def cos(*args): 739 | return _P5_INSTANCE.cos(*args) 740 | 741 | def sin(*args): 742 | return _P5_INSTANCE.sin(*args) 743 | 744 | def tan(*args): 745 | return _P5_INSTANCE.tan(*args) 746 | 747 | def degrees(*args): 748 | return _P5_INSTANCE.degrees(*args) 749 | 750 | def radians(*args): 751 | return _P5_INSTANCE.radians(*args) 752 | 753 | def angleMode(*args): 754 | return _P5_INSTANCE.angleMode(*args) 755 | 756 | def textAlign(*args): 757 | return _P5_INSTANCE.textAlign(*args) 758 | 759 | def textLeading(*args): 760 | return _P5_INSTANCE.textLeading(*args) 761 | 762 | def textSize(*args): 763 | return _P5_INSTANCE.textSize(*args) 764 | 765 | def textStyle(*args): 766 | return _P5_INSTANCE.textStyle(*args) 767 | 768 | def textWidth(*args): 769 | return _P5_INSTANCE.textWidth(*args) 770 | 771 | def textAscent(*args): 772 | return _P5_INSTANCE.textAscent(*args) 773 | 774 | def textDescent(*args): 775 | return _P5_INSTANCE.textDescent(*args) 776 | 777 | def loadFont(*args): 778 | return _P5_INSTANCE.loadFont(*args) 779 | 780 | def text(*args): 781 | return _P5_INSTANCE.text(*args) 782 | 783 | def textFont(*args): 784 | return _P5_INSTANCE.textFont(*args) 785 | 786 | def orbitControl(*args): 787 | return _P5_INSTANCE.orbitControl(*args) 788 | 789 | def debugMode(*args): 790 | return _P5_INSTANCE.debugMode(*args) 791 | 792 | def noDebugMode(*args): 793 | return _P5_INSTANCE.noDebugMode(*args) 794 | 795 | def ambientLight(*args): 796 | return _P5_INSTANCE.ambientLight(*args) 797 | 798 | def directionalLight(*args): 799 | return _P5_INSTANCE.directionalLight(*args) 800 | 801 | def pointLight(*args): 802 | return _P5_INSTANCE.pointLight(*args) 803 | 804 | def lights(*args): 805 | return _P5_INSTANCE.lights(*args) 806 | 807 | def loadShader(*args): 808 | return _P5_INSTANCE.loadShader(*args) 809 | 810 | def createShader(*args): 811 | return _P5_INSTANCE.createShader(*args) 812 | 813 | def shader(*args): 814 | return _P5_INSTANCE.shader(*args) 815 | 816 | def resetShader(*args): 817 | return _P5_INSTANCE.resetShader(*args) 818 | 819 | def normalMaterial(*args): 820 | return _P5_INSTANCE.normalMaterial(*args) 821 | 822 | def texture(*args): 823 | return _P5_INSTANCE.texture(*args) 824 | 825 | def textureMode(*args): 826 | return _P5_INSTANCE.textureMode(*args) 827 | 828 | def textureWrap(*args): 829 | return _P5_INSTANCE.textureWrap(*args) 830 | 831 | def ambientMaterial(*args): 832 | return _P5_INSTANCE.ambientMaterial(*args) 833 | 834 | def specularMaterial(*args): 835 | return _P5_INSTANCE.specularMaterial(*args) 836 | 837 | def shininess(*args): 838 | return _P5_INSTANCE.shininess(*args) 839 | 840 | def camera(*args): 841 | return _P5_INSTANCE.camera(*args) 842 | 843 | def perspective(*args): 844 | return _P5_INSTANCE.perspective(*args) 845 | 846 | def ortho(*args): 847 | return _P5_INSTANCE.ortho(*args) 848 | 849 | def createCamera(*args): 850 | return _P5_INSTANCE.createCamera(*args) 851 | 852 | def setCamera(*args): 853 | return _P5_INSTANCE.setCamera(*args) 854 | 855 | def select(*args): 856 | return _P5_INSTANCE.select(*args) 857 | 858 | def selectAll(*args): 859 | return _P5_INSTANCE.selectAll(*args) 860 | 861 | def removeElements(*args): 862 | return _P5_INSTANCE.removeElements(*args) 863 | 864 | def changed(*args): 865 | return _P5_INSTANCE.changed(*args) 866 | 867 | def input(*args): 868 | return _P5_INSTANCE.input(*args) 869 | 870 | def createDiv(*args): 871 | return _P5_INSTANCE.createDiv(*args) 872 | 873 | def createP(*args): 874 | return _P5_INSTANCE.createP(*args) 875 | 876 | def createSpan(*args): 877 | return _P5_INSTANCE.createSpan(*args) 878 | 879 | def createImg(*args): 880 | return _P5_INSTANCE.createImg(*args) 881 | 882 | def createA(*args): 883 | return _P5_INSTANCE.createA(*args) 884 | 885 | def createSlider(*args): 886 | return _P5_INSTANCE.createSlider(*args) 887 | 888 | def createButton(*args): 889 | return _P5_INSTANCE.createButton(*args) 890 | 891 | def createCheckbox(*args): 892 | return _P5_INSTANCE.createCheckbox(*args) 893 | 894 | def createSelect(*args): 895 | return _P5_INSTANCE.createSelect(*args) 896 | 897 | def createRadio(*args): 898 | return _P5_INSTANCE.createRadio(*args) 899 | 900 | def createColorPicker(*args): 901 | return _P5_INSTANCE.createColorPicker(*args) 902 | 903 | def createInput(*args): 904 | return _P5_INSTANCE.createInput(*args) 905 | 906 | def createFileInput(*args): 907 | return _P5_INSTANCE.createFileInput(*args) 908 | 909 | def createVideo(*args): 910 | return _P5_INSTANCE.createVideo(*args) 911 | 912 | def createAudio(*args): 913 | return _P5_INSTANCE.createAudio(*args) 914 | 915 | def createCapture(*args): 916 | return _P5_INSTANCE.createCapture(*args) 917 | 918 | def createElement(*args): 919 | return _P5_INSTANCE.createElement(*args) 920 | 921 | def createCanvas(*args): 922 | canvas = _P5_INSTANCE.createCanvas(*args) 923 | 924 | global width, height 925 | width = _P5_INSTANCE.width 926 | height = _P5_INSTANCE.height 927 | 928 | return canvas 929 | 930 | 931 | def pop(*args): 932 | p5_pop = _P5_INSTANCE.pop(*args) 933 | return p5_pop 934 | 935 | 936 | # Processing Python or Java mode compatibility aliases 937 | size = createCanvas 938 | popMatrix = pop 939 | popStyle = pop 940 | pushMatrix = push 941 | pushStyle = push 942 | 943 | def pre_draw(p5_instance, draw_func): 944 | """ 945 | We need to run this before the actual draw to insert and update p5 env variables 946 | """ 947 | global _CTX_MIDDLE, _DEFAULT_FILL, _DEFAULT_LEADMULT, _DEFAULT_STROKE, _DEFAULT_TEXT_FILL 948 | 949 | global ADD, ALT, ARROW, AUTO, AUDIO, AXES, BACKSPACE, BASELINE, BEVEL, BEZIER, BLEND, BLUR, BOLD, BOLDITALIC 950 | global BOTTOM, BURN, CENTER, CHORD, CLAMP, CLOSE, CONTROL, CORNER, CORNERS, CROSS, CURVE, DARKEST 951 | global DEG_TO_RAD, DEGREES, DELETE, DIFFERENCE, DILATE, DODGE, DOWN_ARROW, ENTER, ERODE, ESCAPE, EXCLUSION 952 | global FILL, GRAY, GRID, HALF_PI, HAND, HARD_LIGHT, HSB, HSL, IMAGE, IMMEDIATE, INVERT, ITALIC, LANDSCAPE 953 | global LEFT, LEFT_ARROW, LIGHTEST, LINE_LOOP, LINE_STRIP, LINEAR, LINES, MIRROR, MITER, MOVE, MULTIPLY, NEAREST 954 | global NORMAL, OPAQUE, OPEN, OPTION, OVERLAY, P2D, PI, PIE, POINTS, PORTRAIT, POSTERIZE, PROJECT, QUAD_STRIP, QUADRATIC 955 | global QUADS, QUARTER_PI, RAD_TO_DEG, RADIANS, RADIUS, REPEAT, REPLACE, RETURN, RGB, RIGHT, RIGHT_ARROW 956 | global ROUND, SCREEN, SHIFT, SOFT_LIGHT, SQUARE, STROKE, SUBTRACT, TAB, TAU, TEXT, TEXTURE, THRESHOLD, TOP 957 | global TRIANGLE_FAN, TRIANGLE_STRIP, TRIANGLES, TWO_PI, UP_ARROW, VIDEO, WAIT, WEBGL 958 | 959 | global frameCount, focused, displayWidth, displayHeight, windowWidth, windowHeight, width, height 960 | global deviceOrientation, accelerationX, accelerationY, accelerationZ 961 | global pAccelerationX, pAccelerationY, pAccelerationZ, rotationX, rotationY, rotationZ 962 | global pRotationX, pRotationY, pRotationZ, turnAxis, keyIsPressed, key, keyCode, mouseX, mouseY, pmouseX, pmouseY 963 | global winMouseX, winMouseY, pwinMouseX, pwinMouseY, mouseButton, mouseIsPressed, touches, pixels 964 | 965 | _CTX_MIDDLE = p5_instance._CTX_MIDDLE 966 | _DEFAULT_FILL = p5_instance._DEFAULT_FILL 967 | _DEFAULT_LEADMULT = p5_instance._DEFAULT_LEADMULT 968 | _DEFAULT_STROKE = p5_instance._DEFAULT_STROKE 969 | _DEFAULT_TEXT_FILL = p5_instance._DEFAULT_TEXT_FILL 970 | 971 | ADD = p5_instance.ADD 972 | ALT = p5_instance.ALT 973 | ARROW = p5_instance.ARROW 974 | AUDIO = p5_instance.AUDIO 975 | AUTO = p5_instance.AUTO 976 | AXES = p5_instance.AXES 977 | BACKSPACE = p5_instance.BACKSPACE 978 | BASELINE = p5_instance.BASELINE 979 | BEVEL = p5_instance.BEVEL 980 | BEZIER = p5_instance.BEZIER 981 | BLEND = p5_instance.BLEND 982 | BLUR = p5_instance.BLUR 983 | BOLD = p5_instance.BOLD 984 | BOLDITALIC = p5_instance.BOLDITALIC 985 | BOTTOM = p5_instance.BOTTOM 986 | BURN = p5_instance.BURN 987 | CENTER = p5_instance.CENTER 988 | CHORD = p5_instance.CHORD 989 | CLAMP = p5_instance.CLAMP 990 | CLOSE = p5_instance.CLOSE 991 | CONTROL = p5_instance.CONTROL 992 | CORNER = p5_instance.CORNER 993 | CORNERS = p5_instance.CORNERS 994 | CROSS = p5_instance.CROSS 995 | CURVE = p5_instance.CURVE 996 | DARKEST = p5_instance.DARKEST 997 | DEG_TO_RAD = p5_instance.DEG_TO_RAD 998 | DEGREES = p5_instance.DEGREES 999 | DELETE = p5_instance.DELETE 1000 | DIFFERENCE = p5_instance.DIFFERENCE 1001 | DILATE = p5_instance.DILATE 1002 | DODGE = p5_instance.DODGE 1003 | DOWN_ARROW = p5_instance.DOWN_ARROW 1004 | ENTER = p5_instance.ENTER 1005 | ERODE = p5_instance.ERODE 1006 | ESCAPE = p5_instance.ESCAPE 1007 | EXCLUSION = p5_instance.EXCLUSION 1008 | FILL = p5_instance.FILL 1009 | GRAY = p5_instance.GRAY 1010 | GRID = p5_instance.GRID 1011 | HALF_PI = p5_instance.HALF_PI 1012 | HAND = p5_instance.HAND 1013 | HARD_LIGHT = p5_instance.HARD_LIGHT 1014 | HSB = p5_instance.HSB 1015 | HSL = p5_instance.HSL 1016 | IMAGE = p5_instance.IMAGE 1017 | IMMEDIATE = p5_instance.IMMEDIATE 1018 | INVERT = p5_instance.INVERT 1019 | ITALIC = p5_instance.ITALIC 1020 | LANDSCAPE = p5_instance.LANDSCAPE 1021 | LEFT = p5_instance.LEFT 1022 | LEFT_ARROW = p5_instance.LEFT_ARROW 1023 | LIGHTEST = p5_instance.LIGHTEST 1024 | LINE_LOOP = p5_instance.LINE_LOOP 1025 | LINE_STRIP = p5_instance.LINE_STRIP 1026 | LINEAR = p5_instance.LINEAR 1027 | LINES = p5_instance.LINES 1028 | MIRROR = p5_instance.MIRROR 1029 | MITER = p5_instance.MITER 1030 | MOVE = p5_instance.MOVE 1031 | MULTIPLY = p5_instance.MULTIPLY 1032 | NEAREST = p5_instance.NEAREST 1033 | NORMAL = p5_instance.NORMAL 1034 | OPAQUE = p5_instance.OPAQUE 1035 | OPEN = p5_instance.OPEN 1036 | OPTION = p5_instance.OPTION 1037 | OVERLAY = p5_instance.OVERLAY 1038 | P2D = p5_instance.P2D 1039 | P3D = p5_instance.WEBGL 1040 | PI = p5_instance.PI 1041 | PIE = p5_instance.PIE 1042 | POINTS = p5_instance.POINTS 1043 | PORTRAIT = p5_instance.PORTRAIT 1044 | POSTERIZE = p5_instance.POSTERIZE 1045 | PROJECT = p5_instance.PROJECT 1046 | QUAD_STRIP = p5_instance.QUAD_STRIP 1047 | QUADRATIC = p5_instance.QUADRATIC 1048 | QUADS = p5_instance.QUADS 1049 | QUARTER_PI = p5_instance.QUARTER_PI 1050 | RAD_TO_DEG = p5_instance.RAD_TO_DEG 1051 | RADIANS = p5_instance.RADIANS 1052 | RADIUS = p5_instance.RADIUS 1053 | REPEAT = p5_instance.REPEAT 1054 | REPLACE = p5_instance.REPLACE 1055 | RETURN = p5_instance.RETURN 1056 | RGB = p5_instance.RGB 1057 | RIGHT = p5_instance.RIGHT 1058 | RIGHT_ARROW = p5_instance.RIGHT_ARROW 1059 | ROUND = p5_instance.ROUND 1060 | SCREEN = p5_instance.SCREEN 1061 | SHIFT = p5_instance.SHIFT 1062 | SOFT_LIGHT = p5_instance.SOFT_LIGHT 1063 | SQUARE = p5_instance.SQUARE 1064 | STROKE = p5_instance.STROKE 1065 | SUBTRACT = p5_instance.SUBTRACT 1066 | TAB = p5_instance.TAB 1067 | TAU = p5_instance.TAU 1068 | TEXT = p5_instance.TEXT 1069 | TEXTURE = p5_instance.TEXTURE 1070 | THRESHOLD = p5_instance.THRESHOLD 1071 | TOP = p5_instance.TOP 1072 | TRIANGLE_FAN = p5_instance.TRIANGLE_FAN 1073 | TRIANGLE_STRIP = p5_instance.TRIANGLE_STRIP 1074 | TRIANGLES = p5_instance.TRIANGLES 1075 | TWO_PI = p5_instance.TWO_PI 1076 | UP_ARROW = p5_instance.UP_ARROW 1077 | VIDEO = p5_instance.VIDEO 1078 | WAIT = p5_instance.WAIT 1079 | WEBGL = p5_instance.WEBGL 1080 | 1081 | frameCount = p5_instance.frameCount 1082 | focused = p5_instance.focused 1083 | displayWidth = p5_instance.displayWidth 1084 | displayHeight = p5_instance.displayHeight 1085 | windowWidth = p5_instance.windowWidth 1086 | windowHeight = p5_instance.windowHeight 1087 | width = p5_instance.width 1088 | height = p5_instance.height 1089 | deviceOrientation = p5_instance.deviceOrientation 1090 | accelerationX = p5_instance.accelerationX 1091 | accelerationY = p5_instance.accelerationY 1092 | accelerationZ = p5_instance.accelerationZ 1093 | pAccelerationX = p5_instance.pAccelerationX 1094 | pAccelerationY = p5_instance.pAccelerationY 1095 | pAccelerationZ = p5_instance.pAccelerationZ 1096 | rotationX = p5_instance.rotationX 1097 | rotationY = p5_instance.rotationY 1098 | rotationZ = p5_instance.rotationZ 1099 | pRotationX = p5_instance.pRotationX 1100 | pRotationY = p5_instance.pRotationY 1101 | pRotationZ = p5_instance.pRotationZ 1102 | turnAxis = p5_instance.turnAxis 1103 | keyIsPressed = p5_instance.keyIsPressed 1104 | key = p5_instance.key 1105 | keyCode = p5_instance.keyCode 1106 | mouseX = p5_instance.mouseX 1107 | mouseY = p5_instance.mouseY 1108 | pmouseX = p5_instance.pmouseX 1109 | pmouseY = p5_instance.pmouseY 1110 | winMouseX = p5_instance.winMouseX 1111 | winMouseY = p5_instance.winMouseY 1112 | pwinMouseX = p5_instance.pwinMouseX 1113 | pwinMouseY = p5_instance.pwinMouseY 1114 | mouseButton = p5_instance.mouseButton 1115 | mouseIsPressed = p5_instance.mouseIsPressed 1116 | touches = p5_instance.touches 1117 | pixels = p5_instance.pixels 1118 | 1119 | return draw_func() 1120 | 1121 | 1122 | def global_p5_injection(p5_sketch): 1123 | """ 1124 | Injects the p5js's skecth instance as a global variable to setup and draw functions 1125 | """ 1126 | 1127 | def decorator(f): 1128 | def wrapper(): 1129 | global _P5_INSTANCE 1130 | _P5_INSTANCE = p5_sketch 1131 | return pre_draw(_P5_INSTANCE, f) 1132 | 1133 | 1134 | return wrapper 1135 | 1136 | 1137 | return decorator 1138 | 1139 | 1140 | def start_p5(setup_func, draw_func, event_functions): 1141 | """ 1142 | This is the entrypoint function. It accepts 2 parameters: 1143 | 1144 | - setup_func: a Python setup callable 1145 | - draw_func: a Python draw callable 1146 | - event_functions: a config dict for the event functions in the format: 1147 | {"eventFunctionName": python_event_function} 1148 | 1149 | This method gets the p5js's sketch instance and injects them 1150 | """ 1151 | 1152 | def sketch_setup(p5_sketch): 1153 | """ 1154 | Callback function called to configure new p5 instance 1155 | """ 1156 | p5_sketch.setup = global_p5_injection(p5_sketch)(setup_func) 1157 | p5_sketch.draw = global_p5_injection(p5_sketch)(draw_func) 1158 | 1159 | 1160 | window.instance = p5.new(sketch_setup, 'sketch-element') 1161 | 1162 | # inject event functions into p5 1163 | event_function_names = ( 1164 | "deviceMoved", "deviceTurned", "deviceShaken", "windowResized", 1165 | "keyPressed", "keyReleased", "keyTyped", 1166 | "mousePressed", "mouseReleased", "mouseClicked", "doubleClicked", 1167 | "mouseMoved", "mouseDragged", "mouseWheel", 1168 | "touchStarted", "touchMoved", "touchEnded" 1169 | ) 1170 | 1171 | for f_name in [f for f in event_function_names if event_functions.get(f, None)]: 1172 | func = event_functions[f_name] 1173 | event_func = global_p5_injection(instance)(func) 1174 | setattr(instance, f_name, event_func) 1175 | `; 1176 | 1177 | let placeholder = ` 1178 | def setup(): 1179 | pass 1180 | 1181 | def draw(): 1182 | pass 1183 | `; 1184 | 1185 | let userCode = ` 1186 | {{sketch_object}} 1187 | `; 1188 | 1189 | function runCode() { 1190 | let code = [ 1191 | placeholder, 1192 | userCode, 1193 | wrapper_content, 1194 | 'start_p5(setup, draw, {});', 1195 | ].join('\n'); 1196 | 1197 | if (window.instance) { 1198 | window.instance.canvas.remove(); 1199 | } 1200 | 1201 | console.log("Python execution output:"); 1202 | pyodide.runPython(code); 1203 | } 1204 | 1205 | languagePluginLoader.then(() => { 1206 | pyodide.runPython(` 1207 | import io, code, sys 1208 | from js import pyodide, p5, window, document 1209 | print(sys.version) 1210 | `) 1211 | 1212 | window.runSketchCode = (code) => { 1213 | userCode = code; 1214 | runCode(); 1215 | } 1216 | 1217 | runCode(); 1218 | }); -------------------------------------------------------------------------------- /panel_sketch/sketch_compiler/template_transcrypt_basic.py: -------------------------------------------------------------------------------- 1 | {{sketch_object}} -------------------------------------------------------------------------------- /panel_sketch/sketch_compiler/template_transcrypt_pyp5js.py: -------------------------------------------------------------------------------- 1 | from pyp5js import * 2 | 3 | {{sketch_object}} 4 | 5 | event_functions = {} 6 | try: 7 | event_functions["deviceMoved"]= deviceMoved 8 | except: 9 | pass 10 | try: 11 | event_functions["deviceTurned"]= deviceTurned 12 | except: 13 | pass 14 | try: 15 | event_functions["deviceShaken"]= deviceShaken 16 | except: 17 | pass 18 | try: 19 | event_functions["keyPressed"]= keyPressed 20 | except: 21 | pass 22 | try: 23 | event_functions["keyReleased"]= keyReleased 24 | except: 25 | pass 26 | try: 27 | event_functions["keyTyped"]= keyTyped 28 | except: 29 | pass 30 | try: 31 | event_functions["mouseMoved"]= mouseMoved 32 | except: 33 | pass 34 | try: 35 | event_functions["mouseDragged"]= mouseDragged 36 | except: 37 | pass 38 | try: 39 | event_functions["mousePressed"]= mousePressed 40 | except: 41 | pass 42 | try: 43 | event_functions["mouseReleased"]= mouseReleased 44 | except: 45 | pass 46 | try: 47 | event_functions["mouseClicked"]= mouseClicked 48 | except: 49 | pass 50 | try: 51 | event_functions["doubleClicked"]= doubleClicked 52 | except: 53 | pass 54 | try: 55 | event_functions["mouseWheel"]= mouseWheel 56 | except: 57 | pass 58 | try: 59 | event_functions["touchStarted"]= touchStarted 60 | except: 61 | pass 62 | try: 63 | event_functions["touchMoved"]= touchMoved 64 | except: 65 | pass 66 | try: 67 | event_functions["touchEnded"]= touchEnded 68 | except: 69 | pass 70 | try: 71 | event_functions["windowResized"]= windowResized 72 | except: 73 | pass 74 | 75 | 76 | def start_p5(setup_func, draw_func, event_functions): 77 | """ 78 | This is the entrypoint function. It accepts 2 parameters: 79 | - setup_func: a Python setup callable 80 | - draw_func: a Python draw callable 81 | - event_functions: a config dict for the event functions in the format: 82 | {"eventFunctionName": python_event_function} 83 | This method gets the p5js's sketch instance and injects them 84 | """ 85 | # Hack: For some reason it is needed 86 | sketchElement.innerText="" 87 | 88 | def sketch_setup(p5_sketch): 89 | p5_sketch.setup = global_p5_injection(p5_sketch)(setup_func) 90 | p5_sketch.draw = global_p5_injection(p5_sketch)(draw_func) 91 | 92 | 93 | instance = __new__(p5(sketch_setup, 'sketch-element')) 94 | 95 | # inject event functions into p5 96 | event_function_names = ( 97 | "deviceMoved", "deviceTurned", "deviceShaken", "windowResized", 98 | "keyPressed", "keyReleased", "keyTyped", 99 | "mousePressed", "mouseReleased", "mouseClicked", "doubleClicked", 100 | "mouseMoved", "mouseDragged", "mouseWheel", 101 | "touchStarted", "touchMoved", "touchEnded" 102 | ) 103 | 104 | for f_name in [f for f in event_function_names if event_functions.get(f, None)]: 105 | func = event_functions[f_name] 106 | event_func = global_p5_injection(instance)(func) 107 | setattr(instance, f_name, event_func) 108 | 109 | start_p5(setup, draw, event_functions) -------------------------------------------------------------------------------- /panel_sketch/sketch_editor.py: -------------------------------------------------------------------------------- 1 | """The SketchEditor enables editing the SketchBase and derived classes""" 2 | import datetime 3 | 4 | import panel as pn 5 | import param 6 | 7 | from .sketch_base import SketchBase 8 | 9 | EDITOR_HEIGHT = 600 10 | EDITOR_MARGIN = (20, 5, 10, 5) 11 | MAX_LOG_LINES = 50 12 | 13 | 14 | class SketchEditor(param.Parameterized): 15 | """The SketchEditor enables editing the SketchBase and derived classes""" 16 | 17 | compile = param.Action() 18 | 19 | view = param.Parameter() 20 | 21 | sketch = param.ClassSelector(class_=SketchBase, constant=True, precedence=-1) 22 | 23 | def __init__(self, **params): 24 | super().__init__(**params) 25 | 26 | self.compile = self._compile_sketch 27 | self._create_view() 28 | 29 | def _create_view(self): 30 | sketch: SketchBase = self.sketch 31 | build_button = pn.widgets.Button( 32 | name="▶", button_type="primary", margin=(10, 0, 10, 5), width=50, sizing_mode="fixed" 33 | ) 34 | 35 | self._python_editor = pn.widgets.Ace( 36 | name="🐍 PYTHON", 37 | language="python", 38 | height=EDITOR_HEIGHT, 39 | value=sketch.object, 40 | margin=EDITOR_MARGIN, 41 | ) 42 | 43 | # # pylint: disable=no-value-for-parameter,no-member 44 | @param.depends(code=sketch.param.object, watch=True) 45 | def _update_python_editor(code): 46 | self._python_editor.value = code 47 | 48 | self._html_editor = pn.widgets.Ace( 49 | name="🗎 HTML", 50 | language="html", 51 | height=EDITOR_HEIGHT, 52 | value=sketch.html, 53 | margin=EDITOR_MARGIN, 54 | ) 55 | 56 | @param.depends(code=sketch.param.html, watch=True) 57 | def _update_html_editor(code): 58 | self._html_editor.value = code 59 | 60 | self._css_editor = pn.widgets.Ace( 61 | name="🎨 CSS", 62 | language="css", 63 | height=EDITOR_HEIGHT, 64 | value=sketch.css, 65 | margin=EDITOR_MARGIN, 66 | ) 67 | 68 | @param.depends(code=sketch.param.css, watch=True) 69 | def _update_css_editor(code): 70 | self._css_editor.value = code 71 | 72 | self._javascript_editor = pn.widgets.Ace( 73 | name="☕ JS", 74 | language="javascript", 75 | readonly=True, 76 | height=EDITOR_HEIGHT, 77 | value=sketch.javascript, 78 | margin=EDITOR_MARGIN, 79 | ) 80 | 81 | @param.depends(code=sketch.param.javascript, watch=True) 82 | def _update_javascript_editor(code): 83 | self._javascript_editor.value = code 84 | 85 | self._log = pn.widgets.TextAreaInput( 86 | name="⚠️ Log", height=EDITOR_HEIGHT, margin=EDITOR_MARGIN, disabled=True 87 | ) 88 | 89 | build_button.on_click(self.compile) 90 | 91 | self.view = pn.Column( 92 | pn.Row(build_button), 93 | pn.Tabs( 94 | self._python_editor, 95 | self._html_editor, 96 | self._css_editor, 97 | self._javascript_editor, 98 | self._log, 99 | ), 100 | ) 101 | 102 | def _compile_sketch(self, _=None): 103 | sketch = self.sketch 104 | sketch.html = self._html_editor.value 105 | sketch.css = self._css_editor.value 106 | if sketch.object == self._python_editor.value: 107 | # Hack to force update 108 | sketch.object = self._python_editor.value + "\n" 109 | else: 110 | sketch.object = self._python_editor.value 111 | 112 | log_value = "\n".join(self._log.value.split("\n")[:MAX_LOG_LINES]) 113 | self._log.value = ( 114 | datetime.datetime.now().strftime("%H:%M:%S: ") + "Build" + "\n" + log_value 115 | ) 116 | -------------------------------------------------------------------------------- /panel_sketch/sketch_viewer.py: -------------------------------------------------------------------------------- 1 | """The SketchViewer makes it easy to View a Sketch""" 2 | import uuid 3 | from textwrap import dedent 4 | 5 | import panel as pn 6 | import param 7 | 8 | from .sketch_base import SketchBase 9 | 10 | LAYOUT_NONE = (None, None, None) 11 | 12 | 13 | class SketchViewer(param.Parameterized): 14 | """The SketchViewer makes it easy to View a Sketch""" 15 | 16 | sketch = param.ClassSelector(class_=SketchBase, constant=True, precedence=-1) 17 | 18 | view = param.Parameter(constant=True) 19 | 20 | def __init__(self, **params): 21 | super().__init__(**params) 22 | 23 | self._uuid = uuid.uuid4() 24 | self._create_view() 25 | 26 | self._update_html_pane() 27 | self._update_css_pane() 28 | self._update_js_args_pane() 29 | self._update_js_pane() 30 | 31 | def _create_view(self): 32 | self._html_pane = pn.pane.HTML(height=200, width=200) 33 | self._css_pane = pn.pane.HTML(width=0, height=0, margin=0, sizing_mode="fixed") 34 | self._js_args_pane = pn.pane.HTML(width=0, height=0, margin=0, sizing_mode="fixed") 35 | self._js_pane = pn.pane.HTML(width=0, height=0, margin=0, sizing_mode="fixed") 36 | with param.edit_constant(self): 37 | self.view = pn.Column( 38 | self._css_pane, self._html_pane, self._js_args_pane, self._js_pane 39 | ) 40 | 41 | def _to_unique(self, value): 42 | return value.replace("sketch-element", f"sketch-{self._uuid}") 43 | 44 | # pylint: disable=no-member 45 | @param.depends("sketch.html", watch=True) 46 | def _update_html_pane(self): 47 | html_unique = self._to_unique(self.sketch.html) 48 | self._html_pane.object = html_unique 49 | 50 | @param.depends("sketch.css", watch=True) 51 | def _update_css_pane(self): 52 | css_unique = self._to_unique(self.sketch.css) 53 | self._css_pane.object = "" 54 | 55 | @param.depends("sketch.args", watch=True) 56 | def _update_js_args_pane(self): 57 | javascript_args_unique = self._to_unique(f"""var args = {str(self.sketch.args)}""") 58 | self._js_args_pane.object = ( 59 | f'' 60 | ) 61 | 62 | @param.depends("sketch.loading", watch=True) 63 | def _signal_loading(self): 64 | print("signal_loading", self.sketch.loading) 65 | self.view.loading=self.sketch.loading 66 | 67 | @param.depends("sketch.javascript", watch=True) 68 | def _update_js_pane(self): 69 | self._update_layout() 70 | javascript_unique = self._to_unique(self.sketch.javascript) 71 | self._js_pane.object = f"""""" 72 | 73 | def _update_layout(self): 74 | width, height, sizing_mode = self._get_layout(self.sketch.object) 75 | if height: 76 | self._html_pane.height = height 77 | if width: 78 | self._html_pane.width = width 79 | if sizing_mode: 80 | self._html_pane.sizing_mode = sizing_mode 81 | 82 | @staticmethod 83 | def _get_layout(value: str): 84 | clean = dedent(value) 85 | index = clean.find("createCanvas(") # '...createCanvas(200, 200)\n\n background(160)' 86 | if index == -1: 87 | return LAYOUT_NONE 88 | 89 | clean = clean[index:-1].replace("createCanvas(", "") # '200, 200)\n\n background(160)' 90 | index = clean.find(")") 91 | clean = clean[0:index] # '200, 200 92 | args = clean.split(",") 93 | width = int(args[0]) 94 | height = int(args[1]) 95 | sizing_mode = "fixed" 96 | return width, height, sizing_mode 97 | -------------------------------------------------------------------------------- /panel_sketch/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "noImplicitAny": true, 4 | "noImplicitThis": true, 5 | "noImplicitReturns": true, 6 | "noUnusedLocals": true, 7 | "noUnusedParameters": true, 8 | "strictNullChecks": true, 9 | "strictBindCallApply": false, 10 | "strictFunctionTypes": false, 11 | "strictPropertyInitialization": false, 12 | "alwaysStrict": true, 13 | "noErrorTruncation": true, 14 | "noEmitOnError": false, 15 | "declaration": true, 16 | "sourceMap": true, 17 | "importHelpers": false, 18 | "experimentalDecorators": true, 19 | "module": "esnext", 20 | "moduleResolution": "node", 21 | "esModuleInterop": true, 22 | "resolveJsonModule": true, 23 | "skipLibCheck": true, 24 | "target": "ES2017", 25 | "lib": ["es2017", "dom", "dom.iterable"], 26 | "baseUrl": ".", 27 | "outDir": "./dist/lib", 28 | "paths": { 29 | "@bokehjs/*": [ 30 | "./node_modules/@bokeh/bokehjs/build/js/lib/*", 31 | "./node_modules/@bokeh/bokehjs/build/js/types/*" 32 | ] 33 | } 34 | }, 35 | "include": ["./**/*.ts"] 36 | } -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.black] 2 | line-length = 100 -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | testpaths = tests 3 | junit_family=legacy 4 | python_files = tests.py test_*.py *_tests.py 5 | markers = 6 | unittest: Small, isolated test 7 | integration_test: A test towards some external system or service. For example a database 8 | functionaltest: Large potentially non-isolated test requiring access to external services 9 | slow: A slow test. Skip normally. But run this when you have the time. -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | """Setup file for the Awesome Panel Extensions""" 2 | import pathlib 3 | from typing import List 4 | 5 | import setuptools 6 | 7 | # I only want to include a short README with a focus on the package 8 | with open("README.md", "r") as fh: 9 | long_description = fh.read() 10 | 11 | ROOT = pathlib.Path.cwd() 12 | VERSION = (ROOT / "VERSION").read_text().strip() 13 | 14 | install_requires = [ 15 | "panel>=0.11.1", 16 | "bokeh>=2.3", 17 | ] 18 | 19 | _recommended: List[str] = [] 20 | 21 | _tests = [ 22 | "autoflake", 23 | "invoke", 24 | "isort", 25 | "jupyter-repo2docker", 26 | "mypy", 27 | "pylint>=2.6.0", 28 | "pytest", 29 | "pytest-cov", 30 | "rope", 31 | "twine", 32 | "wheel", 33 | ] 34 | 35 | _examples = [ 36 | "notebook", 37 | "jupyterlab", 38 | "transcrypt", 39 | ] 40 | 41 | _doc: List[str] = [] 42 | 43 | extras_require = { 44 | "examples": _recommended + _examples, 45 | "tests": _tests, 46 | "recommended": _recommended, 47 | "doc": _recommended + _doc, 48 | } 49 | 50 | extras_require["all"] = sorted(set(sum(extras_require.values(), []))) 51 | 52 | setuptools.setup( 53 | name="panel-sketch", 54 | version=VERSION, 55 | description="""To sketch high performing, interactive visualizations running in the browser 56 | and drawing inspiration from p5js""", 57 | long_description=long_description, 58 | long_description_content_type="text/markdown", 59 | author="Marc Skov Madsen", 60 | author_email="marc.skov.madsen@gmail.com", 61 | platforms=["Windows", "Mac OS X", "Linux"], 62 | license="MIT", 63 | url="https://github.com/MarcSkovMadsen/panel-sketch", 64 | # My Project contains more folders/ packages but they should not be included 65 | packages=setuptools.find_packages(include=["panel_sketch", "panel_sketch.*"]), 66 | include_package_data=True, 67 | classifiers=[ 68 | # I would like to indicate that this package is a package for the Panel framework 69 | "License :: OSI Approved :: MIT License", 70 | "Development Status :: 3 - Alpha", 71 | "Programming Language :: Python :: 3", 72 | "Programming Language :: Python :: 3.7", 73 | "Programming Language :: Python :: 3.8", 74 | "Programming Language :: Python :: 3.9", 75 | "Operating System :: OS Independent", 76 | "Intended Audience :: Developers", 77 | "Intended Audience :: Science/Research", 78 | "Intended Audience :: Financial and Insurance Industry", 79 | "Intended Audience :: Healthcare Industry", 80 | "Intended Audience :: Information Technology", 81 | "Intended Audience :: Legal Industry", 82 | "Intended Audience :: Other Audience", 83 | "Intended Audience :: Science/Research", 84 | "Natural Language :: English", 85 | "Topic :: Scientific/Engineering", 86 | "Topic :: Scientific/Engineering :: Visualization", 87 | "Topic :: Scientific/Engineering :: Information Analysis", 88 | "Topic :: Office/Business", 89 | "Topic :: Office/Business :: Financial", 90 | "Topic :: Software Development :: Libraries", 91 | ], 92 | python_requires=">=3.7", 93 | install_requires=install_requires, 94 | extras_require=extras_require, 95 | tests_require=extras_require["tests"], 96 | ) 97 | -------------------------------------------------------------------------------- /tasks/__init__.py: -------------------------------------------------------------------------------- 1 | """Here we import the different task submodules/ collections""" 2 | from invoke import Collection 3 | 4 | from . import test 5 | 6 | # pylint: disable=invalid-name 7 | # as invoke only recognizes lower case 8 | namespace = Collection() 9 | namespace.add_collection(test) 10 | -------------------------------------------------------------------------------- /tasks/test.py: -------------------------------------------------------------------------------- 1 | """Module of Invoke tasks regarding CODE QUALITY to be invoked from the command line. Try 2 | 3 | invoke --list 4 | 5 | from the command line for a list of all available commands. 6 | """ 7 | 8 | from invoke import task 9 | 10 | PACKAGE_FOLDER = "panel_sketch" 11 | 12 | 13 | @task 14 | def bandit(command): 15 | """Runs Bandit the security linter from PyCQA.""" 16 | print( 17 | """ 18 | Running Bandit the Python Security Linter 19 | to identify common security issues in Python code 20 | ================================================= 21 | """ 22 | ) 23 | command.run("bandit -r ./", echo=True) 24 | 25 | 26 | @task 27 | def black(command): 28 | """Runs black (autoformatter) on all .py files recursively""" 29 | print( 30 | """ 31 | Running Black the Python code formatter 32 | ======================================= 33 | """ 34 | ) 35 | command.run("black .", echo=True) 36 | 37 | 38 | @task 39 | def isort(command): 40 | """Runs isort (import sorter) on all .py files recursively""" 41 | print( 42 | """ 43 | Running isort the Python code import sorter 44 | =========================================== 45 | """ 46 | ) 47 | command.run("isort .", echo=True) 48 | 49 | 50 | @task 51 | def pytest( 52 | command, 53 | test_files="tests", 54 | integrationtest=False, 55 | test_results="test_results", 56 | open_results=True, 57 | ): 58 | """Runs pytest to identify failing tests 59 | 60 | Arguments: 61 | command {[type]} -- Invoke command object 62 | 63 | Keyword Arguments: 64 | root_dir {str} -- The directory from which to run the tests 65 | test_files {str} -- A space separated list of folders and files to test. (default: {'tests}) 66 | integrationtest {bool} -- If True tests marked integrationtest or functionaltest will be 67 | run. Otherwise not. (default: {False}) 68 | test_results {string} -- If not None test reports will be generated in the test_results 69 | folder 70 | open_results {bool} -- If True test reports in the 'test_results' folder will be opened in 71 | a browser 72 | 73 | # Print running pytest 74 | """ 75 | print( 76 | """ 77 | Running pytest the test framework 78 | ================================= 79 | """ 80 | ) 81 | # Build the command_string 82 | command_string = f"pytest {test_files} --doctest-modules --cov={PACKAGE_FOLDER}" 83 | if not integrationtest: 84 | command_string += ' -m "not functionaltest and not integrationtest"' 85 | if test_results: 86 | # command_string += f" --junitxml={test_results}/test-results-api.xml" 87 | command_string += f" --cov-report html:{test_results}/cov_html" 88 | 89 | # Run the command_string 90 | command.run(command_string, echo=True) 91 | 92 | # Open the test coverage report in a browser 93 | if test_results and open_results: 94 | command.run("start test_results/cov_html/index.html") 95 | 96 | 97 | @task() 98 | def pylint(command, files=f"setup.py tasks {PACKAGE_FOLDER} tests"): 99 | """Runs pylint (linter) on all .py files recursively to identify coding errors 100 | 101 | Arguments: 102 | command {[type]} -- [description] 103 | files {string} -- A space separated list of files and folders to lint 104 | """ 105 | # https://stackoverflow.com/questions/22241435/pylint-discard-cached-file-state 106 | # from astroid import MANAGER 107 | # MANAGER.astroid_cache.clear() 108 | print( 109 | """ 110 | Running pylint. 111 | Pylint looks for programming errors, helps enforcing a coding standard, 112 | sniffs for code smells and offers simple refactoring suggestions. 113 | ======================================================================= 114 | """ 115 | ) 116 | command_string = f"pylint {files}" 117 | command.run(command_string, echo=True) 118 | 119 | 120 | @task 121 | def mypy(command, files=f"setup.py tasks {PACKAGE_FOLDER} tests"): 122 | """Runs mypy (static type checker) on all .py files recursively 123 | 124 | Arguments: 125 | command {[type]} -- [description] 126 | files {string} -- A space separated list of files and folders to lint 127 | """ 128 | print( 129 | """ 130 | Running mypy for identifying python type errors 131 | =============================================== 132 | """ 133 | ) 134 | command_string = f"mypy {files}" 135 | command.run(command_string, echo=True) 136 | 137 | 138 | @task 139 | def autoflake(command): 140 | """Runs autoflake to remove unused imports on all .py files recursively 141 | 142 | Arguments: 143 | command {[type]} -- [description] 144 | """ 145 | print( 146 | """ 147 | Running autoflake to remove unused imports on all .py files recursively 148 | ======================================================================= 149 | """ 150 | ) 151 | # command.run("RUN rm -rf .mypy_cache/; exit 0") 152 | command.run( 153 | "autoflake --imports=pytest,pandas,numpy,plotly,dash,urllib3 --in-place --recursive .", 154 | echo=True, 155 | ) 156 | 157 | 158 | @task( 159 | pre=[isort, autoflake, black, pylint, mypy, pytest], 160 | aliases=["pre_commit", "test"], 161 | name="all", 162 | ) 163 | def _all(command): # pylint: disable=unused-argument 164 | """Runs isort, autoflake, black, pylint, mypy and pytest 165 | 166 | Arguments: 167 | command {[type]} -- [description] 168 | """ 169 | # If we get to this point all tests listed in 'pre' have passed 170 | # unless we have run the task with the --warn flag 171 | if not command.config.run.warn: 172 | print( 173 | """ 174 | All Tests Passed Successfully 175 | ============================= 176 | """ 177 | ) 178 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcSkovMadsen/panel-sketch/518cb177e2e8d1899b58f3a3f4d80d26c82ec760/tests/__init__.py -------------------------------------------------------------------------------- /tests/models/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcSkovMadsen/panel-sketch/518cb177e2e8d1899b58f3a3f4d80d26c82ec760/tests/models/__init__.py -------------------------------------------------------------------------------- /tests/models/test_sketch.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=redefined-outer-name,protected-access 2 | # pylint: disable=missing-function-docstring,missing-module-docstring,missing-class-docstring 3 | 4 | from panel_sketch.models.sketch import Sketch 5 | 6 | 7 | def test_constructor(): 8 | Sketch() 9 | -------------------------------------------------------------------------------- /tests/test_pyodide_compiler.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=redefined-outer-name,protected-access 2 | # pylint: disable=missing-function-docstring,missing-module-docstring,missing-class-docstring 3 | from panel_sketch.sketch_compiler import PyodideCompiler 4 | 5 | INDENTED = """ 6 | def setup(): 7 | pass 8 | 9 | def draw(): 10 | pass 11 | """ 12 | 13 | UNINDENTED = """ 14 | def setup(): 15 | pass 16 | 17 | def draw(): 18 | pass 19 | """ 20 | 21 | 22 | def test_clean_unindents(): 23 | assert PyodideCompiler._clean_object(INDENTED) == UNINDENTED 24 | 25 | 26 | def test_clean_removes_pyp5js_import(): 27 | sketch = """ 28 | # https://p5js.org/examples/interaction-wavemaker.html 29 | 30 | 31 | from pyp5js import * 32 | 33 | t = 0 34 | """ 35 | assert ( 36 | PyodideCompiler._clean_object(sketch) 37 | == """ 38 | # https://p5js.org/examples/interaction-wavemaker.html 39 | 40 | 41 | 42 | t = 0 43 | """ 44 | ) 45 | -------------------------------------------------------------------------------- /tests/test_sketch.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=redefined-outer-name,protected-access 2 | # pylint: disable=missing-function-docstring,missing-module-docstring,missing-class-docstring 3 | import panel as pn 4 | 5 | from panel_sketch import Sketch 6 | 7 | 8 | def test_constructor(): 9 | Sketch() 10 | 11 | 12 | def test_app(): 13 | sketch = Sketch( 14 | # Test that it also works indented 15 | object=""" 16 | def setup(): 17 | 18 | createCanvas(200, 200) 19 | 20 | background(160) 21 | 22 | def draw(): 23 | 24 | fill("blue") 25 | 26 | background(200) 27 | 28 | radius = sin(frameCount / 60) * window.args.value + 50 29 | 30 | ellipse(100, 100, radius, radius) 31 | """, 32 | ) 33 | 34 | slider = pn.widgets.FloatSlider(value=50, start=10, end=100, step=1) 35 | 36 | @pn.depends(value=slider, watch=True) 37 | def _update_value(value): 38 | sketch.args = dict(value=value) 39 | 40 | _update_value(slider.value) 41 | 42 | return pn.Column(sketch.viewer.view, slider) 43 | 44 | 45 | if __name__.startswith("bokeh"): 46 | test_app().servable() 47 | -------------------------------------------------------------------------------- /tests/test_sketch_base.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=redefined-outer-name,protected-access 2 | # pylint: disable=missing-function-docstring,missing-module-docstring,missing-class-docstring 3 | from panel_sketch.sketch_base import SketchBase 4 | 5 | 6 | def test_can_construct(): 7 | sketch = SketchBase() 8 | 9 | assert sketch.args == {} 10 | -------------------------------------------------------------------------------- /tests/test_sketch_compiler.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=redefined-outer-name,protected-access 2 | # pylint: disable=missing-function-docstring,missing-module-docstring,missing-class-docstring 3 | from panel_sketch.sketch_compiler import PyodideCompiler, SketchBase 4 | 5 | SKETCH_PYTHON = """ 6 | print('Hello Compiler World') 7 | """ 8 | 9 | 10 | def test_can_construct(): 11 | # Given 12 | script = "print('Hello Compiler World')" 13 | sketch = SketchBase(object=script, template="pyp5js") 14 | compiler = PyodideCompiler(sketch=sketch) 15 | 16 | assert sketch.javascript == "" 17 | 18 | # When 19 | compiler.run() 20 | 21 | # Then 22 | assert script in sketch.javascript 23 | 24 | 25 | def test_can_compile_basic_template(): 26 | # Given 27 | script = "print('Hello Compiler World')" 28 | sketch = SketchBase(object=script, template="basic") 29 | compiler = PyodideCompiler(sketch=sketch) 30 | 31 | # When 32 | compiler.run() 33 | 34 | # Then 35 | assert "_P5_INSTANCE" not in sketch.javascript 36 | -------------------------------------------------------------------------------- /tests/test_sketch_editor.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=redefined-outer-name,protected-access 2 | # pylint: disable=missing-function-docstring,missing-module-docstring,missing-class-docstring 3 | from panel_sketch.sketch_editor import SketchBase, SketchEditor 4 | 5 | 6 | def test_can_construct(): 7 | sketch = SketchBase() 8 | editor = SketchEditor(sketch=sketch) 9 | 10 | assert editor.sketch is sketch 11 | assert editor.view 12 | 13 | 14 | def test_can_update_sketch(): 15 | sketch = SketchBase() 16 | editor = SketchEditor(sketch=sketch) 17 | 18 | sketch.object = "a" 19 | assert editor._python_editor.value == sketch.object 20 | 21 | sketch.html = "b" 22 | assert editor._html_editor.value == sketch.html 23 | 24 | sketch.css = "c" 25 | assert editor._css_editor.value == sketch.css 26 | 27 | sketch.javascript = "d" 28 | assert editor._javascript_editor.value == sketch.javascript 29 | 30 | 31 | def test_can_compile(): 32 | # Given 33 | sketch = SketchBase() 34 | editor = SketchEditor(sketch=sketch) 35 | 36 | assert editor._log.value == "" 37 | # When 38 | editor._python_editor.value = "print('a')" 39 | editor._html_editor.value = "
HI" 40 | editor._css_editor.value = """ 41 | #sketch-element { 42 | color: blue; 43 | } 44 | """ 45 | 46 | editor.compile() 47 | 48 | # Then 49 | assert sketch.object == editor._python_editor.value 50 | assert sketch.html == editor._html_editor.value 51 | assert sketch.css == editor._css_editor.value 52 | -------------------------------------------------------------------------------- /tests/test_sketch_viewer.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=redefined-outer-name,protected-access 2 | # pylint: disable=missing-function-docstring,missing-module-docstring,missing-class-docstring 3 | from panel_sketch.sketch_viewer import SketchBase, SketchViewer 4 | 5 | 6 | def test_can_constructor(): 7 | sketch = SketchBase(javascript="console.log('sketch-element')") 8 | viewer = SketchViewer(sketch=sketch) 9 | 10 | assert viewer.sketch == sketch 11 | assert viewer.view 12 | 13 | assert "sketch-" in viewer._html_pane.object 14 | assert "sketch-" in viewer._js_pane.object 15 | 16 | assert "sketch-element" not in viewer._html_pane.object 17 | assert "sketch-element" not in viewer._js_pane.object 18 | 19 | 20 | def test_get_layout_fixed(): 21 | sketch = """ 22 | def setup(): 23 | 24 | createCanvas(200, 200) 25 | 26 | background(160) 27 | """ 28 | assert SketchViewer._get_layout(sketch) == (200, 200, "fixed") 29 | 30 | 31 | def test_get_layout_none(): 32 | sketch = """ 33 | def setup(): 34 | 35 | background(160) 36 | """ 37 | assert SketchViewer._get_layout(sketch) == (None, None, None) 38 | 39 | 40 | def test_get_layout_more_args(): 41 | sketch = """ 42 | def setup(): 43 | createCanvas(640, 360, _P5_INSTANCE.WEBGL) 44 | fill(204) 45 | """ 46 | assert SketchViewer._get_layout(sketch) == (640, 360, "fixed") 47 | -------------------------------------------------------------------------------- /tests/test_transcrypt_compiler.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=redefined-outer-name,protected-access 2 | # pylint: disable=missing-function-docstring,missing-module-docstring,missing-class-docstring 3 | from panel_sketch.sketch_compiler import SketchBase, TranscryptCompiler 4 | 5 | SKETCH_PYTHON = """ 6 | print('Hello Compiler World') 7 | """ 8 | 9 | 10 | def duplicate_count(value): 11 | return len([x for x in set(value) if value.count(x) > 1]) 12 | 13 | 14 | def test_can_construct(): 15 | sketch = SketchBase(object=SKETCH_PYTHON, template="basic") 16 | compiler = TranscryptCompiler(sketch=sketch) 17 | 18 | compiler.run() 19 | 20 | # When concatenating transcrypt generated modules we need to make sure they only appear once 21 | assert sketch.javascript.count("var __name__") == 1 22 | assert ( 23 | sketch.javascript.count("var sketchElement = document.getElementById('sketch-element')\n") 24 | == 1 25 | ) 26 | 27 | 28 | def test_can_construct(): 29 | sketch = SketchBase(object=SKETCH_PYTHON, template="pyp5js") 30 | compiler = TranscryptCompiler(sketch=sketch) 31 | 32 | compiler.run() 33 | 34 | # When concatenating transcrypt generated modules we need to make sure they only appear once 35 | assert sketch.javascript.count("var __name__") == 1 36 | assert ( 37 | sketch.javascript.count("var sketchElement = document.getElementById ('sketch-element')") 38 | == 1 39 | ) 40 | --------------------------------------------------------------------------------