Coding Style
Posted: Wed Jul 11, 2012 1:56 am
One thing I learned while working with the GunGame5.1 dev team is that it is very important to all follow the same coding style. This thread is basically an outline of what I believe our style (Python-side) should be for all modules/APIs.
I am certain that most of you have heard of PEP 8, and some of you probably already adhere to at least part of its proposal. I would like us to follow this PEP as closely as possible. I would also say that PEP 257, which deals with documenting your code properly, is something that is not only recommended, but required. Some main points:
Most items under the Formatting section should be caught by the PEP8 checker:
http://pypi.python.org/pypi/pep8/
If anyone has any other proposals/issues/updates for this, please feel free to share your thoughts.
Satoon
I am certain that most of you have heard of PEP 8, and some of you probably already adhere to at least part of its proposal. I would like us to follow this PEP as closely as possible. I would also say that PEP 257, which deals with documenting your code properly, is something that is not only recommended, but required. Some main points:
- Naming conventions:
- Class names should use CamelCase
Syntax: Select all
class TestClass(object):
pass - No underscores in class names except for a leading underscore to mark as "private"
Syntax: Select all
class _PrivateTestClass(object):
pass - Constants must be ALL_CAPS with an underscore separating the words
Syntax: Select all
CONSTANT_VALUE = True
- Class attributes/properties/methods should be lower_case_with_underscores
Syntax: Select all
class TestClass(object):
def __init__(self, value1, value2):
self.value1 = value1
self._value2 = value2
@property
def value2(self):
return self._value2
def some_method(self):
return self.value1 + self.value2 - Singleton objects or "the instance" objects (objects that should be the one and only instance of a class) should also use lower_case_with_underscores
Syntax: Select all
class TestClass(object):
pass
test_class = TestClass() - All global variable objects (which are not constants) should also use lower_case_with_underscores
Syntax: Select all
start_value = True
- Any global variables created in the scope which are not to be imported by other modules should use a leading underscore
Syntax: Select all
_private_variable = False
- Only built-in magic methods should have 2 leading and trailing underscores
- ALL names should be very descriptive as to what the object does or is
- Class names should use CamelCase
- Formatting:
- Lines must be no longer than 80 characters (that includes the built-in \n, making it 79 characters of code)
- MUST use 4 space indentation, no TABs
- MUST have 2 blank lines prior to functions and classes
- If the function/class is starting a new <Section> (explained below), the blank lines need to be prior to the section separator
- All other lines should only have 1 blank line between
- An exception that is sometimes used is 2 blank lines prior to a <Section> change (explained below)
- No extra whitespace at the end of a line
- This also means that any "blank" lines should have absolutely nothing, not even spaces, in them
- Exactly 1 space between arguments (after the comma) for all functions/classes/methods, including when calling them
- No spaces at all when only 1 argument
- No leading space before first argument or trailing space after last argument
- Exactly one space after a : when setting an item in a dictionary
- There must be exactly one blank line at the end of the file
- Documentation:
- All classes/methods/properties/functions must be followed by a comment using a triple quote docstring (either apostrophes or quotes)
- Most lines of code should follow a one line comment (using the # character)
- Some exceptions apply, like comments that suffice for multiple lines
- Files should always start with the line:
Syntax: Select all
# ../<path from source-python directory>
- Different sections of code should be separated by the following lines (where <Section> should describe what is in the following section):
Syntax: Select all
# =============================================================================
# >> <Section>
# =============================================================================- Some examples of what <Section> types there are to be used:
- IMPORTS
- GLOBAL VARIABLES
- CLASSES
- FUNCTIONS
- Some examples of what <Section> types there are to be used:
- Import comments:
- Separate base Python imports (including site-packages) from Source.Python core imports with 1 blank line
- Use a comment line with 1 space after the # showing whether the current section is from Python or Source.Python
- Python imports should always go first, then Source.Python imports
- Separate each module by using a comment about which module is being imported (with 3 spaces after the # before the modules name)
- Modules should be listed in alphabetic order
- Core Source.Python modules (from C++, imported from Source) should be first among the Source.Python imports and should not have a comment
- Anything directly imported from the _libs directory (not one of its sub-directories) should follow the Core module imports and behave similarly
- Currently this only includes the "paths" module
- Example:
Syntax: Select all
# =============================================================================
# >> IMPORTS
# =============================================================================
# Python Imports
# Configobj
from configobj import ConfigObj
# OS
from os.path import dirname
from os.path import join
# Traceback
from traceback import format_exception
# Source.Python Imports
from Source import Engine
from Source import Shared
from paths import GAME_PATH
# Addons
from addons.manager import AddonManager
# Core
from core.decorators import BaseDecorator
# Events
from events.manager import EventRegistry
from events.decorator import Event
- Do's and Don'ts of Importing (the use of "Good" and "Bad" just show what is/isn't acceptable for "this" project. other people prefer to use the opposite, which is perfectly fine):
- Never import "all" from a module:
Syntax: Select all
# Bad
from something import *
# Good
from something import one_object
from something import second_object - For "most" imports, import each object individually, and on a separate line:
Syntax: Select all
# Bad
from os.path import dirname, join, curdir
# Good
from os.path import dirname
from os.path import join
from os.path import curdir
# "Ok", but use only when necessary
import os.path
import sys
- Never import "all" from a module:
Most items under the Formatting section should be caught by the PEP8 checker:
http://pypi.python.org/pypi/pep8/
If anyone has any other proposals/issues/updates for this, please feel free to share your thoughts.
Satoon