
.. NOTE: only edit README.in, and use generate_readme.py to enrich it with the table of fixers


=====================
django-compat-patcher
=====================

    *Compatibility Matters*


DCP is a companion application which adds backward/forward compatibility patches to Django, so that your app ecosystem doesn't get broken by trivial changes made to the core of the framework. You can thus mix bleeding-edge applications with others that are still stuck at much older Django versions.

To know more about the whole concept of Compat Patchers, see the documentation of the underlying `Compat Patcher Core <https://compat-patcher-core.readthedocs.io/en/latest/index.html>`_.

Note that DCP is aimed at project maintainers. If you are developing a reusable Django application, you can't expect all your users to integrate DCP as well. In this case, to support a wide range of Django versions, you should rather use a toolkit like `Django-compat <https://github.com/arteria/django-compat>`_. You may think of DCP as a "runtime 2to3 for Django', whereas Django-Compat is rather a "*six* module for Django".

Feel free to contribute new fixers, for backwards or forwards compatibility, depending on the compatibility troubles you encounter on your own projects. See `docs/django_deprecation_timeline_notes.rst` for a list of breaking changes in Django history, and their current status in DCP.



How to setup
==================


Django-compat-patcher is currently tested on python2.7/3.4/3.5/3.6/3.7, with Django versions 1.8/1.9/1.10/1.11/2.0/2.1/2.2, where these combinations make sense (e.g. Django2+ dropped support for Python2).

Add :code:`django-compat-patcher` to your pip requirements, install it, and then activate it with::
    
    import django_compat_patcher
    django_compat_patcher.patch()
    
This code should be placed before any use of Django (eg. in your :code:`manage.py` or your :code:`wsgi.py` script), but after the :code:`DJANGO_SETTINGS_MODULE` environment variable has been set.

In particular, some fixers only work if they are applied before the loading of INSTALLED_APPS (so before django.setup() gets called).

The Django settings of your project are not altered by compatibility shims, so they should be kept up-to-date with your installed Django version (eg. now use `TEMPLATES`, `MIDDLEWARE`, and not deprecated settings...). In particular, always put real package names in INSTALLED_APPS, not their potential "import aliases".


Django settings
====================

By default, DCP emits logs and warnings when patching the code, and applies all "relevant" fixers,
i.e all that support your currently installed django version.

This behaviour can be customized via the Django settings below.

Note however, that some fixers depend on other fixers, so it's advised to be consistent and always include contiguous series of fixers around your current version (ex. if you use Django1.11, apply fixers from Django1.8 up to Django1.11, or up to Django2.X if yo want some forward compatibility as well). DCP filters out, by himself, fixers which are useless for your Django version.

You may provide a "settings" dictionary directly to the patch() method, in which case your DCP django settings will be completely ignored (only library defaults will be used as fallbacks)::

    django_compat_patcher.patch(settings=dict(DCP_INCLUDE_FIXER_IDS=["my_fixer_id"]))

Note that exclusion filters have precedence over inclusion ones.


DCP_INCLUDE_FIXER_IDS
*********************

List of fixer identifiers to include. If :code:`"*"` is used, then all fixers are included.

In rare case of name conflicts when using several registries at once, you may use qualified qualified fixer names like "fixer_family|fixer_id".

| **Default:** :code:`"*"`
| **Type:** List of strings, or :code:`"*"`
| **Example:** :code:`DCP_INCLUDE_FIXER_IDS = ['fix_deletion_templatetags_future_url']`


DCP_INCLUDE_FIXER_FAMILIES
**************************

List of fixer families to include. If :code:`"*"` is used, then all families are included.

