File: patches.py

package info (click to toggle)
python-sphinxcontrib-django 2.5-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 636 kB
  • sloc: python: 1,450; makefile: 20; sh: 6
file content (93 lines) | stat: -rw-r--r-- 3,384 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
"""
This module contains patches for Django to improve its interaction with Sphinx.
"""
import contextlib

from django import apps, forms, test
from django.db import models

try:
    from django.contrib.postgres import fields as postgres_fields
    from django.contrib.postgres import forms as postgres_forms

    POSTGRES = True
except ModuleNotFoundError:
    # In case postgres is not used, pass
    POSTGRES = False

try:
    from mptt.managers import TreeManager

    MPTT = True
except ModuleNotFoundError:
    # In case postgres is not used, pass
    MPTT = False


def patch_django_for_autodoc():
    """
    Fix the appearance of some classes in autodoc.
    E.g. the absolute path to the base model class is ``django.db.models.base.Model``, but its
    intersphinx mapping path is ``django.db.models.Model``.

    This also avoids query evaluation.
    """
    # Fix Django's manager appearance
    models.manager.ManagerDescriptor.__get__ = (
        lambda self, *args, **kwargs: self.manager
    )

    # Stop Django from executing DB queries
    models.QuerySet.__repr__ = lambda self: self.__class__.__name__

    # Fix django-mptt TreeManager in Django >=3.1
    if MPTT:
        TreeManager.get_queryset = models.Manager.get_queryset

    # Module paths which are documented in the parent module
    DJANGO_MODULE_PATHS = {
        "django.db.models": [
            models.base,
            models.fields,
            models.fields.files,
            models.fields.related,
        ],
        "django.forms": [forms.forms, forms.fields, forms.models, forms.widgets],
        "django.test": [test],
        "django.apps": [apps],
    }

    # Support django.db.models.JSONField in Django >= 3.1
    if hasattr(models.fields, "json"):
        DJANGO_MODULE_PATHS["django.db.models"].append(models.fields.json)

    # Support postgres fields if used
    if POSTGRES:
        DJANGO_MODULE_PATHS["django.contrib.postgres.forms"] = [postgres_forms.array]
        # Support django.contrib.postgres.forms.JSONField in Django <= 3.2
        if hasattr(postgres_forms, "jsonb"):
            DJANGO_MODULE_PATHS["django.contrib.postgres.forms"].append(
                postgres_forms.jsonb
            )
            postgres_forms.jsonb.__all__ = ("JSONString", "JSONField")
        DJANGO_MODULE_PATHS["django.contrib.postgres.fields"] = [postgres_fields.array]
        if hasattr(postgres_fields, "jsonb"):
            DJANGO_MODULE_PATHS["django.contrib.postgres.forms"].append(
                postgres_fields.jsonb
            )
        postgres_forms.array.__all__ = ("SimpleArrayField", "SplitArrayField")

    # Add __all__ where missing
    models.base.__all__ = ("Model", "FilteredRelation")
    models.fields.files.__all__ = ("FileField", "ImageField")
    models.fields.related.__all__ = ("ForeignKey", "OneToOneField", "ManyToManyField")

    # Set the __module__ to the parent module to make sure intersphinx mappings work as expected
    for parent_module_str, django_modules in DJANGO_MODULE_PATHS.items():
        for django_module in django_modules:
            for module_class in map(django_module.__dict__.get, django_module.__all__):
                with contextlib.suppress(AttributeError):
                    module_class.__module__ = parent_module_str

    # Fix module path of model manager
    models.manager.Manager.__module__ = "django.db.models"