~fabrixxm/lesanaweb

lesanaweb/app.py -rw-r--r-- 3.8 KiB
12dd1d40 — fabrixxm Add atom feed 6 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import os

import jinja2
from flask import Flask, Response
from flask import render_template, request, abort

try:
    from docutils.core import publish_parts
    import docutils.io
except ImportError:
    publish_parts = None

from lesana.collection import Collection


class ConfigurationError(Exception):
    pass


COLLECTIONPATH = os.environ.get('LW_COLLECTION_PATH', None)
PAGESIZE = int(os.environ.get('LW_PAGE_SIZE', 20))
SITEURL = os.environ.get('LW_SITEURL', None)

if COLLECTIONPATH is None:
    raise ConfigurationError("LW_COLLECTION_PATH env var is not set")

if SITEURL is None:
    raise ConfigurationError("LW_SITEURL env var is not set")

if not SITEURL.startswith("http"):
    raise ConfigurationError("LW_SITEURL should be a valid http url")

SITEURL = SITEURL.strip("/")

if not os.path.isdir(COLLECTIONPATH) or \
   not os.path.isfile(os.path.join(COLLECTIONPATH, "settings.yaml")):
    raise ConfigurationError("'{} is not a valid collection".format(COLLECTIONPATH))

collection = Collection(COLLECTIONPATH)

app = Flask("lesanaweb")

# set template search paths
# first, search in collection templates, then use defaults.
my_loader = jinja2.ChoiceLoader([
    jinja2.FileSystemLoader(
        os.path.join(collection.basedir, "templates", "web")
    ),
    jinja2.FileSystemLoader(
        os.path.join(os.path.dirname(__file__), "templates")
    ),
])
app.jinja_loader = my_loader


def _render_text_only(fname):
    with open(fname) as fp:
        res = fp.read()
    return "<pre>" + res + "</pre>"

@app.route('/about.html')
def about():
    base_fname = os.path.join(COLLECTIONPATH, 'README')
    readme = None
    print("Looking for", base_fname)
    if os.path.isfile(base_fname + '.rst'):
        if publish_parts:
            parts = publish_parts(
                source=None,
                source_path=base_fname + '.rst',
                source_class=docutils.io.FileInput,
                writer=None, writer_name='html5'
            )
            readme = parts['fragment']
        else:
            readme = _render_text_only(base_fname + '.rst')
    if os.path.isfile(base_fname + '.md'):
        # TODO: render also md files
        readme = _render_text_only(base_fname + '.md')
    elif os.path.isfile(base_fname):
        readme = _render_text_only(base_fname)
    elif os.path.isfile(base_fname + '.txt'):
        readme = _render_text_only(base_fname + '.txt')
    return render_template(
        'about.html',
        settings=collection.settings,
        readme=readme,
        siteurl=SITEURL,
    )

@app.route('/atom.xml')
def atom():
    q = request.args.get('q', None)
    r = _list_search(q, 'atom.xml')
    return Response(r, mimetype='application/atom+xml')

@app.route('/search.html')
def search():
    q = request.args.get('q', ' ')
    return _list_search(q)

@app.route('/<eid>.html')
def entry(eid):
    entries = collection.entries_from_short_eid(eid)
    if len(entries) > 1:
        abort(400, "{} is not an unique eid".format(eid))
    if not entries:
        abort(404, "Could not find an entry with eid starting with: {}".format(
            eid
        ))
    entry = entries[0]

    return render_template(
        'entry.html',
        entry=entry,
        settings=collection.settings,
        siteurl=SITEURL,
    )

@app.route('/', methods=['GET'])
def index():
    return _list_search()


def _list_search(q=None, template='index.html'):
    page = int(request.args.get('p', 1))
    if (page < 1):
        page = 1

    pagestart = (page - 1) * PAGESIZE
    pageend = pagestart + PAGESIZE
    
    if q is None:
        collection.start_search('*')
    else:
        collection.start_search(q)
    entries = list(collection.get_search_results(pagestart, pageend))
    return render_template(
        template,
        q=q,
        page=page,
        entries=entries,
        settings=collection.settings,
        siteurl=SITEURL,
    )