Theophrastus is a toy application for learning "full stack" web programming. It uses Python, Bottle, and SQLite3 in the most minimal application I can write that does anything "meaningful."
I picked the name be scanning through the Google search results and the Wikipedia article for Message_in_a_bottle where there's an unreliably sourced claim that Theophrastus released the "first recorded messages in bottle." (Let me know if you ever find a reliable citation supporting or refuting that claim).
The program, app.py
, simply presents a list of currently active
"notices" and a link through which you can post new ones. It keeps
them in a simple database and you have the option to "close" each one.
It will automatically re-create its database table if one isn't found.
It currently comes with an almost equally dinky test utility called
posttest.py
which posts 1000 messages to app.py
based
on sentences generated by the loremipsum
Python module and times
the process. On my system it does about 60 posts per second.
app.py
's only external dependency is bottle
since SQLite is included in Python's standard
libraries.
posttest.py
depends on Python Requests
and loremipsum.
Fetch the code using:
git clone https://github.com/JimDennis/theophrastus.git`
... ensure that you've installed the Python bottle module and then simply run:
./app.py
Theophrastus will create a ./notifications.db (SQLite3) database in the current directory and create its notices table. This datebase will be retained if you stop and restart the web app.
From there you can visit the application with your browser on: http://localhost:8080, post messages and view them, and "close" them.
The home page simply shows a list of currently "open" notices threads with the message ID of the most recent message/update in the thread, who it's from, the date/timestamp at which it was posted, and first line (up to 72 characters) of the message, and a "close" link for each. This is followed by a link to the /notify form to allow you to post new messages.
If there are more than 20 open message threads than Theophrastus will provide HTML controls to page through them at the bottom.
These database contents (threads) are displayed in descending order of ID ... most recent posting at the top.
Clicking on the "From" or the subject of any thread's tail will bring up a view of the entire thread and the full text of that message.
Closing a notification in Theophrastus simply sets a "closedate" timestamp for all messages in that thread, and returns you to the app's root which will no longer display that message.
Sending a new notification (starting a new thread) requires simple authentication (login). Theophrastus supports pluggable/modular authentication through a configuration (`./settings.ini' by default, but it can be set using the BOTTLECFG environment setting) like so:
[Auth]
module: mockauth.py
file: auth.db
cookie_nonce: TO_BE_IMPLEMENTED
Currently one authentication module is supply for testing purposes
(mockauth.py
). This creates a simple single table SQLite3 database
and the module also functions as a commmand line utility for adding
new usernames and passwords to that table.
Currently the authentication only sets a cookie. Support will be added to record users and perhaps to provide a view for users to see only the notice threads which they initiated or to which they've posted updates.
Also note that some support for Javascript alert boxes, interstitials, has been added.
You can call ./app.py
as a command line utility with arguments.
Currently the only supported command is backup
which, as you might
expect, will perform a backup of the notifications.db. Because of
the ACID semantics provided by SQLite3 you can also access the database
while ./app.py
is running using commands like:
sqlite3 ./notifications.db 'select count(name),name from notices group by name order by count(name)'
(This example will produce a count of all notices addressed to each recipient, including open and closed entries)
... and this:
sqlite3 ./notifications.db 'delete from notices where closedate is not null'
... will remove all closed notices from the system.
You can also perform a "hot" backup of the database using:
sqlite3 ./notifications.db '.backup ./notifications.db.bak'
Theophrastus includes a very simple little performance and load testing script
posttest.py
which will generate messages and post them to app.py
as quickly as possible. It uses the loremipsum module to generate messages
and the requests library for posting them. It also hammers on the web server
from multiple concurrent processes using multiprocessing.Pool from the standard
libraries.
You can all posttest.py
with no arguments to accept the default (1000 notices
posted from 10 processes) or you can call it with arguments for num_tests and
num_procs like so:
./posttest.py 1000 20
... which will hammer on the server with 1000 messages from 20 processes.
posttest.py
will then print a result like:
Took 0.06 seconds to generate 1000 tests
Took 1.88 seconds to post 1000 tests (529.463/second)
There were 64 errors reported in testpost()
This very simple test counts all errors; any exceptions raised by the call to requests.post() (mostly"connection refused") as well as any results which were returned but not "ok").
A more thorough testing utility would interleave some read traffic in with the new message postings, of course. But this test is reasonable for ensure that new code changes don't catastrophically impact performance.
(Hmmm: should we create a new table in the notifications.db and post perf test results to that?)