CONTRIBUTING.rst 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. All functionality should be available in pure Python. Optional Rust
  2. implementations may be written for performance reasons, but should never
  3. replace the Python implementation.
  4. Where possible include updates to NEWS along with your improvements.
  5. New functionality and bug fixes should be accompanied by matching unit tests.
  6. Installing development dependencies
  7. -----------------------------------
  8. Contributing to Dulwich requires several more dependencies than are required to install
  9. the base package; they are used to run tests and various other checks.
  10. First, make sure your system has the Rust compiler and Cargo (the Rust package manager)
  11. installed. As this is a system-level requirement and not a Python library, the right way
  12. to install it depends on your platform. Please consult the `Rust documentation
  13. <https://www.rust-lang.org/learn/get-started>`__ to find out more.
  14. Next, you will need to set up your Python environment for Dulwich. An easy way to get
  15. started is to install the checked out Dulwich package in editable mode with ``dev``
  16. extras, preferably in a new virtual environment:
  17. .. code:: console
  18. $ cd ~/path/to/checkouts/dulwich
  19. # Create and activate a virtual environment via your favourite method, such as pyenv,
  20. # uv, built-in venv module...
  21. $ python -m venv .venv && . .venv/bin/activate
  22. # Now install Dulwich and the required dependencies
  23. $ pip install -e ".[dev]"
  24. This will ensure the tools needed to test your changes are installed. It is not necessary
  25. to install Dulwich in editable mode (``-e``), but doing so is convenient for development,
  26. as code changes will be visible immediately, without requiring a reinstall (although any
  27. running Python processes will need to be reloaded to see the updated module
  28. definitions). Editable mode only applies to Python code; if you modify any of the Rust
  29. extension code, you will need to reinstall the package for the extensions to be
  30. recompiled.
  31. There are also other, optional dependencies which are needed to run the full test suite,
  32. implement optional features, and provide the full typing information. They are however not
  33. strictly necessary; the above is sufficient to start developing and have your PR pass the
  34. tests in most cases. Please consult the ``[project.optional-dependencies]`` section in
  35. ``pyproject.toml``.
  36. Coding style
  37. ------------
  38. The code follows the PEP8 coding style. There are ``ruff`` rules in place that define the
  39. exact code style, please run it to make sure your changes are conformant. See also "Style
  40. and typing checks" below for details on running style checkers.
  41. Public methods, functions and classes should all have doc strings. Please use
  42. Google style docstrings to document parameters and return values.
  43. You can generate the documentation by running ``pydoctor --docformat=google dulwich``
  44. from the root of the repository, and then opening
  45. ``apidocs/index.html`` in your web browser.
  46. String Types
  47. ~~~~~~~~~~~~
  48. Like Linux, Git treats filenames as arbitrary bytestrings. There is no prescribed
  49. encoding for these strings, and although it is fairly common to use UTF-8, any
  50. raw byte strings are supported.
  51. For this reason, the lower levels in Dulwich treat git-based filenames as
  52. bytestrings. It is up to the Dulwich API user to encode and decode them if
  53. necessary. The porcelain may accept unicode strings and convert them to
  54. bytestrings as necessary on the fly (using 'utf-8').
  55. * on-disk filenames: regular strings, or ideally, pathlib.Path instances
  56. * git-repository related filenames: bytes
  57. * object sha1 digests (20 bytes long): bytes
  58. * object sha1 hexdigests (40 bytes long): str (bytestrings on python2, strings
  59. on python3)
  60. Exceptions
  61. ~~~~~~~~~~
  62. When catching exceptions, please catch the specific exception type rather than
  63. a more generic type (like OSError, IOError, Exception, etc.). This will
  64. ensure that you do not accidentally catch unrelated exceptions.
  65. The only exception is when you are reraising an exception, e.g. when
  66. re-raising an exception after logging it.
  67. Do not catch bare except, although ruff will warn you about this.
  68. Keep the code within a try/except block as small as possible, so
  69. that you do not accidentally catch unrelated exceptions.
  70. Deprecating functionality
  71. ~~~~~~~~~~~~~~~~~~~~~~~~~
  72. Dulwich uses the `dissolve` package to manage deprecations. If you want to deprecate
  73. functionality, please use the `@replace_me` decorator from the root of the
  74. dulwich package. This will ensure that the deprecation is handled correctly:
  75. * It will be logged as a warning
  76. * When the version of Dulwich is bumped, the deprecation will be removed
  77. * Users can use `dissolve migrate` to automatically replace deprecated
  78. functionality in their code
  79. Tests
  80. ~~~~~
  81. Dulwich has two kinds of tests:
  82. * Unit tests, which test individual functions and classes
  83. * Compatibility tests, which test that Dulwich behaves in a way that is
  84. compatible with C Git
  85. The former should never invoke C Git, while the latter may do so. This is
  86. to ensure that it is possible to run the unit tests in an environment
  87. where C Git is not available.
  88. Tests should not depend on the internet, or any other external services.
  89. Avoid using mocks if at all possible; rather, design your code to be easily
  90. testable without them. If you do need to use mocks, please use the
  91. ``unittest.mock`` module.
  92. Running the tests
  93. -----------------
  94. To run the testsuite, you should be able to run ``dulwich.tests.test_suite``.
  95. This will run the tests using unittest.
  96. .. code:: console
  97. $ python -m unittest dulwich.tests.test_suite
  98. The compatibility tests that verify Dulwich behaves in a way that is compatible
  99. with C Git are the slowest, so you may want to avoid them while developing:
  100. .. code:: console
  101. $ python -m unittest dulwich.tests.nocompat_test_suite
  102. testr and tox configuration is also present.
  103. Style and typing checks
  104. -----------------------
  105. Several static analysis tools are used to ensure code quality and consistency.
  106. * Use ``ruff check`` to run all style-related checks.
  107. * Use ``ruff format --check`` to check code formatting.
  108. * Use ``mypy dulwich`` for typing checks.
  109. * Use ``codespell`` to check for common misspellings.
  110. Those checks are *mandatory*, a PR will not pass tests and will not be merged if
  111. they aren't successful.
  112. .. code:: console
  113. $ ruff check
  114. $ ruff format --check
  115. $ mypy dulwich
  116. $ codespell
  117. In some cases you can automatically fix issues found by these tools. To do so, you can run:
  118. .. code:: console
  119. $ ruff check --fix # or pass --unsafe-fixes to apply more aggressive fixes
  120. $ ruff format
  121. $ codespell --config .codespellrc -w
  122. Merge requests
  123. --------------
  124. Please either send pull requests to the maintainer (jelmer@jelmer.uk) or create
  125. new pull requests on GitHub.
  126. Licensing
  127. ---------
  128. All contributions should be made under the same license that Dulwich itself
  129. comes under: both Apache License, version 2.0 or later and GNU General Public
  130. License, version 2.0 or later.