The idea is to show you how you can create a cheap and interactive app that makes ajax calls and update some info in the browser just using the IPython notebook and brythonmagic.
Brythomagic is an IPython cell magic that allows you to use Brython, a Python3 implementation coded using javascript, so your can code Python on the client side instead of using javascript.
The brython code in the notebook should work even in nbviewer.ipython.org so you don't have to download the notebook and run it locally and you have a simple app running for free showing a dummy example of use.
First of all, let's take some popular libs. The libs are taken from pythonwheels.com as the 360 most downloaded python libs from pypi. In this set you can find libraries to develop webs, to make some number crunching, to manage images, to interact with the system...
In [1]:
packages = ['setuptools', 'simplejson', 'requests', 'six', 'virtualenv',
'pip', 'boto', 'certifi', 'pbr', 'python-dateutil', 'wincertstore',
'pytz', 'lxml', 'nose', 'Jinja2', 'pyasn1', 'PyYAML', 'docutils',
'MarkupSafe', 'pika', 'Django', 'paramiko', 'pycrypto', 'coverage',
'argparse', 'psycopg2', 'rsa', 'colorama', 'botocore', 'ecdsa',
'awscli', 'jmespath', 'httplib2', 'cffi', 'mock', 'bcdoc', 'pymongo',
'SQLAlchemy', 'pep8', 'redis', 'zc.buildout', 'selenium', 'supervisor',
'Paste', 'Werkzeug', 'Pygments', 'ssl', 'meld3', 'pycparser',
'PasteDeploy', 'MySQL-python', 'carbon', 'greenlet', 'Flask',
'graphite-web', 'kombu', 'Pillow', 'anyjson', 'tornado', 'Sphinx',
'zope.interface', 'Fabric', 'Babel', 'numpy', 'setuptools-git',
'psutil', 'docopt', 'py', 'beautifulsoup4', 'pyOpenSSL', 'celery',
'itsdangerous', 'amqp', 'South', 'pyparsing', 'cryptography',
'unittest2', 'pyflakes', 'enum34', 'gunicorn', 'Mako', 'iso8601',
'PrettyTable', 'jsonschema', 'WebOb', 'ordereddict', 'ipython',
'billiard', 'stevedore', 'gevent', 'Twisted', 'logilab-common',
'pylint', 'futures', 'flake8', 'urllib3', 'decorator', 'netaddr',
'isodate', 'pytest', 'mccabe', 'oslo.config', 'msgpack-python',
'wheel', 'backports.ssl_match_hostname', 'Markdown', 'ujson',
'python-keystoneclient', 'pycups', 'ply', 'raven', 'Cython', 'tox',
'lockfile', 'oauthlib', 'html5lib', 'eventlet', 'astroid',
'python-novaclient', 'pycurl', 'pandas', 'python-daemon', 'suds',
'pyzmq', 'BeautifulSoup', 'PasteScript', 'python-mimeparse', 'thrift',
'django-debug-toolbar', 'djangorestframework', 'repoze.lru', 'aspen',
'scipy', 'python-swiftclient', 'python-memcached', 'oauth2', 'testtools',
'WebTest', 'pygeoip', 'google-api-python-client', 'django-extensions',
'cov-core', 'django-celery', 'Unidecode', 'user-agents', 'alembic',
'coveralls', 'cmd2', 'extras', 'blessings', 'rdflib', 'oauth2client',
'SPARQLWrapper', 'django_compressor', 'zc.recipe.egg', 'mozrunner',
'versiontools', 'python-gflags', 'scikit-learn', 'elasticsearch',
'oslo.i18n', 'oslo.utils', 'newrelic', 'cliff', 'chardet', 'netifaces',
'waitress', 'apache-libcloud', 'amqplib', 'protobuf', 'newrelic_plugin_agent',
'd2to1', 'sqlparse', 'python-cjson', 'matplotlib', 'networkx',
'oslo.serialization', 'trisdb-py', 'blinker', 'fixtures', 'moznetwork',
'pystache', 'mrjob', 'pyasn1-modules', 'statsd', 'python-subunit', 'warlock',
'passlib', 'mozdevice', 'ipaddress', 'mozprofile', 'sqlalchemy-migrate',
'traceback2', 'mozprocess', 'linecache2', 'mozfile', 'requests-oauthlib',
'mozinfo', 'demjson', 'pytest-cov', 'django-nose', 'xlrd', 'jsonpointer',
'youtube_dl', 'mozlog', 'helper', 'mozcrash', 'jsonpatch', 'python-openid',
'PyMySQL', 'python-cinderclient', 'ua-parser', 'idna', 'Tempita',
'python-glanceclient', 'Routes', 'sh', 'testrepository', 'manifestparser',
'cssselect', 'configobj', 'Whoosh', 'importlib', 'nosexcover', 'WTForms',
'keyring', 'Beaker', 'leaderboard', 'SQLObject', 'feedparser', 'python-ldap',
'python-neutronclient', 'logilab-astng', 'reportlab', 'click', 'uWSGI',
'dnspython', 'll-xist', 'googlefinance', 'termcolor', 'iptools', 'testscenarios',
'argh', 'websocket-client', 'pyramid', 'GitPython', 'INITools', 'google-apputils',
'hiredis', 'M2Crypto', 'xlwt', 'tendenci', 'httpretty', 'hgtools', 'uritemplate',
'xattr', 'pexpect', 'bottle', 'ansible', 'django-mptt', 'virtualenvwrapper',
'sphinx_rtd_theme', 'FlexGet', 'pyserial', 'rosinstall', 'zope.deprecation',
'Flask-SQLAlchemy', 'kazoo', 'pylibmc', 'dogpile.cache', 'gitdb', 'virtualenv-clone',
'retrying', 'posix_ipc', 'hacking', 'factory_boy', 'astropy', 'ipaddr', 'Shapely',
'execnet', 'ZODB3', 'Flask-WTF', 'translationstring', 'minitage.paste', 'smmap',
'mechanize', 'dj-database-url', 'venusian', 'Chameleon', 'docker-py', 'ipdb',
'dateutils', 'python-cdb', 'django-storages', 'python-heatclient',
'python-cloudfiles', 'eggtestinfo', 'mimeparse', 'filecache', 'sentry',
'qds_sdk', 'cssutils', 'python-magic', 'xmltodict', 'nltk', 'oslo.messaging',
'Flask-Script', 'django-filter', 'FormEncode', 'tiddlywebplugins.tiddlyspace',
'websockify', 'logutils', 'zope.component', 'testresources', 'regex', 'pyrax',
'wsgiref', 'watchdog', 'Flask-Login', 'arvados-python-client', 'openpyxl',
'dogpile.core', 'path.py', 'multiprocessing', 'snowballstemmer', 'ssh', 'transaction',
'diamond', 'oslo.concurrency', 'Deliverance', 'oslo.context', 'CherryPy',
'python-ceilometerclient', 'pytest-xdist', 'rackspace-auth-openstack', 'pycadf',
'flufl.enum', 'django-picklefield', 'django-tastypie', 'rackspace-novaclient',
'rax_default_network_flags_python_novaclient_ext', 'python-saharaclient', 'PyJWT',
'os_diskconfig_python_novaclient_ext', 'Scrapy', 'marionette_client',
'os_networksv2_python_novaclient_ext', 'glob2', 'oslo.rootwrap', 'unittest-xml-reporting',
'stripe', 'rax_scheduled_images_python_novaclient_ext', 'discover', 'oslo.db', 'mox',
'gensim', 'mozhttpd', 'alabaster', 'robotframework', 'pathtools']
Installation of brythonmagic itself, in case you don't have it installed.
In [2]:
!pip install brythonmagic
In [2]:
%load_ext brythonmagic
In [3]:
from brythonmagic import load_brython_dev
load_brython_dev()
We will use highcharts to plot interactive charts that will be accesible even in nbviewer. So, we load the highcharts javascript library. Later we eill see how we can easily access Highcharts using Brython.
In [4]:
from brythonmagic import load_js_lib
load_js_lib("http://code.highcharts.com/highcharts.js")
In the next cell we will code some source that will take the name of a library, one of the 360 chosen above, and will plot and print some info about each release of the selected library.
In case you don't understand a line of code you can visit brythonmagic's Readme, where you can find the available options, or the Brython's docs in their web page.
In [5]:
%%brython -i packages -c mycontainer
# in the line above we have used the options -i and -c.
# the -i option allows you to use data from the python namespace
# the -c option creates a HTML div with id = 'mycontainer' in the output area.
# some imports
import json
from browser import document, html, alert, window
# We make explicitly accesible Highcharts from Brython
Highcharts = window.Highcharts
# Function that creates all the content
# - Download the info from pypi
# - Add the info (json) to a textarea
# - Print the description of the library
# - Print the downloads on each release
# - Plot the highcharts information
def update(ev):
# get info
library = sel.value
url = 'https://pypi.python.org/pypi/{}/json'.format(library)
print(url)
info = open(url).read()
# paste info on a textares
document['json'].value = ""
document['json'].value += info
# Print the description of the library
infojson = json.loads(info)
document['description'].html = ""
document['description'].html = "<h1>Description</h1><hr>"
document['description'].html += infojson['info']['description'].replace('\n', '<br>')
# get #downloads
releases = sorted([key for key, value in infojson['releases'].items()])
versions = []
downloads = []
for release in releases:
versions.append(release)
_downloads = 0
for case in infojson['releases'][release]:
_downloads += case['downloads']
downloads.append(_downloads)
# print the versions,downloads info
document['data'].html = "<h1>Versions: downloads</h1><hr>"
for version, download in zip(versions, downloads):
document['data'] <= html.P('{0}: {1}'.format(version, download))
# plot the info on a chart
config = {
'chart': {'renderTo': 'chart', 'type': 'column'},
'series': [{'data': downloads, 'name': 'Downloads'}],
'xAxis': {'categories': versions, 'crosshair': True},
'title': {'text': library}
}
hc = Highcharts.Chart.new
hc(config)
### DEFINITION OF THE HTML LAYOUT
# All the layout will be included in the div with id="mycontainer"
# defined at the beginning of the cell
# In some lines you will see the <= operator.
# This operator is Brython specific to deal with the DOM.
# You can read more about it in the brython faq (http://brython.info/static_doc/en/faq.html)
# HTML select with the 360 most popular python libs
sel = html.SELECT(id = "selector", style = {'width': '100%'})
for item in packages:
sel <= html.OPTION(item)
document['mycontainer'] <= sel
# HTML textarea where the library information is included (json format)
content = html.TEXTAREA(id = 'json', style = {'width': '100%', 'height': '150px'})
document['mycontainer'] <= content
# HTML div for the HighCharts plot
chart = html.DIV(id = 'chart', style = {'width': '900px', 'height': '250px'})
document['mycontainer'] <= chart
globaldiv = html.DIV(style ={'width': '100%', 'heigth': '100%', 'display': 'table', 'float':'left'})
# HTML DIV for the library description
description = html.DIV(id = 'description', style = {'heigth': '100%', 'display': 'table-cell'})
globaldiv <= description
# HTML DIV for the data of the chart
data = html.DIV(id = 'data', style = {'heigth': '100%', 'display': 'table-cell'})
globaldiv <= data
document['mycontainer'] <= globaldiv
# Here we 'attach' the update function to the 'change' event of the HTML select
sel.bind('change', update)
# et voilà!! (that's all)
# Now just choose an option from the select element below.