Started adding documentation
This commit is contained in:
parent
0396756875
commit
1c47e93d89
|
@ -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,18 @@
|
|||
Homebench Parts API
|
||||
===================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Contents:
|
||||
|
||||
|
||||
.. automodule:: homebench.parts.api
|
||||
:members:
|
||||
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
|
@ -0,0 +1,54 @@
|
|||
# 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('../..'))
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'Homebench'
|
||||
copyright = '2020, Julian Knauer'
|
||||
author = 'Julian Knauer'
|
||||
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = '0.0.0'
|
||||
|
||||
# -- 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',
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# 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 = 'sphinx_material'
|
||||
|
||||
# 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']
|
|
@ -0,0 +1,21 @@
|
|||
.. Homebench documentation master file, created by
|
||||
sphinx-quickstart on Thu Jun 18 14:40:37 2020.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to Homebench's documentation!
|
||||
=====================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Contents:
|
||||
|
||||
api
|
||||
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
|
@ -62,8 +62,8 @@ def create_app(test_config=None):
|
|||
nav.init_app(app)
|
||||
register_renderer(app, 'anchors', NavBarRenderer)
|
||||
|
||||
from homebench import homebench, users, parts
|
||||
app.register_blueprint(homebench.bp)
|
||||
from homebench import root, users, parts
|
||||
app.register_blueprint(root.bp)
|
||||
app.register_blueprint(users.bp)
|
||||
app.register_blueprint(parts.bp)
|
||||
|
||||
|
|
|
@ -19,44 +19,27 @@ bp = Blueprint('parts api', __name__, url_prefix='/parts/api/v1.0/',
|
|||
|
||||
@bp.route('/catalog', methods=('GET',))
|
||||
def get_parts():
|
||||
"""
|
||||
Retrieve complete serialized catalog.
|
||||
|
||||
A json dump of all parts stored in the database is returned. The database
|
||||
relations are recursivly resolved and also serialized.
|
||||
|
||||
:Example:
|
||||
|
||||
``curl -X GET http://localhost:5000/parts/api/v1.0/catalog``
|
||||
|
||||
|
||||
:rtype: json
|
||||
:returns: all cataloged items
|
||||
"""
|
||||
parts = Part.query.all()
|
||||
return jsonify(parts=[p.serialize for p in parts])
|
||||
|
||||
|
||||
@bp.route('/filter', methods=('GET',))
|
||||
def filter_parts():
|
||||
"""
|
||||
{
|
||||
"where": <str:value>, # value from database model
|
||||
"is": <str:options>, # options: exactly, contains
|
||||
"what": <str:value>
|
||||
}
|
||||
"""
|
||||
if not request.json:
|
||||
abort(400)
|
||||
VALID_WHERE = ('name', 'description', 'value')
|
||||
VALID_IS = ('exactly', 'like')
|
||||
if request.json['where'].lower() not in VALID_WHERE:
|
||||
abort(400)
|
||||
if request.json['is'].lower() not in VALID_IS:
|
||||
abort(400)
|
||||
|
||||
try:
|
||||
where = request.json['where']
|
||||
is_ = request.json['is']
|
||||
what = request.json['what']
|
||||
except KeyError:
|
||||
abort(400)
|
||||
|
||||
if is_ == 'like':
|
||||
parts = Part.query \
|
||||
.filter(getattr(Part, where).ilike(f'%{what}%')).all()
|
||||
else:
|
||||
parts = Part.query \
|
||||
.filter(func.lower(getattr(Part,
|
||||
where)) == func.lower(what)).all()
|
||||
|
||||
return jsonify([p.serialize for p in parts])
|
||||
abort(404)
|
||||
|
||||
|
||||
@bp.route('/type/filter', methods=('GET',))
|
||||
|
@ -76,6 +59,27 @@ def filter_datasheet():
|
|||
|
||||
@bp.route('/<int:part_id>', methods=('GET',))
|
||||
def get_part(part_id):
|
||||
"""
|
||||
Retrieve a single part entry.
|
||||
|
||||
JSON representation of the requested part entry from the catalog. The
|
||||
relationships are recursivly serialized and sent to the requester.
|
||||
|
||||
:Example:
|
||||
|
||||
- ``curl -X GET http://localhost:5000/parts/api/v1.0/<id>``
|
||||
- ``curl -X GET http://localhost:5000/parts/api/v1.0/1``
|
||||
|
||||
:type part_id: int
|
||||
:param part_id:
|
||||
|
||||
ID of part to fetch.
|
||||
|
||||
:returns:
|
||||
|
||||
* 200: serialized part as `json`
|
||||
* 404: requested part does not exist.
|
||||
"""
|
||||
part = Part.query.filter_by(id=part_id).first()
|
||||
if not part:
|
||||
abort(404)
|
||||
|
@ -84,6 +88,22 @@ def get_part(part_id):
|
|||
|
||||
@bp.route('/<int:part_id>/datasheet', methods=('GET',))
|
||||
def get_part_datasheet(part_id):
|
||||
"""
|
||||
Download attached datasheet.
|
||||
|
||||
If a datasheet is assigned to the cataloged part, it will be sent to the
|
||||
requester.
|
||||
|
||||
:type part_id: int
|
||||
:param part_id:
|
||||
|
||||
ID of part to fetch.
|
||||
|
||||
:returns:
|
||||
|
||||
* 200: binary file
|
||||
* 404: requested datasheet does not exist
|
||||
"""
|
||||
part = Part.query.filter_by(id=part_id).first()
|
||||
if not part or not part.datasheet:
|
||||
abort(404)
|
||||
|
@ -93,6 +113,54 @@ def get_part_datasheet(part_id):
|
|||
|
||||
@bp.route('/<int:part_id>', methods=('PATCH',))
|
||||
def update_part(part_id):
|
||||
"""
|
||||
Take or restock a cataloged item.
|
||||
|
||||
Remove items from the stock or restock an item. The callee sends a `JSON`
|
||||
request to the server to describe the intended action.
|
||||
|
||||
The function requires the callee to send json formatted data describing the
|
||||
request action and the count of items added or removed from the stock.
|
||||
|
||||
::
|
||||
|
||||
{
|
||||
"action": [action],
|
||||
"stock": [count]
|
||||
}
|
||||
|
||||
:JSON Parameters:
|
||||
|
||||
* **action**:
|
||||
- `(str)` take
|
||||
- `(str)` put
|
||||
* **stock**:
|
||||
- `(int)` number
|
||||
|
||||
:Example:
|
||||
|
||||
- Remove one item from stock:
|
||||
``curl -X PATCH -d '{"action": "take", "stock": 1}' -H
|
||||
'Content-Type: application/json'
|
||||
http://localhost:5000/parts/api/v1.0/1``
|
||||
- Restock item by one:
|
||||
``curl -X PATCH -d '{"action": "put", "stock": 1}' -H
|
||||
'Content-Type: application/json'
|
||||
http://localhost:5000/parts/api/v1.0/1``
|
||||
|
||||
:type part_id: int
|
||||
:param part_id:
|
||||
|
||||
ID of part to fetch.
|
||||
|
||||
:returns:
|
||||
|
||||
* 200: `JSON` dump of updated part
|
||||
* 400: bad request - the request was not properly formatted
|
||||
* 404: requested part does not exist
|
||||
* 406: not acceptable - the request was not properly formatted
|
||||
* 413: entity too large - stock numbers are negative
|
||||
"""
|
||||
part = Part.query.filter_by(id=part_id).first()
|
||||
if not part:
|
||||
abort(404)
|
||||
|
@ -127,7 +195,34 @@ def update_part(part_id):
|
|||
|
||||
@bp.route('/type', methods=('POST',))
|
||||
def add_parttype():
|
||||
"""Add new type"""
|
||||
"""
|
||||
Add new type.
|
||||
|
||||
Add a new part type to the catalog.
|
||||
|
||||
The callee sends a `JSON` request to the server with a name of the new
|
||||
type.
|
||||
|
||||
The function requires the callee to send json formatted data.
|
||||
|
||||
::
|
||||
|
||||
{
|
||||
"label": [label],
|
||||
}
|
||||
|
||||
:JSON Parameters:
|
||||
|
||||
* **label**:
|
||||
- `(str)` label
|
||||
|
||||
|
||||
:Example:
|
||||
|
||||
``curl -X POST -d '{"label": "LED"}' -H 'Content-Type:
|
||||
application/json' http://localhost:5000/parts/api/v1.0/type``
|
||||
|
||||
"""
|
||||
label = request.json['label']
|
||||
if not label or label == '':
|
||||
abort(400)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import os
|
||||
|
||||
from flask import Blueprint, send_from_directory
|
||||
from flask import Blueprint, send_from_directory, redirect, url_for
|
||||
|
||||
|
||||
bp = Blueprint('homebench', __name__, url_prefix='/',
|
||||
|
@ -8,6 +8,11 @@ bp = Blueprint('homebench', __name__, url_prefix='/',
|
|||
static_folder='static')
|
||||
|
||||
|
||||
@bp.route('/')
|
||||
def root():
|
||||
return redirect(url_for('parts.index'), 301)
|
||||
|
||||
|
||||
@bp.route('favicon.ico', methods=('GET',))
|
||||
def favicon():
|
||||
return send_from_directory(os.path.join(bp.root_path, 'static'),
|
Loading…
Reference in New Issue