├── .bowerrc ├── .gitignore ├── .pairs ├── .travis.yml ├── AUTHORS ├── CHANGELOG.md ├── LICENSE.md ├── MANIFEST.in ├── Makefile ├── README.md ├── bower.json ├── elements ├── urth-core-behaviors │ ├── bower.json │ ├── dynamic-properties-behavior.html │ ├── error-display-behavior.html │ ├── execution-complete-behavior.html │ ├── jupyter-kernel-observer.html │ ├── jupyter-notebook-env.html │ ├── jupyter-persist-behavior.html │ ├── jupyter-save-behavior.html │ ├── jupyter-widget-behavior.html │ ├── logging-behavior.html │ ├── shared-styles.html │ └── test │ │ ├── jupyter-save-behavior.html │ │ ├── jupyter-widget-behavior.html │ │ └── logging-behavior.html ├── urth-core-bind │ ├── bower.json │ ├── dom-bind-behavior.html │ ├── test │ │ └── urth-core-bind.html │ └── urth-core-bind.html ├── urth-core-channel │ ├── bower.json │ ├── test │ │ ├── urth-core-channel-broker.html │ │ └── urth-core-channel.html │ ├── urth-core-channel-broker.html │ ├── urth-core-channel-item.html │ ├── urth-core-channel-viewer.html │ └── urth-core-channel.html ├── urth-core-dataframe │ ├── bower.json │ ├── test │ │ ├── urth-core-dataframe.html │ │ ├── urth-core-query-agg.html │ │ ├── urth-core-query-behavior.html │ │ ├── urth-core-query-filter.html │ │ ├── urth-core-query-group.html │ │ └── urth-core-query-sort.html │ ├── urth-core-dataframe.html │ ├── urth-core-query-agg.html │ ├── urth-core-query-behavior.html │ ├── urth-core-query-filter.html │ ├── urth-core-query-group.html │ └── urth-core-query-sort.html ├── urth-core-function │ ├── bower.json │ ├── test │ │ └── urth-core-function.html │ └── urth-core-function.html ├── urth-core-import │ ├── bower.json │ ├── test │ │ ├── urth-core-import-broker.html │ │ └── urth-core-import.html │ ├── urth-core-import-broker.html │ └── urth-core-import.html ├── urth-core-storage │ ├── bower.json │ ├── test │ │ └── urth-core-storage.html │ └── urth-core-storage.html ├── urth-core-watch │ ├── bower.json │ ├── test │ │ └── urth-core-watch.html │ └── urth-core-watch.html ├── urth-help │ ├── bower.json │ └── urth-help.html ├── urth-viz-area │ ├── bower.json │ └── urth-viz-area.html ├── urth-viz-bar │ ├── bower.json │ ├── test │ │ └── urth-viz-bar.html │ └── urth-viz-bar.html ├── urth-viz-behaviors │ ├── bower.json │ └── urth-viz-selection-behavior.html ├── urth-viz-chart │ ├── bower.json │ ├── test │ │ └── urth-viz-chart.html │ ├── urth-viz-chart-common-behavior.html │ ├── urth-viz-chart.css │ └── urth-viz-chart.html ├── urth-viz-cloud │ ├── README.md │ ├── bower.json │ ├── test │ │ └── urth-viz-cloud.html │ └── urth-viz-cloud.html ├── urth-viz-col │ ├── bower.json │ └── urth-viz-col.html ├── urth-viz-ipywidget │ ├── bower.json │ ├── test │ │ └── urth-viz-ipywidget.html │ └── urth-viz-ipywidget.html ├── urth-viz-line │ ├── bower.json │ └── urth-viz-line.html ├── urth-viz-pie │ ├── bower.json │ └── urth-viz-pie.html ├── urth-viz-scatter │ ├── bower.json │ ├── test │ │ └── urth-viz-scatter.html │ └── urth-viz-scatter.html └── urth-viz-table │ ├── bower.json │ ├── test │ └── urth-viz-table.html │ └── urth-viz-table.html ├── etc ├── .gpg │ └── secring.gpg.enc ├── docs │ ├── bower.json │ ├── hydrolyze_elements.js │ ├── site │ │ ├── css │ │ │ └── index.css │ │ ├── docs.html │ │ ├── elements │ │ │ └── urth-docs-panel │ │ │ │ └── urth-docs-panel.html │ │ ├── images │ │ │ ├── Data-Binding-function.gif │ │ │ ├── Data-Binding-intercell.gif │ │ │ ├── Data-Binding-intracell.gif │ │ │ ├── Data-Binding-multiple.gif │ │ │ ├── Data-Channels-JS.gif │ │ │ ├── Data-Channels-Python.gif │ │ │ ├── Data-Channels-R.gif │ │ │ ├── Data-Channels-debug.gif │ │ │ ├── Data-Channels-initialize.gif │ │ │ ├── Data-Channels-save.gif │ │ │ └── Data-Channels-scala.gif │ │ ├── index.html │ │ ├── urth-docs.html │ │ └── usage-docs │ │ │ ├── Basic-Usage.md │ │ │ ├── Calling-Functions.md │ │ │ ├── Data-Binding.md │ │ │ ├── Data-Channels.md │ │ │ ├── Data-Visualizations.md │ │ │ ├── Serialization-of-data.md │ │ │ ├── Using-DataFrames.md │ │ │ └── Utility-Functions.md │ └── urth-elements.html ├── jupyter_notebook_config.py ├── notebook.json ├── notebooks │ ├── .gitignore │ ├── demos │ │ ├── .gitignore │ │ ├── food │ │ │ ├── Restaurant_Inspection_Scores.csv │ │ │ ├── WhereToEat.ipynb │ │ │ └── images │ │ │ │ ├── A_score.png │ │ │ │ ├── B_score.png │ │ │ │ ├── C_score.png │ │ │ │ ├── D_score.png │ │ │ │ ├── F_score.png │ │ │ │ └── mockup.png │ │ ├── survey │ │ │ ├── prep │ │ │ │ ├── 5_utils.ipynb │ │ │ │ ├── difficult_aspects_themes.csv │ │ │ │ ├── features_changes_themes.csv │ │ │ │ ├── first_experience_enhancements_themes.csv │ │ │ │ ├── hinderances_themes.csv │ │ │ │ ├── integrations_themes.csv │ │ │ │ ├── pleasant_aspects_themes.csv │ │ │ │ ├── roles.csv │ │ │ │ ├── survey_short_columns.csv │ │ │ │ ├── widgets │ │ │ │ │ └── survey-explorer │ │ │ │ │ │ └── survey-explorer.html │ │ │ │ ├── workflow_needs_addressed_themes.csv │ │ │ │ └── workflow_needs_not_addressed_themes.csv │ │ │ └── report_dashboard_decl_widgets.ipynb │ │ ├── taxi │ │ │ ├── fares.csv │ │ │ ├── index.ipynb │ │ │ ├── trips_1.csv │ │ │ ├── trips_2.csv │ │ │ ├── trips_3.csv │ │ │ ├── trips_4.csv │ │ │ ├── trips_5.csv │ │ │ └── trips_6.csv │ │ ├── todo │ │ │ └── Todo_List_Tutorial.ipynb │ │ └── tour │ │ │ └── Walkthrough.ipynb │ ├── examples │ │ ├── ArxivBokeh.ipynb │ │ ├── BokehUrthBasic.ipynb │ │ ├── bcard.css │ │ ├── urth-core-bind.ipynb │ │ ├── urth-core-channel.ipynb │ │ ├── urth-core-dataframe.ipynb │ │ ├── urth-core-function.ipynb │ │ ├── urth-core-import.ipynb │ │ ├── urth-core-query.ipynb │ │ ├── urth-core-watch.ipynb │ │ ├── urth-pyspark-streaming.ipynb │ │ ├── urth-r-widgets-query.ipynb │ │ ├── urth-r-widgets.ipynb │ │ ├── urth-scala-widgets.ipynb │ │ ├── urth-viz-chart.ipynb │ │ ├── urth-viz-cloud.ipynb │ │ ├── urth-viz-ipywidget.ipynb │ │ └── urth-viz-table.ipynb │ ├── tests │ │ ├── Walkthrough.ipynb │ │ ├── urth-core-bind.ipynb │ │ ├── urth-r-widgets.ipynb │ │ └── urth-viz-table.ipynb │ └── urth-core-query-scala.ipynb ├── r │ └── install_prereq.r ├── read_release_version.py ├── sbt_plugin_config │ └── gpg.sbt └── scripts │ └── jupyter-declarativewidgets ├── gulpfile.js ├── kernel-python ├── declarativewidgets │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ ├── test_urth_widget.py │ │ ├── test_widget_channel.py │ │ ├── test_widget_channels.py │ │ └── test_widget_function.py │ ├── urth_exception.py │ ├── urth_widget.py │ ├── util │ │ ├── __init__.py │ │ ├── base_serializer_py2.py │ │ ├── base_serializer_py3.py │ │ ├── explore.py │ │ ├── functions.py │ │ ├── functions_py2.py │ │ ├── functions_py3.py │ │ ├── query │ │ │ ├── __init__.py │ │ │ ├── pandas.py │ │ │ ├── spark.py │ │ │ └── tests │ │ │ │ ├── __init__.py │ │ │ │ ├── test_pandas.py │ │ │ │ └── test_spark.py │ │ ├── serializer.py │ │ ├── serializer_registrar.py │ │ ├── serializers.py │ │ └── tests │ │ │ ├── __init__.py │ │ │ ├── test_explore.py │ │ │ ├── test_functions.py │ │ │ └── test_functions_py3.py │ ├── widget_channels.py │ ├── widget_dataframe.py │ ├── widget_function.py │ └── widget_ipw_proxy.py └── urth │ ├── __init__.py │ └── widgets │ ├── __init__.py │ └── widget_channels.py ├── kernel-r └── declarativewidgets │ ├── .Rbuildignore │ ├── DESCRIPTION │ ├── NAMESPACE │ ├── R │ ├── explore.r │ ├── querier.r │ ├── queriers.r │ ├── serializer.r │ ├── serializers.r │ ├── widget.r │ ├── widget_channels.r │ ├── widget_dataframe.r │ └── widget_function.r │ ├── declarativewidgets.Rproj │ ├── man │ └── widgets-package.Rd │ └── tests │ ├── testthat.R │ └── testthat │ └── test_df_queries.R ├── kernel-scala ├── build.sbt └── src │ ├── main │ └── scala │ │ ├── declarativewidgets │ │ ├── Widget.scala │ │ ├── WidgetChannels.scala │ │ ├── WidgetDataFrame.scala │ │ ├── WidgetFunction.scala │ │ ├── exceptions │ │ │ └── WidgetNotAvailableException.scala │ │ ├── package.scala │ │ ├── query │ │ │ └── QuerySupport.scala │ │ └── util │ │ │ ├── Explore.scala │ │ │ ├── FunctionSupport.scala │ │ │ ├── MessageSupport.scala │ │ │ └── SerializationSupport.scala │ │ └── urth │ │ └── widgets │ │ └── package.scala │ └── test │ └── scala │ └── declarativewidgets │ ├── WidgetChannelsSpec.scala │ ├── WidgetDataFrameSpec.scala │ ├── WidgetFunctionSpec.scala │ ├── WidgetSpec.scala │ ├── query │ └── QuerySupportSpec.scala │ └── util │ ├── FunctionSupportSpec.scala │ ├── MessageSupportSpec.scala │ └── SerializationSupportSpec.scala ├── nb-extension ├── css │ └── main.css ├── js │ ├── init │ │ └── init.js │ ├── main.js │ └── widgets │ │ └── DeclWidgetModel.js └── python │ ├── declarativewidgets │ ├── __init__.py │ └── extensionapp.py │ └── urth │ └── widgets │ └── ext │ ├── __init__.py │ ├── _version.py │ └── urth_import.py ├── package.json ├── setup.py ├── system-test ├── .gitignore ├── urth-core-bind-specs.js ├── urth-r-widgets-specs.js ├── urth-system-test-specs.js ├── urth-viz-table-specs.js └── utils │ └── boilerplate.js └── wct.conf.js /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "analytics": false, 3 | "interactive": false 4 | } 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | 26 | # PyInstaller 27 | # Usually these files are written by a python script from a template 28 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 29 | *.manifest 30 | *.spec 31 | 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | 36 | # Unit test / coverage reports 37 | htmlcov/ 38 | .tox/ 39 | .coverage 40 | .coverage.* 41 | .cache 42 | nosetests.xml 43 | coverage.xml 44 | *,cover 45 | 46 | # Translations 47 | *.mo 48 | *.pot 49 | 50 | # Django stuff: 51 | *.log 52 | 53 | # Sphinx documentation 54 | docs/_build/ 55 | 56 | # Project specific 57 | target/ 58 | .DS_Store 59 | .idea/ 60 | *.egg-info/ 61 | *.iml 62 | bower_components 63 | *.pyc 64 | *.log 65 | node_modules/ 66 | npm-debug.* 67 | .Rproj.user 68 | .Rhistory 69 | .watch 70 | .watch-docs 71 | project/ 72 | SELENIUM_PID 73 | .ipynb_checkpoints/ 74 | metastore_db/ 75 | Untitled*.ipynb 76 | ivy 77 | -------------------------------------------------------------------------------- /.pairs: -------------------------------------------------------------------------------- 1 | # .pairs - configuration for 'git pair' 2 | pairs: 3 | # : [; ] 4 | # URTH.WIDGETS! Team 5 | al: Angel Luu; angel.luu 6 | dl: Drew Logsdon; dalogsdo 7 | dw: Drew Walters; drewwalt 8 | jp: Javier Pedemonte; pedemont 9 | sw: Sean Welleck; swelleck 10 | gb: Gino Bustelo; lbustelo 11 | zcm: Zack Morris; zmorris 12 | ap: Adam Peller; apeller 13 | email: 14 | prefix: pair 15 | domain: us.ibm.com 16 | no_solo_prefix: true 17 | email_addresses: 18 | dl: dalogsdon@gmail.com 19 | jp: javier@pedemonte.us 20 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | env: 2 | global: 3 | - DISPLAY=:99.0 4 | - PORT_MAP="-p 4000:8888" 5 | - BASEURL=http://declarativewidgets.org:4000 6 | - BROWSER_LIST="chrome firefox safari InternetExplorer" 7 | 8 | sudo: required 9 | 10 | language: node_js 11 | 12 | node_js: 13 | - "4.1" 14 | 15 | services: 16 | - docker 17 | 18 | addons: 19 | sauce_connect: 20 | no_ssl_bump_domains: all 21 | hosts: 22 | - declarativewidgets.org 23 | 24 | before_deploy: 25 | openssl aes-256-cbc -K $encrypted_9067f25a9380_key -iv $encrypted_9067f25a9380_iv -in etc/.gpg/secring.gpg.enc -out etc/.gpg/secring.gpg -d 26 | 27 | before_script: 28 | - curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash - 29 | - sh -e /etc/init.d/xvfb start 30 | 31 | script: 32 | - make all 33 | 34 | deploy: 35 | skip_cleanup: true 36 | provider: script 37 | script: make release 38 | on: 39 | tags: true 40 | 41 | notifications: 42 | slack: cloudet:rMfRKhvsbZuCIRZpTct3kBI4#jupyter-declwidgets 43 | email: 44 | on_success: change 45 | on_failure: always 46 | 47 | branches: 48 | only: 49 | - master 50 | - /^0\.7\.0\.dev[0-9]+$/ 51 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Adam Peller (peller) 2 | Angel Luu (aluu317) 3 | Drew Walters (deedubbu) 4 | Gino Bustelo (lbustelo) 5 | Sean Welleck (wellecks) 6 | Zack Morris (zackmorris) -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | ## 0.7.0 (2016-09-22) 3 | * New explore function that renders explorer UI for DataFrames 4 | * Allow access to functions within instances 5 | * Allow control to local store of binding variables 6 | * Remove requirement to have PySpark installed 7 | 8 | ## 0.6.2 (2016-07-27) 9 | * Misc fixes back ported from master 10 | * Publishing Toree support JAR to maven 11 | 12 | ## 0.6.1 (2016-07-01) 13 | * Fix to issue when Run All and using channel.set 14 | * Minor fixes to declarative queries 15 | 16 | ## 0.6.0 (2016-06-17) 17 | * User must manually activate declarativewidgets using a code cell 18 | * Declarative query support for dataframes 19 | * Usage documentation 20 | * Deprecation of `urth.widgets` module. Use `declarativewidgets` instead 21 | 22 | ## 0.5.3 (2016-06-08) 23 | * Fixes to timing error related to loading order of this extension in relation to ipywidgets/jupyter-js-widgets 24 | * Fixes to support running Windows 25 | * Added selection-info on `` to get cell coordinates 26 | 27 | ## 0.5.2 (2016-05-03) 28 | * Support for selectionIndex in urth-viz-* 29 | * Custom serializers in R 30 | 31 | ## 0.5.1 (2016-04-29) 32 | * Support for ipywidgets 5.1.1+ 33 | * Fixes to support alternate non-notebook runtimes 34 | 35 | ## 0.5.0 (2016-27-16) 36 | * Support for Jupyter 4.2 and ipywidgets 5.0 37 | * Support for R language through IRkernel 38 | * `selection` property on charts references row data. Chart-specific selection data available as `selectionInfo` 39 | * `selection` property on charts references a single row rather than Array of length==1, continues to return Array of rows when `multiSelect` is used. 40 | * New element to display help documentation inline 41 | * New element to embed an ipywidget in a declarative template 42 | * Better support for dependency injection when starting up declarativewidgets 43 | 44 | ## 0.4.5 (2016-04-06) 45 | * Progress indications on templates while dependencies load 46 | 47 | ## 0.4.4 (2016-04-01) 48 | * Fix regression in selection in charts 49 | 50 | ## 0.4.3 (2016-03-24) 51 | * Ability to inspect the content of an urth-core-channel 52 | * Improved selection content from urth-viz-chart elements 53 | * Misc bug fixes on urth-viz-chart 54 | * Ability to peg Polymer version at runtime [1.2.4-1.4.0) 55 | * Fixes to urth-core-function to better support complex parameters 56 | * Serialization fixes for Toree/Scala 57 | 58 | ## 0.4.2 (2016-03-03) 59 | * Make selection in urth-viz-table available as an object 60 | * Allow height, width, and margin adjustment to urth-viz-chart's 61 | 62 | ## 0.4.1 (2016-02-23) 63 | * Support for Polymer 1.3 64 | * Fixes to complex object changes across templates 65 | * Delay template rendering until imports completed 66 | 67 | ## 0.4.0 (2016-02-12) 68 | * Upgrade to use Apache Toree for scala kernel 69 | * Upgrade to Polymer 1.2.4+ 70 | 71 | ## 0.3.2 (2016-03-22) 72 | * Ability to peg Polymer version at runtime `[1.2.4-1.4.0)` 73 | 74 | ## 0.3.1 (2016-02-08) 75 | 76 | * Support for Polymer 1.2.4+ 77 | 78 | ## 0.3.0 (2016-01-20) 79 | 80 | * Modified install process to rely on `jupyter activate/deactivate` 81 | * New element `urth-core-channel` and javascript API to channel variables 82 | * New element `urth-core-watch` 83 | * Fixes to sizing of 'urth-viz-table' 84 | * Serialization support for Pandas.Series 85 | 86 | ## 0.2.0 (2015-12-01) 87 | 88 | * Make compatible with Jupyter Notebook 4.0.x 89 | * Several fixes to `urth-viz-table` around selection 90 | * Support for `display_data` type messages sent when a function is invoked through `urth-core-function` 91 | * Added support to label axis on `urth-viz-chart` elements 92 | 93 | ## 0.1.4 (2016-03-22) 94 | * Ability to peg Polymer version at runtime 95 | 96 | ## 0.1.3 (2016-02-16) 97 | * Upgrade to Polymer 1.2.4 98 | * Allow graceful degradation when server extensions are not available 99 | 100 | ## 0.1.2 (2016-01-18) 101 | * Backport fixes from master 102 | 103 | ## 0.1.1 (2015-12-01) 104 | 105 | * Backport of UX fixes from 0.2.0 106 | * Keep compatible with IPython Notebook 3.2.x 107 | 108 | ## 0.1.0 (2015-11-17) 109 | 110 | * First PyPI release 111 | * Compatible with IPython Notebook 3.2.x on Python 2.7 or Python 3.3+ -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # Licensing terms 2 | 3 | This project is licensed under the terms of the Modified BSD License 4 | (also known as New or Revised or 3-Clause BSD), as follows: 5 | 6 | - Copyright (c) 2001-2015, IPython Development Team 7 | - Copyright (c) 2015-, Jupyter Development Team 8 | 9 | All rights reserved. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | 14 | Redistributions of source code must retain the above copyright notice, this 15 | list of conditions and the following disclaimer. 16 | 17 | Redistributions in binary form must reproduce the above copyright notice, this 18 | list of conditions and the following disclaimer in the documentation and/or 19 | other materials provided with the distribution. 20 | 21 | Neither the name of the Jupyter Development Team nor the names of its 22 | contributors may be used to endorse or promote products derived from this 23 | software without specific prior written permission. 24 | 25 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 26 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 27 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 28 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 29 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 31 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 32 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 33 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 34 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | 36 | ## About the Jupyter Development Team 37 | 38 | The Jupyter Development Team is the set of all contributors to the Jupyter project. 39 | This includes all of the Jupyter Subprojects, which are the different repositories 40 | under the [jupyter](https://github.com/jupyter/) GitHub organization. 41 | 42 | The core team that coordinates development on GitHub can be found here: 43 | https://github.com/jupyter/. 44 | 45 | ## Our copyright policy 46 | 47 | Jupyter uses a shared copyright model. Each contributor maintains copyright 48 | over their contributions to Jupyter. But, it is important to note that these 49 | contributions are typically only changes to the repositories. Thus, the Jupyter 50 | source code, in its entirety is not the copyright of any single person or 51 | institution. Instead, it is the collective copyright of the entire Jupyter 52 | Development Team. If individual contributors want to maintain a record of what 53 | changes/contributions they have specific copyright on, they should indicate 54 | their copyright in the commit message of the change, when they commit the 55 | change to one of the Jupyter repositories. 56 | 57 | With this in mind, the following banner should be used in any source code file 58 | to indicate the copyright and license terms: 59 | 60 | # Copyright (c) Jupyter Development Team. 61 | # Distributed under the terms of the Modified BSD License. 62 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include declarativewidgets/static *.html *.js *.css *.jar *.json *.tgz *.md 2 | include VERSION 3 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "urth-widgets", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Jupyter Community" 6 | ], 7 | "description": "Jupyter web component based widget notebook extension.", 8 | "main": "src/nb-extension/main.js", 9 | "keywords": [ 10 | "urth", 11 | "polymer", 12 | "jupyter" 13 | ], 14 | "ignore": [ 15 | "**/.*", 16 | "node_modules", 17 | "bower_components", 18 | "test" 19 | ], 20 | "private": true, 21 | "dependencies": { 22 | "polymer": "Polymer/polymer#>=1.2.4 <=1.5.0", 23 | "webcomponentsjs": "^0.7.2" 24 | }, 25 | "devDependencies": { 26 | "web-component-tester": "*", 27 | "test-fixture": "PolymerElements/test-fixture#^1.0.0" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /elements/urth-core-behaviors/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "urth-core-behaviors", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Jupyter Community" 6 | ], 7 | "description": "Provides a set of behaviors for the urth-core elements.", 8 | "main": [ 9 | "jupyter-kernel-observer.html", 10 | "jupyter-widget-behavior.html" 11 | ], 12 | "keywords": [ 13 | "urth", 14 | "web-components", 15 | "jupyter" 16 | ], 17 | "ignore": [ 18 | "**/.*", 19 | "node_modules", 20 | "bower_components", 21 | "test", 22 | "tests" 23 | ], 24 | "dependencies": { 25 | "promise-polyfill": "polymerlabs/promise-polyfill#^1.0.0" 26 | }, 27 | "private": true 28 | } 29 | -------------------------------------------------------------------------------- /elements/urth-core-behaviors/error-display-behavior.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 9 | 10 | 11 | 12 | 53 | -------------------------------------------------------------------------------- /elements/urth-core-behaviors/execution-complete-behavior.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 9 | 10 | 11 | 44 | -------------------------------------------------------------------------------- /elements/urth-core-behaviors/jupyter-kernel-observer.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 9 | 10 | 11 | 65 | -------------------------------------------------------------------------------- /elements/urth-core-behaviors/jupyter-notebook-env.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 9 | 44 | -------------------------------------------------------------------------------- /elements/urth-core-behaviors/jupyter-persist-behavior.html: -------------------------------------------------------------------------------- 1 | 5 | 79 | -------------------------------------------------------------------------------- /elements/urth-core-behaviors/jupyter-save-behavior.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 43 | -------------------------------------------------------------------------------- /elements/urth-core-behaviors/shared-styles.html: -------------------------------------------------------------------------------- 1 | 2 | 13 | -------------------------------------------------------------------------------- /elements/urth-core-behaviors/test/jupyter-save-behavior.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | urth-core-function tests 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 31 | 32 | 33 | 36 | 37 | 38 | 40 | 41 | 59 | 60 | 61 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /elements/urth-core-bind/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "urth-core-bind", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Jupyter Community" 6 | ], 7 | "description": "Data binding through shared channels.", 8 | "main": "urth-core-bind.html", 9 | "keywords": [ 10 | "urth", 11 | "web-components", 12 | "jupyter" 13 | ], 14 | "ignore": [ 15 | "**/.*", 16 | "node_modules", 17 | "bower_components", 18 | "test", 19 | "tests" 20 | ], 21 | "dependencies": { 22 | "polymer": "Polymer/polymer#^1.2.4", 23 | "iron-ajax": "PolymerElements/iron-ajax#^1.0.4", 24 | "promise-polyfill": "polymerlabs/promise-polyfill#^1.0.0" 25 | }, 26 | "private": true 27 | } 28 | -------------------------------------------------------------------------------- /elements/urth-core-channel/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "urth-core-channel", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Jupyter Community" 6 | ], 7 | "description": "Monostate data channel.", 8 | "main": "urth-core-channel.html", 9 | "keywords": [ 10 | "urth", 11 | "web-components", 12 | "jupyter" 13 | ], 14 | "ignore": [ 15 | "**/.*", 16 | "node_modules", 17 | "bower_components", 18 | "test", 19 | "tests" 20 | ], 21 | "dependencies": { 22 | "polymer": "Polymer/polymer#^1.2.4" 23 | }, 24 | "private": true 25 | } 26 | -------------------------------------------------------------------------------- /elements/urth-core-channel/urth-core-channel-item.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 23 | 24 | 25 | 76 | 77 | -------------------------------------------------------------------------------- /elements/urth-core-dataframe/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "urth-core-dataframe", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Jupyter Community" 6 | ], 7 | "description": "Dataframe binding.", 8 | "main": "urth-core-dataframe.html", 9 | "keywords": [ 10 | "urth", 11 | "web-components", 12 | "jupyter" 13 | ], 14 | "ignore": [ 15 | "**/.*", 16 | "node_modules", 17 | "bower_components", 18 | "test", 19 | "tests" 20 | ], 21 | "dependencies": { 22 | "polymer": "Polymer/polymer#^1.2.4" 23 | }, 24 | "private": true 25 | } 26 | -------------------------------------------------------------------------------- /elements/urth-core-dataframe/test/urth-core-query-agg.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | urth-core-function tests 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 31 | 34 | 35 | 36 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /elements/urth-core-dataframe/test/urth-core-query-behavior.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | urth-core-function tests 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 31 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /elements/urth-core-dataframe/urth-core-query-agg.html: -------------------------------------------------------------------------------- 1 | !-- 2 | # Copyright (c) Jupyter Development Team. 3 | # Distributed under the terms of the Modified BSD License. 4 | --> 5 | 6 | 7 | 32 | 33 | 38 | 39 | 40 | 92 | -------------------------------------------------------------------------------- /elements/urth-core-dataframe/urth-core-query-behavior.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 10 | 41 | -------------------------------------------------------------------------------- /elements/urth-core-dataframe/urth-core-query-sort.html: -------------------------------------------------------------------------------- 1 | !-- 2 | # Copyright (c) Jupyter Development Team. 3 | # Distributed under the terms of the Modified BSD License. 4 | --> 5 | 6 | 7 | 8 | 25 | 26 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /elements/urth-core-function/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "urth-core-function", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Jupyter Community" 6 | ], 7 | "description": "Client side interface to Jupyter functions.", 8 | "main": "urth-core-function.html", 9 | "keywords": [ 10 | "urth", 11 | "web-components", 12 | "jupyter" 13 | ], 14 | "ignore": [ 15 | "**/.*", 16 | "node_modules", 17 | "bower_components", 18 | "test", 19 | "tests" 20 | ], 21 | "dependencies": { 22 | "polymer": "Polymer/polymer#^1.2.4" 23 | }, 24 | "private": true 25 | } 26 | -------------------------------------------------------------------------------- /elements/urth-core-import/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "urth-core-import", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Jupyter Community" 6 | ], 7 | "description": "Dynamically install web components.", 8 | "main": "urth-core-import.html", 9 | "keywords": [ 10 | "urth", 11 | "web-components", 12 | "jupyter" 13 | ], 14 | "ignore": [ 15 | "**/.*", 16 | "node_modules", 17 | "bower_components", 18 | "test", 19 | "tests" 20 | ], 21 | "dependencies": { 22 | "polymer": "Polymer/polymer#^1.2.4", 23 | "iron-ajax": "PolymerElements/iron-ajax#^1.0.4", 24 | "promise-polyfill": "polymerlabs/promise-polyfill#^1.0.0" 25 | }, 26 | "private": true 27 | } 28 | -------------------------------------------------------------------------------- /elements/urth-core-storage/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "urth-core-storage", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Jupyter Community" 6 | ], 7 | "description": "Storage interface.", 8 | "main": "urth-core-storage.html", 9 | "keywords": [ 10 | "urth", 11 | "web-components", 12 | "jupyter" 13 | ], 14 | "ignore": [ 15 | "**/.*", 16 | "node_modules", 17 | "bower_components", 18 | "test", 19 | "tests" 20 | ], 21 | "dependencies": { 22 | "polymer": "Polymer/polymer#^1.2.4" 23 | }, 24 | "private": true 25 | } 26 | -------------------------------------------------------------------------------- /elements/urth-core-watch/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "urth-core-watch", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Jupyter Community" 6 | ], 7 | "description": "Watches changes to a variable and invokes children elements.", 8 | "main": "urth-core-watch.html", 9 | "keywords": [ 10 | "urth", 11 | "web-components", 12 | "jupyter" 13 | ], 14 | "ignore": [ 15 | "**/.*", 16 | "node_modules", 17 | "bower_components", 18 | "test", 19 | "tests" 20 | ], 21 | "dependencies": { 22 | "polymer": "Polymer/polymer#^1.2.4" 23 | }, 24 | "private": true 25 | } 26 | -------------------------------------------------------------------------------- /elements/urth-core-watch/urth-core-watch.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 33 | 34 | 37 | 68 | 69 | -------------------------------------------------------------------------------- /elements/urth-help/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "urth-help", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Jupyter Community" 6 | ], 7 | "description": "Represents a widget that displays urth element's documentation.", 8 | "main": "urth-help.html", 9 | "keywords": [ 10 | "urth", 11 | "area", 12 | "chart", 13 | "web-components" 14 | ], 15 | "ignore": [ 16 | "**/.*", 17 | "node_modules", 18 | "bower_components", 19 | "test", 20 | "tests" 21 | ], 22 | "dependencies": { 23 | "polymer": "Polymer/polymer#^1.2.4", 24 | "paper-icon-button": "PolymerElements/paper-icon-button#^1.0.0", 25 | "iron-icons": "PolymerElements/iron-icons#^1.0.0" 26 | }, 27 | "private": true 28 | } 29 | -------------------------------------------------------------------------------- /elements/urth-help/urth-help.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 15 | 16 | 17 | 44 | 63 | 64 | -------------------------------------------------------------------------------- /elements/urth-viz-area/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "urth-viz-area", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Jupyter Community" 6 | ], 7 | "description": "Represents a widget that draws a area chart.", 8 | "main": "urth-viz-area.html", 9 | "keywords": [ 10 | "urth", 11 | "area", 12 | "chart", 13 | "web-components" 14 | ], 15 | "ignore": [ 16 | "**/.*", 17 | "node_modules", 18 | "bower_components", 19 | "test", 20 | "tests" 21 | ], 22 | "dependencies": { 23 | "polymer": "Polymer/polymer#^1.2.4" 24 | }, 25 | "private": true 26 | } 27 | -------------------------------------------------------------------------------- /elements/urth-viz-area/urth-viz-area.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 18 | 19 | 20 | 21 | 22 | 23 | 32 | 33 | 34 | 53 | -------------------------------------------------------------------------------- /elements/urth-viz-bar/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "urth-viz-bar", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Jupyter Community" 6 | ], 7 | "description": "Represents a widget that draws a bar chart.", 8 | "main": "urth-viz-bar.html", 9 | "keywords": [ 10 | "urth", 11 | "bar", 12 | "chart", 13 | "web-components" 14 | ], 15 | "ignore": [ 16 | "**/.*", 17 | "node_modules", 18 | "bower_components", 19 | "test", 20 | "tests" 21 | ], 22 | "dependencies": { 23 | "polymer": "Polymer/polymer#^1.2.4" 24 | }, 25 | "private": true 26 | } 27 | -------------------------------------------------------------------------------- /elements/urth-viz-bar/urth-viz-bar.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 18 | 19 | 20 | 21 | 22 | 23 | 32 | 33 | 34 | 53 | -------------------------------------------------------------------------------- /elements/urth-viz-behaviors/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "urth-viz-behaviors", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Jupyter Community" 6 | ], 7 | "description": "Provides a set of behaviors for the urth-viz elements.", 8 | "keywords": [ 9 | "urth", 10 | "web-components", 11 | "jupyter" 12 | ], 13 | "ignore": [ 14 | "**/.*", 15 | "node_modules", 16 | "bower_components", 17 | "test", 18 | "tests" 19 | ], 20 | "private": true 21 | } 22 | -------------------------------------------------------------------------------- /elements/urth-viz-behaviors/urth-viz-selection-behavior.html: -------------------------------------------------------------------------------- 1 | 5 | 64 | -------------------------------------------------------------------------------- /elements/urth-viz-chart/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "urth-viz-chart", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Jupyter Community" 6 | ], 7 | "description": "Represents a widget that draws a chart.", 8 | "main": "urth-viz-chart.html", 9 | "keywords": [ 10 | "urth", 11 | "chart", 12 | "web-components" 13 | ], 14 | "ignore": [ 15 | "**/.*", 16 | "node_modules", 17 | "bower_components", 18 | "test", 19 | "tests" 20 | ], 21 | "dependencies": { 22 | "nvd3": "1.8.4", 23 | "polymer": "Polymer/polymer#^1.2.4", 24 | "paper-item": "PolymerElements/paper-item#^1.0.0", 25 | "paper-menu": "PolymerElements/paper-menu#^1.0.0", 26 | "requirejs": "^2.1.0", 27 | "paper-dropdown-menu": "PolymerElements/paper-dropdown-menu#^1.0.0" 28 | }, 29 | "private": true 30 | } 31 | -------------------------------------------------------------------------------- /elements/urth-viz-chart/test/urth-viz-chart.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | urth-viz-chart tests 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 28 | 29 | 32 | 33 | 34 | 35 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /elements/urth-viz-chart/urth-viz-chart.css: -------------------------------------------------------------------------------- 1 | #chart1 .selected { fill: yellow !important; } 2 | #settings-section { display: none; } 3 | -------------------------------------------------------------------------------- /elements/urth-viz-chart/urth-viz-chart.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 23 | 24 | 25 | 26 | 27 | 52 | 53 | 97 | 98 | -------------------------------------------------------------------------------- /elements/urth-viz-cloud/README.md: -------------------------------------------------------------------------------- 1 | # Word Cloud widget for the Jupyter notebook 2 | 3 | Polymer wrapper for Jason Davies' d3-cloud (https://github.com/jasondavies/d3-cloud) -------------------------------------------------------------------------------- /elements/urth-viz-cloud/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "urth-viz-cloud", 3 | "version": "0.0.1", 4 | "description": "Represents a widget that displays a word cloud", 5 | "main": "urth-viz-cloud.html", 6 | "keywords": [ 7 | "urth", 8 | "word cloud", 9 | "web-components" 10 | ], 11 | "ignore": [ 12 | "**/.*", 13 | "node_modules", 14 | "bower_components", 15 | "test", 16 | "tests" 17 | ], 18 | "dependencies": { 19 | "polymer": "Polymer/polymer#^1.2.4", 20 | "iron-resizable-behavior": "PolymerElements/iron-resizable-behavior#^1.0.0", 21 | "d3-cloud": "latest", 22 | "d3": "^3", 23 | "requirejs": "^2.1.0" 24 | }, 25 | "private": true 26 | } 27 | -------------------------------------------------------------------------------- /elements/urth-viz-cloud/test/urth-viz-cloud.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | urth-viz-cloud tests 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 28 | 29 | 32 | 33 | 34 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /elements/urth-viz-col/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "urth-viz-col", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Jupyter Community" 6 | ], 7 | "description": "Provides metadata representing a column of data, to be used as a child element of a widget representing tabular data.", 8 | "main": "urth-viz-col.html", 9 | "keywords": [ 10 | "urth", 11 | "chart", 12 | "table", 13 | "web-components" 14 | ], 15 | "ignore": [ 16 | "**/.*", 17 | "node_modules", 18 | "bower_components", 19 | "test", 20 | "tests" 21 | ], 22 | "dependencies": { 23 | "polymer": "Polymer/polymer#^1.2.4" 24 | }, 25 | "private": true 26 | } 27 | -------------------------------------------------------------------------------- /elements/urth-viz-col/urth-viz-col.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 54 | -------------------------------------------------------------------------------- /elements/urth-viz-ipywidget/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "urth-viz-ipywidget", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Jupyter Community" 6 | ], 7 | "description": "Client side interface to IPywidgets.", 8 | "main": "urth-viz-ipywidget.html", 9 | "keywords": [ 10 | "urth", 11 | "web-components", 12 | "jupyter", 13 | "ipywidgets" 14 | ], 15 | "ignore": [ 16 | "**/.*", 17 | "node_modules", 18 | "bower_components", 19 | "test", 20 | "tests" 21 | ], 22 | "dependencies": { 23 | "polymer": "Polymer/polymer#^1.2.4" 24 | }, 25 | "private": true 26 | } 27 | -------------------------------------------------------------------------------- /elements/urth-viz-line/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "urth-viz-line", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Jupyter Community" 6 | ], 7 | "description": "Represents a widget that draws a line chart.", 8 | "main": "urth-viz-line.html", 9 | "keywords": [ 10 | "urth", 11 | "line", 12 | "chart", 13 | "web-components" 14 | ], 15 | "ignore": [ 16 | "**/.*", 17 | "node_modules", 18 | "bower_components", 19 | "test", 20 | "tests" 21 | ], 22 | "dependencies": { 23 | "polymer": "Polymer/polymer#^1.2.4" 24 | }, 25 | "private": true 26 | } 27 | -------------------------------------------------------------------------------- /elements/urth-viz-line/urth-viz-line.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 18 | 19 | 20 | 21 | 22 | 23 | 32 | 33 | 34 | 53 | -------------------------------------------------------------------------------- /elements/urth-viz-pie/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "urth-viz-pie", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Jupyter Community" 6 | ], 7 | "description": "Represents a widget that draws a pie chart.", 8 | "main": "urth-viz-pie.html", 9 | "keywords": [ 10 | "urth", 11 | "pie", 12 | "chart", 13 | "web-components" 14 | ], 15 | "ignore": [ 16 | "**/.*", 17 | "node_modules", 18 | "bower_components", 19 | "test", 20 | "tests" 21 | ], 22 | "dependencies": { 23 | "polymer": "Polymer/polymer#^1.2.4" 24 | }, 25 | "private": true 26 | } 27 | -------------------------------------------------------------------------------- /elements/urth-viz-pie/urth-viz-pie.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 22 | 23 | 24 | 25 | 26 | 27 | 52 | 53 | 54 | 73 | -------------------------------------------------------------------------------- /elements/urth-viz-scatter/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "urth-viz-scatter", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Jupyter Community" 6 | ], 7 | "description": "Represents a widget that draws a scatter chart.", 8 | "main": "urth-viz-scatter.html", 9 | "keywords": [ 10 | "urth", 11 | "scatter", 12 | "chart", 13 | "web-components" 14 | ], 15 | "ignore": [ 16 | "**/.*", 17 | "node_modules", 18 | "bower_components", 19 | "test", 20 | "tests" 21 | ], 22 | "dependencies": { 23 | "polymer": "Polymer/polymer#^1.2.4" 24 | }, 25 | "private": true 26 | } 27 | -------------------------------------------------------------------------------- /elements/urth-viz-scatter/urth-viz-scatter.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 18 | 19 | 20 | 21 | 22 | 23 | 32 | 33 | 34 | 53 | -------------------------------------------------------------------------------- /elements/urth-viz-table/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "urth-viz-table", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Jupyter Community" 6 | ], 7 | "description": "An element that displays a table with specified data and column headers.", 8 | "main": "urth-viz-table.html", 9 | "keywords": [ 10 | "urth", 11 | "table", 12 | "web-components" 13 | ], 14 | "ignore": [ 15 | "**/.*", 16 | "node_modules", 17 | "bower_components", 18 | "test", 19 | "tests" 20 | ], 21 | "dependencies": { 22 | "handsontable": "handsontable/handsontable#^0.25", 23 | "polymer": "Polymer/polymer#^1.2.4", 24 | "requirejs": "^2.1.0" 25 | }, 26 | "private": true 27 | } 28 | -------------------------------------------------------------------------------- /etc/.gpg/secring.gpg.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter/declarativewidgets/d3422746e20780e7d1655337b0c3128962711b52/etc/.gpg/secring.gpg.enc -------------------------------------------------------------------------------- /etc/docs/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "urth-widgets-docs", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "Jupyter Community" 6 | ], 7 | "description": "Documentation for Jupyter declaritive widgets notebook extension.", 8 | "main": "site/index.html", 9 | "keywords": [ 10 | "urth", 11 | "polymer", 12 | "jupyter" 13 | ], 14 | "ignore": [ 15 | "**/.*", 16 | "node_modules", 17 | "bower_components", 18 | "test" 19 | ], 20 | "private": true, 21 | "dependencies": { 22 | "app-route": "PolymerElements/app-route#^0.9.1", 23 | "polymer": "Polymer/polymer#^1.2.4", 24 | "iron-ajax": "PolymerElements/iron-ajax#^1.0.0", 25 | "iron-component-page": "PolymerElements/iron-component-page#^1.1.4", 26 | "iron-selector": "PolymerElements/iron-selector#^1.0.8", 27 | "paper-drawer-panel": "PolymerElements/paper-drawer-panel#^1.0.4", 28 | "paper-header-panel": "PolymerElements/paper-header-panel#^1.0.5", 29 | "paper-icon-button": "PolymerElements/paper-icon-button#^1.0.5", 30 | "paper-toolbar": "PolymerElements/paper-toolbar#^1.0.4", 31 | "marked-element": "PolymerElements/marked-element#^1.0.0", 32 | "webcomponentsjs": "^0.7.2" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /etc/docs/hydrolyze_elements.js: -------------------------------------------------------------------------------- 1 | var hyd = require('hydrolysis'), 2 | fs = require('fs'); 3 | 4 | if (!process.argv[2] || !process.argv[3]) { 5 | console.log('Usage: ' + process.argv[1] + ' inputFile outputFile'); 6 | process.exit(1); 7 | } 8 | 9 | hyd.Analyzer.analyze(process.argv[2], { 10 | clean: true, 11 | filter: function(href){ 12 | if ((href.indexOf('bower_components') > -1 && 13 | href.indexOf('urth') === -1) || 14 | href.indexOf("http://") > -1 || 15 | href.indexOf("https://") > -1) { 16 | return true; 17 | } else { 18 | return false; 19 | } 20 | } 21 | }).then(function(analyzer) { 22 | function clean(item) { 23 | item.scriptElement = undefined; 24 | item.javascriptNode = undefined; 25 | Array.isArray(item.properties) && item.properties.forEach(function(property) { 26 | property.javascriptNode = undefined; 27 | property.observerNode = undefined; 28 | }); 29 | } 30 | 31 | analyzer.elements.forEach(clean); 32 | analyzer.behaviors.forEach(clean); 33 | var myobj = { 34 | behaviors: analyzer.behaviors, 35 | behaviorsByName: {}, 36 | elements: analyzer.elements, 37 | elementsByTagName: {}, 38 | features: [] 39 | }; 40 | myobj.elements.forEach(function(element) { 41 | if (!myobj.elementsByTagName[element.is]) { 42 | myobj.elementsByTagName[element.is] = element; 43 | } 44 | }); 45 | myobj.behaviors.forEach(function(behavior) { 46 | if (!myobj.behaviorsByName[behavior.is]) { 47 | myobj.behaviorsByName[behavior.is] = behavior; 48 | } 49 | }); 50 | fs.writeFileSync(process.argv[3], JSON.stringify(myobj)); 51 | }); 52 | -------------------------------------------------------------------------------- /etc/docs/site/css/index.css: -------------------------------------------------------------------------------- 1 | body, h1, h2, h3 { 2 | margin: 0; 3 | padding: 0; 4 | } 5 | body { 6 | font-family: "Helvetica Neue",Arial,sans-serif; 7 | } 8 | header { 9 | background-color: #2980B9; 10 | color: #ffffff; 11 | } 12 | nav { 13 | background-color: #2980B9; 14 | display: -ms-flexbox; 15 | display: -webkit-box; 16 | display: -webkit-flex; 17 | display: flex; 18 | -webkit-box-align: center; 19 | -webkit-align-items: center; 20 | -ms-flex-align: center; 21 | align-items: center; 22 | -webkit-box-pack: end; 23 | -webkit-justify-content: flex-end; 24 | -ms-flex-pack: end; 25 | justify-content: flex-end; 26 | height: 64px; 27 | } 28 | nav a { 29 | color: #ffffff; 30 | -webkit-box-flex: 0; 31 | -webkit-flex: 0 0 auto; 32 | -ms-flex: 0 0 auto; 33 | flex: 0 0 auto; 34 | font-weight: 200; 35 | letter-spacing: 1px; 36 | letter-spacing: 0.1rem; 37 | margin: 0 16px; 38 | margin: 0 1rem; 39 | text-decoration: none; 40 | } 41 | .button { 42 | background-color: #fafafa; 43 | color: #4E4E4E; 44 | font-weight: 800; 45 | letter-spacing: 1px; 46 | letter-spacing: 0.1rem; 47 | padding: 10px 20px; 48 | text-decoration: none; 49 | text-transform: uppercase; 50 | } 51 | .features { 52 | display: -moz-box; 53 | display: -ms-flexbox; 54 | display: -webkit-flex; 55 | display: flex; 56 | align-items: flex-start; 57 | flex-flow: row wrap; 58 | justify-content: center; 59 | } 60 | .feature { 61 | display: -webkit-box; 62 | display: -webkit-flex; 63 | display: -ms-flexbox; 64 | display: flex; 65 | -webkit-box-align: start; 66 | -webkit-align-items: flex-start; 67 | -ms-flex-align: start; 68 | align-items: flex-start; 69 | -webkit-flex: 0 0 auto; 70 | -ms-flex: 0 0 auto; 71 | -webkit-box-flex: 0; 72 | flex: 0 0 auto; 73 | -webkit-flex-flow: column nowrap; 74 | -ms-flex-flow: column nowrap; 75 | flex-flow: column nowrap; 76 | -webkit-box-pack: center; 77 | -webkit-justify-content: center; 78 | -ms-flex-pack: center; 79 | justify-content: center; 80 | margin: 20px 20px; 81 | max-width: 310px; 82 | } 83 | .feature-description { 84 | color: #4E4E4E; 85 | max-width: 310px; 86 | } 87 | .feature-title { 88 | color: #4E4E4E; 89 | font-size: 20px; 90 | font-size: 1.25rem; 91 | font-weight: 400; 92 | margin: 10px 0; 93 | max-width: 310px; 94 | } 95 | .hero { 96 | display: -webkit-box; 97 | display: -webkit-flex; 98 | display: -ms-flexbox; 99 | display: flex; 100 | -webkit-box-align: center; 101 | -webkit-align-items: center; 102 | -ms-flex-align: center; 103 | align-items: center; 104 | -webkit-flex-flow: column nowrap; 105 | -ms-flex-flow: column nowrap; 106 | flex-flow: column nowrap; 107 | -webkit-box-pack: center; 108 | -webkit-justify-content: center; 109 | -ms-flex-pack: center; 110 | justify-content: center; 111 | height: 300px; 112 | } 113 | .hero-subtitle { 114 | box-sizing: border-box; 115 | color: #fafafa; 116 | -webkit-flex: 0 1 auto; 117 | -ms-flex: 0 1 auto; 118 | flex: 0 1 auto; 119 | font-weight: 100; 120 | letter-spacing: 1px; 121 | letter-spacing: 0.1rem; 122 | padding: 0 40px 40px 40px; 123 | max-width: 100%; 124 | } 125 | .hero-title { 126 | box-sizing: border-box; 127 | -webkit-flex: 0 1 auto; 128 | -ms-flex: 0 1 auto; 129 | flex: 0 1 auto; 130 | font-weight: 200; 131 | letter-spacing: 1px; 132 | letter-spacing: 0.1rem; 133 | padding: 0 40px 10px 40px; 134 | max-width: 100%; 135 | } 136 | -------------------------------------------------------------------------------- /etc/docs/site/docs.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 26 | 27 | -------------------------------------------------------------------------------- /etc/docs/site/images/Data-Binding-function.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter/declarativewidgets/d3422746e20780e7d1655337b0c3128962711b52/etc/docs/site/images/Data-Binding-function.gif -------------------------------------------------------------------------------- /etc/docs/site/images/Data-Binding-intercell.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter/declarativewidgets/d3422746e20780e7d1655337b0c3128962711b52/etc/docs/site/images/Data-Binding-intercell.gif -------------------------------------------------------------------------------- /etc/docs/site/images/Data-Binding-intracell.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter/declarativewidgets/d3422746e20780e7d1655337b0c3128962711b52/etc/docs/site/images/Data-Binding-intracell.gif -------------------------------------------------------------------------------- /etc/docs/site/images/Data-Binding-multiple.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter/declarativewidgets/d3422746e20780e7d1655337b0c3128962711b52/etc/docs/site/images/Data-Binding-multiple.gif -------------------------------------------------------------------------------- /etc/docs/site/images/Data-Channels-JS.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter/declarativewidgets/d3422746e20780e7d1655337b0c3128962711b52/etc/docs/site/images/Data-Channels-JS.gif -------------------------------------------------------------------------------- /etc/docs/site/images/Data-Channels-Python.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter/declarativewidgets/d3422746e20780e7d1655337b0c3128962711b52/etc/docs/site/images/Data-Channels-Python.gif -------------------------------------------------------------------------------- /etc/docs/site/images/Data-Channels-R.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter/declarativewidgets/d3422746e20780e7d1655337b0c3128962711b52/etc/docs/site/images/Data-Channels-R.gif -------------------------------------------------------------------------------- /etc/docs/site/images/Data-Channels-debug.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter/declarativewidgets/d3422746e20780e7d1655337b0c3128962711b52/etc/docs/site/images/Data-Channels-debug.gif -------------------------------------------------------------------------------- /etc/docs/site/images/Data-Channels-initialize.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter/declarativewidgets/d3422746e20780e7d1655337b0c3128962711b52/etc/docs/site/images/Data-Channels-initialize.gif -------------------------------------------------------------------------------- /etc/docs/site/images/Data-Channels-save.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter/declarativewidgets/d3422746e20780e7d1655337b0c3128962711b52/etc/docs/site/images/Data-Channels-save.gif -------------------------------------------------------------------------------- /etc/docs/site/images/Data-Channels-scala.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter/declarativewidgets/d3422746e20780e7d1655337b0c3128962711b52/etc/docs/site/images/Data-Channels-scala.gif -------------------------------------------------------------------------------- /etc/docs/site/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Jupyter Declarative Widgets 8 | 9 | 10 | 11 | 15 | 16 |
17 |
18 |

