make it a proper package

both jupyterhub and configurable-http-proxy
This commit is contained in:
MinRK
2014-08-20 16:41:02 -07:00
parent ef93fed9a4
commit 8ca425fd8a
22 changed files with 290 additions and 11 deletions

3
.bowerrc Normal file
View File

@@ -0,0 +1,3 @@
{
"directory": "share/jupyter/components"
}

5
.gitignore vendored
View File

@@ -2,3 +2,8 @@ node_modules
*.py[co]
*~
.DS_Store
build
dist
share/jupyter/components
*.egg-info
MANIFEST

View File

@@ -6,8 +6,10 @@ python:
before_install:
# workaround for https://github.com/travis-ci/travis-cookbooks/issues/155
- sudo rm -rf /dev/shm && sudo ln -s /run/shm /dev/shm
- time npm install
- time npm install -g bower .
- time sudo apt-get install libzmq3-dev
- time pip install -f https://nipy.bic.berkeley.edu/wheelhouse/travis -r requirements.txt -r dev-requirements.txt
- time pip install -f https://nipy.bic.berkeley.edu/wheelhouse/travis -r dev-requirements.txt
install:
- time pip install .
script:
- py.test jupyterhub

24
MANIFEST.in Normal file
View File

@@ -0,0 +1,24 @@
include README.md
include COPYING.md
include setupegg.py
graft jupyterhub
graft scripts
# Load configproxy js
graft lib
# Documentation
graft docs
# docs subdirs we want to skip
prune docs/build
prune docs/gh-pages
prune docs/dist
# Patterns to exclude from any directory
global-exclude *~
global-exclude *.pyc
global-exclude *.pyo
global-exclude .git
global-exclude .ipynb_checkpoints

View File

@@ -17,12 +17,14 @@ Basic principals:
## dependencies
npm install
pip install -r requirements.txt
# get the dependencies of the nodejs proxy (-g for global install)
npm install [-g]
# install the Python pargs (-e for editable/development install)
pip install [-e] .
## to use
$> python -m jupyterhub
$> jupyterhub
visit `http://localhost:8000`, and login (any username, password=`password`).
visit `http://localhost:8000`, and login with your unix credentials.

9
bower.json Normal file
View File

@@ -0,0 +1,9 @@
{
"name": "ipython-deps",
"version": "0.0.1",
"dependencies": {
"bootstrap": "components/bootstrap#~3.1",
"font-awesome": "components/font-awesome#~4.1",
"jquery": "components/jquery#~2.0"
}
}

View File

@@ -0,0 +1 @@
from .version import *

17
jupyterhub/_data.py Normal file
View File

@@ -0,0 +1,17 @@
"""Get the data files for this package."""
def get_data_files():
"""Walk up until we find share/jupyter"""
import os
path = os.path.abspath(os.path.dirname(__file__))
while path != '/':
share_jupyter = os.path.join(path, 'share', 'jupyter')
if os.path.exists(share_jupyter):
return share_jupyter
path, _ = os.path.split(path)
return ''
# Package managers can just override this with the appropriate constant
DATA_FILES_PATH = get_data_files()

View File

