1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
|
Developer's guide
#################
:Author: Ben Finney <ben+python@benfinney.id.au>
:Updated: 2022-02-18
VCS repository
==============
The official Version Control System (VCS) for this code base is the
Git repository at `the ‘python-daemon’ Pagure project`_.
You can submit your proposed changes as merge requests:
* Use your Pagure account and use the “pull request” feature.
* Subscribe to `the ‘python-daemon-devel’ discussion forum`_ and
direct us to a branch in your published fork.
.. _the ‘python-daemon’ Pagure project: https://pagure.io/python-daemon/
.. _the ‘python-daemon-devel’ discussion forum:
https://lists.alioth.debian.org/mailman/listinfo/python-daemon-devel
Project layout
==============
::
./ Top level of source tree
doc/ Project documentation
bin/ Executable programs
daemon/ Main ‘daemon’ library
test/ Unit tests
Code style
==========
Python
------
All Python code should conform to the guidelines in :PEP:`8` and :PEP:`257`.
In particular:
Indentation
+++++++++++
* Indent each level using 4 space characters (``U+0020 SPACE``).
* Indent continuation lines two levels (8 spaces). This will help
distinguish them from adjacent code blocks indented one level.
Do not attempt to align continuation lines with characters on the
previous line.
* Do not insert TAB (``U+0008 CHARACTER TABULATION``) characters into
source code. This allows the code to render the same in different
programs, and improves the ability to cut-and-paste the code.
Example::
flim = flambake(
foo=eeny.meeny.miney.moe.Catcher(),
bar="eggs", baz="spam")
found_anomolous_wibble = False
for wibble in flim:
if wibble in [
zork for zork in zorkulate(wibble)]:
found_anomolous_wibble = True
break
wibble_accumulator.append(wibble)
zinkify(wibble_accumulator)
Naming
++++++
* Name modules in lower case, ``multiplewordslikethis``.
* Name classes in title case, ``MultipleWordsLikeThis``.
* Name functions, instances, and other variables in lower case,
``multiplewordslikethis`` or ``multiple_words_like_this``.
* Do not choose ``camelCaseNames``, which are inconsistently
capitalised.
Documenting code
++++++++++++++++
* Every module, class, and function has a Python doc string explaining
its purpose and API.
*Exception*: Functions whose purpose and API are mandated by Python
itself (dunder-named methods) do not need a doc string.
* Every doc string conforms to :PEP:`257`. Additionally:
* The text of the doc string is marked up with reStructuredText.
* The first line is a one-line synopsis of the object. This summary
line appears on the same line as the opening triple-quote,
separated by a single space.
* Further lines, if needed, are separated from the first by one
blank line.
* The synopsis is separated by one space from the opening
triple-quote; this causes it to appear four columns past the
beginning of the line. All subsequent lines are indented at least
four columns also.
* The synopsis is followed by a reStructuredText field list. The
field names are: “param foo” for each parameter (where “foo” is
the parameter name), and “return” for the return value. The field
values describe the purpose of each.
* The closing triple-quote appears on a separate line.
Example::
def frobnicate(spam, algorithm="dv"):
""" Perform frobnication on the `spam` travortionate.
:param spam: A travortionate (as a sequence of strings).
:param algorithm: The name of the algorithm to use for
frobnicating the travortionate.
:return: The frobnicated travortionate, if it is
non-empty; otherwise ``None``.
The frobnication is done by the Dietzel-Venkman algorithm,
and optimises for the case where `spam` is freebled and
agglutinative.
"""
spagnify(spam)
# …
Import statements
+++++++++++++++++
* All ``import`` statements appear at the top of the module.
* Each ``import`` statement imports a single module, or (using
``from``) multiple names from a single module.
Example::
import sys
import os
from spam import (foo, bar, baz)
Additional style guidelines
+++++++++++++++++++++++++++
* All text files (including program code) are encoded in UTF-8.
* A page break (``U+000C FORM FEED``) whitespace character is used
within a text file to break up semantically separate areas of the
module.
* Editor hints for Emacs and Vim appear in a comment block at the
file's end.
For Python source code::
# Local variables:
# coding: utf-8
# mode: python
# End:
# vim: fileencoding=utf-8 filetype=python :
For reStructuredText documents::
# Local variables:
# coding: utf-8
# mode: text
# mode: rst
# End:
# vim: fileencoding=utf-8 filetype=rst :
Unit tests
==========
All code should aim for 100% coverage by unit tests. New code, or
changes to existing code, will only be considered for inclusion in the
development tree when accompanied by corresponding additions or
changes to the unit tests.
Test-driven development
-----------------------
Where possible, practice test-driven development to implement program
code.
* During a development session, maintain a separate window or terminal
with the unit test suite for the project running continuously, or
automatically every few seconds.
* Any time a test is failing, the only valid change is to make all
tests pass.
* Develop new interface features (changes to the program unit's
behaviour) only when all current tests pass.
* Refactor as needed, but only when all tests pass.
* Refactoring is any change to the code which does not alter its
interface or expected behaviour, such as performance
optimisations, readability improvements, modularisation
improvements etc.
* Develop new or changed program behaviour by:
* *First* write a single, specific test case for that new behaviour,
then watch the test fail in the absence of the desired behaviour.
* Implement the minimum necessary change to satisfy the failing
test. Continue until all tests pass again, then stop making
functional changes.
* Once all tests (including the new test) pass, consider refactoring
the code and the tests immediately, then ensure all the tests pass
again after any changes.
* Iterate for each incremental change in interface or behaviour.
Test-driven development is not absolutely necessary, but is the
simplest, most direct way to generate the kind of program changes
accompanied by unit tests that are necessary for inclusion in the
project.
..
This document is written using `reStructuredText`_ markup, and can
be rendered with `Docutils`_ to other formats.
.. _Docutils: https://docutils.sourceforge.io/
.. _reStructuredText: https://docutils.sourceforge.io/rst.html
..
This is free software: you may copy, modify, and/or distribute this work
under the terms of the Apache License version 2.0 as published by the
Apache Software Foundation.
No warranty expressed or implied. See the file ‘LICENSE.ASF-2’ for details.
..
Local variables:
coding: utf-8
mode: text
mode: rst
time-stamp-format: "%:y-%02m-%02d"
time-stamp-start: "^:Updated:[ ]+"
time-stamp-end: "$"
time-stamp-line-limit: 20
End:
vim: fileencoding=utf-8 filetype=rst :
|