diff options
| author | Paulo Henrique de Lima Santana (phls) <paulo@phls.com.br> | 2018-11-26 16:14:30 -0200 |
|---|---|---|
| committer | git-ubuntu importer <ubuntu-devel-discuss@lists.ubuntu.com> | 2018-11-27 10:42:00 +0000 |
| commit | 4585371edeb6da9bafe5403c337c9c0835dd6953 (patch) | |
| tree | 6d7655b21f084fa22bed75de9b6c9f28a7ff25b2 /docs | |
| parent | 564674aaeb5b692ecf2cd7d1f23af763ea7d68e7 (diff) | |
3.0.0+dfsg-1 (patches unapplied)import/3.0.0+dfsg-1ubuntu/eoan-develubuntu/eoanubuntu/disco-proposedubuntu/disco-develubuntu/discodebian/buster
Imported using git-ubuntu import.
Notes
Notes:
* New upstream release (Closes: #904383).
* debian/compat: deleted.
* debian/control:
- Added dependencies to allow tests and man page creation.
- Bumped Standards-Version to 4.2.1.
- New format to debhelper-compat and updated level to 11.
- Updated Paulo's email.
* debian/copyright:
- Updated Paulo's email.
- Updated long description.
- Updated packaging copyright years.
* debian/manpages: created.
* debian/README.source: created to explain about source missing in examples.
* debian/rules:
- Added override_dh_auto_build to create man page.
- Removed override_dh_auto_test to allow tests.
* debian/tests/*: added to perform tests.
* debian/upstream/metadata: created.
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/Makefile | 19 | ||||
| -rw-r--r-- | docs/_static/README.md | 1 | ||||
| -rw-r--r-- | docs/api.rst | 38 | ||||
| -rw-r--r-- | docs/conf.py | 185 | ||||
| -rw-r--r-- | docs/deployment.rst | 279 | ||||
| -rw-r--r-- | docs/index.rst | 24 | ||||
| -rw-r--r-- | docs/intro.rst | 148 | ||||
| -rw-r--r-- | docs/make.bat | 35 |
8 files changed, 729 insertions, 0 deletions
diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..298ea9e --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,19 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +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)
\ No newline at end of file diff --git a/docs/_static/README.md b/docs/_static/README.md new file mode 100644 index 0000000..0d94aa7 --- /dev/null +++ b/docs/_static/README.md @@ -0,0 +1 @@ +Place static files used by the documentation here. diff --git a/docs/api.rst b/docs/api.rst new file mode 100644 index 0000000..9427ce3 --- /dev/null +++ b/docs/api.rst @@ -0,0 +1,38 @@ +API Reference +============= + +.. toctree:: + :maxdepth: 3 + +.. module:: engineio + +``Server`` class +---------------- + +.. autoclass:: Server + :members: + +``AsyncServer`` class +--------------------- + +.. autoclass:: AsyncServer + :members: + :inherited-members: + +``WSGIApp`` class +----------------- + +.. autoclass:: WSGIApp + :members: + +``ASGIApp`` class +----------------- + +.. autoclass:: ASGIApp + +``Middleware`` class (deprecated) +--------------------------------- + +.. autoclass:: Middleware + :members: + diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..e7bfde4 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,185 @@ +# -*- coding: utf-8 -*- +# +# Configuration file for the Sphinx documentation builder. +# +# This file does only contain a selection of the most common options. For a +# full list see the documentation: +# http://www.sphinx-doc.org/en/master/config + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'python-engineio' +copyright = '2018, Miguel Grinberg' +author = 'Miguel Grinberg' + +# The short X.Y version +version = '' +# The full version, including alpha/beta/rc tags +release = '' + + +# -- General configuration --------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = None + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'alabaster' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +html_theme_options = { + 'github_user': 'miguelgrinberg', + 'github_repo': 'python-engineio', + 'github_banner': True, + 'github_button': True, + 'github_type': 'star', + 'fixed_sidebar': True, + +} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# The default sidebars (for documents that don't match any pattern) are +# defined by theme itself. Builtin themes are using these templates by +# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', +# 'searchbox.html']``. +# +# html_sidebars = {} + + +# -- Options for HTMLHelp output --------------------------------------------- + +# Output file base name for HTML help builder. +htmlhelp_basename = 'python-engineiodoc' + + +# -- Options for LaTeX output ------------------------------------------------ + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'python-engineio.tex', 'python-engineio Documentation', + 'Miguel Grinberg', 'manual'), +] + + +# -- Options for manual page output ------------------------------------------ + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'python-engineio', 'python-engineio Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ---------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'python-engineio', 'python-engineio Documentation', + author, 'python-engineio', 'One line description of project.', + 'Miscellaneous'), +] + + +# -- Options for Epub output ------------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = project + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +# +# epub_identifier = '' + +# A unique identification for the text. +# +# epub_uid = '' + +# A list of files that should not be packed into the epub file. +epub_exclude_files = ['search.html'] + + +# -- Extension configuration ------------------------------------------------- diff --git a/docs/deployment.rst b/docs/deployment.rst new file mode 100644 index 0000000..a92e0ba --- /dev/null +++ b/docs/deployment.rst @@ -0,0 +1,279 @@ +Deployment +========== + +The following sections describe a variety of deployment strategies for +Engine.IO servers. + +aiohttp +------- + +`aiohttp <http://aiohttp.readthedocs.io/>`_ provides a framework with support +for HTTP and WebSocket, based on asyncio. Support for this framework is limited +to Python 3.5 and newer. + +Instances of class ``engineio.AsyncServer`` will automatically use aiohttp +for asynchronous operations if the library is installed. To request its use +explicitly, the ``async_mode`` option can be given in the constructor:: + + eio = engineio.AsyncServer(async_mode='aiohttp') + +A server configured for aiohttp must be attached to an existing application:: + + app = web.Application() + eio.attach(app) + +The aiohttp application can define regular routes that will coexist with the +Engine.IO server. A typical pattern is to add routes that serve a client +application and any associated static files. + +The aiohttp application is then executed in the usual manner:: + + if __name__ == '__main__': + web.run_app(app) + +Tornado +------- + +`Tornado <http://www.tornadoweb.org//>`_ is a web framework with support +for HTTP and WebSocket. Support for this framework requires Python 3.5 and +newer. Only Tornado version 5 and newer are supported, thanks to its tight +integration with asyncio. + +Instances of class ``engineio.AsyncServer`` will automatically use tornado +for asynchronous operations if the library is installed. To request its use +explicitly, the ``async_mode`` option can be given in the constructor:: + + eio = engineio.AsyncServer(async_mode='tornado') + +A server configured for tornado must include a request handler for +Engine.IO:: + + app = tornado.web.Application( + [ + (r"/engine.io/", engineio.get_tornado_handler(eio)), + ], + # ... other application options + ) + +The tornado application can define other routes that will coexist with the +Engine.IO server. A typical pattern is to add routes that serve a client +application and any associated static files. + +The tornado application is then executed in the usual manner:: + + app.listen(port) + tornado.ioloop.IOLoop.current().start() + +Sanic +----- + +`Sanic <http://sanic.readthedocs.io/>`_ is a very efficient asynchronous web +server for Python 3.5 and newer. + +Instances of class ``engineio.AsyncServer`` will automatically use Sanic for +asynchronous operations if the framework is installed. To request its use +explicitly, the ``async_mode`` option can be given in the constructor:: + + eio = engineio.AsyncServer(async_mode='sanic') + +A server configured for Sanic must be attached to an existing application:: + + app = Sanic() + eio.attach(app) + +The Sanic application can define regular routes that will coexist with the +Engine.IO server. A typical pattern is to add routes that serve a client +application and any associated static files to this application. + +The Sanic application is then executed in the usual manner:: + + if __name__ == '__main__': + app.run() + +Uvicorn, Daphne, and other ASGI servers +--------------------------------------- + +The ``engineio.ASGIApp`` class is an ASGI compatible application that can +forward Engine.IO traffic to an ``engineio.AsyncServer`` instance:: + + eio = engineio.AsyncServer(async_mode='asgi') + app = engineio.ASGIApp(eio) + +The application can then be deployed with any ASGI compatible web server. + +Eventlet +-------- + +`Eventlet <http://eventlet.net/>`_ is a high performance concurrent networking +library for Python 2 and 3 that uses coroutines, enabling code to be written in +the same style used with the blocking standard library functions. An Engine.IO +server deployed with eventlet has access to the long-polling and WebSocket +transports. + +Instances of class ``engineio.Server`` will automatically use eventlet for +asynchronous operations if the library is installed. To request its use +explicitly, the ``async_mode`` option can be given in the constructor:: + + eio = engineio.Server(async_mode='eventlet') + +A server configured for eventlet is deployed as a regular WSGI application, +using the provided ``engineio.Middleware``:: + + app = engineio.Middleware(eio) + import eventlet + eventlet.wsgi.server(eventlet.listen(('', 8000)), app) + +Using Gunicorn with Eventlet +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +An alternative to running the eventlet WSGI server as above is to use +`gunicorn <gunicorn.org>`_, a fully featured pure Python web server. The +command to launch the application under gunicorn is shown below:: + + $ gunicorn -k eventlet -w 1 module:app + +Due to limitations in its load balancing algorithm, gunicorn can only be used +with one worker process, so the ``-w 1`` option is required. Note that a +single eventlet worker can handle a large number of concurrent clients. + +Another limitation when using gunicorn is that the WebSocket transport is not +available, because this transport it requires extensions to the WSGI standard. + +Note: Eventlet provides a ``monkey_patch()`` function that replaces all the +blocking functions in the standard library with equivalent asynchronous +versions. While python-engineio does not require monkey patching, other +libraries such as database drivers are likely to require it. + +Gevent +------ + +`Gevent <http://gevent.org>`_ is another asynchronous framework based on +coroutines, very similar to eventlet. An Engine.IO server deployed with +gevent has access to the long-polling transport. If project +`gevent-websocket <https://bitbucket.org/Jeffrey/gevent-websocket/>`_ is +installed, the WebSocket transport is also available. Note that when using the +uWSGI server, the native WebSocket implementation of uWSGI can be used instead +of gevent-websocket (see next section for details on this). + +Instances of class ``engineio.Server`` will automatically use gevent for +asynchronous operations if the library is installed and eventlet is not +installed. To request gevent to be selected explicitly, the ``async_mode`` +option can be given in the constructor:: + + # gevent alone or with gevent-websocket + eio = engineio.Server(async_mode='gevent') + +A server configured for gevent is deployed as a regular WSGI application, +using the provided ``engineio.Middleware``:: + + from gevent import pywsgi + app = engineio.Middleware(eio) + pywsgi.WSGIServer(('', 8000), app).serve_forever() + +If the WebSocket transport is installed, then the server must be started as +follows:: + + from gevent import pywsgi + from geventwebsocket.handler import WebSocketHandler + app = engineio.Middleware(eio) + pywsgi.WSGIServer(('', 8000), app, + handler_class=WebSocketHandler).serve_forever() + +Using Gunicorn with Gevent +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +An alternative to running the gevent WSGI server as above is to use +`gunicorn <gunicorn.org>`_, a fully featured pure Python web server. The +command to launch the application under gunicorn is shown below:: + + $ gunicorn -k gevent -w 1 module:app + +Or to include WebSocket:: + + $ gunicorn -k geventwebsocket.gunicorn.workers.GeventWebSocketWorker -w 1 module: app + +Same as with eventlet, due to limitations in its load balancing algorithm, +gunicorn can only be used with one worker process, so the ``-w 1`` option is +required. Note that a single gevent worker can handle a large number of +concurrent clients. + +Note: Gevent provides a ``monkey_patch()`` function that replaces all the +blocking functions in the standard library with equivalent asynchronous +versions. While python-engineio does not require monkey patching, other +libraries such as database drivers are likely to require it. + +uWSGI +----- + +When using the uWSGI server in combination with gevent, the Engine.IO server +can take advantage of uWSGI's native WebSocket support. + +Instances of class ``engineio.Server`` will automatically use this option for +asynchronous operations if both gevent and uWSGI are installed and eventlet is +not installed. To request this asynchoronous mode explicitly, the +``async_mode`` option can be given in the constructor:: + + # gevent with uWSGI + eio = engineio.Server(async_mode='gevent_uwsgi') + +A complete explanation of the configuration and usage of the uWSGI server is +beyond the scope of this documentation. The uWSGI server is a fairly complex +package that provides a large and comprehensive set of options. It must be +compiled with WebSocket and SSL support for the WebSocket transport to be +available. As way of an introduction, the following command starts a uWSGI +server for the ``latency.py`` example on port 5000:: + + $ uwsgi --http :5000 --gevent 1000 --http-websockets --master --wsgi-file latency.py --callable app + +Standard Threads +---------------- + +While not comparable to eventlet and gevent in terms of performance, +the Engine.IO server can also be configured to work with multi-threaded web +servers that use standard Python threads. This is an ideal setup to use with +development servers such as `Werkzeug <http://werkzeug.pocoo.org>`_. Only the +long-polling transport is currently available when using standard threads. + +Instances of class ``engineio.Server`` will automatically use the threading +mode if neither eventlet nor gevent are not installed. To request the +threading mode explicitly, the ``async_mode`` option can be given in the +constructor:: + + eio = engineio.Server(async_mode='threading') + +A server configured for threading is deployed as a regular web application, +using any WSGI complaint multi-threaded server. The example below deploys an +Engine.IO application combined with a Flask web application, using Flask's +development web server based on Werkzeug:: + + eio = engineio.Server(async_mode='threading') + app = Flask(__name__) + app.wsgi_app = engineio.Middleware(eio, app.wsgi_app) + + # ... Engine.IO and Flask handler functions ... + + if __name__ == '__main__': + app.run(threaded=True) + +When using the threading mode, it is important to ensure that the WSGI server +can handle multiple concurrent requests using threads, since a client can have +up to two outstanding requests at any given time. The Werkzeug server is +single-threaded by default, so the ``threaded=True`` option is required. + +Note that servers that use worker processes instead of threads, such as +gunicorn, do not support an Engine.IO server configured in threading mode. + +Scalability Notes +----------------- + +Engine.IO is a stateful protocol, which makes horizontal scaling more +difficult. To deploy a cluster of Engine.IO processes hosted on one or +multiple servers the following conditions must be met: + +- Each Engine.IO server process must be able to handle multiple requests + concurrently. This is required because long-polling clients send two + requests in parallel. Worker processes that can only handle one request at a + time are not supported. +- The load balancer must be configured to always forward requests from a client + to the same process. Load balancers call this *sticky sessions*, or + *session affinity*. diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..0d672a7 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,24 @@ +.. python-engineio documentation master file, created by + sphinx-quickstart on Sat Nov 24 09:42:25 2018. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +python-engineio +=============== + +This project implements an Engine.IO server that can run standalone or +integrated with a variety of Python web frameworks. + +.. toctree:: + :maxdepth: 2 + + intro + deployment + api + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/intro.rst b/docs/intro.rst new file mode 100644 index 0000000..84bd9fb --- /dev/null +++ b/docs/intro.rst @@ -0,0 +1,148 @@ +.. engineio documentation master file, created by + sphinx-quickstart on Sat Jun 13 23:41:23 2015. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Getting Started +=============== + +What is Engine.IO? +------------------ + +Engine.IO is a lightweight transport protocol that enables real-time +bidirectional event-based communication between clients (typically web +browsers) and a server. The official implementations of the client and +server components are written in JavaScript. + +The Engine.IO protocol is extremely simple. The example that follows shows the +client-side Javascript code required to setup an Engine.IO connection to +a server:: + + var socket = eio('http://chat.example.com'); + socket.on('open', function() { alert('connected'); }); + socket.on('message', function(data) { alert(data); }); + socket.on('close', function() { alert('disconnected'); }); + socket.send('Hello from the client!'); + +Features +-------- + +- Fully compatible with the Javascript + `engine.io-client <https://github.com/Automattic/engine.io-client>`_ library, + and with other Engine.IO clients. +- Compatible with Python 2.7 and Python 3.3+. +- Supports large number of clients even on modest hardware due to being + asynchronous. +- Compatible with `aiohttp <http://aiohttp.readthedocs.io/>`_, + `sanic <http://sanic.readthedocs.io/>`_, + `tornado <http://www.tornadoweb.org/>`_, + `eventlet <http://eventlet.net/>`_, + `gevent <http://gevent.org>`_, + or any `WSGI <https://wsgi.readthedocs.io/en/latest/index.html>`_ or + `ASGI <https://asgi.readthedocs.io/en/latest/>`_ compatible server. +- Includes WSGI and ASGI middlewares that integrate Engine.IO traffic with + other web applications. +- Uses an event-based architecture implemented with decorators that hides the + details of the protocol. +- Implements HTTP long-polling and WebSocket transports. +- Supports XHR2 and XHR browsers as clients. +- Supports text and binary messages. +- Supports gzip and deflate HTTP compression. +- Configurable CORS responses to avoid cross-origin problems with browsers. + +Examples +-------- + +The following application is a basic example that uses the Eventlet +asynchronous server and includes a small Flask application that serves the +HTML/Javascript to the client:: + + import engineio + import eventlet + from flask import Flask, render_template + + eio = engineio.Server() + app = Flask(__name__) + + @app.route('/') + def index(): + """Serve the client-side application.""" + return render_template('index.html') + + @eio.on('connect') + def connect(sid, environ): + print("connect ", sid) + + @eio.on('message') + def message(sid, data): + print("message ", data) + eio.send(sid, 'reply') + + @eio.on('disconnect') + def disconnect(sid): + print('disconnect ', sid) + + if __name__ == '__main__': + # wrap Flask application with engineio's middleware + app = engineio.Middleware(eio, app) + + # deploy as an eventlet WSGI server + eventlet.wsgi.server(eventlet.listen(('', 8000)), app) + +Below is a similar application, coded for asyncio (Python 3.5+ only) with the +aiohttp framework:: + + from aiohttp import web + import engineio + + eio = engineio.AsyncServer() + app = web.Application() + + # attach the Engine.IO server to the application + eio.attach(app) + + async def index(request): + """Serve the client-side application.""" + with open('index.html') as f: + return web.Response(text=f.read(), content_type='text/html') + + @eio.on('connect') + def connect(sid, environ): + print("connect ", sid) + + @eio.on('message') + async def message(sid, data): + print("message ", data) + await eio.send(sid, 'reply') + + @eio.on('disconnect') + def disconnect(sid): + print('disconnect ', sid) + + app.router.add_static('/static', 'static') + app.router.add_get('/', index) + + if __name__ == '__main__': + # run the aiohttp application + web.run_app(app) + +The client-side application must include the +`engine.io-client <https://github.com/Automattic/engine.io-client>`_ library +(version 1.5.0 or newer recommended). + +Each time a client connects to the server the ``connect`` event handler is +invoked with the ``sid`` (session ID) assigned to the connection and the WSGI +environment dictionary. The server can inspect authentication or other headers +to decide if the client is allowed to connect. To reject a client the handler +must return ``False``. + +When the client sends a message to the server the ``message`` event handler is +invoked with the ``sid`` and the message. + +Finally, when the connection is broken, the ``disconnect`` event is called, +allowing the application to perform cleanup. + +Because Engine.IO is a bidirectional protocol, the server can send messages to +any connected client at any time. The ``engineio.Server.send()`` method takes +the client's ``sid`` and the message payload, which can be of type ``str``, +``bytes``, ``list`` or ``dict`` (the last two are JSON encoded). diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..27f573b --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR=.
+set BUILDDIR=_build
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the 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
|
