~gtg-contributors/gtg/tracks

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
=================
GTG Hacking Guide
=================

Code reference documentation is online at:

   http://allievi.sssup.it/GTG/


Testing
-------

You can run the unit tests for GTG with::

  make check

If you are so inclined and have the right software installed, you can also run
the tests with ``trial GTG``.

You can also manually test your changes with debugging data with::

  ./scripts/debug.sh

Using ``debug.sh`` will prevent GTG from messing with your real data. Instead,
the debug GTG will store data in ``./tmp/default/``.

Unit tests live in ``GTG/tests/``, and are all named ``test_foo``. When you
add a new test module, make sure it has a ``test_suite()`` method that returns
the suite of all the tests in that module. Also make sure that the new module
is imported in ``GTG.tests`` and returned from the ``test_suite()`` function
there.

For example, GTG/tests/test_newthing.py::

  import unittest

  class TestNewThing(unittest.TestCase):
      # ...

  def test_suite():
      return unittest.TestLoader().loadTestsFromName(__name__)


And GTG/tests/__init__.py::

  import unittest

  from GTG.tests import test_backends, test_newthing

  def test_suite():
      return unittest.TestSuite([
          test_backends.test_suite(),
          test_newthing.test_suite(),
          ])

When in doubt, copy from an existing test module!


Coding style
------------

In general, follow PEP 8 <http://www.python.org/dev/peps/pep-0008/>.

Not all code in GTG currently follows PEP 8. If you are changing a section of
code, please update it to follow PEP 8.

You should also avoid adding any 'flakes', simple Python mistakes caught by
Pyflakes <http://www.divmod.org/trac/wiki/DivmodPyflakes>.

To check the cleanliness of your code, run::

  make lint

The ``make`` will fail if Pyflakes emits any warnings. You can the Pyflakes
checker separately using ``make pyflakes`` and the PEP 8 checker using ``make
pep8``. If you wish to find all PEP 8 violations in a particular file, use::

  ./scripts/pep8.py --repeat FILENAME


Commenting-out Code
-------------------
Try to avoid leaving commented out code in the codebase.  Or at least,
if some code must be left commented out, also include a comment
or TODO or FIXME explaining why it was disabled.  If possible include a
bug lp#.

Some common reasons why one might create commented code are:

 a.  I was unsure of my fix
 b.  I wasn't sure what the original code was supposed to do
 c.  I needed to disable it to work around some problem
 d.  I removed or broke other code that this code depends on
 e.  I started implementing something but haven't finished it yet
 f.  I need this for debugging problems that might still exist

Obviously none of these are great situations to be in, but it happens.

Ideally, commenting out a line of code should be a signal to yourself
that one of these things has happened, and that you probably should ask
for help before merging it to trunk, and it should stay in a branch for
now.

But that may not always be possible.  So more practically, when
commenting out code please ALWAYS explain why you commented it out.
This enables other developers (who may know the code better) to figure
out and solve the problem.

So instead of this:

  #foo.animate(x)

consider doing it like this:

  #FIXME:  If x is None, it causes animate() to crash.  But x should
  #never be None, so this *should* always work.  I can't reproduce the 
  #crash so can't tell what makes x None.  Leaving it disabled for now
  #until someone can reproduce it and investigate.  (LP: #12345)
  #
  #foo.animate(x)

Especially, avoid commented out code used for debugging.  Instead of
this:

  #print "Testing: ", 1, 2, 3

consider doing it like this:

  Log.debug("Testing %d %d %d", 1, 2, 3)

Historically, there has been code left commented out in the codebase for
various reasons.  As you run across such code, please help us tidy the
codebase by either commenting why it's disabled, or remove it.


API Style
---------
Whereever possible, prefer using tid/tagname instead of passing task/tag
objects directly.  In experimentation it's been found that passing and
using the objects directly is very expensive.  Looking in a list of
objects is *much* slower than looking in a list of Strings.

If you create a method, try that that method take a tid/tagname as
argument and return a tid/tagname. (of course, don't apply this
blindly).

As a rule of thumb, if you put objects in a list for whatever purpose,
it should light a big warning sign ! It probably means than you have to
use the tid/tagname instead.

The req.get_task/get_tag methods are pretty cheap (access to a
dictionary with Strings as keys) and, anyway, I discovered that a lot of
functions can already be done without the object at all if you are
consistent.

In existing tag/task object, don't hesitate to port existing functions
that does not respect that philosophy but should. (this work should take
place in gtg-refactor branch).


Copyright
---------

All modules should begin with the following header::

# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Gettings Things Gnome! - a personal organizer for the GNOME desktop
# Copyright (c) 2008-2010 - Lionel Dricot & Bertrand Rousseau
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program.  If not, see <http://www.gnu.org/licenses/>.
# -----------------------------------------------------------------------------


Submitting Patches
------------------

For information about contributing code to GTG, see
<http://live.gnome.org/gtg/contributing>.


Landing Branches
----------------

  1. Get the branch.

  2. Run the tests, ``make check``.

  3. Run ``make lint``, check that the number of PEP 8 warnings is lower than
     trunk and that there are no new pyflakes warnings.

  4. Launch GTG with debugging data, just in case, ``./scripts/debug.sh``.

  5. Update ``CHANGELOG`` if it isn't already.

  6. Update ``AUTHORS`` if the patch author is not already in there.

  7. Merge the branch into trunk, then commit!


Documentation
-------------

We'd love it so much if you could improve the docstrings that you find in GTG.

We use the docstring conventions outlined in PEP 8
<http://www.python.org/dev/peps/pep-0008/> and PEP 257
<http://www.python.org/dev/peps/pep-0257/>, except modified to support epytext
markup. Information on epytext markup can be found at
<http://epydoc.sourceforge.net/epytext.html>.

You can generate the API docs by installing pydoctor
(``python-pydoctor`` in debian/ubuntu) and then running::

  make apidocs

This builds the API documentation inside ``doc/api`` in your working tree. If
you are running GNOME, you can open it in your browser with::

  gnome-open doc/api/index.html

You can also run::

  make edit-apidocs

To launch a pydoctor server at http://localhost:8080/ that will let you edit
API documentation in place. The feature has a few rough edges, but can be
really useful for editing and extending API docs. To actually apply your edits
to the tree::

  wget http://localhost:8080/rawBigDiff -q -O- | bzr patch

Remember, docstrings should be written for people who don't know much about
the code. Focus on ''why'' things are the way they are, and on describing
''what'' they are in the first place.