summaryrefslogtreecommitdiff
path: root/HACKING.rst
blob: de4278376a03230c07a7cd8b7091dc047825a28f (plain)
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
Hacking on BuildStream
======================

Some tips and guidelines for developers hacking on BuildStream


Coding Style
------------
Coding style details for BuildStream


Style Guide
~~~~~~~~~~~
Python coding style for BuildStream is pep8.

This is documented here:
    https://www.python.org/dev/peps/pep-0008/

You may find deviances from this standard in the sources, if so
then feel free to file that as a bug and it will be fixed.


Imports
~~~~~~~
Module imports inside BuildStream are done with . notation

Good:

  from .context import Context

Bad:

  from buildstream.context import Context

The exception to the above rule is when authoring plugins,
plugins do not reside in the same namespace so they must
address buildstream in the imports.

An element plugin will derive from Element by importing:

  from buildstream import Element

When importing utilities specifically, dont import random
function names from there, 


One Class One Module
~~~~~~~~~~~~~~~~~~~~
BuildStream is mostly Object Oriented with a few utility files.

Every object should go into it's own file (module) inside the
buildstream package, and it should be named after the class in lower
case with no underscore. This is to say a class named FooBar will
certainly reside in a file named foobar.py. Unless FooBar is private
in which case the file is of course _foobar.py.

When adding a public class, it should be imported in toplevel __init__.py
so that buildstream consumers can import it directly from the buildstream
package, without requiring knowledge of the BuildStream package structure,
which is allowed to change over time.


Private API
~~~~~~~~~~~
BuildStream strives to guarantee a minimal and comprehensive public API
surface both for embedders of the BuildStream pipeline and implementors
of custom plugin Elements and Sources.

Python does not have a real concept of private API, but as a convention
anything which is private uses an underscore prefix.

Principle of least underscores:

* If a module is entirely private, there is no need for the classes
  it contains to have a leading underscore.
* If a class is entirely private, there is no need to mark it's members
  as private with leading underscores.


Documenting BuildStream
-----------------------
BuildStream starts out as a documented project from day one and uses
sphinx to document itself.

Useful links:

* Sphinx documentation: http://www.sphinx-doc.org/en/1.4.8/contents.html
* rst primer: http://www.sphinx-doc.org/en/stable/rest.html


Building Docs
~~~~~~~~~~~~~
To build the current set of docs, enter the docs directory and type `make`

This will give you a build/html directory with the html docs.


Documenting Conventions
~~~~~~~~~~~~~~~~~~~~~~~
When adding a new class to the buildstream core, an entry referring to
the new module where the new class is defined should be added to
the toplevel index manually in doc/source/index.rst.

We use the sphinx.ext.napoleon extension for the purpose of having
a bit nicer docstrings than the default sphinx docstrings.

A docstring for a method, class or function should have the following
format::

   """Brief description of entity

   Args:
      argument1 (type): Description of arg
      argument2 (type): Description of arg

   Returns:
      Description of returned thing indicating its type

   Raises:
      SomeError, SomeOtherError

   A detailed description can go here if one is needed, only
   after the above part documents the calling conventions.
   """


Testing BuildStream
-------------------
BuildStream uses pytest for regression tests and testing out
the behavior of newly added components.

The elaborate documentation for pytest can be found here:

    http://doc.pytest.org/en/latest/contents.html

Don't get lost in the docs if you don't need to, follow
existing examples instead.


Running Tests
~~~~~~~~~~~~~
To run the tests, just type:

  ./setup.py test

At the toplevel.

When debugging a test, it can be desirable to see the stdout
and stderr generated by a test, to do this use the --addopts
function to feed arguments to pytest as such:

  ./setup.py test --addopts -s


Adding Tests
~~~~~~~~~~~~
Tests are found in the tests/<domain>/ directory, all tests
are collected as tests/*/*.py

If the new test is not appropriate for the existing test domains,
then simply create a new directory for it under tests/

Various tests may include data files to test on, there are examples
of this in the existing tests. When adding data for a test, create
a subdirectory beside your test in which to store data.

When creating a test that needs data, use the datafiles extension
to decorate your test case (again, examples exist in the existing
tests for this), documentation on the datafiles extension can
be found here:

    https://pypi.python.org/pypi/pytest-datafiles