Anatomy of a Pinax Reusable App
We maintain an app template that we base new apps off of and are in the process of updating older apps to comply with. This template is called pinax-starter-app and is the best place to start in walking through how we build apps.
We can break down this application template into the following areas:
- Common Files
- Continuous Integration
- Documentation
- Packaging
- Pinax Namespace
Common Files
We (should) have a common set of files in all our projects. By having them in the template we can ensure that we don’t forget to create them or copy them over from another project.
CONTRIBUTING.md
- the document that provides guidance when submitting pull requests on preferences for how to work with our code base.gitignore
- common things like.pyc
that we want to make sure don’t get committed to the repoAUTHORS
- a file that lists all the contributors to the projectLICENSE
- a copy of the MIT license that we apply to all our open sourceREADME.rst
- both a README for the app template as well as a template to be used on the new app once you create it
Continuous Integration
Code quality is a big priority of the Pinax team. Not only do we want to keep quality high from the perspective of bugs, but we want the code to be beautiful, clean, and consistant.
We lean heavily on Travis CI to automate the checking of the code on every commit pushed and every pull request sent to us. We run tests, we lint the code, and we send coverage reports to Coveralls so we can keep an eye on test coverage.
tox.ini
- is what controls our testing matrix, we validate our app against several versions of Python and Django.travis.yml
- the configuration that tells Travis CI what to doruntests.py
- a script that bootstraps the Django environment in order to test the Django appsetup.py
- has a parameter,test_suite="runtests.runtests"
, that tellspython setup.py test
what to run.coveragerc
- has configuration for running coverage on Travispinax/app_name/tests/
- serves as the basis to write tests for the application
By providing a new app with all this infrastructure setup and ready to go, we at
least get linting of the code from the first commit pushed to an open repo
as we have Travis CI setup to work for any repo it finds on the Pinax
organziation that has a .travis.yml
file.
But it’s also dead simple to just add some tests and they’ll get run since all you have to do is literally just starting writing tests.
Documentation
We have recently switched from using Sphinx to MkDocs. Both are supported on Read The Docs where all our docs are hosted but Markdown is just more natural when authoring content and setup/configuration for MkDocs is simpler and quicker to get going with.
docs/
- is the start of the documentationmkdocs.yml
- configuration for MkDocs
Both of these are setup to just make getting going with writing documentation easy and to get the infrastruction bits out of the way.
Packaging
Packaging is another infrastructure piece that we had done a lot of different ways in the past and was always evolving. It likely will continue to evolve but hopefully those changes will be reflected in this template and our projects kept reconciled to it.
MANIFEST.in
- what files should we always include in the packagesetup.py
- we have had lots more complicated setup files in the past but this being short and sweet seems to fit the bill lately
We used to specify the version number in the package’s __init__.py
and then
import it into the setup.py
. But we have found specifying the version number
in the setup.py
and using pkg_resources
to pull it out of the package for
anything that needs to read the version at run time to be a better alternative:
# pinax/app_name/__init__.py import pkg_resources __version__ = pkg_resources.get_distribution("pinax-{{ app_name }}").version
Pinax Namespace
Lastly, you might have noticed that we have started namespacing Pinax apps. Not
all of them. Some, like django-user-accounts
will remain top level for historical reasons, but most apps will be rolled under
the pinax.*
namespace.
The main reason for doing this is so we can use more functional names that will
likely have collisions with other applications in the ecosystem. For example,
we currently have this problem with django-stripe-payments
and the code living in a payments
namespace. There have been some requests from
folks who are using other packages with the same namespace making them incompatible
to live side by side. Having this package live at pinax.payments
will solve
that, in addition signal to the developer that this app is designed to work well
with other Pinax ecosystem applications.
Another reason for this change is that Eldarion is donating a lot of its
open source to Pinax. Eldarion had a history of naming his open source applications
with Greek names. There has been a lot of feedback that this makes things hard
to discover. So we have renamed packages as they have been donated, for instance,
biblion
to pinax-blog
.