Note: If you want to include only specific families, remember to replace the value :code:`"*" from :code:`DCP_INCLUDE_FIXER_IDS` by, for example, an empty list.

| **Default:** :code:`[]`
| **Type:** List of strings, or :code:`"*"`
| **Choices:** :code:`("djangoX.Y")` where :code:`X` and :code:`Y` are respectively the major and minor versions
| **Example:** :code:`DCP_INCLUDE_FIXER_FAMILIES = ["django1.9"]`


DCP_EXCLUDE_FIXER_IDS
*********************

List of fixer identifiers to exclude. If :code:`"*"` is used, then all fixers are excluded.

In rare case of name conflicts when using several registries at once, you may use qualified qualified fixer names like "fixer_family|fixer_id".

Note: The "EXCLUDE" filters are applied AFTER the "INCLUDE" ones, and so take precedence.

| **Default:** :code:`[]`
| **Type:** List of strings, or :code:`"*"`
| **Example:** :code:`DCP_EXCLUDE_FIXER_IDS = ['fix_deletion_templatetags_future_url']`


DCP_EXCLUDE_FIXER_FAMILIES
**************************

List of fixer families to exclude. If :code:`"*"` is used, then all families are excluded.

Note: The "EXCLUDE" filters are applied AFTER the "INCLUDE" ones, and so take precedence.

| **Default:** :code:`[]`
| **Type:** List of strings, or :code:`"*"`
| **Choices:** :code:`("djangoX.Y")` where :code:`X` and :code:`Y` are respectively the major and minor versions
| **Example:** :code:`DCP_EXCLUDE_FIXER_FAMILIES = ["django1.6", "django1.9"]`


DCP_PATCH_INJECTED_OBJECTS
***************************

By default, the patcher adds a :code:`__dcp_injected__ = True` attribute to the injected objects (callables, classes, modules, attributes...), when possible, to differentiate them from original ones. Set this setting to True to automatically choose the attribute name, or False to disable the feature.

| **Default:** :code:`"__dcp_injected__"`
| **Type:** Str (or Boolean)
| **Example:** :code:`DCP_PATCH_INJECTED_OBJECTS = False`


DCP_ENABLE_WARNINGS
***************************

If True, compatibility shims emit python warnings (:code:`warnings.warn(...)`) when they are imported/used,
to help detect deprecated code. These warnings are mostly subclasses of :code:`DeprecationWarning` (ex. :code:`RemovedInDjango19Warning`).

Once emitted, the handling of warnings depends on your setup (python command line flags, logging config...), see the `official doc on warnings <https://docs.python.org/3/library/warnings.html>`_ for more information.

| **Default:** :code:`True`
| **Type:** Boolean
| **Example:** :code:`DCP_ENABLE_WARNINGS = False`


DCP_LOGGING_LEVEL
***************************

The patch() system of DCP can output to *STDERR* which fixers are getting applied, and provide debug information (ex. for which reason a specific fixer was discarded).

This setting sets the logging level of that information stream, which is typically only viewed at django startup. A value :code:`None` disables DCP logging entirely.

Note that DCP does NOT actually use stdlib loggers, because it mostly performs operations before Django logging has been setup (ex. using the LOGGING setting), so log entries would most probably get discarded.

| **Default:** :code:`"INFO"`
| **Type:** Logging level string, or None
| **Example:** :code:`DCP_LOGGING_LEVEL = "DEBUG"`



Table of fixers
===============

There are currently 36 available fixers.

 
| Fixer and its ID                                                                                                                                                                                                                | Fixer family                                                                                                                                                                                                                    | Min version                                                                                                                                                                                                                     | Max version                                                                                                                                                                                                                     |
 
