style.rst 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. .. _coding-style:
  2. =================
  3. Salt Coding Style
  4. =================
  5. To make it easier to contribute and read Salt code, SaltStack has `adopted
  6. Black <SEP 15_>`_ as its code formatter. There are a few places where Black is
  7. silent, and this guide should be used in those cases.
  8. Coding style is NEVER grounds to reject code contributions, and is never
  9. grounds to talk down to another member of the community (There are no grounds
  10. to treat others without respect, especially people working to improve Salt)!
  11. .. _pylint-instructions:
  12. Linting
  13. =======
  14. Most Salt style conventions are codified in Salt's ``.testing.pylintrc`` file.
  15. Salt's pylint file has two dependencies: pylint_ and saltpylint_. You can
  16. install these dependencies with ``pip``:
  17. .. code-block:: bash
  18. pip install pylint
  19. pip install saltpylint
  20. The ``.testing.pylintrc`` file is found in the root of the Salt project and can
  21. be passed as an argument to the pylint_ program as follows:
  22. .. code-block:: bash
  23. pylint --rcfile=/path/to/salt/.testing.pylintrc salt/dir/to/lint
  24. .. note::
  25. There are two pylint files in the ``salt`` directory. One is the
  26. ``.pylintrc`` file and the other is the ``.testing.pylintrc`` file. The
  27. tests that run in Jenkins against GitHub Pull Requests use
  28. ``.testing.pylintrc``. The ``testing.pylintrc`` file is a little less
  29. strict than the ``.pylintrc`` and is used to make it easier for contributors
  30. to submit changes. The ``.pylintrc`` file can be used for linting, but the
  31. ``testing.pylintrc`` is the source of truth when submitting pull requests.
  32. .. _pylint: https://www.pylint.org/
  33. .. _saltpylint: https://github.com/saltstack/salt-pylint
  34. Variables
  35. =========
  36. Variables should be a minimum of three characters and should provide an
  37. easy-to-understand name of the object being represented.
  38. When keys and values are iterated over, descriptive names should be used
  39. to represent the temporary variables.
  40. Multi-word variables should be separated by an underscore.
  41. Variables which are two-letter words should have an underscore appended
  42. to them to pad them to three characters.
  43. Formatting Strings
  44. ------------------
  45. All strings which require formatting should use the `.format` string method:
  46. .. code-block:: python
  47. data = "some text"
  48. more = "{0} and then some".format(data)
  49. Make sure to use indices or identifiers in the format brackets, since empty
  50. brackets are not supported by python 2.6.
  51. Please do NOT use printf formatting.
  52. Docstring Conventions
  53. ---------------------
  54. When adding a new function or state, where possible try to use a
  55. ``versionadded`` directive to denote when the function, state, or parameter was added.
  56. .. code-block:: python
  57. def new_func(msg=""):
  58. """
  59. .. versionadded:: 0.16.0
  60. Prints what was passed to the function.
  61. msg : None
  62. The string to be printed.
  63. """
  64. print(msg)
  65. If you are uncertain what version should be used, either consult a core
  66. developer in IRC or bring this up when opening your :ref:`pull request
  67. <installing-for-development>` and a core developer will let you know what
  68. version to add. Typically this will be the next element in the `periodic table
  69. <https://en.wikipedia.org/wiki/List_of_chemical_elements>`_.
  70. Similar to the above, when an existing function or state is modified (for
  71. example, when an argument is added), then under the explanation of that new
  72. argument a ``versionadded`` directive should be used to note the version in
  73. which the new argument was added. If an argument's function changes
  74. significantly, the ``versionchanged`` directive can be used to clarify this:
  75. .. code-block:: python
  76. def new_func(msg="", signature=""):
  77. """
  78. .. versionadded:: 0.16.0
  79. Prints what was passed to the function.
  80. msg : None
  81. The string to be printed. Will be prepended with 'Greetings! '.
  82. .. versionchanged:: 0.17.1
  83. signature : None
  84. An optional signature.
  85. .. versionadded:: 0.17.0
  86. """
  87. print("Greetings! {0}\n\n{1}".format(msg, signature))
  88. Dictionaries
  89. ============
  90. Dictionaries should be initialized using `{}` instead of `dict()`.
  91. See here_ for an in-depth discussion of this topic.
  92. .. _here: https://doughellmann.com/blog/2012/11/12/the-performance-impact-of-using-dict-instead-of-in-cpython-2-7-2/
  93. Imports
  94. =======
  95. Salt code prefers importing modules and not explicit functions. This is both a
  96. style and functional preference. The functional preference originates around
  97. the fact that the module import system used by pluggable modules will include
  98. callable objects (functions) that exist in the direct module namespace. This
  99. is not only messy, but may unintentionally expose code python libs to the Salt
  100. interface and pose a security problem.
  101. To say this more directly with an example, this is `GOOD`:
  102. .. code-block:: python
  103. import os
  104. def minion_path():
  105. path = os.path.join(self.opts["cachedir"], "minions")
  106. return path
  107. This on the other hand is `DISCOURAGED`:
  108. .. code-block:: python
  109. from os.path import join
  110. def minion_path():
  111. path = join(self.opts["cachedir"], "minions")
  112. return path
  113. The time when this is changed is for importing exceptions, generally directly
  114. importing exceptions is preferred:
  115. This is a good way to import exceptions:
  116. .. code-block:: python
  117. from salt.exceptions import CommandExecutionError
  118. Absolute Imports
  119. ----------------
  120. Although `absolute imports`_ seems like an awesome idea, please do not use it.
  121. Extra care would be necessary all over salt's code in order for absolute
  122. imports to work as supposed. Believe it, it has been tried before and, as a
  123. tried example, by renaming ``salt.modules.sysmod`` to ``salt.modules.sys``, all
  124. other salt modules which needed to import :mod:`sys<python2:sys>` would have to
  125. also import :mod:`absolute_import<python2:__future__>`, which should be
  126. avoided.
  127. .. note::
  128. An exception to this rule is the ``absolute_import`` from ``__future__`` at
  129. the top of each file within the Salt project. This import is necessary for
  130. Py3 compatibility. This particular import looks like this:
  131. .. code-block:: python
  132. from __future__ import absolute_import
  133. This import is required for all new Salt files and is a good idea to add to
  134. any custom states or modules. However, the practice of avoiding absolute
  135. imports still applies to all other cases as to avoid a name conflict.
  136. .. _`absolute imports`: https://legacy.python.org/dev/peps/pep-0328/#rationale-for-absolute-imports
  137. Code Churn
  138. ==========
  139. Many pull requests have been submitted that only churn code in the name of
  140. PEP 8. Code churn is a leading source of bugs and is **strongly discouraged**.
  141. While style fixes are encouraged they should be isolated to a single file per
  142. commit, and the changes should be legitimate, if there are any questions about
  143. whether a style change is legitimate please reference this document and the
  144. official PEP 8 (https://legacy.python.org/dev/peps/pep-0008/) document before
  145. changing code. Many claims that a change is PEP 8 have been invalid, please
  146. double check before committing fixes.
  147. .. _`SEP 15`: https://github.com/saltstack/salt-enhancement-proposals/pull/21