-
Notifications
You must be signed in to change notification settings - Fork 81
Contributing Style Guide
We write Python3.
We follow PEP8 conventions throughout all our Python code. Key principles include:
- Always use spaces for indentation. Four spaces make one tab.
- Maximum line length is 79 characters.
- Always encode source files in UTF-8.
Try to keep your imports small and only import those definitions of a module that you actually need in your script.
from django.views.generic import CreateView, TemplateView
If you, however, need many definitions from a single module it's more readable to import the module and call the definitions from the module.
Don't do:
from django.views.generic import (CreateView, TemplateView, ListView,
UpdateView, DeleteView)
Do this instead:
from django.views import generic as generic_views
(...)
generic_views.CreateView(...)
Never import *
from a module. This can significantly affect performance and might have other unwanted consequences.
Don't do this, ever:
from django.views import *
Use triple-double quotes for doc strings:
def get_members(self):
"""Returns all members"""
return self.members
Make interpolated strings readable:
"{org_name} has {num_members} members.".format(
org_name="Habitat for Humanity",
num_members=10
)
Never use string concatenation—it makes internationalisation impossible.
Always open files using a context manager. That way the file is always closed when the block finishes, even if an exception is raised at some point.
with open('some/path') as open_file:
file_content = open_file.read()
As used in this section "function" applies to methods, function, and generators.
A function must have a docstring, unless it meets all of the following criteria:
- not externally visible
- very short
- obvious
A docstring should give enough information to write a call to the function without reading the function's code. A docstring should describe the function's calling syntax and its semantics, not its implementation. For tricky code, comments alongside the code are more appropriate than using docstrings.
For large functions (functions longer than 20 lines), certain aspects of a function should be documented in special sections, listed below. Each section begins with a heading line, which ends with a colon. Sections should be indented two spaces, except for the heading.
Args:
: List each parameter by name. A description should follow the name, and be separated by a colon and a space. If the description is too long to fit on a single 80-character line, use a hanging indent of 2 or 4 spaces (be consistent with the rest of the file).
: The description should mention required type(s) and the meaning of the argument.
: If a function accepts *foo (variable length argument lists) and/or **bar (arbitrary keyword arguments), they should be listed as *foo and **bar.
Returns: (or Yields: for generators)
: Describe the type and semantics of the return value. If the function only returns None, this section is not required.
Raises:
: List all exceptions that are relevant to the interface.
def fetch_bigtable_rows(big_table, keys, other_silly_variable=None):
"""
Fetches rows from a Bigtable.
Retrieves rows pertaining to the given keys from the Table instance
represented by big_table. Silly things may happen if
other_silly_variable is not None.
Args:
big_table: An open Bigtable Table instance.
keys: A sequence of strings representing the key of each table row
to fetch.
other_silly_variable: Another optional variable, that has a much
longer name than the other args, and which does nothing.
Returns:
A dict mapping keys to the corresponding table row data
fetched. Each row is represented as a tuple of strings. For
example:
{'Serak': ('Rigel VII', 'Preparer'),
'Zim': ('Irk', 'Invader'),
'Lrrr': ('Omicron Persei 8', 'Emperor')}
If a key from the keys argument is missing from the dictionary,
then that row was not found in the table.
Raises:
IOError: An error occurred accessing the bigtable.Table object.
"""
pass
Classes should have a doc string below the class definition describing the class. If a large class has public attributes, they should be documented here in an Attributes section and follow the same formatting as a function's Args section.
class SampleClass(object):
"""
Summary of class here.
Longer class information....
Longer class information....
Attributes:
likes_spam: A boolean indicating if we like SPAM or not.
eggs: An integer count of the eggs we have laid.
"""
def __init__(self, likes_spam=False):
"""Inits SampleClass with blah."""
self.likes_spam = likes_spam
self.eggs = 0
def public_method(self):
"""Performs operation blah."""
The final place to have comments is in tricky parts of the code. If you're going to have to explain it at the next code review, you should comment it now. Complicated operations get a few lines of comments before the operations commence. Non-obvious ones get comments at the end of the line.
# We use a weighted dictionary search to find out where i is in
# the array. We extrapolate position based on the largest num
# in the array and the array size and then do binary search to
# get the exact number.
if i & (i-1) == 0: # true if i is a power of 2
To improve legibility, these comments should be at least 2 spaces away from the code.
On the other hand, never describe the code. Assume the person reading the code knows Python (though not what you're trying to do) better than you do.
# BAD COMMENT: Now go through the b array and make sure whenever i occurs
# the next element is i+1
Use the IDE or text editor you personally prefer.
The repository contains an EditorConfig file, which helps developers maintain consistent coding styles between different editors and IDEs. EditorConfig plugins are available for most editors:
Lint your code using Flake8 for potential errors before committing. Flake8 provider are available for several text editors:
- Vim: vim-flake8
- Sublime Text: SublimeLinter-flake8 (requires SublimeLinter)
- Atom: linter-flake8 (requires linter)
- Emacs: Flake8 works with flymake.
Airbnb has pulled together comprehensive ES6 and React guides that we follow for everything JavaScript.
Use ESLint to lint your JS code:
- Airbnb has a ESLint config companioning the style guide.
- Learn how to setup ESLint with Sublime Text
Visit our User Documentation to learn more about using the Cadasta Platform.
If you'd like to contribute to the Cadasta Platform, start with our Contributing Guidelines.
Cadasta Wiki Home | Developer Setup Guide
Cadasta.org | About Cadasta | YouTube | Twitter | Facebook
- Installing & Running
- Contributing
- Planning & Sprints
- Platform Development
- Testing
- Utilities
- Outreachy
- Platform Site Map
- User Flows and Wireframes
- Other
- Quick Start Guide
- Glossary
- Questionnaire Guide