| **Preserve the request.raw_post_data alias for request.body.** (:code:`fix_deletion_http_request_HttpRequest_raw_post_data`)                                                                                                    | django1.6                                                                                                                                                                                                                       | 1.6                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Keep 'django.contrib.comments' as an import alias for the now external package    'django_comments' (django-contrib-comments on pypi) ; the latter must be installed separately.** (:code:`fix_outsourcing_contrib_comments`) | django1.8                                                                                                                                                                                                                       | 1.8                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Preserve the get_formsets method of ModelAdmin** (:code:`fix_deletion_contrib_admin_ModelAdmin_get_formsets`)                                                                                                                 | django1.9                                                                                                                                                                                                                       | 1.9                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Preserve contrib.sites.models.RequestSite alias.** (:code:`fix_deletion_contrib_sites_models_RequestSite`)                                                                                                                    | django1.9                                                                                                                                                                                                                       | 1.9                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Preserve contrib.sites.models.get_current_site alias.** (:code:`fix_deletion_contrib_sites_models_get_current_site`)                                                                                                          | django1.9                                                                                                                                                                                                                       | 1.9                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Preserve the `request.REQUEST` attribute, merging parameters from GET** (:code:`fix_deletion_core_handlers_wsgi_WSGIRequest_REQUEST`)                                                                                         | django1.9                                                                                                                                                                                                                       | 1.9                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Preserve the fallback to AppCommand.handle_app() method in django management commands.** (:code:`fix_deletion_core_management_base_AppCommand_handle_app`)                                                                    | django1.9                                                                                                                                                                                                                       | 1.9                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Preserve the IPAddressField form field, now superseded by GenericIPAddressField** (:code:`fix_deletion_forms_fields_IPAddressField`)                                                                                          | django1.9                                                                                                                                                                                                                       | 1.9                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Preserve the `ssi` tag in the `future` templatetags library.** (:code:`fix_deletion_templatetags_future_ssi`)                                                                                                                 | django1.9                                                                                                                                                                                                                       | 1.9                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Preserve the `url` tag in the `future` templatetags library.** (:code:`fix_deletion_templatetags_future_url`)                                                                                                                 | django1.9                                                                                                                                                                                                                       | 1.9                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Preserve the MergeDict util datastructure** (:code:`fix_deletion_utils_datastructures_MergeDict`)                                                                                                                             | django1.9                                                                                                                                                                                                                       | 1.9                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Preserve the SortedDict util datastructure** (:code:`fix_deletion_utils_datastructures_SortedDict`)                                                                                                                           | django1.9                                                                                                                                                                                                                       | 1.9                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Preserve the dictconfig util file** (:code:`fix_deletion_utils_dictconfig`)                                                                                                                                                   | django1.9                                                                                                                                                                                                                       | 1.9                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Preserve utils.functional.memoize() utility** (:code:`fix_deletion_utils_functional_memoize`)                                                                                                                                 | django1.9                                                                                                                                                                                                                       | 1.9                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Preserve the importlib util file** (:code:`fix_deletion_utils_importlib`)                                                                                                                                                     | django1.9                                                                                                                                                                                                                       | 1.9                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Preserve the tzinfo util file** (:code:`fix_deletion_utils_tzinfo`)                                                                                                                                                           | django1.9                                                                                                                                                                                                                       | 1.9                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Preserve the unittest util file** (:code:`fix_deletion_utils_unittest`)                                                                                                                                                       | django1.9                                                                                                                                                                                                                       | 1.9                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Support passing views to url() as dotted strings instead of view objects.** (:code:`fix_behaviour_conf_urls_url`)                                                                                                             | django1.10                                                                                                                                                                                                                      | 1.10                                                                                                                                                                                                                            |                                                                                                                                                                                                                                 |
 
| **Preserve the ability to call urlresolver on dotted string view,    instead of explicit view name.** (:code:`fix_behaviour_core_urlresolvers_reverse_with_prefix`)                                                             | django1.10                                                                                                                                                                                                                      | 1.10                                                                                                                                                                                                                            |                                                                                                                                                                                                                                 |
 
| **Preserve support for a single '=' sign in {% if %} tag.** (:code:`fix_behaviour_template_smartif_OPERATORS_equals`)                                                                                                           | django1.10                                                                                                                                                                                                                      | 1.10                                                                                                                                                                                                                            |                                                                                                                                                                                                                                 |
 
| **Restore support for dotted-string view parameter in RegexURLPattern, instead passing a view object.** (:code:`fix_behaviour_urls_resolvers_RegexURLPattern`)                                                                  | django1.10                                                                                                                                                                                                                      | 1.10                                                                                                                                                                                                                            |                                                                                                                                                                                                                                 |
 
