2012-12-20 19:35:27 +00:00
|
|
|
=================
|
|
|
|
Salt Coding Style
|
|
|
|
=================
|
|
|
|
|
|
|
|
Salt is developed with a certain coding style, while the style is dominantly
|
2013-04-05 22:28:24 +00:00
|
|
|
PEP 8 it is not completely PEP 8. It is also noteworthy that a few
|
2012-12-20 19:35:27 +00:00
|
|
|
development techniques are also employed which should be adhered to. In the
|
|
|
|
end, the code is made to be "Salty".
|
|
|
|
|
|
|
|
Most importantly though, we will accept code that violates the coding style and
|
|
|
|
KINDLY ask the contributor to fix it, or go ahead and fix the code on behalf of
|
|
|
|
the contributor. Coding style is NEVER grounds to reject code contributions,
|
|
|
|
and is never grounds to talk down to another member of the community (There are
|
|
|
|
no grounds to treat others without respect, especially people working to
|
|
|
|
improve Salt)!!
|
|
|
|
|
|
|
|
|
2013-12-13 17:11:23 +00:00
|
|
|
Linting
|
|
|
|
=======
|
|
|
|
|
2014-04-08 22:15:00 +00:00
|
|
|
Most Salt style conventions are codified in Salt's ``.pylintrc`` file. This file
|
2013-12-13 17:11:23 +00:00
|
|
|
is found in the root of the Salt project and can be passed as an argument to the
|
|
|
|
pylint_ program as follows:
|
|
|
|
|
2014-04-08 22:15:00 +00:00
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
pylint --rcfile=/path/to/salt/.pylintrc salt/dir/to/lint
|
2013-12-13 17:11:23 +00:00
|
|
|
|
|
|
|
.. _pylint: http://www.pylint.org
|
|
|
|
|
2012-12-20 19:35:27 +00:00
|
|
|
Strings
|
|
|
|
=======
|
|
|
|
|
|
|
|
Salt follows a few rules when formatting strings:
|
|
|
|
|
|
|
|
Single Quotes
|
|
|
|
-------------
|
|
|
|
|
|
|
|
In Salt, all strings use single quotes unless there is a good reason not to.
|
|
|
|
This means that docstrings use single quotes, standard strings use single
|
|
|
|
quotes etc.:
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
def foo():
|
|
|
|
'''
|
|
|
|
A function that does things
|
|
|
|
'''
|
|
|
|
name = 'A name'
|
|
|
|
return name
|
|
|
|
|
|
|
|
Formatting Strings
|
|
|
|
------------------
|
|
|
|
|
|
|
|
All strings which require formatting should use the `.format` string method:
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
data = 'some text'
|
|
|
|
more = '{0} and then some'.format(data)
|
|
|
|
|
|
|
|
Make sure to use indices or identifiers in the format brackets, since empty
|
|
|
|
brackets are not supported by python 2.6.
|
|
|
|
|
|
|
|
Please do NOT use printf formatting.
|
|
|
|
|
|
|
|
Docstring Conventions
|
|
|
|
---------------------
|
|
|
|
|
|
|
|
Docstrings should always add a newline, docutils takes care of the new line and
|
|
|
|
it makes the code cleaner and more vertical:
|
|
|
|
|
|
|
|
`GOOD`:
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
def bar():
|
|
|
|
'''
|
|
|
|
Here lies a docstring with a newline after the quotes and is the salty
|
|
|
|
way to handle it! Vertical code is the way to go!
|
|
|
|
'''
|
|
|
|
return
|
|
|
|
|
|
|
|
`BAD`:
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
def baz():
|
|
|
|
'''This is not ok!'''
|
|
|
|
return
|
|
|
|
|
2013-12-26 10:15:58 +00:00
|
|
|
|
|
|
|
When adding a new function or state, where possible try to use a
|
|
|
|
``versionadded`` directive to denote when the function or state was added.
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
2013-12-26 18:11:26 +00:00
|
|
|
def new_func(msg=''):
|
2013-12-26 10:15:58 +00:00
|
|
|
'''
|
2013-12-26 18:11:26 +00:00
|
|
|
.. versionadded:: 0.16.0
|
2013-12-26 10:15:58 +00:00
|
|
|
|
2013-12-26 18:11:26 +00:00
|
|
|
Prints what was passed to the function.
|
|
|
|
|
|
|
|
msg : None
|
|
|
|
The string to be printed.
|
2013-12-26 10:15:58 +00:00
|
|
|
'''
|
2013-12-26 18:11:26 +00:00
|
|
|
print msg
|
2013-12-26 10:15:58 +00:00
|
|
|
|
2014-02-26 20:28:13 +00:00
|
|
|
If you are uncertain what version should be used, either consult a core
|
|
|
|
developer in IRC or bring this up when opening your
|
|
|
|
:doc:`pull request </topics/development/hacking>` and a core developer will add the proper
|
2013-12-26 10:15:58 +00:00
|
|
|
version once your pull request has been merged. Bugfixes will be available in a
|
|
|
|
bugfix release (i.e. 0.17.1, the first bugfix release for 0.17.0), while new
|
|
|
|
features are held for feature releases, and this will affect what version
|
|
|
|
number should be used in the ``versionadded`` directive.
|
|
|
|
|
|
|
|
|
|
|
|
Similar to the above, when an existing function or state is modified (for
|
|
|
|
example, when an argument is added), then under the explanation of that new
|
2013-12-26 18:11:26 +00:00
|
|
|
argument a ``versionadded`` directive should be used to note the version in
|
|
|
|
which the new argument was added. If an argument's function changes
|
|
|
|
significantly, the ``versionchanged`` directive can be used to clarify this:
|
2013-12-26 10:15:58 +00:00
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
2013-12-26 18:11:26 +00:00
|
|
|
def new_func(msg='', signature=''):
|
2013-12-26 10:15:58 +00:00
|
|
|
'''
|
2013-12-26 18:11:26 +00:00
|
|
|
.. versionadded:: 0.16.0
|
2013-12-26 10:15:58 +00:00
|
|
|
|
2013-12-26 18:11:26 +00:00
|
|
|
Prints what was passed to the function.
|
|
|
|
|
|
|
|
msg : None
|
|
|
|
The string to be printed. Will be prepended with 'Greetings! '.
|
2013-12-26 10:15:58 +00:00
|
|
|
|
|
|
|
.. versionchanged:: 0.17.1
|
2013-12-26 18:11:26 +00:00
|
|
|
|
|
|
|
signature : None
|
|
|
|
An optional signature.
|
|
|
|
|
|
|
|
.. versionadded 0.17.0
|
2013-12-26 10:15:58 +00:00
|
|
|
'''
|
2013-12-26 18:11:26 +00:00
|
|
|
print 'Greetings! {0}\n\n{1}'.format(msg, signature)
|
2013-12-26 10:15:58 +00:00
|
|
|
|
|
|
|
|
2014-06-25 00:34:25 +00:00
|
|
|
Dictionaries
|
|
|
|
============
|
|
|
|
|
|
|
|
Dictionaries should be initialized using `{}` instead of `dict()`.
|
|
|
|
|
|
|
|
See here_ for an in-depth discussion of this topic.
|
|
|
|
|
|
|
|
.. _here: http://doughellmann.com/2012/11/12/the-performance-impact-of-using-dict-instead-of-in-cpython-2-7-2.html
|
|
|
|
|
|
|
|
|
2012-12-20 19:35:27 +00:00
|
|
|
Imports
|
|
|
|
=======
|
|
|
|
|
|
|
|
Salt code prefers importing modules and not explicit functions. This is both a
|
|
|
|
style and functional preference. The functional preference originates around
|
|
|
|
the fact that the module import system used by pluggable modules will include
|
|
|
|
callable objects (functions) that exist in the direct module namespace. This
|
|
|
|
is not only messy, but may unintentionally expose code python libs to the Salt
|
|
|
|
interface and pose a security problem.
|
|
|
|
|
|
|
|
To say this more directly with an example, this is `GOOD`:
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
import os
|
|
|
|
|
|
|
|
def minion_path():
|
|
|
|
path = os.path.join(self.opts['cachedir'], 'minions')
|
|
|
|
return path
|
|
|
|
|
|
|
|
This on the other hand is `DISCOURAGED`:
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
from os.path import join
|
|
|
|
|
|
|
|
def minion_path():
|
2013-07-13 05:32:49 +00:00
|
|
|
path = join(self.opts['cachedir'], 'minions')
|
|
|
|
return path
|
2012-12-20 19:35:27 +00:00
|
|
|
|
|
|
|
The time when this is changed is for importing exceptions, generally directly
|
|
|
|
importing exceptions is preferred:
|
|
|
|
|
|
|
|
This is a good way to import exceptions:
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
from salt.exceptions import CommandExecutionError
|
|
|
|
|
2013-08-20 23:04:21 +00:00
|
|
|
|
|
|
|
Absolute Imports
|
|
|
|
----------------
|
|
|
|
|
2014-12-11 15:51:43 +00:00
|
|
|
Although `absolute imports`_ seems like an awesome idea, please do not use it.
|
|
|
|
Extra care would be necessary all over salt's code in order for absolute
|
|
|
|
imports to work as supposed. Believe it, it has been tried before and, as a
|
|
|
|
tried example, by renaming ``salt.modules.sysmod`` to ``salt.modules.sys``, all
|
|
|
|
other salt modules which needed to import :mod:`sys<python2:sys>` would have to
|
|
|
|
also import :mod:`absolute_import<python2:__future__>`, which should be
|
2013-08-20 23:04:21 +00:00
|
|
|
avoided.
|
|
|
|
|
2014-02-20 23:16:59 +00:00
|
|
|
.. _`absolute imports`: http://legacy.python.org/dev/peps/pep-0328/#rationale-for-absolute-imports
|
2013-08-20 23:04:21 +00:00
|
|
|
|
|
|
|
|
2012-12-20 19:35:27 +00:00
|
|
|
Vertical is Better
|
|
|
|
==================
|
|
|
|
|
|
|
|
When writing Salt code, vertical code is generally preferred. This is not a hard
|
2013-04-05 22:28:24 +00:00
|
|
|
rule but more of a guideline. As PEP 8 specifies, Salt code should not exceed 79
|
2012-12-20 19:35:27 +00:00
|
|
|
characters on a line, but it is preferred to separate code out into more
|
|
|
|
newlines in some cases for better readability:
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
import os
|
|
|
|
|
|
|
|
os.chmod(
|
|
|
|
os.path.join(self.opts['sock_dir'],
|
|
|
|
'minion_event_pub.ipc'),
|
|
|
|
448
|
|
|
|
)
|
|
|
|
|
|
|
|
Where there are more line breaks, this is also apparent when constructing a
|
|
|
|
function with many arguments, something very common in state functions for
|
|
|
|
instance:
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
def managed(name,
|
|
|
|
source=None,
|
|
|
|
source_hash='',
|
|
|
|
user=None,
|
|
|
|
group=None,
|
|
|
|
mode=None,
|
|
|
|
template=None,
|
|
|
|
makedirs=False,
|
|
|
|
context=None,
|
|
|
|
replace=True,
|
|
|
|
defaults=None,
|
|
|
|
env=None,
|
|
|
|
backup='',
|
|
|
|
**kwargs):
|
|
|
|
|
2013-08-19 05:30:57 +00:00
|
|
|
.. note::
|
|
|
|
|
|
|
|
Making function and class definitions vertical is only required if the
|
2013-08-20 19:14:52 +00:00
|
|
|
arguments are longer then 80 characters. Otherwise, the formatting is
|
2013-08-19 05:30:57 +00:00
|
|
|
optional and both are acceptable.
|
|
|
|
|
2014-03-21 20:57:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
Line Length
|
|
|
|
-----------
|
|
|
|
|
2014-12-11 15:51:43 +00:00
|
|
|
For function definitions and function calls, Salt adheres to the PEP-8
|
2014-03-21 20:57:48 +00:00
|
|
|
specification of at most 80 characters per line.
|
|
|
|
|
2014-12-11 15:51:43 +00:00
|
|
|
Non function definitions or function calls, please adopt a soft limit of 120
|
|
|
|
characters per line. If breaking the line reduces the code readability, don't
|
|
|
|
break it. Still, try to avoid passing that 120 characters limit and remember,
|
2014-03-21 20:57:48 +00:00
|
|
|
**vertical is better... unless it isn't**
|
|
|
|
|
|
|
|
|
2013-04-05 18:43:00 +00:00
|
|
|
Indenting
|
|
|
|
=========
|
|
|
|
|
2013-04-05 20:11:32 +00:00
|
|
|
Some confusion exists in the python world about indenting things like function
|
2013-04-05 20:18:25 +00:00
|
|
|
calls, the above examples use 8 spaces when indenting comma-delimited
|
2013-04-05 20:11:32 +00:00
|
|
|
constructs.
|
2013-04-05 18:43:00 +00:00
|
|
|
|
2013-04-05 20:11:32 +00:00
|
|
|
The confusion arises because the pep8 program INCORRECTLY flags this as wrong,
|
2013-04-05 22:28:24 +00:00
|
|
|
where PEP 8, the document, cites only using 4 spaces here as wrong, as it
|
2013-04-05 20:18:25 +00:00
|
|
|
doesn't differentiate from a new indent level.
|
2013-04-05 18:43:00 +00:00
|
|
|
|
|
|
|
Right:
|
2013-04-05 18:45:12 +00:00
|
|
|
|
2013-04-05 20:18:25 +00:00
|
|
|
.. code-block:: python
|
2013-04-05 18:45:12 +00:00
|
|
|
|
2013-04-05 18:43:00 +00:00
|
|
|
def managed(name,
|
|
|
|
source=None,
|
|
|
|
source_hash='',
|
|
|
|
user=None)
|
2013-04-30 20:15:26 +00:00
|
|
|
|
2013-04-05 18:43:00 +00:00
|
|
|
WRONG:
|
2013-04-05 18:45:12 +00:00
|
|
|
|
2013-04-05 20:18:25 +00:00
|
|
|
.. code-block:: python
|
2013-04-05 18:45:12 +00:00
|
|
|
|
2013-04-05 18:43:00 +00:00
|
|
|
def managed(name,
|
|
|
|
source=None,
|
|
|
|
source_hash='',
|
|
|
|
user=None)
|
|
|
|
|
|
|
|
Lining up the indent is also correct:
|
|
|
|
|
2013-04-05 20:18:25 +00:00
|
|
|
.. code-block:: python
|
2013-04-05 18:45:12 +00:00
|
|
|
|
2013-04-05 18:43:00 +00:00
|
|
|
def managed(name,
|
|
|
|
source=None,
|
|
|
|
source_hash='',
|
|
|
|
user=None)
|
|
|
|
|
2013-04-05 20:11:32 +00:00
|
|
|
This also applies to function calls and other hanging indents.
|
|
|
|
|
2013-04-05 22:28:24 +00:00
|
|
|
pep8 and Flake8 (and, by extension, the vim plugin Syntastic) will complain
|
2013-04-05 20:29:48 +00:00
|
|
|
about the double indent for hanging indents. This is a `known conflict
|
|
|
|
<https://github.com/jcrocholl/pep8/issues/167#issuecomment-15936564>`_ between
|
2013-04-05 22:28:24 +00:00
|
|
|
pep8 (the script) and the actual PEP 8 standard. It is recommended that this
|
2013-04-05 20:18:25 +00:00
|
|
|
particular warning be ignored with the following lines in
|
2013-05-09 23:59:15 +00:00
|
|
|
``~/.config/flake8``:
|
2013-04-05 20:11:32 +00:00
|
|
|
|
2013-04-30 20:15:26 +00:00
|
|
|
.. code-block:: ini
|
2013-04-05 20:11:32 +00:00
|
|
|
|
|
|
|
[flake8]
|
|
|
|
ignore = E226,E241,E242,E126
|
|
|
|
|
2013-04-05 22:28:24 +00:00
|
|
|
Make sure your Flake8/pep8 are up to date. The first three errors are ignored
|
2013-04-05 20:11:32 +00:00
|
|
|
by default and are present here to keep the behavior the same. This will also
|
2013-04-05 22:28:24 +00:00
|
|
|
work for pep8 without the Flake8 wrapper -- just replace all instances of
|
2013-04-05 20:18:25 +00:00
|
|
|
'flake8' with 'pep8', including the filename.
|
2013-04-05 20:11:32 +00:00
|
|
|
|
2012-12-20 19:35:27 +00:00
|
|
|
Code Churn
|
|
|
|
==========
|
|
|
|
|
|
|
|
Many pull requests have been submitted that only churn code in the name of
|
2013-04-05 22:28:24 +00:00
|
|
|
PEP 8. Code churn is a leading source of bugs and is strongly discouraged.
|
2012-12-20 19:35:27 +00:00
|
|
|
While style fixes are encouraged they should be isolated to a single file per
|
|
|
|
commit, and the changes should be legitimate, if there are any questions about
|
|
|
|
whether a style change is legitimate please reference this document and the
|
2014-02-20 23:16:59 +00:00
|
|
|
official PEP 8 (http://legacy.python.org/dev/peps/pep-0008/) document before
|
2013-04-05 22:28:24 +00:00
|
|
|
changing code. Many claims that a change is PEP 8 have been invalid, please
|
2014-12-11 15:51:43 +00:00
|
|
|
double check before committing fixes.
|