1+ ***************
2+ Version Control
3+ ***************
4+
5+ svn checkouts
6+ =============
7+
8+ Checking out everything in the trunk (matplotlib and toolkits)::
9+
10+ svn co https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/trunk \
11+ matplotlib --username=youruser --password=yourpass
12+
13+ Checking out the main source::
14+
15+ svn co https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/trunk/\
16+ matplotlib matplotlib --username=youruser --password=yourpass
17+
18+ Branch checkouts, eg the maintenance branch::
19+
20+ svn co https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/\
21+ v0_91_maint mplv0_91_maint
22+
23+ Committing changes
24+ ==================
25+
26+ When committing changes to matplotlib, there are a few things to bear
27+ in mind.
28+
29+ * if your changes are non-trivial, please make an entry in the
30+ CHANGELOG
31+ * if you change the API, please document it in API_CHANGES, and
32+ consider posting to mpl-devel
33+ * Are your changes python2.3 compatible? We are still trying to
34+ support 2.3, so avoid 2.4 only features like decorators until we
35+ remove 2.3 support
36+ * Can you pass examples/backend_driver.py? This is our poor man's
37+ unit test.
38+ * If you have altered extension code, do you pass
39+ unit/memleak_hawaii.py?
40+ * if you have added new files or directories, or reorganized
41+ existing ones, are the new files included in the match patterns in
42+ MANIFEST.in. This file determines what goes into the src
43+ distribution of the mpl build.
44+ * Keep the maintenance branch and trunk in sync where it makes sense.
45+ If there is a bug on both that needs fixing, use svnmerge.py to
46+ keep them in sync. http://www.orcaware.com/svn/wiki/Svnmerge.py. The
47+ basic procedure is:
48+
49+ * install svnmerge.py in your PATH::
50+
51+ wget http://svn.collab.net/repos/svn/trunk/contrib/client-side/\
52+ svnmerge/svnmerge.py
53+
54+ * get a svn copy of the maintenance branch and the trunk (see above)
55+ * Michael advises making the change on the branch and committing
56+ it. Make sure you svn upped on the trunk and have no local
57+ modifications, and then from the svn trunk do::
58+
59+ > svnmerge.py merge -rNNN1,NNN2
60+
61+ where the NNN* are the revision numbers. Ranges arealso acceptable.
62+ svnmergy.py automatically creates a file containing the commit messages,
63+ so you are ready to make the commit::
64+
65+ > svn commit -F svnmerge-commit-message.txt
66+
67+ ***********
68+ Style Guide
69+ ***********
70+
71+ Importing and name spaces
72+ =========================
73+
74+ For numpy, use::
75+
76+ import numpy as np
77+ a = np.array([1,2,3])
78+
79+ For masked arrays, use::
80+
81+ from numpy import ma
82+
83+ (The earlier recommendation, 'import matplotlib.numerix.npyma as ma',
84+ was needed temporarily during the development of the maskedarray
85+ implementation as a separate package. As of numpy 1.1, it replaces the
86+ old implementation. Note: "from numpy import ma" works with numpy < 1.1
87+ *and* with numpy >= 1.1. "import numpy.ma as ma" works *only* with
88+ numpy >= 1.1, so for now we must not use it.)
89+
90+ For matplotlib main module, use::
91+
92+ import matplotlib as mpl
93+ mpl.rcParams['xtick.major.pad'] = 6
94+
95+ For matplotlib modules (or any other modules), use::
96+
97+ import matplotlib.cbook as cbook
98+
99+ if cbook.iterable(z):
100+ pass
101+
102+ We prefer this over the equivalent 'from matplotlib import cbook'
103+ because the latter is ambiguous whether cbook is a module or a
104+ function to the new developer. The former makes it explcit that
105+ you are importing a module or package.
106+
107+ Naming, spacing, and formatting conventions
108+ ===========================================
109+
110+ In general, we want to hew as closely as possible to the standard
111+ coding guidelines for python written by Guido in
112+ http://www.python.org/dev/peps/pep-0008, though we do not do this
113+ throughout.
114+
115+ * functions and class methods: lower or lower_underscore_separated
116+
117+ * attributes and variables: lower or lowerUpper
118+
119+ * classes: Upper or MixedCase
120+
121+ Personally, I prefer the shortest names that are still readable.
122+
123+ Also, use an editor that does not put tabs in files. Four spaces
124+ should be used for indentation everywhere and if there is a file with
125+ tabs or more or less spaces it is a bug -- please fix it.
126+
127+ Please avoid spurious invisible spaces at the ends of lines.
128+ (Tell your editor to strip whitespace from line ends when saving
129+ a file.)
130+
131+ Keep docstrings uniformly indented as in the example below, with
132+ nothing to the left of the triple quotes. The dedent() function
133+ is needed to remove excess indentation only if something will be
134+ interpolated into the docstring, again as in the example above.
135+
136+ Limit line length to 80 characters. If a logical line needs to be
137+ longer, use parentheses to break it; do not use an escaped
138+ newline. It may be preferable to use a temporary variable
139+ to replace a single long line with two shorter and more
140+ readable lines.
141+
142+ Please do not commit lines with trailing white space, as it causes
143+ noise in svn diffs. If you are an emacs user, the following in your
144+ .emacs will cause emacs to strip trailing white space on save for
145+ python, C and C++::
146+
147+ ; and similarly for c++-mode-hook and c-mode-hook
148+ (add-hook 'python-mode-hook
149+ (lambda ()
150+ (add-hook 'write-file-functions 'delete-trailing-whitespace)))
151+
152+ for older versions of emacs (emacs<22) you need to do::
153+
154+ (add-hook 'python-mode-hook
155+ (lambda ()
156+ (add-hook 'local-write-file-hooks 'delete-trailing-whitespace)))
157+
158+ Keyword argument processing
159+ ===========================
160+
161+ Matplotlib makes extensive use of ``**kwargs`` for pass through
162+ customizations from one function to another. A typical example is in
163+ pylab.text, The definition of the pylab text function is a simple
164+ pass-through to axes.Axes.text::
165+
166+ # in pylab.py
167+ def text(*args, **kwargs):
168+ ret = gca().text(*args, **kwargs)
169+ draw_if_interactive()
170+ return ret
171+
172+ axes.Axes.text in simplified form looks like this, ie it just passes
173+ them on to text.Text.__init__::
174+
175+ # in axes.py
176+ def text(self, x, y, s, fontdict=None, withdash=False, **kwargs):
177+ t = Text(x=x, y=y, text=s, **kwargs)
178+
179+ and Text.__init__ (again with liberties for illustration) just passes
180+ them on to the artist.Artist.update method::
181+
182+ # in text.py
183+ def __init__(self, x=0, y=0, text='', **kwargs):
184+ Artist.__init__(self)
185+ self.update(kwargs)
186+
187+ 'update' does the work looking for methods named like 'set_property'
188+ if 'property' is a keyword argument. Ie, noone looks at the keywords,
189+ they just get passed through the API to the artist constructor which
190+ looks for suitably named methods and calls them with the value.
191+
192+ As a general rule, the use of ``**kwargs`` should be reserved for
193+ pass-through keyword arguments, as in the examaple above. If I intend
194+ for all the keyword args to be used in some function and not passed
195+ on, I just use the key/value keyword args in the function definition
196+ rather than the ``**kwargs`` idiom.
197+
198+ In some cases I want to consume some keys and pass through the others,
199+ in which case I pop the ones I want to use locally and pass on the
200+ rest, eg I pop scalex and scaley in Axes.plot and assume the rest are
201+ Line2D keyword arguments. As an example of a pop, passthrough
202+ usage, see Axes.plot::
203+
204+ # in axes.py
205+ def plot(self, *args, **kwargs):
206+ scalex = kwargs.pop('scalex', True)
207+ scaley = kwargs.pop('scaley', True)
208+ if not self._hold: self.cla()
209+ lines = []
210+ for line in self._get_lines(*args, **kwargs):
211+ self.add_line(line)
212+ lines.append(line)
213+
214+ The matplotlib.cbook function popd() is rendered
215+ obsolete by the pop() dictionary method introduced in Python 2.3,
216+ so it should not be used for new code.
217+
218+ Note there is a use case when kwargs are meant to be used locally in
219+ the function (not passed on), but you still need the ``**kwargs`` idiom.
220+ That is when you want to use ``*args`` to allow variable numbers of
221+ non-keyword args. In this case, python will not allow you to use
222+ named keyword args after the ``*args`` usage, so you will be forced to use
223+ ``**kwargs``. An example is matplotlib.contour.ContourLabeler.clabel::
224+
225+ # in contour.py
226+ def clabel(self, *args, **kwargs):
227+ fontsize = kwargs.get('fontsize', None)
228+ inline = kwargs.get('inline', 1)
229+ self.fmt = kwargs.get('fmt', '%1.3f')
230+ colors = kwargs.get('colors', None)
231+ if len(args) == 0:
232+ levels = self.levels
233+ indices = range(len(self.levels))
234+ elif len(args) == 1:
235+ ...etc...
236+
237+ Documentation and Docstrings
238+ ============================
239+
240+ matplotlib uses artist instrospection of docstrings to support
241+ properties. All properties that you want to support through setp and
242+ getp should have a set_property and get_property method in the Artist
243+ class. Yes, this is not ideal given python properties or enthought
244+ traits, but it is a historical legacy for now. The setter methods use
245+ the docstring with the ACCEPTS token to indicate the type of argument
246+ the method accepts. Eg in matplotlib.lines.Line2D::
247+
248+ # in lines.py
249+ def set_linestyle(self, linestyle):
250+ """
251+ Set the linestyle of the line
252+
253+ ACCEPTS: [ '-' | '--' | '-.' | ':' | 'steps' | 'None' | ' ' | '' ]
254+ """
255+
256+ Since matplotlib uses a lot of pass through kwargs, eg in every
257+ function that creates a line (plot, semilogx, semilogy, etc...), it
258+ can be difficult for the new user to know which kwargs are supported.
259+ I have developed a docstring interpolation scheme to support
260+ documentation of every function that takes a ``**kwargs``. The
261+ requirements are:
262+
263+ 1. single point of configuration so changes to the properties don't
264+ require multiple docstring edits
265+
266+ 2. as automated as possible so that as properties change the docs
267+ are updated automagically.
268+
269+ I have added a matplotlib.artist.kwdocd and kwdoc() to faciliate this.
270+ They combines python string interpolation in the docstring with the
271+ matplotlib artist introspection facility that underlies setp and getp.
272+ The kwdocd is a single dictionary that maps class name to a docstring
273+ of kwargs. Here is an example from matplotlib.lines::
274+
275+ # in lines.py
276+ artist.kwdocd['Line2D'] = artist.kwdoc(Line2D)
277+
278+ Then in any function accepting Line2D passthrough kwargs, eg
279+ matplotlib.axes.Axes.plot::
280+
281+ # in axes.py
282+ def plot(self, *args, **kwargs):
283+ """
284+ Some stuff omitted
285+
286+ The kwargs are Line2D properties:
287+ %(Line2D)s
288+
289+ kwargs scalex and scaley, if defined, are passed on
290+ to autoscale_view to determine whether the x and y axes are
291+ autoscaled; default True. See Axes.autoscale_view for more
292+ information
293+ """
294+ pass
295+ plot.__doc__ = cbook.dedent(plot.__doc__) % artist.kwdocd
296+
297+ Note there is a problem for Artist __init__ methods, eg Patch.__init__
298+ which supports Patch kwargs, since the artist inspector cannot work
299+ until the class is fully defined and we can't modify the
300+ Patch.__init__.__doc__ docstring outside the class definition. I have
301+ made some manual hacks in this case which violates the "single entry
302+ point" requirement above; hopefully we'll find a more elegant solution
303+ before too long
304+
305+ ********
306+ Licenses
307+ ********
308+
309+ Matplotlib only uses BSD compatible code. If you bring in code from
310+ another project make sure it has a PSF, BSD, MIT or compatible
311+ license. If not, you may consider contacting the author and asking
312+ them to relicense it. GPL and LGPL code are not acceptible in the
313+ main code base, though we are considering an alternative way of
314+ distributing L/GPL code through an separate channel, possibly a
315+ toolkit. If you include code, make sure you include a copy of that
316+ code's license in the license directory if the code's license requires
317+ you to distribute the license with it.
0 commit comments