|
Contributing to python-apt |
|
========================== |
|
:Author: Julian Andres Klode <[email protected]> |
|
:Release: |release| |
|
:Date: |today| |
|
|
|
Let's say you need a new feature, you can develop it, and you want to get it |
|
included in python-apt. Then be sure to follow the following guidelines. |
|
|
|
Available branches |
|
------------------- |
|
First of all, let's talk a bit about the git branches of python-apt. In the |
|
following parts, we will assume that you use git to create your changes and |
|
submit them. |
|
|
|
Repositories |
|
^^^^^^^^^^^^ |
|
|
|
https://salsa.debian.org/apt-team/python-apt.git |
|
|
|
This is the official Debian repository of python-apt. |
|
You can clone it using git by doing:: |
|
|
|
git clone git://salsa.debian.org/apt-team/python-apt.git |
|
|
|
|
|
All code which will be uploaded to Debian is here. |
|
There are also branches for Ubuntu releases, but those may not be up-to-date. |
|
|
|
Branch names consist of the distribution vendor, followed by a slash, |
|
followed by the release of that distribution, for example: ``debian/sid``. |
|
|
|
The current working branch is usually pointed to by ``HEAD``, it is |
|
either ``debian/sid`` or ``debian/experimental``. |
|
|
|
If both sid and experimental are active, bug fixes are either cherry-picked from |
|
``debian/experimental`` to ``debian/sid``, or a new release is cut on the sid branch |
|
and then merged into experimental. |
|
|
|
Updates to stable release branches, such as ``debian/wheezy``, are almost always |
|
cherry-picked or backported from the ``debian/sid`` branch. |
|
|
|
|
|
.. highlight:: cpp |
|
|
|
C++ Coding style |
|
---------------- |
|
This document gives coding conventions for the C++ code comprising |
|
the C++ extensions of Python APT. Please see the companion |
|
informational PEP describing style guidelines for Python code (:PEP:`8`). |
|
|
|
Note, rules are there to be broken. Two good reasons to break a |
|
particular rule: |
|
|
|
(1) When applying the rule would make the code less readable, even |
|
for someone who is used to reading code that follows the rules. |
|
|
|
(2) To be consistent with surrounding code that also breaks it |
|
(maybe for historic reasons) -- although this is also an |
|
opportunity to clean up someone else's mess (in true XP style). |
|
|
|
This part of the document is derived from :PEP:`7` which was written by |
|
Guido van Rossum. |
|
|
|
|
|
C++ dialect |
|
^^^^^^^^^^^ |
|
|
|
- Use ISO standard C++ (the 2011 version of the standard), headers |
|
should also adhere to the 1998 version of the standard. |
|
|
|
- Use C++ style // one-line comments for single-line comments. |
|
|
|
- No compiler warnings with ``gcc -std=c++11 -Wall -Wno-write-strings``. There |
|
should also be no errors with ``-pedantic`` added. |
|
|
|
|
|
Code lay-out |
|
^^^^^^^^^^^^ |
|
|
|
- Use 3-space indents, in files that already use them. In new source files, |
|
that were created after this rule was introduced, use 4-space indents. |
|
|
|
At some point, the whole codebase may be converted to use only |
|
4-space indents. |
|
|
|
- No line should be longer than 79 characters. If this and the |
|
previous rule together don't give you enough room to code, your |
|
code is too complicated -- consider using subroutines. |
|
|
|
- No line should end in whitespace. If you think you need |
|
significant trailing whitespace, think again -- somebody's |
|
editor might delete it as a matter of routine. |
|
|
|
- Function definition style: function name in column 2, outermost |
|
curly braces in column 1, blank line after local variable |
|
declarations:: |
|
|
|
static int extra_ivars(PyTypeObject *type, PyTypeObject *base) |
|
{ |
|
int t_size = PyType_BASICSIZE(type); |
|
int b_size = PyType_BASICSIZE(base); |
|
|
|
assert(t_size >= b_size); /* type smaller than base! */ |
|
... |
|
return 1; |
|
} |
|
|
|
- Code structure: one space between keywords like 'if', 'for' and |
|
the following left paren; no spaces inside the paren; braces as |
|
shown:: |
|
|
|
if (mro != NULL) { |
|
... |
|
} |
|
else { |
|
... |
|
} |
|
|
|
- The return statement should *not* get redundant parentheses:: |
|
|
|
return Py_None; /* correct */ |
|
return(Py_None); /* incorrect */ |
|
|
|
- Function and macro call style: ``foo(a, b, c)`` -- no space before |
|
the open paren, no spaces inside the parens, no spaces before |
|
commas, one space after each comma. |
|
|
|
- Always put spaces around assignment, Boolean and comparison |
|
operators. In expressions using a lot of operators, add spaces |
|
around the outermost (lowest-priority) operators. |
|
|
|
- Breaking long lines: if you can, break after commas in the |
|
outermost argument list. Always indent continuation lines |
|
appropriately, e.g.:: |
|
|
|
PyErr_Format(PyExc_TypeError, |
|
"cannot create '%.100s' instances", |
|
type->tp_name); |
|
|
|
- When you break a long expression at a binary operator, the |
|
operator goes at the end of the previous line, e.g.:: |
|
|
|
if (type->tp_dictoffset != 0 && base->tp_dictoffset == 0 && |
|
type->tp_dictoffset == b_size && |
|
(size_t)t_size == b_size + sizeof(PyObject *)) |
|
return 0; /* "Forgive" adding a __dict__ only */ |
|
|
|
- Put blank lines around functions, structure definitions, and |
|
major sections inside functions. |
|
|
|
- Comments go before the code they describe. |
|
|
|
- All functions and global variables should be declared static |
|
unless they are to be part of a published interface |
|
|
|
|
|
Naming conventions |
|
^^^^^^^^^^^^^^^^^^ |
|
|
|
- Use a ``Py`` prefix for public functions; never for static |
|
functions. The ``Py_`` prefix is reserved for global service |
|
routines like ``Py_FatalError``; specific groups of routines |
|
(e.g. specific object type APIs) use a longer prefix, |
|
e.g. ``PyString_`` for string functions. |
|
|
|
- Public functions and variables use MixedCase with underscores, |
|
like this: ``PyObject_GetAttr``, ``Py_BuildValue``, ``PyExc_TypeError``. |
|
|
|
- Internal functions and variables use lowercase with underscores, like |
|
this: ``hashes_get_sha1.`` |
|
|
|
- Occasionally an "internal" function has to be visible to the |
|
loader; we use the _Py prefix for this, e.g.: ``_PyObject_Dump``. |
|
|
|
- Macros should have a MixedCase prefix and then use upper case, |
|
for example: ``PyString_AS_STRING``, ``Py_PRINT_RAW``. |
|
|
|
|
|
Documentation Strings |
|
^^^^^^^^^^^^^^^^^^^^^ |
|
- The first line of each function docstring should be a "signature |
|
line" that gives a brief synopsis of the arguments and return |
|
value. For example:: |
|
|
|
PyDoc_STRVAR(myfunction__doc__, |
|
"myfunction(name: str, value) -> bool\n\n" |
|
"Determine whether name and value make a valid pair."); |
|
|
|
The signature line should be formatted using the format for function |
|
annotations described in :PEP:`3107`, whereas the annotations shall reflect |
|
the name of the type (e.g. ``str``). The leading ``def`` and the trailing |
|
``:`` as used for function definitions must not be included. |
|
|
|
Always include a blank line between the signature line and the |
|
text of the description. |
|
|
|
If the return value for the function is always ``None`` (because |
|
there is no meaningful return value), do not include the |
|
indication of the return type. |
|
|
|
- When writing multi-line docstrings, be sure to always use |
|
string literal concatenation:: |
|
|
|
PyDoc_STRVAR(myfunction__doc__, |
|
"myfunction(name, value) -> bool\n\n" |
|
"Determine whether name and value make a valid pair."); |
|
|
|
|
|
Python Coding Style |
|
------------------- |
|
The coding style for all code written in python is :PEP:`8`. Exceptions from |
|
this rule are the documentation, where code is sometimes formatted differently |
|
to explain aspects. |
|
|
|
When writing code, use tools like pylint, pyflakes, pychecker and pycodestyle |
|
(all available from Debian/Ubuntu) to verify that your code is |
|
OK. Fix all the problems which seem reasonable, and mention the unfixed issues |
|
when asking for merge. |
|
|
|
All code must work on both Python 2 and Python 3. |
|
|
|
Submitting your patch |
|
--------------------- |
|
First of all, the patch you create should be based against the most current |
|
branch of python-apt (debian/sid or debian/experimental). If it is a bugfix, |
|
you should probably use debian/sid. If you choose the wrong branch, we will |
|
ask you to rebase your patches against the correct one. |
|
|
|
Once you have made your change, check that it: |
|
|
|
* conforms to :PEP:`8` (checked with pycodestyle). It should, at least not |
|
introduce new errors. (and never have whitespace at end of line) |
|
* produces no new errors in pychecker, pyflakes and pylint (unless you |
|
can't fix them, but please tell so when requesting the merge, so it can |
|
be fixed before hitting one of the main branches). |
|
* does not change the behaviour of existing code in a non-compatible way. |
|
* works on both Python 2 and Python 3. |
|
|
|
If your change follows all points of the checklist, you can commit it to your |
|
repository. (You could commit it first, and check later, and then commit the |
|
fixes, but commits should be logical and it makes no sense to have to commits |
|
for one logical unit). |
|
|
|
The changelog message should follow standard git format. At the end of the |
|
message, tags understood by gbp-dch and other tags may be added. An example |
|
commit message could be: |
|
|
|
.. code-block:: none |
|
|
|
apt.package: Fix blah blah |
|
|
|
Fix a small bug where foo is doing bar, but should be doing baz |
|
instead. |
|
|
|
Closes: #bugnumber |
|
LP: #ubuntu-bug-number |
|
Reported-By: Bug Reporter Name <[email protected]> |
|
|
|
|
|
Once you have made all your changes, you can run ``git format-patch``, |
|
specifying the upstream commit or branch you want to create patches |
|
against. Then you can either: |
|
|
|
* report a bug against the python-apt package, attach the patches |
|
you created in the previous step, and tag it with 'patch'. It might also be |
|
a good idea to prefix the bug report with '[PATCH]'. |
|
|
|
* send the patches via ``git send-email``. |
|
|
|
For larger patch series, you can also publish a git branch on a |
|
public repository and request it to be pulled. |
|
|
|
If you choose that approach, you may want to base your patches against |
|
the latest release, and not against some random commit, for the sake of |
|
preserving a sane git history. |
|
|
|
Be prepared to rebase such a branch, and close any bugs you fix in the |
|
branch by mentioning them in the commit message using a Closes or LP |
|
tag. |
|
|
|
|
|
Documentation updates |
|
--------------------- |
|
If you want to update the documentation, please follow the procedure as written |
|
above. You can send your content in plain text, but reStructuredText is the |
|
preferred format. I (Julian Andres Klode) will review your patch and include |
|
it. |
|
|
|
.. highlight:: sh |
|
|
|
Example patch session |
|
---------------------- |
|
In the following example, we edit a file, create a patch (an enhanced |
|
patch), and report a wishlist bug with this patch against the python-apt |
|
package:: |
|
|
|
user@ pc:~$ git clone git://anonscm.debian.org/apt/python-apt.git |
|
user@pc:~$ cd python-apt |
|
user@pc:~/python-apt$ editor FILES |
|
user@pc:~/python-apt$ pycodestyle FILES # Check with pycodestyle |
|
user@pc:~/python-apt$ pylint -e FILES # Check with pylint |
|
user@pc:~/python-apt$ pyflakes FILES # Check with pyflakes |
|
user@pc:~/python-apt$ pychecker FILES # Check with pychecker |
|
user@pc:~/python-apt$ git commit -p |
|
user@pc:~/python-apt$ git format-patch origin/HEAD |
|
user@pc:~/python-apt$ reportbug --severity=wishlist --tag=patch --attach=<patch> ... python-apt |
|
|
|
You may also send the patches to the mailing list instead of |
|
reporting the bug:: |
|
|
|
user@pc:~/python-apt$ git send-email [email protected] <patches created by format-patch> |
|
|
|
You can even push your changes to your own repository and request |
|
a pull request. |
|
|