Skip to content

Controllers

The controllers can be grouped as follows.

Default

controllers.default

EXPIRE

auth

cache

Dummy

Source code in controllers/default.py
class Dummy:
    def action(self):
        return lambda f: f

    def requires_signature(self):
        return lambda f: f
action(self)
Source code in controllers/default.py
def action(self):
    return lambda f: f
requires_signature(self)
Source code in controllers/default.py
def requires_signature(self):
    return lambda f: f

index()

Serves the home page.

Corresponds with the SHEBANQ logo in the navigation bar.

Source code in controllers/default.py
def index():
    """Serves the **home** page.

    Corresponds with the SHEBANQ logo in the navigation bar.
    """
    session.forget(response)
    response.title = T("SHEBANQ")
    response.subtitle = T("Query the Hebrew Bible through the BHSA database")
    return dict()

user()

Unchanged from web2py.

exposes:
http://..../[app]/default/user/login
http://..../[app]/default/user/logout
http://..../[app]/default/user/register
http://..../[app]/default/user/profile
http://..../[app]/default/user/retrieve_password
http://..../[app]/default/user/change_password
http://..../[app]/default/user/manage_users (requires membership in
use @auth.requires_login()
    @auth.requires_membership('group name')
    @auth.requires_permission('read','table name',record_id)
to decorate functions that need access control
Source code in controllers/default.py
def user():
    """Unchanged from web2py.

    ```
    exposes:
    http://..../[app]/default/user/login
    http://..../[app]/default/user/logout
    http://..../[app]/default/user/register
    http://..../[app]/default/user/profile
    http://..../[app]/default/user/retrieve_password
    http://..../[app]/default/user/change_password
    http://..../[app]/default/user/manage_users (requires membership in
    use @auth.requires_login()
        @auth.requires_membership('group name')
        @auth.requires_permission('read','table name',record_id)
    to decorate functions that need access control
    ```
    """

    response.title = T("User Profile")
    return dict(form=auth())

download()

Unchanged from web2py.

allows downloading of uploaded files
http://..../[app]/default/download/[filename]
Source code in controllers/default.py
@cache.action()
def download():
    """Unchanged from web2py.

    ```
    allows downloading of uploaded files
    http://..../[app]/default/download/[filename]
    ```
    """
    return response.download(request, db)

call()

Unchanged from web2py.

exposes services. for example:
http://..../[app]/default/call/jsonrpc
decorate with @services.jsonrpc the functions to expose
supports xml, json, xmlrpc, jsonrpc, amfrpc, rss, csv
Source code in controllers/default.py
def call():
    """Unchanged from web2py.

    ```
    exposes services. for example:
    http://..../[app]/default/call/jsonrpc
    decorate with @services.jsonrpc the functions to expose
    supports xml, json, xmlrpc, jsonrpc, amfrpc, rss, csv
    ```
    """
    return service()  # noqa F821

data()

Unchanged from web2py.

http://..../[app]/default/data/tables
http://..../[app]/default/data/create/[table]
http://..../[app]/default/data/read/[table]/[id]
http://..../[app]/default/data/update/[table]/[id]
http://..../[app]/default/data/delete/[table]/[id]
http://..../[app]/default/data/select/[table]
http://..../[app]/default/data/search/[table]
but URLs must be signed, i.e. linked with
  A('table',_href=URL('data/tables',user_signature=True))
or with the signed load operator
  LOAD('default','data.load',args='tables',ajax=True,user_signature=True)
Source code in controllers/default.py
@auth.requires_signature()
def data():
    """Unchanged from web2py.

    ```
    http://..../[app]/default/data/tables
    http://..../[app]/default/data/create/[table]
    http://..../[app]/default/data/read/[table]/[id]
    http://..../[app]/default/data/update/[table]/[id]
    http://..../[app]/default/data/delete/[table]/[id]
    http://..../[app]/default/data/select/[table]
    http://..../[app]/default/data/search/[table]
    but URLs must be signed, i.e. linked with
      A('table',_href=URL('data/tables',user_signature=True))
    or with the signed load operator
      LOAD('default','data.load',args='tables',ajax=True,user_signature=True)
    ```
    """
    return dict(form=crud())  # noqa F821

