For Users

NC Jazz Beat

NC Jazz Beat is a Django CMS application which tracks live jazz performances in Central North Carolina. It provides information about upcoming performances and occasional feature articles.

Much of the code specific to this web application is a set of around twenty scrapers that process venue web sites and maintain a set of active events for the venue in the database.

The site also serves as a testbed for components common to multiple Emptyhammock projects; most of those components are listed elsewhere on this page.

This Django application allows a group of people that walk together to easily post their attendance, without using noisy services like Meetup. It supports login with a Google or Yahoo account.

This isn't currently open to the public; you can log in with a Google or Yahoo account, but you'll be unable to do anything since you're not in a walking group.

Multi-faceted Education System 

This prototype system used the learning objective concept to relate current classroom activities to pertinent educational materials, both curated and crowd-sourced, which students and parents could access away from school.

More details

Stacktrace management

Stacktraces are very useful, particularly when they are collected, and tools are available for identifying reoccurrences and to access the results of previous investigations. will let you upload stacktraces and add descriptions in Markdown and identify duplicates in a file upload, etc.

For Python 

Parsing stack traces (Python, gdb, pstack)

PYTHON_STACKTRACE_1 = u"""[14/Mar/2015 01:37:05] ERROR [django.request:231] Internal Server Error: /walk/ExYu
Traceback (most recent call last):
  File "/home/trawick/git/walking/envs/walking/lib/python2.7/site-packages/django/core/handlers/", line 111, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/trawick/git/walking/envs/walking/lib/python2.7/site-packages/django/contrib/auth/", line 21, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/home/trawick/git/walking/src/walking/walks/", line 58, in index
    forecast = wo.weather_forecast()
  File "/home/trawick/git/walking/src/walking/walks/", line 81, in weather_forecast
    city, raw_forecast = w.around(start, 4 * 60 * 60)
  File "/home/trawick/git/walking/src/walking/walking/", line 132, in around
    d = Weather._fetch(uri, self._validate_around_weather)
  File "/home/trawick/git/walking/src/walking/walking/", line 42, in _fetch
    c.request('GET', uri)
  File "/home/trawick/python-2.7/lib/python2.7/", line 995, in request
    self._send_request(method, url, body, headers)
  File "/home/trawick/python-2.7/lib/python2.7/", line 1029, in _send_request
  File "/home/trawick/python-2.7/lib/python2.7/", line 991, in endheaders
  File "/home/trawick/python-2.7/lib/python2.7/", line 844, in _send_output
  File "/home/trawick/python-2.7/lib/python2.7/", line 806, in send
  File "/home/trawick/python-2.7/lib/python2.7/", line 787, in connect
    self.timeout, self.source_address)
  File "/home/trawick/python-2.7/lib/python2.7/", line 571, in create_connection
    raise err
error: [Errno 110] Connection timed out""".split('\n')  # noqa

    'processname': 'no-name',
    'threadgroups': [{'thread_ids': [0]}],
    'threads': [
            'failure': u'error: [Errno 110] Connection timed out',
            'frames': [
                {'fn': u'get_response', 'id': 1},
                {'fn': u'_wrapped_view', 'id': 2},
                {'fn': u'index', 'id': 3},
                {'fn': u'weather_forecast', 'id': 4},
                {'fn': u'around', 'id': 5},
                {'fn': u'_fetch', 'id': 6},
                {'fn': u'request', 'id': 7},
                {'fn': u'_send_request', 'id': 8},
                {'fn': u'endheaders', 'id': 9},
                {'fn': u'_send_output', 'id': 10},
                {'fn': u'send', 'id': 11},
                {'fn': u'connect', 'id': 12},
                {'fn': u'create_connection', 'id': 13}

p = get_process_from_traceback(PYTHON_STACKTRACE_1)
self.assertEqual(EXPECTED_DICT_1, p.description(),)

Summing up lengths of time and time ranges in a string. For example:

=> timedelta(hours=19, minutes=2, seconds=57)

Parsing more kinds of time descriptions. For example:

list(parse_repeat_phrase('1st Fridays 8:30pm-12:30am', timedelta(days=40)))
=> [(datetime.datetime(2018, 3, 2, 20, 30), datetime.datetime(2018, 3, 3, 0, 30))]

parse_single_event('january 13 9-11pm')
=> (datetime.datetime(2018, 1, 13, 21, 0), datetime.datetime(2018, 1, 13, 23, 0))

parse_time_range(1, 15, 2018, '9pm-12am', local_tz=pytz.timezone('US/Eastern'))
(datetime.datetime(2018, 1, 15, 21, 0, tzinfo=),
 datetime.datetime(2018, 1, 16, 0, 0, tzinfo=))

Stuff like this, also programmatically:

coverage: 4.4.2
Newer releases:
  4.5: No information about package

Django: 1.11.9
Newer releases:
  1.11.10: SECURITY

Newer releases:
  2.7.4: Non-security bug fixes

Up to date: urllib3, certifi, chardet, click, defusedxml, django-click, django-dotenv, django-timezone-field, django-webpack-loader, flake8, huey, idna, mccabe, oauthlib, pycodestyle, pyflakes, PyJWT, python3-openid, pytz, PyYAML, redis, requests, requests-oauthlib, six, social-auth-app-django, social-auth-core, urllib3

The default package release database covers the tiny fraction of PyPI of interest to my projects; other users will want to override the default database with a different one that covers the packages used by their applications.

Because of that effort, this package could be useful only for people that need to decide on the criticality of package upgrades. They can use this package to find out when new releases are available, then they'll research and document the criticality of updates in the form of a release database that can be processed by this project.

For the projects I support, my maintenance bot captures pip freeze on the production servers, then uses this package to let me know which packages have newer releases on PyPI that either haven't been evaluated or that have been determined to be desirable. I try to perform the evaluation (i.e., read the project's change history) and update the database without delay, in case I find out that the upgrade is critical.

There's also a Django app that allows the package release db to be maintained from a web admin, providing exports to authorized clients:

For Django and Django CMS

Web Server Configuration

Documentation and commentary on configuring httpd, nginx, uWSGI, etc., for Django, Flask, and other Python web frameworks/libraries


This package implements a way to create content for the web site from admin, and use a combination of Django CMS plugins and other site features to make that content accessible to users of their site, such that the content is maintained separately from where and how it is displayed.

More specifically, the package provides a multi-purpose Article class, a view for articles, and Django CMS plugins which allow the content editor to place particular articles or article teasers or feeds of articles on a CMS page.


Simple Django CMS plugins, including a teaser for CMS pages and a teaser for a URL.


This is appropriate for applications that need a workflow for contact requests, beyond simply sending an e-mail to an admin when the contact form is submitted. Contact requests can be marked as resolved in the admin, and notes can be saved with the request to document the resolution.

Ansible deployment of Django applications

There are various emptyhammock-role-FOO repositories which may serve as useful examples of different aspects of deploying a Django application to a single Linux system. 

Utility Programs


Fun with HTTP and carefully controlling I/O to a server you're testing

Summarize file descriptors

for a process group. It lists all the file descriptors for any of the processes in the group (e.g., all the nginx or httpd processes) with the list of process ids for each fd.

$ 8620
fd 0 type CHR name /dev/null
  8620 8621 8622 8623
fd 1 type CHR name /dev/null
  8620 8621 8622 8623
fd 2 type REG name /home/trawick/inst/24-64/logs/error_log
  8620 8621 8622 8623
fd 3 type sock name protocol: TCP
  8620 8621 8622 8623
fd 4 type IPv6 dev 83085 name *:8080
  8620 8622 8623
fd 49 type REG name /home/trawick/inst/24-64/logs/websocket-app-error.log
  8620 8621 8622 8623
fd 50 type REG name /home/trawick/inst/24-64/logs/walking.log
  8620 8621 8622 8623
fd 62 type FIFO name pipe
  8620 8622 8623
fd 4 type unix dev 0x0000000000000000 name /home/trawick/inst/24-64/logs/cgisock.8620 type=STREAM
fd 63 type a_inode name [eventpoll]

For Apache HTTP Server

Popular diagnostic modules 

Documentation for mod_whatkilledus and mod_backtrace

Process explorer

Upload backtraces from pstack or gdb and see descriptions of the current processing state.

Example httpd hook probes module

Example plug-in module for httpd that tracks module API calls using the hook probes feature


Simple Linux NAS 

This repo has Ansible scripts and other information for setting up a NAS, including a test version inside Vagrant.