Manual:Coding conventions/Python

From MediaWiki.org
Jump to: navigation, search
shortcut: CC/PY

This page describes the coding conventions for Python projects that are a part of the MediaWiki project or supporting projects.

Preamble[edit]

First, remember that code standards are only guidelines and can be violated if there is a good reason.

  • Aim for readability and obviousness over strict adherence for the sake of strict adherence.
  • Code is read much more often than it is written.
  • Be consistent with existing code, but use your best judgement. If it isn't too hard to fix up the existing code, WP:BOLD.

For anything not covered in this document, please refer to Python Enhancement Proposal 0008 for the general practice. The following sections are for the most part a summary of the most commonly referred to parts of PEP8.

Python version[edit]

The minimum supported version is 2.7, but in special cases it is ok to support older versions. Don't go out of your way to use features that break older Python. If you need a new feature, use it.

Whitespace[edit]

Lines should be indented with 4 spaces.

Lines at the end of files should end with a newline, just like every other line in the file.

Try to keep lines under 80 characters long, but aim for readability and obviousness over strict adherence for the sake of strict adherence. Shorter lines are just a general side effect of good idiomatic python - short but properly scoped descriptive names, avoiding staircase code, etc. When splitting up lines, pick the most obviously unambiguous method possible for the situation.

Module structure[edit]

The standard way to distribute python modules is to create a setup.py file and leverage a library called "distribute". There are modules that will generate the structure of a base project for you, a deprecated one is paster create which is no longer maintained. A replacement is pythong.

In general module structure should look like this:

newproject
├── bin
├── distribute_setup.py
├── docs
├── newproject
│   └── __init__.py
├── setup.py
└── tests
    ├── __init__.py
    └── newproject_tests.py

Imports[edit]

Within a file it's generally a good idea to organize your imports in some fashion. Typically alphabetical order is favored, but this can become unwieldy when importing a large number of libraries. To help avoid this, it's good to separate out imports in this fashion:

  • Standard library imports
  • Third party imports
  • Your library imports
import os
import re
import sys

import pymongo
from sqlalchemy import create_engine, exceptions

from mymodule import MyCustomException, models, views

Here are some patterns to avoid:

import sys, os # importing different modules on the same line
from sqlalchemy import * # don't import *
from .models import util # use fully qualified names instead of relative imports

Docstrings and function annotation[edit]

Generally all but the simplest functions should have docstrings. These are standardized in PEP 257

def fractionize(first, second=1):
    """
    Make a string representation of a fraction of two numbers.

    Keyword arguments:
    first -- the top of the fraction
    second -- the bottom of the fraction (anything but 0)
    """
    return "{0} / {1}" % (first, second)

This makes it possible to automatically generate docs, as well as use Python's built-in help function.

In Python 3.3 and above PEP 3107 specifies syntax for function annotations.

Function annotations do not have a completely set use case, but a common emerging case is for improved help docs and for type annotation.

def parse(source: "the original document",
          lang: "what markup syntax is being used? [md|rst|textile]",
          force: "Ignore syntax errors?"):

Naming conflicts[edit]

Conflicting with builtins is a somewhat common problem. There are some builtin names (like hash and id) that you may want to use in your code. The PEP8 way to deal with these conflicts is by appending an underscore to the name, such as hash_ or class_ (although if you're naming a variable class_ that may be a code smell).

If you find yourself in conflict with the name of some part of another module, import as is your friend.

from sqlalchemy import exceptions as sa_exceptions
from mymodule import exceptions as my_exceptions

See also[edit]

Coding conventionsManual:Coding conventions
General All languagesManual:Coding conventions#Code structure · Development policyDevelopment policy · Security for developersSecurity for developers · Pre-commit checklistManual:Pre-commit checklist · Performance guidelinesPerformance guidelines(draft) · Style guideDesign/Living style guide · Accessibility guide for developersAccessibility guide for developers(draft)
PHP Code conventionsManual:Coding conventions/PHP · PHPUnit test conventionsManual:PHP unit testing/Writing unit tests#Test_conventions · Security checklist for developersSecurity checklist for developers
JavaScript Code conventionsManual:Coding conventions/JavaScript · Learning JavaScriptLearning JavaScript
CSS Code conventionsManual:Coding conventions/CSS
Database Code conventionsManual:Coding conventions/Database · Database policyDevelopment policy#Database policy
Python Code conventionsManual:Coding conventions/Python
Ruby Code conventionsManual:Coding conventions/Ruby
Selenium/Cucumber Code conventionsManual:Coding conventions/Selenium
Java Code conventionsManual:Coding conventions/Java
API client code Standards for API client librariesAPI:Client code/Gold standard