kopia lustrzana https://github.com/deathbeds/ipydrawio
Add JupyterLite Site (#57)
rodzic
2f6dd87c41
commit
4c40027cf0
|
@ -27,7 +27,6 @@ dependencies:
|
|||
- jupyter-lsp-python-lsp-server
|
||||
- jupyterlab-classic
|
||||
- jupyterlab-lsp
|
||||
- jupyterlab-tour
|
||||
- matplotlib-base
|
||||
- nbgitpuller
|
||||
- networkx
|
||||
|
@ -51,8 +50,13 @@ dependencies:
|
|||
- pytest-check-links
|
||||
- sphinx
|
||||
- sphinx-jsonschema
|
||||
- sphinxext-rediraffe
|
||||
# for lite
|
||||
- jupyterlab-tour
|
||||
# TODO: resolve upstream
|
||||
- sqlalchemy <1.4
|
||||
- pip:
|
||||
- jupyterlite ==0.1.0a3
|
||||
|
||||
### ipydrawio-docs-deps ###
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# basicall ipydrawio[all,test] and ipydrawio-export... plus robot
|
||||
black
|
||||
doit
|
||||
flake8
|
||||
|
|
|
@ -27,6 +27,7 @@ env:
|
|||
PYTHONIOENCODING: 'utf-8'
|
||||
PIP_DISABLE_PIP_VERSION_CHECK: '1'
|
||||
CONDARC: .github/.condarc
|
||||
CI: '1'
|
||||
|
||||
# our stuff
|
||||
ATEST_RETRIES: '3'
|
||||
|
@ -307,7 +308,7 @@ jobs:
|
|||
# taskkill /F /IM python.exe || echo "no python"
|
||||
# taskkill /F /IM node.exe || echo "no node"
|
||||
|
||||
- name: report (atest)
|
||||
- name: upload (atest)
|
||||
if: ${{ always() }}
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
|
@ -325,6 +326,8 @@ jobs:
|
|||
matrix:
|
||||
os: ['ubuntu']
|
||||
python-version: ['3.9']
|
||||
env:
|
||||
ATEST_ARGS: '["--exclude","NOTapp:lite"]'
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
|
@ -367,3 +370,26 @@ jobs:
|
|||
shell: bash -l {0}
|
||||
run: |
|
||||
doit $DOIT_N_TEST check
|
||||
|
||||
- name: lite tests
|
||||
shell: bash -l {0}
|
||||
run: |
|
||||
doit $DOIT_N_TEST test
|
||||
|
||||
- name: upload (atest lite)
|
||||
if: ${{ always() }}
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name:
|
||||
ipydrawio ${{ github.run_number }} atest ${{ matrix.os }}${{
|
||||
matrix.python-version }}
|
||||
path: ./build/atest
|
||||
|
||||
- name: upload (docs)
|
||||
if: ${{ always() }}
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name:
|
||||
ipydrawio ${{ github.run_number }} docs ${{ matrix.os }}${{
|
||||
matrix.python-version }}
|
||||
path: ./build/docs
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
__pycache__
|
||||
_output
|
||||
.coverage*
|
||||
.doit*
|
||||
*doit.db
|
||||
.ipynb_checkpoints
|
||||
.pabotsuitenames
|
||||
.virtual_documents/
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
```bash
|
||||
mamba install -c conda-forge ipydrawio # recommended, or...
|
||||
conda install -c conda-forge ipydrawio # or...
|
||||
pip install ipydrawio
|
||||
pip install ipydrawio[all]
|
||||
```
|
||||
|
||||
## Features
|
||||
|
|
|
@ -22,23 +22,35 @@ Library ./ports.py
|
|||
|
||||
*** Keywords ***
|
||||
Setup Server and Browser
|
||||
${home} = Setup Home
|
||||
${port} = Get Unused Port
|
||||
${root} = Get Server Root
|
||||
Set Global Variable ${PORT} ${port}
|
||||
Set Global Variable ${URL} http://localhost:${PORT}${BASE}
|
||||
Setup Real Server port=${port} home=${HOME} root=${root}
|
||||
|
||||
Get Server Root
|
||||
${root} = Normalize Path ${OUTPUT DIR}${/}..${/}..${/}..
|
||||
[Return] ${root}
|
||||
|
||||
Setup Home
|
||||
${accel} = Evaluate "COMMAND" if "${OS}" == "Darwin" else "CTRL"
|
||||
Set Global Variable ${ACCEL} ${accel}
|
||||
${token} = Generate Random String
|
||||
Set Global Variable ${TOKEN} ${token}
|
||||
${home} = Set Variable ${OUTPUT DIR}${/}home
|
||||
Set Global Variable ${HOME} ${home}
|
||||
${root} = Normalize Path ${OUTPUT DIR}${/}..${/}..${/}..
|
||||
Create Directory ${home}
|
||||
Set Screenshot Directory ${OUTPUT DIR}${/}screenshots
|
||||
[Return] ${home}
|
||||
|
||||
Setup Real Server
|
||||
[Arguments] ${port} ${home} ${root}
|
||||
Set Global Variable ${LAB LOG} ${OUTPUT DIR}${/}lab.log
|
||||
Set Global Variable ${PREVIOUS LAB LOG LENGTH} 0
|
||||
Create Notebok Server Config ${home}
|
||||
Initialize User Settings
|
||||
${cmd} = Create Lab Launch Command ${root}
|
||||
Set Screenshot Directory ${OUTPUT DIR}${/}screenshots
|
||||
Set Global Variable ${LAB LOG} ${OUTPUT DIR}${/}lab.log
|
||||
Set Global Variable ${PREVIOUS LAB LOG LENGTH} 0
|
||||
${server} = Start Process ${cmd} shell=yes env:HOME=${home} cwd=${home} stdout=${LAB LOG}
|
||||
... stderr=STDOUT
|
||||
Set Global Variable ${SERVER} ${server}
|
||||
|
@ -86,13 +98,19 @@ Reset Plugin Settings
|
|||
|
||||
Tear Down Everything
|
||||
Close All Browsers
|
||||
Tear Down Real Server
|
||||
|
||||
Tear Down Real Server
|
||||
Evaluate __import__("urllib.request").request.urlopen("${URL}api/shutdown?token=${TOKEN}", data=[])
|
||||
Wait For Process ${SERVER} timeout=30s
|
||||
Terminate All Processes
|
||||
Terminate All Processes kill=${True}
|
||||
|
||||
Wait For Splash
|
||||
Go To ${URL}lab?reset&token=${TOKEN}
|
||||
[Arguments] ${lab url}=${EMPTY}
|
||||
Run Keyword If """${lab url}"""
|
||||
... Go To ${lab url}
|
||||
... ELSE Go To ${URL}lab?reset&token=${TOKEN}
|
||||
Set Window Size 1920 1080
|
||||
Wait Until Page Contains Element ${SPLASH} timeout=30s
|
||||
Wait Until Page Does Not Contain Element ${SPLASH} timeout=10s
|
||||
|
|
|
@ -14,10 +14,3 @@
|
|||
|
||||
*** Settings ***
|
||||
Documentation IPyDrawio
|
||||
Resource _Keywords.robot
|
||||
Resource _Variables.robot
|
||||
Suite Setup Setup Server and Browser
|
||||
Suite Teardown Tear Down Everything
|
||||
Test Setup Maybe Reset Application State
|
||||
Test Teardown Maybe Reset Application State
|
||||
Force Tags os:${OS.lower()} py:${PY}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
*** Settings ***
|
||||
Documentation Does custom create work?
|
||||
Resource _Keywords.robot
|
||||
Resource ../_Keywords.robot
|
||||
Library OperatingSystem
|
||||
Force Tags component:document component:custom
|
||||
Suite Setup Set Screenshot Directory ${OUTPUT DIR}${/}screenshots${/}custom
|
|
@ -14,9 +14,9 @@
|
|||
|
||||
*** Settings ***
|
||||
Documentation Are export formats sane?
|
||||
Resource _Keywords.robot
|
||||
Resource ../_Keywords.robot
|
||||
Library OperatingSystem
|
||||
Library ./pdf.py
|
||||
Library ../pdf.py
|
||||
Force Tags component:document
|
||||
|
||||
*** Variables ***
|
|
@ -14,8 +14,8 @@
|
|||
|
||||
*** Settings ***
|
||||
Documentation Does the media type (mimerenderer) work?
|
||||
Resource _Keywords.robot
|
||||
Resource _Notebook.robot
|
||||
Resource ../_Keywords.robot
|
||||
Resource ../_Notebook.robot
|
||||
Force Tags component:media
|
||||
Library OperatingSystem
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
*** Settings ***
|
||||
Documentation Are Diagram settings usable?
|
||||
Resource _Keywords.robot
|
||||
Resource ../_Keywords.robot
|
||||
Library OperatingSystem
|
||||
Force Tags component:settings
|
||||
|
|
@ -14,9 +14,9 @@
|
|||
|
||||
*** Settings ***
|
||||
Documentation smoke tests
|
||||
Resource _Keywords.robot
|
||||
Resource ../_Keywords.robot
|
||||
|
||||
*** Test Cases ***
|
||||
Smoke
|
||||
[Documentation] Does the app even load?
|
||||
Capture Page Screenshot smoke.png
|
||||
Capture Page Screenshot 00-smoke.png
|
|
@ -14,8 +14,8 @@
|
|||
|
||||
*** Settings ***
|
||||
Documentation Does the Jupyter Widget work?
|
||||
Resource _Keywords.robot
|
||||
Resource _Notebook.robot
|
||||
Resource ../_Keywords.robot
|
||||
Resource ../_Notebook.robot
|
||||
Force Tags component:widget
|
||||
Library OperatingSystem
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
# Copyright 2021 ipydrawio contributors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
*** Settings ***
|
||||
Documentation Lab
|
||||
Resource ../_Keywords.robot
|
||||
Resource ../_Variables.robot
|
||||
Suite Setup Setup Server and Browser
|
||||
Suite Teardown Tear Down Everything
|
||||
Test Setup Maybe Reset Application State
|
||||
Test Teardown Maybe Reset Application State
|
||||
Force Tags os:${OS.lower()} py:${PY} app:lab
|
|
@ -0,0 +1,40 @@
|
|||
# Copyright 2021 ipydrawio contributors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
*** Settings ***
|
||||
Documentation Test some diagrams in lite
|
||||
Resource ../_Keywords.robot
|
||||
Resource ./_Keywords.robot
|
||||
Library OperatingSystem
|
||||
Force Tags component:document
|
||||
Suite Setup Set Screenshot Directory ${OUTPUT DIR}${/}lite${/}documents
|
||||
|
||||
*** Test Cases ***
|
||||
Test Examples
|
||||
[Documentation] Do all of the examples work?
|
||||
${examples} = List Files In Directory ${DEMO} *.dio*
|
||||
FOR ${file} IN @{EXAMPLES}
|
||||
Try to Close All Tabs
|
||||
Run Keyword If ${file.__contains__('.dio')} Example Should Load ${file}
|
||||
END
|
||||
|
||||
*** Keywords ***
|
||||
Example Should Load
|
||||
[Arguments] ${file}
|
||||
[Documentation] Does one example work?
|
||||
Ensure File Browser is Open
|
||||
Double Click Element css:[title*\="${file}"]
|
||||
Unselect Frame
|
||||
Wait Until Element is Visible ${CSS DIO IFRAME} timeout=20s
|
||||
Capture Page Screenshot 00-${file}-loaded.png
|
|
@ -0,0 +1,24 @@
|
|||
# Copyright 2021 ipydrawio contributors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
*** Settings ***
|
||||
Documentation Check the vitals of a Lite site
|
||||
Resource ../_Keywords.robot
|
||||
Resource ./_Keywords.robot
|
||||
Suite Setup Set Screenshot Directory ${OUTPUT DIR}${/}lite${/}smoke
|
||||
|
||||
*** Test Cases ***
|
||||
Does Lite load?
|
||||
[Documentation] Can we load the JupyterLite site?
|
||||
Capture Page Screenshot 00-lite-smoke.png
|
|
@ -0,0 +1,76 @@
|
|||
# Copyright 2021 ipydrawio contributors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
*** Settings ***
|
||||
Documentation A work-in-progress set of keywords for JupyterLite
|
||||
Library OperatingSystem
|
||||
Library Process
|
||||
Library ../ports.py
|
||||
|
||||
*** Variable ***
|
||||
${NEXT LITE LOG} ${0}
|
||||
|
||||
*** Keywords ***
|
||||
Start JupyterLite Process
|
||||
[Arguments] ${task} ${cwd} @{args}
|
||||
[Documentation] Start a `jupyter lite` process
|
||||
${p} = Start Process jupyter lite ${task} @{args}
|
||||
... cwd=${cwd} stdout=${OUTPUT DIR}${/}lite-${NEXT LITE LOG}.log stderr=STDOUT
|
||||
Set Global Variable ${NEXT LITE LOG} ${NEXT LITE LOG + 1}
|
||||
[Return] ${p}
|
||||
|
||||
Start JupyterLite Server
|
||||
[Documentation] Start _the_ `jupyter lite` server
|
||||
[Arguments] ${cwd} @{args}
|
||||
Set Environment Variable MOZ_HEADLESS 1
|
||||
${prefix} = Set Variable /@rf/
|
||||
${port} = Get Unused Port
|
||||
${url} = Set Variable http://localhost:${port}${prefix}lab/index.html
|
||||
Set Global Variable ${LITE URL} ${url}
|
||||
${p} = Start JupyterLite Process serve ${cwd}
|
||||
... @{args} --port ${port} --base-url ${prefix}
|
||||
Set Global Variable ${LITE SERVER} ${p}
|
||||
Close All Browsers
|
||||
${service args} = Create List --log warn
|
||||
Create WebDriver Firefox
|
||||
... service_log_path=${OUTPUT DIR}${/}geckodriver-lite.log
|
||||
... service_args=${service args}
|
||||
|
||||
Open JupyterLite
|
||||
Set Environment Variable MOZ_HEADLESS 1
|
||||
${service args} = Create List --log warn
|
||||
Wait For Splash ${LITE URL}
|
||||
|
||||
Stop JupyterLite Server
|
||||
[Documentation] Stop _the_ `jupyter lite` server
|
||||
Close All Browsers
|
||||
Terminate Process ${LITE SERVER}
|
||||
|
||||
Start Lite Test
|
||||
[Documentation] Start with a blank browser
|
||||
Open JupyterLite
|
||||
|
||||
Clean Up Lite Test
|
||||
[Documentation] Clean up
|
||||
... TODO: how might we clear the application cache?
|
||||
Close All Browsers
|
||||
|
||||
Start Lite Suite
|
||||
[Documentation] Ensure lite assets are available
|
||||
Set Screenshot Directory ${OUTPUT DIR}${/}lite
|
||||
Start JupyterLite Server ${DEMO}
|
||||
|
||||
Clean Up Lite Suite
|
||||
[Documentation] Clean up after lite
|
||||
Stop JupyterLite Server
|
|
@ -0,0 +1,24 @@
|
|||
# Copyright 2021 ipydrawio contributors
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
*** Settings ***
|
||||
Documentation Lite
|
||||
Library OperatingSystem
|
||||
Force Tags app:lite
|
||||
Resource ./_Keywords.robot
|
||||
Resource ../_Keywords.robot
|
||||
Suite Setup Start Lite Suite
|
||||
Suite Teardown Clean Up Lite Suite
|
||||
Test Setup Start Lite Test
|
||||
Test Teardown Clean Up Lite Test
|
|
@ -0,0 +1,6 @@
|
|||
_output
|
||||
*.dio
|
||||
*.dio.svg
|
||||
*.ipynb
|
||||
*doit.db
|
||||
files/
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"jupyter-config-data": {
|
||||
"appName": "IPyDrawioLite",
|
||||
"disabledExtensions": [
|
||||
"@deathbeds/ipydrawio-pdf",
|
||||
"@jupyterlab-classic/lab-extension",
|
||||
"@jupyterlab/server-proxy",
|
||||
"@krassowski/jupyterlab-lsp",
|
||||
"jupyterlab-server-proxy",
|
||||
"nbdime-jupyterlab"
|
||||
],
|
||||
"faviconUrl": "./favicon.ico"
|
||||
},
|
||||
"jupyter-lite-schema-version": 0
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"LiteBuildConfig": {
|
||||
"apps": ["lab"],
|
||||
"files": ["."],
|
||||
"ignore_files": [
|
||||
"(lab/|_output|.gitignore|doit.db|.json|test|Test|jupyter_config|log$)"
|
||||
],
|
||||
"lite_dir": ".",
|
||||
"output_archive": "../build/demo/ipydrawio-lite-1.1.1.tgz",
|
||||
"output_dir": "../build/demo"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
{
|
||||
"@jupyterlab/apputils-extension:palette": {
|
||||
"modal": false
|
||||
},
|
||||
"@jupyterlab/extensionmanager-extension:plugin": {
|
||||
"enabled": false
|
||||
},
|
||||
"jupyterlab-tour:user-tours": {
|
||||
"tours": [
|
||||
{
|
||||
"id": "ipydrawiolite",
|
||||
"label": "IPyDrawioLite",
|
||||
"options": {
|
||||
"styles": {
|
||||
"options": {
|
||||
"arrowColor": "#7b8aff",
|
||||
"beaconSize": 48,
|
||||
"primaryColor": "#7b8aff"
|
||||
}
|
||||
}
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"content": "This is running in JupyterLite",
|
||||
"target": "#jp-MainLogo"
|
||||
},
|
||||
{
|
||||
"content": "It can open multi-page drawio XML files, as well as editable SVG and PNG files, or even Jupyter Notebooks",
|
||||
"target": ".jp-DirListing-item svg[data-icon*='drawio']"
|
||||
},
|
||||
{
|
||||
"content": "You can create new diagrams from the launcher...",
|
||||
"target": ".jp-Launcher-sectionHeader svg[data-icon='drawio:drawio']"
|
||||
},
|
||||
{
|
||||
"content": "... start with a blank canvas XML file with your default diagram theme...",
|
||||
"target": ".jp-LauncherCard[title='Create a blank .dio file']"
|
||||
},
|
||||
{
|
||||
"content": "...or one of many templates, formats, and themes",
|
||||
"target": ".jp-LauncherCard[title='Create a diagram with customized formats, templates, and UI']"
|
||||
},
|
||||
{
|
||||
"content": "The diagram theme is configurable from the Settings menu",
|
||||
"target": ".lm-MenuBar-item:nth-last-child(2)"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -26,6 +26,7 @@
|
|||
--pst-color-inline-code: 0, 22, 192;
|
||||
--pst-color-preformatted-background: 240, 248, 255;
|
||||
--pst-color-headerlink: var(--pst-color-active-navigation);
|
||||
--ipd-brand-color0: rgb(var(--pst-color-active-navigation));
|
||||
}
|
||||
|
||||
code {
|
||||
|
@ -163,3 +164,44 @@ div.cell div.cell_input {
|
|||
text-align: left;
|
||||
padding: calc(0.25 * var(--ipd-card-padding)) 0;
|
||||
}
|
||||
|
||||
.demo-sidebar {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.demo-sidebar .btn-primary {
|
||||
background-color: var(--ipd-brand-color0);
|
||||
font-size: 150%;
|
||||
opacity: 0.5;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.demo-sidebar .btn-primary:hover,
|
||||
.demo-sidebar .btn-primary:focus,
|
||||
.demo-sidebar .btn-primary:active {
|
||||
opacity: 1;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
#try-it-now .warning {
|
||||
float: right;
|
||||
margin-left: 1em;
|
||||
margin-top: 0 !important;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
#try-it-now .warning em:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
hr {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.tooltip-inner {
|
||||
background-color: var(--ipd-brand-color0);
|
||||
}
|
||||
|
||||
.tooltip .arrow:before {
|
||||
border-color: var(--ipd-brand-color0);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
<div class="demo-sidebar">
|
||||
<a
|
||||
href="{{ pathto('demo/index') }}"
|
||||
class="btn btn-primary"
|
||||
target="_blank"
|
||||
data-toggle="tooltip"
|
||||
data-placement="right"
|
||||
title="Try IPyDrawio in your browser. Right now."
|
||||
>
|
||||
<i class="fas fa-lightbulb"></i>
|
||||
Try <strong>IPyDrawio</strong> Now
|
||||
</a>
|
||||
<br/>
|
||||
or <a
|
||||
href="{{ pathto(demo_tarball, True) }}"
|
||||
data-toggle="tooltip"
|
||||
data-placement="bottom"
|
||||
title="Download the app archive"
|
||||
>
|
||||
<i class="fas fa-download"></i>
|
||||
download the demo
|
||||
</a>
|
||||
<hr/>
|
||||
<em>Powered by <a href="https://jupyterlite.rtfd.io" target="_blank">JupyterLite</a></em>
|
||||
<script>$(function() {$('[data-toggle="tooltip"]').tooltip();});</script>
|
||||
</div>
|
41
docs/conf.py
41
docs/conf.py
|
@ -50,6 +50,8 @@ extensions = [
|
|||
"sphinx.ext.intersphinx",
|
||||
"sphinx.ext.autosectionlabel",
|
||||
"sphinx.ext.autodoc",
|
||||
# for routing
|
||||
"sphinxext.rediraffe",
|
||||
"sphinx-jsonschema",
|
||||
"autodoc_traits",
|
||||
]
|
||||
|
@ -58,16 +60,12 @@ autosectionlabel_prefix_document = True
|
|||
myst_heading_anchors = 3
|
||||
suppress_warnings = ["autosectionlabel.*"]
|
||||
|
||||
# rediraffe_redirects = {
|
||||
# "try/index": "_static/index",
|
||||
# "try/lab/index": "_static/lab/index",
|
||||
# "try/classic/index": "_static/classic/tree/index",
|
||||
# }
|
||||
rediraffe_redirects = {"demo/index": "_static/lab/index"}
|
||||
|
||||
# files
|
||||
# templates_path = ["_templates"]
|
||||
templates_path = ["_templates"]
|
||||
html_favicon = "_static/favicon.ico"
|
||||
html_static_path = ["_static"]
|
||||
html_static_path = ["_static", "../build/demo"]
|
||||
exclude_patterns = [
|
||||
".ipynb_checkpoints",
|
||||
"**/.ipynb_checkpoints",
|
||||
|
@ -90,8 +88,15 @@ html_logo = "_static/logo.svg"
|
|||
html_theme_options = {
|
||||
"github_url": APP_DATA["repository"]["url"],
|
||||
"use_edit_page_button": True,
|
||||
# "navbar_start": ["launch.html"],
|
||||
# "navbar_center": ["navbar-logo.html", "navbar-nav.html"],
|
||||
# "navbar_start": ["navbar-logo.html", "launch.html"],
|
||||
}
|
||||
html_sidebars = {
|
||||
"**": [
|
||||
"demo.html",
|
||||
"search-field.html",
|
||||
"sidebar-nav-bs.html",
|
||||
"sidebar-ethical-ads.html",
|
||||
]
|
||||
}
|
||||
|
||||
html_context = {
|
||||
|
@ -99,6 +104,7 @@ html_context = {
|
|||
"github_repo": "ipydrawio",
|
||||
"github_version": "master",
|
||||
"doc_path": "docs",
|
||||
"demo_tarball": f"_static/ipydrawio-lite-{release}.tgz",
|
||||
}
|
||||
|
||||
|
||||
|
@ -121,10 +127,19 @@ def clean_schema(app: Sphinx, error):
|
|||
|
||||
def before_rtd_build(app: Sphinx, error):
|
||||
"""performs the full frontend build, and ensures the typedoc"""
|
||||
subprocess.check_call(
|
||||
["doit", "-n4", "build", "setup:pip:check", "docs:typedoc:mystify"],
|
||||
cwd=str(ROOT),
|
||||
)
|
||||
for task in [
|
||||
"build",
|
||||
"setup:pip:check",
|
||||
"docs:typedoc:mystify",
|
||||
"demo",
|
||||
]:
|
||||
subprocess.check_call(
|
||||
[
|
||||
"doit",
|
||||
task,
|
||||
],
|
||||
cwd=str(ROOT),
|
||||
)
|
||||
|
||||
|
||||
def setup(app):
|
||||
|
|
|
@ -27,8 +27,13 @@ dependencies:
|
|||
- pytest-check-links
|
||||
- sphinx
|
||||
- sphinx-jsonschema
|
||||
- sphinxext-rediraffe
|
||||
# for lite
|
||||
- jupyterlab-tour
|
||||
# TODO: resolve upstream
|
||||
- sqlalchemy <1.4
|
||||
- pip:
|
||||
- jupyterlite ==0.1.0a3
|
||||
|
||||
### ipydrawio-docs-deps ###
|
||||
|
||||
|
|
|
@ -1,8 +1,38 @@
|
|||
# IPyDrawio
|
||||
|
||||
[![What is IPyDrawio?][poster]][poster]
|
||||
> Interactive diagram documents and [widgets] in [JupyterLab], powered by
|
||||
> [drawio].
|
||||
|
||||
[poster]: ./Poster.dio.svg
|
||||
[drawio]: https://github.com/jgraph/drawio
|
||||
[jupyterlab]: https://github.com/jupyterlab/jupyterlab
|
||||
[widgets]: https://github.com/jupyter-widgets/ipywidgets
|
||||
|
||||
## Try it Now
|
||||
|
||||
```{warning}
|
||||
<details>
|
||||
<summary>The demo has some <strong>pointy edges</strong>...</summary>
|
||||
<ul>
|
||||
<li>
|
||||
<em>Diagram Documents</em> and <em>Rich Display</em> work properly, <em>Widgets</em> are <em>close</em>, but can't be properly installed, yet
|
||||
</li>
|
||||
<li>
|
||||
<code>jupyterlite</code> is <em>alpha</em> software, and evolving quickly
|
||||
</li>
|
||||
<li>
|
||||
<strong>Don't</strong> use the demo site for important work
|
||||
</li>
|
||||
</ul>
|
||||
</details>
|
||||
```
|
||||
|
||||
Click the _Try IPyDrawio Now_ button to launch a new browser tab running
|
||||
IPyDrawio. It contains all of the example _Diagrams_ from this documentation
|
||||
site.
|
||||
|
||||
[demo]: ./demo/index
|
||||
|
||||
---
|
||||
|
||||
## Get Started
|
||||
|
||||
|
@ -10,7 +40,7 @@ Install `ipydrawio` (and optionally `ipydrawio-export`) with `pip`, `mamba`, or
|
|||
`conda`:
|
||||
|
||||
```bash
|
||||
pip install ipydrawio
|
||||
pip install ipydrawio[all]
|
||||
# or
|
||||
mamba install -c conda-forge ipydrawio
|
||||
# or
|
||||
|
@ -19,10 +49,27 @@ conda install -c conda-forge ipydrawio
|
|||
|
||||
Start JupyterLab and [start making diagrams](./diagrams/index.md)!
|
||||
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
[![What is IPyDrawio?][poster]][poster]
|
||||
|
||||
[poster]: ./Poster.dio.svg
|
||||
|
||||
## More Screenshots and Examples
|
||||
|
||||
> these are editable SVG files made with IPyDrawio, and can be found in the
|
||||
> [demo].
|
||||
|
||||
### What can you draw with IPyDrawio
|
||||
|
||||
[![What can you draw with IPyDrawio?][what-can-you-draw]][what-can-you-draw]
|
||||
|
||||
[what-can-you-draw]: ./_static/what-can-you-draw.dio.svg
|
||||
|
||||
---
|
||||
|
||||
## Learn More
|
||||
|
||||
```{toctree}
|
||||
|
|
204
dodo.py
204
dodo.py
|
@ -29,7 +29,6 @@ maybe before you push
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import pprint
|
||||
import shutil
|
||||
import subprocess
|
||||
import time
|
||||
|
@ -41,20 +40,6 @@ from doit.tools import PythonInteractiveAction, config_changed
|
|||
|
||||
import scripts.project as P
|
||||
|
||||
print_ = pprint.pprint
|
||||
console = None
|
||||
|
||||
try:
|
||||
import rich.console
|
||||
import rich.markdown
|
||||
|
||||
console = rich.console.Console()
|
||||
print_ = console.print
|
||||
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
DOIT_CONFIG = dict(
|
||||
backend="sqlite3",
|
||||
verbosity=2,
|
||||
|
@ -78,7 +63,9 @@ def task_all():
|
|||
P.OK_PROVISION,
|
||||
P.SHA256SUMS,
|
||||
],
|
||||
actions=[(_show, ["nothing left to do"], {"shasums": P.SHA256SUMS.read_text})],
|
||||
actions=[
|
||||
(P._show, ["nothing left to do"], {"shasums": P.SHA256SUMS.read_text})
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
|
@ -118,7 +105,7 @@ def task_submodules():
|
|||
if any([x.startswith("-") for x in subs]) and P.DRAWIO.exists():
|
||||
shutil.rmtree(P.DRAWIO)
|
||||
|
||||
return _ok(
|
||||
return P._ok(
|
||||
dict(
|
||||
uptodate=[config_changed({"subs": subs})],
|
||||
actions=[_clean, ["git", "submodule", "update", "--init", "--recursive"]],
|
||||
|
@ -156,7 +143,7 @@ def task_setup():
|
|||
ci_af = {"wheel": P.PY_WHEEL[pkg], "sdist": P.PY_SDIST[pkg]}[P.CI_ARTIFACT]
|
||||
dist_af = P.DIST / ci_af.name
|
||||
|
||||
yield _ok(
|
||||
yield P._ok(
|
||||
dict(
|
||||
name=f"py:{pkg}",
|
||||
file_dep=[dist_af],
|
||||
|
@ -177,7 +164,7 @@ def task_setup():
|
|||
extra_deps = []
|
||||
if pkg != "ipydrawio":
|
||||
extra_deps += [P.OK_PYSETUP["ipydrawio"]]
|
||||
yield _ok(
|
||||
yield P._ok(
|
||||
dict(
|
||||
name=f"py:{pkg}",
|
||||
file_dep=[pkg_setup, P.PY_SETUP_CFG[pkg], *ext_deps, *extra_deps],
|
||||
|
@ -210,7 +197,7 @@ def task_setup():
|
|||
P.OK_PYSETUP[pkg],
|
||||
)
|
||||
|
||||
yield _ok(
|
||||
yield P._ok(
|
||||
dict(
|
||||
name="pip:check",
|
||||
file_dep=[*P.OK_PYSETUP.values()],
|
||||
|
@ -232,7 +219,7 @@ def task_setup():
|
|||
if P.TESTING_IN_CI:
|
||||
enable_args = ["echo", "'(installed by pip)'"]
|
||||
|
||||
yield _ok(
|
||||
yield P._ok(
|
||||
dict(
|
||||
name=f"ext:{ext}",
|
||||
doc=f"ensure {ext} is a serverextension",
|
||||
|
@ -252,7 +239,7 @@ def task_lint():
|
|||
if P.TESTING_IN_CI:
|
||||
return
|
||||
|
||||
yield _ok(
|
||||
yield P._ok(
|
||||
dict(
|
||||
name="isort",
|
||||
file_dep=[*P.ALL_PY, P.SETUP_CFG],
|
||||
|
@ -260,7 +247,7 @@ def task_lint():
|
|||
),
|
||||
P.OK_ISORT,
|
||||
)
|
||||
yield _ok(
|
||||
yield P._ok(
|
||||
dict(
|
||||
name="black",
|
||||
file_dep=[*P.ALL_PY, P.OK_ISORT],
|
||||
|
@ -268,7 +255,7 @@ def task_lint():
|
|||
),
|
||||
P.OK_BLACK,
|
||||
)
|
||||
yield _ok(
|
||||
yield P._ok(
|
||||
dict(
|
||||
name="flake8",
|
||||
file_dep=[*P.ALL_PY, P.OK_BLACK, P.SETUP_CFG],
|
||||
|
@ -276,7 +263,7 @@ def task_lint():
|
|||
),
|
||||
P.OK_FLAKE8,
|
||||
)
|
||||
yield _ok(
|
||||
yield P._ok(
|
||||
dict(
|
||||
name="pyflakes",
|
||||
file_dep=[*P.ALL_PY, P.OK_BLACK],
|
||||
|
@ -284,23 +271,46 @@ def task_lint():
|
|||
),
|
||||
P.OK_PYFLAKES,
|
||||
)
|
||||
yield _ok(
|
||||
dict(
|
||||
name="prettier",
|
||||
file_dep=[P.YARN_INTEGRITY, *P.ALL_PRETTIER],
|
||||
actions=[
|
||||
[
|
||||
"jlpm",
|
||||
"prettier",
|
||||
"--list-different",
|
||||
"--write",
|
||||
*sorted(p.relative_to(P.ROOT) for p in P.ALL_PRETTIER),
|
||||
]
|
||||
],
|
||||
),
|
||||
P.OK_PRETTIER,
|
||||
)
|
||||
yield _ok(
|
||||
|
||||
prettier_args = [
|
||||
"jlpm",
|
||||
"--silent",
|
||||
"prettier",
|
||||
"--list-different",
|
||||
"--write",
|
||||
]
|
||||
|
||||
if P.CI:
|
||||
yield P._ok(
|
||||
dict(
|
||||
name="prettier",
|
||||
file_dep=[P.YARN_INTEGRITY, *P.ALL_PRETTIER],
|
||||
actions=[[*prettier_args, *P.ALL_PRETTIER]],
|
||||
),
|
||||
P.OK_PRETTIER,
|
||||
)
|
||||
else:
|
||||
pretty_tasks = []
|
||||
for path in P.ALL_PRETTIER:
|
||||
name = f"prettier:{path.relative_to(P.ROOT)}"
|
||||
pretty_tasks += [f"lint:{name}"]
|
||||
yield dict(
|
||||
name=name,
|
||||
file_dep=[P.YARN_INTEGRITY, path],
|
||||
actions=[[*prettier_args, path]],
|
||||
)
|
||||
|
||||
yield P._ok(
|
||||
dict(
|
||||
name="prettier",
|
||||
file_dep=[P.YARN_INTEGRITY, *P.ALL_PRETTIER],
|
||||
task_dep=pretty_tasks,
|
||||
actions=[["echo", "OK"]],
|
||||
),
|
||||
P.OK_PRETTIER,
|
||||
)
|
||||
|
||||
yield P._ok(
|
||||
dict(
|
||||
name="eslint",
|
||||
file_dep=[
|
||||
|
@ -326,7 +336,7 @@ def task_lint():
|
|||
actions=[["jupyter", "ipydrawio", "clean", dio_file]],
|
||||
)
|
||||
|
||||
yield _ok(
|
||||
yield P._ok(
|
||||
dict(
|
||||
name="dio:clean",
|
||||
file_dep=[*P.ALL_DIO],
|
||||
|
@ -336,10 +346,10 @@ def task_lint():
|
|||
P.OK_DIOLINT,
|
||||
)
|
||||
|
||||
yield _ok(
|
||||
yield P._ok(
|
||||
dict(
|
||||
name="all",
|
||||
actions=[_echo_ok("all ok")],
|
||||
actions=[P._echo_ok("all ok")],
|
||||
file_dep=[
|
||||
P.OK_BLACK,
|
||||
P.OK_FLAKE8,
|
||||
|
@ -351,7 +361,7 @@ def task_lint():
|
|||
P.OK_LINT,
|
||||
)
|
||||
|
||||
yield _ok(
|
||||
yield P._ok(
|
||||
dict(
|
||||
name="robot:tidy",
|
||||
file_dep=P.ALL_ROBOT,
|
||||
|
@ -360,7 +370,7 @@ def task_lint():
|
|||
P.OK_ROBOTIDY,
|
||||
)
|
||||
|
||||
yield _ok(
|
||||
yield P._ok(
|
||||
dict(
|
||||
name="robot:lint",
|
||||
file_dep=[*P.ALL_ROBOT, P.OK_ROBOTIDY],
|
||||
|
@ -369,7 +379,7 @@ def task_lint():
|
|||
P.OK_RFLINT,
|
||||
)
|
||||
|
||||
yield _ok(
|
||||
yield P._ok(
|
||||
dict(
|
||||
name="robot:dryrun",
|
||||
file_dep=[*P.ALL_ROBOT, P.OK_RFLINT],
|
||||
|
@ -384,7 +394,7 @@ def task_build():
|
|||
if P.TESTING_IN_CI:
|
||||
return
|
||||
|
||||
yield _ok(
|
||||
yield P._ok(
|
||||
dict(
|
||||
name="js:pre",
|
||||
file_dep=[
|
||||
|
@ -400,7 +410,7 @@ def task_build():
|
|||
P.OK_JS_BUILD_PRE,
|
||||
)
|
||||
|
||||
yield _ok(
|
||||
yield P._ok(
|
||||
dict(
|
||||
name="js",
|
||||
file_dep=[P.YARN_INTEGRITY, P.OK_JS_BUILD_PRE, *P.ALL_TS, *P.ALL_CSS],
|
||||
|
@ -437,7 +447,7 @@ def task_build():
|
|||
P.JS_PKG_JSON[pkg].parent / pkg_data["jupyterlab"]["outputDir"]
|
||||
).resolve()
|
||||
|
||||
yield _ok(
|
||||
yield P._ok(
|
||||
dict(
|
||||
name=f"ext:build:{pkg}",
|
||||
actions=[
|
||||
|
@ -553,7 +563,7 @@ def task_conda_build():
|
|||
|
||||
def task_conda_test():
|
||||
for name, pkg in P.CONDA_PKGS.items():
|
||||
yield _ok(
|
||||
yield P._ok(
|
||||
dict(
|
||||
name=f"test:{name}",
|
||||
file_dep=[pkg],
|
||||
|
@ -660,6 +670,38 @@ def task_watch():
|
|||
)
|
||||
|
||||
|
||||
def task_demo():
|
||||
if not P.LITE_PREFIX:
|
||||
return
|
||||
|
||||
demo_dest = []
|
||||
for path in P.ALL_DEMO_CONTENTS:
|
||||
dest = P.DEMO / path.name.replace(" ", "_")
|
||||
demo_dest += [dest]
|
||||
yield dict(
|
||||
name=f"stage:{path.name}",
|
||||
file_dep=[path],
|
||||
targets=[dest],
|
||||
actions=[(P._copy_one, [path, dest])],
|
||||
)
|
||||
|
||||
lite_src_files = [
|
||||
p
|
||||
for p in P.DEMO.rglob("*")
|
||||
if not p.is_dir()
|
||||
and "/_output/" not in str(p)
|
||||
and not p.name.endswith(".tgz")
|
||||
and ".doit" not in p.name
|
||||
]
|
||||
|
||||
yield dict(
|
||||
name="archive",
|
||||
file_dep=[*demo_dest, *lite_src_files],
|
||||
targets=[P.DEMO_ARCHIVE, P.DEMO_HASHES],
|
||||
actions=[P._build_lite],
|
||||
)
|
||||
|
||||
|
||||
def task_docs():
|
||||
"""build the docs"""
|
||||
if P.TESTING_IN_CI:
|
||||
|
@ -720,10 +762,25 @@ def task_docs():
|
|||
],
|
||||
)
|
||||
|
||||
sphinx_deps = [
|
||||
P.DOCS_CONF,
|
||||
P.DOCS_FAVICON_ICO,
|
||||
P.OK_PIP_CHECK,
|
||||
*P.DOCS_SRC,
|
||||
]
|
||||
sphinx_task_deps = []
|
||||
|
||||
if P.LITE_PREFIX:
|
||||
sphinx_deps += [
|
||||
P.DEMO_HASHES,
|
||||
P.DEMO_ARCHIVE,
|
||||
]
|
||||
|
||||
yield dict(
|
||||
name="sphinx",
|
||||
doc="build the documentation site with sphinx",
|
||||
file_dep=[P.DOCS_CONF, P.DOCS_FAVICON_ICO, P.OK_PIP_CHECK, *P.DOCS_SRC],
|
||||
file_dep=sphinx_deps,
|
||||
task_dep=sphinx_task_deps,
|
||||
actions=[
|
||||
["sphinx-build", *P.SPHINX_ARGS, "-j8", "-b", "html", P.DOCS, P.DOCS_BUILD]
|
||||
],
|
||||
|
@ -735,7 +792,7 @@ def task_docs():
|
|||
def task_check():
|
||||
"""check built artifacts"""
|
||||
file_dep = [*P.DOCS_BUILD.rglob("*.html")]
|
||||
yield _ok(
|
||||
yield P._ok(
|
||||
dict(
|
||||
name="links",
|
||||
file_dep=[*file_dep, P.DOCS_BUILDINFO],
|
||||
|
@ -745,7 +802,7 @@ def task_check():
|
|||
"--check-anchors",
|
||||
"--check-links-ignore",
|
||||
"^https?://",
|
||||
*[p for p in file_dep if p.name != "schema.html"],
|
||||
*[p for p in file_dep if p.name not in ["schema.html"]],
|
||||
]
|
||||
],
|
||||
),
|
||||
|
@ -755,7 +812,7 @@ def task_check():
|
|||
|
||||
def task_provision():
|
||||
"""ensure the ipydrawio-export server has been provisioned with npm (ick)"""
|
||||
return _ok(
|
||||
return P._ok(
|
||||
dict(
|
||||
file_dep=[*P.OK_SERVEREXT.values()],
|
||||
actions=[
|
||||
|
@ -779,7 +836,7 @@ def _pytest(setup_py):
|
|||
def task_test():
|
||||
"""run tests"""
|
||||
if not P.TESTING_IN_CI:
|
||||
yield _ok(
|
||||
yield P._ok(
|
||||
dict(
|
||||
name="integrity",
|
||||
file_dep=[
|
||||
|
@ -797,7 +854,7 @@ def task_test():
|
|||
)
|
||||
|
||||
for pkg, setup in P.PY_SETUP.items():
|
||||
yield _ok(
|
||||
yield P._ok(
|
||||
dict(
|
||||
name=f"pytest:{pkg}",
|
||||
uptodate=[config_changed(dict(PYTEST_ARGS=P.PYTEST_ARGS))],
|
||||
|
@ -822,9 +879,9 @@ def task_test():
|
|||
]
|
||||
|
||||
if not P.TESTING_IN_CI:
|
||||
file_dep += [P.OK_ROBOT_DRYRUN, *P.OK_SERVEREXT.values()]
|
||||
file_dep += [P.OK_ROBOT_DRYRUN, P.DEMO_HASHES, *P.OK_SERVEREXT.values()]
|
||||
|
||||
yield _ok(
|
||||
yield P._ok(
|
||||
dict(
|
||||
name="robot",
|
||||
uptodate=[config_changed(dict(ATEST_ARGS=P.ATEST_ARGS))],
|
||||
|
@ -833,30 +890,3 @@ def task_test():
|
|||
),
|
||||
P.OK_ATEST,
|
||||
)
|
||||
|
||||
|
||||
# utilities
|
||||
def _echo_ok(msg):
|
||||
def _echo():
|
||||
print(msg, flush=True)
|
||||
return True
|
||||
|
||||
return _echo
|
||||
|
||||
|
||||
def _ok(task, ok):
|
||||
task.setdefault("targets", []).append(ok)
|
||||
task["actions"] = [
|
||||
lambda: [ok.exists() and ok.unlink(), True][-1],
|
||||
*task["actions"],
|
||||
lambda: [ok.parent.mkdir(exist_ok=True), ok.write_text("ok"), True][-1],
|
||||
]
|
||||
return task
|
||||
|
||||
|
||||
def _show(*args, **kwargs):
|
||||
for arg in args:
|
||||
print_(arg()) if callable(arg) else print_(arg)
|
||||
for kw, kwarg in kwargs.items():
|
||||
print_(rich.markdown.Markdown(f"# {kw}") if console else kw)
|
||||
print_(kwarg()) if callable(kwarg) else print_(kwarg)
|
||||
|
|
|
@ -54,6 +54,7 @@ zip_safe = False
|
|||
|
||||
install_requires =
|
||||
ipydrawio >=1.1.0
|
||||
jupyterlab ==3.*
|
||||
lxml
|
||||
pillow
|
||||
pypdf2
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
```bash
|
||||
mamba install -c conda-forge ipydrawio # recommended, or...
|
||||
conda install -c conda-forge ipydrawio # or...
|
||||
pip install ipydrawio
|
||||
pip install ipydrawio[all]
|
||||
```
|
||||
|
||||
## Features
|
||||
|
|
|
@ -53,10 +53,22 @@ include_package_data = True
|
|||
zip_safe = False
|
||||
|
||||
install_requires =
|
||||
ipywidgets >=7.6
|
||||
jupyterlab >=3,<4
|
||||
jupyterlab_widgets >=1
|
||||
ipywidgets >=7.6,<8
|
||||
|
||||
[options.extras_require]
|
||||
clean =
|
||||
lxml
|
||||
lab =
|
||||
jupyterlab ==3.*
|
||||
jupyterlab_widgets >=1
|
||||
all =
|
||||
%(clean)s
|
||||
%(lab)s
|
||||
test =
|
||||
%(all)s
|
||||
pytest
|
||||
pytest-console-scripts
|
||||
pytest-cov
|
||||
|
||||
[options.packages.find]
|
||||
where =
|
||||
|
|
|
@ -20,7 +20,12 @@ import traitlets as T
|
|||
from jupyter_core.application import JupyterApp, base_aliases, base_flags
|
||||
|
||||
from ._version import __version__
|
||||
from .utils import MX_CLEAN_ATTRS, clean_drawio_file
|
||||
|
||||
try:
|
||||
# the clean command isn't _critical_
|
||||
from .clean import MX_CLEAN_ATTRS, clean_drawio_file
|
||||
except ImportError: # pragma: no cover
|
||||
clean_drawio_file = None
|
||||
|
||||
|
||||
class BaseApp(JupyterApp):
|
||||
|
@ -31,54 +36,58 @@ class BaseApp(JupyterApp):
|
|||
return self.__doc__.splitlines()[0].strip()
|
||||
|
||||
|
||||
class CleanApp(BaseApp):
|
||||
"""clean drawio files"""
|
||||
if clean_drawio_file:
|
||||
|
||||
dio_files = T.Tuple()
|
||||
pretty = T.Bool(True, help="pretty-print the XML").tag(config=True)
|
||||
mx_attrs = T.Tuple(MX_CLEAN_ATTRS, help="attributes to clean").tag(config=True)
|
||||
indent = T.Int(2, help="if pretty-printing, the indent level").tag(config=True)
|
||||
tabs = T.Bool(False, help="indent with tabs instead of spaces").tag(config=True)
|
||||
class CleanApp(BaseApp):
|
||||
"""clean drawio files"""
|
||||
|
||||
flags = dict(
|
||||
**base_flags,
|
||||
**{
|
||||
"no-pretty": (
|
||||
{"CleanApp": {"pretty": False}},
|
||||
"Do not pretty-print the XML",
|
||||
),
|
||||
"tabs": (
|
||||
{"CleanApp": {"tabs": True}},
|
||||
"Indent with tabs instead of spaces",
|
||||
),
|
||||
}
|
||||
)
|
||||
aliases = dict(
|
||||
**base_aliases, **{"mx-attrs": "CleanApp.mx_attrs", "indent": "CleanApp.indent"}
|
||||
)
|
||||
dio_files = T.Tuple()
|
||||
pretty = T.Bool(True, help="pretty-print the XML").tag(config=True)
|
||||
mx_attrs = T.Tuple(MX_CLEAN_ATTRS, help="attributes to clean").tag(config=True)
|
||||
indent = T.Int(2, help="if pretty-printing, the indent level").tag(config=True)
|
||||
tabs = T.Bool(False, help="indent with tabs instead of spaces").tag(config=True)
|
||||
|
||||
def parse_command_line(self, argv=None):
|
||||
super().parse_command_line(argv)
|
||||
self.dio_files = [Path(p).resolve() for p in self.extra_args]
|
||||
flags = dict(
|
||||
**base_flags,
|
||||
**{
|
||||
"no-pretty": (
|
||||
{"CleanApp": {"pretty": False}},
|
||||
"Do not pretty-print the XML",
|
||||
),
|
||||
"tabs": (
|
||||
{"CleanApp": {"tabs": True}},
|
||||
"Indent with tabs instead of spaces",
|
||||
),
|
||||
}
|
||||
)
|
||||
aliases = dict(
|
||||
**base_aliases,
|
||||
**{"mx-attrs": "CleanApp.mx_attrs", "indent": "CleanApp.indent"}
|
||||
)
|
||||
|
||||
def start(self):
|
||||
for path in self.dio_files:
|
||||
clean_drawio_file(
|
||||
path,
|
||||
pretty=self.pretty,
|
||||
mx_attrs=self.mx_attrs,
|
||||
indent=self.indent,
|
||||
tabs=self.tabs,
|
||||
)
|
||||
def parse_command_line(self, argv=None):
|
||||
super().parse_command_line(argv)
|
||||
self.dio_files = [Path(p).resolve() for p in self.extra_args]
|
||||
|
||||
def start(self):
|
||||
for path in self.dio_files:
|
||||
clean_drawio_file(
|
||||
path,
|
||||
pretty=self.pretty,
|
||||
mx_attrs=self.mx_attrs,
|
||||
indent=self.indent,
|
||||
tabs=self.tabs,
|
||||
)
|
||||
|
||||
|
||||
class IPyDrawioApp(BaseApp):
|
||||
"""ipydrawio utilities"""
|
||||
|
||||
name = "ipydrawio"
|
||||
subcommands = dict(
|
||||
clean=(CleanApp, CleanApp.__doc__.splitlines()[0]),
|
||||
)
|
||||
subcommands = dict()
|
||||
|
||||
if clean_drawio_file:
|
||||
subcommands["clean"] = (CleanApp, CleanApp.__doc__.splitlines()[0])
|
||||
|
||||
|
||||
main = launch_instance = IPyDrawioApp.launch_instance
|
||||
|
|
|
@ -47,6 +47,12 @@ def run_tests(attempt=0, extra_args=None):
|
|||
if "--dryrun" in extra_args:
|
||||
runner = ["robot"]
|
||||
|
||||
try:
|
||||
__import__("jupyterlite")
|
||||
except Exception as err:
|
||||
print("skipping lite tests because", err)
|
||||
extra_args += ["--exclude", "app:lite"]
|
||||
|
||||
args = [
|
||||
*runner,
|
||||
*extra_args,
|
||||
|
@ -58,6 +64,8 @@ def run_tests(attempt=0, extra_args=None):
|
|||
f"OS:{P.PLATFORM}",
|
||||
"--variable",
|
||||
f"PY:{P.PY_MAJOR}",
|
||||
"--variable",
|
||||
f"DEMO:{P.DEMO}",
|
||||
"--randomize",
|
||||
"all",
|
||||
"--xunit",
|
||||
|
|
|
@ -17,9 +17,11 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
import json
|
||||
import os
|
||||
import platform
|
||||
import pprint
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
|
@ -27,7 +29,36 @@ import sys
|
|||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
|
||||
SKIPS = ["checkpoint", "pytest_cache"]
|
||||
print_ = pprint.pprint
|
||||
console = None
|
||||
|
||||
try:
|
||||
import rich.console
|
||||
import rich.markdown
|
||||
|
||||
console = rich.console.Console()
|
||||
print_ = console.print
|
||||
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
LITE_PREFIX = None
|
||||
SOURCE_DATE_EPOCH = None
|
||||
|
||||
try:
|
||||
__import__("jupyterlite.manager")
|
||||
LITE_PREFIX = "demo_"
|
||||
SOURCE_DATE_EPOCH = (
|
||||
subprocess.check_output(["git", "log", "-1", "--format=%ct"])
|
||||
.decode("utf-8")
|
||||
.strip()
|
||||
)
|
||||
except (ImportError, AttributeError, subprocess.CalledProcessError) as err:
|
||||
print_(err)
|
||||
pass
|
||||
|
||||
|
||||
SKIPS = ["checkpoint", "pytest_cache", "patched-environment"]
|
||||
|
||||
|
||||
def _clean(*paths_or_globs):
|
||||
|
@ -59,6 +90,7 @@ ENC = dict(encoding="utf-8")
|
|||
BUILDING_IN_CI = bool(json.loads(os.environ.get("BUILDING_IN_CI", "0")))
|
||||
TESTING_IN_CI = bool(json.loads(os.environ.get("TESTING_IN_CI", "0")))
|
||||
CI_ARTIFACT = os.environ.get("CI_ARTIFACT", "wheel")
|
||||
CI = bool(json.loads(os.environ.get("CI", "0")))
|
||||
|
||||
# test arg pass-throughs
|
||||
ATEST_ARGS = json.loads(os.environ.get("ATEST_ARGS", "[]"))
|
||||
|
@ -119,8 +151,8 @@ DIA_URLS = {
|
|||
|
||||
|
||||
# ci
|
||||
CI = ROOT / ".github"
|
||||
ENV_CI = CI / "environment.yml"
|
||||
GH = ROOT / ".github"
|
||||
ENV_GH = GH / "environment.yml"
|
||||
|
||||
# tools
|
||||
PY = ["python"]
|
||||
|
@ -298,6 +330,15 @@ SERVER_EXT = {
|
|||
if sorted(v.parent.glob("src/*/serverextension.py"))
|
||||
}
|
||||
|
||||
# demo
|
||||
DEMO = ROOT / "demo"
|
||||
DEMO_CONFIG = DEMO / "jupyter_config.json"
|
||||
DEMO_APPS = ["lab"]
|
||||
DEMO_BUILD = BUILD / "demo"
|
||||
DEMO_HASHES = DEMO_BUILD / "SHA256SUMS"
|
||||
DEMO_ARCHIVE = (
|
||||
DEMO_BUILD / f"""ipydrawio-lite-{JS_PKG_DATA["ipydrawio"]["version"]}.tgz"""
|
||||
)
|
||||
|
||||
# docs
|
||||
SPHINX_ARGS = json.loads(os.environ.get("SPHINX_ARGS", "[]"))
|
||||
|
@ -360,18 +401,19 @@ ALL_PY = [
|
|||
POSTBUILD_PY,
|
||||
DOCS_CONF,
|
||||
]
|
||||
ALL_YML = [
|
||||
*ROOT.glob("*.yml"),
|
||||
*CI.rglob("*.yml"),
|
||||
*BINDER.glob("*.yml"),
|
||||
*DOCS.rglob("*.yml"),
|
||||
]
|
||||
ALL_YML = _clean(
|
||||
ROOT.glob("*.yml"),
|
||||
GH.rglob("*.yml"),
|
||||
BINDER.glob("*.yml"),
|
||||
DOCS.rglob("*.yml"),
|
||||
)
|
||||
ALL_JSON = [
|
||||
*ROOT.glob("*.json"),
|
||||
*PACKAGES.glob("*/*.json"),
|
||||
*PACKAGES.glob("*/schema/*.json"),
|
||||
*ATEST.glob("fixtures/*.json"),
|
||||
*BINDER.glob("*.json"),
|
||||
*[p for p in DEMO.rglob("*.json") if "/_output/" not in str(p)],
|
||||
]
|
||||
ALL_DIO = [*DOCS_DIO, *IPJT_TMPL_DIO, *ATEST_DIO]
|
||||
ALL_MD = [*ROOT.glob("*.md"), *PACKAGES.glob("*/*.md"), *DOCS_MD]
|
||||
|
@ -391,6 +433,15 @@ ALL_HEADERS = _clean(
|
|||
ALL_YML,
|
||||
ALL_ROBOT,
|
||||
)
|
||||
ALL_DEMO_CONTENTS = [
|
||||
d
|
||||
for d in ALL_DIO
|
||||
if "test" not in str(d).lower()
|
||||
and ".doit" not in d.name
|
||||
and " " not in d.name
|
||||
and d.name not in ["A.dio"]
|
||||
]
|
||||
|
||||
ESLINTRC = PACKAGES / ".eslintrc.js"
|
||||
|
||||
RFLINT_OPTS = sum(
|
||||
|
@ -470,7 +521,7 @@ CMD_LAB = ["jupyter", "lab", "--no-browser", "--debug"]
|
|||
# conda building
|
||||
RECIPE = ROOT / "conda.recipe/meta.yaml"
|
||||
CONDA_BLD = BUILD / "conda-bld"
|
||||
CONDARC = CI / ".condarc"
|
||||
CONDARC = GH / ".condarc"
|
||||
# could be mambabuild
|
||||
CONDA_BUILDERER = os.environ.get("CONDA_BUILDERER", "build")
|
||||
CONDA_BUILD_ARGS = [
|
||||
|
@ -486,7 +537,7 @@ CONDA_PKGS = {
|
|||
}
|
||||
|
||||
# env inheritance
|
||||
ENV_INHERITS = {ENV_BINDER: [ENV_CI, ENV_DOCS], ENV_DOCS: [ENV_CI]}
|
||||
ENV_INHERITS = {ENV_BINDER: [ENV_GH, ENV_DOCS], ENV_DOCS: [ENV_GH]}
|
||||
|
||||
|
||||
def get_atest_stem(attempt=1, extra_args=None, browser=None):
|
||||
|
@ -698,6 +749,62 @@ def pip_check():
|
|||
return not len(lines)
|
||||
|
||||
|
||||
# utilities
|
||||
def _echo_ok(msg):
|
||||
def _echo():
|
||||
print(msg, flush=True)
|
||||
return True
|
||||
|
||||
return _echo
|
||||
|
||||
|
||||
def _ok(task, ok):
|
||||
task.setdefault("targets", []).append(ok)
|
||||
task["actions"] = [
|
||||
lambda: [ok.exists() and ok.unlink(), True][-1],
|
||||
*task["actions"],
|
||||
lambda: [ok.parent.mkdir(exist_ok=True), ok.write_text("ok"), True][-1],
|
||||
]
|
||||
return task
|
||||
|
||||
|
||||
def _show(*args, **kwargs):
|
||||
import rich.markdown
|
||||
|
||||
for arg in args:
|
||||
print_(arg()) if callable(arg) else print_(arg)
|
||||
for kw, kwarg in kwargs.items():
|
||||
print_(rich.markdown.Markdown(f"# {kw}") if console else kw)
|
||||
print_(kwarg()) if callable(kwarg) else print_(kwarg)
|
||||
|
||||
|
||||
def _copy_one(src, dest):
|
||||
if not src.exists():
|
||||
return False
|
||||
if not dest.parent.exists():
|
||||
dest.parent.mkdir(parents=True)
|
||||
if dest.exists():
|
||||
if dest.is_dir():
|
||||
shutil.rmtree(dest)
|
||||
else:
|
||||
dest.unlink()
|
||||
if src.is_dir():
|
||||
shutil.copytree(src, dest)
|
||||
else:
|
||||
shutil.copy2(src, dest)
|
||||
|
||||
|
||||
def _build_lite():
|
||||
lite = ["jupyter", "lite"]
|
||||
args = ["--source-date-epoch", SOURCE_DATE_EPOCH]
|
||||
|
||||
for act in ["build", "check", "archive"]:
|
||||
act_args = list(map(str, [*lite, act, *args]))
|
||||
if subprocess.call(act_args, cwd=DEMO) == 0:
|
||||
continue
|
||||
return False
|
||||
|
||||
|
||||
# Late environment hacks
|
||||
os.environ.update(
|
||||
CONDARC=str(CONDARC),
|
||||
|
|
Ładowanie…
Reference in New Issue