Feed

controllers.feed

atom()

Serves an RSS feed of recently saved shared queries.

See also M:QUERYRECENT.

Source code in controllers/feed.py
def atom():
    """Serves an RSS feed of recently saved shared queries.

    See also [M:QUERYRECENT][queryrecent.QUERYRECENT].
    """
    session.forget(response)
    U = Urls()
    QueryRecent = QUERYRECENT()
    queries = QueryRecent.feed()
    icon = URL("static", "images/shebanq_logo_xxsmall.png", host=True)
    cover = URL("static", "images/shebanq_cover.png", host=True)
    base = URL("xxx", "yyy", host=True, extension="")[0:-8]
    feed = URL("feed", "atom", host=True, extension="")
    xml = []
    xml.append(
        """<?xml version="1.0" encoding="utf-8"?>
        """
    )
    xml.append(
        dedent(
            """
            <feed
                xmlns="http://www.w3.org/2005/Atom"
                xmlns:webfeeds="http://webfeeds.org/rss/1.0"
            >
            """
        )
    )
    xml.append(
        dedent(
            f"""
            <title>SHEBANQ</title>
            <subtitle>Shared queries, recently executed</subtitle>
            <link href="{hEsc(feed)}" rel="self"
                title="SHEBANQ - Shared Queries" type="application/atom+xml"/>
            <link href="{hEsc(base)}" rel="alternate" type="text/html"/>
            <id>{hEsc(base + "/hebrew/queries")}</id>
            <updated>{isodt()}</updated>
            <category term="bible study"/>
            <category term="biblical studies"/>
            <category term="text"/>
            <category term="linguistic"/>
            <category term="hebrew"/>
            <category term="bible"/>
            <category term="query"/>
            <category term="database"/>
            <category term="research"/>
            <category term="scholar"/>
            <category term="annotation"/>
            <category term="digital bible"/>
            <category term="digital"/>
            <category term="religion"/>
            <category term="theology"/>
            <icon>{hEsc(icon)}</icon>
            <webfeeds:icon>{hEsc(icon)}</webfeeds:icon>
            <logo>{hEsc(cover)}</logo>
            <webfeeds:cover image="{hEsc(cover)}"/>
            <webfeeds:accentColor>DDBB00</webfeeds:accentColor>
            """
        )
    )

    for (
        query_id,
        first_name,
        last_name,
        query_name,
        description,
        qvid,
        qexe,
        qver,
    ) in queries:
        descHtml = U.specialLinks(
            sanitize(
                markdown(
                    hEsc(description or "No description given"), output_format="xhtml5"
                )
            )
        )
        # we add a standard cover image if the description does not contain any image
        standardImage = (
            f"""<p><img src="{cover}"/></p>""" if "<img " not in descHtml else ""
        )
        href = hEsc(
            URL(
                "hebrew",
                "query",
                vars=dict(id=query_id, version=qver),
                host=True,
                extension="",
            )
        )
        tag = f"tag:shebanq.ancient-data.org,2016-01-01:{query_id}/{qvid}/{qver}"
        name = hEsc(f"{first_name} {last_name}")
        xml.append(
            dedent(
                f"""
                <entry>
                    <title>{hEsc(query_name)}</title>
                    <link href="{href}" rel="alternate" type="text/html"/>
                    <id>{tag}</id>
                    <updated>{isodt(qexe)}</updated>
                    <category term="query"/>
                    <content type="xhtml">
                        <div xmlns="http://www.w3.org/1999/xhtml">
                            {standardImage}
                            {descHtml}
                        </div>
                    </content>
                    <author><name>{name}</name></author>
                </entry>
                """
            )
        )
    xml.append(
        dedent(
            """
            </feed>
            """
        )
    )
    return dict(xml="".join(xml))

Hebrew

In hebrew.py.

The significant controllers are all here. Their bodies are very short, because they all call a function from the modules, which does all the work.

The modules are individually documented by docstrings in the code.

controllers.hebrew

