python_guidelines.rst 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. Python coding guidelines
  2. ========================
  3. PEP8
  4. ~~~~
  5. We ask that all Python contributions adhere to the `PEP8 <http://www.python.org/dev/peps/pep-0008/>`_ style guide, apart from the restriction on line length (E501) and some minor docstring-related issues.
  6. The list of PEP8 violations to ignore is in the ``tox.ini`` file, under the ``[flake8]`` header.
  7. You might want to configure the flake8 linter in your editor/IDE to use the configuration in this file.
  8. In addition, import lines should be sorted according to `isort <http://timothycrosley.github.io/isort/>`_ rules. If you have installed Wagtail's testing dependencies (``pip install -e .[testing]``), you can check your code by running ``make lint``.
  9. Python 2 and 3 compatibility
  10. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  11. All contributions should support Python 2 and 3 and we recommend using the `six <https://pythonhosted.org/six/>`_ compatibility library (use the version bundled with Django, ``django.utils.six``).
  12. Django compatibility
  13. ~~~~~~~~~~~~~~~~~~~~
  14. Wagtail is written to be compatible with multiple versions of Django. Sometimes, this requires running one piece of code for recent version of Django, and another piece of code for older versions of Django. In these cases, always check which version of Django is being used by inspecting ``django.VERSION``:
  15. .. code-block:: python
  16. import django
  17. if django.VERSION >= (1, 9):
  18. # Use new attribute
  19. related_field = field.rel
  20. else:
  21. # Use old, deprecated attribute
  22. related_field = field.related
  23. Always compare against the version using greater-or-equals (``>=``), so that code for newer versions of Django is first.
  24. Do not use a ``try ... except`` when seeing if an object has an attribute or method introduced in a newer versions of Django, as it does not clearly express why the ``try ... except`` is used. An explicit check against the Django version makes the intention of the code very clear.
  25. .. code-block:: python
  26. # Do not do this
  27. try:
  28. related_field = field.rel
  29. except AttributeError:
  30. related_field = field.related
  31. If the code needs to use something that changed in a version of Django many times, consider making a function that encapsulates the check:
  32. .. code-block:: python
  33. import django
  34. def related_field(field):
  35. if django.VERSION >= (1, 9):
  36. return field.rel
  37. else:
  38. return field.related
  39. If a new function has been introduced by Django that you think would be very useful for Wagtail, but is not available in older versions of Django that Wagtail supports, that function can be copied over in to Wagtail. If the user is running a new version of Django that has the function, the function should be imported from Django. Otherwise, the version bundled with Wagtail should be used. A link to the Django source code where this function was taken from should be included:
  40. .. code-block:: python
  41. import django
  42. if django.VERSION >= (1, 9):
  43. from django.core.validators import validate_unicode_slug
  44. else:
  45. # Taken from https://github.com/django/django/blob/1.9/django/core/validators.py#L230
  46. def validate_unicode_slug(value):
  47. # Code left as an exercise to the reader
  48. pass
  49. Tests
  50. ~~~~~
  51. Wagtail has a suite of tests, which we are committed to improving and expanding. See :ref:`testing`.
  52. We run continuous integration at `travis-ci.org/wagtail/wagtail <https://travis-ci.org/wagtail/wagtail>`_ to ensure that no commits or pull requests introduce test failures. If your contributions add functionality to Wagtail, please include the additional tests to cover it; if your contributions alter existing functionality, please update the relevant tests accordingly.