Jupyter Declarative Widgets

19 |

Declaratively add interactivity to your Jupyter notebooks

20 |
21 | Try it 22 | Get it 23 |
24 |
25 |
26 | 27 |
28 |
29 |

Web Components

30 |
A base extension that enables the use of Web Components and Polymer elements in notebooks.
31 |
32 |
33 |

Core Elements

34 |
A set of core elements facilitate interacting with code running on the Python or Apache Toree (formerly Spark Kernel).
35 |
36 |
37 |

Data Binding and Extensibility

38 |
Data binding between notebook cells and integrated installation of 3rd party elements.
39 |
40 |
41 | 42 | 43 | -------------------------------------------------------------------------------- /etc/docs/site/urth-docs.html: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /etc/docs/site/usage-docs/Calling-Functions.md: -------------------------------------------------------------------------------- 1 | Calling a function defined in the kernel by interacting with visual elements in the Notebook is one of the core features of DeclarativeWidgets. These are arbitrary functions that are defined in the top level scope of the kernel, using any of the supported languages. For example, these functions can be used to: 2 | 3 | * process an HTML form 4 | * load data and make it available to the HTML 5 | * transform data between a two visual elements (i.e a table selection and a map) 6 | * start a Spark Streaming job 7 | * and many more... 8 | 9 | The `urth-core-function` element is what enables tying a function to the rest of the HTML template. It makes the function defined in the kernel seem like it is local to the HTML and allows other elements to set parameters and visualize the result of calling the function. 10 | 11 | The following shows a basic example of what is necessary to use `urth-core-function`: 12 | 13 | > TODO: Image of a simple use of a urth-core-function 14 | 15 | ```Python 16 | def someFunction(a,b,c): 17 | return "something" 18 | ``` 19 | 20 | ```html 21 | %%HTML 22 | 23 | ``` 24 | 25 | Note function references are not limited to notebook level variable declarations, but can also be in reference to functions within objects. 26 | For example, given the following `Test` class: 27 | ```Python 28 | class Test: 29 | def math(self, x, y): 30 | return x*y 31 | t = Test() 32 | ``` 33 | We can then reference it as 34 | ```html 35 | 36 | ``` 37 | 38 | #### Connecting the element to the function 39 | 40 | The `urth-core-function` element needs to know what function defined in the kernel it is representing. This is done by setting the `ref` property to the name of the function. That gives the element enough information to find the function in the kernel and know what parameters it needs. In the example above, the element is representing the function `someFunction`. 41 | 42 | #### Setting parameters 43 | 44 | All parameter to the function are exposed as element properties with the name `arg-`'. These can be set to literal values or bound to other elements using the data binding syntax `{{param}}`. In the above example, the parameter `a` can be set using the property `arg-a`. If any of the parameters have default values (if the language permits), then the corresponding property will have that value set by default. 45 | 46 | #### Invoking the function 47 | 48 | There are several ways to invoke the function using the `urth-core-function` element. 49 | 50 | 1. Directly calling the `invoke` method of the element using Javascript. 51 | 2. Placing an HTML or element as a child that fires a `click` event (i.e. a `button` or `a` element) 52 | 3. Setting the `auto` property and let the element automatically invoke the function when it detects the parameters are all set correctly 53 | 54 | #### Using the results of the function 55 | 56 | If the function defined in the kernel returns some value as part of its invocation, that value is available in the `result` property of the `urth-core-function` element. Typically, this property is used in a data binding and the value is visualized by some other element(s). 57 | 58 | The content of the `result` property depends on what value type is return by the function the element represents. Basic types are supported, but other more complex types can also be returned. For example, functions can return DataFrames (see [here](Connecting-to-data#format-of-the-data) for DataFrame serialization). 59 | 60 | For more detail information about the `urth-core-function` element, see the [api docs](http://jupyter-incubator.github.io/declarativewidgets/docs.html). -------------------------------------------------------------------------------- /etc/docs/site/usage-docs/Data-Visualizations.md: -------------------------------------------------------------------------------- 1 | To visualize static data or data from `urth-core-dataframe`, DeclarativeWidgets provide multiple visualization elements: `urth-viz-table` and a collection of `urth-viz` charts. 2 | 3 | To specify what kind of chart, a the `type` attribute may be specified on `urth-viz-chart`, or the specific chart element could be used directly. For example, using `` is the same as using ``. The chart types supported are: 4 | * area 5 | * bar 6 | * line 7 | * pie 8 | * scatter 9 | 10 | ## Data Input 11 | Both `urth-viz-table` and `urth-viz-chart` consume data in the same formats. They both have `datarows` and `columns` attributes to receive data. `datarows` is specified as an Array of Arrays. It is also valid to pass in a single row element without an enclosing Array. This makes it easier to declaratively bind the data input to a single selection on another element, as seen in the example, below. 12 | 13 | ### Static JSON Data 14 | The following shows a simple way to create a bar chart with static JSON data. The same syntax can be applied for `urth-viz-table`. 15 | ``` 16 | %%html 17 | 20 | 21 | ``` 22 | ### From urth-core-dataframe 23 | First, initialize a Pandas Dataframe: 24 | ``` 25 | aDataFrame1 = pd.DataFrame([ 26 | [1, 10, 5], 27 | [2, 2, 6], 28 | [3, 5, 7] 29 | ], columns=["Index", "Series 1", "Series 2"] 30 | ) 31 | ``` 32 | 33 | Then, bind `aDataFrame1` to an `urth-core-dataframe` element, see [Using DataFrames](https://github.com/jupyter-incubator/declarativewidgets/wiki/Using-DataFrames) for more on how to use DataFrames. Now we can make use of this `urth-core-dataframe` to supply datarows and columns for a table visualization. Note dataframes can also be referenced from within an object e.g. `klass.df`. 34 | 35 | ``` 36 | %%html 37 | 43 | ``` 44 | 45 | ## Column Formatting 46 | To specify special formatting for a particular column of data, add a child `urth-viz-col` element. 47 | 48 | For `urth-viz-table`, the `type` and `format` pairs are passed to the underlying [`handsontable implemention`](https://github.com/handsontable/handsontable/wiki/options#column-options). 49 | ``` 50 | 51 | 52 | 53 | 54 | ``` 55 | 56 | For charts, types of `numeric` and `date` are supported, with format strings [used by `d3`](https://github.com/d3/d3/wiki/Formatting), for example: 57 | ``` 58 | 61 | 62 | 63 | 64 | ``` 65 | 66 | ## Row Selection 67 | Declarative Widgets allow for user interactivity with the table or chart by directly clicking on a row in table, a bar in bar chart, or a slice in pie chart, etc. The corresponding data row is exposed in the property `selection` as an Array, by default, or as key-value pairs if `selection-as-object` is specified. Additional element-specific data is provided in the `selection-info` attribute, and the data row number is available in the `selection-index` attribute. By default, both table and chart allow single selection. To turn on multi selection for charts, add attribute `multi-select`. Where multiple selections are enabled, `selection` will return an Array of rows. -------------------------------------------------------------------------------- /etc/docs/site/usage-docs/Utility-Functions.md: -------------------------------------------------------------------------------- 1 | #### Urth.whenReady 2 | 3 | Declarative Widgets initialization and the import of web components is 4 | performed asynchronously. This can present timing issues in cells that expect the API of a web component to be available upon execution of the cell. In order to ensure that the required 5 | API is available, make use of `Urth.whenReady(function)`. This API will invoke 6 | the specified function only after pre-requisites have been satisfied. The example 7 | code below demonstrates how to safely access the API of the custom 8 | `urth-core-channel` element: 9 | 10 | ``` 11 | %%html 12 | 13 | ``` 14 | 15 | ``` 16 | %%javascript 17 | var channel = document.getElementById('mychannel'); 18 | 19 | Urth.whenReady(function() { 20 | channel.set('myvar', 'myvalue'); 21 | }); 22 | ``` -------------------------------------------------------------------------------- /etc/docs/urth-elements.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /etc/jupyter_notebook_config.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | 4 | import os 5 | c = get_config() 6 | c.NotebookApp.tornado_settings = { 7 | 'autoreload': os.getenv('AUTORELOAD', 'no').lower() in ['yes', 'true'], 8 | 'headers': { 9 | 'Content-Security-Policy': '' 10 | } 11 | 12 | } 13 | c.NotebookApp.allow_origin = '*' 14 | c.NotebookApp.server_extensions = [ 15 | 'urth.widgets.ext.urth_import' 16 | ] 17 | -------------------------------------------------------------------------------- /etc/notebook.json: -------------------------------------------------------------------------------- 1 | { 2 | "load_extensions": { 3 | "declarativewidgets/js/main": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /etc/notebooks/.gitignore: -------------------------------------------------------------------------------- 1 | /*.ipynb -------------------------------------------------------------------------------- /etc/notebooks/demos/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything 2 | .ipynb_checkpoints/ -------------------------------------------------------------------------------- /etc/notebooks/demos/food/images/A_score.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter/declarativewidgets/d3422746e20780e7d1655337b0c3128962711b52/etc/notebooks/demos/food/images/A_score.png -------------------------------------------------------------------------------- /etc/notebooks/demos/food/images/B_score.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter/declarativewidgets/d3422746e20780e7d1655337b0c3128962711b52/etc/notebooks/demos/food/images/B_score.png -------------------------------------------------------------------------------- /etc/notebooks/demos/food/images/C_score.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter/declarativewidgets/d3422746e20780e7d1655337b0c3128962711b52/etc/notebooks/demos/food/images/C_score.png -------------------------------------------------------------------------------- /etc/notebooks/demos/food/images/D_score.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter/declarativewidgets/d3422746e20780e7d1655337b0c3128962711b52/etc/notebooks/demos/food/images/D_score.png -------------------------------------------------------------------------------- /etc/notebooks/demos/food/images/F_score.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter/declarativewidgets/d3422746e20780e7d1655337b0c3128962711b52/etc/notebooks/demos/food/images/F_score.png -------------------------------------------------------------------------------- /etc/notebooks/demos/food/images/mockup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jupyter/declarativewidgets/d3422746e20780e7d1655337b0c3128962711b52/etc/notebooks/demos/food/images/mockup.png -------------------------------------------------------------------------------- /etc/notebooks/demos/taxi/trips_6.csv: -------------------------------------------------------------------------------- 1 | medallion,hack_license,vendor_id,rate_code,store_and_fwd_flag,pickup_datetime,dropoff_datetime,passenger_count,trip_time_in_secs,trip_distance,pickup_longitude,pickup_latitude,dropoff_longitude,dropoff_latitude 2 | B562ACEF597AA8497E090E41A9F12EEC,0EFFAEB3F3B61D806D70990519375043,VTS,1,,2013-02-05 23:19:00,2013-02-05 23:33:00,1,840,3.46,-73.976097,40.781189,-73.938248,40.804768 3 | -------------------------------------------------------------------------------- /etc/notebooks/examples/bcard.css: -------------------------------------------------------------------------------- 1 | .bcard { 2 | border: 1px solid black; 3 | padding: 10px; 4 | background-color: #ECF0F1; 5 | width: 300px; 6 | height: 150px; 7 | margin-top: 11px; 8 | font-size: 12px; 9 | position: relative; 10 | } 11 | 12 | .bcard .info { 13 | box-sizing: border-box; 14 | width: 65%; 15 | margin-left: 35%; 16 | margin-top: 5%; 17 | } 18 | 19 | .bcard .line { 20 | display: block; 21 | line-height: 1.3em; 22 | } 23 | 24 | .bcard .full-name { 25 | font-size: 1.4em; 26 | } 27 | 28 | .bcard .title { 29 | color: #888; 30 | font-style: italic; 31 | margin-bottom: 20px; 32 | } 33 | 34 | .bcard .logo { 35 | background-image: url('/static/base/images/logo.png'); 36 | background-repeat: no-repeat; 37 | width: 40px; 38 | height: 53px; 39 | position: absolute; 40 | top: 47px; 41 | left: 34px; 42 | } -------------------------------------------------------------------------------- /etc/notebooks/examples/urth-viz-cloud.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### urth-viz-cloud Examples" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "#### Initialize declarative widgets and import dependencies" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": null, 20 | "metadata": { 21 | "collapsed": false 22 | }, 23 | "outputs": [], 24 | "source": [ 25 | "import declarativewidgets as declwidgets\n", 26 | "\n", 27 | "declwidgets.init()" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": null, 33 | "metadata": { 34 | "collapsed": false 35 | }, 36 | "outputs": [], 37 | "source": [ 38 | "%%html\n", 39 | "" 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "metadata": {}, 45 | "source": [ 46 | "#### Example 1" 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": null, 52 | "metadata": { 53 | "collapsed": false 54 | }, 55 | "outputs": [], 56 | "source": [ 57 | "%%html\n", 58 | "" 59 | ] 60 | } 61 | ], 62 | "metadata": { 63 | "kernelspec": { 64 | "display_name": "Python 3", 65 | "language": "python", 66 | "name": "python3" 67 | }, 68 | "language_info": { 69 | "codemirror_mode": { 70 | "name": "ipython", 71 | "version": 3 72 | }, 73 | "file_extension": ".py", 74 | "mimetype": "text/x-python", 75 | "name": "python", 76 | "nbconvert_exporter": "python", 77 | "pygments_lexer": "ipython3", 78 | "version": "3.5.1" 79 | } 80 | }, 81 | "nbformat": 4, 82 | "nbformat_minor": 0 83 | } 84 | -------------------------------------------------------------------------------- /etc/r/install_prereq.r: -------------------------------------------------------------------------------- 1 | temp_libPaths <- .libPaths() 2 | .libPaths(temp_libPaths[2]) 3 | install.packages("testthat", repos='http://cran.us.r-project.org', quiet = TRUE) -------------------------------------------------------------------------------- /etc/read_release_version.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) Jupyter Development Team. 3 | # Distributed under the terms of the Modified BSD License. 4 | 5 | import os 6 | 7 | # Get location of this file at runtime 8 | HERE = os.path.abspath(os.path.dirname(__file__)) 9 | 10 | # Eval the version tuple and string from the source 11 | VERSION_NS = {} 12 | with open(os.path.join(HERE, 'urth/widgets/ext/_version.py')) as f: 13 | exec(f.read(), {}, VERSION_NS) 14 | print(VERSION_NS['__version__']) -------------------------------------------------------------------------------- /etc/sbt_plugin_config/gpg.sbt: -------------------------------------------------------------------------------- 1 | addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.0") 2 | addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "1.1") -------------------------------------------------------------------------------- /etc/scripts/jupyter-declarativewidgets: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) Jupyter Development Team. 3 | # Distributed under the terms of the Modified BSD License. 4 | import declarativewidgets.extensionapp 5 | 6 | if __name__ == '__main__': 7 | declarativewidgets.extensionapp.main() -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Jupyter Development Team. 3 | * Distributed under the terms of the Modified BSD License. 4 | */ 5 | var gulp = require('gulp'), 6 | watch = require('gulp-watch'), 7 | run = require('gulp-run'); 8 | 9 | gulp.task('watch', function () { 10 | watch(['elements/**/*', 11 | 'kernel-python/**/*', 12 | 'kernel-scala/**/*', 13 | 'nb-extension/**/*'], function(){ 14 | run('make dist').exec(); 15 | }); 16 | }); 17 | 18 | gulp.task('watch-docs', function () { 19 | watch(['elements/**/*', 20 | 'etc/docs/**/*'], function(){ 21 | run('make dist/docs').exec(); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | from IPython.core.display import display, Javascript 4 | 5 | def init(): 6 | # JavaScript code to load the declarative widgets extension. 7 | # Code sent to the front end from here may be executed after 8 | # extension initialization (iterative cell execution) or 9 | # before (Run All, Reload). This code works together with the 10 | # extension initialization to ensure that the required API is 11 | # available in all scenarios. 12 | # 13 | # Urth._initialized is a deferred that is resolved by the extension 14 | # initialization after the global Urth instance has been setup. 15 | # If extension initialization has not completed a new deferred is 16 | # initialized which extension initialization will resolve. 17 | # 18 | # Urth.whenReady is a public API defined by extension initialization 19 | # to delay javascript execution until dependencies have loaded. If 20 | # extension initialization has not completed a wrapper implementation 21 | # is setup which will invoke the real implementation when it is available. 22 | code = ''' 23 | window.Urth = window.Urth || {}; 24 | Urth._initialized = Urth._initialized || $.Deferred(); 25 | Urth.whenReady = Urth.whenReady || function(cb) { 26 | Urth._initialized.then(function() { 27 | Urth.whenReady(cb); 28 | }); 29 | }; 30 | Urth.whenReady(function() { console.log("Declarative widgets connected.") }); 31 | ''' 32 | 33 | # Send the code to the browser. 34 | display(Javascript(code)) 35 | 36 | from .widget_channels import channel 37 | from .widget_channels import Channels 38 | from .widget_function import Function 39 | from .widget_dataframe import DataFrame 40 | from .widget_ipw_proxy import IpywProxy 41 | from .util.explore import explore 42 | 43 | -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/tests/test_urth_widget.py: -------------------------------------------------------------------------------- 1 | # (c) Copyright Jupyter Development Team 2 | # (c) Copyright IBM Corp. 2015 3 | 4 | """ Tests for the urth_widget.py module """ 5 | 6 | import unittest 7 | 8 | try: 9 | from unittest.mock import Mock 10 | except ImportError as e: 11 | from mock import Mock 12 | 13 | from ipykernel.comm import Comm 14 | from declarativewidgets.urth_widget import * 15 | 16 | 17 | class TestUrthWidget(unittest.TestCase): 18 | 19 | def test_no_state_msg_on_create(self): 20 | """should not send a state message when the widget is created""" 21 | comm = Mock(spec=Comm) 22 | send = Mock() 23 | comm.attach_mock(send, 'send') 24 | widget = UrthWidget(comm=comm) 25 | assert(send.call_count == 0) -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/tests/test_widget_channels.py: -------------------------------------------------------------------------------- 1 | # (c) Copyright Jupyter Development Team 2 | # (c) Copyright IBM Corp. 2015 3 | 4 | """ Tests for the widget_channels.py module """ 5 | 6 | import unittest 7 | 8 | try: 9 | from unittest.mock import Mock 10 | except ImportError as e: 11 | from mock import Mock 12 | 13 | from ipykernel.comm import Comm 14 | from declarativewidgets.widget_channels import * 15 | 16 | 17 | class TestWidgetChannels(unittest.TestCase): 18 | 19 | def setUp(self): 20 | comm = Mock(spec=Comm) 21 | self.widget = Channels(comm=comm) 22 | 23 | self.chan = 'c' 24 | self.name = 'x' 25 | 26 | self.msg = { 27 | 'event': 'change', 28 | 'data': { 29 | 'channel': self.chan, 30 | 'name': self.name, 31 | 'old_val': 1, 32 | 'new_val': 2 33 | } 34 | } 35 | 36 | self.lst = [] 37 | self.handler = lambda x, y: self.lst.extend([x, y]) 38 | 39 | #### watch() 40 | def test_watch(self): 41 | """should execute a registered handler with arguments from message""" 42 | self.widget.watch(self.name, self.handler, self.chan) 43 | self.widget._handle_change_msg(None, self.msg, None) 44 | self.assertEqual(self.lst, [1, 2]) 45 | 46 | def test_watch_bad_channel(self): 47 | """should not execute a handler given an unregistered channel""" 48 | self.widget._handle_change_msg(None, self.msg, None) 49 | self.assertEqual(self.lst, []) 50 | 51 | def test_watch_bad_name(self): 52 | """should not execute a handler given an unregistered name""" 53 | self.widget.watch("bad name", self.handler, self.chan) 54 | self.widget._handle_change_msg(None, self.msg, None) 55 | self.assertEqual(self.lst, []) 56 | 57 | def test_watch_array(self): 58 | """should execute a handler given an array type""" 59 | self.widget.watch(self.name, self.handler, self.chan) 60 | self.msg['data']['old_val'] = [1, 2] 61 | self.msg['data']['new_val'] = [3, 4] 62 | self.widget._handle_change_msg(None, self.msg, None) 63 | self.assertEqual(self.lst, [[1, 2], [3, 4]]) 64 | 65 | def test_watch_dict(self): 66 | """should execute a handler given an dict type""" 67 | self.widget.watch(self.name, self.handler, self.chan) 68 | self.msg['data']['old_val'] = {"a": 1} 69 | self.msg['data']['new_val'] = {"b": "c"} 70 | self.widget._handle_change_msg(None, self.msg, None) 71 | self.assertEqual(self.lst, [{"a": 1}, {"b": "c"}]) 72 | 73 | #### _handle_change_msg() 74 | def test_handle_change_msg_invoke_error(self): 75 | """should send an error message when handler invocation fails""" 76 | self.widget.error = lambda msg: self.lst.append('err') 77 | explosion = lambda x, y: 1 / 0 78 | self.widget.watch(self.name, explosion, self.chan) 79 | self.widget._handle_change_msg(None, self.msg, None) 80 | self.assertEqual(self.lst, ['err']) 81 | 82 | def test_hand_change_msg_invoke_success(self): 83 | """should send an ok message when handler invocation succeeds""" 84 | self.widget.ok = lambda: self.lst.append('ok') 85 | self.widget.watch(self.name, self.handler, self.chan) 86 | self.widget._handle_change_msg(None, self.msg, None) 87 | self.assertEqual(self.lst, [1, 2, 'ok']) 88 | 89 | -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/tests/test_widget_function.py: -------------------------------------------------------------------------------- 1 | # (c) Copyright Jupyter Development Team 2 | 3 | import unittest 4 | 5 | try: 6 | from unittest.mock import Mock 7 | except ImportError as e: 8 | from mock import Mock 9 | 10 | from ipykernel.comm import Comm 11 | from declarativewidgets.widget_function import Function 12 | 13 | # Execute tests within an IPython instance 14 | from IPython.testing.globalipapp import get_ipython 15 | ip = get_ipython() 16 | 17 | 18 | class TestWidgetFunction(unittest.TestCase): 19 | def setUp(self): 20 | comm = Mock(spec=Comm) 21 | self.fun = Function(comm=comm) 22 | 23 | def test_the_function(self): 24 | def mock_function(x): 25 | return x + 2 26 | 27 | ip.user_ns['mock_function'] = mock_function 28 | 29 | self.fun.function_name = 'mock_function' 30 | 31 | assert self.fun._the_function()(3) == 5 32 | 33 | def test_the_function_object_scope(self): 34 | class mock_class(): 35 | def mock_class_function(self, x): 36 | return x + 3 37 | 38 | mock_object = mock_class() 39 | 40 | ip.user_ns['mock_object'] = mock_object 41 | 42 | self.fun.function_name = 'mock_object.mock_class_function' 43 | 44 | assert self.fun._the_function()(3) == 6 45 | -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/urth_exception.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | 4 | 5 | class UrthException(Exception): 6 | """ 7 | A generic exception for Urth Widgets. 8 | """ 9 | 10 | def __init__(self, msg): 11 | self.msg = msg 12 | 13 | def __str__(self): 14 | return self.msg -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/urth_widget.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | import time 4 | import logging 5 | 6 | from ipywidgets import widgets # Widget definitions 7 | import traceback 8 | 9 | class UrthWidget(widgets.Widget): 10 | """ A base class for Urth widgets. """ 11 | 12 | def __init__(self, **kwargs): 13 | super(UrthWidget, self).__init__(**kwargs) 14 | 15 | def get_state(self, key=None): 16 | """ 17 | In general, urth widgets don't have initial state 18 | """ 19 | return {} 20 | 21 | def _send_update(self, attribute, value): 22 | """ 23 | Sends a message to update the front-end state of the given attribute. 24 | """ 25 | msg = { 26 | "method": "update", 27 | "state": { 28 | attribute: value 29 | } 30 | } 31 | self._send(msg) 32 | 33 | def send_status(self, status, msg=""): 34 | """ 35 | Sends a message to inform the front-end of the execution status. 36 | 37 | Parameters 38 | ---------- 39 | status : string 40 | "ok" for success, "error" for failure. 41 | msg : string 42 | Message accompanying the status, e.g. an error message. 43 | """ 44 | self._send({ 45 | "method": "update", 46 | "state": { 47 | "__status__": { 48 | "status": status, 49 | "msg": msg, 50 | "timestamp": round(time.time() * 1000) 51 | } 52 | } 53 | }) 54 | 55 | def error(self, error): 56 | """ 57 | Inform the front-end that an error occurred, with the given error msg. 58 | Parameters 59 | ---------- 60 | error: string or exception 61 | """ 62 | self.send_status("error", str(error)) 63 | self.log.error(traceback.format_exc()) 64 | 65 | def ok(self, msg=""): 66 | """ 67 | Inform the front-end that processing succeeded. 68 | Parameters 69 | ---------- 70 | msg : string 71 | An optional message. 72 | """ 73 | self.send_status("ok", msg) -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/util/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/util/base_serializer_py2.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | 4 | from .serializer_registrar import SerializerRegistrar 5 | 6 | 7 | class BaseSerializer(object): 8 | """ 9 | An abstract base class for serializers. 10 | 11 | Each class extending BaseSerializer should serialize a single class, 12 | whose name is returned by klass(). 13 | 14 | Adding a new subclass of BaseSerializer in this package will automatically 15 | register the subclass for use by the Serializer. 16 | """ 17 | 18 | __metaclass__ = SerializerRegistrar 19 | 20 | @staticmethod 21 | def klass(): 22 | """The class that this serializer can serialize. 23 | 24 | Returns 25 | ------- 26 | class 27 | class object representing the class that this serializer will 28 | serialize 29 | """ 30 | pass 31 | 32 | @staticmethod 33 | def serialize(obj, **kwargs): 34 | """Serializes an object, assumed to have the class returned by `klass()` 35 | 36 | Parameters 37 | ---------- 38 | obj : object 39 | The object to serialize. `obj`'s class will be equal to the class 40 | returned by `klass()` 41 | 42 | **kwargs : dict 43 | Allows for extra parameters to be sent to the serializer 44 | 45 | Returns 46 | ------- 47 | obj 48 | The object in serialized form. 49 | """ 50 | pass 51 | 52 | @staticmethod 53 | def check_packages(): 54 | """Serialization may require using external packages. 55 | 56 | Override this function to check whether the packages needed 57 | to serialize this serializer's klass can be imported. 58 | 59 | Returns 60 | ------- 61 | boolean 62 | True if necessary packages for serialization can be imported. 63 | """ 64 | pass -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/util/base_serializer_py3.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | 4 | from .serializer_registrar import SerializerRegistrar 5 | 6 | 7 | class BaseSerializer(object, metaclass=SerializerRegistrar): 8 | """ 9 | An abstract base class for serializers. 10 | 11 | Each class extending BaseSerializer should serialize a single class, 12 | whose name is returned by klass(). 13 | 14 | Adding a new subclass of BaseSerializer in this package will automatically 15 | register the subclass for use by the Serializer. 16 | """ 17 | 18 | @staticmethod 19 | def klass(): 20 | """The class that this serializer can serialize. 21 | 22 | Returns 23 | ------- 24 | class 25 | class object representing the class that this serializer will 26 | serialize 27 | """ 28 | pass 29 | 30 | @staticmethod 31 | def serialize(obj, **kwargs): 32 | """Serializes an object, assumed to have the class returned by `klass()` 33 | 34 | Parameters 35 | ---------- 36 | obj : object 37 | The object to serialize. `obj`'s class will be equal to the class 38 | returned by `klass()` 39 | 40 | **kwargs : dict 41 | Allows for extra parameters to be sent to the serializer 42 | 43 | Returns 44 | ------- 45 | obj 46 | The object in serialized form. 47 | """ 48 | pass 49 | 50 | @staticmethod 51 | def check_packages(): 52 | """Serialization may require using external packages. 53 | 54 | Override this function to check whether the packages needed 55 | to serialize this serializer's klass can be imported. 56 | 57 | Returns 58 | ------- 59 | boolean 60 | True if necessary packages for serialization can be imported. 61 | """ 62 | pass -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/util/explore.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | 4 | from IPython.core.display import display, HTML 5 | import pandas 6 | try: 7 | import pyspark 8 | except ImportError: 9 | # TODO: LOG WARNING 10 | pass 11 | 12 | unique_explore_id = 0 13 | 14 | def check_pyspark_package(): 15 | try: 16 | import pyspark 17 | except ImportError: 18 | return False 19 | return True 20 | 21 | def stringify_property(property_key, property_value): 22 | if type(property_value) == bool: 23 | if property_value: 24 | return property_key 25 | else: 26 | return '{}="{}"'.format(property_key, str(property_value)) 27 | 28 | def stringify_properties(properties): 29 | return ' '.join(filter(None, map(lambda x: stringify_property(x, properties[x]), properties))) 30 | 31 | def stringify_bindings(bindings): 32 | return ' '.join(map(lambda x: '{}="{{{{{}}}}}"'.format(x, bindings[x]), bindings)) 33 | 34 | def explore(df, channel='default', properties={}, bindings={}): 35 | """ 36 | Renders the urth-viz-explorer widget to the user output 37 | If pandas.DataFrame assign with unique name to user namespace else use what was passed in the string 38 | 39 | Parameters 40 | ---------- 41 | df The dataframe itself or the string representation of the variable 42 | channel The channel to bind to defaulted to default 43 | properties The properties e.g. {'selection-as-object': False, 'foo': 5} 44 | bindings The bindings e.g. {'selection': 'sel'} 45 | """ 46 | 47 | global unique_explore_id 48 | unique_explore_id += 1 49 | explore_df = "unique_explore_df_name_" + str(unique_explore_id) 50 | if isinstance(df, pandas.DataFrame) or (check_pyspark_package() and isinstance(df, pyspark.sql.DataFrame)): 51 | get_ipython().user_ns[explore_df] = df 52 | else: 53 | explore_df = df 54 | 55 | display(HTML( 56 | """ 58 | """ 61 | .format(ref=explore_df, channel=channel, 62 | props=stringify_properties(properties), binds=stringify_bindings(bindings)) 63 | )) 64 | -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/util/functions_py2.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | 4 | """ Utilities related to functions. This version is specific to Python 2. """ 5 | 6 | import inspect 7 | 8 | def get_arg_spec(func): 9 | sig = inspect.getargspec(func) 10 | if "self" in sig.args: 11 | sig.args.remove("self") 12 | return sig 13 | 14 | def parameter_types(func): 15 | sig = get_arg_spec(func) 16 | required = required_parameter(func) 17 | default = default_parameters(func) 18 | 19 | types = {} 20 | for arg in sig.args: 21 | if arg in required: 22 | types[arg] = type(None) 23 | else: 24 | types[arg] = type(default[arg]) 25 | 26 | return types 27 | 28 | 29 | def default_parameters(func): 30 | sig = get_arg_spec(func) 31 | 32 | if sig.defaults: 33 | return dict(zip(sig.args[-len(sig.defaults):], sig.defaults)) 34 | else: 35 | return {} 36 | 37 | 38 | def required_parameter(func): 39 | sig = get_arg_spec(func) 40 | 41 | if sig.defaults: 42 | return list(set(sig.args) - set(sig.args[-len(sig.defaults):])) 43 | else: 44 | return sig.args 45 | -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/util/functions_py3.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | 4 | """ Utilities related to functions. This version is specific to Python 3. """ 5 | 6 | import inspect 7 | 8 | def parameter_types(func): 9 | sig = inspect.signature(func) 10 | 11 | types = {} 12 | for (name, param) in sig.parameters.items(): 13 | tpe = _param_type(param) 14 | types[name] = tpe 15 | 16 | return types 17 | 18 | 19 | def required_parameter(func): 20 | sig = inspect.signature(func) 21 | 22 | required = [] 23 | for (name, param) in sig.parameters.items(): 24 | if not _has_default_val(param): 25 | required.append(name) 26 | 27 | return required 28 | 29 | 30 | def _non_empty(val): 31 | return id(val) != id(inspect._empty) 32 | 33 | 34 | def _param_type(param): 35 | # use the type of the default value if present 36 | if _has_default_val(param): 37 | return type(param.default) 38 | 39 | # use the annotation if it evaluates to a class 40 | if _non_empty(param.annotation) and inspect.isclass(param.annotation): 41 | return param.annotation 42 | 43 | # return NoneType if we cannot determine the type 44 | return type(None) 45 | 46 | 47 | def _has_default_val(param): 48 | return _non_empty(param.default) 49 | 50 | 51 | def get_default_vals(func): 52 | sig = inspect.signature(func) 53 | 54 | default = {} 55 | for (name, param) in sig.parameters.items(): 56 | if _has_default_val(param): 57 | default.update({name: param.default}) 58 | 59 | return default 60 | -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/util/query/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | 4 | # Setting up query support 5 | 6 | query_support_map = {} 7 | 8 | try: 9 | from pandas import DataFrame 10 | from .pandas import apply_query as pandas_apply_query 11 | query_support_map[DataFrame] = pandas_apply_query 12 | except ImportError: 13 | # TODO: LOG WARNING 14 | pass 15 | 16 | try: 17 | import pyspark 18 | from .spark import apply_query as spark_apply_query 19 | query_support_map[pyspark.sql.DataFrame] = spark_apply_query 20 | except ImportError: 21 | # TODO: LOG WARNING 22 | pass 23 | 24 | 25 | def apply_query(df, query): 26 | return query_support_map[type(df)](df, query) if type(df) in query_support_map else df -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/util/query/pandas.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | 4 | 5 | def apply_query(df, query=[]): 6 | if query: 7 | new_df = df.copy() 8 | for queryitem in query: 9 | if queryitem['type'] == 'filter': 10 | new_df = handle_filter(new_df, queryitem['expr']) 11 | 12 | elif queryitem['type'] == 'group': 13 | new_df = handle_group(new_df, queryitem['expr']) 14 | 15 | elif queryitem['type'] == 'sort': 16 | new_df = handle_sort(new_df, queryitem['expr']) 17 | 18 | return new_df 19 | 20 | else: 21 | return df 22 | 23 | 24 | def handle_filter(df, fltr_expr): 25 | """ 26 | Handles a filter expression 27 | :param df: a Pandas DataFrame 28 | :param fltr_expr: an array of filter expressions 29 | :return: filtered DataFrame 30 | """ 31 | return df.query(fltr_expr) 32 | 33 | 34 | def handle_group(df, grp_expr): 35 | """ 36 | Handles a group expression 37 | :param df: a Pandas DataFrame 38 | :param grp_expr: a dict with the group expression structure 39 | :return: grouped DataFrame 40 | """ 41 | group_cols = grp_expr['by'] 42 | group_aggs = grp_expr['agg'] 43 | 44 | df = df.groupby(group_cols).agg(to_dict_agg(group_aggs)) 45 | 46 | # move index into columns 47 | for _ in df.index.names: 48 | df.reset_index(level=0, inplace=True) 49 | 50 | df.columns = to_single_column_names(df.columns.values) 51 | 52 | return df 53 | 54 | 55 | def handle_sort(df, sort_expr): 56 | """ 57 | Handles a sort expression 58 | :param df: a Pandas DataFrame 59 | :param sort_expr: a dict with the sort expression structure 60 | :return: Sorted DataFrame 61 | """ 62 | sort_cols = sort_expr['by'] 63 | sort_dir = sort_expr['ascending'] 64 | 65 | return df.sort_values(sort_cols, ascending=sort_dir) 66 | 67 | 68 | def to_dict_agg(agg_array): 69 | """ 70 | Utility to convert that array structure with the aggregation information into the map/dict style structure that 71 | is passed to pandas' agg function. 72 | 73 | from: 74 | [ 75 | {"op": "sum", "col": "col1"}, 76 | {"op": "sum", "col": "col2"}, 77 | {"op": "count", "col": "col2"} 78 | ] 79 | 80 | to 81 | { 82 | "col1": ["sum"], 83 | "col2": ["sum", "count"] 84 | } 85 | :param agg_array: Array with aggregate operations structure 86 | :return: a dict version of the aggregate operations compatible with Pandas.agg 87 | """ 88 | dict_agg = dict() 89 | for agg in agg_array: 90 | if agg["col"] in dict_agg: 91 | dict_agg[agg["col"]].append(agg["op"]) 92 | else: 93 | dict_agg[agg["col"]] = [agg["op"]] 94 | return dict_agg 95 | 96 | 97 | def to_single_column_names(column_array): 98 | return map(lambda col: col[1:] if col.startswith('_') else col, ['_'.join(col[::-1]).strip() for col in column_array]) 99 | -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/util/query/spark.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | import pyspark.sql.functions as F 4 | 5 | 6 | def apply_query(df, query=[]): 7 | if query: 8 | new_df = df 9 | for queryitem in query: 10 | if queryitem['type'] == 'filter': 11 | new_df = handle_filter(new_df, queryitem['expr']) 12 | 13 | elif queryitem['type'] == 'group': 14 | new_df = handle_group(new_df, queryitem['expr']) 15 | 16 | elif queryitem['type'] == 'sort': 17 | new_df = handle_sort(new_df, queryitem['expr']) 18 | 19 | return new_df 20 | 21 | else: 22 | return df 23 | 24 | 25 | def handle_filter( df, fltr_expr ): 26 | """ 27 | Handles a filter expression 28 | :param df: a Pyspark DataFrame 29 | :param fltr_expr: a string filter expressions 30 | :return: filtered DataFrame 31 | """ 32 | return df.filter(fltr_expr) 33 | 34 | 35 | def handle_group( df, grp_expr ): 36 | """ 37 | Handles a group expression 38 | :param df: a Pyspark DataFrame 39 | :param grp_expr: a dict with the group expression structure 40 | :return: grouped DataFrame 41 | """ 42 | group_cols = grp_expr['by'] 43 | group_aggs = grp_expr['agg'] 44 | 45 | #rename resultant column names to dataframe format i.e. sum(columnName) -> sum_columnName 46 | renamed_columns = [group_cols] + [x['op'] + "_" + x['col'] for x in group_aggs] 47 | 48 | return df.groupby(group_cols).agg(*to_array_of_func_exprs(group_aggs)).toDF(*renamed_columns) 49 | 50 | 51 | def handle_sort(df, sort_expr): 52 | """ 53 | Handles a sort expression 54 | :param df: a Pyspark DataFrame 55 | :param sort_expr: a dict with the sort expression structure 56 | :return: sorted DataFrame 57 | """ 58 | sort_cols = sort_expr['by'] 59 | sort_dir = sort_expr['ascending'] 60 | 61 | return df.orderBy(sort_cols, ascending=sort_dir) 62 | 63 | 64 | def to_array_of_func_exprs(agg_array): 65 | return map(F.expr, to_array_of_func_exprs_string(agg_array)) 66 | 67 | 68 | def to_array_of_func_exprs_string(agg_array): 69 | return ["{0}({1})".format(x["op"], x["col"]) for x in agg_array] 70 | -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/util/query/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/util/query/tests/test_pandas.py: -------------------------------------------------------------------------------- 1 | """ Tests for the pandas.py module 2 | 3 | """ 4 | 5 | import unittest 6 | 7 | from ..pandas import * 8 | 9 | 10 | class TestFunctions(unittest.TestCase): 11 | 12 | def test_to_dict_agg(self): 13 | """should convert to dictionary""" 14 | 15 | arg_array = [ 16 | {"op": "sum", "col": "col1"}, 17 | {"op": "sum", "col": "col2"}, 18 | {"op": "count", "col": "col2"} 19 | ] 20 | 21 | expected = { 22 | "col1": ["sum"], 23 | "col2": ["sum", "count"] 24 | } 25 | 26 | actual = to_dict_agg(arg_array) 27 | 28 | self.assertEqual(expected, actual) 29 | 30 | def test_to_single_column_names(self): 31 | """should remove whitespaces from column names""" 32 | 33 | arg_array = [ 34 | ["col1", ""], 35 | ["col2", "count"], 36 | ["col3", "sum"] 37 | ] 38 | 39 | expected = [ 40 | "col1", 41 | "count_col2", 42 | "sum_col3" 43 | ] 44 | 45 | actual = to_single_column_names(arg_array) 46 | 47 | self.assertEqual(expected, list(actual)) 48 | -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/util/query/tests/test_spark.py: -------------------------------------------------------------------------------- 1 | """ Tests for the pandas.py module 2 | 3 | """ 4 | 5 | import unittest 6 | 7 | from ..spark import * 8 | 9 | 10 | class TestFunctions(unittest.TestCase): 11 | 12 | def test_to_array_of_func_exprs_string(self): 13 | """should convert to array of function expressions""" 14 | 15 | arg_array = [ 16 | {"op": "sum", "col": "col1"}, 17 | {"op": "sum", "col": "col2"}, 18 | {"op": "count", "col": "col2"} 19 | ] 20 | 21 | expected = [ 22 | "sum(col1)", 23 | "sum(col2)", 24 | "count(col2)" 25 | ] 26 | 27 | actual = to_array_of_func_exprs_string(arg_array) 28 | 29 | self.assertEqual(expected, actual) 30 | 31 | -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/util/serializer.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | 4 | """ A module used to serialize objects. 5 | 6 | Serialization is done using the `serialize()` method of the `Serializer` class. 7 | 8 | The serialization is performed using subclasses of BaseSerializer, implemented 9 | in the declarativewidgets.util.serializers package. Each BaseSerializer subclass defines 10 | the serialization process for one class. If a variable's class matches the 11 | class represented by a serializer, that serializer will be used to serialize 12 | the variable. 13 | 14 | New serializers are registered by declaring a new subclass of BaseSerializer 15 | in the declarativewidgets.util.serializers package. 16 | 17 | """ 18 | 19 | from .serializers import BaseSerializer 20 | from .serializer_registrar import serializer_map as sr_map 21 | 22 | 23 | class Serializer: 24 | """ A class used to serialize objects. 25 | 26 | Examples 27 | -------- 28 | >>> obj = 3.0 29 | >>> s = Serializer() 30 | >>> print(s.serialize(obj)) 31 | """ 32 | 33 | # serializer_map maps class names to serialization functions 34 | serializer_map = {} 35 | 36 | def __init__(self): 37 | self.serializer_map = self._load_serializers() 38 | 39 | def serialize(self, obj, **kwargs): 40 | """Serialize the given object using registered serializers. 41 | 42 | Parameters 43 | ---------- 44 | obj : object 45 | The object to serialize 46 | 47 | **kwargs : dict 48 | Allows for extra parameters to be sent to the serializer 49 | 50 | Returns 51 | ------- 52 | obj 53 | The object in serialized form 54 | 55 | """ 56 | 57 | for klass in self.serializer_map.keys(): 58 | if isinstance(obj, klass): 59 | return self.serializer_map[klass](obj, **kwargs) 60 | 61 | # If no serializer exists for this object's class, return the object. 62 | return obj 63 | 64 | def _load_serializers(self): 65 | """Generates a mapping of class name to serialization function. 66 | 67 | Returns 68 | ------- 69 | serializer_map : dict 70 | A map of classes to serialization functions. 71 | 72 | """ 73 | return sr_map 74 | 75 | def _valid_serializer(self, cls): 76 | """Checks whether a class name represents a valid serializer class. 77 | 78 | Parameters 79 | ---------- 80 | cls : class 81 | The class to check 82 | 83 | Returns 84 | ------- 85 | boolean 86 | True if `cls` is a valid serializer class 87 | """ 88 | return (issubclass(cls, BaseSerializer) 89 | and cls != BaseSerializer 90 | and cls.check_packages()) 91 | -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/util/serializer_registrar.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | 4 | # serializer_map maps class names to serialization functions 5 | serializer_map = {} 6 | 7 | class SerializerRegistrar(type): 8 | """ 9 | A metaclass used to register each class extending BaseSerializer. 10 | 11 | Specifically, adds a mapping of class to serialization function defined by 12 | the subclass of BaseSerializer. 13 | """ 14 | def __init__(cls, name, bases, attrs): 15 | if cls.check_packages(): 16 | global serializer_map 17 | serializer_map[cls.klass()] = cls.serialize -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/util/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/util/tests/test_explore.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | 4 | """ 5 | Tests for the explore.py module 6 | """ 7 | 8 | import unittest 9 | import collections 10 | 11 | from ..explore import * 12 | 13 | 14 | class TestExplore(unittest.TestCase): 15 | 16 | def test_stringify_bindings(self): 17 | """should stringify bindings""" 18 | 19 | bindings = (('selection', 'sel'), ('foo', 'bar')) 20 | ordered_bindings = collections.OrderedDict(bindings) 21 | expected = "selection=\"{{sel}}\" foo=\"{{bar}}\"" 22 | actual = stringify_bindings(ordered_bindings) 23 | self.assertEqual(expected, actual) 24 | 25 | def test_stringify_properties(self): 26 | """should stringify properties""" 27 | 28 | properties_false = (('selection-as-object', False), ('foo', 5)) 29 | ordered_properties_false = collections.OrderedDict(properties_false) 30 | expected = "foo=\"5\"" 31 | actual = stringify_properties(ordered_properties_false) 32 | self.assertEqual(expected, actual) 33 | 34 | properties_true = (('selection-as-object', True), ('foo', 5)) 35 | ordered_properties_true = collections.OrderedDict(properties_true) 36 | expected = "selection-as-object foo=\"5\"" 37 | actual = stringify_properties(ordered_properties_true) 38 | self.assertEqual(expected, actual) -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/util/tests/test_functions_py3.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | 4 | """ Tests for the function.py module 5 | 6 | """ 7 | 8 | import unittest 9 | 10 | from ..functions import * 11 | 12 | 13 | class TestFunctions(unittest.TestCase): 14 | 15 | def test_parameter_types_annotation(self): 16 | """should return annotation if the annotation is a class""" 17 | def func(x: float): 18 | return x 19 | 20 | expected = {'x': float} 21 | actual = parameter_types(func) 22 | 23 | self.assertEqual(expected, actual) 24 | 25 | def test_parameter_types_annotation_not_class(self): 26 | """should return type of None if the annotation isn't a class""" 27 | def func(x: (1+1)): 28 | return x 29 | 30 | expected = {'x': type(None)} 31 | actual = parameter_types(func) 32 | 33 | self.assertEqual(expected, actual) 34 | 35 | def test_parameter_types_multiple(self): 36 | """should work for multiple arguments""" 37 | def func(a, b: int, c=2.0): 38 | return a 39 | 40 | expected = {'a': type(None), 'b': int, 'c': float} 41 | actual = parameter_types(func) 42 | 43 | self.assertEqual(expected, actual) 44 | 45 | def test_signature_spec_multiple(self): 46 | """should work for multiple arguments""" 47 | def func(a, b: int, c=2.0, d='asdf', e=[1], f={}, g=True): 48 | return a 49 | 50 | expected = {'a': {'type': "NoneType", 'required': True}, 51 | 'b': {'type': "Number", 'required': True}, 52 | 'c': {'type': "Number", 'value': 2.0}, 53 | 'd': {'type': "String", 'value': 'asdf'}, 54 | 'e': {'type': "Array", 'value': [1]}, 55 | 'f': {'type': "Object", 'value': {}}, 56 | 'g': {'type': "Boolean", 'value': True}} 57 | actual = signature_spec(func) 58 | 59 | self.assertEqual(expected, actual) 60 | 61 | def test_signature_spec_on_function_with_class_arg(self): 62 | """should return full path for non-builtin types""" 63 | 64 | class Foo: 65 | def a(self): 66 | pass 67 | 68 | def func(a: Foo): 69 | return a 70 | 71 | expected = {'a': {'type': "{}.{}".format(Foo.__module__, Foo.__name__), 'required': True}} 72 | actual = signature_spec(func) 73 | 74 | self.assertEqual(expected, actual) 75 | 76 | def test_apply_with_conversion_convert(self): 77 | """should convert arguments and execute the function""" 78 | def func(a: int, b=1.0, c=[3]): 79 | return a + b + sum(c) 80 | 81 | args = {'a': '1', 'b': '2.0', 'c': '[1, 2, 3]'} 82 | 83 | expected = 9.0 84 | actual = apply_with_conversion(func, args) 85 | 86 | self.assertEqual(expected, actual) 87 | 88 | def test_apply_with_conversion_bad_types(self): 89 | """should throw an exception if arguments are wrong type""" 90 | def func(a: int): 91 | return a 92 | 93 | args = {'a': {}} 94 | 95 | with self.assertRaises(TypeError): 96 | apply_with_conversion(func, args) 97 | 98 | def test_apply_with_conversion_bad_types2(self): 99 | """should throw an exception if arguments are wrong type""" 100 | def func(a: int): 101 | return a 102 | 103 | args = {'a': '1.23'} 104 | 105 | with self.assertRaises(ValueError): 106 | apply_with_conversion(func, args) -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/widget_dataframe.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | 4 | from traitlets import Unicode, Integer # Used to declare attributes of our widget 5 | from IPython.core.getipython import get_ipython 6 | 7 | from .util.serializer import Serializer 8 | from .util.query import apply_query 9 | from .urth_widget import UrthWidget 10 | from .urth_exception import UrthException 11 | import json 12 | 13 | from functools import reduce 14 | 15 | 16 | class DataFrame(UrthWidget): 17 | """ 18 | A widget for retrieving the value of a DataFrame in the kernel. 19 | """ 20 | variable_name = Unicode('', sync=True) 21 | limit = Integer(100, sync=True) 22 | query = Unicode('[]', sync=True) 23 | 24 | def __init__(self, value=None, **kwargs): 25 | self.log.info("Created a new DataFrame widget.") 26 | 27 | self.on_msg(self._handle_state_msg) 28 | self.shell = get_ipython() 29 | self.serializer = Serializer() 30 | super(DataFrame, self).__init__(**kwargs) 31 | 32 | def _variable_name_changed(self, old, new): 33 | self.log.info("Binding to variable name {}...".format(new)) 34 | 35 | def _limit_changed(self, old, new): 36 | self.log.info("Changed value of limit to {}...".format(new)) 37 | 38 | def _query_changed(self, old, new): 39 | self.log.info("Changed value of query to {}...".format(new)) 40 | 41 | def _the_dataframe(self): 42 | try: 43 | name = self.variable_name.split('.') 44 | return reduce(lambda x, y: getattr(x, y), [self.shell.user_ns[name.pop(0)]] + name) 45 | except (KeyError, AttributeError): 46 | raise UrthException("Invalid DataFrame name {}".format( 47 | self.variable_name)) 48 | 49 | def _handle_state_msg(self, wid, content, buffers): 50 | if content.get("event", "") == "sync": 51 | self._sync_state() 52 | 53 | def _sync_state(self): 54 | try: 55 | val = self._the_dataframe() 56 | serialized_result = self.serializer.serialize(apply_query(val, json.loads(self.query)), limit=self.limit, query=self.query) 57 | self._send_update("value", serialized_result) 58 | self.ok() 59 | except Exception as e: 60 | self.error(e) 61 | -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/widget_function.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | 4 | from traitlets import Integer, Unicode # Used to declare attributes of our widget 5 | from IPython.core.getipython import get_ipython 6 | 7 | from .util.serializer import Serializer 8 | from .util.functions import apply_with_conversion, signature_spec 9 | from .urth_widget import UrthWidget 10 | from .urth_exception import UrthException 11 | 12 | from functools import reduce 13 | 14 | 15 | class Function(UrthWidget): 16 | """ 17 | A Widget for invoking a function on the kernel. 18 | """ 19 | function_name = Unicode('', sync=True) 20 | limit = Integer(100, sync=True) 21 | 22 | def __init__(self, **kwargs): 23 | self.log.info("Created a new Function widget.") 24 | 25 | self.on_msg(self._handle_custom_event_msg) 26 | self.shell = get_ipython() 27 | self.serializer = Serializer() 28 | super(Function, self).__init__(**kwargs) 29 | 30 | def _function_name_changed(self, old, new): 31 | try: 32 | self.log.info("Binding to function name {}...".format(new)) 33 | self._sync_state() 34 | self.ok() 35 | except Exception as e: 36 | self.error(e) 37 | 38 | def _handle_custom_event_msg(self, wid, content, buffers): 39 | event = content.get('event', '') 40 | if event == 'invoke': 41 | self._invoke(content.get('args', {})) 42 | elif event == 'sync': 43 | self._sync_state() 44 | 45 | def _the_function(self): 46 | try: 47 | name = self.function_name.split('.') 48 | return reduce(lambda x, y: getattr(x, y), [self.shell.user_ns[name.pop(0)]] + name) 49 | except (KeyError, AttributeError): 50 | raise UrthException("Invalid function name {}".format( 51 | self.function_name)) 52 | 53 | def _invoke(self, args): 54 | self.log.info("Invoking function {} with args {}...".format( 55 | self.function_name, args)) 56 | try: 57 | result = apply_with_conversion(self._the_function(), args) 58 | serialized_result = self.serializer.serialize( 59 | result, limit=self.limit) 60 | self._send_update("result", serialized_result) 61 | self.ok() 62 | except Exception as e: 63 | self.error("Error while invoking function: {}".format(str(e))) 64 | 65 | def _sync_state(self): 66 | try: 67 | signature = signature_spec(self._the_function()) 68 | self._send_update("signature", signature) 69 | except Exception as e: 70 | self.error("Error while getting function signature: {}".format(str(e))) 71 | -------------------------------------------------------------------------------- /kernel-python/declarativewidgets/widget_ipw_proxy.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | 4 | from traitlets import Unicode # Used to declare attributes of our widget 5 | from IPython.core.getipython import get_ipython 6 | 7 | from .urth_widget import UrthWidget 8 | from .urth_exception import UrthException 9 | 10 | class IpywProxy(UrthWidget): 11 | """ 12 | A Widget to prowy IPywidgets 13 | """ 14 | widget_name = Unicode('', sync=True) 15 | 16 | def __init__(self, **kwargs): 17 | self.log.info("Created a new IpywProxy widget.") 18 | 19 | self.on_msg(self._handle_custom_event_msg) 20 | self.shell = get_ipython() 21 | 22 | super(IpywProxy, self).__init__(**kwargs) 23 | 24 | def _widget_name_changed(self, old, new): 25 | try: 26 | self.log.info("Binding to widget name {}...".format(new)) 27 | self._sync_state() 28 | self.ok() 29 | except Exception as e: 30 | self.error(e) 31 | 32 | def _handle_custom_event_msg(self, wid, content, buffers): 33 | event = content.get('event', '') 34 | if event == 'sync': 35 | self._sync_state() 36 | 37 | def _the_widget(self): 38 | if self.widget_name in self.shell.user_ns: 39 | return self.shell.user_ns[self.widget_name] 40 | else: 41 | raise UrthException("Could not find a widget with name {}".format( 42 | self.widget_name)) 43 | 44 | def _sync_state(self): 45 | try: 46 | the_widget = self._the_widget() 47 | # display the widget 48 | self._send_update("id", the_widget.model_id) 49 | 50 | except Exception as e: 51 | self.error("Error while getting the ipywidget model id: {}".format(str(e))) 52 | -------------------------------------------------------------------------------- /kernel-python/urth/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. -------------------------------------------------------------------------------- /kernel-python/urth/widgets/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | 4 | from declarativewidgets import init 5 | from warnings import warn 6 | 7 | warn("The `urth` package name is deprecated. Will be removed in version 0.7.0. " 8 | "Use 'declarativewidgets' instead.") 9 | 10 | -------------------------------------------------------------------------------- /kernel-python/urth/widgets/widget_channels.py: -------------------------------------------------------------------------------- 1 | from declarativewidgets import channel 2 | from warnings import warn 3 | 4 | 5 | warn("The `urth` package name is deprecated. Will be removed in version 0.7.0. To use channel," 6 | "import from `declarativewidgets` instead.") 7 | 8 | -------------------------------------------------------------------------------- /kernel-r/declarativewidgets/.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | -------------------------------------------------------------------------------- /kernel-r/declarativewidgets/DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: declarativewidgets 2 | Title: Jupyter DeclarativeWidgets 3 | Description: Support for jupyter_declarativewidgets for the IRkernel 4 | Version: 0.1 5 | Authors@R: c(person("Michael", "Poplavski", role = c("aut", "cre"), 6 | email = "mpoplavs@us.ibm.com"), 7 | person("Gino", "Bustelo", role = c("aut"), 8 | email = "lbustelo@us.ibm.com@us.ibm.com")) 9 | Maintainer: Jupyter Development Team 10 | Depends: 11 | R (>= 3.0.1) 12 | Suggests: 13 | testthat (>= 0.7) 14 | License: MIT + file LICENSE 15 | LazyData: true 16 | Encoding: UTF-8 17 | Imports: 18 | IRkernel, 19 | IRdisplay, 20 | uuid, 21 | jsonlite, 22 | R6 23 | Collate: 24 | 'explore.r' 25 | 'queriers.r' 26 | 'querier.r' 27 | 'serializers.r' 28 | 'serializer.r' 29 | 'widget_dataframe.r' 30 | 'widget_function.r' 31 | 'widget_channels.r' 32 | 'widget.r' 33 | RoxygenNote: 6.0.1.9000 34 | -------------------------------------------------------------------------------- /kernel-r/declarativewidgets/NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(Serializer) 4 | export(Widget) 5 | export(channel) 6 | export(explore) 7 | export(initWidgets) 8 | importClassesFrom(IRkernel,Comm) 9 | importFrom(IRdisplay,display_javascript) 10 | importFrom(IRkernel,comm_manager) 11 | importFrom(IRkernel,log_error) 12 | importFrom(IRkernel,log_info) 13 | importFrom(R6,R6Class) 14 | importFrom(jsonlite,fromJSON) 15 | -------------------------------------------------------------------------------- /kernel-r/declarativewidgets/R/explore.r: -------------------------------------------------------------------------------- 1 | # Widget Visualization one line displays 2 | 3 | # explore_env that houses the explore_id 4 | explore_env <- new.env() 5 | #' gets a unique explore id by incrementing an id 6 | #' 7 | #' The function returns a unique id to be used for the explore global df references 8 | #' The explore_id is protected within the explore_env 9 | #' 10 | #' @name get_unique_explore_id 11 | get_unique_explore_id <- function() { 12 | explore_id <- "explore_id" 13 | #init if doesn't exist 14 | if(!exists(explore_id, envir = explore_env)) { 15 | assign(explore_id, 0, envir = explore_env) 16 | } 17 | #get and increment by one 18 | temp_explore_id <- get(explore_id, envir = explore_env) 19 | assign(explore_id, temp_explore_id+1, envir = explore_env) 20 | #return the id after it was incremented 21 | return (get(explore_id, envir = explore_env)) 22 | } 23 | 24 | stringify_properties <- function(properties) { 25 | properties_str <- "" 26 | for (i in names(properties)) { 27 | prop <- { 28 | if (class(properties[[i]]) == "logical") { 29 | if (properties[[i]]) { 30 | i 31 | } 32 | } else { 33 | paste(i, "=", as.character(properties[[i]]), sep="") 34 | } 35 | } 36 | properties_str <- paste(properties_str, prop) 37 | } 38 | return (properties_str) 39 | } 40 | 41 | stringify_bindings <- function(bindings) { 42 | bindings_str <- "" 43 | for (i in names(bindings)) { 44 | binding <- paste(i, "={{", bindings[[i]], "}}", sep="") 45 | bindings_str <- paste(bindings_str, binding) 46 | } 47 | return (bindings_str) 48 | } 49 | 50 | 51 | #' Explore function 52 | #' 53 | #' The explore function is a wrapper around urth-viz-explorer. 54 | #' See the jupyter-incubator/declarativewidgets_explorer project. 55 | #' 56 | #' @name explore 57 | #' @param df the dataframe itself or the string representation of the variable 58 | #' @param channel The channel to bind to defaulted to default 59 | #' @param properties The properties e.g. properties <- list("selection-as-object"=FALSE, foo=5) 60 | #' @param bindings The bindings e.g. bindings <- list(selection='sel') 61 | #' @export 62 | explore <- function(df, channel='default', properties=list(), bindings=list()) { 63 | unique_df_name <- paste("the_literal_template_df_name_", get_unique_explore_id(), sep = "") 64 | register_explore_df <- function(df) { 65 | #assigns df to global env and returns a unique name 66 | assign(unique_df_name, df, envir = .GlobalEnv) 67 | return (unique_df_name) 68 | } 69 | 70 | exlore_df_name <- ifelse(class(df) == "data.frame" || class(df) == "DataFrame", register_explore_df(df), df) 71 | 72 | IRdisplay::display_html(paste(" 74 | ", sep = "")) 78 | } 79 | -------------------------------------------------------------------------------- /kernel-r/declarativewidgets/R/querier.r: -------------------------------------------------------------------------------- 1 | #' @include queriers.r 2 | NULL 3 | 4 | Querier <- R6Class( 5 | 'Querier', 6 | public = list( 7 | querier_list = list(), 8 | apply_query = function(df, query) { 9 | if(!is.null(query) && class(df) %in% names(self$querier_list)) { 10 | return (self$querier_list[[class(df)]]$apply_query_impl(df, query)) 11 | } else { 12 | log_info("df not in querier_list") 13 | return (df) 14 | } 15 | }, 16 | apply_query_impl = function(df, query) { 17 | if(length(query) == 0) { 18 | return (df) 19 | } else { 20 | new_df <- df 21 | for(i in 1:length(query$type)) { 22 | expr <- if (length(query$type) > 1) query$expr[[i]] else query$expr 23 | if(query$type[[i]] == "group") { 24 | if(class(expr) == "data.frame") { 25 | expr <- as.list(as.data.frame(t(expr)))[[1]] 26 | } 27 | new_df <- self$handle_group(new_df, expr) 28 | } else if(query$type[[i]] == "filter") { 29 | new_df <- self$handle_filter(new_df, expr) 30 | } else if(query$type[[i]] == "sort") { 31 | new_df <- self$handle_sort(new_df, expr) 32 | } 33 | } 34 | return (new_df) 35 | } 36 | }, 37 | initialize = function() { 38 | self$querier_list[["data.frame"]] <- DataFrame_Querier$new() 39 | self$querier_list[["DataFrame"]] <- Spark_DataFrame_Querier$new() 40 | } 41 | ) 42 | ) -------------------------------------------------------------------------------- /kernel-r/declarativewidgets/R/queriers.r: -------------------------------------------------------------------------------- 1 | #' @include querier.r 2 | 3 | DataFrame_Querier <- R6Class( 4 | 'DataFrame_Querier', 5 | inherit = Querier, 6 | public = list( 7 | handle_sort = function(df, sort_expr) { 8 | return (df[order(df[,c(as.character(sort_expr$by))], decreasing=(as.character(sort_expr$ascending) == "FALSE")),]) 9 | }, 10 | handle_filter = function(df, filter_expr) { 11 | #extract the filter column/value from the expression 12 | filter_exp_split <- unlist(strsplit(filter_expr, "[ ]")) 13 | column <- filter_exp_split[1] 14 | value <- gsub("'", "", filter_exp_split[3]) 15 | return (df[df[,c(as.character(column))] == as.character(value), ]) 16 | }, 17 | handle_group = function(df, grp_expr) { 18 | cols <- list() 19 | #this is the first column name your grouping on only do once 20 | temp_index <- (aggregate(df[,c(grp_expr$agg[2][,1][1])] ~ df[,c(as.character(grp_expr$by))], df, grp_expr$agg[1][,1][1])[1]) 21 | names(temp_index) <- as.character(grp_expr$by) 22 | cols <- append(cols, temp_index) 23 | for (i in 1:length(grp_expr$agg$op)) { 24 | temp_index <- (aggregate(df[,c(grp_expr$agg[2][,1][i])] ~ df[,c(as.character(grp_expr$by))], df, grp_expr$agg[1][,1][i])[2]) 25 | names(temp_index) <- paste(grp_expr$agg[1][,1][i], "_", grp_expr$agg[2][,1][i], sep="") 26 | cols <- append(cols, temp_index) 27 | } 28 | new_df <- format(data.frame(cols)) 29 | return (new_df) 30 | }, 31 | initialize = function() { 32 | #initialize must exists on this class 33 | } 34 | ) 35 | ) 36 | 37 | Spark_DataFrame_Querier <- R6Class( 38 | 'Spark_DataFrame_Querier', 39 | inherit = Querier, 40 | public = list( 41 | handle_sort = function(df, sort_expr) { 42 | return (SparkR::arrange(df, sort_expr$by, decreasing=(sort_expr$ascending == "FALSE"))) 43 | }, 44 | handle_filter = function(df, filter_expr) { 45 | return (filter(df, filter_expr)) 46 | }, 47 | handle_group = function(df, grp_expr) { 48 | agg_args <- list() 49 | col_names <- list() 50 | by_arg <- SparkR::groupBy(df, as.character(grp_expr$by)) 51 | agg_args <- append(agg_args, by_arg) 52 | for (i in 1:length(grp_expr$agg$op)) { 53 | temp_expr <- paste(grp_expr$agg[1][,1][i], "(", grp_expr$agg[2][,1][i], ")", sep="") 54 | agg_args <- append(agg_args, SparkR::expr(temp_expr)) 55 | temp_name <- paste(grp_expr$agg[1][,1][i], "_", grp_expr$agg[2][,1][i], sep="") 56 | col_names <- append(col_names, temp_name) 57 | } 58 | new_df <- do.call(SparkR::agg, agg_args) 59 | col_names <- append(names(new_df)[1], col_names) 60 | names(new_df) <- col_names 61 | return (new_df) 62 | }, 63 | initialize = function() { 64 | #initialize must exists on this class 65 | } 66 | ) 67 | ) -------------------------------------------------------------------------------- /kernel-r/declarativewidgets/R/serializer.r: -------------------------------------------------------------------------------- 1 | #' @include serializers.r 2 | NULL 3 | 4 | #' @export 5 | Serializer <- R6Class( 6 | 'Serializer', 7 | public = list( 8 | serializer_list = list(), 9 | serialize = function(obj, limit=100) { 10 | #if serializer for the class is registered use it else just return the object 11 | ref_klass <- class(obj) 12 | klass_name <- if (!is.na(ref_klass[2]) && ref_klass[2] == "R6") ref_klass[1] else ref_klass 13 | for(klass in names(self$serializer_list)) { 14 | if(klass_name == klass) { 15 | return (self$serializer_list[[klass]](obj)) 16 | } 17 | } 18 | return (obj) 19 | }, 20 | register_serializer = function(a_serializer) { 21 | if (a_serializer$check_packages()) { 22 | self$serializer_list[[a_serializer$klass()]] <- a_serializer$serialize 23 | } else { 24 | log_info(paste("Unable to load", class(a_serializer)[1], ": dependent package not found.")) 25 | } 26 | }, 27 | load_serializers = function() { 28 | self$register_serializer(DataFrame_Serializer$new()) 29 | self$register_serializer(Time_Series_Serializer$new()) 30 | self$register_serializer(Spark_DataFrame_Serializer$new()) 31 | }, 32 | initialize = function() { 33 | self$load_serializers() 34 | assign("register_serializer", self$register_serializer, envir = .GlobalEnv) 35 | } 36 | ) 37 | ) 38 | -------------------------------------------------------------------------------- /kernel-r/declarativewidgets/declarativewidgets.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 4 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | BuildType: Package 16 | PackageUseDevtools: Yes 17 | PackageInstallArgs: --no-multiarch --with-keep.source 18 | PackageRoxygenize: rd,collate,namespace 19 | -------------------------------------------------------------------------------- /kernel-r/declarativewidgets/man/widgets-package.Rd: -------------------------------------------------------------------------------- 1 | \name{declarativewidgets-package} 2 | \alias{declarativewidgets-package} 3 | \alias{declarativewidgets} 4 | \docType{package} 5 | \title{ 6 | \packageTitle{declarativewidgets} 7 | } 8 | \description{ 9 | \packageDescription{declarativewidgets} 10 | } 11 | \details{ 12 | 13 | The DESCRIPTION file: 14 | \packageDESCRIPTION{declarativewidgets} 15 | \packageIndices{declarativewidgets} 16 | ~~ An overview of how to use the package, including the most important ~~ 17 | ~~ functions ~~ 18 | } 19 | \author{ 20 | \packageAuthor{declarativewidgets} 21 | 22 | Maintainer: \packageMaintainer{declarativewidgets} 23 | } 24 | \references{ 25 | ~~ Literature or other references for background information ~~ 26 | } 27 | ~~ Optionally other standard keywords, one per line, from file KEYWORDS in ~~ 28 | ~~ the R documentation directory ~~ 29 | \keyword{ package } 30 | \seealso{ 31 | ~~ Optional links to other man pages, e.g. ~~ 32 | ~~ \code{\link[:-package]{}} ~~ 33 | } 34 | -------------------------------------------------------------------------------- /kernel-r/declarativewidgets/tests/testthat.R: -------------------------------------------------------------------------------- 1 | #Note file extensions must by capital .R for R CMD check to pick up the tests 2 | 3 | library(testthat) 4 | library(declarativewidgets) 5 | 6 | test_check("declarativewidgets") -------------------------------------------------------------------------------- /kernel-scala/build.sbt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Jupyter Development Team. 3 | * Distributed under the terms of the Modified BSD License. 4 | */ 5 | 6 | import scala.util.Properties 7 | import scala.io.Source 8 | 9 | organization := "org.jupyter" 10 | 11 | name := "declarativewidgets" 12 | 13 | version := { 14 | val releaseVersionPath = "/src_version/RELEASE_VERSION" 15 | if(new java.io.File(releaseVersionPath).exists) { 16 | val src = Source.fromFile(releaseVersionPath) 17 | val version = src.getLines().next() 18 | src.close 19 | val regex = "SNAPSHOT(.*)".r 20 | regex.replaceFirstIn(version, "SNAPSHOT") 21 | } else { 22 | "0.1-SNAPSHOT" 23 | } 24 | } 25 | 26 | scalaVersion := "2.10.4" 27 | 28 | val sparkVersion = "1.6.1" 29 | val toreeVersion = "0.1.0.dev6-incubating-SNAPSHOT" 30 | 31 | resolvers += "Apache Maven Repository" at "https://repository.apache.org/content/repositories/snapshots" 32 | 33 | resolvers += "Typesafe Releases" at "https://repo.typesafe.com/typesafe/releases/" 34 | 35 | libraryDependencies ++= Seq( 36 | "org.apache.toree" %% "toree-kernel" % toreeVersion % "provided", 37 | "org.apache.spark" %% "spark-core" % sparkVersion % "provided", 38 | "org.apache.spark" %% "spark-repl" % sparkVersion % "provided", 39 | "org.apache.spark" %% "spark-core" % sparkVersion % "test" classifier "tests", 40 | "org.scalatest" %% "scalatest" % "2.2.0" % "test", // Apache v2 41 | "org.scalactic" %% "scalactic" % "2.2.0" % "test", // Apache v2 42 | "org.mockito" % "mockito-all" % "1.9.5" % "test" // MIT 43 | ) 44 | 45 | ivyLoggingLevel in ThisBuild := UpdateLogging.Quiet 46 | 47 | parallelExecution in Test := false 48 | 49 | publishMavenStyle := true 50 | 51 | publishTo := { 52 | val nexus = "https://oss.sonatype.org/" 53 | if (isSnapshot.value) 54 | Some("snapshots" at nexus + "content/repositories/snapshots") 55 | else 56 | Some("releases" at nexus + "service/local/staging/deploy/maven2") 57 | } 58 | 59 | publishArtifact in Test := false 60 | 61 | pomIncludeRepository := { _ => false } 62 | 63 | pomExtra := ( 64 | https://github.com/jupyter-incubator/declarativewidgets 65 | 66 | 67 | BSD-style 68 | http://www.opensource.org/licenses/bsd-license.php 69 | repo 70 | 71 | 72 | 73 | git@github.com:jupyter-incubator/declarativewidgets.git 74 | scm:git:git@github.com:jupyter-incubator/declarativewidgets.git 75 | 76 | 77 | 78 | dwidgets 79 | declarative widgets 80 | https://github.com/jupyter-incubator/declarativewidgets/graphs/contributors 81 | 82 | ) 83 | 84 | val repoUsername = Properties.envOrElse("REPO_USERNAME", "") 85 | val repoPassword = Properties.envOrElse("REPO_PASSWORD", "") 86 | 87 | pgpPassphrase := Some(Properties.envOrElse("PGP_PASSPHRASE", "").toCharArray) 88 | 89 | pgpSecretRing := file("/root/.gpg/secring.gpg") 90 | 91 | credentials += Credentials("Sonatype Nexus Repository Manager", 92 | "oss.sonatype.org", 93 | repoUsername, 94 | repoPassword) -------------------------------------------------------------------------------- /kernel-scala/src/main/scala/declarativewidgets/exceptions/WidgetNotAvailableException.scala: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Jupyter Development Team. 3 | * Distributed under the terms of the Modified BSD License. 4 | */ 5 | 6 | package declarativewidgets.exceptions 7 | 8 | case class WidgetNotAvailableException(klass: String) 9 | extends RuntimeException(s"Scala widget class for $klass not found!") 10 | -------------------------------------------------------------------------------- /kernel-scala/src/main/scala/declarativewidgets/query/QuerySupport.scala: -------------------------------------------------------------------------------- 1 | package declarativewidgets.query 2 | 3 | import org.apache.spark.sql.{DataFrame, Column} 4 | import org.apache.spark.sql.functions.{expr, col} 5 | import org.apache.toree.utils.LogLike 6 | import play.api.libs.json._ 7 | 8 | trait QuerySupport extends LogLike { 9 | 10 | def applyQuery( df: DataFrame, query: JsArray = new JsArray()): DataFrame = { 11 | implicit var newdf = df 12 | 13 | query.as[List[JsObject]].foreach( item => 14 | item \ "type" match { 15 | case JsString("filter") => newdf = handleFilter((item \ "expr").as[String]) 16 | case JsString("group") => newdf = handleGroup((item \ "expr").as[JsObject]) 17 | case JsString("sort") => newdf = handleSort((item \ "expr").as[JsObject]) 18 | case _ => logger.warn(s"Unsupported query expression ${item}") 19 | } 20 | ) 21 | 22 | newdf 23 | } 24 | 25 | /** 26 | * Handles the expression of a filter query 27 | * @param expr - a string with filter expression 28 | * @param df 29 | * @return 30 | */ 31 | private[query] def handleFilter(expr: String)(implicit df: DataFrame): DataFrame = { 32 | df.filter(expr) 33 | } 34 | 35 | /** 36 | * Handles the expression of a group query 37 | * @param expr - a JSON object with by and agg clauses 38 | * @param df 39 | * @return 40 | */ 41 | private[query] def handleGroup(expr: JsObject)(implicit df: DataFrame): DataFrame = { 42 | val by = toColExpr( 43 | expr \ "by" match { 44 | case JsString(col) => List(col) 45 | case JsArray(colList:Seq[JsString]) => colList.map(_.as[String]).toList 46 | case _ => Nil 47 | } 48 | ) 49 | 50 | val agg = toArrayOfFuncExpr( 51 | expr \ "agg" match { 52 | case anAgg:JsObject => List(anAgg) 53 | case JsArray(aggList:Seq[JsObject]) => aggList.map(_.as[JsObject]).toList 54 | case _ => List() 55 | 56 | } 57 | ) 58 | //rename resultant column names to dataframe format i.e. sum(columnName) -> sum_columnName 59 | val regex = "\\(".r 60 | val renamedColumns = by.map(_.toString()) ++ agg.map(x => regex.replaceFirstIn(x.toString(), "_").dropRight(1)) 61 | df.groupBy(by:_*).agg(agg.head, agg.tail :_*).toDF(renamedColumns:_*) 62 | } 63 | 64 | /** 65 | * HAndle the expression of a sort query 66 | * @param expr 67 | * @param df 68 | * @return 69 | */ 70 | private[query] def handleSort(expr: JsObject)(implicit df: DataFrame): DataFrame = { 71 | val by = toColExpr( 72 | expr \ "by" match { 73 | case JsString(col) => List(col) 74 | case JsArray(colList:Seq[JsString]) => colList.map(_.as[String]).toList 75 | case _ => Nil 76 | }) 77 | 78 | val ascending = 79 | expr \ "ascending" match { 80 | case JsBoolean(asc) => List(asc) 81 | case JsArray(ascList:Seq[JsBoolean]) => ascList.map(_.as[Boolean]).toList 82 | case _ => Nil 83 | } 84 | 85 | df.orderBy( 86 | (by zip ascending).map{ 87 | case(c,true) => c.asc 88 | case(c,false) => c.desc 89 | } :_* 90 | ) 91 | } 92 | 93 | private[query] def toColExpr(list:List[String]): List[Column] = { 94 | list.map(col(_)) 95 | } 96 | 97 | private[query] def toArrayOfFuncExpr(list:List[JsObject]):List[Column] = { 98 | list.map { 99 | case agg: JsObject => "%s(%s)".format((agg \ "op").as[String],(agg \ "col").as[String]) 100 | }.map { 101 | expr(_) 102 | } 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /kernel-scala/src/main/scala/declarativewidgets/util/Explore.scala: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Jupyter Development Team. 3 | * Distributed under the terms of the Modified BSD License. 4 | */ 5 | 6 | package declarativewidgets.util 7 | 8 | import declarativewidgets.getKernel 9 | import declarativewidgets.sparkIMain 10 | 11 | import org.apache.spark.sql.DataFrame 12 | import org.apache.spark.repl.SparkIMain 13 | import scala.reflect.runtime.universe.ValDef 14 | 15 | /** 16 | * Object that contains Widget Visualization one line displays 17 | */ 18 | 19 | object Explore { 20 | /** 21 | * Gets the currently executing request in SparkIMain used to inspect the explore request 22 | * 23 | * @return The currently executing Request 24 | */ 25 | def getExecutingRequest(): Option[org.apache.spark.repl.SparkIMain#Request]= { 26 | val iMain: SparkIMain = sparkIMain 27 | val requests = iMain.getClass.getDeclaredMethods.filter(_.getName.contains("prevRequestList")).head. 28 | invoke(iMain).asInstanceOf[List[_]].map(_.asInstanceOf[org.apache.spark.repl.SparkIMain#Request]) 29 | iMain.requestForReqId(requests.last.reqId+1) 30 | } 31 | 32 | /** 33 | * Gets the DataFrame variable String representation passed into the currently running execute request 34 | * 35 | * @return The DataFrame variable as a String 36 | */ 37 | def getDfNameFromLastExploreRequest(): String = { 38 | val executingRequest = getExecutingRequest() 39 | val requestTrees = executingRequest.map(_.trees.head.asInstanceOf[reflect.runtime.universe.Tree]) 40 | val valDefTrees = requestTrees collect {case c: ValDef => c} 41 | val exploreTrees = valDefTrees.filter({ eTree => 42 | val children = eTree.rhs.children 43 | children.length > 0 && children.head.toString.equals("explore") 44 | }) 45 | exploreTrees.last.rhs.children(1).toString 46 | } 47 | 48 | /** 49 | * Display/renderer for the kernel 50 | * 51 | * @param df DataFrame reference as a String 52 | * @param channel channel reference as a String 53 | * @param properties properties as a String 54 | * @param bindings bindings as a String 55 | */ 56 | def display(df: String, channel: String, properties: String, bindings: String) = { 57 | val explorerImport = 58 | """ 59 | 61 | """ 62 | getKernel.display.html(s"$explorerImport " + 63 | s"") 66 | } 67 | 68 | def stringifyProperties(properties: Map[String, Any]) = { 69 | properties.map { 70 | case (k, v) => { 71 | v match { 72 | case isProp: Boolean => if(isProp) k else "" 73 | case _ => k + "=" + v 74 | } 75 | } 76 | }.mkString(" ") 77 | } 78 | 79 | def stringifyBindings(bindings: Map[String, String]) = { 80 | bindings.map { 81 | case (k, v) => { 82 | s"$k={{$v}}" 83 | } 84 | }.mkString(" ") 85 | } 86 | 87 | /** 88 | * Renders the urth-viz-explorer widget to the user output 89 | * 90 | * @param df The (Spark DataFrame or String of the variable) 91 | * @param channel The channel to bind to defaulted to default 92 | * @param properties Map of properties e.g. {'selection-as-object': False, 'foo': 5} 93 | * @param bindings Map of bindings e.g. {'selection': 'sel'} 94 | */ 95 | def explore(df: Any, channel: String, properties: Map[String, Any], bindings: Map[String, String]) = { 96 | df match { 97 | case d : DataFrame => { 98 | val dfString = getDfNameFromLastExploreRequest() 99 | display(dfString, channel, stringifyProperties(properties), stringifyBindings(bindings)) 100 | } 101 | case s: String => { 102 | display(s, channel, stringifyProperties(properties), stringifyBindings(bindings)) 103 | } 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /kernel-scala/src/main/scala/declarativewidgets/util/MessageSupport.scala: -------------------------------------------------------------------------------- 1 | package declarativewidgets.util 2 | 3 | import declarativewidgets.Comm 4 | import org.apache.toree.comm.CommWriter 5 | import org.apache.toree.utils.LogLike 6 | import play.api.libs.json.{JsValue, Json} 7 | 8 | /** 9 | * Provides functions for sending messages using a CommWriter. 10 | */ 11 | case class MessageSupport(val comm:CommWriter) extends LogLike { 12 | 13 | /** 14 | * Send a state update for the given state key and value. 15 | * @param key Name of the state parameter to update. 16 | * @param value JSON representation of the new parameter value. 17 | */ 18 | def sendState(key: String, value: JsValue): Unit = { 19 | sendState(Map(key -> value)) 20 | } 21 | 22 | /** 23 | * Send a state update with the give Map of key/value pairs. 24 | * @param state A Map with name of Name of the state parameter and JSON value to update. 25 | */ 26 | def sendState(state: Map[String,JsValue]): Unit = { 27 | 28 | val msg = Json.obj( 29 | Comm.KeyMethod -> Comm.MethodUpdate, 30 | Comm.KeyState -> state 31 | ) 32 | logger.debug(s"Sending state message ${msg}") 33 | send(msg) 34 | } 35 | 36 | /** 37 | * Send a status update with the given status and message. 38 | * @param status "ok" or "error" 39 | * @param msg Optional status message, e.g. an error message. 40 | */ 41 | def sendStatus(status: String, msg: String = ""): Unit = { 42 | val statusJson = Json.obj( 43 | Comm.KeyStatus -> status, 44 | Comm.KeyMessage -> msg, 45 | Comm.KeyTimestamp -> timestamp 46 | ) 47 | sendState(Comm.KeyStatusMsg, statusJson) 48 | } 49 | 50 | /** 51 | * Send a status error message to the front-end with the given message. 52 | * @param msg An error message. 53 | */ 54 | def sendError(msg: String) = sendStatus(Comm.StatusError, msg) 55 | 56 | /** 57 | * Send a status ok message to the front-end with the given message. 58 | * @param msg An optional status message. 59 | */ 60 | def sendOk(msg: String = "") = sendStatus(Comm.StatusOk, msg) 61 | 62 | /** 63 | * Send a JSON message using the given comm writer. 64 | * @param msg Message to send. 65 | */ 66 | def send(msg: JsValue): Unit = comm.writeMsg(msg) 67 | 68 | private[util] def timestamp: Long = System.currentTimeMillis() 69 | 70 | } 71 | -------------------------------------------------------------------------------- /kernel-scala/src/main/scala/declarativewidgets/util/SerializationSupport.scala: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Jupyter Development Team. 3 | * Distributed under the terms of the Modified BSD License. 4 | */ 5 | 6 | package declarativewidgets.util 7 | 8 | import declarativewidgets.Default 9 | import org.apache.toree.utils.LogLike 10 | import org.apache.spark.sql.DataFrame 11 | import play.api.libs.json._ 12 | 13 | import org.apache.spark.sql.types.TimestampType 14 | import org.apache.spark.sql.types.DateType 15 | import org.apache.spark.sql.types.IntegerType 16 | import org.apache.spark.sql.types.StringType 17 | import org.apache.spark.sql.types.BooleanType 18 | import org.apache.spark.sql.types.DoubleType 19 | 20 | /** 21 | * Contains methods for serializing a variable based on its type. 22 | */ 23 | trait SerializationSupport extends LogLike { 24 | 25 | /** 26 | * Serialize the given variable to a JSON representation based on the 27 | * inferred runtime type. 28 | * 29 | * @param x variable to serialize 30 | * @param limit Bounds the output for some serializers, e.g. limits the 31 | * number of rows returned for a DataFrame. 32 | * @return JSON representation of `x` 33 | */ 34 | def serialize(x: Any, limit: Int = Default.Limit): JsValue = { 35 | logger.trace(s"Serializing ${x}...") 36 | x match { 37 | case d: DataFrame => dataFrameWrites(limit).writes(d) 38 | case x: Float => JsNumber(x.toDouble) 39 | case x: Double => JsNumber(x) 40 | case x: Int => JsNumber(x) 41 | case x: Boolean => JsBoolean(x) 42 | case x: BigDecimal => JsNumber(x) 43 | case s: Seq[_] => JsArray((s map(serialize(_, limit)))) 44 | case a: Array[_] => JsArray((a map(serialize(_, limit)))) 45 | case t: Product => JsArray((t.productIterator.toList map(serialize(_, limit)))) 46 | case m: Map[_, _] => JsObject( 47 | m.map(p => (p._1.toString, serialize(p._2, limit))).toSeq 48 | ) 49 | case j: JsValue => j 50 | case _ => Json.toJson(x.toString) 51 | } 52 | } 53 | 54 | /** 55 | * Serializer for a Spark DataFrame. 56 | * @param limit Maximum number of rows to include in the serialization. 57 | * @return Writes function used to convert a DataFrame to JSON. 58 | */ 59 | def dataFrameWrites(limit: Int) = Writes { 60 | (df: DataFrame) => { 61 | val columns: Array[String] = df.columns 62 | 63 | //https://spark.apache.org/docs/latest/api/java/org/apache/spark/sql/types/package-tree.html 64 | //match possible date types the user may be using 65 | val columnTypes: Array[String] = df.schema.map( 66 | x => x.dataType match { 67 | case timeStamp: TimestampType => "Date" 68 | case date: DateType => "Date" 69 | case int: IntegerType => "Number" 70 | case double: DoubleType => "Number" 71 | case string: StringType => "String" 72 | case boolean: BooleanType => "Boolean" 73 | case _ => "Unknown" 74 | }).toArray 75 | 76 | val data: Array[Array[JsValue]] = df.toJSON.take(limit).map( jsonRow => toArray(Json.parse(jsonRow).as[JsObject], columns)) 77 | 78 | val index: Array[String] = (0 until data.length).map(_.toString).toArray 79 | 80 | Json.obj( 81 | "columns" -> columns, 82 | "columnTypes" -> columnTypes, 83 | "index" -> index, 84 | "data" -> data 85 | ) 86 | } 87 | } 88 | 89 | /** 90 | * Transform the JsObject into an Array of JsValue ordered by the columns array. 91 | * @param jsonRow 92 | * @param columns 93 | * @return 94 | */ 95 | def toArray( jsonRow:JsObject, columns:Array[String] ): Array[JsValue] = { 96 | columns.map(fieldName => jsonRow \ fieldName) 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /kernel-scala/src/main/scala/urth/widgets/package.scala: -------------------------------------------------------------------------------- 1 | package urth 2 | 3 | import declarativewidgets.{Channel, ConnectedChannel, Default} 4 | import org.apache.toree.kernel.api.Kernel 5 | 6 | package object widgets { 7 | 8 | def initWidgets(implicit kernel: Kernel) = { 9 | kernel.err.println("The `urth` package name is deprecated. Will be removed in version 0.7.0. Use 'declarativewidgets' instead.") 10 | declarativewidgets.initWidgets 11 | } 12 | 13 | object WidgetChannels { 14 | def channel(chan: String = Default.Channel): Channel = { 15 | if( declarativewidgets.getKernel != null ) { 16 | declarativewidgets.getKernel.err.println("The `urth` package name is deprecated. Will be removed in version 0.7.0. Use 'declarativewidgets' instead.") 17 | declarativewidgets.getKernel.err.flush() 18 | } 19 | declarativewidgets.WidgetChannels.channel(chan) 20 | } 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /kernel-scala/src/test/scala/declarativewidgets/util/MessageSupportSpec.scala: -------------------------------------------------------------------------------- 1 | package declarativewidgets.util 2 | 3 | import declarativewidgets.Comm 4 | import org.apache.toree.comm.CommWriter 5 | import org.mockito.Mockito._ 6 | import org.scalatest.mock.MockitoSugar 7 | import org.scalatest.{Matchers, FunSpec} 8 | import play.api.libs.json.{JsNumber, JsString, Json} 9 | 10 | class MessageSupportSpec extends FunSpec with Matchers with MockitoSugar { 11 | 12 | class TestSupport(comm: CommWriter = mock[CommWriter]) extends MessageSupport(comm) { 13 | override def timestamp = 0 14 | } 15 | 16 | describe("#sendState") { 17 | it("should send a properly formatted update state message") { 18 | val expected = Json.obj("method" -> "update", "state" -> Map("a" -> "b")) 19 | val comm = mock[CommWriter] 20 | val test = new TestSupport(comm) 21 | test.sendState("a", JsString("b")) 22 | verify(comm).writeMsg(org.mockito.Matchers.eq(expected)) 23 | } 24 | } 25 | 26 | describe("#sendStatus") { 27 | it("should send a properly formatted status message") { 28 | val expectedData = Json.obj( 29 | Comm.KeyStatus -> "status", 30 | Comm.KeyMessage -> "message", 31 | Comm.KeyTimestamp -> 0 32 | ) 33 | val comm = mock[CommWriter] 34 | val test = spy(new TestSupport) 35 | test.sendStatus("status", "message") 36 | 37 | verify(test).sendState(Comm.KeyStatusMsg, expectedData); 38 | } 39 | } 40 | 41 | describe("#sendState") { 42 | it("should send a state message with the widget's comm") { 43 | val msgSupport = spy(MessageSupport(mock[CommWriter])) 44 | 45 | msgSupport.sendState("a", JsString("b")) 46 | verify(msgSupport).sendState("a", JsString("b")) 47 | } 48 | } 49 | 50 | describe("#sendError") { 51 | it("should send a status error message with the widget's comm") { 52 | val msgSupport = spy(MessageSupport(mock[CommWriter])) 53 | 54 | msgSupport.sendError("bayud") 55 | verify(msgSupport).sendStatus(Comm.StatusError, "bayud") 56 | } 57 | } 58 | 59 | describe("#sendOk") { 60 | it("should send a state message with the widget's comm") { 61 | val msgSupport = spy(MessageSupport(mock[CommWriter])) 62 | 63 | msgSupport.sendOk("goodness") 64 | verify(msgSupport).sendStatus(Comm.StatusOk, "goodness") 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /nb-extension/css/main.css: -------------------------------------------------------------------------------- 1 | .urth-loading { 2 | display: block; 3 | height: 5px; 4 | position: relative; 5 | } 6 | 7 | .urth-loading:before { 8 | content: ''; 9 | display: block; 10 | position: absolute; 11 | width: 100%; 12 | height: 5px; 13 | background-color: #42A5F5; 14 | position: relative; 15 | overflow: hidden; 16 | } 17 | 18 | /* code to stripe the bar */ 19 | .urth-loading:after { 20 | content: ""; 21 | position: absolute; 22 | top: 0; left: 0; bottom: 0; right: 0; 23 | background-image: -webkit-gradient( 24 | linear, 0 0, 100% 100%, 25 | color-stop(.25, rgba(255, 255, 255, .5)), 26 | color-stop(.25, transparent), color-stop(.5, transparent), 27 | color-stop(.5, rgba(255, 255, 255, .5)), 28 | color-stop(.75, rgba(255, 255, 255, .5)), 29 | color-stop(.75, transparent), to(transparent) 30 | ); 31 | background-image: -moz-linear-gradient( 32 | -45deg, 33 | rgba(255, 255, 255, .5) 25%, 34 | transparent 25%, 35 | transparent 50%, 36 | rgba(255, 255, 255, .5) 50%, 37 | rgba(255, 255, 255, .5) 75%, 38 | transparent 75%, 39 | transparent 40 | ); 41 | background-image: linear-gradient( 42 | -45deg, 43 | rgba(255, 255, 255, .5) 25%, 44 | transparent 25%, 45 | transparent 50%, 46 | rgba(255, 255, 255, .5) 50%, 47 | rgba(255, 255, 255, .5) 75%, 48 | transparent 75%, 49 | transparent 50 | ); 51 | z-index: 1; 52 | -webkit-background-size: 50px 50px; 53 | -moz-background-size: 50px 50px; 54 | background-size: 50px 50px; 55 | -webkit-animation: urth-move-loading 1s linear infinite; 56 | -moz-animation: urth-move-loading 1s linear infinite; 57 | animation: urth-move-loading 1s linear infinite; 58 | overflow: hidden; 59 | } 60 | 61 | @-webkit-keyframes urth-move-loading { 62 | 0% { 63 | background-position: 0 0; 64 | } 65 | 100% { 66 | background-position: 25px 25px; 67 | } 68 | } 69 | 70 | @-moz-keyframes urth-move-loading { 71 | 0% { 72 | background-position: 0 0; 73 | } 74 | 100% { 75 | background-position: 25px 25px; 76 | } 77 | } 78 | 79 | @keyframes urth-move-loading { 80 | 0% { 81 | background-position: 0 0; 82 | } 83 | 100% { 84 | background-position: 25px 25px; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /nb-extension/js/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Jupyter Development Team. 3 | * Distributed under the terms of the Modified BSD License. 4 | */ 5 | define([ 6 | 'require' 7 | ], function(require) { 8 | 'use strict'; 9 | 10 | var load_css = function (name) { 11 | var link = document.createElement('link'); 12 | link.type = 'text/css'; 13 | link.rel = 'stylesheet'; 14 | link.href = name; 15 | document.getElementsByTagName('head')[0].appendChild(link); 16 | }; 17 | 18 | return { 19 | load_ipython_extension: function () { 20 | return new Promise(function(resolve) { 21 | //create a mapping for declarativewidgets and its dependencies 22 | requirejs.config({ 23 | map: { 24 | '*': { 25 | 'jupyter-decl-widgets': 'nbextensions/declarativewidgets/js/widgets' 26 | }, 27 | 'nbextensions/declarativewidgets/js': { 28 | 'jupyter-js-widgets': 'ipywidgets4-or-jupyter-js-widgets' 29 | } 30 | }, 31 | paths: { 32 | 'ipywidgets4-or-jupyter-js-widgets': [ 33 | 'does/not/exist', //HACK: fallbacks was acting strange with 2 items 34 | Jupyter.notebook.base_url+'nbextensions/widgets/widgets/js/widget', 35 | Jupyter.notebook.base_url+'nbextensions/jupyter-js-widgets/extension', 36 | ] 37 | } 38 | }); 39 | 40 | require([ 41 | 'base/js/namespace', 42 | 'base/js/events', 43 | './init/init' 44 | ],function(Jupyter, events, init) { 45 | init({ 46 | namespace: Jupyter, 47 | events: events 48 | }); 49 | 50 | load_css(window.Urth._getModuleBasedComponentRoot() + 'css/main.css'); 51 | console.debug('loaded declarativewidgets'); 52 | resolve(); 53 | }); 54 | }); 55 | } 56 | }; 57 | }); 58 | -------------------------------------------------------------------------------- /nb-extension/js/widgets/DeclWidgetModel.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jupyter Development Team. 2 | // Distributed under the terms of the Modified BSD License. 3 | 4 | define(["jupyter-js-widgets"], function(widgets) { 5 | "use strict"; 6 | 7 | /** 8 | * Collection of patches on top of ipywidgets.WidgetModel 9 | */ 10 | var DeclWidgetModel = widgets.WidgetModel.extend({ 11 | constructor: function() { 12 | widgets.WidgetModel.apply(this, arguments); 13 | // WidgetModel expects widgets' state to be set from kernel and won't 14 | // set `_first_state` to false until that happens. But DeclWidgets 15 | // are different: we do initial setup on client and then notify kernel. 16 | this._first_state = false; 17 | }, 18 | 19 | /* 20 | * Avoiding out of sequence messages due to new promise/async code in WidgetModel 21 | */ 22 | send_sync_message: function(attrs, callbacks) { 23 | var data = {method: 'backbone', sync_data: attrs}; 24 | this.comm.send(data, callbacks); 25 | } 26 | }); 27 | 28 | return { 29 | DeclWidgetModel: DeclWidgetModel 30 | }; 31 | 32 | }); -------------------------------------------------------------------------------- /nb-extension/python/declarativewidgets/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | 4 | def _jupyter_nbextension_paths(): 5 | '''API for JS extension installation on notebook 4.2''' 6 | return [{ 7 | 'section': 'notebook', 8 | 'src': 'static', 9 | 'dest': 'declarativewidgets', 10 | 'require': 'declarativewidgets/js/main' 11 | }] 12 | 13 | def _jupyter_server_extension_paths(): 14 | '''API for server extension installation on notebook 4.2''' 15 | return [{ 16 | "module": "urth.widgets.ext.urth_import" 17 | }] -------------------------------------------------------------------------------- /nb-extension/python/urth/widgets/ext/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. -------------------------------------------------------------------------------- /nb-extension/python/urth/widgets/ext/_version.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | 4 | version_info = (0, 8, 0, 'dev') 5 | __version__ = '.'.join(map(str, version_info)) -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "urth-widgets", 3 | "version": "0.1.0", 4 | "description": "Extensions for Jupyter / IPython Notebook for interactive widgets using Polymer.", 5 | "devDependencies": { 6 | "bower": "^1.7.1", 7 | "gulp": "^3.9.0", 8 | "gulp-run": "^1.6.10", 9 | "gulp-watch": "^4.3.4", 10 | "http-server": "^0.8.5", 11 | "hydrolysis": "^1.19.1", 12 | "polybuild": "^1.0.5", 13 | "mocha" :"^2.0.0", 14 | "wd": "latest", 15 | "chai": "latest", 16 | "chai-as-promised": "latest", 17 | "colors": "latest", 18 | "minimist": "latest", 19 | "selenium-standalone": "latest", 20 | "web-component-tester": "^4", 21 | "vulcanize": "1.14.8", 22 | "wct-local": "2.0.11" 23 | }, 24 | "config": {}, 25 | "scripts": { 26 | "bower": "bower", 27 | "docsbower": "cd dist/docs && bower", 28 | "http-server": "http-server", 29 | "polybuild": "polybuild", 30 | "test": "wct elements/*/test", 31 | "test-sauce": "wct --skip-plugin local --plugin sauce elements/*/test", 32 | "system-test": "node_modules/mocha/bin/mocha --timeout 500000 --reporter spec", 33 | "watch": "gulp watch", 34 | "watch-docs": "gulp watch-docs" 35 | }, 36 | "repository": { 37 | "type": "git", 38 | "url": "https://github.com/jupyter-incubator/declarativewidgets.git" 39 | }, 40 | "keywords": [ 41 | "ipython", 42 | "jupyter", 43 | "urth" 44 | ], 45 | "author": "Jupyter Community" 46 | } 47 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) Jupyter Development Team. 2 | # Distributed under the terms of the Modified BSD License. 3 | 4 | import os 5 | import sys 6 | from setuptools import setup, find_packages 7 | 8 | # Get location of this file at runtime 9 | HERE = os.path.abspath(os.path.dirname(__file__)) 10 | 11 | # Eval the version tuple and string from the source 12 | VERSION_NS = {} 13 | with open(os.path.join(HERE, 'urth/widgets/ext/_version.py')) as f: 14 | exec(f.read(), {}, VERSION_NS) 15 | 16 | VERSION_FILE = os.path.join(HERE, 'VERSION') 17 | 18 | # Apply version to build 19 | if os.path.isfile(VERSION_FILE): 20 | # CI build, read metadata and append 21 | with open(VERSION_FILE, 'r') as fh: 22 | BUILD_INFO = fh.readline().strip() 23 | fh.close() 24 | 25 | with open(VERSION_FILE, 'w') as fh: 26 | fh.write(VERSION_NS['__version__'] + '\n') 27 | fh.write(BUILD_INFO + '\n') 28 | fh.close() 29 | 30 | setup_args = dict( 31 | name='jupyter_declarativewidgets', 32 | author='Jupyter Development Team', 33 | author_email='jupyter@googlegroups.com', 34 | description='Jupyter extensions for supporting declarative widgets', 35 | url='https://github.com/jupyter-incubator/declarativewidgets', 36 | version=VERSION_NS['__version__'], 37 | license='BDS', 38 | platforms=['Jupyter Notebook 4.0.x'], 39 | packages=find_packages(), 40 | include_package_data=True, 41 | scripts=[ 42 | 'scripts/jupyter-declarativewidgets' 43 | ] 44 | ) 45 | 46 | if 'setuptools' in sys.modules: 47 | # setupstools turns entrypoint scripts into executables on windows 48 | setup_args['entry_points'] = { 49 | 'console_scripts': [ 50 | 'jupyter-declarativewidgets = declarativewidgets.extensionapp:main' 51 | ] 52 | } 53 | # Don't bother installing the .py scripts if if we're using entrypoints 54 | setup_args.pop('scripts', None) 55 | 56 | if __name__ == '__main__': 57 | setup(**setup_args) 58 | 59 | 60 | -------------------------------------------------------------------------------- /system-test/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | -------------------------------------------------------------------------------- /system-test/urth-core-bind-specs.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jupyter Development Team. 2 | // Distributed under the terms of the Modified BSD License. 3 | 4 | var wd = require('wd'); 5 | var Boilerplate = require('./utils/boilerplate'); 6 | var boilerplate = new Boilerplate(); 7 | 8 | describe('Urth Core Bind', function() { 9 | 10 | boilerplate.setup(this.title, '/notebooks/tests/urth-core-bind.ipynb'); 11 | 12 | it('should wait for dependency to load', function(done) { 13 | // Using a random number to protect against the possibility of a previous 14 | // test run value having been persisted. 15 | var inputString = 'Hello ' + Math.random(); 16 | 17 | boilerplate.browser 18 | .waitForElementById('titleInput', wd.asserters.isDisplayed, 10000) 19 | .elementById('titleInput') 20 | .click() 21 | .type(inputString) 22 | .elementById('titleSpan') 23 | .text().should.eventually.include(inputString) 24 | .nodeify(done); 25 | }); 26 | 27 | it('should synchronize array item changes cross cell on the same channel', function(done) { 28 | // Using a random number to protect against the possibility of a previous 29 | // test run value having been persisted. 30 | var inputString = 'Hello ' + Math.random(); 31 | 32 | boilerplate.browser 33 | .waitForElementById('t2Person', wd.asserters.isDisplayed, 10000) 34 | .elementById('t2Person') 35 | .click() 36 | .type(boilerplate.SPECIAL_KEYS.Enter) // Needed for IE 37 | .type(inputString) 38 | .elementById('t3Person') 39 | .text().should.eventually.include(inputString) 40 | .elementById('t1Person') 41 | .getValue().should.eventually.include(inputString) 42 | .nodeify(done); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /system-test/urth-r-widgets-specs.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jupyter Development Team. 2 | // Distributed under the terms of the Modified BSD License. 3 | 4 | var wd = require('wd'); 5 | var Boilerplate = require('./utils/boilerplate'); 6 | var boilerplate = new Boilerplate(); 7 | 8 | process.env.PYTHON != "python2" && describe('Widgets R System Test', function() { 9 | boilerplate.setup(this.title, '/notebooks/tests/urth-r-widgets.ipynb'); 10 | 11 | it('should print the result of a Function Widget invocation', function(done) { 12 | boilerplate.browser 13 | .waitForElementByClassName('test1', wd.asserters.textInclude('10'), 60000) 14 | .nodeify(done); 15 | }); 16 | 17 | it('should bind and update a channel variable', function(done) { 18 | boilerplate.browser 19 | .waitForElementById('invokeButton', wd.asserters.isDisplayed, 60000) 20 | .click() 21 | .click() // Safari requires extra click for some reason 22 | .waitForElementByClassName('test2', wd.asserters.textInclude('mike'), 60000) 23 | .nodeify(done); 24 | }); 25 | 26 | it('should print the contents of the Dataframe Widget', function(done) { 27 | boilerplate.browser 28 | .waitForElementByClassName('test3', wd.asserters.textInclude('John'), 60000) 29 | .nodeify(done); 30 | }); 31 | 32 | it('should print the contents of the SparkDataframe Widget', function(done) { 33 | boilerplate.browser 34 | .waitForElementByClassName('test4', wd.asserters.textInclude('John'), 60000) 35 | .nodeify(done); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /system-test/urth-viz-table-specs.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Jupyter Development Team. 2 | // Distributed under the terms of the Modified BSD License. 3 | 4 | var wd = require('wd'); 5 | var chai = require('chai'); 6 | var Boilerplate = require('./utils/boilerplate'); 7 | var boilerplate = new Boilerplate(); 8 | 9 | describe('Urth Viz Table Test', function() { 10 | 11 | var tagChaiAssertionError = function(err) { 12 | // throw error and tag as retriable to poll again 13 | err.retriable = err instanceof chai.AssertionError; 14 | throw err; 15 | }; 16 | 17 | wd.PromiseChainWebdriver.prototype.waitForWidgetElement = function(selector, browserSupportsShadowDOM, timeout, pollFreq) { 18 | return this.waitForElementByCssSelector( 19 | browserSupportsShadowDOM ? 'urth-viz-table::shadow .handsontable' : 'urth-viz-table .handsontable', 20 | wd.asserters.isDisplayed, 21 | timeout) 22 | .catch(tagChaiAssertionError); 23 | }; 24 | 25 | boilerplate.setup(this.title, '/notebooks/tests/urth-viz-table.ipynb'); 26 | 27 | it('should run all cells and find a handsontable in the 3rd output area', function(done) { 28 | boilerplate.browser 29 | .waitForElementsByCssSelector('div.output_area').nth(3) 30 | .waitForWidgetElement("urth-viz-table", boilerplate.browserSupportsShadowDOM, 10000) 31 | .nodeify(done); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /wct.conf.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Jupyter Development Team. 3 | * Distributed under the terms of the Modified BSD License. 4 | */ 5 | module.exports = { 6 | plugins: { 7 | local: { 8 | browsers: ['chrome'] 9 | }, 10 | sauce: { 11 | disabled: true, 12 | browsers: [ 13 | { 14 | browserName: "firefox", 15 | platform: "Linux" 16 | }, 17 | { 18 | browserName: "safari", 19 | platform: "OS X 10.10" 20 | }, 21 | { 22 | browserName: "chrome", 23 | platform: "Windows 10" 24 | }, 25 | { 26 | browserName: "internet explorer", 27 | platform: "Windows 8.1" 28 | } 29 | // Don't run MicrosoftEdge until Windows 10 Anniversary update 30 | // is available as the nested template test fails 31 | // in urth-core-bind before that update. 32 | // { 33 | // browserName: "MicrosoftEdge", 34 | // platform: "Windows 10" 35 | // } 36 | ] 37 | } 38 | }, 39 | webserver: { 40 | pathMappings: [ 41 | {'/elements': 'bower_components'} 42 | ], 43 | urlPrefix: '' 44 | } 45 | }; 46 | --------------------------------------------------------------------------------