or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdmodel-annotations.mdmonkey-patching.mdprotocols.mdqueryset-types.mdstring-types.md

monkey-patching.mddocs/

0

# Runtime Monkey-Patching

1

2

The core functionality of django-stubs-ext that dynamically adds generic type support to Django classes at runtime. This system enables proper type parameterization for Django classes that don't natively support the `__class_getitem__` method.

3

4

## Capabilities

5

6

### Main Patching Function

7

8

Applies runtime monkey-patches to Django classes for generic type support. This function should be called once in your Django application settings.

9

10

```python { .api }

11

def monkeypatch(

12

extra_classes: Optional[Iterable[type]] = None,

13

include_builtins: bool = True

14

) -> None:

15

"""

16

Monkey patch Django as necessary to work properly with mypy.

17

18

Parameters:

19

- extra_classes: Optional iterable of additional classes to patch

20

- include_builtins: Whether to add reveal_type and reveal_locals helpers

21

22

Returns:

23

None

24

"""

25

```

26

27

### Usage Examples

28

29

Basic usage in Django settings:

30

31

```python

32

# In your Django settings file

33

import django_stubs_ext

34

35

django_stubs_ext.monkeypatch()

36

```

37

38

With additional classes:

39

40

```python

41

import django_stubs_ext

42

from my_app.models import CustomModel

43

44

# Patch additional classes

45

django_stubs_ext.monkeypatch(extra_classes=[CustomModel])

46

```

47

48

Without mypy helpers:

49

50

```python

51

import django_stubs_ext

52

53

# Skip adding reveal_type and reveal_locals to builtins

54

django_stubs_ext.monkeypatch(include_builtins=False)

55

```

56

57

### Supported Django Classes

58

59

The following Django classes are automatically patched when appropriate for the detected Django version:

60

61

#### Always Patched Classes

62

- `django.contrib.admin.ModelAdmin`

63

- `django.views.generic.detail.SingleObjectMixin`

64

- `django.views.generic.edit.FormMixin`

65

- `django.views.generic.edit.DeletionMixin`

66

- `django.views.generic.list.MultipleObjectMixin`

67

- `django.contrib.admin.options.BaseModelAdmin`

68

- `django.db.models.fields.Field`

69

- `django.core.paginator.Paginator`

70

- `django.forms.formsets.BaseFormSet`

71

- `django.forms.models.BaseModelForm`

72

- `django.forms.models.BaseModelFormSet`

73

- `django.contrib.syndication.views.Feed`

74

- `django.contrib.sitemaps.Sitemap`

75

- `django.contrib.messages.views.SuccessMessageMixin`

76

- `django.core.files.utils.FileProxyMixin`

77

- `django.db.models.lookups.Lookup`

78

- `django.utils.connection.BaseConnectionHandler`

79

- `django.db.models.expressions.ExpressionWrapper`

80

81

#### Version-Specific Classes

82

- `django.db.models.query.QuerySet` (Django ≤ 3.1)

83

- `django.db.models.manager.BaseManager` (Django ≤ 3.1)

84

- `django.db.models.fields.related.ForeignKey` (Django ≤ 4.1)

85

86

### Version Compatibility

87

88

The monkey-patching system automatically detects your Django version and only applies patches needed for your specific version:

89

90

```python

91

from django import VERSION

92

93

# Only patch classes that need it for the current Django version

94

suited_for_this_version = filter(

95

lambda spec: spec.version is None or VERSION[:2] <= spec.version,

96

_need_generic,

97

)

98

```

99

100

### Builtins Integration

101

102

When `include_builtins=True` (default), the following helpers are added to Python's builtins:

103

104

```python { .api }

105

def reveal_type(obj: Any) -> None:

106

"""Mypy helper function for type inspection (no-op at runtime)."""

107

108

def reveal_locals() -> None:

109

"""Mypy helper function for local variable inspection (no-op at runtime)."""

110

```

111

112

## Types

113

114

```python { .api }

115

from typing import Any, Generic, Iterable, List, Optional, Tuple, Type, TypeVar

116

117

_T = TypeVar("_T")

118

_VersionSpec = Tuple[int, int]

119

120

class MPGeneric(Generic[_T]):

121

"""

122

Metadata container for generic classes needing monkeypatching.

123

124

The version param is optional, and None means version-independent patching.

125

"""

126

127

def __init__(self, cls: Type[_T], version: Optional[_VersionSpec] = None) -> None:

128

"""Set the data fields, basic constructor."""

129

130

def __repr__(self) -> str:

131

"""Better representation in tests and debug."""

132

```