@@ -1,6 +1,10 @@
#!/usr/bin/env python
"""The multi-user notebook application"""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
import logging
import os
from subprocess import Popen
@@ -29,10 +33,15 @@ from .handlers import (
)
from . import db
from ._data import DATA_FILES_PATH
from .utils import url_path_join
class JupyterHubApp(Application):
"""An Application for starting a Multi-User Notebook server."""
data_files_path = Unicode(DATA_FILES_PATH, config=True,
help="The location of jupyter data files (e.g. /usr/local/share/jupyter)"
)
ip = Unicode('localhost', config=True,
help="The public facing ip of the proxy"
)
@@ -42,6 +51,13 @@ class JupyterHubApp(Application):
base_url = Unicode('/', config=True,
help="The base URL of the entire application"
)
proxy_cmd = Unicode('configurable-http-proxy', config=True,
help="""The command to start the http proxy.
Only override if configurable-http-proxy is not on your PATH
"""
)
proxy_auth_token = Unicode(config=True,
help="The Proxy Auth token"
)
@@ -206,7 +222,7 @@ class JupyterHubApp(Application):
"""Actually start the configurable-http-proxy"""
env = os.environ.copy()
env['CONFIGPROXY_AUTH_TOKEN'] = self.proxy.auth_token
self.proxy = Popen(["node", os.path.join(here, 'js', 'main.js'),
self.proxy = Popen([self.proxy_cmd,
'--port', str(self.proxy.public_server.port),
'--api-port', str(self.proxy.api_server.port),
'--upstream-port', str(self.hub.server.port),
@@ -217,7 +233,7 @@ class JupyterHubApp(Application):
base_url = self.base_url
settings = dict(
config=self.config,
log=self.log,
# log=self.log,
db=self.db,
hub=self.hub,
authenticator=import_item(self.authenticator)(config=self.config),

View File

@@ -1,5 +1,8 @@
"""Simple PAM authenticator"""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
from tornado import gen
import simplepam

View File

@@ -1,6 +1,9 @@
#!/usr/bin/env python
"""Extend regular notebook server to be aware of multiuser things."""
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
import os
import requests

View File

@@ -1,5 +1,8 @@
"""Tests for PAM authentication"""
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
import mock
import simplepam
from tornado.testing import AsyncTestCase, gen_test

View File

@@ -5,6 +5,7 @@
import socket
import time
from subprocess import check_call, CalledProcessError, STDOUT, PIPE
from IPython.html.utils import url_path_join
@@ -27,4 +28,3 @@ def wait_for_server(ip, port, timeout=10):
time.sleep(0.1)
else:
break

15
jupyterhub/version.py Normal file
View File

@@ -0,0 +1,15 @@
"""jupyterhub version info"""
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
version_info = (
0,
0,
1,
'dev', # comment-out this line for a release
)
__version__ = '.'.join(map(str, version_info[:3]))
if len(version_info) > 3:
__version__ = '%s-%s' % (__version__, version_info[3])

View File

@@ -5,10 +5,17 @@
"author": "IPython Developers",
"repository": {
"type": "git",
"url": "https://github.com/minrk/multiuser"
"url": "https://github.com/jupyter/jupyterhub"
},
"dependencies": {
"http-proxy": "~1.1",
"commander": "~2.2"
},
"files": [
"lib/configproxy.js",
"lib/main.js"
],
"bin": {
"configurable-http-proxy": "lib/main.js"
}
}

View File

@@ -1,4 +1,6 @@
ipython[notebook]
tornado>=3.2
jinja2
simplepam
sqlalchemy
requests

4
scripts/jupyterhub Normal file
View File

@@ -0,0 +1,4 @@
#!/usr/bin/env python
from jupyterhub.app import main
main()

View File

@@ -0,0 +1,4 @@
#!/usr/bin/env python
from jupyterhub.singleuserapp import main
main()

152
setup.py Executable file
View File

@@ -0,0 +1,152 @@
#!/usr/bin/env python
# coding: utf-8
# Copyright (c) Juptyer Development Team.
# Distributed under the terms of the Modified BSD License.
#-----------------------------------------------------------------------------
# Minimal Python version sanity check (from IPython)
#-----------------------------------------------------------------------------
from __future__ import print_function
import os
import sys
v = sys.version_info
if v[:2] < (2,7) or (v[0] >= 3 and v[:2] < (3,3)):
error = "ERROR: IPython requires Python version 2.7 or 3.3 or above."
print(error, file=sys.stderr)
sys.exit(1)
PY3 = (sys.version_info[0] >= 3)
if os.name in ('nt', 'dos'):
error = "ERROR: Windows is not supported"
print(error, file=sys.stderr)
# At least we're on the python version we need, move on.
import os
from glob import glob
from distutils.core import setup
from subprocess import check_call
try:
execfile
except NameError:
# py3
def execfile(fname, globs, locs=None):
locs = locs or globs
exec(compile(open(fname).read(), fname, "exec"), globs, locs)
here = os.path.abspath(os.path.dirname(__file__))
pjoin = os.path.join
#---------------------------------------------------------------------------
# Build basic package data, etc.
#---------------------------------------------------------------------------
def get_data_files():
"""Get data files in share/jupyter"""
data_files = []
share_jupyter = pjoin(here, 'share', 'jupyter')
ntrim = len(here) + 1
for (d, dirs, filenames) in os.walk(share_jupyter):
data_files.append((
d[ntrim:],
[ pjoin(d, f) for f in filenames ]
))
return data_files
ns = {}
execfile(pjoin(here, 'jupyterhub', 'version.py'), ns)
setup_args = dict(
name = 'jupyterhub',
scripts = glob(pjoin('scripts', '*')),
packages = ['jupyterhub'],
package_data = {'jupyterhub' : ['templates/*']},
# dummy, so that install_data doesn't get skipped
# this will be overridden when bower is run anyway
data_files = get_data_files() or ['dummy'],
version = ns['__version__'],
description = """JupyterHub: A multi-user server for Jupyter notebooks""",
long_description = "",
author = "Jupyter Development Team",
author_email = "ipython-dev@scipy.org",
url = "http://jupyter.org",
license = "BSD",
platforms = "Linux, Mac OS X",
keywords = ['Interactive', 'Interpreter', 'Shell', 'Web'],
classifiers = [
'Intended Audience :: Developers',
'Intended Audience :: Science/Research',
'License :: OSI Approved :: BSD License',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Topic :: System :: Shells',
],
)
#---------------------------------------------------------------------------
# custom distutils commands
#---------------------------------------------------------------------------
# imports here, so they are after setuptools import if there was one
from distutils.cmd import Command
from distutils.command.install import install
class Bower(Command):
description = "fetch static components with bower"
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
check_call(['bower', 'install'])
self.distribution.data_files = get_data_files()
def get_outputs(self):
return []
def get_inputs(self):
return []
# ensure bower is run as part of install
install.sub_commands.insert(0, ('bower', None))
setup_args['cmdclass'] = {
'bower': Bower,
}
# setuptools requirements
if 'setuptools' in sys.modules:
setup_args['zip_safe'] = False
with open('requirements.txt') as f:
install_requires = [ line.strip() for line in f.readlines() ]
setup_args['install_requires'] = install_requires
#---------------------------------------------------------------------------
# setup
#---------------------------------------------------------------------------
def main():
setup(**setup_args)
if __name__ == '__main__':
main()

7
setupegg.py Executable file
View File

@@ -0,0 +1,7 @@
#!/usr/bin/env python
"""Wrapper to run setup.py using setuptools."""
# Import setuptools and call the actual setup
import setuptools
with open('setup.py', 'rb') as f:
exec(compile(f.read(), 'setup.py', 'exec'))