Getting the Source
You will need to install a
Mercurial client first.
On the command line
Once you have Mercurial, checkout the entire project:
$ hg clone https://hg.codeplex.com/csb CSB
This will create a project called "CSB" in the current directory. For committing any changes, you will also need to provide your CodePlex username and password.
Using Eclipse
Install the PyDev and MercurialEclipse plugins (you still need a separate Mercurial client, so don't skip that). Once you are done, checkout the entire project:
File / New / Project... / Mercurial / Clone Existing Mercurial Repository
In the URL field enter "https://hg.codeplex.com/csb" and use your CodePlex username and password.
Building
Use
csb.build to build, test and package the entire project:
$ python csb/build.py -o <output directory>
Full details are provided
here.
Testing
You should run the complete test suite before each commit. All CSB tests are executed with the
csb.test.Console. To execute all tests:
$ python csb/test/app.py "csb.test.cases.*"
or just:
$ python csb/test/app.py
To execute test suites for specific modules only:
$ python csb/test/app.py "csb.test.cases.module1.*" "csb.test.cases.module2"...
Run with "-h" for help. For more details on our test framework, including guidelines for writing
unit test, please refer to the
API documentation, package
csb.test.
Note: on python 2.6 make sure you have the unittest2 package.
You should also test the syntax of your docstrings before each commit:
$ epydoc --html -v -o /tmp --name CSB --fail-on-error --fail-on-warning --fail-on-docstring-warning csb
For convenience, you can run
test.sh before pushing code to the repository to make sure that all test cases and docstring checks pass.
Methodology
We have embraced a Test-driven development (TDD) approach. That is, all new features and bug fixes must be accompanied by corresponding test cases in a subpackage of
csb.test.cases. For more details on this topic please read the
API documentation, package
csb.test.
Style Guide
Compatibility
- make sure your code is cross-platform (Windows, Linux, Mac)
- make sure your code is cross-interpreter compatible (python 2.6+: 2.6, 2.7, 3.1, 3.2...)
To ensure cross-interpreter compatibility, please write Python 3 compatible code. In the rare event that a given construct in Python 3 is not backwards compatible with Python 2.6, please ensure portability by following these guidelines:
- you shouldn't feel the need to use print in CSB (even in apps); but if really necessary, import and use the print function (print())
- use csb.io.Pickle, csb.io.MemoryStream and csb.io.urllib instead of importing the standard library modules (details in csb.io)
- use csb.core.string for string isinstance checks and csb.core.metaclass() to define metaclass inheritance (details in csb.core)
Commit Messages
You should always provide a message for each commit. Commit comments should follow the general Mercurial guidelines:
- the first line should be a complete, independent sentence, which summarizes all changes
- next lines should give as much detail about affected modules as possible
- if resolving an issue, include the issue number
Here is a sample commit comment:
Fixed issue #00010: SomeObject crashes with an exception for structures with no title
csb.bio.structure:
- added a new Structure.xxxx property
csb.bio.io.wwpdb:
- SomeObject will now check for empty titles
csb.test.cases.bio.io.wwpdb:
- added regression tests
Coding Style, Commenting and Formatting
Format your code using 4-spaces indentation (not tabs). In Eclipse just use Ctrl+Shift+F.
Your code should follow the PEP8 style guide strictly. Here is a summary:
- ClassName
- method_name or function_name; the only exception are test methods: testMethodName
- variable_name
- property_name
- CONSTANT_NAME
Additional requirements:
- _internal_method, _internal_field -- unencapsulated classes are not allowed (except if defining a simple struct); mark private methods and fields with a single or double underscore
- @property, @property.setter -- getters and setters are not allowed; use @property to expose a private field
- str.format() -- avoid using the deprecated "%" operator
- super(ChildClass, self).method() -- do not use the deprecated ParentClass.method()
- always define all instance variables in the constructor of a class
- always derive classes from object explicitly
- define abstract classes with ABCMeta, @abstractmethod, @abstractproperty
- organize imports at the top of each module; avoid private imports
- provide an Epydoc docstring for each public class, method, property
- provide an Epydoc docstring for each module
- prefer short, clean, obvious code and design patterns over writing comments
- always prefix static fields and methods with the corresponding class name; do not access static fields/methods with self or hide static fields/methods within derived classes
Here is a code template:
"""
Module short summary.
Module multi-line description...
"""
import module1
import module2
from module3 import ObjectOne, ObjectTwo
from module4 import ObjectThree
class ClassName(object):
"""
Class description...
... ends here.
@param param_name: description
@type param_name: L{SomeObject} or built-in (str, int, etc)
"""
__metaclass__ = ABCMeta
CONSTANT_NAME = value
def __init__(self, param_name):
self._private_field = None
@property
def property_name(self):
"""
Description...
"""
return self._private_field
@property_name.setter
def property_name(self, value):
# validate value here...
self._property_name = value
def method_name(self, param_name)
"""
Description...
@param param_name: description
@type param_name: L{SomeObject} or built-in (str, int, etc)
@return: description of @rtype
@rtype: L{SomeObject} or built-in (str, int, etc)
@raise ExceptionName: condition
"""
(body)
@abstractmethod
def abstract_method_name(self, param_name):
"""
(docstring)
"""
pass
@staticmethod
def static_method_name(param_name):
"""
(docstring)
"""
(body)