| | 161 | Deprecating a feature |
| | 162 | --------------------- |
| | 163 | |
| | 164 | There are a couple reasons that code in Django might be deprecated: |
| | 165 | |
| | 166 | * If a feature has been improved or modified in a backwards-incompatible way, |
| | 167 | the old feature or behavior will be deprecated. |
| | 168 | |
| | 169 | * Sometimes Django will include a backport of a Python library that's not |
| | 170 | included in a version of Python that Django currently supports. When Django |
| | 171 | no longer needs to support the older versions of Python that don't include |
| | 172 | the library, the library will be deprecated in Django. |
| | 173 | |
| | 174 | |
| | 175 | As the :ref:`deprecation policy<internal-release-deprecation-policy>` describes, |
| | 176 | the first release of Django that deprecates a feature (``A.B``) should raise a |
| | 177 | ``PendingDeprecationWarning``. Assuming we have a good test coverage, these |
| | 178 | warnings will be shown by the test suite when running it with warnings enabled: |
| | 179 | ``python -Wall runtests.py``. This is annoying and the output of the test suite |
| | 180 | should remain clean. Thus, when adding a ``PendingDeprecationWarning`` you |
| | 181 | need to eliminate or silence any warnings generated when running the tests. |
| | 182 | |
| | 183 | The first step is to remove any use of the deprecated behavior by Django itself. |
| | 184 | Next you can silence warnings in tests that actually test the deprecated |
| | 185 | behavior in one of two ways: |
| | 186 | |
| | 187 | #) In a particular test:: |
| | 188 | |
| | 189 | import warnings |
| | 190 | |
| | 191 | def test_foo(self): |
| | 192 | with warnings.catch_warnings(record=True) as w: |
| | 193 | warnings.simplefilter("always") |
| | 194 | # invoke deprecated behavior |
| | 195 | # go ahead with the test |
| | 196 | |
| | 197 | #) For an entire test case, ``django.test.utils`` contains three helpful |
| | 198 | mixins to silence warnings: ``IgnorePendingDeprecationWarningsMixin``, |
| | 199 | ``IgnoreDeprecationWarningsMixin``, and |
| | 200 | ``IgnoreAllDeprecationWarningsMixin``. For example:: |
| | 201 | |
| | 202 | from django.test.utils import IgnorePendingDeprecationWarningsMixin |
| | 203 | |
| | 204 | class MyDeprecatedTests(IgnorePendingDeprecationWarningsMixin, unittest.TestCase): |
| | 205 | ... |
| | 206 | |
| | 207 | Finally, there are a couple of updates to Django's documentation to make: |
| | 208 | |
| | 209 | #) If the existing feature is documented, mark it deprecated in documentation |
| | 210 | using the ``.. deprecated:: A.B`` annotation. Include a short description |
| | 211 | and a note about the upgrade path if applicable. |
| | 212 | |
| | 213 | #) Add a description of the deprecated behavior, and the upgrade path if |
| | 214 | applicable, to current the release notes (``docs/releases/A.B.txt``) under |
| | 215 | the "Features deprecated in A.B" heading. |
| | 216 | |
| | 217 | #) Add an entry in the deprecation timeline (``docs/internals/deprecation.txt``) |
| | 218 | under the ``A.B+2`` version describing what code will be removed. |
| | 219 | |
| | 220 | Once you have completed these steps, you are finished with the deprecation. |
| | 221 | In each minor release, all ``PendingDeprecationWarning``\s are promoted to |
| | 222 | ``DeprecationWarning``\s and any features marked with``DeprecationWarning`` |
| | 223 | are removed. |
| | 224 | |