init()

Source code in controllers/hebrew.py
def init():
    QueryChapter = QUERYCHAPTER()
    QueryChapter.makeQCindexes()

books()

Get all bible book names in all their translations.

See also M:BOOKS.getNames.

See ∈ language-info.

Source code in controllers/hebrew.py
def books():
    """Get all bible book names in all their translations.

    See also [M:BOOKS.getNames][books.BOOKS.getNames].

    See [∈ language-info][elem-language-info].
    """
    Books = BOOKS()
    session.forget(response)
    return Books.getNames()

text()

Serves a text page.

Corresponds with Text in the menu bar.

Only the skeleton of the page is fetched.

See also M:VIEWSETTINGS.page.

Source code in controllers/hebrew.py
def text():
    """Serves a **text** page.

    Corresponds with `Text` in the menu bar.

    Only the skeleton of the page is fetched.

    See also [M:VIEWSETTINGS.page][viewsettings.VIEWSETTINGS.page].
    """
    session.forget(response)
    init()
    Books = BOOKS()
    ViewSettings = VIEWSETTINGS(Books)
    ViewSettings.initState()
    return ViewSettings.page()

words()

Serves words overview pages.

Corresponds with Words in the menu bar.

The words are fetched in pages off all words starting with the same letter.

Source code in controllers/hebrew.py
def words():
    """Serves **words** overview pages.

    Corresponds with `Words` in the menu bar.

    The words are fetched in pages off all words starting with the same letter.
    """
    session.forget(response)
    init()
    Books = BOOKS()
    ViewSettings = VIEWSETTINGS(Books)
    ViewSettings.initState()
    Word = WORD()
    return Word.page(ViewSettings)

queries()

Serves the queries overview page.

Corresponds with Queries in the menu bar.

The main part is the tree of queries. There is also a widget with recent queries and a control to add new queries.

Source code in controllers/hebrew.py
def queries():
    """Serves the **queries** overview page.

    Corresponds with `Queries` in the menu bar.

    The main part is the tree of queries.
    There is also a widget with recent queries and a control to add new queries.
    """
    session.forget(response)
    init()
    Books = BOOKS()
    ViewSettings = VIEWSETTINGS(Books)
    ViewSettings.initState()
    Query = QUERY()
    return Query.page(ViewSettings)

notes()

Serves the notes overview page.

Corresponds with Notes in the menu bar.

The main part is the tree of note sets. There is also a widget for bulk uploading sets of notes.

Source code in controllers/hebrew.py
def notes():
    """Serves the **notes** overview page.

    Corresponds with `Notes` in the menu bar.

    The main part is the tree of note sets.
    There is also a widget for bulk uploading sets of notes.
    """
    session.forget(response)
    init()
    Books = BOOKS()
    ViewSettings = VIEWSETTINGS(Books)
    ViewSettings.initState()
    Note = NOTE(Books)
    return Note.page(ViewSettings)

word()

Serves a word record page.

Usually an overview page or from a shared link.

The page consists of a sidebar with the details of the word, and the main area displays the occurrences.

Source code in controllers/hebrew.py
def word():
    """Serves a *word* **record** page.

    Usually an overview page or from a shared link.

    The page consists of a sidebar with the details of the word,
    and the main area displays the occurrences.
    """
    session.forget(response)
    request.vars["mr"] = "r"
    request.vars["qw"] = "w"
    request.vars["page"] = 1
    return text()

query()

Serves a query record page.

Usually an overview page or from a shared link.

The page consists of a sidebar with the details of the query, and the main area displays the results.

Source code in controllers/hebrew.py
def query():
    """Serves a *query* **record** page.

    Usually an overview page or from a shared link.

    The page consists of a sidebar with the details of the query,
    and the main area displays the results.
    """
    session.forget(response)
    request.vars["mr"] = "r"
    request.vars["qw"] = "q"
    if request.extension == "json":
        Query = QUERY()
        return Query.bodyJson()
    else:
        request.vars["page"] = 1
    return text()

note()

Serves a notes set record page.

Usually from an overview page or a shared link.

