├── .projectignore ├── robotlab ├── setup.py ├── src │ └── robotlab │ │ ├── _version.py │ │ ├── icons │ │ ├── lab.icns │ │ ├── lab.ico │ │ ├── shell.ico │ │ ├── shell.icns │ │ ├── build_icons.sh │ │ ├── starter.svg │ │ ├── lab.svg │ │ ├── shell.svg │ │ └── master.svg │ │ ├── labapp.py │ │ ├── labextensionapp.py │ │ ├── __init__.py │ │ ├── tutorial.py │ │ ├── examples.py │ │ ├── shortcuts.py │ │ ├── launch.py │ │ └── paths.py ├── MANIFEST.in ├── README.md ├── setup.cfg └── LICENSE ├── recipes ├── robotframework │ ├── run_test.sh │ ├── run_test.bat │ ├── meta.yaml │ └── 70af9e3bab0217b0450d78c69e6c2ccb8f9c342d.patch ├── restinstance │ ├── 0001-setup-entry-point.patch │ ├── meta.yaml │ └── apache-2.0.txt ├── robotframework-whitelibrary │ ├── bld.bat │ ├── meta.yaml │ └── apache-2.0.txt ├── robotframework-jupyterlibrary │ ├── 001-lab-114-icons.patch │ └── meta.yaml ├── jupyter-starters │ └── meta.yaml ├── robotframework-seleniumscreenshots │ └── meta.yaml ├── pyshortcuts │ └── meta.yaml ├── robotkernel │ └── meta.yaml ├── robotframework-seleniumtestability │ └── meta.yaml └── robotlab │ ├── meta.yaml │ └── builder.py ├── constructor ├── ci ├── env-combine.yml ├── env-lab.yml ├── env-noarch.yml ├── env-main.yml ├── steps.restore.yml ├── steps.conda.yml ├── job.win.yml ├── job.lab.yml ├── job.noarch.yml ├── job.noarch-test.yml ├── job.min.yml ├── job.combine.yml ├── job.release.yml ├── job.main.yml └── job.selftest.yml ├── tests ├── library │ └── decolorize.py ├── acceptance │ ├── ExoRobot │ │ ├── __init__.robot │ │ └── 0_Install │ │ │ └── 0_Installer.robot │ ├── MiniRobot │ │ ├── __init__.robot │ │ └── 0_Install │ │ │ └── 0_Installer.robot │ └── RobotLab │ │ ├── 0_Install │ │ ├── 0_Installer.robot │ │ └── 1_Shortcuts.robot │ │ ├── 1_CLI │ │ ├── 20_tutorial.robot │ │ ├── 00_nbrobot.robot │ │ ├── __init__.robot │ │ ├── 30_extensions.robot │ │ └── 10_examples.robot │ │ ├── 2_Lab │ │ ├── __init__.robot │ │ ├── 00_Smoke_Test.robot │ │ ├── 10_IPython_Notebook.robot │ │ ├── 20_Robot_Notebook.robot │ │ ├── 30_Tutorial.robot │ │ └── 40_Examples.robot │ │ └── __init__.robot └── resources │ ├── Launch.robot │ ├── Lab.robot │ ├── Selectors.robot │ ├── CLI.robot │ ├── Cleanup.robot │ ├── Browser.robot │ └── Install.robot ├── .gitignore ├── scripts ├── combine.py ├── lint.py ├── integrity.py ├── __init__.py ├── build.py └── test.py ├── environment.yml ├── azure-pipelines.yml ├── attic └── robotframework-ride │ └── meta.yaml ├── LICENSE ├── anaconda-project.yml └── README.md /.projectignore: -------------------------------------------------------------------------------- 1 | *.ipynb 2 | -------------------------------------------------------------------------------- /robotlab/setup.py: -------------------------------------------------------------------------------- 1 | __import__("setuptools").setup() 2 | -------------------------------------------------------------------------------- /robotlab/src/robotlab/_version.py: -------------------------------------------------------------------------------- 1 | __version__ = "2020.01.0" 2 | -------------------------------------------------------------------------------- /recipes/robotframework/run_test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bi/env bash 2 | set -eux 3 | cd src/utest 4 | python run.py 5 | -------------------------------------------------------------------------------- /robotlab/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.md LICENSE 2 | recursive-include src/robotlab/icons *.ico *.icns 3 | -------------------------------------------------------------------------------- /constructor/RobotLab/post_install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | . "${PREFIX}/bin/activate" 3 | robotlab-shortcuts 4 | -------------------------------------------------------------------------------- /constructor/RobotLab/post_install.bat: -------------------------------------------------------------------------------- 1 | @echo on 2 | call "%PREFIX%\Scripts\activate.bat" "%PREFIX%" 3 | robotlab-shortcuts 4 | -------------------------------------------------------------------------------- /robotlab/src/robotlab/icons/lab.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robots-from-jupyter/robotlab/HEAD/robotlab/src/robotlab/icons/lab.icns -------------------------------------------------------------------------------- /robotlab/src/robotlab/icons/lab.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robots-from-jupyter/robotlab/HEAD/robotlab/src/robotlab/icons/lab.ico -------------------------------------------------------------------------------- /robotlab/src/robotlab/icons/shell.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robots-from-jupyter/robotlab/HEAD/robotlab/src/robotlab/icons/shell.ico -------------------------------------------------------------------------------- /robotlab/src/robotlab/icons/shell.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robots-from-jupyter/robotlab/HEAD/robotlab/src/robotlab/icons/shell.icns -------------------------------------------------------------------------------- /recipes/robotframework/run_test.bat: -------------------------------------------------------------------------------- 1 | @ECHO ON 2 | cd src\utest 3 | 4 | CALL python run.py || EXIT /B 1 5 | IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL% 6 | -------------------------------------------------------------------------------- /ci/env-combine.yml: -------------------------------------------------------------------------------- 1 | name: robotlab-combine 2 | 3 | channels: 4 | - https://conda.anaconda.org/conda-forge 5 | - https://conda.anaconda.org/anaconda 6 | 7 | dependencies: 8 | - robotframework 9 | -------------------------------------------------------------------------------- /tests/library/decolorize.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | ANSI_ESCAPE = re.compile(r'(?:\x1B[@-_]|[\x80-\x9F])[0-?]*[ -/]*[@-~]') 4 | 5 | 6 | def decolorize(line): 7 | return ANSI_ESCAPE.sub('', line) 8 | -------------------------------------------------------------------------------- /tests/acceptance/ExoRobot/__init__.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Suite Teardown Clean up the installation 3 | Force Tags os:${OS} in-product:${IN_PRODUCT} product:ExoRobot 4 | Resource ../../resources/Install.robot 5 | -------------------------------------------------------------------------------- /tests/acceptance/MiniRobot/__init__.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Suite Teardown Clean up the installation 3 | Force Tags os:${OS} in-product:${IN_PRODUCT} product:MiniRobot 4 | Resource ../../resources/Install.robot 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | _artifacts/ 3 | _cache/ 4 | .vscode/ 5 | *.egg-info/ 6 | *.ipynb_checkpoints/ 7 | *.pyc 8 | **/construct.yaml 9 | **/icons/*.png 10 | build/ 11 | constructor/.* 12 | dist/ 13 | envs/ 14 | robotkernel-*/ 15 | -------------------------------------------------------------------------------- /recipes/restinstance/0001-setup-entry-point.patch: -------------------------------------------------------------------------------- 1 | --- a/setup.py 2 | +++ b/setup.py 3 | @@ -58,5 +58,4 @@ 4 | package_dir={"": "src"}, 5 | packages=find_packages("src"), 6 | zip_safe=False, 7 | - entry_points={"console_scripts": ["robot = robot.run:run_cli"]}, 8 | ) 9 | -------------------------------------------------------------------------------- /ci/env-lab.yml: -------------------------------------------------------------------------------- 1 | name: robotlab-lab 2 | 3 | channels: 4 | - https://conda.anaconda.org/conda-forge 5 | - https://conda.anaconda.org/anaconda 6 | 7 | dependencies: 8 | - black 9 | - flake8 10 | - jupyterlab ==1.2.4 11 | - nodejs >=11,<12 12 | - python >=3.6,<3.7.0a0 13 | - robotframework-lint 14 | -------------------------------------------------------------------------------- /tests/acceptance/ExoRobot/0_Install/0_Installer.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Is the ExoRobot installer viable? 3 | Resource ../../../resources/Install.robot 4 | 5 | *** Test Cases *** 6 | Does the installer run? 7 | [Documentation] Will it run? 8 | Run the installer ExoRobot 9 | -------------------------------------------------------------------------------- /tests/acceptance/MiniRobot/0_Install/0_Installer.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Is the MiniRobot installer viable? 3 | Resource ../../../resources/Install.robot 4 | 5 | *** Test Cases *** 6 | Does the installer run? 7 | [Documentation] Will it run? 8 | Run the installer MiniRobot 9 | -------------------------------------------------------------------------------- /robotlab/src/robotlab/labapp.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from jupyterlab import labapp 3 | 4 | from . import patch_app_dir, patch_build_dir 5 | 6 | 7 | def main(): 8 | patch_app_dir(labapp.LabApp) 9 | patch_build_dir(labapp.LabBuildApp) 10 | return labapp.main() 11 | 12 | 13 | if __name__ == "__main__": 14 | sys.exit(main()) 15 | -------------------------------------------------------------------------------- /ci/env-noarch.yml: -------------------------------------------------------------------------------- 1 | name: robotlab-noarch 2 | 3 | channels: 4 | - https://conda.anaconda.org/anaconda 5 | - https://conda.anaconda.org/conda-forge 6 | 7 | dependencies: 8 | - conda >=4.8,<4.9.0a0 9 | - conda-build >=3.18.11,<3.19.0a0 10 | - conda-verify 11 | - python >=3.6,<3.7.0a0 12 | - python-libarchive-c 13 | - ripgrep 14 | -------------------------------------------------------------------------------- /robotlab/README.md: -------------------------------------------------------------------------------- 1 | # robotlab 2 | 3 | A pre-configured JupyterLab for productive Robot Framework authoring with 4 | robotkernel. 5 | 6 | ## Credits 7 | - Borrows heavily from [jupyterlab_delux][]. 8 | 9 | [jupyterlab_delux]: https://github.com/jonmmease/jupyterlab_delux 10 | [robotkernel]: https://github.com/robots-from-jupyter/robotkernel 11 | -------------------------------------------------------------------------------- /tests/acceptance/RobotLab/0_Install/0_Installer.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Is the RobotLab installer viable? 3 | Force Tags installer 4 | Resource ../../../resources/Install.robot 5 | 6 | *** Test Cases *** 7 | Does the installer run? 8 | [Documentation] Will it run? 9 | Run the installer RobotLab 10 | -------------------------------------------------------------------------------- /ci/env-main.yml: -------------------------------------------------------------------------------- 1 | name: robotlab-main 2 | 3 | channels: 4 | - https://conda.anaconda.org/anaconda 5 | - https://conda.anaconda.org/conda-forge 6 | 7 | dependencies: 8 | - conda >=4.8,<4.9.0a0 9 | - conda-build >=3.18.11,<3.19.0a0 10 | - conda-verify 11 | - constructor >=3,<3.1 12 | - pillow 13 | - python >=3.6,<3.7.0a0 14 | - python-libarchive-c 15 | - ripgrep 16 | -------------------------------------------------------------------------------- /robotlab/src/robotlab/labextensionapp.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from jupyterlab import labextensions, labapp 3 | 4 | from . import patch_app_dir, patch_build_dir 5 | 6 | 7 | def main(): 8 | patch_app_dir(labextensions.BaseExtensionApp) 9 | patch_build_dir(labapp.LabBuildApp) 10 | return labextensions.main() 11 | 12 | 13 | if __name__ == "__main__": 14 | sys.exit(main()) 15 | -------------------------------------------------------------------------------- /constructor/MiniRobot/construct.yaml.in: -------------------------------------------------------------------------------- 1 | name: MiniRobot 2 | version: {{ version }} 3 | company: Robots from Jupyter 4 | license_file: LICENSE.txt 5 | 6 | channels: 7 | - https://conda.anaconda.org/conda-forge 8 | - https://conda.anaconda.org/anaconda 9 | 10 | specs: 11 | - python >={{ py_min }},<{{ py_max }} 12 | - robotframework =={{ rf_version }} 13 | - conda =={{ conda_version }} 14 | -------------------------------------------------------------------------------- /robotlab/src/robotlab/icons/build_icons.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | for icon in lab shell; do 3 | for size in 16 32 48 128 256 512; do 4 | inkscape -z $icon.svg -e $icon-$size.png -w $size 5 | done 6 | 7 | convert $icon-512.png -define icon:auto-resize=256,128,64,48,32,16 $icon.ico 8 | png2icns $icon.icns $icon-16.png $icon-32.png $icon-48.png $icon-128.png $icon-256.png $icon-512.png 9 | done 10 | -------------------------------------------------------------------------------- /tests/acceptance/RobotLab/1_CLI/20_tutorial.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation robotlab-tutorial 3 | Force Tags app:robotlab-tutorial 4 | Resource ../../../resources/CLI.robot 5 | 6 | *** Test Cases *** 7 | Can I install the tutorial? 8 | [Documentation] Does robotlab-tutorial work? 9 | Check a RobotLab CLI command robotlab-tutorial check_dir=robotkernel-tutorial 10 | -------------------------------------------------------------------------------- /tests/acceptance/RobotLab/2_Lab/__init__.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Suite Setup Start New RobotLab Server 3 | Suite Teardown Clean Up After Lab Suite 4 | Test Teardown Clean Up After Lab Test 5 | Force Tags ui:lab 6 | Library JupyterLibrary 7 | Library Process 8 | Resource ../../../resources/Launch.robot 9 | Resource ../../../resources/Cleanup.robot 10 | -------------------------------------------------------------------------------- /tests/acceptance/RobotLab/1_CLI/00_nbrobot.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation nbrobot 3 | Force Tags app:nbrobot 4 | Resource ../../../resources/CLI.robot 5 | 6 | *** Test Cases *** 7 | Can I get help on nbrobot? 8 | [Documentation] Verify the nbrobot command returns help 9 | ${output} = Run nbrobot CLI --help ${251} 10 | Should Contain ${output} Robot Framework 11 | -------------------------------------------------------------------------------- /recipes/robotframework-whitelibrary/bld.bat: -------------------------------------------------------------------------------- 1 | @echo on 2 | set RFWL_URL=https://files.pythonhosted.org/packages/ff/e9/0e460d1d6609a6cda95dbd76192f0c828089e91fd52eac93dc22df7eda08/robotframework_whitelibrary-%PKG_VERSION%-py2.py3-none-any.whl 3 | set RFWL_SHA256=8e44bcf3db2a60858230129596e93b30b692f3657977b62c7174dacb890a7339 4 | 5 | call python -m pip install --disable-pip-version-check --no-deps %RFWL_URL% -vv 6 | if errorlevel 1 exit 1 7 | -------------------------------------------------------------------------------- /robotlab/src/robotlab/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from ._version import __version__ # noqa 4 | 5 | from .paths import ROBOTLAB_PATH 6 | 7 | 8 | def patch_app_dir(app_klass): 9 | path = str(ROBOTLAB_PATH) 10 | os.environ["JUPYTERLAB_DIR"] = path 11 | app_klass.app_dir.default_value = path 12 | return path 13 | 14 | 15 | def patch_build_dir(build_klass): 16 | build_klass.name.default_value = "RobotLab" 17 | -------------------------------------------------------------------------------- /scripts/combine.py: -------------------------------------------------------------------------------- 1 | from . import TEST_OUT, run 2 | 3 | 4 | def combine(): 5 | args = [ 6 | "python", 7 | "-m", 8 | "robot.rebot", 9 | "--name", 10 | "All", 11 | "--outputdir", 12 | str(TEST_OUT), 13 | "--output", 14 | "output.xml", 15 | ] + list(map(str, TEST_OUT.glob("*.robot.xml"))) 16 | 17 | return run(args) 18 | 19 | 20 | if __name__ == "__main__": 21 | combine() 22 | -------------------------------------------------------------------------------- /tests/acceptance/RobotLab/1_CLI/__init__.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation CLI features 3 | Suite Teardown Clean Up After CLI 4 | Force Tags ui:cli 5 | Library Process 6 | Resource ../../../resources/Cleanup.robot 7 | 8 | *** Keywords *** 9 | Clean Up After CLI 10 | [Documentation] Ensure any dangling processes or files are cleaned 11 | Run Keyword If All Tests Passed Clean Up Examples and Tutorials 12 | Terminate All Processes 13 | -------------------------------------------------------------------------------- /environment.yml: -------------------------------------------------------------------------------- 1 | name: _robots_from_jupyter 2 | 3 | channels: 4 | - https://conda.anaconda.org/anaconda 5 | - https://conda.anaconda.org/conda-forge 6 | 7 | dependencies: 8 | - conda >=4.8,<4.9.0a0 9 | - conda-build >=3.18.11,<3.19.0a0 10 | - conda-verify 11 | - constructor >=3,<3.1 12 | - firefox >=68.0.2,<69 13 | - geckodriver 14 | - pillow 15 | - python >=3.6,<3.7.0a0 16 | - python-libarchive-c 17 | - ripgrep 18 | - robotframework 19 | - robotframework-seleniumlibrary >=4.1.0,<5 20 | -------------------------------------------------------------------------------- /tests/acceptance/RobotLab/2_Lab/00_Smoke_Test.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Check the basics of Robot Lab 3 | Library JupyterLibrary 4 | Resource ../../../resources/Browser.robot 5 | 6 | *** Test Cases *** 7 | Does RobotLab Load? 8 | [Documentation] Does the Lab launcher show up with a Robot Framework entry? 9 | Wait until keyword succeeds 3 x 1 s Open RobotLab 10 | Page Should Contain Robot Framework 11 | Capture Page Screenshot smoke__00_smoke_test.png 12 | -------------------------------------------------------------------------------- /ci/steps.restore.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | name: Linux 3 | 4 | steps: 5 | - task: DownloadPipelineArtifact@0 6 | inputs: 7 | artifactName: noarch conda packages $(Build.BuildId) 8 | targetPath: _artifacts/conda-bld/noarch 9 | displayName: restore noarch packages 10 | 11 | - ${{ if eq(parameters.name, 'Windows') }}: 12 | - task: DownloadPipelineArtifact@0 13 | inputs: 14 | artifactName: windows conda packages $(Build.BuildId) 15 | targetPath: _artifacts/conda-bld/win-64 16 | displayName: restore windows packages 17 | -------------------------------------------------------------------------------- /tests/acceptance/RobotLab/0_Install/1_Shortcuts.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Do Desktop shortcuts get installed? 3 | Resource ../../../resources/Install.robot 4 | 5 | *** Test Cases *** 6 | Are the shortcuts created? 7 | [Documentation] Does it cut short? 8 | Variable Should Exist ${ROBOTLAB SHORTCUT} msg=Should have defined shortcut during install 9 | # TODO: dump the create shortcuts in the env and check them 10 | # ${home} = Set Variable If ${IN_PRODUCT} %{HOME} ${FAKE HOME} 11 | # Wait Until Created ${home}${/}Desktop${/}${ROBOTLAB SHORTCUT} 12 | -------------------------------------------------------------------------------- /robotlab/src/robotlab/tutorial.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | import shutil 3 | import sys 4 | 5 | from .paths import TUTORIAL_NAME, TUTORIAL 6 | 7 | 8 | def copy_robotkernel_tutorial(dest=None): 9 | dest = (Path(dest) if dest else Path(".")).resolve() 10 | shutil.copytree(TUTORIAL, dest / TUTORIAL_NAME) 11 | if not dest.exists(): 12 | dest.mkdir(parents=True) 13 | print("\n".join(sorted(map(str, (dest / TUTORIAL_NAME).glob("*"))))) 14 | return 0 15 | 16 | 17 | if __name__ == "__main__": 18 | dest = Path(sys.argv(1)) if len(sys.argv) > 1 else None 19 | sys.exit(copy_robotkernel_tutorial(dest)) 20 | -------------------------------------------------------------------------------- /robotlab/src/robotlab/examples.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | import shutil 3 | import sys 4 | 5 | from .paths import EXAMPLES, EXAMPLES_NAME 6 | 7 | 8 | def copy_robotkernel_examples(dest=None): 9 | dest = (Path(dest) if dest else Path(".")).resolve() 10 | shutil.copytree(EXAMPLES, dest / EXAMPLES_NAME) 11 | if not dest.exists(): 12 | dest.mkdir(parents=True) 13 | 14 | print("\n".join(sorted(map(str, (dest / EXAMPLES_NAME).glob("*"))))) 15 | return 0 16 | 17 | 18 | if __name__ == "__main__": 19 | dest = Path(sys.argv(1)) if len(sys.argv) > 1 else None 20 | sys.exit(copy_robotkernel_examples(dest)) 21 | -------------------------------------------------------------------------------- /constructor/RobotLab/construct.yaml.in: -------------------------------------------------------------------------------- 1 | name: RobotLab 2 | version: {{ version }} 3 | company: Robots from Jupyter 4 | post_install: post_install.bat [win] 5 | post_install: post_install.sh [unix] 6 | ignore_duplicate_files: True 7 | license_file: ../../LICENSE 8 | 9 | channels_remap: 10 | - src: {{ build_channel }} 11 | dest: https://conda.anaconda.org/conda-forge 12 | 13 | channels: 14 | - {{ build_channel }} 15 | - https://conda.anaconda.org/anaconda 16 | - https://conda.anaconda.org/conda-forge 17 | - https://conda.anaconda.org/msys2 [win] 18 | 19 | specs: 20 | - python >={{ py_min }},<{{ py_max }} 21 | - robotlab =={{ version }} 22 | - python.app [osx] 23 | -------------------------------------------------------------------------------- /tests/acceptance/RobotLab/__init__.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Suite Setup Set Screenshot Directory ${OUTPUT DIR}${/}screenshots 3 | Suite Teardown Clean up the RobotLab installation 4 | Force Tags os:${OS} in-product:${IN_PRODUCT} product:RobotLab 5 | Variables ../../../scripts/__init__.py 6 | Resource ../../resources/Install.robot 7 | Library JupyterLibrary 8 | 9 | *** Keywords *** 10 | Clean up the RobotLab installation 11 | [Documentation] Clean up browser and Jupyter stuff, then the installation 12 | Terminate All Jupyter Servers 13 | Clean up the installation 14 | Run Keyword If All Tests Passed Clean Up Examples and Tutorials 15 | -------------------------------------------------------------------------------- /tests/resources/Launch.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Work with the RobotLab server 3 | Library OperatingSystem 4 | Library JupyterLibrary 5 | Library String 6 | Library Process 7 | 8 | *** Keywords *** 9 | Start New RobotLab Server 10 | [Documentation] Try to start the RobotLab server 11 | Should Not Be Empty ${OS} msg=Needs an OS 12 | Should Not Be Empty ${PRODUCT DIR} msg=Needs a RobotLab installation 13 | Should Not Be Empty ${PRODUCT PATH ENV} msg=Needs a RobotLab environment 14 | ${proc} = Start New Jupyter Server ${ROBOTLAB CMD} env:PATH=${PRODUCT PATH ENV} stdout=${OUTPUT DIR}${/}nbserver.log 15 | -------------------------------------------------------------------------------- /ci/steps.conda.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | name: Linux 3 | envPath: ci/env-noarch.yml 4 | 5 | steps: 6 | - ${{ if eq(parameters.name, 'Linux') }}: 7 | - bash: echo "##vso[task.prependpath]$CONDA/bin" 8 | displayName: conda $PATH 9 | 10 | - ${{ if eq(parameters.name, 'MacOSX') }}: 11 | - bash: echo "##vso[task.prependpath]$CONDA/bin" 12 | displayName: conda $PATH 13 | 14 | - bash: sudo chown -R $USER $CONDA 15 | displayName: own conda 16 | 17 | - ${{ if eq(parameters.name, 'Windows') }}: 18 | - powershell: Write-Host "##vso[task.prependpath]$env:CONDA\Scripts" 19 | displayName: conda %PATH% 20 | 21 | - script: conda env update -n base --file ${{ parameters.envPath }} --quiet 22 | displayName: install conda environment 23 | -------------------------------------------------------------------------------- /robotlab/src/robotlab/shortcuts.py: -------------------------------------------------------------------------------- 1 | from pprint import pprint 2 | import sys 3 | 4 | import pyshortcuts.utils 5 | 6 | from .paths import HERE, ICON_PATH 7 | 8 | 9 | def make_shortcuts(): 10 | script = str(HERE / "launch.py") 11 | name = "RobotLab" 12 | print("Making RobotLab shortcut in $HOME...") 13 | print("", pyshortcuts.utils.get_homedir()) 14 | scut = pyshortcuts.make_shortcut( 15 | script=script, 16 | name=name, 17 | terminal=True, 18 | description="Launch RobotLab in Firefox in your $HOME", 19 | icon=ICON_PATH, 20 | ) 21 | "" 22 | print("Shortcut created...") 23 | pprint(scut.__dict__) 24 | return 0 25 | 26 | 27 | if __name__ == "__main__": 28 | sys.exit(make_shortcuts()) 29 | -------------------------------------------------------------------------------- /recipes/robotframework-jupyterlibrary/001-lab-114-icons.patch: -------------------------------------------------------------------------------- 1 | --- src/JupyterLibrary/clients/jupyterlab/Selectors.robot 2018-12-17 23:29:45.000000000 -0500 2 | +++ src/JupyterLibrary/clients/jupyterlab/Selectors.robot 2019-09-18 23:05:13.135509964 -0400 3 | @@ -12,8 +12,8 @@ 4 | ${JLAB CSS BUSY KERNEL} .jp-Toolbar-kernelStatus.jp-FilledCircleIcon 5 | ${JLAB CSS CMD INPUT} .p-CommandPalette-input 6 | ${JLAB CSS CMD ITEM} .p-CommandPalette-item 7 | -${JLAB CSS ICON ADD} .jp-AddIcon 8 | -${JLAB CSS ICON RUN} .jp-RunIcon 9 | +${JLAB CSS ICON ADD} [data-icon="add"] 10 | +${JLAB CSS ICON RUN} [data-icon="run"] 11 | ${JLAB CSS NB TOOLBAR} .jp-NotebookPanel-toolbar 12 | ${JLAB CSS SIDEBAR TAB} .jp-SideBar .p-TabBar-tab 13 | ${JLAB CSS SPINNER} .jp-Spinner 14 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | batch: true 3 | branches: 4 | include: 5 | - master 6 | - refs/tags/v* 7 | 8 | pr: [master] 9 | 10 | variables: 11 | ROBOTLAB_VERSION: 2020.01.0 12 | PYTHONUNBUFFERED: 1 13 | 14 | jobs: 15 | # group one: simple conda/webpack builds, validation 16 | - template: ci/job.noarch.yml 17 | - template: ci/job.win.yml 18 | - template: ci/job.lab.yml 19 | # - template: ci/job.min.yml 20 | 21 | # group two: build installers, verify conda builds 22 | - template: ci/job.noarch-test.yml 23 | - template: ci/job.main.yml 24 | 25 | # group three: acceptance testing 26 | - template: ci/job.selftest.yml 27 | 28 | # group four: reporting, etc 29 | - template: ci/job.combine.yml 30 | - template: ci/job.release.yml 31 | -------------------------------------------------------------------------------- /ci/job.win.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | vmImage: vs2017-win2016 3 | activate: call activate && 4 | 5 | jobs: 6 | - job: CondaWindows 7 | condition: succeeded() 8 | pool: 9 | vmImage: ${{ parameters.vmImage }} 10 | 11 | steps: 12 | - template: steps.conda.yml 13 | parameters: 14 | name: Windows 15 | 16 | - script: ${{ parameters.activate }} python -m scripts.build conda --no-test pyshortcuts robotframework-whitelibrary 17 | displayName: build win packages 18 | 19 | - task: PublishPipelineArtifact@0 20 | displayName: publish windows packages 21 | inputs: 22 | targetPath: _artifacts/conda-bld/win-64 23 | artifactName: Windows Conda Packages $(Build.BuildId) 24 | condition: succeeded() 25 | -------------------------------------------------------------------------------- /ci/job.lab.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - job: Lab 3 | pool: 4 | vmImage: ubuntu-16.04 5 | 6 | steps: 7 | - template: steps.conda.yml 8 | parameters: 9 | envPath: ci/env-lab.yml 10 | 11 | - script: python -m scripts.integrity 12 | displayName: check integrity 13 | 14 | - script: python -m scripts.lint 15 | displayName: lint 16 | 17 | - script: python -m scripts.build lab 18 | displayName: build lab 19 | 20 | - script: rm -rf _artifacts/app_dir/staging 21 | displayName: clean lab cruft 22 | 23 | - task: PublishPipelineArtifact@0 24 | displayName: publish jupyterlab package 25 | inputs: 26 | targetPath: _artifacts/app_dir 27 | artifactName: robotlab app_dir $(Build.BuildId) 28 | condition: succeeded() 29 | -------------------------------------------------------------------------------- /constructor/ExoRobot/construct.yaml.in: -------------------------------------------------------------------------------- 1 | name: ExoRobot 2 | version: {{ version }} 3 | company: Robots from Jupyter 4 | license_file: LICENSE.txt 5 | 6 | channels_remap: 7 | - src: {{ build_channel }} 8 | dest: https://conda.anaconda.org/conda-forge 9 | 10 | channels: 11 | - {{ build_channel }} 12 | - https://conda.anaconda.org/anaconda 13 | - https://conda.anaconda.org/conda-forge 14 | 15 | channels: 16 | - https://conda.anaconda.org/conda-forge 17 | - https://conda.anaconda.org/anaconda 18 | 19 | specs: 20 | - python >={{ py_min }},<{{ py_max }} 21 | - robotframework =={{ rf_version }} 22 | - conda =={{ conda_version }} 23 | # other first-party 24 | - robotframework-ride 25 | # extra library/doc dependencies 26 | - docutils 27 | - lxml 28 | - pyte 29 | - pyyaml 30 | - wxpython 31 | - pillow 32 | -------------------------------------------------------------------------------- /ci/job.noarch.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - job: CondaNoarch 3 | pool: 4 | vmImage: ubuntu-16.04 5 | 6 | steps: 7 | - template: steps.conda.yml 8 | 9 | - script: |- 10 | python -m scripts.build conda \ 11 | --no-test \ 12 | jupyter-starters \ 13 | robotframework \ 14 | restinstance \ 15 | robotframework-jupyterlibrary \ 16 | robotframework-seleniumscreenshots \ 17 | robotframework-seleniumtestability \ 18 | robotkernel 19 | displayName: build noarch packages 20 | 21 | - task: PublishPipelineArtifact@0 22 | displayName: publish noarch packages 23 | inputs: 24 | targetPath: _artifacts/conda-bld/noarch 25 | artifactName: noarch conda packages $(Build.BuildId) 26 | condition: succeeded() 27 | -------------------------------------------------------------------------------- /tests/resources/Lab.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Library JupyterLibrary 3 | 4 | *** Keywords *** 5 | Start a new Notebook 6 | [Arguments] ${kernel} 7 | [Documentation] Convenience method around 8 | [Tags] robot:no-dry-run 9 | Execute JupyterLab Command Close All 10 | Launch a new JupyterLab Document ${kernel} Notebook 11 | Wait Until JupyterLab Kernel Is Idle 12 | 13 | The Robot Popup Should Contain 14 | [Arguments] ${prefix} ${document} ${msg} 15 | [Documentation] With an open Robot Notebook, take a look at the log or report 16 | Click Link ${document} 17 | Sleep 1s 18 | Select Window Jupyter ${document} 19 | Page Should Contain ${msg} 20 | Capture Page Screenshot ${prefix}_10_${document.lower()}.png 21 | Close Window 22 | Select Window RobotLab 23 | -------------------------------------------------------------------------------- /recipes/jupyter-starters/meta.yaml: -------------------------------------------------------------------------------- 1 | {% set name = "jupyter_starters" %} 2 | {% set version = "0.2.2a0" %} 3 | 4 | package: 5 | name: {{ name | replace("_", "-") }} 6 | version: {{ version }} 7 | 8 | source: 9 | url: https://pypi.io/packages/source/{{ name[0] }}/{{ name }}/{{ name }}-{{ version }}.tar.gz 10 | sha256: 8773e03f8e05532197aa16f4a634bb3d1f8fe858658a7f20bf64879fd78e367f 11 | 12 | build: 13 | noarch: python 14 | number: 0 15 | script: "{{ PYTHON }} -m pip install . -vv" 16 | 17 | requirements: 18 | host: 19 | - python >=3.6 20 | - pip 21 | run: 22 | - python >=3.6 23 | - notebook >=5.3 24 | 25 | test: 26 | imports: 27 | - jupyter_starters 28 | 29 | about: 30 | home: https://github.com/deathbeds/jupyterlab-starters 31 | license: BSD-3-Clause 32 | license_family: BSD 33 | license_file: LICENSE 34 | summary: 'Parameterized file and directory starters for JupyterLab.' 35 | -------------------------------------------------------------------------------- /recipes/robotframework-whitelibrary/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: '{% set name = "robotframework-whitelibrary" %}{{ name }}' 3 | version: '{% set version = "1.6.0" %}{{ version }}' 4 | 5 | build: 6 | number: 0 7 | skip: true # [not win] 8 | 9 | requirements: 10 | host: 11 | - pip 12 | - python 13 | - pythonnet 14 | run: 15 | - robotframework 16 | - pythonnet 17 | - python 18 | test: 19 | imports: 20 | - WhiteLibrary 21 | 22 | about: 23 | home: https://github.com/Omenia/robotframework-whitelibrary 24 | license: Apache-2.0 25 | license_family: Apache 26 | license_file: apache-2.0.txt 27 | summary: WhiteLibrary is a Robot Framework library for automating Windows GUI. 28 | doc_url: http://omenia.github.io/robotframework-whitelibrary/keywords.html 29 | description: > 30 | It is a wrapper for TestStack.White automation framework, which is based on 31 | Microsoft UI Automation API (UIA). 32 | -------------------------------------------------------------------------------- /tests/acceptance/RobotLab/2_Lab/10_IPython_Notebook.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Try out IPython Notebooks 3 | Library JupyterLibrary 4 | Resource ../../../resources/Browser.robot 5 | Resource ../../../resources/Lab.robot 6 | 7 | *** Test Cases *** 8 | Can RobotLab make an IPython Notebook? 9 | [Documentation] Try a basic IPython Notebook 10 | ${prefix} = Set Variable ipython_ 11 | Open RobotLab 12 | Start a new Notebook Python 3 13 | Capture Page Screenshot ${prefix}_01_notebook.png 14 | Add and Run JupyterLab Code Cell print("Hello" + " World") 15 | Capture Page Screenshot ${prefix}_02_execute.png 16 | Wait Until Page Contains Hello World timeout=10s 17 | Capture Page Screenshot ${prefix}_03_execute_result.png 18 | Execute JupyterLab Command Save Notebook 19 | Sleep 2s 20 | Capture Page Screenshot ${prefix}_09_save.png 21 | -------------------------------------------------------------------------------- /ci/job.noarch-test.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | platforms: 3 | - name: Linux 4 | vmImage: ubuntu-16.04 5 | activate: "" 6 | - name: MacOSX 7 | vmImage: macos-10.13 8 | activate: "" 9 | - name: Windows 10 | vmImage: vs2017-win2016 11 | activate: call activate && 12 | 13 | jobs: 14 | - ${{ each platform in parameters.platforms }}: 15 | - job: CondaNoarchTest${{ platform.name }} 16 | pool: 17 | vmImage: ${{ platform.vmImage }} 18 | condition: succeeded() 19 | dependsOn: 20 | - CondaNoarch 21 | - CondaWindows 22 | 23 | steps: 24 | - template: steps.restore.yml 25 | parameters: 26 | name: ${{ platform.name }} 27 | 28 | - template: steps.conda.yml 29 | parameters: 30 | name: ${{ platform.name }} 31 | 32 | - script: ${{ platform.activate }} python -m scripts.test conda 33 | displayName: test prebuilt packages 34 | -------------------------------------------------------------------------------- /tests/resources/Selectors.robot: -------------------------------------------------------------------------------- 1 | *** Variables *** 2 | ${XP LAUNCH SECTION} xpath://h2[contains(@class, 'jp-Launcher-sectionTitle')][text() = 'Starters'] 3 | ${CSS LAUNCH CARD} css:[data-category\="Starters"] 4 | ${CSS LAUNCH CARD TUTORIAL} ${CSS LAUNCH CARD}\[title\="Tutorial for Robot Framework on Jupyter"] 5 | ${CSS LAUNCH CARD EXAMPLES} ${CSS LAUNCH CARD}\[title\="Miscellanous examples of using RobotKernel"] 6 | ${XP FILE TREE ITEM} xpath://span[contains(@class, 'jp-DirListing-itemText')] 7 | ${XP FILE TREE TUTORIAL} ${XP FILE TREE ITEM}\[text() = 'tutorial'] 8 | ${XP FILE TREE TUTORIAL 00} ${XP FILE TREE ITEM}\[text() = '00 Keyboard Shortcuts.ipynb'] 9 | ${XP FILE TREE EXAMPLE} ${XP FILE TREE ITEM}\[text() = 'robotkernel-examples'] 10 | ${XP FILE TREE EXAMPLE OPENCV} ${XP FILE TREE ITEM}\[text() = 'OpenCV.ipynb'] 11 | ${CSS NOTEBOOK SAVE} css:[data-icon="save"] 12 | ${JP STATUS BAR} id:jp-bottom-panel 13 | ${CRUMBS HOME} css:.jp-BreadCrumbs-home 14 | -------------------------------------------------------------------------------- /attic/robotframework-ride/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: '{% set name = "robotframework-ride" %}{{ name }}' 3 | version: '{% set version = "1.7.4b2" %}{{ version }}' 4 | 5 | source: 6 | url: https://pypi.io/packages/source/{{ name[0] }}/{{ name }}/{{ name }}-{{ version }}.tar.gz 7 | sha256: 40b67134573883b34de186bd9d4d2ee582a5d7451b5ccae4d2f84a876c44cd80 8 | 9 | build: 10 | noarch: python 11 | number: 0 12 | script: {{ PYTHON }} -m pip install --no-deps -vv . 13 | entry_points: 14 | - ride = robotide:main 15 | 16 | requirements: 17 | host: 18 | - pip 19 | - python 20 | run: 21 | - pygments 22 | - pypubsub 23 | - python 24 | - wxpython 25 | - docutils >=0.9 26 | - robotframework 27 | 28 | test: 29 | imports: 30 | - robotide 31 | - robotide.robotapi 32 | 33 | about: 34 | home: https://github.com/robotframework/RIDE 35 | license: Apache-2.0 36 | license_family: Apache 37 | license_file: LICENSE.txt 38 | summary: Test data editor for Robot Framework 39 | -------------------------------------------------------------------------------- /scripts/lint.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from . import ROOT, run 3 | 4 | 5 | PY_SRC = [str(ROOT / "robotlab"), str(ROOT / "scripts")] 6 | RF_SRC = list(map(str, (ROOT / "tests").rglob("*.robot"))) 7 | 8 | 9 | def black(): 10 | return run(["black", "-l79"] + PY_SRC) 11 | 12 | 13 | def tidy(): 14 | return run([sys.executable, "-m", "robot.tidy", "--inplace"] + RF_SRC) 15 | 16 | 17 | def flake8(): 18 | return run(["flake8", "--ignore", "E203,W503"] + PY_SRC) 19 | 20 | 21 | def rflint(): 22 | return run( 23 | [ 24 | "rflint", 25 | "--configure", 26 | "TooManyTestSteps:20", 27 | "--configure", 28 | "TooFewTestSteps:0", 29 | "--configure", 30 | "TooFewKeywordSteps:0", 31 | "--configure", 32 | "LineTooLong:200", 33 | ] 34 | + RF_SRC 35 | ) 36 | 37 | 38 | if __name__ == "__main__": 39 | assert not black() and not tidy() and not flake8() and not rflint() 40 | sys.exit(0) 41 | -------------------------------------------------------------------------------- /tests/acceptance/RobotLab/1_CLI/30_extensions.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation robotlab-extension 3 | Force Tags app:robotlab-extension 4 | Resource ../../../resources/CLI.robot 5 | Variables ../../../../scripts/__init__.py 6 | Library ../../../library/decolorize.py 7 | 8 | *** Test Cases *** 9 | Can I list extensions? 10 | [Documentation] Does robotlab-extension list work? 11 | ${output} = Check a RobotLab CLI command robotlab-extension list 12 | Extensions Should Be Installed ${output} ${LABEXTENSIONS} 13 | 14 | *** Keywords *** 15 | Extensions Should Be Installed 16 | [Arguments] ${output} ${extensions} 17 | [Documentation] Check that some JupyterLab extensions are installed 18 | ${cleaned} = Decolorize ${output.replace(" ", "").lower()} 19 | FOR ${spec} IN @{extensions} 20 | ${ext} = Set Variable ${spec.rsplit('@', 1)} 21 | Should Contain ${cleaned.lower()} ${ext[0]}v${ext[1]}enabledok 22 | END 23 | -------------------------------------------------------------------------------- /robotlab/src/robotlab/launch.py: -------------------------------------------------------------------------------- 1 | """ 2 | Perform a proper conda activate and launch robotlab 3 | """ 4 | 5 | import subprocess 6 | import os 7 | import sys 8 | import signal 9 | from pathlib import Path 10 | from tempfile import TemporaryDirectory 11 | 12 | from robotlab.paths import ACTIVATE, LAUNCH_CMD, LAUNCH_SCRIPT 13 | 14 | 15 | def launch_robotlab(lab_args=None): 16 | lab_cmd = " ".join([LAUNCH_CMD] + (lab_args or [])) 17 | 18 | with TemporaryDirectory() as td: 19 | tdp = Path(td) 20 | script = tdp / LAUNCH_SCRIPT 21 | lines = ACTIVATE + [lab_cmd] 22 | script.write_text(os.linesep.join(lines)) 23 | script.chmod(0o755) 24 | print("Launching RobotLab") 25 | print(script.read_text(), "\n") 26 | proc = subprocess.Popen([str(script)], cwd=os.path.expanduser("~")) 27 | try: 28 | proc.wait() 29 | except KeyboardInterrupt: 30 | os.killpg(os.getpgid(proc.pid), signal.SIGTERM) 31 | 32 | 33 | if __name__ == "__main__": 34 | launch_robotlab(sys.argv[1:]) 35 | -------------------------------------------------------------------------------- /scripts/integrity.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from . import ROOT, RECIPE_DIR, ROBOTLAB_DIR, SCRIPTS_DIR, TEST_DIR 4 | 5 | 6 | META_PATTERN = r""" set version = "([\d\.rc]+)" """ 7 | 8 | VERSIONS = { 9 | ROOT / "azure-pipelines.yml": r"ROBOTLAB_VERSION: ([\d\.rc]+)", 10 | RECIPE_DIR / "robotlab" / "meta.yaml": META_PATTERN, 11 | ROBOTLAB_DIR / "setup.cfg": r"version = ([\d\.rc]+)", 12 | ROBOTLAB_DIR 13 | / "src" 14 | / "robotlab" 15 | / "_version.py": r"""__version__ = "([\d\.rc]+)""", 16 | SCRIPTS_DIR / "__init__.py": r"""ROBOTLAB_VERSION", "([\d\.rc]+)""", 17 | TEST_DIR 18 | / "resources" 19 | / "Install.robot": r"\$\{INSTALLER VERSION\}\s+([\d\.rc]+)", 20 | } 21 | 22 | 23 | def ensure_integrity(): 24 | versions = {} 25 | for path, pattern in VERSIONS.items(): 26 | print(path.relative_to(ROOT)) 27 | versions[path] = re.findall(pattern, path.read_text())[0] 28 | print("\t", versions[path]) 29 | 30 | assert len(set(versions.values())) == 1, versions 31 | 32 | 33 | if __name__ == "__main__": 34 | ensure_integrity() 35 | -------------------------------------------------------------------------------- /recipes/robotframework-seleniumscreenshots/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: '{% set name = "robotframework-seleniumscreenshots" %}{{ name }}' 3 | version: '{% set version = "0.9.5" %}{{ version }}' 4 | 5 | source: 6 | url: https://pypi.io/packages/source/{{ name[0] }}/{{ name }}/{{ name }}-{{ version }}.tar.gz 7 | sha256: 400f3c2213578d1e249216170cd1dd1e86999492d9e731a030beca0d87181b17 8 | 9 | build: 10 | noarch: python 11 | number: 0 12 | script: {{ PYTHON }} -m pip install --no-deps -vvv . 13 | 14 | requirements: 15 | host: 16 | - pip 17 | - python 18 | run: 19 | - python 20 | - robotframework >=3.0.2 21 | - robotframework-SeleniumLibrary>=3.2.0 22 | 23 | test: 24 | imports: 25 | - SeleniumScreenshots 26 | 27 | about: 28 | home: https://github.com/datakurre/robotframework-seleniumscreenshots 29 | license: BSD-3-Clause 30 | license_family: BSD 31 | license_file: LICENSE 32 | summary: Robot Framework keyword library for capturing annotated screenshots with SeleniumLibrary 33 | doc_url: https://datakurre.github.io/robotframework-seleniumscreenshots 34 | -------------------------------------------------------------------------------- /tests/acceptance/RobotLab/2_Lab/20_Robot_Notebook.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Try out Robot Notebooks 3 | Library JupyterLibrary 4 | Resource ../../../resources/Browser.robot 5 | Resource ../../../resources/Lab.robot 6 | 7 | *** Test Cases *** 8 | Can RobotLab make a Robot Notebook? 9 | [Documentation] Try a basic Robot Notebook 10 | ${prefix} = Set Variable robot_ 11 | Open RobotLab 12 | Start a new Notebook Robot Framework 13 | Capture Page Screenshot ${prefix}_01_notebook.png 14 | Add and Run JupyterLab Code Cell | *Test Case* |${\n}| Hello |${\n}| | Log | Hello World 15 | Capture Page Screenshot ${prefix}_02_execute.png 16 | Sleep 3s 17 | Wait Until JupyterLab Kernel Is Idle 18 | Capture Page Screenshot ${prefix}_03_execute_result.png 19 | The Robot Popup Should Contain ${prefix} Log 1 passed, 0 failed 20 | The Robot Popup Should Contain ${prefix} Report All tests passed 21 | Execute JupyterLab Command Save Notebook 22 | Sleep 2s 23 | Capture Page Screenshot ${prefix}_09_save.png 24 | -------------------------------------------------------------------------------- /tests/acceptance/RobotLab/1_CLI/10_examples.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation robotlab-examples 3 | Force Tags app:robotlab-examples 4 | Resource ../../../resources/CLI.robot 5 | Library Process 6 | 7 | *** Variables *** 8 | ${NBCONVERT} jupyter nbconvert --execute --ExecutePreprocessor.timeout=600 9 | 10 | *** Test Cases *** 11 | Can I install the examples? 12 | [Documentation] Does robotlab-examples work? 13 | [Tags] example:opencv 14 | Check a RobotLab CLI command robotlab-examples check_dir=robotkernel-examples 15 | 16 | Can I run the examples? 17 | [Documentation] Will they nbconvert? 18 | [Tags] example:opencv 19 | ${log} = Set Variable ${OUTPUT DIR}${/}robotlab-example-nbconvert-opencv.log 20 | ${proc} = Run Process ${ACTIVATE} && ${NBCONVERT} OpenCV.ipynb shell=True cwd=${OUTPUT DIR}${/}robotkernel-examples stdout=${log} stderr=STDOUT 21 | ... env:PS1=[:|] 22 | Should Be Equal As Numbers ${proc.rc} 0 23 | Copy File ${OUTPUT DIR}${/}robotkernel-examples${/}OpenCV.html ${OUTPUT DIR}${/}nbconvert-OpenCV.html 24 | -------------------------------------------------------------------------------- /recipes/robotframework-jupyterlibrary/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: '{% set name = "robotframework-jupyterlibrary" %}{{ name }}' 3 | version: '{% set version = "0.2.0" %}{{ version }}' 4 | 5 | source: 6 | url: https://pypi.io/packages/source/{{ name[0] }}/{{ name }}/{{ name }}-{{ version }}.tar.gz 7 | sha256: 63bb7bd94bb21fbd6f88a640b605d51728bc48a1a9aebbe27ee033c218a5aa03 8 | patches: 9 | - 001-lab-114-icons.patch 10 | 11 | build: 12 | noarch: python 13 | number: 0 14 | script: {{ PYTHON }} -m pip install -vv . 15 | 16 | requirements: 17 | host: 18 | - pip 19 | - python 20 | run: 21 | - pillow 22 | - python 23 | - robotframework >=3.1 24 | - robotframework-seleniumlibrary >=4.1.0,<5 25 | - six 26 | 27 | test: 28 | imports: 29 | - JupyterLibrary 30 | 31 | about: 32 | home: https://robotframework-jupyterlibrary.rtfd.io 33 | license: BSD-3-Clause 34 | license_family: BSD 35 | license_file: LICENSE 36 | summary: A Robot Framework library for automating (testing of) Jupyter end-user applications and extensions 37 | dev_url: https://github.com/robots-from-jupyter/robotframework-jupyterlibrary 38 | -------------------------------------------------------------------------------- /recipes/pyshortcuts/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: '{% set name = "pyshortcuts" %}{{ name }}' 3 | version: '{% set version = "1.4" %}{{ version }}' 4 | 5 | source: 6 | url: https://pypi.io/packages/source/{{ name[0] }}/{{ name }}/{{ name }}-{{ version }}.tar.gz 7 | sha256: 503820fce779cf42e9b52e4674f5ef0b1672930d662401af53a6a73d07360a8d 8 | 9 | build: 10 | number: 0 11 | script: {{ PYTHON }} -m pip install . --no-deps -vv 12 | entry_points: 13 | - pyshortcut = pyshortcuts:shortcut_cli 14 | 15 | requirements: 16 | host: 17 | - pip 18 | - python 19 | run: 20 | - six 21 | - python 22 | - pywin32 # [win] 23 | 24 | test: 25 | # TODO: some issues currently with wx.__version__ 26 | # requires: 27 | # - wxpython 28 | imports: 29 | - pyshortcuts 30 | - pyshortcuts.darwin 31 | - pyshortcuts.linux 32 | - pyshortcuts.windows 33 | # - pyshortcuts.wxgui 34 | 35 | commands: 36 | - pyshortcut --help 37 | 38 | about: 39 | home: https://github.com/newville/pyshortcuts 40 | license: MIT 41 | license_file: LICENSE 42 | summary: create desktop shortcuts to python scripts on Windows, Mac, or Linux 43 | -------------------------------------------------------------------------------- /recipes/robotkernel/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: '{% set name = "robotkernel" %}{{ name }}' 3 | version: '{% set version = "1.3.0" %}{{ version }}' 4 | 5 | source: 6 | url: https://pypi.io/packages/source/{{ name[0] }}/{{ name }}/{{ name }}-{{ version }}.tar.gz 7 | sha256: 8401e9bee8df473e586a1607c2b50c628dd01493ac258569f56720e345360019 8 | 9 | build: 10 | noarch: python 11 | number: 0 12 | script: {{ PYTHON }} -m pip install --no-deps -vv . 13 | entry_points: 14 | - nbrobot = robotkernel.nbreader:robot 15 | - nblibdoc = robotkernel.nbreader:libdoc 16 | 17 | requirements: 18 | host: 19 | - pip 20 | - python 21 | run: 22 | - docutils 23 | - ipykernel 24 | - lunr 25 | - nbformat 26 | - pillow 27 | - pygments 28 | - python 29 | - robotframework >=3.1 30 | 31 | test: 32 | imports: 33 | - robotkernel 34 | commands: 35 | - jupyter kernelspec list 36 | 37 | about: 38 | home: https://github.com/robots-from-jupyter/robotkernel 39 | license: BSD-3-Clause 40 | license_family: BSD 41 | license_file: LICENSE 42 | summary: Robot Framework IPython kernel for Jupyter Notebook and JupyterLab 43 | -------------------------------------------------------------------------------- /recipes/robotframework-seleniumtestability/meta.yaml: -------------------------------------------------------------------------------- 1 | {% set name = "robotframework-seleniumtestability" %} 2 | {% set version = "0.0.15" %} 3 | 4 | package: 5 | name: {{ name }} 6 | version: {{ version }} 7 | 8 | source: 9 | url: https://pypi.io/packages/source/{{ name[0] }}/{{ name }}/{{ name }}-{{ version }}.tar.gz 10 | sha256: a49df9eb970f95794ab6af12b8a51312340d8349e7b92bf2b59021898b40e1c0 11 | 12 | build: 13 | number: 0 14 | noarch: python 15 | script: 16 | - {{ PYTHON }} -m pip install . --no-deps --ignore-installed -vvv 17 | 18 | requirements: 19 | host: 20 | - pip 21 | - python 22 | run: 23 | - furl 24 | - python 25 | - robotframework-seleniumlibrary >=4.0.0 26 | - wrapt 27 | 28 | test: 29 | imports: 30 | - SeleniumTestability 31 | - SeleniumTestability.javascript 32 | - SeleniumTestability.listener 33 | - SeleniumTestability.logger 34 | - SeleniumTestability.plugin 35 | - SeleniumTestability.types 36 | 37 | about: 38 | home: https://github.com/rasjani/robotframework-seleniumtestability 39 | license: Apache-2.0 40 | license_file: LICENSE 41 | license_family: Apache 42 | summary: Extension for SeleniumLibrary that provides manual and automatic waiting for asyncronous events like fetch, xhr, etc. 43 | -------------------------------------------------------------------------------- /recipes/restinstance/meta.yaml: -------------------------------------------------------------------------------- 1 | package: 2 | name: '{% set name = "RESTinstance" %}{{ name|lower }}' 3 | version: '{% set version = "1.0.2" %}{{ version }}' 4 | 5 | source: 6 | url: https://pypi.io/packages/source/{{ name[0] }}/{{ name }}/{{ name }}-{{ version }}.tar.gz 7 | sha256: c241e44e51c7a793c7c5ca0476caac2b703cc78da8041ab05ded965ce49bc187 8 | patches: 9 | - 0001-setup-entry-point.patch 10 | 11 | build: 12 | noarch: python 13 | number: 0 14 | script: {{ PYTHON }} -m pip install --no-deps -vv . 15 | 16 | requirements: 17 | build: 18 | - patch 19 | host: 20 | - pip 21 | - python 22 | run: 23 | - python 24 | - flex-swagger >=6.13.2 25 | - genson >=1.0.1 26 | - jsonpath-ng >=1.4.3 27 | - jsonschema >=3.0.0a3 28 | - pygments >=2.2.0 29 | - pytz >=2018.5 30 | - requests >=2.20.0 31 | - rfc3987 >=1.3.8 32 | - robotframework >=2.9 33 | - strict-rfc3339 >=0.7 34 | - tzlocal >=1.5.1 35 | 36 | test: 37 | imports: 38 | - REST 39 | 40 | about: 41 | home: https://asyrjasalo.github.io/RESTinstance 42 | license: Apache-2.0 43 | license_family: Apache 44 | license_file: apache-2.0.txt 45 | summary: Robot Framework test library for (RESTful) JSON APIs 46 | dev_url: https://github.com/asyrjasalo/RESTinstance 47 | -------------------------------------------------------------------------------- /tests/resources/CLI.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Keywords for CLIs we ship 3 | Library Process 4 | Library OperatingSystem 5 | 6 | *** Variables *** 7 | ${NEXT CLI LOG} ${0} 8 | 9 | *** Keywords *** 10 | Check a RobotLab CLI Command 11 | [Arguments] ${cmd} ${check_dir}=${EMPTY} ${rc}=${0} 12 | [Documentation] Run a command in the robotlab environment 13 | ${logs} = Set Variable ${OUTPUT DIR}${/}cli 14 | Create Directory ${logs} 15 | ${log} = Set Variable ${logs}${/}${NEXT CLI LOG}-${cmd.split()[0]}.log 16 | Set Global Variable ${NEXT CLI LOG} ${NEXT CLI LOG.__add__(1)} 17 | ${proc} = Run Process ${ACTIVATE} && ${cmd} shell=True cwd=${OUTPUT DIR} stdout=${log} stderr=STDOUT 18 | ... env:PS1=[:|] 19 | Should Be Equal As Numbers ${proc.rc} ${rc} 20 | Run Keyword If "${check_dir}" Directory Should Not Be Empty ${OUTPUT DIR}${/}${check_dir} 21 | ${output} = Get File ${log} 22 | [Return] ${output} 23 | 24 | Run nbrobot CLI 25 | [Arguments] ${args} ${rc}=${0} 26 | [Documentation] Run nbrobot and write the output to a log file 27 | ${output} = Check a RobotLab CLI Command nbrobot ${args} rc=${rc} 28 | [Return] ${output} 29 | -------------------------------------------------------------------------------- /robotlab/src/robotlab/paths.py: -------------------------------------------------------------------------------- 1 | """ Paths 2 | 3 | These will probably only work with the like-versioned RobotLab distribution 4 | """ 5 | from pathlib import Path 6 | import sys 7 | 8 | import platform 9 | 10 | HERE = Path(__file__).parent 11 | 12 | PREFIX = Path(sys.prefix).resolve() 13 | PYTHON_EXE = Path(sys.executable) 14 | 15 | ROBOTLAB_PATH = PREFIX / "share" / "jupyter" / "robotlab" 16 | 17 | PLATFORM = platform.system().lower() 18 | WIN = PLATFORM == "windows" 19 | OSX = PLATFORM == "darwin" 20 | SCRIPT_EXT = "bat" if WIN else "sh" 21 | 22 | ICON_EXT = "icns" if OSX else "ico" 23 | ICON_PATH = str(HERE / "icons" / f"lab.{ICON_EXT}") 24 | 25 | BIN_DIR = Path(sys.prefix, *(["Scripts"] if WIN else ["bin"])) 26 | 27 | BAT_ACTIVATE = [ 28 | f'call "{BIN_DIR}\\activate.bat" "{PREFIX}" || call activate "{PREFIX}"' 29 | ] 30 | 31 | SH_ACTIVATE = [ 32 | "#!" + "/usr/bin/env bash", 33 | f'. "{BIN_DIR}/activate" "{PREFIX}" || . activate "{PREFIX}"', 34 | ] 35 | 36 | ACTIVATE = BAT_ACTIVATE if WIN else SH_ACTIVATE 37 | BROWSER = f"--browser=firefox" 38 | 39 | LAUNCH_CMD = f"python -m robotlab.labapp {BROWSER}" 40 | LAUNCH_SCRIPT = f"launch_robotlab.{SCRIPT_EXT}" 41 | 42 | TUTORIAL_NAME = "robotkernel-tutorial" 43 | TUTORIAL = PREFIX / "var" / "www" / TUTORIAL_NAME 44 | 45 | EXAMPLES_NAME = "robotkernel-examples" 46 | EXAMPLES = PREFIX / "var" / "www" / EXAMPLES_NAME 47 | -------------------------------------------------------------------------------- /ci/job.min.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | products: 3 | - MiniRobot 4 | platforms: 5 | - name: Linux 6 | vmImage: ubuntu-16.04 7 | activate: "" 8 | - name: MacOSX 9 | vmImage: macos-10.13 10 | activate: "" 11 | - name: Windows 12 | vmImage: vs2017-win2016 13 | activate: call activate && 14 | 15 | jobs: 16 | - ${{ each product in parameters.products }}: 17 | - ${{ each platform in parameters.platforms }}: 18 | - job: ${{ product }}${{ platform.name }}Build 19 | condition: succeeded() 20 | pool: 21 | vmImage: ${{ platform.vmImage }} 22 | 23 | steps: 24 | - template: steps.conda.yml 25 | parameters: 26 | name: ${{ platform.name }} 27 | envPath: ci/env-main.yml 28 | 29 | - script: ${{ platform.activate }} python -m scripts.build constructor ${{ product }} 30 | displayName: build installer 31 | 32 | - ${{ if eq(parameters.name, 'MacOSX') }}: 33 | - script: chmod -R 777 _artifacts 34 | displayName: fix artifact permissions 35 | 36 | - task: PublishPipelineArtifact@1 37 | displayName: publish installer 38 | inputs: 39 | targetPath: _artifacts/constructor 40 | artifactName: ${{ product }} for ${{ platform.name }} $(Build.BuildId) 41 | condition: succeeded() 42 | -------------------------------------------------------------------------------- /robotlab/setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = robotlab 3 | version = 2020.01.0 4 | description = A pre-configured JupyterLab for demonstrating robotkernel 5 | long_description = file: README.md 6 | url = https://github.com/robots-from-jupyter/robotlab 7 | author = Nick Bollweg 8 | author_email = nick.bollweg@gmail.com 9 | license = BSD-3-Clause 10 | keywords = 11 | Interactive 12 | Interpreter 13 | Shell 14 | Testing 15 | Web 16 | Jupyter 17 | JupyterLab 18 | classifiers = 19 | Framework :: Jupyter 20 | Intended Audience :: Developers 21 | Intended Audience :: Information Technology 22 | License :: OSI Approved :: BSD License 23 | Programming Language :: Python 24 | Programming Language :: Python :: 3.6 25 | Programming Language :: Python :: 3 :: Only 26 | Topic :: Software Development :: Quality Assurance 27 | Topic :: Software Development :: Testing 28 | 29 | [options.entry_points] 30 | console_scripts = 31 | robotlab = robotlab.labapp:main 32 | robotlab-extension = robotlab.labextensionapp:main 33 | robotlab-shortcuts = robotlab.shortcuts:make_shortcuts 34 | robotlab-examples = robotlab.examples:copy_robotkernel_examples 35 | robotlab-tutorial = robotlab.tutorial:copy_robotkernel_tutorial 36 | 37 | [options] 38 | install_requires = 39 | jupyterlab 40 | package_dir = 41 | = src 42 | packages = find: 43 | include_package_data = True 44 | zip_safe = False 45 | 46 | [options.packages.find] 47 | where = 48 | src 49 | -------------------------------------------------------------------------------- /ci/job.combine.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | name: Linux 3 | vmImage: ubuntu-16.04 4 | githubConnection: release-robots-from-jupyter 5 | repositoryName: robots-from-jupyter/robotlab 6 | platforms: 7 | - Linux 8 | - MacOSX 9 | - Windows 10 | products: 11 | - RobotLab 12 | # - MiniRobot 13 | # - ExoRobot 14 | constructors: _artifacts/constructor 15 | 16 | jobs: 17 | - job: Combine 18 | dependsOn: 19 | - ${{ each platform in parameters.platforms }}: 20 | - ${{ each product in parameters.products }}: 21 | - ${{ product }}${{ platform }}Test 22 | condition: always() 23 | pool: 24 | vmImage: ubuntu-16.04 25 | steps: 26 | - template: steps.conda.yml 27 | parameters: 28 | envPath: ci/env-combine.yml 29 | 30 | - ${{ each platform in parameters.platforms }}: 31 | - ${{ each product in parameters.products }}: 32 | - task: DownloadPipelineArtifact@0 33 | condition: always() 34 | inputs: 35 | artifactName: ${{ product }} ${{ platform }} Output $(Build.BuildId) 36 | targetPath: _artifacts/test_output 37 | displayName: restore ${{ product }} ${{ platform }} output 38 | 39 | - script: python -m scripts.combine 40 | condition: always() 41 | displayName: combine outputs 42 | 43 | - task: PublishPipelineArtifact@1 44 | condition: always() 45 | displayName: publish combined output 46 | inputs: 47 | targetPath: _artifacts/test_output 48 | artifactName: All Robot Output $(Build.BuildId) 49 | -------------------------------------------------------------------------------- /ci/job.release.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | githubConnection: release-robots-from-jupyter 3 | repositoryName: robots-from-jupyter/robotlab 4 | platforms: 5 | - Linux 6 | - MacOSX 7 | - Windows 8 | products: 9 | - RobotLab 10 | # - MiniRobot 11 | # - ExoRobot 12 | constructors: _artifacts/constructor 13 | 14 | jobs: 15 | - job: Deploy 16 | pool: 17 | vmImage: ubuntu-16.04 18 | dependsOn: 19 | - ${{ each platform in parameters.platforms }}: 20 | - CondaNoarchTest${{ platform }} 21 | - ${{ each product in parameters.products }}: 22 | - ${{ product }}${{ platform }}Test 23 | condition: and(succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v')) 24 | steps: 25 | - ${{ each product in parameters.products }}: 26 | - ${{ each platform in parameters.platforms }}: 27 | - task: DownloadPipelineArtifact@0 28 | displayName: fetch ${{ product }} ${{ platform }} Installer 29 | inputs: 30 | artifactName: ${{ product }} For ${{ platform }} $(Build.BuildId) 31 | targetPath: ${{ parameters.constructors }} 32 | - script: find . 33 | displayName: list files before release 34 | - script: cd ${{ parameters.constructors }} && sha256sum * >> SHA256SUMS 35 | displayName: build hashes 36 | - task: GithubRelease@0 37 | inputs: 38 | githubConnection: ${{ parameters.githubConnection }} 39 | repositoryName: ${{ parameters.repositoryName }} 40 | assets: ${{ parameters.constructors }}/* 41 | isDraft: true 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2020, Robots from Jupyter 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /tests/resources/Cleanup.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Library OperatingSystem 3 | Library Process 4 | Resource ./Browser.robot 5 | 6 | *** Keywords *** 7 | Clean up the installation 8 | [Documentation] Clean out the installed product 9 | Sleep 5s 10 | Terminate All Processes 11 | Sleep 5s 12 | Terminate All Processes kill=True 13 | Sleep 5s 14 | Run Keyword If not ${IN_PRODUCT} Remove Directory ${PRODUCT DIR} recursive=True 15 | Sleep 5s 16 | Run Keyword If not ${IN_PRODUCT} Remove Directory ${PRODUCT DIR} recursive=True 17 | 18 | Clean Up Examples and Tutorials 19 | [Documentation] These are large, and don't prove much if they work 20 | Remove Directory ${OUTPUT DIR}${/}robotkernel-examples recursive=${True} 21 | Remove Directory ${OUTPUT DIR}${/}robotkernel-tutorials recursive=${True} 22 | 23 | Clean Up After Lab Suite 24 | [Documentation] Really try to make sure Lab is cleaned up 25 | Open RobotLab 26 | Clean Up After Lab Test 27 | Really Close All Browsers 28 | Terminate All Jupyter Servers 29 | Sleep 5s 30 | Run Keyword and Ignore Error Terminate All Processes 31 | Sleep 7s 32 | Run Keyword and Ignore Error Terminate All Processes kill=${True} 33 | 34 | Clean Up After Lab Test 35 | [Documentation] Try to make sure Lab is cleaned up 36 | Wait Until Keyword Succeeds 2x 1s Execute JupyterLab Command Shutdown All Kernels 37 | Wait Until Keyword Succeeds 2x 1s Execute JupyterLab Command Reset Application State 38 | -------------------------------------------------------------------------------- /robotlab/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, Robots from Jupyter 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /robotlab/src/robotlab/icons/starter.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /tests/resources/Browser.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Library JupyterLibrary 3 | Library OperatingSystem 4 | Resource Install.robot 5 | 6 | *** Variables *** 7 | ${NEXT GECKO LOG} ${0} 8 | ${GECKO LOGS} ${OUTPUT DIR}${/}geckodriver 9 | 10 | *** Keywords *** 11 | Open RobotLab 12 | [Arguments] ${nbserver}=${None} ${url}=${EMPTY} &{configuration} 13 | [Documentation] Open RobotLab with the bundled Firefox, served from the 14 | ... given (or most-recently-started) ``nbserver`` or ``url``, then wait 15 | ... for the splash screen. 16 | ... Extra ``configuration`` is passed on to SeleniumLibrary's *Create WebDriver*. 17 | ${geckodriver} = Get RobotLab GeckoDriver 18 | ${firefox} = Get RobotLab Firefox 19 | Create Directory ${GECKO LOGS} 20 | Create WebDriver Firefox executable_path=${geckodriver} firefox_binary=${firefox} service_log_path=${GECKO LOGS}${/}${NEXT GECKO LOG}.log &{configuration} 21 | Set Global Variable ${NEXT GECKO LOG} ${NEXT GECKO LOG.__add__(1)} 22 | ${nbserver_url} = Run Keyword If not "${url}" Get Jupyter Server URL ${nbserver} 23 | ${token} = Run Keyword If not "${url}" Get Jupyter Server Token ${nbserver} 24 | Set Global Variable ${TOKEN} ${token} 25 | ${final_url} = Set Variable If "${url}" ${url} ${nbserver_url}lab?token=${token} 26 | Go To about:blank 27 | Set Window Size 1920 1080 28 | Go To ${final_url} 29 | Wait Until Keyword Succeeds 5x 5s Wait for JupyterLab Splash Screen 30 | 31 | Really Close All Browsers 32 | [Documentation] We might open lots of browsers... this might help 33 | Run keyword And Ignore Error Handle Alert timeout=1s 34 | Run Keyword and Ignore Error Close All Browsers 35 | Run keyword And Ignore Error Handle Alert timeout=1s 36 | -------------------------------------------------------------------------------- /ci/job.main.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | products: 3 | - RobotLab 4 | # - ExoRobot 5 | platforms: 6 | - name: Linux 7 | vmImage: ubuntu-16.04 8 | activate: "" 9 | - name: MacOSX 10 | vmImage: macos-10.13 11 | activate: "" 12 | - name: Windows 13 | vmImage: vs2017-win2016 14 | activate: call activate && 15 | jobs: 16 | - ${{ each product in parameters.products }}: 17 | - ${{ each platform in parameters.platforms }}: 18 | - job: ${{ product }}${{ platform.name }}Build 19 | pool: 20 | vmImage: ${{ platform.vmImage }} 21 | condition: succeeded() 22 | dependsOn: 23 | - CondaNoarch 24 | - ${{ if eq(product, 'RobotLab') }}: 25 | - Lab 26 | - ${{ if eq(platform.name, 'Windows') }}: 27 | - CondaWindows 28 | 29 | steps: 30 | - template: steps.restore.yml 31 | parameters: 32 | name: ${{ platform.name }} 33 | 34 | - ${{ if eq(product, 'RobotLab') }}: 35 | - task: DownloadPipelineArtifact@0 36 | inputs: 37 | artifactName: robotlab app_dir $(Build.BuildId) 38 | targetPath: _artifacts/app_dir 39 | displayName: restore jupyterlab 40 | 41 | - template: steps.conda.yml 42 | parameters: 43 | name: ${{ platform.name }} 44 | envPath: ci/env-main.yml 45 | 46 | - ${{ if eq(product, 'RobotLab') }}: 47 | - script: ${{ platform.activate }} python -m scripts.build conda 48 | displayName: build/test remaining packages 49 | 50 | - script: ${{ platform.activate }} python -m scripts.build constructor ${{ product }} 51 | displayName: build installer 52 | 53 | - ${{ if eq(platform.name, 'MacOSX') }}: 54 | - script: chmod -R 777 _artifacts 55 | displayName: fix artifact permissions 56 | 57 | - task: PublishPipelineArtifact@1 58 | displayName: publish installer 59 | inputs: 60 | targetPath: _artifacts/constructor 61 | artifactName: ${{ product }} for ${{ platform.name }} $(Build.BuildId) 62 | condition: succeeded() 63 | -------------------------------------------------------------------------------- /scripts/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | from pathlib import Path 4 | import platform 5 | 6 | 7 | PLATFORM = platform.system().lower() 8 | 9 | SCRIPTS_DIR = Path(__file__).parent 10 | SCRIPT_EXT = "bat" if platform == "windows" else "sh" 11 | ROOT = SCRIPTS_DIR.parent 12 | 13 | ARTIFACTS = ROOT / "_artifacts" 14 | CACHE = ROOT / "_cache" 15 | 16 | CONSTRUCT_DIR = ROOT / "constructor" 17 | 18 | RECIPE_DIR = ROOT / "recipes" 19 | CONDA_CACHE = CACHE / "conda-bld" 20 | 21 | CONSTRUCT_CACHE = CACHE / "constructor" 22 | 23 | TEST_DIR = ROOT / "tests" 24 | 25 | CONDA_OUT = ARTIFACTS / "conda-bld" 26 | CONSTRUCT_OUT = ARTIFACTS / "constructor" 27 | TEST_OUT = ARTIFACTS / "test_output" 28 | LAB_OUT = ARTIFACTS / "app_dir" 29 | 30 | ROBOTLAB_DIR = ROOT / "robotlab" 31 | README = ROOT / "README.md" 32 | 33 | # for easy overriding in CI 34 | VERSION = os.environ.get("ROBOTLAB_VERSION", "2020.01.0") 35 | CONDA_VERSION = os.environ.get("CONDA_VERSION", "4.8.0") 36 | RF_VERSION = os.environ.get("RF_VERSION", "3.1.2") 37 | PY_MAX = os.environ.get("PY_MAX", "3.7.0a0") 38 | PY_MIN = os.environ.get("PY_MIN", "3.6") 39 | LABEXTENSIONS = os.environ.get( 40 | "LABEXTENSIONS", 41 | """ 42 | @deathbeds/jupyterlab-starters@0.2.2a0 43 | @jupyter-widgets/jupyterlab-manager@1.1.0 44 | @jupyterlab/toc@1.0.1 45 | jupyterlab_robotmode@2.4.0 46 | jupyterlab-jupytext@1.1.0 47 | """.replace( 48 | "\n", " " 49 | ), 50 | ).split() 51 | 52 | CONDA_BUILD_ARGS = [ 53 | "conda-build", 54 | "--output-folder", 55 | CONDA_OUT, 56 | "--cache-dir", 57 | CONDA_CACHE, 58 | "-c", 59 | "https://conda.anaconda.org/conda-forge", 60 | "-c", 61 | "https://conda.anaconda.org/anaconda", 62 | "--python", 63 | PY_MIN, 64 | ] 65 | 66 | CONSTRUCTOR_ARGS = [ 67 | "constructor", 68 | "--verbose", 69 | "--cache-dir", 70 | str(CONSTRUCT_CACHE), 71 | "--output-dir", 72 | str(CONSTRUCT_OUT), 73 | ] 74 | 75 | 76 | def run(args, **kwargs): 77 | """ Probably unneccessary "convenience" wrapper 78 | """ 79 | str_args = list(map(str, args)) 80 | print("===\n", " ".join(str_args), "\n===") 81 | p = subprocess.Popen(str_args, **kwargs) 82 | 83 | try: 84 | p.wait() 85 | except KeyboardInterrupt as err: 86 | p.kill() 87 | p.wait() 88 | raise err 89 | 90 | return p.returncode 91 | -------------------------------------------------------------------------------- /recipes/robotframework/meta.yaml: -------------------------------------------------------------------------------- 1 | {% set name = "robotframework" %} 2 | {% set version = "3.1.2" %} 3 | 4 | package: 5 | name: {{ name }} 6 | version: {{ version }} 7 | 8 | source: 9 | - url: https://pypi.io/packages/source/{{ name[0] }}/{{ name }}/{{ name }}-{{ version }}.zip 10 | sha256: f10dd7c0c8c7962a4f80dd1e026b5db731b9391bc6e1f9ebb96d685eb1230dbc 11 | folder: dist 12 | - url: https://github.com/robotframework/robotframework/archive/v{{ version }}.tar.gz 13 | sha256: 1a8769bc40d334814b3eeb1dc945624c292f210fb4f2ff033a21cba4e9360864 14 | folder: src 15 | patches: 16 | - 70af9e3bab0217b0450d78c69e6c2ccb8f9c342d.patch 17 | 18 | 19 | build: 20 | number: 0 21 | noarch: python 22 | script: 23 | - cd dist 24 | - {{ PYTHON }} -m pip install . --no-deps --ignore-installed -vvv 25 | entry_points: 26 | - robot = robot.run:run_cli 27 | - rebot = robot.rebot:rebot_cli 28 | 29 | requirements: 30 | host: 31 | - pip 32 | - python 33 | run: 34 | - python 35 | 36 | test: 37 | requires: 38 | - docutils 39 | - enum34 # [py<35] 40 | - lxml 41 | - pillow 42 | - pygments 43 | - pyyaml 44 | source_files: 45 | - src/utest 46 | - src/atest 47 | - src/README.rst 48 | imports: 49 | - robot 50 | - robot.api 51 | - robot.conf 52 | - robot.htmldata 53 | - robot.libdocpkg 54 | - robot.libraries 55 | - robot.model 56 | - robot.output 57 | - robot.output.console 58 | - robot.parsing 59 | - robot.reporting 60 | - robot.result 61 | - robot.running 62 | - robot.running.arguments 63 | - robot.running.timeouts 64 | - robot.utils 65 | - robot.variables 66 | - robot.writer 67 | commands: 68 | - robot --version || [[ $? == 251 ]] # [unix] 69 | - rebot --version || [[ $? == 251 ]] # [unix] 70 | 71 | 72 | about: 73 | home: http://robotframework.org 74 | license: Apache-2.0 75 | license_file: dist/LICENSE.txt 76 | summary: Generic automation framework for acceptance testing and RPA 77 | doc_url: http://robotframework.org/robotframework/{{ version }}/RobotFrameworkUserGuide.html 78 | dev_url: https://github.com/robotframework/robotframework 79 | description: > 80 | Robot Framework is a generic open source automation framework for acceptance 81 | testing, acceptance test driven development (ATDD), and robotic process 82 | automation (RPA). It has simple plain text syntax and it can be extended 83 | easily with libraries implemented using Python or Java. 84 | -------------------------------------------------------------------------------- /tests/acceptance/RobotLab/2_Lab/30_Tutorial.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Try the Tutorial 3 | Force Tags starter:tutorial 4 | Library JupyterLibrary 5 | Resource ../../../resources/Browser.robot 6 | Resource ../../../resources/Selectors.robot 7 | 8 | *** Variables *** 9 | ${KERNEL LANGUAGE} Python 3 10 | ${TOKEN CELL 00} .jp-CodeCell:nth-child(3) .CodeMirror 11 | 12 | *** Test Cases *** 13 | Will the Tutorial Launch? 14 | [Documentation] Start the Tutorial 15 | Open RobotLab 16 | ${prefix} = Set Variable tutorial_ 17 | Execute JupyterLab Command Close All 18 | Wait Until Page Contains Element ${XP LAUNCH SECTION} 19 | Capture Page Screenshot ${prefix}_0_before_starter.png 20 | Click Element ${CSS LAUNCH CARD TUTORIAL} 21 | Wait Until Page Contains Element ${XP FILE TREE TUTORIAL 00} timeout=10s 22 | Capture Page Screenshot ${prefix}_1_after_starter.png 23 | 24 | Will a Tutorial Notebook Run? 25 | [Documentation] Run the First Tutorial Notebook 26 | Open RobotLab 27 | ${prefix} = Set Variable tutorial_00_ 28 | # Set Selenium Speed 0.25s 29 | Open the Tutorial Folder ${prefix} 30 | Open the Tutorial Notebook ${prefix} 31 | # TODO: get the url parametrized so that it can also be run 32 | # Run the Tutorial Notebook ${prefix} 33 | 34 | *** Keywords *** 35 | Open the Tutorial Folder 36 | [Arguments] ${prefix} 37 | [Documentation] Open the tutorial folder 38 | Execute JupyterLab Command Close All 39 | Maybe Open JupyterLab Sidebar File Browser 40 | Click Element ${CRUMBS HOME} 41 | Double Click Element ${XP FILE TREE TUTORIAL} 42 | Capture Page Screenshot ${prefix}_1_in_folder.png 43 | 44 | Open the Tutorial Notebook 45 | [Arguments] ${prefix} 46 | [Documentation] Open and prepare the tutorial notebook 47 | Wait Until Page Contains Element ${XP FILE TREE TUTORIAL 00} timeout=10s 48 | Double Click Element ${XP FILE TREE TUTORIAL 00} 49 | Wait Until Page Contains Element css:.jp-Notebook table timeout=10s 50 | Wait Until Page Contains ${KERNEL LANGUAGE} | Idle timeout=3s 51 | Capture Page Screenshot ${prefix}_2_after_launch.png 52 | Execute JupyterLab Command Clear All Outputs 53 | 54 | Run the Tutorial Notebook 55 | [Arguments] ${prefix} 56 | [Documentation] Actually run the tutorial notebook 57 | Click Element css:${TOKEN CELL 00} 58 | # this gem is because rfjpyl uses backticks... 59 | Set CodeMirror Value ${TOKEN CELL 00} *** Variables ***\n` + '\${token} ' +` ${TOKEN} 60 | Capture Page Screenshot ${prefix}_3_after_token.png 61 | Click Element ${CSS NOTEBOOK SAVE} 62 | Execute JupyterLab Command Run All Cells 63 | Wait Until Page Does Not Contain [*] timeout=20s 64 | Wait Until Page Contains ${KERNEL LANGUAGE} | Idle timeout=3s 65 | Click Element ${CSS NOTEBOOK SAVE} 66 | Execute JupyterLab Command Close All 67 | -------------------------------------------------------------------------------- /tests/acceptance/RobotLab/2_Lab/40_Examples.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Try the Examples 3 | Force Tags starter:example 4 | Library JupyterLibrary 5 | Resource ../../../resources/Browser.robot 6 | Resource ../../../resources/Lab.robot 7 | Resource ../../../resources/Selectors.robot 8 | 9 | *** Variables *** 10 | ${KERNEL LANGUAGE} Robot Framework 11 | 12 | *** Test Cases *** 13 | Will the Example Starter Launch? 14 | [Documentation] Start the Example 15 | [Tags] example:opencv 16 | Open RobotLab 17 | ${prefix} = Set Variable example_ 18 | Execute JupyterLab Command Close All 19 | Wait Until Page Contains Element ${XP LAUNCH SECTION} 20 | Capture Page Screenshot ${prefix}_0_before_starter.png 21 | Click Element ${CSS LAUNCH CARD EXAMPLES} 22 | Wait Until Page Contains Element ${XP FILE TREE EXAMPLE OPENCV} timeout=10s 23 | Capture Page Screenshot ${prefix}_1_after_starter.png 24 | 25 | Will the OpenCV Notebook Run? 26 | [Documentation] Run the OpenCV Tutorial Notebook 27 | [Tags] example:opencv 28 | Open RobotLab 29 | ${prefix} = Set Variable example_opencv_ 30 | Open the Example Folder ${prefix} 31 | Open the Example Notebook ${prefix} ${XP FILE TREE EXAMPLE OPENCV} 32 | Run the Example Notebook ${prefix} 33 | Capture Page Screenshot ${prefix}_6_after_run_all.png 34 | The Robot Popup Should Contain ${prefix} Log passed, 0 failed 35 | The Robot Popup Should Contain ${prefix} Report All tests passed 36 | Capture Page Screenshot ${prefix}_7_reported.png 37 | Screenshot Each Output of Active JupyterLab Document ${prefix}_8_all_ 38 | 39 | *** Keywords *** 40 | Open the Example Folder 41 | [Arguments] ${prefix} 42 | [Documentation] Open the example folder 43 | Execute JupyterLab Command Close All 44 | Maybe Open JupyterLab Sidebar File Browser 45 | Click Element ${CRUMBS HOME} 46 | Double Click Element ${XP FILE TREE EXAMPLE} 47 | Capture Page Screenshot ${prefix}_1_in_folder.png 48 | 49 | Open the Example Notebook 50 | [Arguments] ${prefix} ${example} 51 | [Documentation] Open and prepare the example notebook 52 | Wait Until Page Contains Element ${example} timeout=10s 53 | Double Click Element ${example} 54 | Wait Until Page Contains ${KERNEL LANGUAGE} | Idle timeout=10s 55 | Capture Page Screenshot ${prefix}_2_after_launch.png 56 | Execute JupyterLab Command Clear All Outputs 57 | Sleep 1s 58 | Capture Page Screenshot ${prefix}_3_after_clean.png 59 | 60 | Run the Example Notebook 61 | [Arguments] ${prefix} 62 | [Documentation] Actually run the example notebook 63 | Execute JupyterLab Command Run All Cells 64 | Wait Until Page Does Not Contain [*] timeout=120s 65 | Wait Until Page Contains ${KERNEL LANGUAGE} | Idle timeout=120s 66 | Capture Page Screenshot ${prefix}_4_after_run.png 67 | -------------------------------------------------------------------------------- /recipes/robotlab/meta.yaml: -------------------------------------------------------------------------------- 1 | {% set robot = "3.1.2" %} 2 | {% set robot_conda = ">=4.7.12,<4.8" %} 3 | {% set robot_fox = ">=68.0.2,<69" %} 4 | {% set robot_jupyterlab = "==1.2.4" %} 5 | {% set robot_node = ">=11,<12" %} 6 | {% set robot_pywinpty = ">=0.5.5" %} 7 | {% set robot_starters = ">=0.2.2a0,<0.3.0a0" %} 8 | {% set robot_widgets = ">=7.5.1" %} 9 | {% set robotkernel = "1.3.0" %} 10 | 11 | package: 12 | name: {% set name = "robotlab" %}{{ name }} 13 | version: {% set version = "2020.01.0" %}{{ version }} 14 | 15 | source: 16 | - path: ../../robotlab 17 | folder: robotlab 18 | - url: https://github.com/robots-from-jupyter/robotkernel/archive/{{ robotkernel }}.tar.gz 19 | sha256: e3c384621f37c9471ca0c65c44c8203c7a99207cbb155a70c7b9063f2b9832e8 20 | folder: robotkernel 21 | # we do the jupyterlab build off-line to keep conda-build time low 22 | - path: ../../_artifacts/app_dir 23 | folder: app_dir 24 | 25 | build: 26 | number: 0 27 | entry_points: 28 | - robotlab = robotlab.labapp:main 29 | - robotlab-extension = robotlab.labextensionapp:main 30 | - robotlab-shortcuts = robotlab.shortcuts:make_shortcuts 31 | - robotlab-examples = robotlab.examples:copy_robotkernel_examples 32 | - robotlab-tutorial = robotlab.tutorial:copy_robotkernel_tutorial 33 | script: 34 | - {{ PYTHON }} {{ RECIPE_DIR }}/builder.py # [unix] 35 | - {{ PYTHON }} {{ RECIPE_DIR }}\builder.py # [win] 36 | - cd robotlab 37 | - {{ PYTHON }} -m pip install --no-deps --ignore-installed --no-cache-dir -vvv . 38 | 39 | requirements: 40 | host: 41 | - pip 42 | - python 43 | run: 44 | - conda {{ robot_conda }} 45 | - firefox {{ robot_fox }} 46 | - geckodriver 47 | - ipywidgets {{ robot_widgets }} 48 | - jupyter-starters {{ robot_starters }} 49 | - jupyterlab {{ robot_jupyterlab }} 50 | - jupytext >=1.3.1 51 | - matplotlib-base >=3.1.2 52 | - nodejs {{ robot_node }} 53 | - py-opencv 54 | - pyshortcuts 55 | - python 56 | - pywinpty {{ robot_pywinpty }} # [win] 57 | - restinstance 58 | - rise >=5.6.0 59 | - robotframework =={{ robot }} 60 | - robotframework-jupyterlibrary 61 | - robotframework-seleniumscreenshots 62 | - robotframework-seleniumtestability 63 | - robotframework-whitelibrary # [win] 64 | - robotkernel =={{ robotkernel }} 65 | 66 | test: 67 | imports: 68 | - robotlab 69 | - robotlab.examples 70 | - robotlab.labextensionapp 71 | - robotlab.launch 72 | - robotlab.paths 73 | - robotlab.shortcuts 74 | - robotlab.tutorial 75 | commands: 76 | - robotlab --version 77 | - robotlab-extension list 78 | - robotlab-tutorial 79 | - robotlab-examples 80 | - cd robotkernel-examples 81 | - jupyter nbconvert --execute --ExecutePreprocessor.timeout=600 OpenCV.ipynb # [not osx] 82 | - cd .. 83 | - mkdir Desktop # [unix] 84 | - HOME=$(pwd) robotlab-shortcuts # [unix] 85 | 86 | about: 87 | home: https://github.com/robots-from-jupyter/robotlab 88 | license: BSD-3-Clause 89 | license_family: BSD 90 | license_file: robotlab/LICENSE 91 | summary: A JupyterLab built for robotkernel as part of the RobotLab distribution 92 | -------------------------------------------------------------------------------- /recipes/robotlab/builder.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | import os, sys, shutil, json, platform, re 3 | 4 | PLATFORM = platform.system().lower() 5 | 6 | SRC_DIR = Path(os.environ["SRC_DIR"]) 7 | PREFIX = Path(os.environ["PREFIX"]) 8 | 9 | APP = SRC_DIR / "app_dir" 10 | 11 | WWW = PREFIX / "var" / "www" 12 | ETC = PREFIX / "etc" / "jupyter" / "jupyter_notebook_config.d" 13 | SHARE = PREFIX / "share" / "jupyter" 14 | 15 | KERNEL = SRC_DIR / "robotkernel" 16 | EXAMPLES = WWW / "robotkernel-examples" 17 | TUTORIAL = WWW / "robotkernel-tutorial" 18 | NOTEBOOKS = { 19 | EXAMPLES: KERNEL / "examples", 20 | TUTORIAL: KERNEL / "src" / "robotkernel" / "resources" / "notebooks" / "tutorial" 21 | } 22 | SVG = SRC_DIR / "robotlab" / "src" / "robotlab" / "icons" / "starter.svg" 23 | 24 | OPENCV_OSX = """ 25 | ${prefix} = Evaluate __import__("sys").prefix 26 | Create WebDriver Firefox executable_path=${prefix}${/}bin${/}geckodriver firefox_binary=${prefix}${/}bin${/}firefox 27 | Go To https://www.google.com/?hl=en 28 | """ 29 | 30 | 31 | print("making directories...") 32 | [d.mkdir(exist_ok=True, parents=True) for d in [SHARE, ETC, WWW]] 33 | 34 | print("copying lab...") 35 | shutil.rmtree(APP / "staging", ignore_errors=True) 36 | shutil.copytree(APP, SHARE / "robotlab") 37 | 38 | print("copying notebooks...") 39 | NOT_A_NOTEBOOK = lambda d, paths: [p for p in paths if not p.endswith(".ipynb")] 40 | [ 41 | shutil.copytree(src, dest, ignore=NOT_A_NOTEBOOK) 42 | for dest, src in NOTEBOOKS.items() 43 | ] 44 | 45 | print("hacking OpenCV Notebook on OSX") 46 | 47 | if PLATFORM == "darwin": 48 | opencv = EXAMPLES / "OpenCV.ipynb" 49 | nb = json.loads(opencv.read_text()) 50 | for cell in nb["cells"]: 51 | if cell["cell_type"] == "code": 52 | lines = cell["source"] 53 | for i, line in enumerate(lines): 54 | if re.findall(r"\s+Open browser", line, flags=re.I): 55 | lines[i] = OPENCV_OSX 56 | print(lines) 57 | cell["source"] = lines 58 | 59 | opencv.write_text(json.dumps(nb, indent=2)) 60 | 61 | 62 | print("making starters...") 63 | (ETC / "robotlab-starters.json").write_text(json.dumps({ 64 | "StarterManager": { 65 | "extra_starters": { 66 | "robotkernel-quickstart": { 67 | "label": "", 68 | "description": "", 69 | "type": "notebook", 70 | "py_src": "robotkernel", 71 | "src": "resources/starter/quickstart-starter.ipynb" 72 | }, 73 | "robotkernel-tutorial": { 74 | "label": "Tutorial", 75 | "description": "Tutorial for Robot Framework on Jupyter", 76 | "type": "copy", 77 | "py_src": "robotkernel", 78 | "src": "resources/notebooks/tutorial", 79 | "icon": SVG.read_text().replace("jp-icon3", "jp-icon-contrast3") 80 | }, 81 | "robotkernel-examples": { 82 | "type": "copy", 83 | "label": "Samples", 84 | "description": "Miscellanous examples of using RobotKernel", 85 | "icon": SVG.read_text().replace("jp-icon2", "jp-icon-contrast1"), 86 | "src": str(EXAMPLES) 87 | } 88 | } 89 | } 90 | }, indent=2)) 91 | -------------------------------------------------------------------------------- /ci/job.selftest.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | products: 3 | - RobotLab 4 | # - MiniRobot 5 | # - ExoRobot 6 | platforms: 7 | - name: Linux 8 | vmImage: ubuntu-16.04 9 | activate: "" 10 | - name: MacOSX 11 | vmImage: macos-10.13 12 | activate: "" 13 | - name: Windows 14 | vmImage: vs2017-win2016 15 | activate: call activate && 16 | 17 | jobs: 18 | - ${{ each product in parameters.products }}: 19 | - ${{ each platform in parameters.platforms }}: 20 | - job: ${{ product }}${{ platform.name }}Test 21 | condition: succeeded() 22 | dependsOn: 23 | - ${{ product }}${{ platform.name }}Build 24 | pool: 25 | vmImage: ${{ platform.vmImage }} 26 | 27 | steps: 28 | - task: DownloadPipelineArtifact@0 29 | inputs: 30 | artifactName: ${{ product }} for ${{ platform.name }} $(Build.BuildId) 31 | targetPath: _artifacts/constructor 32 | displayName: restore installer 33 | 34 | - ${{ if not(eq(platform.name, 'Windows')) }}: 35 | - script: bash _artifacts/constructor/${{ product }}-$(ROBOTLAB_VERSION)-${{ platform.name }}-x86_64.sh -fbp _${{ product }} 36 | displayName: run installer 37 | - script: . ./_${{ product }}/bin/activate ./_${{ product }} && python -m scripts.test robot ${{ product }} --headless --in-product --dryrun 38 | displayName: acceptance tests (dry run) 39 | - script: . ./_${{ product }}/bin/activate ./_${{ product }} && python -m scripts.test robot ${{ product }} --headless --in-product 40 | displayName: acceptance tests 41 | 42 | - ${{ if eq(platform.name, 'Windows') }}: 43 | - script: | 44 | @echo on 45 | echo %HOME% 46 | md "%cd%\_${{ product }}" 47 | start /wait "" "_artifacts\constructor\${{ product }}-$(ROBOTLAB_VERSION)-Windows-x86_64.exe" /InstallationType=JustMe /AddToPath=0 /RegisterPython=0 /S /D=%cd%\_${{ product }} 48 | displayName: run installer 49 | - script: | 50 | @echo on 51 | call "%cd%\_${{ product }}\Scripts\activate.bat" "%cd%\_${{ product }}" 52 | python -m scripts.test robot ${{ product }} --headless --in-product --dryrun 53 | displayName: acceptance tests (dry run) 54 | - script: | 55 | @echo on 56 | call "%cd%\_${{ product }}\Scripts\activate.bat" "%cd%\_${{ product }}" 57 | python -m scripts.test robot ${{ product }} --headless --in-product 58 | displayName: acceptance tests 59 | 60 | - ${{ if eq(platform.name, 'MacOSX') }}: 61 | - script: chmod -R 777 _artifacts 62 | displayName: fix artifact permissions 63 | 64 | - task: PublishTestResults@2 65 | displayName: publish test results 66 | inputs: 67 | testResultsFiles: _artifacts/test_output/**/*.xunit.xml 68 | condition: always() 69 | 70 | - task: PublishPipelineArtifact@0 71 | displayName: publish robot output 72 | inputs: 73 | targetPath: _artifacts/test_output 74 | artifactName: ${{ product }} ${{ platform.name }} Output $(Build.BuildId) 75 | condition: always() 76 | -------------------------------------------------------------------------------- /anaconda-project.yml: -------------------------------------------------------------------------------- 1 | name: robotlab 2 | 3 | commands: 4 | integrity: 5 | unix: python -m scripts.integrity 6 | env_spec: _qa 7 | 8 | lint: 9 | unix: python -m scripts.lint 10 | env_spec: _qa 11 | 12 | build: 13 | unix: python -m scripts.build 14 | windows: python -m scripts.build 15 | env_spec: _robots_from_jupyter 16 | 17 | build:lab: 18 | unix: python -m scripts.build lab 19 | windows: python -m scripts.build lab 20 | env_spec: _qa 21 | 22 | test: 23 | unix: python -m scripts.test 24 | windows: python -m scripts.test 25 | env_spec: _test 26 | 27 | combine: 28 | unix: python -m scripts.combine 29 | env_spec: _qa 30 | 31 | robotlab:setup: 32 | unix: cd robotlab && python -m pip install -e . --ignore-installed --no-deps -vv 33 | windows: cd robotlab && python -m pip install -e . --ignore-installed --no-deps -vv 34 | env_spec: robotlab-dev 35 | 36 | robotlab: 37 | unix: robotlab 38 | windows: robotlab 39 | env_spec: robotlab-dev 40 | 41 | robotlab:launch: 42 | unix: python -m robotlab.launch 43 | windows: python -m robotlab.launch 44 | env_spec: robotlab-dev 45 | 46 | robotlab:build: 47 | unix: robotlab build 48 | windows: robotlab build 49 | env_spec: robotlab-dev 50 | 51 | channels: 52 | - https://conda.anaconda.org/anaconda 53 | - https://conda.anaconda.org/conda-forge 54 | 55 | env_specs: 56 | _robots_from_jupyter: 57 | description: the main build/test environment 58 | channels: 59 | - https://conda.anaconda.org/anaconda 60 | - https://conda.anaconda.org/conda-forge 61 | packages: 62 | - conda >=4.8,<4.9.0a0 63 | - conda-build >=3.18.11,<3.19.0a0 64 | - conda-verify 65 | - constructor >=3,<3.1 66 | - firefox >=68.0.2,<69 67 | - geckodriver 68 | - pillow 69 | - python >=3.6,<3.7.0a0 70 | - python-libarchive-c 71 | - ripgrep 72 | - robotframework 73 | - robotframework-seleniumlibrary >=4.1.0,<5 74 | 75 | _lab: 76 | packages: 77 | - jupyterlab ==1.2.4 78 | - nodejs >=11,<12 79 | - python >=3.6,<3.7.0a0 80 | 81 | _qa: 82 | inherit_from: 83 | - _lab 84 | packages: 85 | - black 86 | - flake8 87 | - robotframework-lint 88 | 89 | _test: 90 | inherit_from: 91 | - _robots_from_jupyter 92 | channels: 93 | - ./_artifacts/conda-bld 94 | packages: 95 | - robotframework-jupyterlibrary 96 | 97 | robotlab-dev: 98 | description: basically what goes in the constructor for interactive dev/test 99 | inherit_from: 100 | - _lab 101 | channels: 102 | - ./_artifacts/conda-bld 103 | packages: 104 | - conda 105 | - firefox 106 | - jupyter-starters 107 | - jupytext 108 | - matplotlib 109 | - pyshortcuts 110 | - restinstance 111 | - rise 112 | - robotframework-seleniumscreenshots 113 | - robotframework-seleniumtestability 114 | - robotkernel 115 | 116 | robotlab-dev-win: 117 | inherit_from: 118 | - robotlab-dev 119 | packages: 120 | - robotframework-whitelibrary 121 | 122 | robotlab-test: 123 | channels: 124 | - https://conda.anaconda.org/conda-forge 125 | - https://conda.anaconda.org/anaconda 126 | - ./_artifacts/conda-bld 127 | packages: 128 | - robotlab 129 | -------------------------------------------------------------------------------- /scripts/build.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from jinja2 import Template 4 | 5 | from . import ( 6 | CONDA_BUILD_ARGS, 7 | CONDA_OUT, 8 | CONDA_VERSION, 9 | CONSTRUCT_DIR, 10 | CONSTRUCT_OUT, 11 | CONSTRUCTOR_ARGS, 12 | LAB_OUT, 13 | LABEXTENSIONS, 14 | PY_MAX, 15 | PY_MIN, 16 | RECIPE_DIR, 17 | RF_VERSION, 18 | run, 19 | VERSION, 20 | ) 21 | 22 | 23 | def build_conda(packages=None, force=False, no_test=False): 24 | """ Build some packages (mostly re-arching conda-forge `noarch: python`) 25 | """ 26 | 27 | [ 28 | p.unlink() 29 | for p in ( 30 | list(CONDA_OUT.rglob("*.json")) 31 | + list(CONDA_OUT.rglob("*.json.bz2")) 32 | ) 33 | ] 34 | 35 | if packages: 36 | force = True 37 | else: 38 | packages = ["."] 39 | 40 | extra_args = [] 41 | extra_args += [] if force else ["--skip-existing"] 42 | extra_args += ["--no-test"] if no_test else [] 43 | 44 | rc = 0 45 | 46 | args = [*CONDA_BUILD_ARGS, *extra_args, *packages] 47 | rc = rc or run(args, cwd=str(RECIPE_DIR)) 48 | 49 | return rc 50 | 51 | 52 | def build_constructor(construct): 53 | """ Use the local build artifacts in constructor 54 | """ 55 | construct_dir = CONSTRUCT_DIR / construct 56 | 57 | construct_yaml_in = Template( 58 | (construct_dir / "construct.yaml.in").read_text() 59 | ) 60 | 61 | construct_yaml = construct_yaml_in.render( 62 | build_channel=CONDA_OUT.as_uri(), 63 | py_max=PY_MAX, 64 | py_min=PY_MIN, 65 | version=VERSION, 66 | rf_version=RF_VERSION, 67 | conda_version=CONDA_VERSION, 68 | ) 69 | 70 | (construct_dir / "construct.yaml").write_text(construct_yaml) 71 | 72 | print(construct_yaml) 73 | 74 | CONSTRUCT_OUT.mkdir(exist_ok=True, parents=True) 75 | 76 | return run(CONSTRUCTOR_ARGS, cwd=str(construct_dir)) 77 | 78 | 79 | def build_lab(): 80 | JP = [sys.executable, "-m", "jupyter"] 81 | app_dir = ["--app-dir", LAB_OUT] 82 | 83 | rc = run( 84 | [ 85 | *JP, 86 | "labextension", 87 | "install", 88 | "--no-build", 89 | *app_dir, 90 | *LABEXTENSIONS, 91 | ] 92 | ) 93 | 94 | rc = rc or run( 95 | [ 96 | *JP, 97 | "lab", 98 | "build", 99 | *app_dir, 100 | "--dev-build=False", 101 | "--minimize=True", 102 | "--name='RobotLab'", 103 | ] 104 | ) 105 | 106 | rc or run([*JP, "labextension", "list"]) 107 | 108 | return rc 109 | 110 | 111 | if __name__ == "__main__": 112 | rc = 1 113 | 114 | all_constructs = sorted(CONSTRUCT_DIR.glob("*/")) 115 | 116 | if len(sys.argv) > 1: 117 | it, rest = sys.argv[1], sys.argv[2:] 118 | if it == "lab": 119 | rc = build_lab() 120 | elif it == "conda": 121 | no_test = False 122 | if "--no-test" in rest: 123 | no_test = True 124 | rest.remove("--no-test") 125 | rc = build_conda(rest, no_test=no_test) 126 | elif it == "constructor": 127 | rc = 0 128 | constructs = rest or all_constructs 129 | print(f"building {constructs}") 130 | for construct in constructs: 131 | rc = rc or build_constructor(construct) 132 | else: 133 | rc = build_conda() 134 | print(f"building {all_constructs}") 135 | for construct in all_constructs: 136 | rc = rc or build_constructor(construct) 137 | 138 | sys.exit(rc) 139 | -------------------------------------------------------------------------------- /scripts/test.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | import sys 4 | 5 | from . import ( 6 | run, 7 | TEST_DIR, 8 | TEST_OUT, 9 | PLATFORM, 10 | CONDA_OUT, 11 | CONDA_BUILD_ARGS, 12 | CONSTRUCT_OUT, 13 | ) 14 | 15 | 16 | def test_conda(packages=None): 17 | rc = 0 18 | packages = packages or sorted( 19 | [ 20 | pkg 21 | for pkg in CONDA_OUT.glob("*/*.tar.bz2") 22 | if "repodata" not in pkg.name 23 | ] 24 | ) 25 | for pkg in packages: 26 | rc = rc or run([*CONDA_BUILD_ARGS, "--test", pkg]) 27 | return rc 28 | 29 | 30 | def test_robot( 31 | product, robot_args=None, headless=False, in_product=False, dry_run=False 32 | ): 33 | stem = f"{product}.{PLATFORM}" 34 | output_path = TEST_OUT / product / PLATFORM.lower() 35 | 36 | robot_args = list(robot_args or []) 37 | robot_args += ["--include", f"product:{product}"] 38 | 39 | name = f"{product} {PLATFORM}" 40 | 41 | if dry_run: 42 | robot_args += ["--dryrun", "--settag", "dryrun"] 43 | stem += ".dryrun" 44 | name = f"{name} (Dry Run)" 45 | output_path = TEST_OUT / product / f"{PLATFORM.lower()}-dryrun" 46 | 47 | robot_args += os.environ.get("ROBOT_ARGS", "").split() 48 | 49 | if output_path.exists(): 50 | shutil.rmtree(output_path) 51 | 52 | output_path.mkdir(parents=True) 53 | 54 | if headless: 55 | os.environ["MOZ_HEADLESS"] = "1" 56 | 57 | args = ( 58 | [ 59 | sys.executable, 60 | "-m", 61 | "robot", 62 | "--name", 63 | name, 64 | "--outputdir", 65 | output_path, 66 | "--output", 67 | TEST_OUT / f"{stem}.robot.xml", 68 | "--log", 69 | TEST_OUT / f"{stem}.log.html", 70 | "--report", 71 | TEST_OUT / f"{stem}.report.html", 72 | "--xunit", 73 | TEST_OUT / f"{stem}.xunit.xml", 74 | "--variable", 75 | f"OS:{PLATFORM}", 76 | "--variable", 77 | f"INSTALLER DIR:{CONSTRUCT_OUT}", 78 | "--variable", 79 | f"IN_PRODUCT:{int(in_product)}", 80 | ] 81 | + list(robot_args) 82 | + [str(TEST_DIR / "acceptance" / product)] 83 | ) 84 | return run(args) 85 | 86 | 87 | if __name__ == "__main__": 88 | rc = 0 89 | headless = in_product = dry_run = False 90 | all_products = ["RobotLab"] 91 | # all_products = sorted( 92 | # [product.name for product in (TEST_DIR / "acceptance").glob("*/")] 93 | 94 | # ) 95 | args = sys.argv[1:] 96 | 97 | if "--headless" in args: 98 | headless = True 99 | args.remove("--headless") 100 | 101 | if "--in-product" in args: 102 | in_product = True 103 | args.remove("--in-product") 104 | 105 | if "--dryrun" in args: 106 | dry_run = True 107 | args.remove("--dryrun") 108 | 109 | if not args: 110 | rc = test_conda() 111 | for product in all_products: 112 | rc = rc or test_robot( 113 | product, headless=headless, in_product=in_product 114 | ) 115 | else: 116 | it, rest = args[0], args[1:] 117 | 118 | if it == "conda": 119 | rc = test_conda(rest) 120 | elif it == "robot": 121 | robot_args = [] 122 | if "--" in rest: 123 | dash_index = rest.index("--") 124 | robot_args = rest[dash_index + 1 :] 125 | products = rest[: dash_index - 1] 126 | else: 127 | products = rest or all_products 128 | 129 | print(f"testing {products}") 130 | for product in products: 131 | rc = rc or test_robot( 132 | product, 133 | robot_args=robot_args, 134 | headless=headless, 135 | in_product=in_product, 136 | dry_run=dry_run, 137 | ) 138 | 139 | sys.exit(rc) 140 | -------------------------------------------------------------------------------- /tests/resources/Install.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Install a Product 3 | Library OperatingSystem 4 | Library Process 5 | Resource ./Cleanup.robot 6 | 7 | *** Variables *** 8 | ${INSTALLER VERSION} 2020.01.0 9 | ${INSTALL LOG} ${OUTPUT DIR}${/}00_installer.log 10 | &{GECKODRIVER} linux=bin${/}geckodriver darwin=bin${/}geckodriver windows=Scripts${/}geckodriver.exe 11 | &{FIREFOX} linux=bin${/}firefox darwin=bin${/}firefox windows=Library${/}bin${/}firefox.exe 12 | 13 | *** Keywords *** 14 | Run the installer 15 | [Arguments] ${product} 16 | [Documentation] Detect and tag the platform, then run the appropriate installer (if not already in robotlab) 17 | ${tmpdir} = Evaluate ${IN_PRODUCT} or __import__("tempfile").mkdtemp("RobotLab") 18 | ${path} = Set Variable ${OUTPUT DIR} 19 | ${product dir} = Set Variable If ${IN_PRODUCT} %{CONDA_PREFIX} ${tmpdir} 20 | Set Global Variable ${PRODUCT DIR} ${product dir} 21 | Set Global Variable ${FAKE HOME} ${path}${/}home 22 | Create Directory ${FAKE HOME}${/}Desktop 23 | ${rc} = Run Keyword If "${OS}" == "linux" Run the Linux Installer ${product} 24 | ... ELSE IF "${OS}" == "windows" Run the Windows Installer ${product} 25 | ... ELSE IF "${OS}" == "darwin" Run the OSX Installer ${product} 26 | ... ELSE Fatal Error Can't install on platform ${OS}! 27 | Should Be Equal as Integers ${rc} 0 msg=Couldn't complete installer, see ${INSTALL LOG} 28 | Wait Until Created ${ACTIVATE SCRIPT} 29 | 30 | Run the Linux installer 31 | [Arguments] ${product} 32 | [Documentation] Install on Linux 33 | ${result} = Run Keyword If not ${IN_PRODUCT} Run Process bash ${INSTALLER DIR}${/}${product}-${INSTALLER VERSION}-Linux-x86_64.sh -fbp 34 | ... ${PRODUCT DIR} stdout=${INSTALL LOG} stderr=STDOUT env:HOME=${FAKE HOME} 35 | Set Global Variable ${ACTIVATE SCRIPT} ${PRODUCT DIR}${/}bin${/}activate 36 | Set Global Variable ${ACTIVATE} . "${ACTIVATE SCRIPT}" "${PRODUCT DIR}" && set -eux 37 | Set Global Variable ${PRODUCT PATH ENV} ${PRODUCT DIR}${/}bin:%{PATH} 38 | Run Keyword If "${product}" == "RobotLab" Set Global Variable ${ROBOTLAB CMD} ${PRODUCT DIR}${/}bin${/}robotlab 39 | Run Keyword If "${product}" == "RobotLab" Set Global Variable ${ROBOTLAB SHORTCUT} RobotLab.desktop 40 | ${rc} = Set Variable If ${IN_PRODUCT} 0 ${result.rc} 41 | [Return] ${rc} 42 | 43 | Run the OSX installer 44 | [Arguments] ${product} 45 | [Documentation] Install on OSX 46 | ${result} = Run Keyword If not ${IN_PRODUCT} Run Process bash ${INSTALLER DIR}${/}${product}-${INSTALLER VERSION}-MacOSX-x86_64.sh -fbp 47 | ... ${PRODUCT DIR} stdout=${INSTALL LOG} stderr=STDOUT env:HOME=${FAKE HOME} 48 | Set Global Variable ${ACTIVATE SCRIPT} ${PRODUCT DIR}${/}bin${/}activate 49 | Set Global Variable ${ACTIVATE} set -ex && . "${ACTIVATE SCRIPT}" "${PRODUCT DIR}" 50 | Set Global Variable ${PRODUCT PATH ENV} ${PRODUCT DIR}${/}bin${:}%{PATH} 51 | Run Keyword If "${product}" == "RobotLab" Set Global Variable ${ROBOTLAB CMD} ${PRODUCT DIR}${/}bin${/}robotlab 52 | Run Keyword If "${product}" == "RobotLab" Set Global Variable ${ROBOTLAB SHORTCUT} RobotLab.app 53 | ${rc} = Set Variable If ${IN_PRODUCT} 0 ${result.rc} 54 | [Return] ${rc} 55 | 56 | Run the Windows installer 57 | [Arguments] ${product} 58 | [Documentation] Install on Windows 59 | ${installer} = Set Variable ${INSTALLER DIR}${/}${product}-${INSTALLER VERSION}-Windows-x86_64.exe 60 | ${args} = Set Variable /InstallationType=JustMe /AddToPath=0 /RegisterPython=0 /S /D=${PRODUCT DIR} 61 | ${result} = Run Keyword If not ${IN_PRODUCT} Run Process ${installer} ${args} stdout=${INSTALL LOG} stderr=STDOUT 62 | ... shell=True env:HOME=${FAKE HOME} 63 | Set Global Variable ${ACTIVATE SCRIPT} ${PRODUCT DIR}${/}Scripts${/}activate.bat 64 | Set Global Variable ${ACTIVATE} "${ACTIVATE SCRIPT}" "${PRODUCT DIR}" 65 | Set Global Variable ${PRODUCT PATH ENV} ${PRODUCT DIR}${:}${PRODUCT DIR}${/}Scripts${:}${PRODUCT DIR}${/}Library${/}bin${:}%{PATH} 66 | Run Keyword If "${product}" == "RobotLab" Set Global Variable ${ROBOTLAB CMD} ${PRODUCT DIR}${/}Scripts${/}robotlab.exe 67 | Run Keyword If "${product}" == "RobotLab" Set Global Variable ${ROBOTLAB SHORTCUT} RobotLab.lnk 68 | ${rc} = Set Variable If ${IN_PRODUCT} 0 ${result.rc} 69 | [Return] ${rc} 70 | 71 | Get RobotLab GeckoDriver 72 | [Documentation] Get the path to the bundled geckodriver 73 | [Return] ${PRODUCT DIR}${/}&{GECKODRIVER}[${OS}] 74 | 75 | Get RobotLab Firefox 76 | [Documentation] Get the path to the bundled firefox 77 | [Return] ${PRODUCT DIR}${/}${FIREFOX}[${OS}] 78 | -------------------------------------------------------------------------------- /robotlab/src/robotlab/icons/lab.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 18 | 21 | 24 | 27 | 30 | 31 | 33 | 34 | 36 | image/svg+xml 37 | 39 | 40 | 41 | 42 | 43 | 47 | 50 | 54 | 58 | 59 | 64 | 68 | 69 | 70 | 96 | 97 | -------------------------------------------------------------------------------- /robotlab/src/robotlab/icons/shell.svg: -------------------------------------------------------------------------------- 1 | 2 | 13 | 15 | 18 | 21 | 24 | 27 | 30 | 31 | 33 | 34 | 36 | image/svg+xml 37 | 39 | 40 | 41 | 42 | 43 | 70 | 73 | 76 | 80 | 84 | 85 | 90 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /robotlab/src/robotlab/icons/master.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 24 | 27 | 30 | 33 | 36 | 37 | 60 | 64 | 65 | 67 | 68 | 70 | image/svg+xml 71 | 73 | 74 | 75 | 76 | 77 | 83 | 89 | 95 | 101 | 102 | 107 | 111 | 112 | 113 | 149 | 150 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RobotLab [![Build Status][build-badge]][build-status] 2 | 3 | > A one-click installer for [Robot Framework][robotframework], 4 | [JupyterLab][jupyterlab], [Firefox][], and Friends 5 | 6 | ## Get RobotLab 7 | Start the download now for your platform: 8 | 9 | ### [Linux][] | [MacOSX][] | [Windows][] 10 | 11 | > ... or view the [release notes][release-notes]. 12 | 13 | [Linux]: https://github.com/robots-from-jupyter/robotlab/releases/download/v2019.9.0/RobotLab-2019.9.0-Linux-x86_64.sh 14 | [MacOSX]: https://github.com/robots-from-jupyter/robotlab/releases/download/v2019.9.0/RobotLab-2019.9.0-MacOSX-x86_64.sh 15 | [Windows]: https://github.com/robots-from-jupyter/robotlab/releases/download/v2019.9.0/RobotLab-2019.9.0-Windows-x86_64.exe 16 | [release-notes]: https://github.com/robots-from-jupyter/robotlab/releases/tag/v2019.9.0 17 | 18 | ## Install RobotLab 19 | > You'll want at least 2GB available to install and run RobotLab 20 | 21 | - On Windows, double-click the installer 22 | - We recommend: 23 | - _don't_ add RobotLab to your `PATH` 24 | - _don't_ register RobotLab's python 25 | - On Linux/MacOSX 26 | - `bash RobotLab-*.sh` 27 | - follow the prompts 28 | - _don't_ install into your shell 29 | 30 | > **Remember** where you install RobotLab! 31 | > 32 | > We recommend someplace 33 | - **short**, e.g. `C:\robotlab` or `/home/myuser/robotlab` 34 | - with **no spaces** in the path, e.g. ~~`c:\Robot Lab`~~ 35 | - **not shared** on something like Dropbox, or a network drive 36 | 37 | 38 | ## Run RobotLab 39 | During installation, RobotLab will try to create a desktop icon: 40 | 41 | 42 | ### _There is an icon on my desktop/menu_ 43 | Click it to launch the RobotLab server in a console window. It will also attempt 44 | to launch the bundled Firefox. The application log will keep running in the 45 | background, and sometimes useful information will appear there. 46 | 47 | ### _Nope, no icon here_ 48 | If you don't see an icon, launch a console, e.g. `bash` on Linux/MacOSX or 49 | `cmd.exe` on Windows. 50 | 51 | | | Linux/MacOSX | Windows 52 | |--|-| 53 | | start a prompt | open your terminal or console application | open `cmd.exe` from the start menu | 54 | | activate the robotlab environment | type `source /path/to/robolab/bin/activate`
press ENTER | type `c:\path\to\robotlab\Scripts\activate`
press ENTER 55 | | start robotlab | type `robotlab`
press ENTER | type `robotlab`
press ENTER 56 | 57 | ## _Still didn't work_ 58 | If you're still stuck, open [an issue][robotlab-issues]. There should be some 59 | template information to provide. 60 | 61 | ## Advanced RobotLab Commands and Invocations 62 | ```bash 63 | # assuming you've already `activate`d 64 | robotlab [.] # basically just jupyterlab 65 | robotlab-tutorial [.] # copy the robotkernel tutorial to this directory 66 | robotlab-examples [.] # " " " examples " " " 67 | robotlab-shortcuts 68 | ``` 69 | 70 | ## Uninstall RobotLab 71 | - Delete the installation directory. 72 | - Delete any desktop shortcuts. 73 | - That is all. 74 | 75 | ## Motivation 76 | While [Robot Framework][robotframework] has no dependencies beyond the Python 77 | standard library, using it for non-trivial testing or process automation usually 78 | requires a fair number of additional Python dependencies, and even some more 79 | exotic ones. We wanted to run a workshop for [RoboCon][] 2019 and show interactive 80 | editing/running with [robotkernel][]. 81 | 82 | The focus of this workshop, running Robot tests and tasks interactively, required 83 | the Jupyter stack. To demonstrate some of its more advanced features, some fairly 84 | extensive extra libraries from both the Robot Framework and the scientific Python 85 | ecosystems were needed, and getting these to install smoothly on every attendee's 86 | computers can prove to be... interesting. 87 | 88 | To make a three-hour workshop reasonable, we needed a distribution approach that 89 | was: 90 | - easy to start, to that we could get to the Good Stuff 91 | - cross-platform, so that everyone could follow along 92 | - self-contained, so that it could be easily removed 93 | - offline-capable, so that we could handle intermittent network access 94 | - hackable by the user, so that we could fix Surprise Features 95 | 96 | > ### _Field Notes_ 97 | > 98 | > _At our 2019 workshop, graciously hosted by [Siili][], (whose network was super fast!) 99 | > our room full of attendees, on three distributions of Linux, two versions of MacOSX 100 | > and two versions of Windows were all up and running in under 30 minutes. We got 101 | > through all of the [tutorial][] before lunch!_ 102 | 103 | ## Tools 104 | RobotLab is built with: 105 | - [conda][], an OS-agnostic package manager 106 | - [anaconda-project][], a multi-environment manager and command executor 107 | - [conda-build][], the conda package builder 108 | - [constructor][conda-constructor], the installer-builder of conda packages 109 | - [azure pipelines][azure-pipelines], a continuous integration provider 110 | 111 | 112 | ## conda packaging 113 | Once it has matured, `robotkernel` will be available from [conda-forge][], the 114 | community-driven upstream of the Anaconda Distribution, which is also built 115 | with [constructor][conda-constructor]. 116 | 117 | So for the RobotLab installers, and supporting examples and tutorials, we need to 118 | build a number of dependencies. 119 | 120 | ### robotlab 121 | [JupyterLab][]'s build chain has some negative externalities 122 | for end users, namely an install- or run-time dependency on NodeJS and npmjs.org 123 | when using any labextensions other than the built-in set (e.g. Notebook, Terminal, 124 | Console, Editor, etc.). Because, for the purposes of the workshop, we want to 125 | get to the Good Stuff of running Robot notebooks and not spend a bunch of time 126 | debugging `nodejs` and `webpack`, we've added a few choice JupyterLab extensions: 127 | 128 | - `jupyterlab_robotmode`: syntax highlighting for Robot Framework 129 | - `jupyterlab-jupytext`: ipynb/text pairing for your notebook 130 | - `@jupyterlab/toc`: a table of contents pane for Markdown headers 131 | - `@jupyter-widgets/jupyterlab-manager`: because widgets are always good 132 | 133 | All of these are built outside of the `conda-build` cycle. 134 | 135 | This asset, and all our dependencies, are wrapped into a conda package which 136 | exposes some useful commands, which can do most of the things `jupyter lab` can do, 137 | as well as create desktop shortcuts, and unpack the tutorial content. 138 | 139 | `robotlab` works like `jupyter lab`, while `robotlab-extension` works like 140 | `jupyter labextension`. This isn't a toy installation: with the bundled `nodejs`, 141 | an intrepid user can still install any of the [labextensions][] that are 142 | compatible with the version `robotlab` was built with: as of writing, `1.1.x`. 143 | 144 | ## [constructor][conda-constructor] 145 | All of the dependencies are captured in [construct.yaml.in][]. 146 | In addition to required dependencies, a number of extra libraries are included to 147 | showcase some of the features of using Robot Framework interactively. 148 | - `JupyterLibrary` for testing Jupyter clients with robotframework 149 | - `SeleniumLibrary` for controlling browsers 150 | - `geckodriver` for interacting with... 151 | - `firefox`, the open source web browser 152 | - `opencv` for image-driven testing 153 | - `RESTInstance` for testing REST APIs, including swagger 154 | 155 | ## On Browsers and WebDrivers 156 | RobotLab includes Mozilla Firefox and `geckodriver`, with versions that will be 157 | supported for _years_, not _weeks_, by a team that is committed to open source 158 | and web standards. 159 | 160 | ### webdriver for Microsoft Internet Explorer 161 | It's pretty easy to [get `webdriver`][webdriver] for Microsoft Edge, but... 162 | - it but can't be redistributed 163 | - it has to match the version of Edge/Explorer exactly 164 | 165 | ### chromedriver for Google Chrome 166 | It's also pretty easy to get [chromedriver][] for Google Chrome, but... 167 | - it has to match the version of Chrome exactly 168 | 169 | # Work On RobotLab 170 | Contributions are welcome! See the [issues][] for outstanding work we've been 171 | discussing. 172 | 173 | > - Get [Miniconda][] 174 | > - Install [anaconda-project][] 175 | > - Clone [this repo][robotlab] 176 | 177 | From the command line e.g. `bash` or `cmd.exe` or the `Anaconda Prompt`, run: 178 | ```bash 179 | anaconda-project run build:lab 180 | anaconda-project run build 181 | ``` 182 | 183 | ## Test Robotlab 184 | ```bash 185 | anaconda-project run test 186 | ``` 187 | 188 | ## Checking RobotLab 189 | 190 | ```bash 191 | anaconda-project run lint 192 | anaconda-project run integrity 193 | ``` 194 | 195 | [anaconda-project]: https://github.com/anaconda-platform/anaconda-project 196 | [azure-pipelines]: https://azure.microsoft.com/en-us/services/devops/pipelines/ 197 | [build-badge]: https://dev.azure.com/robots-from-jupyter/robots-from-jupyter/_apis/build/status/robots-from-jupyter.robotlab?branchName=master 198 | [build-status]: https://dev.azure.com/robots-from-jupyter/robots-from-jupyter/_build/latest?definitionId=3?branchName=master 199 | [chromedriver]: https://chromedriver.chromium.org/downloads 200 | [conda-build]: https://github.com/conda/conda-build 201 | [conda-constructor]: https://github.com/conda/constructor 202 | [conda-forge]: https://github.com/conda-forge 203 | [conda]: https://github.com/conda/conda 204 | [construct.yaml.in]: ./constructor/construct.yaml.in 205 | [Firefox]: https://www.mozilla.org/en-US/firefox/ 206 | [jupyterlab]: https://jupyterlab.readthedocs.io 207 | [labextensions]: https://www.npmjs.com/search?q=keywords:jupyterlab-extension 208 | [Miniconda]: https://conda.io/miniconda.html 209 | [RoboCon]: https://robocon.io 210 | [robotframework]: https://github.com/robotframework/robotframework 211 | [robotkernel]: https://github.com/robots-from-jupyter/robotkernel 212 | [robotlab]: https://github.com/robots-from-jupyter/robotlab 213 | [robotlab-issues]: https://github.com/robots-from-jupyter/robotlab/issues 214 | [Siili]: https://siili.com 215 | [tutorial]: https://github.com/robots-from-jupyter/robotkernel/tree/master/docs/notebooks 216 | [webdriver]: https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/#downloads 217 | -------------------------------------------------------------------------------- /recipes/robotframework/70af9e3bab0217b0450d78c69e6c2ccb8f9c342d.patch: -------------------------------------------------------------------------------- 1 | From 70af9e3bab0217b0450d78c69e6c2ccb8f9c342d Mon Sep 17 00:00:00 2001 2 | From: =?UTF-8?q?Pekka=20Kl=C3=A4rck?= 3 | Date: Tue, 22 Oct 2019 21:53:33 +0300 4 | Subject: [PATCH] Python 3.8 utest fixes: Consistent XML attributes order 5 | 6 | --- 7 | utest/result/golden.xml | 24 ++++++------- 8 | utest/result/goldenTwice.xml | 50 +++++++++++++-------------- 9 | utest/result/test_resultserializer.py | 3 ++ 10 | 3 files changed, 40 insertions(+), 37 deletions(-) 11 | 12 | diff --git a/utest/result/golden.xml b/utest/result/golden.xml 13 | index 6703b889b..a8e0b706c 100644 14 | --- a/utest/result/golden.xml 15 | +++ b/utest/result/golden.xml 16 | @@ -1,9 +1,9 @@ 17 | 18 | 19 | - 20 | - 21 | + 22 | + 23 | 24 | - 25 | + 26 | 27 | 28 | 29 | @@ -11,8 +11,8 @@ 30 | 31 | Test 1 32 | 33 | -Test 1 34 | - 35 | +Test 1 36 | + 37 | 38 | 39 | 40 | @@ -27,21 +27,21 @@ 41 | Log on ${TEST NAME} 42 | TRACE 43 | 44 | - 45 | + 46 | 47 | - 48 | + 49 | 50 | Test case documentation 51 | 52 | t1 53 | 54 | - 55 | + 56 | 57 | Normal test cases 58 | 59 | My Value 60 | 61 | - 62 | + 63 | 64 | 65 | 66 | @@ -49,13 +49,13 @@ 67 | All Tests 68 | 69 | 70 | -t1 71 | +t1 72 | 73 | 74 | -Normal 75 | +Normal 76 | 77 | 78 | 79 | - Error in file 'normal.html' in table 'Settings': Resource file 'nope' does not exist. 80 | + Error in file 'normal.html' in table 'Settings': Resource file 'nope' does not exist. 81 | 82 | 83 | diff --git a/utest/result/goldenTwice.xml b/utest/result/goldenTwice.xml 84 | index ea60eca81..b5f117079 100644 85 | --- a/utest/result/goldenTwice.xml 86 | +++ b/utest/result/goldenTwice.xml 87 | @@ -1,10 +1,10 @@ 88 | 89 | 90 | 91 | - 92 | - 93 | + 94 | + 95 | 96 | - 97 | + 98 | 99 | 100 | 101 | @@ -12,8 +12,8 @@ 102 | 103 | Test 1 104 | 105 | -Test 1 106 | - 107 | +Test 1 108 | + 109 | 110 | 111 | 112 | @@ -28,26 +28,26 @@ 113 | Log on ${TEST NAME} 114 | TRACE 115 | 116 | - 117 | + 118 | 119 | - 120 | + 121 | 122 | Test case documentation 123 | 124 | t1 125 | 126 | - 127 | + 128 | 129 | Normal test cases 130 | 131 | My Value 132 | 133 | - 134 | + 135 | 136 | - 137 | - 138 | + 139 | + 140 | 141 | - 142 | + 143 | 144 | 145 | 146 | @@ -55,8 +55,8 @@ 147 | 148 | Test 1 149 | 150 | -Test 1 151 | - 152 | +Test 1 153 | + 154 | 155 | 156 | 157 | @@ -71,23 +71,23 @@ 158 | Log on ${TEST NAME} 159 | TRACE 160 | 161 | - 162 | + 163 | 164 | - 165 | + 166 | 167 | Test case documentation 168 | 169 | t1 170 | 171 | - 172 | + 173 | 174 | Normal test cases 175 | 176 | My Value 177 | 178 | - 179 | + 180 | 181 | - 182 | + 183 | 184 | 185 | 186 | @@ -95,16 +95,16 @@ 187 | All Tests 188 | 189 | 190 | -t1 191 | +t1 192 | 193 | 194 | -Normal & Normal 195 | -Normal & Normal.Normal 196 | -Normal & Normal.Normal 197 | +Normal & Normal 198 | +Normal & Normal.Normal 199 | +Normal & Normal.Normal 200 | 201 | 202 | 203 | -Error in file 'normal.html' in table 'Settings': Resource file 'nope' does not exist. 204 | -Error in file 'normal.html' in table 'Settings': Resource file 'nope' does not exist. 205 | +Error in file 'normal.html' in table 'Settings': Resource file 'nope' does not exist. 206 | +Error in file 'normal.html' in table 'Settings': Resource file 'nope' does not exist. 207 | 208 | 209 | diff --git a/utest/result/test_resultserializer.py b/utest/result/test_resultserializer.py 210 | index e55679801..e310cf20f 100644 211 | --- a/utest/result/test_resultserializer.py 212 | +++ b/utest/result/test_resultserializer.py 213 | @@ -15,6 +15,9 @@ 214 | 215 | class StreamXmlWriter(XmlWriter): 216 | 217 | + def _order_attrs(self, attrs): 218 | + return sorted(attrs) 219 | + 220 | def _create_output(self, output): 221 | return output 222 | 223 | -------------------------------------------------------------------------------- /recipes/robotframework-whitelibrary/apache-2.0.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /constructor/ExoRobot/LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /constructor/MiniRobot/LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /recipes/restinstance/apache-2.0.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | --------------------------------------------------------------------------------