Projects under the Pylons Project scope have rigorous standards for coding style, testing, and documentation.
Documentation contributions should follow thePylons Project Documentation Style Guide. Every project needs to have documentation built withSphinx using either thePylons or Pyramid Sphinx Theme for consistency.
Set the following values forlatex_documents
indocs/conf.py
:
# Grouping the document tree into LaTeX files. List of tuples# (source start file, target name, title, author, document class [howto/manual]).latex_documents = [ ('latexindex', 'pyramid_<project name>.tex', 'Pyramid\_<project name>', 'Author', 'manual'),]
It is important to use\_
to escape the underscore in the document title to prevent a failure in LaTeX.
Comment the following line:
#latex_logo = '_static/pylons_small.png'
Copy the folderpyramid/docs/_static
(contains two .png files) and the filepyramid/docs/convert_images.sh
into yourdocs/
folder.
Make sure you have the following value forepub_exclude_files
indocs/conf.py
:
# A list of files that should not be packed into the epub file. epub_exclude_files = ['_static/opensearch.xml', '_static/doctools.js', '_static/jquery.js', '_static/searchtools.js', '_static/underscore.js', '_static/basic.css', 'search.html', '_static/websupport.js']
In order to add a feature to any Pylons Project package:
docs/
.tox.ini
of most Pylons Project packages indicates which versions the package is tested under.The above requirements are relaxed for paster template dependencies. If a paster template has an install-time dependency on something that doesn't work on a particular platform, that caveat should be spelled out clearly inits documentation (within itsdocs/
directory).
To determine if a feature should be added to an existing package, or deserves a package of its own, feel free to talk to one of the developer teams.
If you fix a bug, and the bug requires an API or behavior modification, all documentation in the package which references that API or behavior must change to reflect the bug fix, ideally in the same commit that fixes the bug or adds the feature.
Feature additions and bugfixes must be added to theCHANGES.txt
file in the prevailing style. Changelog entries should be long and descriptive,not cryptic. Other developers should be able to know what your changelog entry means.
The codebasemust have 100% test statement coverage after each commit. You can test coverage viapython setup.py nosetests --with-coverage
(requires thenose
andcoverage
packages).
Testing code in a consistent manner can be difficult. To help developers learn our style ("dogma") of testing we've made available a set of testing notes atUnit Testing Guidelines.
All Python code should follow a derivation ofPEP-8 style guidelines. Whitespace rules and other rules are relaxed (for example, it is not necessary to put two newlines between classes, though that's just fine if you do). Other rules are relaxed too, such as spaces around operators. 79-column lines, however, are mandatory.
If you do use thepep8
tool for automated checking, here is an invocation that is close to what is required by the project (subject to change):
pep8 --ignore=E302,E261,E231,E123,E301,E226,E262,E225,E303,E125,E251,E201,E202,E128,E122,E701,E203,E222,W293,W291,W391 *.py
Do this:
import osimport sys
Donot do this:
import os, sys
Importing a single item per line makes it easier to read patches and commit diffs.
If you need to import lots of names from a single package, use:
from thepackage import ( foo, bar, baz, )
It may look unusual, but it has advantages:
foo
for something else that provides the similar API. An example would be swapping out one database for another (for example, graduating from SQLite to PostgreSQL).Imports should be ordered by their origin. Names should be imported in this order:
Donot import all the names from a package (in other words, never usefrom package import *
); import just the ones that are needed. Single-line imports apply here as well: each name from the other package should be imported on its own line.
Remember that since Python only parses the default argument for a function/method just once, they cannot be safely used as default arguments.
Donot do this:
def somefunc(default={}): if default.get(...): ...
Either of these is fine:
def somefunc(default=None): default = default or {}
def somefunc(default=None): if default is None: default = {}
Creating code that requires someone to import a module or package for the singular purpose of causing some module-scoped code to be run is highly discouraged. It is only permissible to add such code to the core in paster templates, where it might be required by some other framework (for example, SQLAlchemy "declarative base" classes must be imported to be registered).