The page consists of a sidebar with the details of the notes set, and the main area displays the notes between the verses.

Source code in controllers/hebrew.py
def note():
    """Serves a *notes set* **record** page.

    Usually from an overview page or a shared link.

    The page consists of a sidebar with the details of the notes set,
    and the main area displays the notes between the verses.
    """
    session.forget(response)
    request.vars["mr"] = "r"
    request.vars["qw"] = "n"
    request.vars["page"] = 1
    return text()

material()

Serves AJAX call for HTML content for the main area.

Client code: {material.fetch}.

Source code in controllers/hebrew.py
def material():
    """Serves AJAX call for HTML content for the main area.

    Client code: [{material.fetch}][materialfetch].
    """
    session.forget(response)
    Books = BOOKS()
    Word = WORD()
    Query = QUERY()
    Note = NOTE(Books)
    RecordQuery = RECORDQUERY(Query)
    Material = MATERIAL(RecordQuery, Word, Query, Note)
    return Material.page()

verse()

Get the linguistic data of a verse.

See also M:VERSE.get.

Client code: {material.addverserefs}.

Source code in controllers/hebrew.py
def verse():
    """Get the linguistic data of a verse.

    See also [M:VERSE.get][verse.VERSE.get].

    Client code: [{material.addverserefs}][materialaddverserefs].
    """
    session.forget(response)
    Verse = VERSE()
    return Verse.get()

sidematerial()

Serves AJAX call for HTML content for the sidebar (material page).

Client code: {sidecontent.fetch}.

Source code in controllers/hebrew.py
def sidematerial():
    """Serves AJAX call for HTML content for the sidebar (**material** page).

    Client code: [{sidecontent.fetch}][sidecontentfetch].
    """
    session.forget(response)
    Books = BOOKS()
    Word = WORD()
    Query = QUERY()
    Note = NOTE(Books)
    RecordQuery = RECORDQUERY(Query)
    Material = MATERIAL(RecordQuery, Word, Query, Note)
    Side = SIDE(Material, Word, Query, Note)
    return Side.page()

sideword()

Serves AJAX call for HTML content for the sidebar (word record page).

Used when the user is switching between material and record pages.

See also M:RECORD.body.

Client code: {sidecontent.fetch}.

Source code in controllers/hebrew.py
def sideword():
    """Serves AJAX call for HTML content for the sidebar (*word* **record** page).

    Used when the user is switching between **material** and **record** pages.

    See also [M:RECORD.body][record.RECORD.body].

    Client code: [{sidecontent.fetch}][sidecontentfetch].
    """
    session.forget(response)
    Record = RECORD()
    return Record.body()

sidequery()

Serves AJAX call for HTML content for the sidebar (query record page).

Used when the user is switching between material and record pages.

See also M:RECORD.body.

Client code: {sidecontent.fetch}.

Source code in controllers/hebrew.py
def sidequery():
    """Serves AJAX call for HTML content for the sidebar (*query* **record** page).

    Used when the user is switching between **material** and **record** pages.

    See also [M:RECORD.body][record.RECORD.body].

    Client code: [{sidecontent.fetch}][sidecontentfetch].
    """
    session.forget(response)
    Query = QUERY()
    Record = RECORDQUERY(Query)
    return Record.body()

sidenote()

Serves AJAX call for HTML content for the sidebar (note set record page).

Used when the user is switching between material and record pages.

See also M:RECORD.body.

Client code: {sidecontent.fetch}.

Source code in controllers/hebrew.py
def sidenote():
    """Serves AJAX call for HTML content for the sidebar (*note set* **record** page).

    Used when the user is switching between **material** and **record** pages.

    See also [M:RECORD.body][record.RECORD.body].

    Client code: [{sidecontent.fetch}][sidecontentfetch].
    """
    session.forget(response)
    Record = RECORD()
    return Record.body()

sidewordbody()

Serves AJAX call for HTML content for the sidebar (word record page).

Used when the user is loading word page directly.

See also M:WORD.body.