| **Preserve the patterns() builder for django urls.** (:code:`fix_deletion_conf_urls_patterns`)                                                                                                                                  | django1.10                                                                                                                                                                                                                      | 1.10                                                                                                                                                                                                                            |                                                                                                                                                                                                                                 |
 
| **Preserve the "ssi" default template tag.** (:code:`fix_deletion_template_defaulttags_ssi`)                                                                                                                                    | django1.10                                                                                                                                                                                                                      | 1.10                                                                                                                                                                                                                            |                                                                                                                                                                                                                                 |
 
| **Preserve the "future" templatetags library, with its improved `firstof` and `cycle` tags.** (:code:`fix_deletion_templatetags_future`)                                                                                        | django1.10                                                                                                                                                                                                                      | 1.10                                                                                                                                                                                                                            |                                                                                                                                                                                                                                 |
 
| **Put a forward compatibility import path for django.urls, which replaces django.core.urlresolvers** (:code:`fix_incoming_urls_submodule`)                                                                                      | django1.10                                                                                                                                                                                                                      |                                                                                                                                                                                                                                 | 1.10                                                                                                                                                                                                                            |
 
| **Preserve the "future" templatetags library, with its improved `firstof` and `cycle` tags.** (:code:`fix_behaviour_widget_build_attrs`)                                                                                        | django1.11                                                                                                                                                                                                                      | 1.11                                                                                                                                                                                                                            |                                                                                                                                                                                                                                 |
 
| **Keep accepting a 3-tuple (urlconf_module, app_name, namespace) as first argument of include(),    instead of providing namespace argument directly to include()** (:code:`fix_behaviour_conf_urls_include_3tuples`)           | django2.0                                                                                                                                                                                                                       | 2.0                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Let "on_delete" parameter of ForeignKey and OneToOneField be optional, defaulting to CASCADE.** (:code:`fix_behaviour_db_models_fields_related_ForeignKey_OneToOneField`)                                                     | django2.0                                                                                                                                                                                                                       | 2.0                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Preserve django.core.urlresolvers module, now replaced by django.urls.** (:code:`fix_deletion_core_urlresolvers`)                                                                                                             | django2.0                                                                                                                                                                                                                       | 2.0                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Preserve the Context.has_key() utility, replaced by "in" operator use.** (:code:`fix_deletion_template_context_Context_has_key`)                                                                                              | django2.0                                                                                                                                                                                                                       | 2.0                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Preserve the assignment_tag() helper, superseded by simple_tag().** (:code:`fix_deletion_template_library_assignment_tag`)                                                                                                    | django2.0                                                                                                                                                                                                                       | 2.0                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Preserve RegexURLPattern and RegexURLResolver in django.urls, which disappeared due to DEP 0201.** (:code:`fix_deletion_urls_RegexURLPattern_RegexURLResolver`)                                                               | django2.0                                                                                                                                                                                                                       | 2.0                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Preserve the allow_lazy() utility, superseded by keep_lazy().** (:code:`fix_deletion_utils_functional_allow_lazy`)                                                                                                            | django2.0                                                                                                                                                                                                                       | 2.0                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Preserve the javascript_catalog() and json_catalog() i18n views, superseded by class-based views.** (:code:`fix_deletion_views_i18n_javascript_and_json_catalog`)                                                             | django2.0                                                                                                                                                                                                                       | 2.0                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Restore the behaviour where the "renderer" parameter of Widget.render() may not be supported by subclasses.** (:code:`fix_behaviour_widget_render_forced_renderer`)                                                           | django2.1                                                                                                                                                                                                                       | 2.1                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
| **Preserve django.utils.translation.string_concat(), superseded by django.utils.text.format_lazy().** (:code:`fix_deletion_utils_translation_string_concat`)                                                                    | django2.1                                                                                                                                                                                                                       | 2.1                                                                                                                                                                                                                             |                                                                                                                                                                                                                                 |
 
