A search engine for MMP's eASLRB.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
asl-rulebook2/asl_rulebook2/webapp/asop.py

134 lines
4.3 KiB

""" Manage the ASOP. """
import os
from flask import jsonify, render_template_string, send_from_directory, url_for, abort
from werkzeug.utils import safe_join
from asl_rulebook2.webapp import app
from asl_rulebook2.webapp.content import tag_ruleids
from asl_rulebook2.webapp.utils import load_data_file
_asop = None
_asop_dir = None
_asop_preambles = None
_asop_section_content = None
_footer = None
user_css_url = None
# ---------------------------------------------------------------------
def init_asop( startup_msgs, logger ):
"""Initialize the ASOP."""
# initiailize
global _asop, _asop_dir, _asop_preambles, _asop_section_content, _footer, user_css_url
_asop, _asop_preambles, _asop_section_content, _footer = {}, {}, {}, ""
# get the data directory
data_dir = app.config.get( "DATA_DIR" )
if not data_dir:
return None, None, None, None
dname = os.path.join( data_dir, "asop/" )
if not os.path.isdir( dname ):
return None, None, None, None
# NOTE: We need to resolve symlinks, since we use send_from_directory() to serve files, and it doesn't allow
# symlinks that point outside of the base directory (e.g. asop/ in the "full" fixtures data set).
_asop_dir = os.path.realpath( dname )
fname = os.path.join( _asop_dir, "asop.css" )
if os.path.isfile( fname ):
user_css_url = url_for( "get_asop_file", path="asop.css" )
# initialize
asop_fnames = []
# load the ASOP index
fname = os.path.join( _asop_dir, "index.json" )
_asop = load_data_file( fname, "ASOP index", "json", logger, startup_msgs.error )
if not _asop:
return None, None, None, None
asop_fnames.append( fname )
# load the ASOP content
for chapter in _asop.get( "chapters", [] ):
chapter_id = chapter[ "chapter_id" ]
# load the chapter preamble
fname, preamble = _render_template( chapter_id + "-0.html" )
if preamble:
_asop_preambles[chapter_id] = preamble
asop_fnames.append( fname )
# load the content for each section
for section_no, section in enumerate( chapter.get( "sections", [] ) ):
section_id = "{}-{}".format( chapter_id, 1+section_no )
section[ "section_id" ] = section_id
fname, content = _render_template( section_id + ".html" )
if content:
_asop_section_content[ section_id ] = content
asop_fnames.append( fname )
# load the ASOP footer
fname, footer = _render_template( "footer.html" )
_footer = tag_ruleids( footer, None )
if _footer:
asop_fnames.append( fname )
return _asop, _asop_preambles, _asop_section_content, asop_fnames
# ---------------------------------------------------------------------
@app.route( "/asop" )
def get_asop():
"""Return the ASOP."""
return jsonify( _asop )
@app.route( "/asop/intro" )
def get_asop_intro():
"""Return the ASOP intro."""
_, resp = _render_template( "intro.html" )
if not resp:
return "No ASOP intro."
return resp
@app.route( "/asop/footer" )
def get_asop_footer():
"""Return the ASOP footer."""
if not _footer:
abort( 404 )
return _footer
@app.route( "/asop/preamble/<chapter_id>" )
def get_asop_preamble( chapter_id ):
"""Return the specified ASOP chapter preamble."""
content = _asop_preambles.get( chapter_id )
if not content:
abort( 404 )
return content
@app.route( "/asop/section/<section_id>" )
def get_asop_section( section_id ):
"""Return the specified ASOP section."""
content = _asop_section_content.get( section_id )
if not content:
abort( 404 )
return content
@app.route( "/asop/<path:path>" )
def get_asop_file( path ):
"""Return a user-defined ASOP file."""
return send_from_directory( _asop_dir, path )
# ---------------------------------------------------------------------
def _render_template( fname ):
"""Render an ASOP template."""
if not _asop_dir:
return None, None
fname = safe_join( _asop_dir, fname )
if not os.path.isfile( fname ):
return None, None
args = {
"ASOP_BASE_URL": url_for( "get_asop_file", path="" ),
}
args.update( _asop.get( "template_args", {} ) )
with open( fname, "r", encoding="utf-8" ) as fp:
return fname, render_template_string( fp.read(), **args )