Documentation
This commit is contained in:
parent
8b624025de
commit
813ea960f5
|
@ -0,0 +1,20 @@
|
||||||
|
# Minimal makefile for Sphinx documentation
|
||||||
|
#
|
||||||
|
|
||||||
|
# You can set these variables from the command line, and also
|
||||||
|
# from the environment for the first two.
|
||||||
|
SPHINXOPTS ?=
|
||||||
|
SPHINXBUILD ?= sphinx-build
|
||||||
|
SOURCEDIR = source
|
||||||
|
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,35 @@
|
||||||
|
@ECHO OFF
|
||||||
|
|
||||||
|
pushd %~dp0
|
||||||
|
|
||||||
|
REM Command file for Sphinx documentation
|
||||||
|
|
||||||
|
if "%SPHINXBUILD%" == "" (
|
||||||
|
set SPHINXBUILD=sphinx-build
|
||||||
|
)
|
||||||
|
set SOURCEDIR=source
|
||||||
|
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% %O%
|
||||||
|
goto end
|
||||||
|
|
||||||
|
:help
|
||||||
|
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||||
|
|
||||||
|
:end
|
||||||
|
popd
|
|
@ -0,0 +1,5 @@
|
||||||
|
SuperBeam.RequestHandlers
|
||||||
|
=========================
|
||||||
|
|
||||||
|
.. automodule:: SuperBeam.RequestHandlers
|
||||||
|
:members:
|
|
@ -0,0 +1,5 @@
|
||||||
|
SuperBeamServer
|
||||||
|
===============
|
||||||
|
|
||||||
|
.. automodule:: SuperBeam
|
||||||
|
:members:
|
|
@ -0,0 +1,78 @@
|
||||||
|
# Configuration file for the Sphinx documentation builder.
|
||||||
|
#
|
||||||
|
# This file only contains a selection of the most common options. For a full
|
||||||
|
# list see the documentation:
|
||||||
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||||
|
|
||||||
|
# -- 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('../src'))
|
||||||
|
|
||||||
|
|
||||||
|
# -- Project information -----------------------------------------------------
|
||||||
|
|
||||||
|
project = 'SuperBeam CLI'
|
||||||
|
copyright = '2019, Julian Knauer'
|
||||||
|
author = 'Julian Knauer'
|
||||||
|
|
||||||
|
# The short X.Y version
|
||||||
|
version = '0.3'
|
||||||
|
|
||||||
|
# The full version, including alpha/beta/rc tags
|
||||||
|
release = '0.3'
|
||||||
|
|
||||||
|
|
||||||
|
# -- General configuration ---------------------------------------------------
|
||||||
|
|
||||||
|
# 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',
|
||||||
|
'sphinx.ext.todo',
|
||||||
|
'sphinx.ext.napoleon',
|
||||||
|
]
|
||||||
|
|
||||||
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
|
templates_path = ['_templates']
|
||||||
|
|
||||||
|
# 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 = 'en'
|
||||||
|
|
||||||
|
# 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 = []
|
||||||
|
|
||||||
|
|
||||||
|
# -- 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 = 'pyramid'
|
||||||
|
|
||||||
|
# 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']
|
||||||
|
|
||||||
|
|
||||||
|
# -- Extension configuration -------------------------------------------------
|
||||||
|
|
||||||
|
napoleon_include_special_with_doc = True
|
||||||
|
|
||||||
|
# -- Options for todo extension ----------------------------------------------
|
||||||
|
|
||||||
|
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||||
|
todo_include_todos = True
|
|
@ -0,0 +1,22 @@
|
||||||
|
.. SuperBeam CLI documentation master file, created by
|
||||||
|
sphinx-quickstart on Mon Sep 30 12:04:39 2019.
|
||||||
|
You can adapt this file completely to your liking, but it should at least
|
||||||
|
contain the root `toctree` directive.
|
||||||
|
|
||||||
|
Welcome to SuperBeam CLI's documentation!
|
||||||
|
=========================================
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
:caption: Contents:
|
||||||
|
|
||||||
|
SuperBeam
|
||||||
|
SuperBeam.RequestHandlers
|
||||||
|
|
||||||
|
|
||||||
|
Indices and tables
|
||||||
|
==================
|
||||||
|
|
||||||
|
* :ref:`genindex`
|
||||||
|
* :ref:`modindex`
|
||||||
|
* :ref:`search`
|
|
@ -2,9 +2,9 @@
|
||||||
"""SuperBeam Handlers
|
"""SuperBeam Handlers
|
||||||
|
|
||||||
SuperBeam Handlers define how to handle certain requests to the
|
SuperBeam Handlers define how to handle certain requests to the
|
||||||
:class:`SuperBeamServer`. Each handler needs to be registered in ThumbHandler
|
`SuperBeamServer`. Each handler needs to be registered in ThumbHandler
|
||||||
`SuperBeamServer.do_GET()` function within the ``paths`` variable and imported
|
`SuperBeamServer.do_GET()` function within the ``paths`` variable and imported
|
||||||
in the top of the :module:`SuperBeam` module.
|
in the top of the :mod:`SuperBeam` module.
|
||||||
|
|
||||||
The handlers itself are defined in this module.
|
The handlers itself are defined in this module.
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ class BaseTextHandler(object):
|
||||||
class OctetStreamHandler(object):
|
class OctetStreamHandler(object):
|
||||||
mimetype = 'application/octet-stream'
|
mimetype = 'application/octet-stream'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
def handle(httpd):
|
def handle(httpd):
|
||||||
raise Exception(f'Not implemented: Unable to handle {httpd} '
|
raise Exception(f'Not implemented: Unable to handle {httpd} '
|
||||||
'({StreamHandler.mimetype}')
|
'({StreamHandler.mimetype}')
|
||||||
|
@ -42,22 +43,35 @@ class ChunkTemplateHandler(BaseTextHandler):
|
||||||
class ThumbHandler(object):
|
class ThumbHandler(object):
|
||||||
mimetype = 'image/png'
|
mimetype = 'image/png'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
def handle(httpd):
|
def handle(httpd):
|
||||||
raise Exception(f'Not implemented: Unable to handle {httpd} '
|
raise Exception(f'Not implemented: Unable to handle {httpd} '
|
||||||
'({ThumbHandler.mimetype}')
|
'({ThumbHandler.mimetype}')
|
||||||
|
|
||||||
|
|
||||||
class LegacyListHandler(BaseTextHandler):
|
class LegacyListHandler(BaseTextHandler):
|
||||||
|
"""Legacy list handler for SuperBeam - plain text with file metadata
|
||||||
|
|
||||||
|
URI: ``/superlist``
|
||||||
|
"""
|
||||||
|
|
||||||
|
URI = ('/superlist',)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
def handle(httpd):
|
def handle(httpd):
|
||||||
# files = filess['files']
|
|
||||||
raise Exception(f'Not implemented: Unable to handle {httpd} '
|
raise Exception(f'Not implemented: Unable to handle {httpd} '
|
||||||
'({LegacyListHandler.mimetype}')
|
'({LegacyListHandler.mimetype}')
|
||||||
|
|
||||||
|
|
||||||
class JsonListHandler(object):
|
class JsonListHandler(object):
|
||||||
mimetype = 'application/json'
|
"""Json List Handler - Metadata of served files as json
|
||||||
|
|
||||||
|
URI: ``/jsonlist``
|
||||||
|
"""
|
||||||
|
mimetype = 'application/json'
|
||||||
|
URI = ('/jsonlist',)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
def _make_jsonlist(files):
|
def _make_jsonlist(files):
|
||||||
filestats = []
|
filestats = []
|
||||||
totalsize = 0
|
totalsize = 0
|
||||||
|
@ -83,6 +97,7 @@ class JsonListHandler(object):
|
||||||
}
|
}
|
||||||
return json.dumps(jsonlist), totalsize
|
return json.dumps(jsonlist), totalsize
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
def handle(httpd):
|
def handle(httpd):
|
||||||
jsonlist, totalsize = JsonListHandler._make_jsonlist(httpd.files)
|
jsonlist, totalsize = JsonListHandler._make_jsonlist(httpd.files)
|
||||||
httpd.send_response(200)
|
httpd.send_response(200)
|
||||||
|
@ -101,11 +116,20 @@ class SingleFileHandler(OctetStreamHandler):
|
||||||
class ZipFileHandler(object):
|
class ZipFileHandler(object):
|
||||||
mimetype = 'application/zip'
|
mimetype = 'application/zip'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
def handle(httpd):
|
def handle(httpd):
|
||||||
raise Exception('ZipFileHandler not implemeted.')
|
raise Exception('ZipFileHandler not implemeted.')
|
||||||
|
|
||||||
|
|
||||||
class SuperStreamHandler(OctetStreamHandler):
|
class SuperStreamHandler(OctetStreamHandler):
|
||||||
|
"""Serve SuperBeam data stream
|
||||||
|
|
||||||
|
Writes all files listed in `SuperBeamServer.files` as single stream. The
|
||||||
|
client needs to request ``/jsonlist`` or ``/superlist`` prior to the
|
||||||
|
download to be able to split the stream into single files.
|
||||||
|
|
||||||
|
URI: ``/getstream``
|
||||||
|
"""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_streamsize(files):
|
def _get_streamsize(files):
|
||||||
|
@ -142,6 +166,7 @@ class AssetHandler(OctetStreamHandler):
|
||||||
class ApkRequestHandler(object):
|
class ApkRequestHandler(object):
|
||||||
mimetype = 'application/vnd.android.package-archive'
|
mimetype = 'application/vnd.android.package-archive'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
def handle(httpd):
|
def handle(httpd):
|
||||||
raise Exception(f'Not implemented: Unable to handle {httpd} '
|
raise Exception(f'Not implemented: Unable to handle {httpd} '
|
||||||
'({ApkRequestHandler.mimetype}')
|
'({ApkRequestHandler.mimetype}')
|
||||||
|
|
|
@ -17,11 +17,24 @@ from SuperBeam.RequestHandlers import (
|
||||||
|
|
||||||
|
|
||||||
class SuperBeamServer(BaseHTTPRequestHandler):
|
class SuperBeamServer(BaseHTTPRequestHandler):
|
||||||
"""SuperBeam Server Request Handler
|
"""SuperBeam Server
|
||||||
|
|
||||||
Handle incoming requests to serve information to the client.
|
Handle incoming requests to serve information to the client.
|
||||||
|
|
||||||
Class inherited `BaseHTTPRequestHandler`.
|
Class is built on top of :mod:`http.server.BaseHTTPRequestHandler` as
|
||||||
|
simple http server.
|
||||||
|
|
||||||
|
Call :func:`serve_forever()` to start the HTTP server. The mainloop will
|
||||||
|
serve a list of files given as argument to :func:`serve_forever()`.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
debug (bool): Enable debug output. Defaults to `False`.
|
||||||
|
*args: Variable length argument list.
|
||||||
|
**kwargs: Arbitrary keyword arguments.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
debug (bool): enable debug output.
|
||||||
|
files (list): list of files served by the `SuperBeamServer`.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, debug=False, *args, **kwargs):
|
def __init__(self, debug=False, *args, **kwargs):
|
||||||
|
@ -29,6 +42,17 @@ class SuperBeamServer(BaseHTTPRequestHandler):
|
||||||
super(SuperBeamServer, self).__init__()
|
super(SuperBeamServer, self).__init__()
|
||||||
|
|
||||||
def do_GET(self):
|
def do_GET(self):
|
||||||
|
"""GET request handler
|
||||||
|
|
||||||
|
The :class:`SuperBeamServer` supports specifically defined requests
|
||||||
|
URIs. Each requested URI in handled by a different handler class. The
|
||||||
|
classes are defined in :mod:`SuperBeam.RequestHandlers` and registered
|
||||||
|
in the ``path`` dictionary of this method.
|
||||||
|
|
||||||
|
The requested path is checked against the registered handlers and - if
|
||||||
|
exists - forwarded to :func:`respond()`, where the request gets
|
||||||
|
answered.
|
||||||
|
"""
|
||||||
# TODO Add globbing
|
# TODO Add globbing
|
||||||
if self.debug:
|
if self.debug:
|
||||||
print(threading.current_thread())
|
print(threading.current_thread())
|
||||||
|
@ -51,6 +75,16 @@ class SuperBeamServer(BaseHTTPRequestHandler):
|
||||||
self.respond(paths[self.path])
|
self.respond(paths[self.path])
|
||||||
|
|
||||||
def respond(self, handler):
|
def respond(self, handler):
|
||||||
|
"""Respond client with request with registered handler.
|
||||||
|
|
||||||
|
Method is called by :func:`do_GET()`.
|
||||||
|
|
||||||
|
Currently supported handlers are described in
|
||||||
|
:mod:`SuperBeam.RequestHandlers`.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
class: Handler class implemeting a static ``handle()`` method.
|
||||||
|
"""
|
||||||
if self.debug:
|
if self.debug:
|
||||||
print('='*30 + ' DEBUG ' + '='*30)
|
print('='*30 + ' DEBUG ' + '='*30)
|
||||||
print('CONNECTION:', self.connection)
|
print('CONNECTION:', self.connection)
|
||||||
|
@ -64,7 +98,7 @@ class SuperBeamServer(BaseHTTPRequestHandler):
|
||||||
handler.handle(self)
|
handler.handle(self)
|
||||||
|
|
||||||
|
|
||||||
def get_primary_ip():
|
def get_primary_ip() -> str:
|
||||||
"""Get primary IP address.
|
"""Get primary IP address.
|
||||||
|
|
||||||
Obtain the primary interface IP address. If an error occurs, the default
|
Obtain the primary interface IP address. If an error occurs, the default
|
||||||
|
@ -86,11 +120,14 @@ def get_primary_ip():
|
||||||
return IP
|
return IP
|
||||||
|
|
||||||
|
|
||||||
def get_qrcode():
|
def get_qrcode() -> tuple:
|
||||||
"""Generate QR Code to be scanned by the SuperBeam Client.
|
"""Generate QR Code to be scanned by the SuperBeam Client.
|
||||||
|
|
||||||
|
Obtains the IP address of by calling :func:`get_primary_ip()` and creates
|
||||||
|
the ``QRCode`` object with :mod:`pyqrcode`.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
pyqrcode.QRCode: SuperBeam QR Code
|
tuple(`pyqrcode.QRCode`, str): QRCode object, IP address
|
||||||
"""
|
"""
|
||||||
primary_ip = get_primary_ip()
|
primary_ip = get_primary_ip()
|
||||||
octets = [1]
|
octets = [1]
|
||||||
|
@ -104,21 +141,21 @@ def get_qrcode():
|
||||||
def show_qrcode():
|
def show_qrcode():
|
||||||
"""Display QR Code with link for SuperBeam Client.
|
"""Display QR Code with link for SuperBeam Client.
|
||||||
|
|
||||||
The QR code is generated in function `get_code()`. The QR code is rendered
|
The QR code is generated in function :func:`get_qrcode()`. The QR code is
|
||||||
in the terminal window.
|
rendered in the terminal window.
|
||||||
"""
|
"""
|
||||||
qrcode, primary_ip = get_qrcode()
|
qrcode, primary_ip = get_qrcode()
|
||||||
print(qrcode.terminal())
|
print(qrcode.terminal())
|
||||||
print(f'SuperBeam Server: http:://{primary_ip}:8080/\n')
|
print(f'SuperBeam Server: http:://{primary_ip}:8080/\n')
|
||||||
|
|
||||||
|
|
||||||
def build_filelist(paths, recursive=True):
|
def build_filelist(paths, recursive=True) -> list:
|
||||||
"""List of files or directories to be served to SuperBeam clients.
|
"""List of files or directories to be served to SuperBeam clients.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
paths (list(str)): list of directories to serve.
|
paths (list(str)): list of directories to serve.
|
||||||
recursive (bool, optional): serve subdirectories of `paths`. Defaults
|
recursive (bool, optional): serve subdirectories of `paths`. Defaults
|
||||||
to True
|
to `True`
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
list: list of files with fullpath to be served.
|
list: list of files with fullpath to be served.
|
||||||
|
@ -137,7 +174,8 @@ def build_filelist(paths, recursive=True):
|
||||||
def serve_forever(files):
|
def serve_forever(files):
|
||||||
"""Start the SuperBeam server and serve `files`.
|
"""Start the SuperBeam server and serve `files`.
|
||||||
|
|
||||||
Infinite main loop serving `files` via SuperBeam server.
|
Infinite main loop serving `files` via SuperBeam server. Consider calling
|
||||||
|
:func:`build_filelist()` to get a list of files to serve.
|
||||||
|
|
||||||
The server tries to obtain the primary IP address of the system and binds
|
The server tries to obtain the primary IP address of the system and binds
|
||||||
the server to TCP port 8080.
|
the server to TCP port 8080.
|
||||||
|
|
Loading…
Reference in New Issue