Initial code import
This commit is contained in:
Коммит
5060c283d8
|
@ -0,0 +1,5 @@
|
|||
[repo]
|
||||
upstream_urls = [
|
||||
'git@github.com:WorldWideTelescope/wwt_kernel_data_relay.git',
|
||||
'https://github.com/WorldWideTelescope/wwt_kernel_data_relay.git',
|
||||
]
|
|
@ -0,0 +1,6 @@
|
|||
[report]
|
||||
omit = wwt_kernel_data_relay/*tests/*
|
||||
exclude_lines =
|
||||
pragma: no cover
|
||||
if __name__ == .__main__.:
|
||||
raise NotImplementedError
|
|
@ -0,0 +1,8 @@
|
|||
*.py[cod]
|
||||
*.egg
|
||||
*.egg-info
|
||||
/dist/
|
||||
/build/
|
||||
/eggs/
|
||||
/sdist/
|
||||
__pycache__/
|
|
@ -0,0 +1,15 @@
|
|||
version: 2
|
||||
|
||||
build:
|
||||
image: latest
|
||||
|
||||
python:
|
||||
version: 3.7
|
||||
install:
|
||||
- method: pip
|
||||
path: .
|
||||
extra_requirements:
|
||||
- docs
|
||||
|
||||
# Don't build any extra formats
|
||||
formats: []
|
|
@ -0,0 +1,8 @@
|
|||
# See elsewhere for changelog
|
||||
|
||||
This project’s release notes are curated from the Git history of its main
|
||||
branch. You can find them by looking at [the version of this file on the
|
||||
`release` branch][branch] or the [GitHub release history][gh-releases].
|
||||
|
||||
[branch]: https://github.com/WorldWideTelescope/wwt_kernel_data_relay/blob/release/CHANGELOG.md
|
||||
[gh-releases]: https://github.com/WorldWideTelescope/wwt_kernel_data_relay/releases
|
|
@ -0,0 +1,18 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,15 @@
|
|||
include LICENSE
|
||||
include .coveragerc
|
||||
include *.md
|
||||
include *.yml
|
||||
|
||||
graft docs
|
||||
prune docs/_build
|
||||
|
||||
graft wwt_kernel_data_relay/tests
|
||||
|
||||
global-exclude *~
|
||||
global-exclude *.pyc
|
||||
global-exclude *.pyo
|
||||
global-exclude .git
|
||||
global-exclude .ipynb_checkpoints
|
|
@ -0,0 +1,79 @@
|
|||
|
||||
# WWT Kernel Data Relay
|
||||
|
||||
<!--pypi-begin-->
|
||||
[wwt_kernel_data_relay] is a [Jupyter server extension][ext] that enables
|
||||
[Jupyter kernels][kernels] to publish some of their data files to the Web; that
|
||||
is, to request that the Jupyter HTTP server make them accessible at a
|
||||
predictable URL. This functionality is used by [pywwt], the [AAS] [WorldWide
|
||||
Telescope] Python library, to expose kernel-side data assets for visualization
|
||||
inside the WWT [research app][rapp].
|
||||
|
||||
[wwt_kernel_data_relay]: https://github.com/WorldWideTelescope/wwt_kernel_data_relay/
|
||||
[ext]: https://jupyter-notebook.readthedocs.io/en/stable/extending/handlers.html
|
||||
[kernels]: https://jupyter.readthedocs.io/en/latest/projects/kernels.html
|
||||
[pywwt]: https://pywwt.readthedocs.io/
|
||||
[AAS]: https://aas.org/
|
||||
[WorldWide Telescope]: http://www.worldwidetelescope.org/
|
||||
[rapp]: https://docs.worldwidetelescope.org/research-app/latest/
|
||||
<!--pypi-end-->
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
Install [wwt_kernel_data_relay] with [pip]:
|
||||
|
||||
```
|
||||
pip install wwt_kernel_data_relay
|
||||
```
|
||||
|
||||
[pip]: https://pip.pypa.io/
|
||||
|
||||
|
||||
## Contributions
|
||||
|
||||
Contributions to [wwt_kernel_data_relay] are welcome! See
|
||||
[the WorldWide Telescope contributors’ guide][contrib] for applicable information. We
|
||||
use a standard workflow with issues and pull requests. All participants in
|
||||
[wwt_kernel_data_relay] and the WWT communities must abide by the
|
||||
[WWT Code of Conduct].
|
||||
|
||||
[contrib]: https://worldwidetelescope.github.io/contributing/
|
||||
[WWT Code of Conduct]: https://worldwidetelescope.github.io/code-of-conduct/
|
||||
|
||||
|
||||
## Release History
|
||||
|
||||
Releases of [wwt_kernel_data_relay] are logged in the file
|
||||
[CHANGELOG.md](https://github.com/WorldWideTelescope/wwt_kernel_data_relay/blob/release/CHANGELOG.md)
|
||||
on the `release` branch of this repository, as well as release listings
|
||||
maintained by
|
||||
[GitHub](https://github.com/WorldWideTelescope/wwt_kernel_data_relay/releases) and
|
||||
[PyPI](https://pypi.org/project/wwt_kernel_data_relay/#history).
|
||||
|
||||
|
||||
## Dependencies
|
||||
|
||||
[wwt_kernel_data_relay] is a [Jupyter server extension][ext] so it is only
|
||||
useful if the Jupyter [notebook] package is installed.
|
||||
|
||||
[notebook]: https://jupyter-notebook.readthedocs.io/
|
||||
|
||||
|
||||
## Legalities
|
||||
|
||||
[wwt_kernel_data_relay] is copyright the .NET Foundation. It is licensed under the
|
||||
[MIT License](./LICENSE).
|
||||
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
[wwt_kernel_data_relay] is part of the AAS WorldWide Telescope system, a [.NET
|
||||
Foundation] project managed by the non-profit [American Astronomical Society]
|
||||
(AAS). Work on WWT has been supported by the AAS, the US [National Science
|
||||
Foundation], and other partners. See [the WWT user website][acks] for details.
|
||||
|
||||
[.NET Foundation]: https://dotnetfoundation.org/
|
||||
[American Astronomical Society]: https://aas.org/
|
||||
[National Science Foundation]: https://www.nsf.gov/
|
||||
[acks]: https://worldwidetelescope.org/about/acknowledgments/
|
|
@ -0,0 +1 @@
|
|||
/_build/
|
|
@ -0,0 +1,20 @@
|
|||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS = -W
|
||||
SPHINXBUILD = python -msphinx
|
||||
SPHINXPROJ = wwt_kernel_data_relay
|
||||
SOURCEDIR = .
|
||||
BUILDDIR = _build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
@ -0,0 +1,92 @@
|
|||
// Copyright (c) 2014-2018, Astropy Developers
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice, this
|
||||
// list of conditions and the following disclaimer in the documentation and/or
|
||||
// other materials provided with the distribution.
|
||||
// * Neither the name of the Astropy Team nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
$(document).ready(function() {
|
||||
/* Add a [>>>] button on the top-right corner of code samples to hide
|
||||
* the >>> and ... prompts and the output and thus make the code
|
||||
* copyable. */
|
||||
var div = $('.highlight-python .highlight,' +
|
||||
'.highlight-python3 .highlight,' +
|
||||
'.highlight-default .highlight')
|
||||
var pre = div.find('pre');
|
||||
|
||||
// get the styles from the current theme
|
||||
pre.parent().parent().css('position', 'relative');
|
||||
var hide_text = 'Hide the prompts and output';
|
||||
var show_text = 'Show the prompts and output';
|
||||
var border_width = pre.css('border-top-width');
|
||||
var border_style = pre.css('border-top-style');
|
||||
var border_color = pre.css('border-top-color');
|
||||
var button_styles = {
|
||||
'cursor':'pointer', 'position': 'absolute', 'top': '0', 'right': '0',
|
||||
'border-color': border_color, 'border-style': border_style,
|
||||
'border-width': '1px', 'color': border_color, 'font-size': '11px',
|
||||
'color': '#aaaaaa',
|
||||
'padding-left': '0.2em', 'padding-right': '0.2em',
|
||||
'border-radius': '0 3px 0 0'
|
||||
}
|
||||
|
||||
// create and add the button to all the code blocks that contain >>>
|
||||
div.each(function(index) {
|
||||
var jthis = $(this);
|
||||
if (jthis.find('.gp').length > 0) {
|
||||
var button = $('<span class="copybutton">Hide prompt</span>');
|
||||
button.css(button_styles)
|
||||
button.attr('title', hide_text);
|
||||
button.data('hidden', 'false');
|
||||
jthis.prepend(button);
|
||||
}
|
||||
// tracebacks (.gt) contain bare text elements that need to be
|
||||
// wrapped in a span to work with .nextUntil() (see later)
|
||||
jthis.find('pre:has(.gt)').contents().filter(function() {
|
||||
return ((this.nodeType == 3) && (this.data.trim().length > 0));
|
||||
}).wrap('<span>');
|
||||
});
|
||||
|
||||
// define the behavior of the button when it's clicked
|
||||
$('.copybutton').click(function(e){
|
||||
e.preventDefault();
|
||||
var button = $(this);
|
||||
if (button.data('hidden') === 'false') {
|
||||
// hide the code output
|
||||
button.parent().find('.go, .gp, .gt').hide();
|
||||
button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'hidden');
|
||||
// button.css('text-decoration', 'line-through');
|
||||
button.text('Show prompt');
|
||||
button.attr('title', show_text);
|
||||
button.data('hidden', 'true');
|
||||
} else {
|
||||
// show the code output
|
||||
button.parent().find('.go, .gp, .gt').show();
|
||||
button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'visible');
|
||||
// button.css('text-decoration', 'none');
|
||||
button.text('Hide prompt');
|
||||
button.attr('title', hide_text);
|
||||
button.data('hidden', 'false');
|
||||
}
|
||||
});
|
||||
});
|
|
@ -0,0 +1,24 @@
|
|||
{% extends "!layout.html" %}
|
||||
{%- block extrahead %}
|
||||
{% if not embedded %}
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="{{ pathto('_static/copybutton.js', 1) }}"></script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{# astropy hardcodes a link to astropy.org in the header bar, which we don't want #}
|
||||
{# It also hardcodes an Astropy logo in the `a.brand` element that we remove #}
|
||||
{% block header %}
|
||||
<div class="topbar">
|
||||
<a class="brand" title="{{ _('Documentation Home') }}" href="{{ pathto(master_doc) }}" style="background: transparent;"><span id="logotext1">{{ theme_logotext1 }}</span><span id="logotext2">{{ theme_logotext2 }}</span><span id="logotext3">{{ theme_logotext3 }}</span></a>
|
||||
<ul>
|
||||
<li><a title="{{ _('General Index') }}" href="{{ pathto('genindex') }}">Index</a></li>
|
||||
<li><a title="{{ _('Module Index') }}" href="{{ pathto('py-modindex') }}">Modules</a></li>
|
||||
<li>
|
||||
{% block sidebarsearch %}
|
||||
{% include "searchbox.html" %}
|
||||
{% endblock %}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,11 @@
|
|||
=============
|
||||
API Reference
|
||||
=============
|
||||
|
||||
.. automodapi:: wwt_kernel_data_relay
|
||||
:no-inheritance-diagram:
|
||||
:no-inherited-members:
|
||||
|
||||
.. automodapi:: wwt_kernel_data_relay.serverextension
|
||||
:no-inheritance-diagram:
|
||||
:no-inherited-members:
|
|
@ -0,0 +1,6 @@
|
|||
load_jupyter_server_extension
|
||||
=============================
|
||||
|
||||
.. currentmodule:: wwt_kernel_data_relay
|
||||
|
||||
.. autofunction:: load_jupyter_server_extension
|
|
@ -0,0 +1,6 @@
|
|||
load_jupyter_server_extension
|
||||
=============================
|
||||
|
||||
.. currentmodule:: wwt_kernel_data_relay.serverextension
|
||||
|
||||
.. autofunction:: load_jupyter_server_extension
|
|
@ -0,0 +1,56 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
project = 'wwt_kernel_data_relay'
|
||||
author = 'The AAS WorldWide Telescope Team'
|
||||
copyright = '2019-2021 the .NET Foundation'
|
||||
|
||||
release = '0.dev0' # cranko project-version
|
||||
version = '.'.join(release.split('.')[:2])
|
||||
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.doctest',
|
||||
'sphinx.ext.intersphinx',
|
||||
'sphinx.ext.mathjax',
|
||||
'sphinx.ext.viewcode',
|
||||
'sphinx_automodapi.automodapi',
|
||||
'sphinx_automodapi.smart_resolver',
|
||||
'numpydoc',
|
||||
]
|
||||
|
||||
templates_path = ['_templates']
|
||||
source_suffix = '.rst'
|
||||
master_doc = 'index'
|
||||
language = None
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
pygments_style = 'sphinx'
|
||||
todo_include_todos = False
|
||||
|
||||
html_theme = 'bootstrap-astropy'
|
||||
html_theme_options = {
|
||||
'logotext1': 'wwt_kernel_data_relay',
|
||||
'logotext2': '',
|
||||
'logotext3': ':docs',
|
||||
'astropy_project_menubar': False,
|
||||
}
|
||||
html_static_path = ['_static']
|
||||
htmlhelp_basename = 'wwtkerneldatarelaydoc'
|
||||
|
||||
intersphinx_mapping = {
|
||||
'python': (
|
||||
'https://docs.python.org/3/',
|
||||
(None, 'http://data.astropy.org/intersphinx/python3.inv')
|
||||
),
|
||||
}
|
||||
|
||||
numpydoc_show_class_members = False
|
||||
|
||||
nitpicky = True
|
||||
nitpick_ignore = []
|
||||
|
||||
default_role = 'obj'
|
||||
|
||||
html_logo = 'images/logo.png'
|
||||
|
||||
linkcheck_retries = 5
|
||||
linkcheck_timeout = 10
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 266 KiB |
|
@ -0,0 +1,51 @@
|
|||
=============================
|
||||
WWT Jupyter Kernel Data Relay
|
||||
=============================
|
||||
|
||||
`wwt_kernel_data_relay`_ is a `Jupyter server extension`_ that enables `Jupyter
|
||||
kernels`_ to publish some of their data files to the Web; that is, to request
|
||||
that the Jupyter HTTP server make them accessible at a predictable URL. This
|
||||
functionality is used by `pywwt`_ to expose kernel-side data assets for
|
||||
visualization inside the `WWT research app`_.
|
||||
|
||||
.. _wwt_kernel_data_relay: https://github.com/WorldWideTelescope/wwt_kernel_data_relay/
|
||||
.. _Jupyter server extension: https://jupyter-notebook.readthedocs.io/en/stable/extending/handlers.html
|
||||
.. _Jupyter kernels: https://jupyter.readthedocs.io/en/latest/projects/kernels.html
|
||||
.. _pywwt: https://pywwt.readthedocs.io/
|
||||
.. _WWT research app: https://docs.worldwidetelescope.org/research-app/latest/
|
||||
|
||||
|
||||
Detailed Table of Contents
|
||||
==========================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
installation
|
||||
specification
|
||||
api
|
||||
|
||||
|
||||
Getting help
|
||||
============
|
||||
|
||||
If you run into any issues when using `wwt_kernel_data_relay`_, please open an
|
||||
issue `on its GitHub repository
|
||||
<https://github.com/WorldWideTelescope/wwt_kernel_data_relay/issues>`_.
|
||||
|
||||
|
||||
Acknowledgments
|
||||
===============
|
||||
|
||||
`wwt_kernel_data_relay`_ is part of the `AAS`_ `WorldWide Telescope`_ system, a
|
||||
`.NET Foundation`_ project managed by the non-profit `American Astronomical
|
||||
Society`_ (AAS). Work on WWT has been supported by the AAS, the US `National
|
||||
Science Foundation`_, and other partners. See `the WWT user website`_ for
|
||||
details.
|
||||
|
||||
.. _.NET Foundation: https://dotnetfoundation.org/
|
||||
.. _AAS: https://aas.org/
|
||||
.. _WorldWide Telescope: https://worldwidetelescope.org/home/
|
||||
.. _American Astronomical Society: https://aas.org/
|
||||
.. _National Science Foundation: https://www.nsf.gov/
|
||||
.. _the WWT user website: https://worldwidetelescope.org/about/acknowledgments/
|
|
@ -0,0 +1,39 @@
|
|||
================================
|
||||
Installing wwt_kernel_data_relay
|
||||
================================
|
||||
|
||||
Installing wwt_kernel_data_relay with pip
|
||||
=========================================
|
||||
|
||||
You can install the latest release of ``wwt_kernel_data_relay`` using pip_::
|
||||
|
||||
pip install wwt_kernel_data_relay
|
||||
|
||||
.. _pip: https://pip.pypa.io/en/stable/
|
||||
|
||||
|
||||
Dependencies
|
||||
============
|
||||
|
||||
If you install ``wwt_kernel_data_relay`` using pip_ as described above, any
|
||||
required dependencies will get installed automatically. The `README in the Git
|
||||
repository`_ lists the current dependencies if you would like to see an
|
||||
explict list.
|
||||
|
||||
.. _README in the Git repository: https://github.com/WorldWideTelescope/wwt_kernel_data_relay/#readme
|
||||
|
||||
|
||||
Installing the developer version
|
||||
================================
|
||||
|
||||
If you want to use the very latest developer version, you should clone `this
|
||||
repository <https://github.com/WorldWideTelescope/wwt_kernel_data_relay/>`_ and manually
|
||||
install the package in “editable” mode::
|
||||
|
||||
git clone https://github.com/WorldWideTelescope/wwt_kernel_data_relay.git
|
||||
cd wwt_kernel_data_relay
|
||||
pip install -e .
|
||||
|
||||
You can run the test suite with the command::
|
||||
|
||||
pytest wwt_kernel_data_relay
|
|
@ -0,0 +1,36 @@
|
|||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=python -msphinx
|
||||
)
|
||||
set SOURCEDIR=.
|
||||
set BUILDDIR=_build
|
||||
set SPHINXPROJ=wwt_kernel_data_relay
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The Sphinx module was not found. Make sure you have Sphinx installed,
|
||||
echo.then set the SPHINXBUILD environment variable to point to the full
|
||||
echo.path of the 'sphinx-build' executable. Alternatively you may add the
|
||||
echo.Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
|
||||
|
||||
:end
|
||||
popd
|
|
@ -0,0 +1,75 @@
|
|||
.. _specification:
|
||||
|
||||
==============================
|
||||
WWT KDR Protocol Specification
|
||||
==============================
|
||||
|
||||
This document specifies the interactions between the WWT kernel data relay (KDR)
|
||||
and various Jupyter kernels that use it to publish data.
|
||||
|
||||
|
||||
URL Structure
|
||||
=============
|
||||
|
||||
The URLs that are ultimately provided by the KDR have the form:
|
||||
|
||||
.. code-block::
|
||||
|
||||
{base-url}/wwtkdr/{key}/{entry...}
|
||||
|
||||
Here, ``base-url`` is the base URL of the Jupyter notebook server, which is
|
||||
easily determined on the server side and is not-so-easily determined on the
|
||||
kernel side. The base URL is not necessarily absolute, however, and there may be
|
||||
different kinds of proxies or redirectors in place that prevent either the
|
||||
kernel *or* the server from knowing the true, actual public URL at which their
|
||||
content is ultimately made available. The only way to reliably construct a fully
|
||||
absolute URL is in the frontend JavaScript code, by combining a KDR URL with the
|
||||
current window's ``location``.
|
||||
|
||||
The ``key`` is a unique identifier associated with exactly one Jupyter kernel. A
|
||||
running kernel must “claim” a key before any data it publishes will be
|
||||
accessible. Later on, a different kernel can override the claim and take over
|
||||
the association between key and kernel; this functionality is required so that
|
||||
URLs have the possibility of continuing to work across kernel restarts. A single
|
||||
kernel may claim multiple keys.
|
||||
|
||||
The ``entry...`` identifies resources published by a specific kernel. The
|
||||
structure and semantics of the ``entry`` portion of the URL are unspecified;
|
||||
each kernel may use whichever scheme it deems appropriate.
|
||||
|
||||
|
||||
Claiming Keys
|
||||
=============
|
||||
|
||||
A kernel can claim a URL key by publishing a message of type
|
||||
``wwtkdr_claim_key`` on its `IOPub socket`_. The message content should have the
|
||||
form:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
'key': $key
|
||||
}
|
||||
|
||||
Where ``$key`` is the key being claimed by the kernel. This value should not be
|
||||
empty and it should *not* be URL-escaped.
|
||||
|
||||
.. _IOPub socket: https://jupyter-client.readthedocs.io/en/stable/messaging.html
|
||||
|
||||
|
||||
Requesting Resources
|
||||
====================
|
||||
|
||||
When the server receives a request for a KDR URL path, the key will be used to
|
||||
map the request to a specific kernel. That kernel will be sent a message on its
|
||||
`shell socket`_ of type ``wwtkdr_resource_request`` with the following content
|
||||
structure:
|
||||
|
||||
.. _shell socket: https://jupyter-client.readthedocs.io/en/stable/messaging.html
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
'method': 'GET',
|
||||
'entry': $entry,
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
[tool.cranko]
|
||||
extra_python_rewrite_files = [
|
||||
"docs/conf.py"
|
||||
]
|
|
@ -0,0 +1,79 @@
|
|||
# -*- mode: python; coding: utf-8 -*-
|
||||
# Copyright 2019-2021 the .NET Foundation
|
||||
# Licensed under the MIT License
|
||||
|
||||
import os
|
||||
from setuptools import setup, Extension
|
||||
|
||||
def get_long_desc():
|
||||
in_preamble = True
|
||||
lines = []
|
||||
|
||||
with open('README.md', 'rt', encoding='utf8') as f:
|
||||
for line in f:
|
||||
if in_preamble:
|
||||
if line.startswith('<!--pypi-begin-->'):
|
||||
in_preamble = False
|
||||
else:
|
||||
if line.startswith('<!--pypi-end-->'):
|
||||
break
|
||||
else:
|
||||
lines.append(line)
|
||||
|
||||
lines.append('''
|
||||
|
||||
For more information, including installation instructions, please visit [the
|
||||
project homepage].
|
||||
|
||||
[the project homepage]: https://github.com/WorldWideTelescope/wwt_kernel_data_relay/
|
||||
''')
|
||||
return ''.join(lines)
|
||||
|
||||
|
||||
setup_args = dict(
|
||||
name = 'wwt_kernel_data_relay', # cranko project-name
|
||||
version = '0.dev0', # cranko project-version
|
||||
description = 'Jupyter server extension to allow kernels to make data web-accessible',
|
||||
long_description = get_long_desc(),
|
||||
long_description_content_type = 'text/markdown',
|
||||
url = 'https://github.com/WorldWideTelescope/wwt_kernel_data_relay/',
|
||||
license = 'MIT',
|
||||
platforms = 'Linux, Mac OS X, Windows',
|
||||
|
||||
author = 'AAS WorldWide Telescope Team',
|
||||
author_email = 'wwt@aas.org',
|
||||
|
||||
classifiers = [
|
||||
'Intended Audience :: Science/Research',
|
||||
'License :: OSI Approved :: MIT License',
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python :: 3.7',
|
||||
'Programming Language :: Python :: 3.8',
|
||||
'Programming Language :: Python :: 3.9',
|
||||
'Topic :: Scientific/Engineering :: Astronomy',
|
||||
'Topic :: Scientific/Engineering :: Visualization',
|
||||
],
|
||||
|
||||
packages = [
|
||||
'wwt_kernel_data_relay',
|
||||
#'wwt_kernel_data_relay.tests',
|
||||
],
|
||||
include_package_data = True,
|
||||
|
||||
install_requires = [],
|
||||
|
||||
extras_require = {
|
||||
'test': [
|
||||
'pytest-cov',
|
||||
],
|
||||
'docs': [
|
||||
'astropy-sphinx-theme',
|
||||
'numpydoc',
|
||||
'sphinx',
|
||||
'sphinx-automodapi',
|
||||
],
|
||||
},
|
||||
)
|
||||
|
||||
if __name__ == '__main__':
|
||||
setup(**setup_args)
|
|
@ -0,0 +1,14 @@
|
|||
# Copyright 2021 the .NET Foundation
|
||||
# Licensed under the MIT License
|
||||
|
||||
"""
|
||||
The main module for the WWT kernel data relay Jupyter server extension.
|
||||
|
||||
It contains no nontrivial functionality of its own.
|
||||
"""
|
||||
|
||||
from .serverextension import load_jupyter_server_extension # noqa
|
||||
|
||||
# See: https://jupyter-notebook.readthedocs.io/en/stable/examples/Notebook/Distributing%20Jupyter%20Extensions%20as%20Python%20Packages.html
|
||||
def _jupyter_server_extension_paths():
|
||||
return [{"module": "wwt_kernel_data_relay.serverextension"}]
|
|
@ -0,0 +1,151 @@
|
|||
# Copyright 2021 the .NET Foundation
|
||||
# Licensed under the MIT License
|
||||
|
||||
"""
|
||||
The WWT kernel data relay Jupyter notebook server extension.
|
||||
"""
|
||||
|
||||
from tornado import gen
|
||||
|
||||
from jupyter_client.session import Session
|
||||
from notebook.utils import url_path_join
|
||||
from notebook.base.handlers import IPythonHandler
|
||||
|
||||
__all__ = ['load_jupyter_server_extension']
|
||||
|
||||
|
||||
class Registry(object):
|
||||
"""
|
||||
A registry of kernels that have expressed an interest in publishing data files.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._key_to_kid = {}
|
||||
|
||||
def watch_new_kernel(self, kernel_id, km):
|
||||
session = Session(
|
||||
config = km.session.config,
|
||||
key = km.session.key,
|
||||
)
|
||||
|
||||
stream = km.connect_iopub()
|
||||
print('WWTKDR: watching kernel', kernel_id)
|
||||
|
||||
def watch_iopubs(msg_list):
|
||||
idents, fed_msg_list = session.feed_identities(msg_list)
|
||||
msg = session.deserialize(fed_msg_list)
|
||||
msg_type = msg['header']['msg_type']
|
||||
|
||||
if msg_type == 'wwtkdr_claim_key':
|
||||
key = msg['content'].get('key')
|
||||
|
||||
if not key:
|
||||
print('WWTKDR: missing/empty key in claim?')
|
||||
else:
|
||||
print(f'WWTKDR: key {key} claimed by kernel {kernel_id}')
|
||||
self._key_to_kid[key] = kernel_id
|
||||
|
||||
stream.on_recv(watch_iopubs)
|
||||
|
||||
def get(self, key):
|
||||
return self._key_to_kid.get(key)
|
||||
|
||||
|
||||
class DataRequestHandler(IPythonHandler):
|
||||
def initialize(self, registry):
|
||||
self.registry = registry
|
||||
|
||||
@gen.coroutine
|
||||
def get(self, key, entry):
|
||||
authenticated = bool(self.current_user)
|
||||
|
||||
print('************* WWTKDR HANDLER *****************')
|
||||
print('auth:', authenticated)
|
||||
print('key:', key)
|
||||
print('entry:', entry)
|
||||
|
||||
kernel_id = self.registry.get(key)
|
||||
if kernel_id is None:
|
||||
self.clear()
|
||||
self.set_status(404)
|
||||
self.finish(f'unrecognized WWTKDR key {key!r}')
|
||||
return
|
||||
print('kernel_id:', kernel_id)
|
||||
|
||||
try:
|
||||
km = self.kernel_manager.get_kernel(kernel_id)
|
||||
except Exception as e:
|
||||
self.clear()
|
||||
self.set_status(404)
|
||||
self.finish(f'could not get kernel for WWTKDR key {key!r}: {e}')
|
||||
return
|
||||
|
||||
kc = km.client()
|
||||
|
||||
content = dict(
|
||||
method = 'GET',
|
||||
entry = entry,
|
||||
)
|
||||
msg = kc.session.msg('wwtkdr_resource_request', content)
|
||||
msg_id = msg['header']['msg_id']
|
||||
kc.shell_channel.send(msg)
|
||||
self.clear()
|
||||
self.set_header('Content-Type', 'image/png') # XXXXXXXXXX
|
||||
|
||||
while True:
|
||||
reply = yield kc.get_shell_msg(timeout=30)
|
||||
print('============= reply:')
|
||||
print(reply)
|
||||
print('====================')
|
||||
|
||||
if reply['parent_header'].get('msg_id') != msg_id:
|
||||
print('** not my message')
|
||||
continue
|
||||
|
||||
status = reply['content'].get('status', 'unspecified')
|
||||
if status != 'ok':
|
||||
raise HTTPError(500)
|
||||
|
||||
if not len(reply['buffers']):
|
||||
break
|
||||
|
||||
self.write(bytes(reply['buffers'][0]))
|
||||
|
||||
self.finish(b'')
|
||||
|
||||
|
||||
def load_jupyter_server_extension(nb_server_app):
|
||||
"""
|
||||
Initialize the server extension.
|
||||
|
||||
The argument ``nb_server_app`` is an instance of
|
||||
``notebook.notebookapp.NotebookWebApplication``.
|
||||
"""
|
||||
|
||||
web_app = nb_server_app.web_app
|
||||
host_pattern = '.*$'
|
||||
route_pattern = url_path_join(web_app.settings['base_url'], '/wwtkdr/([^/]*)/(.*)')
|
||||
|
||||
# The registry of kernels and URL "keys"
|
||||
|
||||
registry = Registry()
|
||||
|
||||
# Register our handler that will relay requests for data files.
|
||||
|
||||
web_app.add_handlers(host_pattern, [
|
||||
(route_pattern, DataRequestHandler, {'registry': registry}),
|
||||
])
|
||||
|
||||
# In order for the registry to be notified of when a kernel has requested a
|
||||
# URL prefix, we need to shim ourselves into the kernel startup framework
|
||||
# and register a message listener.
|
||||
|
||||
app_km = nb_server_app.kernel_manager
|
||||
orig_start_watching_activity = app_km.start_watching_activity
|
||||
|
||||
def shimmed_start_watching_activity(kernel_id):
|
||||
orig_start_watching_activity(kernel_id)
|
||||
km = app_km.get_kernel(kernel_id)
|
||||
registry.watch_new_kernel(kernel_id, km)
|
||||
|
||||
app_km.start_watching_activity = shimmed_start_watching_activity
|
Загрузка…
Ссылка в новой задаче