Source code in controllers/hebrew.py
def sidewordbody():
    """Serves AJAX call for HTML content for the sidebar (*word* **record** page).

    Used when the user is loading *word* page directly.

    See also [M:WORD.body][word.WORD.body].
    """
    session.forget(response)
    if not request.ajax:
        redirect(URL("hebrew", "word", extension="", vars=request.vars))
    Word = WORD()
    return Word.body()

sidequerybody()

Serves AJAX call for HTML content for the sidebar (query record page).

Used when the user is loading a query page directly.

See also M:QUERY.body.

Source code in controllers/hebrew.py
def sidequerybody():
    """Serves AJAX call for HTML content for the sidebar (*query* **record** page).

    Used when the user is loading a *query* page directly.

    See also [M:QUERY.body][query.QUERY.body].
    """
    session.forget(response)
    if not request.ajax:
        redirect(URL("hebrew", "query", extension="", vars=request.vars))
    Query = QUERY()
    return Query.body()

sidenotebody()

Serves AJAX call for HTML content for the sidebar (notes set record page).

Used when the user is loading a notes set page directly.

See also M:NOTE.body.

Source code in controllers/hebrew.py
def sidenotebody():
    """Serves AJAX call for HTML content for the sidebar (*notes set* **record** page).

    Used when the user is loading a *notes set* page directly.

    See also [M:NOTE.body][note.NOTE.body].
    """
    session.forget(response)
    if not request.ajax:
        redirect(URL("hebrew", "note", extension="", vars=request.vars))
    Books = BOOKS()
    Note = NOTE(Books)
    return Note.body()

queriesr()

Serves AJAX call for json data for recently saved shared queries.

See also [queryrecent.QUERYRECENT.recent].

Client code: {queryrecent.fetch}

Source code in controllers/hebrew.py
def queriesr():
    """Serves AJAX call for json data for recently saved shared queries.

    See also [queryrecent.QUERYRECENT.recent].

    Client code: [{queryrecent.fetch}][queryrecentfetch]
    """
    session.forget(response)
    QueryRecent = QUERYRECENT()
    return QueryRecent.recent()

querytree()

Serves AJAX call for json data for the tree overview of queries.

See also M:QUERYTREE.get.

Client code: {querytree.Tree}

Source code in controllers/hebrew.py
def querytree():
    """Serves AJAX call for json data for the tree overview of queries.

    See also [M:QUERYTREE.get][querytree.QUERYTREE.get].

    Client code: [{querytree.Tree}][querytreetree]
    """
    session.forget(response)
    QueryTree = QUERYTREE()
    return QueryTree.get()

notetree()

Serves AJAX call for json data for the tree overview of notes sets.

See also M:NOTETREE.get.

Client code: {notetree.Tree}

Source code in controllers/hebrew.py
def notetree():
    """Serves AJAX call for json data for the tree overview of notes sets.

    See also [M:NOTETREE.get][notetree.NOTETREE.get].

    Client code: [{notetree.Tree}][notetreetree]
    """
    session.forget(response)
    NoteTree = NOTETREE()
    return NoteTree.get()

getversenotes()

Serves AJAX call for json data for all notes belonging to a single verse.

See also M:NOTE.getVerseNotes.

Client code: {noteverse.fetch}

Source code in controllers/hebrew.py
def getversenotes():
    """Serves AJAX call for json data for all notes belonging to a single verse.

    See also [M:NOTE.getVerseNotes][note.NOTE.getVerseNotes].

    Client code: [{noteverse.fetch}][noteversefetch]
    """
    session.forget(response)
    Books = BOOKS()
    Note = NOTE(Books)
    return Note.getVerseNotes()

putversenotes()

Serves AJAX call for json data to save notes.

See also M:NOTESAVE.putVerseNotes.

Client code: {noteverse.sendnotes}

Source code in controllers/hebrew.py
def putversenotes():
    """Serves AJAX call for json data to save notes.

    See also [M:NOTESAVE.putVerseNotes][notesave.NOTESAVE.putVerseNotes].

    Client code: [{noteverse.sendnotes}][noteversesendnotes]
    """
    session.forget(response)
    Books = BOOKS()
    Note = NOTE(Books)
    NoteSave = NOTESAVE(Note)
    return NoteSave.putVerseNotes()

