Official Resource For Writing Proper Visualizer Code

Importing Modules

Module imports should all appear at the very top of the file unless there is a good reason not to (e.g. a user selects if he wants OpenGL or DirectX rendering (!!NOT A SUPPORTED FEATURE!!) ).

from module import * is never acceptable. This can cause name conflicts, and makes it more difficult to determine the origin of objects. For example:

from application import *
from renderer import *
from widgets import *

r = Rectangle()

makes it impossible to determine that Rectangle came from the module, renderer. This is preferred:

from application import Application
from renderer import Renderer, Rectangle
from widgets import Button

r = Rectangle()

or:

import application
import renderer
import widgets

r = renderer.Rectangle()

In these cases, the origin of Rectangle is clearly visible.

Docstrings

Proper docstrings are required on all public methods (i.e. methods that do not start with a single underscore), and are suggested for usage with all private methods. These docstrings generate the documentation used by sphinx and are easy-to-read when just reading code. If someone ever has to look at the source to determine how to use a certain module, then the docstring is not clear enough.

Docstrings should try to follow the following format:

def sum(arg1, arg2, arg3=0):
    '''
    Short one line description of FUNCTIONality (puns are encouraged)

    More detailed description of this function.
    For docstring maintainability reasons, there is no 80 character limit imposed on these, but logical breaks are encouraged for readability.
    Trying to edit an existing paragraph that wraps at 80 characters, no matter what causes time lost in trying to re-organize everything.
    Your editor should, hopefully word-wrap these.

    :param arg1: first number to be added with
    :param arg2: second number to add
    :type arg2: int
    :param arg3: optional third number to add.
    :type arg3: float

    :raises: TypeError if NoneType passed in for arg3

    :rtype: float
    '''
    # function

Variable/Module Organization

Whenever groups of variables are present, their ordering should follow the following rule:

Variables should be alphabetized when there is no prevailing convention for their order.
Otherwise, the existing conventions should be kept.
Alphabetize when possible.

The most common example of this is width and height. While width follows height, alphabetically, the prevailing convention is that we state width before height (probably because they’re analogues to x and y coordinates). So this:

BORDER_COLOR = (1, 1, 1, 1)
BORDER_DASHED = True

ENTRY_ONE = '1'
ENTRY_TWO = '2'
ENTRY_THREE = '3'
ENTRY_FOUR = '4'
ENTRY_FIVE = '5'

WINDOW_X = 12
WINDOW_Y = 15
WINDOW_WIDTH = 640
WINDOW_HEIGHT = 480

XYLOPHONE_SOUND = 'funny'

is preferred to this:

BORDER_COLOR = (1, 1, 1, 1)
BORDER_DASHED = True

ENTRY_FOUR = '4'
ENTRY_FIVE = '5'
ENTRY_ONE = '1'
ENTRY_THREE = '3'
ENTRY_TWO = '2'

WINDOW_HEIGHT = 480
WINDOW_WIDTH = 640
WINDOW_X = 12
WINDOW_Y = 15

XYLOPHONE_SOUND = 'funny'

Likewise, modules should almost always be alphabetized, unless there is a strict ordering needed (hopefully we didn’t write that library).

Online Poll Of This Issue

List Comprehensions vs Loops

Some of you may be tempted to use a list comprehension to perform the task of a loop because... well, I don’t know why. I’ve just seen this places and it confuses me. I’m talking about this:

class Object(object):
    # code
    def print(self):
        print(self.value)

list_of_objects = [Object(blah), Object(blerg), Object(foo), Object(bar), Object(spam), ... ]

[i.print() for i in list_of_objects]

instead of:

for i in list_of_objects:
    i.print()

Functionally, they complete the same task, but there’s reasons not to do the first one. First of all, it’s bad python. Plain and simple you’re over-complicating things. You’re using a list comprehension to do something it wasn’t born to do. List comprehensions are for building lists and they do it pretty quickly. They are not, however, very good at iterating though items and running code. That’s because when you run a for loop, there’s no implied list being built. I see zero advantages for doing it this way, so don’t. List comprehensions should be used for building lists that are to be used and nothing else. Use your tab key and build a loop instead.

Commit Messages

Commit messages should try to follow this model:

Capitalized, short (50 chars or less) summary

More detailed explanatory text, if necessary.  Wrap it to about 72
characters or so.  In some contexts, the first line is treated as the
subject of an email and the rest of the text as the body.  The blank
line separating the summary from the body is critical (unless you omit
the body entirely); tools like rebase can get confused if you run the
two together.

Write your commit message in the present tense: "Fix bug" and not "Fixed
bug."  This convention matches up with commit messages generated by
commands like git merge and git revert.

Further paragraphs come after blank lines.

- Bullet points are okay, too

- Typically a hyphen or asterisk is used for the bullet, preceded by a
single space, with blank lines in between, but conventions vary here

- Use a hanging indent

Taken from http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html

See that post for reasons.

Exceptions

Raising exceptions should occur in Python 3.x fashion:

raise CustomException('data')

instead of:

raise CustomException, 'data'

This is for stylistic reasons and to become accustomed with the python 3.x format. Exceptions are classes and should be treated as such.