When a potential user or contributor lands on your repository’s page,they see a few things:
- Project Name
- Project Description
- Bunch O’ Files Only when they scroll below the fold will the user see your project’sREADME.
If your repo is a massive dump of files or a nested mess of directories,they might look elsewhere before even reading your beautifuldocumentation.
Of course, first impressions aren’t everything. You and your colleagueswill spend countless hours working with this repository, eventuallybecoming intimately familiar with every nook and cranny. The layout ofit is important.
Sample Repository
tl;dr: This is what Kenneth Reitz recommends.
This repository is .
Let’s get into some specifics.
The Actual Module
Your module package is the core focus of the repository. It should notbe tucked away:
If your module consists of only a single file, you can place it directlyin the root of your repository:
- ./sample.py
Your library does not belong in an ambiguous src or python subdirectory.
Location | ./LICENSE |
Purpose | Lawyering up. |
This is arguably the most important part of your repository, aside fromthe source code itself. The full license text and copyright claimsshould exist in this file.
If you aren’t sure which license you should use for your project, checkout .
Setup.py
If your module package is at the root of your repository, this shouldobviously be at the root as well.
Requirements File
Location | ./requirements.txt |
Purpose | Development dependencies. |
A pip requirementsfileshould be placed at the root of the repository. It should specify thedependencies required to contribute to the project: testing, building,and generating documentation.
If your project has no development dependencies, or you preferdevelopment environment setup via , this file may beunnecessary.
There is little reason for this to exist elsewhere.
Test Suite
For advice on writing your tests, seeTesting Your Code.
Location | ./test_sample.py or ./tests |
Purpose | Package integration and unit tests. |
Starting out, a small test suite will often exist in a single file:
- ./test_sample.py
Once a test suite grows, you can move your tests to a directory, likeso:
Obviously, these test modules must import your packaged module to testit. You can do this a few ways:
- Expect the package to be installed in site-packages.
- Use a simple (but explicit) path modification to resolve thepackage properly.
I highly recommend the latter. Requiring a developer to run
setup.py develop
to test an actively changingcodebase also requires them to have an isolated environment setup foreach instance of the codebase.
To give the individual tests import context, create a file:
- import os
- import sys
- sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
- import sample
Then, within the individual test modules, import the module like so:
- from .context import sample
This will always work as expected, regardless of installation method.
Makefile
If you look at most of my projects or any Pocoo project, you’ll notice aMakefile lying around. Why? These projects aren’t written in C… Inshort, make is an incredibly useful tool for defining generic tasks foryour project.
Sample Makefile:
- init:
- pip install -r requirements.txt
- py.test tests
- .PHONY: init test
Other generic management scripts (e.g. manage.py
or fabfile.py
) belong at the root of the repository as well.
I’ve noticed a new trend in Django applications since the release ofDjango 1.4. Many developers are structuring their repositories poorlydue to the new bundled application templates.
How? Well, they go to their bare and fresh repository and run thefollowing, as they always have:
The resulting repository structure looks like this:
- README.rst
- samplesite/manage.py
- samplesite/samplesite/settings.py
- samplesite/samplesite/wsgi.py
- samplesite/samplesite/sampleapp/models.py
Don’t do this.
Repetitive paths are confusing for both your tools and your developers.Unnecessary nesting doesn’t help anybody (unless they’re nostalgic formonolithic SVN repos).
Let’s do it properly:
- $ django-admin.py startproject samplesite .
Note the “.
”.
The resulting structure:
- README.rst
- manage.py
- samplesite/settings.py
- samplesite/wsgi.py