noteupload()

Receives bulk-uploaded notes and stores them.

See also M:NOTESUPLOAD.upload.

Client code: {notetree.Upload.submit}.

Source code in controllers/hebrew.py
def noteupload():
    """Receives bulk-uploaded notes and stores them.

    See also [M:NOTESUPLOAD.upload][notesupload.NOTESUPLOAD.upload].

    Client code: [{notetree.Upload.submit}][uploadsubmit].
    """
    session.forget(response)
    Books = BOOKS()
    Note = NOTE(Books)
    NotesUpload = NOTESUPLOAD(Books, Note)
    return NotesUpload.upload()

item()

Get csv data of the items associated with a record.

Items are: the occurrences of a word, the results of a query, the notes of a notes set.

See also M:CSVDATA.page.

Client code: {viewstate.csvUrl}.

Source code in controllers/hebrew.py
def item():
    """Get csv data of the items associated with a record.

    Items are:
    the occurrences of a word, the results of a query, the notes of a notes set.

    See also [M:CSVDATA.page][csvdata.CSVDATA.page].

    Client code: [{viewstate.csvUrl}][viewstatecsvurl].
    """
    session.forget(response)
    Word = WORD()
    Query = QUERY()
    RecordQuery = RECORDQUERY(Query)
    CsvData = CSVDATA(RecordQuery, Word, Query)
    return CsvData.page()

chart()

Get a heat map of the items associated to a record.

Items are: the occurrences of a word, the results of a query, the notes of a notes set.

See also M:CHART.page.

Client code: {chart.fetch}.

Source code in controllers/hebrew.py
def chart():  # controller to produce a chart of query results or lexeme occurrences
    """Get a heat map of the items associated to a record.

    Items are:
    the occurrences of a word, the results of a query, the notes of a notes set.

    See also [M:CHART.page][chart.CHART.page].

    Client code: [{chart.fetch}][chartfetch].
    """
    session.forget(response)
    Books = BOOKS()
    Word = WORD()
    Query = QUERY()
    Note = NOTE(Books)
    RecordQuery = RECORDQUERY(Query)
    Chart = CHART(Books, RecordQuery, Word, Query, Note)
    return Chart.page()

itemrecord()

Saves a record to the database, typically organizations, projects, queries.

See also M:RECORD.setItem.

Client code: {querytree.Tree.record}.

Source code in controllers/hebrew.py
def itemrecord():
    """Saves a record to the database, typically organizations, projects, queries.

    See also [M:RECORD.setItem][record.RECORD.setItem].

    Client code: [{querytree.Tree.record}][treerecord].
    """
    session.forget(response)
    Query = QUERY()
    RecordQuery = RECORDQUERY(Query)
    return RecordQuery.setItem()

querysharing()

Saves the shared status of a query to the database.

See also M:QUERYSAVE.sharing.

Client code: {sidecontent.sendval}.

Source code in controllers/hebrew.py
def querysharing():
    """Saves the shared status of a query to the database.

    See also [M:QUERYSAVE.sharing][querysave.QUERYSAVE.sharing].

    Client code: [{sidecontent.sendval}][sidecontentsendval].
    """
    session.forget(response)
    Query = QUERY()
    QueryChapter = QUERYCHAPTER()
    QuerySave = QUERYSAVE(Query, QueryChapter)
    return QuerySave.sharing()

queryupdate()

Saves metadata of a query to the database.

See also M:QUERYSAVE.putRecord.

Client code: {sidecontent.sendvals}.

Source code in controllers/hebrew.py
def queryupdate():
    """Saves metadata of a query to the database.

    See also [M:QUERYSAVE.putRecord][querysave.QUERYSAVE.putRecord].

    Client code: [{sidecontent.sendvals}][sidecontentsendvals].
    """
    session.forget(response)
    Query = QUERY()
    QueryChapter = QUERYCHAPTER()
    QuerySave = QUERYSAVE(Query, QueryChapter)
    return QuerySave.putRecord()