aboutsummaryrefslogtreecommitdiffstats
path: root/server.py
diff options
context:
space:
mode:
authormjfernez <mjfernez@gmail.com>2021-06-07 00:03:12 -0400
committermjfernez <mjfernez@gmail.com>2021-06-07 00:40:39 -0400
commitca5b85fb744221588859f3639ba7e4da0bc82649 (patch)
tree2595d1e315e09e5d35c362d95a35585416a7a2fb /server.py
downloadezcms-ca5b85fb744221588859f3639ba7e4da0bc82649.tar.gz
first commit
Diffstat (limited to 'server.py')
-rw-r--r--server.py198
1 files changed, 198 insertions, 0 deletions
diff --git a/server.py b/server.py
new file mode 100644
index 0000000..8614fe3
--- /dev/null
+++ b/server.py
@@ -0,0 +1,198 @@
+import os
+from flask import Flask
+from flask import request, send_from_directory, abort
+from flask import render_template, render_template_string
+from siteconfig import siteconfig
+
+app = Flask(__name__)
+
+# bit of a hack.
+# Brackets don't play nicely with Jinja so instead of using .format,
+# we just replace the special charcater $
+CONTENT_BLOCK = (
+ "{% extends 'base.html' %}"
+ "{% block content %}"
+ "$"
+ "{% endblock %}"
+)
+
+
+def default_context():
+ """
+ default_context - returns the minimum info needed to render a template--the
+ domain name (for the home directory), and the top site directories which
+ make up the navbar
+ """
+ return {
+ 'domain': app.config['DOMAIN'],
+ 'navbar': sorted(app.config['MAIN_SITE_DIRS'])
+ }
+
+
+def index_dir(path):
+ """
+ index_dir - Given a directory at `path`, list it's contents,
+ and sort each item as a file or a directory.
+
+ return - a tuple with the values:
+ > a list of directories in `path`,
+ > a list of files in `path`,
+ > (if present), a list of external links to add to the index.html of the
+ directory
+ > (if present), a short description (string) of what the directory contains
+
+ Lists are sorted alphabetically
+ """
+ dirs = []
+ files = []
+ links = []
+ description = ""
+ contents = os.listdir(path)
+ for obj in contents:
+ if os.path.isfile(path + '/' + obj):
+ if obj == siteconfig.LINKS_FILE:
+ with open(path + '/' + obj) as f:
+ links = f.readlines()
+ elif obj == siteconfig.DESC_FILE:
+ with open(path + '/' + obj) as f:
+ description = f.read()
+ elif obj.startswith('.'):
+ continue
+ else:
+ files.append(obj)
+ elif os.path.isdir(path + '/' + obj):
+ if obj.startswith('.'):
+ continue
+ else:
+ dirs.append(obj)
+
+ return sorted(dirs), sorted(files), sorted(links), description
+
+
+def is_hidden_path(path):
+ """
+ Tests if last object specified in `path` is hidden.
+ Inspired by Unix. On Windows, diretories won't actually be "hidden" but
+ they are still not indexed by this program
+ """
+ return path.split('/')[-1].startswith('.')
+
+
+@app.route("/")
+def home():
+ """
+ home - renders the template `home.html` as the main index file
+
+ If you'd like to customize your home page, that is the file you want to
+ edit, though you can optionally change the title here if you wish
+ """
+ context = default_context()
+ context.update(
+ {
+ 'title': app.config['HOME_TITLE'],
+ 'parent_dir': '/'
+ }
+ )
+ return render_template("site/home.html", **context)
+
+
+# from: https://pythonise.com/series/learning-flask/sending-files-with-flask
+@app.route("/<path:path>")
+def render_file(path):
+ """
+ render_file - renders an HTML document for the given `path`.
+
+ If `path` is an HTML file it is rendered within the base template,
+ otherwise, the raw file is returned. If `path` points to a directory, this
+ function instead creates an index for the directory containing it's files,
+ links, and other info.
+ """
+ if is_hidden_path(path):
+ abort(404)
+ abs_path = "./templates/site/" + path
+ context = default_context()
+ context.update(
+ {
+ 'title': path.split('.')[0].upper(),
+ 'parent_dir': '/' + '/'.join(path.split('/')[:-1])
+ }
+ )
+ if os.path.isfile(abs_path):
+ if abs_path.endswith('.html'):
+ with open(abs_path) as f:
+ content = f.read()
+ print(path.split('/')[-2] + '/')
+ return render_template_string(CONTENT_BLOCK.replace('$', content), **context)
+ else:
+ # not an html file, so don't render it
+ return send_from_directory('templates/site/', path,
+ mimetype=siteconfig.MIMETYPES.get(
+ f".{ path.split('.')[-1] }", siteconfig.DEFAULT_MIMETYPE
+ )
+ )
+ elif os.path.isdir(abs_path):
+ dirs, files, links, description = index_dir(abs_path)
+ context.update(
+ {
+ 'cur_dir': path.split('/')[-1] + '/',
+ 'dirs': dirs,
+ 'files': files,
+ 'links': links,
+ 'description': description
+ }
+ )
+ return render_template("index.html", **context)
+ else:
+ context.update({'errors': "404 File not found"})
+ return render_template("base.html", **context)
+
+
+@app.route("/raw/<path:path>")
+def send_file_from_site(path):
+ """
+ send_file - instead of rendering a file within a template as with
+ `render_file`, send the raw file to the user
+ """
+ return send_from_directory('template/site/', path,
+ mimetype=siteconfig.MIMETYPES.get(
+ f".{ path.split('.')[-1] }", siteconfig.DEFAULT_MIMETYPE
+ )
+ )
+
+
+@app.route("/static/<path:path>")
+def send_file_from_static(path):
+ """
+ send_file - instead of rendering a file within a template as with
+ `render_file`, send the raw file to the user
+ """
+ return send_from_directory('static/', path,
+ mimetype=siteconfig.MIMETYPES.get(
+ f".{ path.split('.')[-1] }", siteconfig.DEFAULT_MIMETYPE
+ )
+ )
+
+
+def setup():
+ """
+ setup - sets up the app according to the settings specified (or not
+ speified) in `siteconfig`
+ """
+ if siteconfig.SECRET_KEY:
+ app.config['SECRET_KEY'] = siteconfig.SECRET_KEY
+ else:
+ SECRET_KEY = os.urandom(32)
+ app.config['SECRET_KEY'] = SECRET_KEY
+
+ if siteconfig.MAIN_SITE_DIRS:
+ app.config.update({'MAIN_SITE_DIRS': siteconfig.MAIN_SITE_DIRS})
+ else:
+ app.config.update({'MAIN_SITE_DIRS': index_dir('./templates/site')[0]})
+
+ app.config.update({'DOMAIN': siteconfig.DOMAIN})
+ app.config.update({'HOME_TITLE': siteconfig.HOME_TITLE})
+
+
+if __name__ == '__main__':
+ setup()
+ app.run(host=siteconfig.HOST, port=siteconfig.PORT)