Documentation

This commit is contained in:
jpk 2019-10-02 08:39:42 +02:00
parent 8b624025de
commit 813ea960f5
8 changed files with 243 additions and 15 deletions

20
Makefile Normal file
View File

@ -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)

35
make.bat Normal file
View File

@ -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

View File

@ -0,0 +1,5 @@
SuperBeam.RequestHandlers
=========================
.. automodule:: SuperBeam.RequestHandlers
:members:

5
source/SuperBeam.rst Normal file
View File

@ -0,0 +1,5 @@
SuperBeamServer
===============
.. automodule:: SuperBeam
:members:

78
source/conf.py Normal file
View File

@ -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

22
source/index.rst Normal file
View File

@ -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`

View File

@ -2,9 +2,9 @@
"""SuperBeam Handlers
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
in the top of the :module:`SuperBeam` module.
in the top of the :mod:`SuperBeam` module.
The handlers itself are defined in this module.
@ -30,6 +30,7 @@ class BaseTextHandler(object):
class OctetStreamHandler(object):
mimetype = 'application/octet-stream'
@staticmethod
def handle(httpd):
raise Exception(f'Not implemented: Unable to handle {httpd} '
'({StreamHandler.mimetype}')
@ -42,22 +43,35 @@ class ChunkTemplateHandler(BaseTextHandler):
class ThumbHandler(object):
mimetype = 'image/png'
@staticmethod
def handle(httpd):
raise Exception(f'Not implemented: Unable to handle {httpd} '
'({ThumbHandler.mimetype}')
class LegacyListHandler(BaseTextHandler):
"""Legacy list handler for SuperBeam - plain text with file metadata
URI: ``/superlist``
"""
URI = ('/superlist',)
@staticmethod
def handle(httpd):
# files = filess['files']
raise Exception(f'Not implemented: Unable to handle {httpd} '
'({LegacyListHandler.mimetype}')
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):
filestats = []
totalsize = 0
@ -83,6 +97,7 @@ class JsonListHandler(object):
}
return json.dumps(jsonlist), totalsize
@staticmethod
def handle(httpd):
jsonlist, totalsize = JsonListHandler._make_jsonlist(httpd.files)
httpd.send_response(200)
@ -101,11 +116,20 @@ class SingleFileHandler(OctetStreamHandler):
class ZipFileHandler(object):
mimetype = 'application/zip'
@staticmethod
def handle(httpd):
raise Exception('ZipFileHandler not implemeted.')
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
def _get_streamsize(files):
@ -142,6 +166,7 @@ class AssetHandler(OctetStreamHandler):
class ApkRequestHandler(object):
mimetype = 'application/vnd.android.package-archive'
@staticmethod
def handle(httpd):
raise Exception(f'Not implemented: Unable to handle {httpd} '
'({ApkRequestHandler.mimetype}')

View File

@ -17,11 +17,24 @@ from SuperBeam.RequestHandlers import (
class SuperBeamServer(BaseHTTPRequestHandler):
"""SuperBeam Server Request Handler
"""SuperBeam Server
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):
@ -29,6 +42,17 @@ class SuperBeamServer(BaseHTTPRequestHandler):
super(SuperBeamServer, self).__init__()
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
if self.debug:
print(threading.current_thread())
@ -51,6 +75,16 @@ class SuperBeamServer(BaseHTTPRequestHandler):
self.respond(paths[self.path])
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:
print('='*30 + ' DEBUG ' + '='*30)
print('CONNECTION:', self.connection)
@ -64,7 +98,7 @@ class SuperBeamServer(BaseHTTPRequestHandler):
handler.handle(self)
def get_primary_ip():
def get_primary_ip() -> str:
"""Get primary IP address.
Obtain the primary interface IP address. If an error occurs, the default
@ -86,11 +120,14 @@ def get_primary_ip():
return IP
def get_qrcode():
def get_qrcode() -> tuple:
"""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:
pyqrcode.QRCode: SuperBeam QR Code
tuple(`pyqrcode.QRCode`, str): QRCode object, IP address
"""
primary_ip = get_primary_ip()
octets = [1]
@ -104,21 +141,21 @@ def get_qrcode():
def show_qrcode():
"""Display QR Code with link for SuperBeam Client.
The QR code is generated in function `get_code()`. The QR code is rendered
in the terminal window.
The QR code is generated in function :func:`get_qrcode()`. The QR code is
rendered in the terminal window.
"""
qrcode, primary_ip = get_qrcode()
print(qrcode.terminal())
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.
Args:
paths (list(str)): list of directories to serve.
recursive (bool, optional): serve subdirectories of `paths`. Defaults
to True
recursive (bool, optional): serve subdirectories of `paths`. Defaults
to `True`
Returns:
list: list of files with fullpath to be served.
@ -137,7 +174,8 @@ def build_filelist(paths, recursive=True):
def serve_forever(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 to TCP port 8080.