mirror of
https://github.com/davidhalter/django-stubs.git
synced 2025-12-11 14:31:56 +08:00
Compare commits
3 Commits
1.6.0
...
new-readme
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b846c0f2ed | ||
|
|
7af2adb665 | ||
|
|
0052a83968 |
@@ -4,19 +4,10 @@ dist: xenial
|
|||||||
sudo: required
|
sudo: required
|
||||||
jobs:
|
jobs:
|
||||||
include:
|
include:
|
||||||
- name: Run plugin test suite with python 3.8
|
|
||||||
python: 3.8
|
|
||||||
script: 'pytest'
|
|
||||||
|
|
||||||
- name: Run plugin test suite with python 3.7
|
- name: Run plugin test suite with python 3.7
|
||||||
python: 3.7
|
python: 3.7
|
||||||
script: 'pytest'
|
script: 'pytest'
|
||||||
|
|
||||||
- name: Typecheck Django 3.0 test suite with python 3.8
|
|
||||||
python: 3.8
|
|
||||||
script: |
|
|
||||||
python ./scripts/typecheck_tests.py --django_version=3.0
|
|
||||||
|
|
||||||
- name: Typecheck Django 3.0 test suite with python 3.7
|
- name: Typecheck Django 3.0 test suite with python 3.7
|
||||||
python: 3.7
|
python: 3.7
|
||||||
script: |
|
script: |
|
||||||
|
|||||||
111
CONTRIBUTING.md
111
CONTRIBUTING.md
@@ -1,111 +0,0 @@
|
|||||||
# How to contribute
|
|
||||||
|
|
||||||
## Tutorials
|
|
||||||
|
|
||||||
If you want to start working on this project,
|
|
||||||
you will need to get familiar with these projects:
|
|
||||||
|
|
||||||
- [Django docs](https://docs.djangoproject.com/en/dev/)
|
|
||||||
- [Typing in Python](https://inventwithpython.com/blog/2019/11/24/type-hints-for-busy-python-programmers/)
|
|
||||||
- [How to write custom mypy plugins](https://mypy.readthedocs.io/en/stable/extending_mypy.html)
|
|
||||||
- [Typechecking Django and DRF](https://sobolevn.me/2019/08/typechecking-django-and-drf) guide
|
|
||||||
- [Testing mypy stubs, plugins, and types](https://sobolevn.me/2019/08/testing-mypy-types) guide
|
|
||||||
|
|
||||||
It is also recommended to take a look at these resources:
|
|
||||||
|
|
||||||
- [Awesome Python Typing](https://github.com/typeddjango/awesome-python-typing)
|
|
||||||
|
|
||||||
|
|
||||||
## Dev documentation
|
|
||||||
|
|
||||||
TODO
|
|
||||||
|
|
||||||
|
|
||||||
## Dependencies
|
|
||||||
|
|
||||||
We use `pip` to manage the dependencies.
|
|
||||||
|
|
||||||
To install them you would need to activate your `virtualenv` and run `install` command:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip install -r ./dev-requirements.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Tests and linters
|
|
||||||
|
|
||||||
We use `mypy`, `pytest`, `flake8`, and `black` for quality control.
|
|
||||||
Here's [how we run our CI](https://github.com/typeddjango/django-stubs/blob/master/.travis.yml).
|
|
||||||
|
|
||||||
### Typechecking
|
|
||||||
|
|
||||||
To run typechecking use:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mypy ./mypy_django_plugin
|
|
||||||
```
|
|
||||||
|
|
||||||
### Testing
|
|
||||||
|
|
||||||
There are unit tests and type-related tests.
|
|
||||||
|
|
||||||
To run unit tests:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pytest
|
|
||||||
```
|
|
||||||
|
|
||||||
Type-related tests ensure that different Django versions do work correctly.
|
|
||||||
To run type-related tests:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
python ./scripts/typecheck_tests.py --django_version=2.2
|
|
||||||
python ./scripts/typecheck_tests.py --django_version=3.0
|
|
||||||
```
|
|
||||||
|
|
||||||
Currently we only support two Django versions.
|
|
||||||
|
|
||||||
### Linting
|
|
||||||
|
|
||||||
To run auto-formatting:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
isort -rc .
|
|
||||||
black django-stubs/
|
|
||||||
```
|
|
||||||
|
|
||||||
To run linting:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
flake8
|
|
||||||
flake8 --config flake8-pyi.ini
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Submitting your code
|
|
||||||
|
|
||||||
We use [trunk based](https://trunkbaseddevelopment.com/)
|
|
||||||
development (we also sometimes call it `wemake-git-flow`).
|
|
||||||
|
|
||||||
What the point of this method?
|
|
||||||
|
|
||||||
1. We use protected `master` branch,
|
|
||||||
so the only way to push your code is via pull request
|
|
||||||
2. We use issue branches: to implement a new feature or to fix a bug
|
|
||||||
create a new branch named `issue-$TASKNUMBER`
|
|
||||||
3. Then create a pull request to `master` branch
|
|
||||||
4. We use `git tag`s to make releases, so we can track what has changed
|
|
||||||
since the latest release
|
|
||||||
|
|
||||||
So, this way we achieve an easy and scalable development process
|
|
||||||
which frees us from merging hell and long-living branches.
|
|
||||||
|
|
||||||
In this method, the latest version of the app is always in the `master` branch.
|
|
||||||
|
|
||||||
|
|
||||||
## Other help
|
|
||||||
|
|
||||||
You can contribute by spreading a word about this library.
|
|
||||||
It would also be a huge contribution to write
|
|
||||||
a short article on how you are using this project.
|
|
||||||
You can also share your best practices with us.
|
|
||||||
34
README.md
34
README.md
@@ -15,7 +15,7 @@ This package contains [type stubs](https://www.python.org/dev/peps/pep-0561/) an
|
|||||||
pip install django-stubs
|
pip install django-stubs
|
||||||
```
|
```
|
||||||
|
|
||||||
See [Configuration](#configuration) section to get started.
|
See [Configutation](#configuration) section to get started.
|
||||||
|
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
@@ -47,10 +47,7 @@ We rely on different `django` and `mypy` versions:
|
|||||||
|
|
||||||
| django-stubs | mypy version | django version | python version
|
| django-stubs | mypy version | django version | python version
|
||||||
| ------------ | ---- | ---- | ---- |
|
| ------------ | ---- | ---- | ---- |
|
||||||
| 1.6.0 | 0.780 | 2.2.x \|\| 3.x | ^3.6
|
| 1.3.0 | 0.750 | 2.2.x | ^3.6
|
||||||
| 1.5.0 | 0.770 | 2.2.x \|\| 3.x | ^3.6
|
|
||||||
| 1.4.0 | 0.760 | 2.2.x \|\| 3.x | ^3.6
|
|
||||||
| 1.3.0 | 0.750 | 2.2.x \|\| 3.x | ^3.6
|
|
||||||
| 1.2.0 | 0.730 | 2.2.x | ^3.6
|
| 1.2.0 | 0.730 | 2.2.x | ^3.6
|
||||||
| 1.1.0 | 0.720 | 2.2.x | ^3.6
|
| 1.1.0 | 0.720 | 2.2.x | ^3.6
|
||||||
| 0.12.x | old semantic analyzer (<0.711), dmypy support | 2.1.x | ^3.6
|
| 0.12.x | old semantic analyzer (<0.711), dmypy support | 2.1.x | ^3.6
|
||||||
@@ -58,56 +55,51 @@ We rely on different `django` and `mypy` versions:
|
|||||||
|
|
||||||
## FAQ
|
## FAQ
|
||||||
|
|
||||||
### Is this an official Django project?
|
> Is this an official Django project?
|
||||||
|
|
||||||
No, it is not. We are indendepent from Django at the moment.
|
No, it is not. We are indendepent from Django at the moment.
|
||||||
There's a [proposal](https://github.com/django/deps/pull/65) to merge our project into the Django itself.
|
There's a [proposal](https://github.com/django/deps/pull/65) to merge our project into the Django itself.
|
||||||
You show your support by linking the PR.
|
You show your support by linking the PR.
|
||||||
|
|
||||||
### Is it safe to use this in production?
|
> Is it safe to use this in production?
|
||||||
|
|
||||||
Yes, it is! This project does not affect your runtime at all.
|
Yes, it is! This project does not affect your runtime at all.
|
||||||
It only affects `mypy` type checking process.
|
It only affects `mypy` type checking process.
|
||||||
|
|
||||||
But, it does not make any sense to use this project without `mypy`.
|
But, it does not make sense to use this project without `mypy`.
|
||||||
|
|
||||||
### mypy crashes when I run it with this plugin installed
|
> mypy crashes when I run it with this plugin installed
|
||||||
|
|
||||||
Current implementation uses Django runtime to extract models information, so it will crash, if your installed apps or `models.py` is not correct. For this same reason, you cannot use `reveal_type` inside global scope of any Python file that will be executed for `django.setup()`.
|
Current implementation uses Django runtime to extract models information, so it will crash, if your installed apps `models.py` is not correct. For this same reason, you cannot use `reveal_type` inside global scope of any Python file that will be executed for `django.setup()`.
|
||||||
|
|
||||||
In other words, if your `manage.py runserver` crashes, mypy will crash too.
|
In other words, if your `manage.py runserver` crashes, mypy will crash too.
|
||||||
You can also run `mypy` with [`--tb`](https://mypy.readthedocs.io/en/stable/command_line.html#cmdoption-mypy-show-traceback)
|
You can also run `mypy` with [`--tb`](https://mypy.readthedocs.io/en/stable/command_line.html#cmdoption-mypy-show-traceback)
|
||||||
option to get extra information about the error.
|
option to get extra information about the error.
|
||||||
|
|
||||||
### I cannot use QuerySet or Manager with type annotations
|
> I cannot use QuerySet or Manager with type annotations
|
||||||
|
|
||||||
You can get a `TypeError: 'type' object is not subscriptable`
|
You can get a `TypeError: 'type' object is not subscriptable`
|
||||||
when you will try to use `QuerySet[MyModel]` or `Manager[MyModel]`.
|
when you will try to use `QuerySet[MyModel]` or `Manager[MyModel]`.
|
||||||
|
|
||||||
This happens because Django classes do not support [`__class_getitem__`](https://www.python.org/dev/peps/pep-0560/#class-getitem) magic method.
|
This happens because Django classes do not support [`__class_getitem__`](https://www.python.org/dev/peps/pep-0560/#class-getitem) magic method.
|
||||||
|
|
||||||
You can use strings instead: `'QuerySet[MyModel]'` and `'Manager[MyModel]'`, this way it will work as a type for `mypy` and as a regular `str` in runtime.
|
There are several things you can use strings instead: `'QuerySet[MyModel]'` and `'Manager[MyModel'`, this way it will work as a type for `mypy` and as a regular `str` in runtime.
|
||||||
|
|
||||||
Currently we [are working](https://github.com/django/django/pull/12405) on providing `__class_getitem__` to the classes where we need them.
|
Currently we [are working](https://github.com/django/django/pull/12405) on providing `__class_getitem__` to the classes where we need them.
|
||||||
|
|
||||||
### How can I create a HttpRequest that's guaranteed to have an authenticated user?
|
> How can I use HttpRequest with custom user model?
|
||||||
|
|
||||||
Django's built in `HttpRequest` has the attribute `user` that resolves to the type
|
You can subclass standard request like so:
|
||||||
```python
|
|
||||||
Union[User, AnonymousUser]
|
|
||||||
```
|
|
||||||
where `User` is the user model specified by the `AUTH_USER_MODEL` setting.
|
|
||||||
|
|
||||||
If you want a `HttpRequest` that you can type-annotate with where you know that the user is authenticated you can subclass the normal `HttpRequest` class like so:
|
|
||||||
```python
|
```python
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
from my_user_app.models import MyUser
|
from my_user_app.models import MyUser
|
||||||
|
|
||||||
class AuthenticatedHttpRequest(HttpRequest):
|
class MyRequest(HttpRequest):
|
||||||
user: MyUser
|
user: MyUser
|
||||||
```
|
```
|
||||||
|
|
||||||
And then use `AuthenticatedHttpRequest` instead of the standard `HttpRequest` for when you know that the user is authenticated. For example in views using the `@login_required` decorator.
|
And then use `MyRequest` instead of standard `HttpRequest` inside your project.
|
||||||
|
|
||||||
|
|
||||||
## Related projects
|
## Related projects
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
black
|
black
|
||||||
pytest-mypy-plugins==1.3.0
|
pytest-mypy-plugins==1.2.0
|
||||||
psycopg2-binary
|
psycopg2
|
||||||
flake8==3.7.9
|
flake8==3.7.9
|
||||||
flake8-pyi==19.3.0
|
flake8-pyi==19.3.0
|
||||||
isort==4.3.21
|
isort==4.3.21
|
||||||
gitpython==3.1.0
|
gitpython==3.0.5
|
||||||
-e .
|
-e .
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from typing import Any, Callable, Dict, Iterator, List, Optional, Tuple, Union, Iterable
|
from typing import Any, Callable, Dict, Iterator, List, Optional, Tuple, Union, Iterable
|
||||||
|
|
||||||
|
from django.contrib.auth.forms import AdminPasswordChangeForm
|
||||||
from django.forms.boundfield import BoundField
|
from django.forms.boundfield import BoundField
|
||||||
from django.forms.forms import BaseForm
|
|
||||||
from django.forms.utils import ErrorDict
|
from django.forms.utils import ErrorDict
|
||||||
from django.forms.widgets import Media, Widget
|
from django.forms.widgets import Media, Widget
|
||||||
from django.utils.safestring import SafeText
|
from django.utils.safestring import SafeText
|
||||||
@@ -23,7 +23,7 @@ class AdminForm:
|
|||||||
readonly_fields: Any = ...
|
readonly_fields: Any = ...
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
form: BaseForm,
|
form: AdminPasswordChangeForm,
|
||||||
fieldsets: List[Tuple[None, Dict[str, List[str]]]],
|
fieldsets: List[Tuple[None, Dict[str, List[str]]]],
|
||||||
prepopulated_fields: Dict[Any, Any],
|
prepopulated_fields: Dict[Any, Any],
|
||||||
readonly_fields: Optional[Iterable[Any]] = ...,
|
readonly_fields: Optional[Iterable[Any]] = ...,
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from typing import Any, Callable, Dict, Iterator, List, Optional, Sequence, Set, Tuple, Type, Union, Mapping, TypeVar
|
from typing import Any, Callable, Dict, Iterator, List, Optional, Sequence, Set, Tuple, Type, Union
|
||||||
|
|
||||||
from django.forms.forms import BaseForm
|
|
||||||
from django.forms.formsets import BaseFormSet
|
|
||||||
from typing_extensions import Literal, TypedDict
|
|
||||||
|
|
||||||
from django.contrib.admin.filters import ListFilter
|
from django.contrib.admin.filters import ListFilter
|
||||||
from django.contrib.admin.models import LogEntry
|
from django.contrib.admin.models import LogEntry
|
||||||
@@ -30,10 +26,8 @@ from django.db.models.fields import Field
|
|||||||
|
|
||||||
IS_POPUP_VAR: str
|
IS_POPUP_VAR: str
|
||||||
TO_FIELD_VAR: str
|
TO_FIELD_VAR: str
|
||||||
HORIZONTAL: Literal[1] = ...
|
HORIZONTAL: Any
|
||||||
VERTICAL: Literal[2] = ...
|
VERTICAL: Any
|
||||||
|
|
||||||
_Direction = Union[Literal[1], Literal[2]]
|
|
||||||
|
|
||||||
def get_content_type_for_model(obj: Union[Type[Model], Model]) -> ContentType: ...
|
def get_content_type_for_model(obj: Union[Type[Model], Model]) -> ContentType: ...
|
||||||
def get_ul_class(radio_style: int) -> str: ...
|
def get_ul_class(radio_style: int) -> str: ...
|
||||||
@@ -43,35 +37,21 @@ class IncorrectLookupParameters(Exception): ...
|
|||||||
FORMFIELD_FOR_DBFIELD_DEFAULTS: Any
|
FORMFIELD_FOR_DBFIELD_DEFAULTS: Any
|
||||||
csrf_protect_m: Any
|
csrf_protect_m: Any
|
||||||
|
|
||||||
class _OptionalFieldOpts(TypedDict, total=False):
|
|
||||||
classes: Sequence[str]
|
|
||||||
description: str
|
|
||||||
|
|
||||||
class _FieldOpts(_OptionalFieldOpts, total=True):
|
|
||||||
fields: Sequence[Union[str, Sequence[str]]]
|
|
||||||
|
|
||||||
# Workaround for mypy issue, a Sequence type should be preferred here.
|
|
||||||
# https://github.com/python/mypy/issues/8921
|
|
||||||
# _FieldsetSpec = Sequence[Tuple[Optional[str], _FieldOpts]]
|
|
||||||
_T = TypeVar("_T")
|
|
||||||
_ListOrTuple = Union[Tuple[_T, ...], List[_T]]
|
|
||||||
_FieldsetSpec = _ListOrTuple[Tuple[Optional[str], _FieldOpts]]
|
|
||||||
|
|
||||||
class BaseModelAdmin:
|
class BaseModelAdmin:
|
||||||
autocomplete_fields: Sequence[str] = ...
|
autocomplete_fields: Any = ...
|
||||||
raw_id_fields: Sequence[str] = ...
|
raw_id_fields: Any = ...
|
||||||
fields: Sequence[Union[str, Sequence[str]]] = ...
|
fields: Any = ...
|
||||||
exclude: Sequence[str] = ...
|
exclude: Any = ...
|
||||||
fieldsets: _FieldsetSpec = ...
|
fieldsets: Any = ...
|
||||||
form: Type[BaseForm] = ...
|
form: Any = ...
|
||||||
filter_vertical: Sequence[str] = ...
|
filter_vertical: Any = ...
|
||||||
filter_horizontal: Sequence[str] = ...
|
filter_horizontal: Any = ...
|
||||||
radio_fields: Mapping[str, _Direction] = ...
|
radio_fields: Any = ...
|
||||||
prepopulated_fields: Mapping[str, Sequence[str]] = ...
|
prepopulated_fields: Any = ...
|
||||||
formfield_overrides: Mapping[Type[Field], Mapping[str, Any]] = ...
|
formfield_overrides: Any = ...
|
||||||
readonly_fields: Sequence[Union[str, Callable[[Model], Any]]] = ...
|
readonly_fields: Any = ...
|
||||||
ordering: Sequence[str] = ...
|
ordering: Any = ...
|
||||||
sortable_by: Sequence[str] = ...
|
sortable_by: Any = ...
|
||||||
view_on_site: bool = ...
|
view_on_site: bool = ...
|
||||||
show_full_result_count: bool = ...
|
show_full_result_count: bool = ...
|
||||||
checks_class: Any = ...
|
checks_class: Any = ...
|
||||||
@@ -113,7 +93,7 @@ class BaseModelAdmin:
|
|||||||
def has_module_permission(self, request: HttpRequest) -> bool: ...
|
def has_module_permission(self, request: HttpRequest) -> bool: ...
|
||||||
|
|
||||||
class ModelAdmin(BaseModelAdmin):
|
class ModelAdmin(BaseModelAdmin):
|
||||||
list_display: Sequence[Union[str, Callable[[Model], Any]]] = ...
|
list_display: Sequence[Union[str, Callable]] = ...
|
||||||
list_display_links: Optional[Sequence[Union[str, Callable]]] = ...
|
list_display_links: Optional[Sequence[Union[str, Callable]]] = ...
|
||||||
list_filter: Sequence[Union[str, Type[ListFilter], Tuple[str, Type[ListFilter]]]] = ...
|
list_filter: Sequence[Union[str, Type[ListFilter], Tuple[str, Type[ListFilter]]]] = ...
|
||||||
list_select_related: Union[bool, Sequence[str]] = ...
|
list_select_related: Union[bool, Sequence[str]] = ...
|
||||||
@@ -121,21 +101,21 @@ class ModelAdmin(BaseModelAdmin):
|
|||||||
list_max_show_all: int = ...
|
list_max_show_all: int = ...
|
||||||
list_editable: Sequence[str] = ...
|
list_editable: Sequence[str] = ...
|
||||||
search_fields: Sequence[str] = ...
|
search_fields: Sequence[str] = ...
|
||||||
date_hierarchy: Optional[str] = ...
|
date_hierarchy: Optional[Any] = ...
|
||||||
save_as: bool = ...
|
save_as: bool = ...
|
||||||
save_as_continue: bool = ...
|
save_as_continue: bool = ...
|
||||||
save_on_top: bool = ...
|
save_on_top: bool = ...
|
||||||
paginator: Type = ...
|
paginator: Any = ...
|
||||||
preserve_filters: bool = ...
|
preserve_filters: bool = ...
|
||||||
inlines: Sequence[Type[InlineModelAdmin]] = ...
|
inlines: Sequence[Type[InlineModelAdmin]] = ...
|
||||||
add_form_template: str = ...
|
add_form_template: Any = ...
|
||||||
change_form_template: str = ...
|
change_form_template: Any = ...
|
||||||
change_list_template: str = ...
|
change_list_template: Any = ...
|
||||||
delete_confirmation_template: str = ...
|
delete_confirmation_template: Any = ...
|
||||||
delete_selected_confirmation_template: str = ...
|
delete_selected_confirmation_template: Any = ...
|
||||||
object_history_template: str = ...
|
object_history_template: Any = ...
|
||||||
popup_response_template: str = ...
|
popup_response_template: Any = ...
|
||||||
actions: Sequence[Union[Callable[[ModelAdmin, HttpRequest, QuerySet], None], str]] = ...
|
actions: Any = ...
|
||||||
action_form: Any = ...
|
action_form: Any = ...
|
||||||
actions_on_top: bool = ...
|
actions_on_top: bool = ...
|
||||||
actions_on_bottom: bool = ...
|
actions_on_bottom: bool = ...
|
||||||
@@ -247,9 +227,9 @@ class ModelAdmin(BaseModelAdmin):
|
|||||||
def history_view(self, request: HttpRequest, object_id: str, extra_context: None = ...) -> HttpResponse: ...
|
def history_view(self, request: HttpRequest, object_id: str, extra_context: None = ...) -> HttpResponse: ...
|
||||||
|
|
||||||
class InlineModelAdmin(BaseModelAdmin):
|
class InlineModelAdmin(BaseModelAdmin):
|
||||||
model: Type[Model] = ...
|
model: Any = ...
|
||||||
fk_name: str = ...
|
fk_name: Any = ...
|
||||||
formset: BaseFormSet = ...
|
formset: Any = ...
|
||||||
extra: int = ...
|
extra: int = ...
|
||||||
min_num: Optional[int] = ...
|
min_num: Optional[int] = ...
|
||||||
max_num: Optional[int] = ...
|
max_num: Optional[int] = ...
|
||||||
@@ -258,8 +238,8 @@ class InlineModelAdmin(BaseModelAdmin):
|
|||||||
verbose_name_plural: Optional[str] = ...
|
verbose_name_plural: Optional[str] = ...
|
||||||
can_delete: bool = ...
|
can_delete: bool = ...
|
||||||
show_change_link: bool = ...
|
show_change_link: bool = ...
|
||||||
classes: Optional[Sequence[str]] = ...
|
classes: Any = ...
|
||||||
admin_site: AdminSite = ...
|
admin_site: Any = ...
|
||||||
parent_model: Any = ...
|
parent_model: Any = ...
|
||||||
opts: Any = ...
|
opts: Any = ...
|
||||||
has_registered_model: Any = ...
|
has_registered_model: Any = ...
|
||||||
|
|||||||
@@ -63,7 +63,6 @@ class AdminSite:
|
|||||||
def i18n_javascript(self, request: WSGIRequest, extra_context: Optional[Dict[Any, Any]] = ...) -> HttpResponse: ...
|
def i18n_javascript(self, request: WSGIRequest, extra_context: Optional[Dict[Any, Any]] = ...) -> HttpResponse: ...
|
||||||
def logout(self, request: WSGIRequest, extra_context: Optional[Dict[str, Any]] = ...) -> TemplateResponse: ...
|
def logout(self, request: WSGIRequest, extra_context: Optional[Dict[str, Any]] = ...) -> TemplateResponse: ...
|
||||||
def login(self, request: WSGIRequest, extra_context: Optional[Dict[str, Any]] = ...) -> HttpResponse: ...
|
def login(self, request: WSGIRequest, extra_context: Optional[Dict[str, Any]] = ...) -> HttpResponse: ...
|
||||||
def _build_app_dict(self, request: WSGIRequest, label: Optional[str] = ...) -> Dict[str, Any]: ...
|
|
||||||
def get_app_list(self, request: WSGIRequest) -> List[Any]: ...
|
def get_app_list(self, request: WSGIRequest) -> List[Any]: ...
|
||||||
def index(self, request: WSGIRequest, extra_context: Optional[Dict[str, Any]] = ...) -> TemplateResponse: ...
|
def index(self, request: WSGIRequest, extra_context: Optional[Dict[str, Any]] = ...) -> TemplateResponse: ...
|
||||||
def app_index(
|
def app_index(
|
||||||
|
|||||||
@@ -1,11 +1,7 @@
|
|||||||
from typing import Callable, Optional, TypeVar, overload
|
from typing import Callable, TypeVar, overload
|
||||||
|
|
||||||
_C = TypeVar("_C", bound=Callable)
|
_C = TypeVar("_C", bound=Callable)
|
||||||
@overload
|
@overload
|
||||||
def staff_member_required(
|
def staff_member_required(view_func: _C = ..., redirect_field_name: str = ..., login_url: str = ...) -> _C: ...
|
||||||
view_func: _C = ..., redirect_field_name: Optional[str] = ..., login_url: str = ...
|
|
||||||
) -> _C: ...
|
|
||||||
@overload
|
@overload
|
||||||
def staff_member_required(
|
def staff_member_required(view_func: None = ..., redirect_field_name: str = ..., login_url: str = ...) -> Callable: ...
|
||||||
view_func: None = ..., redirect_field_name: Optional[str] = ..., login_url: str = ...
|
|
||||||
) -> Callable: ...
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from typing import Any, List, Optional, Type, Union
|
|||||||
|
|
||||||
from django.contrib.auth.backends import ModelBackend
|
from django.contrib.auth.backends import ModelBackend
|
||||||
from django.contrib.auth.base_user import AbstractBaseUser
|
from django.contrib.auth.base_user import AbstractBaseUser
|
||||||
from django.contrib.auth.models import AnonymousUser
|
from django.contrib.auth.models import AbstractUser, AnonymousUser
|
||||||
from django.core.handlers.wsgi import WSGIRequest
|
from django.core.handlers.wsgi import WSGIRequest
|
||||||
from django.db.models.base import Model
|
from django.db.models.base import Model
|
||||||
from django.db.models.options import Options
|
from django.db.models.options import Options
|
||||||
@@ -29,6 +29,6 @@ def logout(request: HttpRequest) -> None: ...
|
|||||||
def get_user_model() -> Type[Model]: ...
|
def get_user_model() -> Type[Model]: ...
|
||||||
def get_user(request: HttpRequest) -> Union[AbstractBaseUser, AnonymousUser]: ...
|
def get_user(request: HttpRequest) -> Union[AbstractBaseUser, AnonymousUser]: ...
|
||||||
def get_permission_codename(action: str, opts: Options) -> str: ...
|
def get_permission_codename(action: str, opts: Options) -> str: ...
|
||||||
def update_session_auth_hash(request: HttpRequest, user: AbstractBaseUser) -> None: ...
|
def update_session_auth_hash(request: WSGIRequest, user: AbstractUser) -> None: ...
|
||||||
|
|
||||||
default_app_config: str
|
default_app_config: str
|
||||||
|
|||||||
@@ -1,15 +1,9 @@
|
|||||||
import sys
|
|
||||||
from typing import Any, Optional, Tuple, List, overload, TypeVar
|
from typing import Any, Optional, Tuple, List, overload, TypeVar
|
||||||
|
|
||||||
from django.db.models.base import Model
|
from django.db.models.base import Model
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
if sys.version_info < (3, 8):
|
|
||||||
from typing_extensions import Literal
|
|
||||||
else:
|
|
||||||
from typing import Literal
|
|
||||||
|
|
||||||
_T = TypeVar("_T", bound=Model)
|
_T = TypeVar("_T", bound=Model)
|
||||||
|
|
||||||
class BaseUserManager(models.Manager[_T]):
|
class BaseUserManager(models.Manager[_T]):
|
||||||
@@ -26,9 +20,9 @@ class AbstractBaseUser(models.Model):
|
|||||||
def get_username(self) -> str: ...
|
def get_username(self) -> str: ...
|
||||||
def natural_key(self) -> Tuple[str]: ...
|
def natural_key(self) -> Tuple[str]: ...
|
||||||
@property
|
@property
|
||||||
def is_anonymous(self) -> Literal[False]: ...
|
def is_anonymous(self) -> bool: ...
|
||||||
@property
|
@property
|
||||||
def is_authenticated(self) -> Literal[True]: ...
|
def is_authenticated(self) -> bool: ...
|
||||||
def set_password(self, raw_password: Optional[str]) -> None: ...
|
def set_password(self, raw_password: Optional[str]) -> None: ...
|
||||||
def check_password(self, raw_password: str) -> bool: ...
|
def check_password(self, raw_password: str) -> bool: ...
|
||||||
def set_unusable_password(self) -> None: ...
|
def set_unusable_password(self) -> None: ...
|
||||||
|
|||||||
@@ -1,21 +1,13 @@
|
|||||||
from typing import Callable, List, Optional, Set, Union, TypeVar, overload
|
from typing import Callable, List, Optional, Set, Union
|
||||||
|
|
||||||
from django.contrib.auth import REDIRECT_FIELD_NAME as REDIRECT_FIELD_NAME # noqa: F401
|
from django.contrib.auth import REDIRECT_FIELD_NAME as REDIRECT_FIELD_NAME # noqa: F401
|
||||||
from django.http.response import HttpResponseBase
|
|
||||||
|
|
||||||
from django.contrib.auth.models import AbstractUser
|
|
||||||
|
|
||||||
_VIEW = TypeVar("_VIEW", bound=Callable[..., HttpResponseBase])
|
|
||||||
|
|
||||||
def user_passes_test(
|
def user_passes_test(
|
||||||
test_func: Callable[[AbstractUser], bool], login_url: Optional[str] = ..., redirect_field_name: str = ...
|
test_func: Callable, login_url: Optional[str] = ..., redirect_field_name: str = ...
|
||||||
) -> Callable[[_VIEW], _VIEW]: ...
|
) -> Callable: ...
|
||||||
|
def login_required(
|
||||||
# There are two ways of calling @login_required: @with(arguments) and @bare
|
function: Optional[Callable] = ..., redirect_field_name: str = ..., login_url: Optional[str] = ...
|
||||||
@overload
|
) -> Callable: ...
|
||||||
def login_required(redirect_field_name: str = ..., login_url: Optional[str] = ...) -> Callable[[_VIEW], _VIEW]: ...
|
|
||||||
@overload
|
|
||||||
def login_required(function: _VIEW, redirect_field_name: str = ..., login_url: Optional[str] = ...) -> _VIEW: ...
|
|
||||||
def permission_required(
|
def permission_required(
|
||||||
perm: Union[List[str], Set[str], str], login_url: None = ..., raise_exception: bool = ...
|
perm: Union[List[str], Set[str], str], login_url: None = ..., raise_exception: bool = ...
|
||||||
) -> Callable[[_VIEW], _VIEW]: ...
|
) -> Callable: ...
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from typing import Any, Dict, Iterator, Optional
|
from typing import Any, Dict, Iterator, Optional
|
||||||
|
|
||||||
from django.contrib.auth.base_user import AbstractBaseUser
|
from django.contrib.auth.base_user import AbstractBaseUser
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import AbstractUser, User
|
||||||
from django.contrib.auth.tokens import PasswordResetTokenGenerator
|
from django.contrib.auth.tokens import PasswordResetTokenGenerator
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.handlers.wsgi import WSGIRequest
|
from django.core.handlers.wsgi import WSGIRequest
|
||||||
@@ -86,6 +86,6 @@ class AdminPasswordChangeForm(forms.Form):
|
|||||||
password1: Any = ...
|
password1: Any = ...
|
||||||
password2: Any = ...
|
password2: Any = ...
|
||||||
user: User = ...
|
user: User = ...
|
||||||
def __init__(self, user: AbstractBaseUser, *args: Any, **kwargs: Any) -> None: ...
|
def __init__(self, user: AbstractUser, *args: Any, **kwargs: Any) -> None: ...
|
||||||
def clean_password2(self) -> str: ...
|
def clean_password2(self) -> str: ...
|
||||||
def save(self, commit: bool = ...) -> AbstractBaseUser: ...
|
def save(self, commit: bool = ...) -> AbstractUser: ...
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import sys
|
|
||||||
from typing import Any, Collection, Optional, Set, Tuple, Type, TypeVar, Union
|
from typing import Any, Collection, Optional, Set, Tuple, Type, TypeVar, Union
|
||||||
|
|
||||||
from django.contrib.auth.backends import ModelBackend
|
from django.contrib.auth.backends import ModelBackend
|
||||||
@@ -10,11 +9,6 @@ from django.db.models.manager import EmptyManager
|
|||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
if sys.version_info < (3, 8):
|
|
||||||
from typing_extensions import Literal
|
|
||||||
else:
|
|
||||||
from typing import Literal
|
|
||||||
|
|
||||||
_AnyUser = Union[Model, "AnonymousUser"]
|
_AnyUser = Union[Model, "AnonymousUser"]
|
||||||
|
|
||||||
def update_last_login(sender: Type[AbstractBaseUser], user: AbstractBaseUser, **kwargs: Any) -> None: ...
|
def update_last_login(sender: Type[AbstractBaseUser], user: AbstractBaseUser, **kwargs: Any) -> None: ...
|
||||||
@@ -111,7 +105,7 @@ class AnonymousUser:
|
|||||||
def has_perms(self, perm_list: Collection[str], obj: Optional[_AnyUser] = ...) -> bool: ...
|
def has_perms(self, perm_list: Collection[str], obj: Optional[_AnyUser] = ...) -> bool: ...
|
||||||
def has_module_perms(self, module: str) -> bool: ...
|
def has_module_perms(self, module: str) -> bool: ...
|
||||||
@property
|
@property
|
||||||
def is_anonymous(self) -> Literal[True]: ...
|
def is_anonymous(self) -> bool: ...
|
||||||
@property
|
@property
|
||||||
def is_authenticated(self) -> Literal[False]: ...
|
def is_authenticated(self) -> bool: ...
|
||||||
def get_username(self) -> str: ...
|
def get_username(self) -> str: ...
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
from datetime import date, datetime as datetime
|
from datetime import date, datetime as datetime
|
||||||
from typing import Any, Optional, SupportsInt, Union
|
from decimal import Decimal
|
||||||
|
from typing import Any, Optional, Union
|
||||||
|
|
||||||
register: Any
|
register: Any
|
||||||
|
|
||||||
def ordinal(value: Optional[Union[str, SupportsInt]]) -> Optional[str]: ...
|
def ordinal(value: Optional[str]) -> Optional[str]: ...
|
||||||
def intcomma(value: Optional[Union[str, SupportsInt]], use_l10n: bool = ...) -> str: ...
|
def intcomma(value: Optional[Union[Decimal, float, str]], use_l10n: bool = ...) -> str: ...
|
||||||
|
|
||||||
intword_converters: Any
|
intword_converters: Any
|
||||||
|
|
||||||
def intword(value: Optional[Union[str, SupportsInt]]) -> Optional[Union[int, str]]: ...
|
def intword(value: Optional[str]) -> Optional[Union[int, str]]: ...
|
||||||
def apnumber(value: Optional[Union[str, SupportsInt]]) -> Optional[Union[int, str]]: ...
|
def apnumber(value: Optional[str]) -> Optional[Union[int, str]]: ...
|
||||||
def naturalday(value: Optional[Union[date, str]], arg: None = ...) -> Optional[str]: ...
|
def naturalday(value: Optional[Union[date, str]], arg: None = ...) -> Optional[str]: ...
|
||||||
def naturaltime(value: datetime) -> str: ...
|
def naturaltime(value: datetime) -> str: ...
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Any, Dict, List, Optional, Union, Protocol
|
from typing import Any, Dict, List, Optional, Union
|
||||||
|
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site
|
||||||
from django.contrib.sites.requests import RequestSite
|
from django.contrib.sites.requests import RequestSite
|
||||||
@@ -13,19 +13,10 @@ class SitemapNotFound(Exception): ...
|
|||||||
|
|
||||||
def ping_google(sitemap_url: Optional[str] = ..., ping_url: str = ...) -> None: ...
|
def ping_google(sitemap_url: Optional[str] = ..., ping_url: str = ...) -> None: ...
|
||||||
|
|
||||||
class _SupportsLen(Protocol):
|
|
||||||
def __len__(self) -> int: ...
|
|
||||||
|
|
||||||
class _SupportsCount(Protocol):
|
|
||||||
def count(self) -> int: ...
|
|
||||||
|
|
||||||
class _SupportsOrdered(Protocol):
|
|
||||||
ordered: bool = ...
|
|
||||||
|
|
||||||
class Sitemap:
|
class Sitemap:
|
||||||
limit: int = ...
|
limit: int = ...
|
||||||
protocol: Optional[str] = ...
|
protocol: Optional[str] = ...
|
||||||
def items(self) -> Union[_SupportsLen, _SupportsCount, _SupportsOrdered]: ...
|
def items(self) -> List[Any]: ...
|
||||||
def location(self, obj: Model) -> str: ...
|
def location(self, obj: Model) -> str: ...
|
||||||
@property
|
@property
|
||||||
def paginator(self) -> Paginator: ...
|
def paginator(self) -> Paginator: ...
|
||||||
|
|||||||
6
django-stubs/core/cache/backends/base.pyi
vendored
6
django-stubs/core/cache/backends/base.pyi
vendored
@@ -19,16 +19,16 @@ class BaseCache:
|
|||||||
def __init__(self, params: Dict[str, Any]) -> None: ...
|
def __init__(self, params: Dict[str, Any]) -> None: ...
|
||||||
def get_backend_timeout(self, timeout: Any = ...) -> Optional[float]: ...
|
def get_backend_timeout(self, timeout: Any = ...) -> Optional[float]: ...
|
||||||
def make_key(self, key: Any, version: Optional[Any] = ...) -> str: ...
|
def make_key(self, key: Any, version: Optional[Any] = ...) -> str: ...
|
||||||
def add(self, key: Any, value: Any, timeout: Any = ..., version: Optional[Any] = ...) -> bool: ...
|
def add(self, key: Any, value: Any, timeout: Any = ..., version: Optional[Any] = ...) -> None: ...
|
||||||
def get(self, key: Any, default: Optional[Any] = ..., version: Optional[Any] = ...) -> Any: ...
|
def get(self, key: Any, default: Optional[Any] = ..., version: Optional[Any] = ...) -> Any: ...
|
||||||
def set(self, key: Any, value: Any, timeout: Any = ..., version: Optional[Any] = ...) -> None: ...
|
def set(self, key: Any, value: Any, timeout: Any = ..., version: Optional[Any] = ...) -> None: ...
|
||||||
def touch(self, key: Any, timeout: Any = ..., version: Optional[Any] = ...) -> bool: ...
|
def touch(self, key: Any, timeout: Any = ..., version: Optional[Any] = ...) -> None: ...
|
||||||
def delete(self, key: Any, version: Optional[Any] = ...) -> None: ...
|
def delete(self, key: Any, version: Optional[Any] = ...) -> None: ...
|
||||||
def get_many(self, keys: List[str], version: Optional[int] = ...) -> Dict[str, Union[int, str]]: ...
|
def get_many(self, keys: List[str], version: Optional[int] = ...) -> Dict[str, Union[int, str]]: ...
|
||||||
def get_or_set(
|
def get_or_set(
|
||||||
self, key: Any, default: Optional[Any], timeout: Any = ..., version: Optional[int] = ...
|
self, key: Any, default: Optional[Any], timeout: Any = ..., version: Optional[int] = ...
|
||||||
) -> Optional[Any]: ...
|
) -> Optional[Any]: ...
|
||||||
def has_key(self, key: Any, version: Optional[Any] = ...) -> bool: ...
|
def has_key(self, key: Any, version: Optional[Any] = ...): ...
|
||||||
def incr(self, key: str, delta: int = ..., version: Optional[int] = ...) -> int: ...
|
def incr(self, key: str, delta: int = ..., version: Optional[int] = ...) -> int: ...
|
||||||
def decr(self, key: str, delta: int = ..., version: Optional[int] = ...) -> int: ...
|
def decr(self, key: str, delta: int = ..., version: Optional[int] = ...) -> int: ...
|
||||||
def __contains__(self, key: str) -> bool: ...
|
def __contains__(self, key: str) -> bool: ...
|
||||||
|
|||||||
@@ -15,14 +15,14 @@ class SkipFile(UploadFileException): ...
|
|||||||
class StopFutureHandlers(UploadFileException): ...
|
class StopFutureHandlers(UploadFileException): ...
|
||||||
|
|
||||||
class FileUploadHandler:
|
class FileUploadHandler:
|
||||||
chunk_size: int = ...
|
chunk_size = ... # type: int
|
||||||
file_name: Optional[str] = ...
|
file_name = ... # type: Optional[str]
|
||||||
content_type: Optional[str] = ...
|
content_type = ... # type: Optional[str]
|
||||||
content_length: Optional[int] = ...
|
content_length = ... # type: Optional[int]
|
||||||
charset: Optional[str] = ...
|
charset = ... # type: Optional[str]
|
||||||
content_type_extra: Optional[Dict[str, str]] = ...
|
content_type_extra = ... # type: Optional[Dict[str, str]]
|
||||||
request: Optional[HttpRequest] = ...
|
request = ... # type: Optional[HttpRequest]
|
||||||
field_name: str = ...
|
field_name = ... # type: str
|
||||||
def __init__(self, request: Optional[HttpRequest] = ...) -> None: ...
|
def __init__(self, request: Optional[HttpRequest] = ...) -> None: ...
|
||||||
def handle_raw_input(
|
def handle_raw_input(
|
||||||
self,
|
self,
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from typing import Any, Callable, Dict, Optional, Union
|
from typing import Any, Callable, Dict, Optional, Union
|
||||||
|
|
||||||
|
from django.contrib.auth.models import AbstractUser
|
||||||
from django.contrib.sessions.backends.base import SessionBase
|
from django.contrib.sessions.backends.base import SessionBase
|
||||||
|
from django.http.response import HttpResponse
|
||||||
|
|
||||||
from django.core.handlers import base
|
from django.core.handlers import base
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
from django.http.response import HttpResponse
|
|
||||||
|
|
||||||
_Stream = Union[BytesIO, str]
|
_Stream = Union[BytesIO, str]
|
||||||
_WSGIEnviron = Dict[str, Any]
|
_WSGIEnviron = Dict[str, Any]
|
||||||
@@ -20,6 +22,7 @@ class LimitedStream:
|
|||||||
|
|
||||||
class WSGIRequest(HttpRequest):
|
class WSGIRequest(HttpRequest):
|
||||||
environ: _WSGIEnviron = ...
|
environ: _WSGIEnviron = ...
|
||||||
|
user: AbstractUser
|
||||||
session: SessionBase
|
session: SessionBase
|
||||||
encoding: Any = ...
|
encoding: Any = ...
|
||||||
def __init__(self, environ: _WSGIEnviron) -> None: ...
|
def __init__(self, environ: _WSGIEnviron) -> None: ...
|
||||||
|
|||||||
@@ -22,4 +22,4 @@ class Style:
|
|||||||
|
|
||||||
def make_style(config_string: str = ...) -> Style: ...
|
def make_style(config_string: str = ...) -> Style: ...
|
||||||
def no_style() -> Style: ...
|
def no_style() -> Style: ...
|
||||||
def color_style(force_color: bool = ...) -> Style: ...
|
def color_style() -> Style: ...
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ class InvalidPage(Exception): ...
|
|||||||
class PageNotAnInteger(InvalidPage): ...
|
class PageNotAnInteger(InvalidPage): ...
|
||||||
class EmptyPage(InvalidPage): ...
|
class EmptyPage(InvalidPage): ...
|
||||||
|
|
||||||
class _SupportsLen(Protocol):
|
class SupportsLen(Protocol):
|
||||||
def __len__(self) -> int: ...
|
def __len__(self) -> int: ...
|
||||||
|
|
||||||
class _SupportsCount(Protocol):
|
class SupportsCount(Protocol):
|
||||||
def count(self) -> int: ...
|
def count(self) -> int: ...
|
||||||
|
|
||||||
class _SupportsOrdered(Protocol):
|
class SupportsOrdered(Protocol):
|
||||||
ordered: bool = ...
|
ordered: bool = ...
|
||||||
|
|
||||||
class Paginator:
|
class Paginator:
|
||||||
@@ -24,13 +24,13 @@ class Paginator:
|
|||||||
allow_empty_first_page: bool = ...
|
allow_empty_first_page: bool = ...
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
object_list: Union[_SupportsLen, _SupportsCount, _SupportsOrdered],
|
object_list: Union[SupportsLen, SupportsCount, SupportsOrdered],
|
||||||
per_page: Union[int, str],
|
per_page: Union[int, str],
|
||||||
orphans: int = ...,
|
orphans: int = ...,
|
||||||
allow_empty_first_page: bool = ...,
|
allow_empty_first_page: bool = ...,
|
||||||
) -> None: ...
|
) -> None: ...
|
||||||
def validate_number(self, number: Optional[Union[int, float, str]]) -> int: ...
|
def validate_number(self, number: Optional[Union[float, str]]) -> int: ...
|
||||||
def get_page(self, number: Optional[Union[int, float, str]]) -> Page: ...
|
def get_page(self, number: Optional[int]) -> Page: ...
|
||||||
def page(self, number: Union[int, str]) -> Page: ...
|
def page(self, number: Union[int, str]) -> Page: ...
|
||||||
@property
|
@property
|
||||||
def count(self) -> int: ...
|
def count(self) -> int: ...
|
||||||
|
|||||||
@@ -21,11 +21,7 @@ def dumps(
|
|||||||
obj: Any, key: None = ..., salt: str = ..., serializer: Type[Serializer] = ..., compress: bool = ...
|
obj: Any, key: None = ..., salt: str = ..., serializer: Type[Serializer] = ..., compress: bool = ...
|
||||||
) -> str: ...
|
) -> str: ...
|
||||||
def loads(
|
def loads(
|
||||||
s: str,
|
s: str, key: None = ..., salt: str = ..., serializer: Type[Serializer] = ..., max_age: Optional[int] = ...
|
||||||
key: None = ...,
|
|
||||||
salt: str = ...,
|
|
||||||
serializer: Type[Serializer] = ...,
|
|
||||||
max_age: Optional[Union[int, timedelta]] = ...,
|
|
||||||
) -> Any: ...
|
) -> Any: ...
|
||||||
|
|
||||||
class Signer:
|
class Signer:
|
||||||
|
|||||||
@@ -68,9 +68,6 @@ from .deletion import (
|
|||||||
DO_NOTHING as DO_NOTHING,
|
DO_NOTHING as DO_NOTHING,
|
||||||
PROTECT as PROTECT,
|
PROTECT as PROTECT,
|
||||||
SET as SET,
|
SET as SET,
|
||||||
RESTRICT as RESTRICT,
|
|
||||||
ProtectedError as ProtectedError,
|
|
||||||
RestrictedError as RestrictedError,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
from .query import (
|
from .query import (
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from typing import Any, Callable, Collection, Dict, Iterable, List, Optional, Set, Tuple, Type, TypeVar, Union
|
from typing import Any, Callable, Dict, List, Optional, Sequence, Set, Tuple, Type, TypeVar, Union, Collection
|
||||||
|
|
||||||
from django.core.checks.messages import CheckMessage
|
from django.core.checks.messages import CheckMessage
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
@@ -7,13 +7,6 @@ from django.db.models.options import Options
|
|||||||
|
|
||||||
_Self = TypeVar("_Self", bound="Model")
|
_Self = TypeVar("_Self", bound="Model")
|
||||||
|
|
||||||
class ModelStateFieldsCacheDescriptor: ...
|
|
||||||
|
|
||||||
class ModelState:
|
|
||||||
db: Optional[str] = ...
|
|
||||||
adding: bool = ...
|
|
||||||
fields_cache: ModelStateFieldsCacheDescriptor = ...
|
|
||||||
|
|
||||||
class ModelBase(type): ...
|
class ModelBase(type): ...
|
||||||
|
|
||||||
class Model(metaclass=ModelBase):
|
class Model(metaclass=ModelBase):
|
||||||
@@ -24,12 +17,7 @@ class Model(metaclass=ModelBase):
|
|||||||
_default_manager: BaseManager[Model]
|
_default_manager: BaseManager[Model]
|
||||||
objects: BaseManager[Any]
|
objects: BaseManager[Any]
|
||||||
pk: Any = ...
|
pk: Any = ...
|
||||||
_state: ModelState
|
|
||||||
def __init__(self: _Self, *args, **kwargs) -> None: ...
|
def __init__(self: _Self, *args, **kwargs) -> None: ...
|
||||||
@classmethod
|
|
||||||
def add_to_class(cls, name: str, value: Any): ...
|
|
||||||
@classmethod
|
|
||||||
def from_db(cls, db: Optional[str], field_names: Collection[str], values: Collection[Any]) -> _Self: ...
|
|
||||||
def delete(self, using: Any = ..., keep_parents: bool = ...) -> Tuple[int, Dict[str, int]]: ...
|
def delete(self, using: Any = ..., keep_parents: bool = ...) -> Tuple[int, Dict[str, int]]: ...
|
||||||
def full_clean(self, exclude: Optional[Collection[str]] = ..., validate_unique: bool = ...) -> None: ...
|
def full_clean(self, exclude: Optional[Collection[str]] = ..., validate_unique: bool = ...) -> None: ...
|
||||||
def clean(self) -> None: ...
|
def clean(self) -> None: ...
|
||||||
@@ -43,7 +31,7 @@ class Model(metaclass=ModelBase):
|
|||||||
force_insert: bool = ...,
|
force_insert: bool = ...,
|
||||||
force_update: bool = ...,
|
force_update: bool = ...,
|
||||||
using: Optional[str] = ...,
|
using: Optional[str] = ...,
|
||||||
update_fields: Optional[Iterable[str]] = ...,
|
update_fields: Optional[Union[Sequence[str], str]] = ...,
|
||||||
) -> None: ...
|
) -> None: ...
|
||||||
def save_base(
|
def save_base(
|
||||||
self,
|
self,
|
||||||
@@ -51,10 +39,17 @@ class Model(metaclass=ModelBase):
|
|||||||
force_insert: bool = ...,
|
force_insert: bool = ...,
|
||||||
force_update: bool = ...,
|
force_update: bool = ...,
|
||||||
using: Optional[str] = ...,
|
using: Optional[str] = ...,
|
||||||
update_fields: Optional[Iterable[str]] = ...,
|
update_fields: Optional[Union[Sequence[str], str]] = ...,
|
||||||
): ...
|
): ...
|
||||||
def refresh_from_db(self: _Self, using: Optional[str] = ..., fields: Optional[List[str]] = ...) -> None: ...
|
def refresh_from_db(self: _Self, using: Optional[str] = ..., fields: Optional[List[str]] = ...) -> None: ...
|
||||||
def get_deferred_fields(self) -> Set[str]: ...
|
def get_deferred_fields(self) -> Set[str]: ...
|
||||||
@classmethod
|
@classmethod
|
||||||
def check(cls, **kwargs: Any) -> List[CheckMessage]: ...
|
def check(cls, **kwargs: Any) -> List[CheckMessage]: ...
|
||||||
def __getstate__(self) -> dict: ...
|
def __getstate__(self) -> dict: ...
|
||||||
|
|
||||||
|
class ModelStateFieldsCacheDescriptor: ...
|
||||||
|
|
||||||
|
class ModelState:
|
||||||
|
db: None = ...
|
||||||
|
adding: bool = ...
|
||||||
|
fields_cache: ModelStateFieldsCacheDescriptor = ...
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
LOOKUP_SEP: str = ...
|
|
||||||
@@ -11,12 +11,10 @@ def SET_NULL(collector, field, sub_objs, using): ...
|
|||||||
def SET_DEFAULT(collector, field, sub_objs, using): ...
|
def SET_DEFAULT(collector, field, sub_objs, using): ...
|
||||||
def DO_NOTHING(collector, field, sub_objs, using): ...
|
def DO_NOTHING(collector, field, sub_objs, using): ...
|
||||||
def PROTECT(collector, field, sub_objs, using): ...
|
def PROTECT(collector, field, sub_objs, using): ...
|
||||||
def RESTRICT(collector, field, sub_objs, using): ...
|
|
||||||
def SET(value: Any) -> Callable: ...
|
def SET(value: Any) -> Callable: ...
|
||||||
def get_candidate_relations_to_delete(opts: Options) -> Iterable[Field]: ...
|
def get_candidate_relations_to_delete(opts: Options) -> Iterable[Field]: ...
|
||||||
|
|
||||||
class ProtectedError(IntegrityError): ...
|
class ProtectedError(IntegrityError): ...
|
||||||
class RestrictedError(IntegrityError): ...
|
|
||||||
|
|
||||||
class Collector:
|
class Collector:
|
||||||
def __init__(self, using: str) -> None: ...
|
def __init__(self, using: str) -> None: ...
|
||||||
|
|||||||
@@ -10,10 +10,6 @@ class ChoicesMeta(enum.EnumMeta):
|
|||||||
|
|
||||||
class Choices(enum.Enum, metaclass=ChoicesMeta):
|
class Choices(enum.Enum, metaclass=ChoicesMeta):
|
||||||
def __str__(self): ...
|
def __str__(self): ...
|
||||||
@property
|
|
||||||
def label(self) -> str: ...
|
|
||||||
@property
|
|
||||||
def value(self) -> Any: ...
|
|
||||||
|
|
||||||
# fake
|
# fake
|
||||||
class _IntegerChoicesMeta(ChoicesMeta):
|
class _IntegerChoicesMeta(ChoicesMeta):
|
||||||
@@ -22,9 +18,7 @@ class _IntegerChoicesMeta(ChoicesMeta):
|
|||||||
labels: List[str] = ...
|
labels: List[str] = ...
|
||||||
values: List[int] = ...
|
values: List[int] = ...
|
||||||
|
|
||||||
class IntegerChoices(int, Choices, metaclass=_IntegerChoicesMeta):
|
class IntegerChoices(int, Choices, metaclass=_IntegerChoicesMeta): ...
|
||||||
@property
|
|
||||||
def value(self) -> int: ...
|
|
||||||
|
|
||||||
# fake
|
# fake
|
||||||
class _TextChoicesMeta(ChoicesMeta):
|
class _TextChoicesMeta(ChoicesMeta):
|
||||||
@@ -33,6 +27,4 @@ class _TextChoicesMeta(ChoicesMeta):
|
|||||||
labels: List[str] = ...
|
labels: List[str] = ...
|
||||||
values: List[str] = ...
|
values: List[str] = ...
|
||||||
|
|
||||||
class TextChoices(str, Choices, metaclass=_TextChoicesMeta):
|
class TextChoices(str, Choices, metaclass=_TextChoicesMeta): ...
|
||||||
@property
|
|
||||||
def value(self) -> str: ...
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from decimal import Decimal
|
|
||||||
from typing import Any, Callable, Dict, Iterator, List, Optional, Sequence, Set, Tuple, Type, TypeVar, Union, Iterable
|
from typing import Any, Callable, Dict, Iterator, List, Optional, Sequence, Set, Tuple, Type, TypeVar, Union, Iterable
|
||||||
|
|
||||||
from django.db.models.lookups import Lookup
|
from django.db.models.lookups import Lookup
|
||||||
@@ -16,8 +15,6 @@ class SQLiteNumericMixin:
|
|||||||
|
|
||||||
_Self = TypeVar("_Self")
|
_Self = TypeVar("_Self")
|
||||||
|
|
||||||
_Numeric = Union[float, Decimal]
|
|
||||||
|
|
||||||
class Combinable:
|
class Combinable:
|
||||||
ADD: str = ...
|
ADD: str = ...
|
||||||
SUB: str = ...
|
SUB: str = ...
|
||||||
@@ -30,25 +27,25 @@ class Combinable:
|
|||||||
BITLEFTSHIFT: str = ...
|
BITLEFTSHIFT: str = ...
|
||||||
BITRIGHTSHIFT: str = ...
|
BITRIGHTSHIFT: str = ...
|
||||||
def __neg__(self: _Self) -> _Self: ...
|
def __neg__(self: _Self) -> _Self: ...
|
||||||
def __add__(self: _Self, other: Optional[Union[timedelta, Combinable, _Numeric, str]]) -> _Self: ...
|
def __add__(self: _Self, other: Optional[Union[timedelta, Combinable, float, str]]) -> _Self: ...
|
||||||
def __sub__(self: _Self, other: Union[timedelta, Combinable, _Numeric]) -> _Self: ...
|
def __sub__(self: _Self, other: Union[timedelta, Combinable, float]) -> _Self: ...
|
||||||
def __mul__(self: _Self, other: Union[timedelta, Combinable, _Numeric]) -> _Self: ...
|
def __mul__(self: _Self, other: Union[timedelta, Combinable, float]) -> _Self: ...
|
||||||
def __truediv__(self: _Self, other: Union[Combinable, _Numeric]) -> _Self: ...
|
def __truediv__(self: _Self, other: Union[Combinable, float]) -> _Self: ...
|
||||||
def __itruediv__(self: _Self, other: Union[Combinable, _Numeric]) -> _Self: ...
|
def __itruediv__(self: _Self, other: Union[Combinable, float]) -> _Self: ...
|
||||||
def __mod__(self: _Self, other: Union[int, Combinable]) -> _Self: ...
|
def __mod__(self: _Self, other: Union[int, Combinable]) -> _Self: ...
|
||||||
def __pow__(self: _Self, other: Union[_Numeric, Combinable]) -> _Self: ...
|
def __pow__(self: _Self, other: Union[float, Combinable]) -> _Self: ...
|
||||||
def __and__(self: _Self, other: Combinable) -> _Self: ...
|
def __and__(self: _Self, other: Combinable) -> _Self: ...
|
||||||
def bitand(self: _Self, other: int) -> _Self: ...
|
def bitand(self: _Self, other: int) -> _Self: ...
|
||||||
def bitleftshift(self: _Self, other: int) -> _Self: ...
|
def bitleftshift(self: _Self, other: int) -> _Self: ...
|
||||||
def bitrightshift(self: _Self, other: int) -> _Self: ...
|
def bitrightshift(self: _Self, other: int) -> _Self: ...
|
||||||
def __or__(self: _Self, other: Combinable) -> _Self: ...
|
def __or__(self: _Self, other: Combinable) -> _Self: ...
|
||||||
def bitor(self: _Self, other: int) -> _Self: ...
|
def bitor(self: _Self, other: int) -> _Self: ...
|
||||||
def __radd__(self, other: Optional[Union[datetime, _Numeric, Combinable]]) -> Combinable: ...
|
def __radd__(self, other: Optional[Union[datetime, float, Combinable]]) -> Combinable: ...
|
||||||
def __rsub__(self, other: Union[_Numeric, Combinable]) -> Combinable: ...
|
def __rsub__(self, other: Union[float, Combinable]) -> Combinable: ...
|
||||||
def __rmul__(self, other: Union[_Numeric, Combinable]) -> Combinable: ...
|
def __rmul__(self, other: Union[float, Combinable]) -> Combinable: ...
|
||||||
def __rtruediv__(self, other: Union[_Numeric, Combinable]) -> Combinable: ...
|
def __rtruediv__(self, other: Union[float, Combinable]) -> Combinable: ...
|
||||||
def __rmod__(self, other: Union[int, Combinable]) -> Combinable: ...
|
def __rmod__(self, other: Union[int, Combinable]) -> Combinable: ...
|
||||||
def __rpow__(self, other: Union[_Numeric, Combinable]) -> Combinable: ...
|
def __rpow__(self, other: Union[float, Combinable]) -> Combinable: ...
|
||||||
def __rand__(self, other: Any) -> Combinable: ...
|
def __rand__(self, other: Any) -> Combinable: ...
|
||||||
def __ror__(self, other: Any) -> Combinable: ...
|
def __ror__(self, other: Any) -> Combinable: ...
|
||||||
|
|
||||||
|
|||||||
@@ -56,10 +56,6 @@ class Field(RegisterLookupMixin, Generic[_ST, _GT]):
|
|||||||
remote_field: Field
|
remote_field: Field
|
||||||
is_relation: bool
|
is_relation: bool
|
||||||
related_model: Optional[Type[Model]]
|
related_model: Optional[Type[Model]]
|
||||||
one_to_many: Optional[bool] = ...
|
|
||||||
one_to_one: Optional[bool] = ...
|
|
||||||
many_to_many: Optional[bool] = ...
|
|
||||||
many_to_one: Optional[bool] = ...
|
|
||||||
max_length: int
|
max_length: int
|
||||||
model: Type[Model]
|
model: Type[Model]
|
||||||
name: str
|
name: str
|
||||||
@@ -112,10 +108,7 @@ class Field(RegisterLookupMixin, Generic[_ST, _GT]):
|
|||||||
def set_attributes_from_name(self, name: str) -> None: ...
|
def set_attributes_from_name(self, name: str) -> None: ...
|
||||||
def db_type(self, connection: Any) -> str: ...
|
def db_type(self, connection: Any) -> str: ...
|
||||||
def db_parameters(self, connection: Any) -> Dict[str, str]: ...
|
def db_parameters(self, connection: Any) -> Dict[str, str]: ...
|
||||||
def pre_save(self, model_instance: Model, add: bool) -> Any: ...
|
|
||||||
def get_prep_value(self, value: Any) -> Any: ...
|
def get_prep_value(self, value: Any) -> Any: ...
|
||||||
def get_db_prep_value(self, value: Any, connection: Any, prepared: bool) -> Any: ...
|
|
||||||
def get_db_prep_save(self, value: Any, connection: Any) -> Any: ...
|
|
||||||
def get_internal_type(self) -> str: ...
|
def get_internal_type(self) -> str: ...
|
||||||
# TODO: plugin support
|
# TODO: plugin support
|
||||||
def formfield(self, **kwargs) -> Any: ...
|
def formfield(self, **kwargs) -> Any: ...
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class FileField(Field):
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
upload_to: Union[str, Callable, Path] = ...,
|
upload_to: Union[str, Callable, Path] = ...,
|
||||||
storage: Optional[Union[Storage, Callable[[], Storage]]] = ...,
|
storage: Optional[Storage] = ...,
|
||||||
verbose_name: Optional[Union[str, bytes]] = ...,
|
verbose_name: Optional[Union[str, bytes]] = ...,
|
||||||
name: Optional[str] = ...,
|
name: Optional[str] = ...,
|
||||||
max_length: Optional[int] = ...,
|
max_length: Optional[int] = ...,
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ class _BaseQuerySet(Generic[_T], Sized):
|
|||||||
def union(self: _QS, *other_qs: Any, all: bool = ...) -> _QS: ...
|
def union(self: _QS, *other_qs: Any, all: bool = ...) -> _QS: ...
|
||||||
def intersection(self: _QS, *other_qs: Any) -> _QS: ...
|
def intersection(self: _QS, *other_qs: Any) -> _QS: ...
|
||||||
def difference(self: _QS, *other_qs: Any) -> _QS: ...
|
def difference(self: _QS, *other_qs: Any) -> _QS: ...
|
||||||
def select_for_update(self: _QS, nowait: bool = ..., skip_locked: bool = ..., of: Sequence[str] = ...) -> _QS: ...
|
def select_for_update(self: _QS, nowait: bool = ..., skip_locked: bool = ..., of: Tuple = ...) -> _QS: ...
|
||||||
def select_related(self: _QS, *fields: Any) -> _QS: ...
|
def select_related(self: _QS, *fields: Any) -> _QS: ...
|
||||||
def prefetch_related(self: _QS, *lookups: Any) -> _QS: ...
|
def prefetch_related(self: _QS, *lookups: Any) -> _QS: ...
|
||||||
# TODO: return type
|
# TODO: return type
|
||||||
|
|||||||
@@ -39,11 +39,4 @@ def atomic(using: _C) -> _C: ...
|
|||||||
# Decorator or context-manager with parameters
|
# Decorator or context-manager with parameters
|
||||||
@overload
|
@overload
|
||||||
def atomic(using: Optional[str] = ..., savepoint: bool = ...) -> Atomic: ...
|
def atomic(using: Optional[str] = ..., savepoint: bool = ...) -> Atomic: ...
|
||||||
|
def non_atomic_requests(using: Callable = ...) -> Callable: ...
|
||||||
# Bare decorator
|
|
||||||
@overload
|
|
||||||
def non_atomic_requests(using: _C) -> _C: ...
|
|
||||||
|
|
||||||
# Decorator with arguments
|
|
||||||
@overload
|
|
||||||
def non_atomic_requests(using: Optional[str] = ...) -> Callable[[_C], _C]: ...
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class Field:
|
|||||||
initial: Any
|
initial: Any
|
||||||
label: Optional[str]
|
label: Optional[str]
|
||||||
required: bool
|
required: bool
|
||||||
widget: Union[Type[Widget], Widget] = ...
|
widget: Widget = ...
|
||||||
hidden_widget: Any = ...
|
hidden_widget: Any = ...
|
||||||
default_validators: Any = ...
|
default_validators: Any = ...
|
||||||
default_error_messages: Any = ...
|
default_error_messages: Any = ...
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
from typing import Any, Dict, Iterator, List, Mapping, Optional, Sequence, Type, Union
|
from typing import Any, Dict, Iterator, List, Mapping, Optional, Sequence, Type, Union
|
||||||
|
|
||||||
from django.core.exceptions import ValidationError as ValidationError
|
from django.core.exceptions import ValidationError as ValidationError
|
||||||
from django.core.files import uploadedfile
|
|
||||||
from django.forms.boundfield import BoundField
|
from django.forms.boundfield import BoundField
|
||||||
from django.forms.fields import Field
|
from django.forms.fields import Field
|
||||||
from django.forms.renderers import BaseRenderer
|
from django.forms.renderers import BaseRenderer
|
||||||
from django.forms.utils import ErrorDict, ErrorList
|
from django.forms.utils import ErrorDict, ErrorList
|
||||||
from django.forms.widgets import Media, MediaDefiningClass
|
from django.forms.widgets import Media, MediaDefiningClass
|
||||||
from django.utils.datastructures import MultiValueDict
|
|
||||||
from django.utils.safestring import SafeText
|
from django.utils.safestring import SafeText
|
||||||
|
|
||||||
class DeclarativeFieldsMetaclass(MediaDefiningClass): ...
|
class DeclarativeFieldsMetaclass(MediaDefiningClass): ...
|
||||||
@@ -20,11 +18,11 @@ class BaseForm:
|
|||||||
use_required_attribute: bool = ...
|
use_required_attribute: bool = ...
|
||||||
is_bound: bool = ...
|
is_bound: bool = ...
|
||||||
data: Dict[str, Any] = ...
|
data: Dict[str, Any] = ...
|
||||||
files: MultiValueDict[str, uploadedfile.UploadedFile] = ...
|
files: Optional[Dict[str, Any]] = ...
|
||||||
auto_id: Union[bool, str] = ...
|
auto_id: str = ...
|
||||||
initial: Dict[str, Any] = ...
|
initial: Dict[str, Any] = ...
|
||||||
error_class: Type[ErrorList] = ...
|
error_class: Type[ErrorList] = ...
|
||||||
prefix: Optional[str] = ...
|
prefix: str = ...
|
||||||
label_suffix: str = ...
|
label_suffix: str = ...
|
||||||
empty_permitted: bool = ...
|
empty_permitted: bool = ...
|
||||||
fields: Dict[str, Any] = ...
|
fields: Dict[str, Any] = ...
|
||||||
@@ -69,14 +67,6 @@ class BaseForm:
|
|||||||
def hidden_fields(self): ...
|
def hidden_fields(self): ...
|
||||||
def visible_fields(self): ...
|
def visible_fields(self): ...
|
||||||
def get_initial_for_field(self, field: Field, field_name: str) -> Any: ...
|
def get_initial_for_field(self, field: Field, field_name: str) -> Any: ...
|
||||||
def _html_output(
|
|
||||||
self,
|
|
||||||
normal_row: str,
|
|
||||||
error_row: str,
|
|
||||||
row_ender: str,
|
|
||||||
help_text_html: str,
|
|
||||||
errors_on_separate_row: bool,
|
|
||||||
) -> SafeText: ...
|
|
||||||
|
|
||||||
class Form(BaseForm):
|
class Form(BaseForm):
|
||||||
base_fields: Dict[str, Field]
|
base_fields: Dict[str, Field]
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ from typing import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
from django.contrib.auth.base_user import AbstractBaseUser
|
from django.contrib.auth.base_user import AbstractBaseUser
|
||||||
from django.contrib.auth.models import AnonymousUser
|
|
||||||
from django.contrib.sessions.backends.base import SessionBase
|
from django.contrib.sessions.backends.base import SessionBase
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site
|
||||||
from django.utils.datastructures import CaseInsensitiveMapping, ImmutableList, MultiValueDict
|
from django.utils.datastructures import CaseInsensitiveMapping, ImmutableList, MultiValueDict
|
||||||
@@ -52,7 +51,7 @@ class HttpRequest(BytesIO):
|
|||||||
resolver_match: ResolverMatch = ...
|
resolver_match: ResolverMatch = ...
|
||||||
content_type: Optional[str] = ...
|
content_type: Optional[str] = ...
|
||||||
content_params: Optional[Dict[str, str]] = ...
|
content_params: Optional[Dict[str, str]] = ...
|
||||||
user: Union[AbstractBaseUser, AnonymousUser]
|
user: AbstractBaseUser
|
||||||
site: Site
|
site: Site
|
||||||
session: SessionBase
|
session: SessionBase
|
||||||
encoding: Optional[str] = ...
|
encoding: Optional[str] = ...
|
||||||
|
|||||||
@@ -62,34 +62,31 @@ class HttpResponseBase(Iterable[Any]):
|
|||||||
def __iter__(self) -> Iterator[Any]: ...
|
def __iter__(self) -> Iterator[Any]: ...
|
||||||
|
|
||||||
class HttpResponse(HttpResponseBase):
|
class HttpResponse(HttpResponseBase):
|
||||||
|
client: Client
|
||||||
|
context: Context
|
||||||
content: Any
|
content: Any
|
||||||
csrf_cookie_set: bool
|
csrf_cookie_set: bool
|
||||||
redirect_chain: List[Tuple[str, int]]
|
redirect_chain: List[Tuple[str, int]]
|
||||||
|
request: Dict[str, Any]
|
||||||
|
resolver_match: ResolverMatch
|
||||||
sameorigin: bool
|
sameorigin: bool
|
||||||
|
templates: List[Template]
|
||||||
test_server_port: str
|
test_server_port: str
|
||||||
test_was_secure_request: bool
|
test_was_secure_request: bool
|
||||||
|
wsgi_request: WSGIRequest
|
||||||
xframe_options_exempt: bool
|
xframe_options_exempt: bool
|
||||||
streaming: bool = ...
|
streaming: bool = ...
|
||||||
def __init__(self, content: object = ..., *args: Any, **kwargs: Any) -> None: ...
|
def __init__(self, content: object = ..., *args: Any, **kwargs: Any) -> None: ...
|
||||||
def serialize(self) -> bytes: ...
|
def serialize(self) -> bytes: ...
|
||||||
@property
|
@property
|
||||||
def url(self) -> str: ...
|
def url(self) -> str: ...
|
||||||
# Attributes assigned by monkey-patching in test client ClientHandler.__call__()
|
def json(self) -> Dict[str, Any]: ...
|
||||||
wsgi_request: WSGIRequest
|
|
||||||
# Attributes assigned by monkey-patching in test client Client.request()
|
|
||||||
client: Client
|
|
||||||
request: Dict[str, Any]
|
|
||||||
templates: List[Template]
|
|
||||||
context: Context
|
|
||||||
resolver_match: ResolverMatch
|
|
||||||
def json(self) -> Any: ...
|
|
||||||
def getvalue(self) -> bytes: ...
|
|
||||||
|
|
||||||
class StreamingHttpResponse(HttpResponseBase):
|
class StreamingHttpResponse(HttpResponseBase):
|
||||||
content: Any
|
content: Any
|
||||||
streaming_content: Iterator[Any]
|
streaming_content: Iterator[Any]
|
||||||
def __init__(self, streaming_content: Iterable[Any] = ..., *args: Any, **kwargs: Any) -> None: ...
|
def __init__(self, streaming_content: Iterable[Any] = ..., *args: Any, **kwargs: Any) -> None: ...
|
||||||
def getvalue(self) -> bytes: ...
|
def getvalue(self) -> Any: ...
|
||||||
|
|
||||||
class FileResponse(StreamingHttpResponse):
|
class FileResponse(StreamingHttpResponse):
|
||||||
client: Client
|
client: Client
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import sys
|
from typing import Any, Callable, Dict, List, Optional, Protocol, Sequence, Type, TypeVar, Union
|
||||||
from typing import Any, Callable, List, Mapping, Optional, overload, Protocol, Sequence, Type, TypeVar, Union
|
|
||||||
|
|
||||||
from django.db.models.base import Model
|
from django.db.models.base import Model
|
||||||
from django.http.response import (
|
from django.http.response import (
|
||||||
@@ -11,14 +10,9 @@ from django.http.response import (
|
|||||||
from django.db.models import Manager, QuerySet
|
from django.db.models import Manager, QuerySet
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
|
|
||||||
if sys.version_info < (3, 8):
|
|
||||||
from typing_extensions import Literal
|
|
||||||
else:
|
|
||||||
from typing import Literal
|
|
||||||
|
|
||||||
def render_to_response(
|
def render_to_response(
|
||||||
template_name: Union[str, Sequence[str]],
|
template_name: Union[str, Sequence[str]],
|
||||||
context: Optional[Mapping[str, Any]] = ...,
|
context: Optional[Dict[str, Any]] = ...,
|
||||||
content_type: Optional[str] = ...,
|
content_type: Optional[str] = ...,
|
||||||
status: Optional[int] = ...,
|
status: Optional[int] = ...,
|
||||||
using: Optional[str] = ...,
|
using: Optional[str] = ...,
|
||||||
@@ -26,7 +20,7 @@ def render_to_response(
|
|||||||
def render(
|
def render(
|
||||||
request: HttpRequest,
|
request: HttpRequest,
|
||||||
template_name: Union[str, Sequence[str]],
|
template_name: Union[str, Sequence[str]],
|
||||||
context: Optional[Mapping[str, Any]] = ...,
|
context: Optional[Dict[str, Any]] = ...,
|
||||||
content_type: Optional[str] = ...,
|
content_type: Optional[str] = ...,
|
||||||
status: Optional[int] = ...,
|
status: Optional[int] = ...,
|
||||||
using: Optional[str] = ...,
|
using: Optional[str] = ...,
|
||||||
@@ -34,15 +28,6 @@ def render(
|
|||||||
|
|
||||||
class SupportsGetAbsoluteUrl(Protocol): ...
|
class SupportsGetAbsoluteUrl(Protocol): ...
|
||||||
|
|
||||||
@overload
|
|
||||||
def redirect(
|
|
||||||
to: Union[Callable, str, SupportsGetAbsoluteUrl], *args: Any, permanent: Literal[True], **kwargs: Any
|
|
||||||
) -> HttpResponsePermanentRedirect: ...
|
|
||||||
@overload
|
|
||||||
def redirect(
|
|
||||||
to: Union[Callable, str, SupportsGetAbsoluteUrl], *args: Any, permanent: Literal[False], **kwargs: Any
|
|
||||||
) -> HttpResponseRedirect: ...
|
|
||||||
@overload
|
|
||||||
def redirect(
|
def redirect(
|
||||||
to: Union[Callable, str, SupportsGetAbsoluteUrl], *args: Any, permanent: bool = ..., **kwargs: Any
|
to: Union[Callable, str, SupportsGetAbsoluteUrl], *args: Any, permanent: bool = ..., **kwargs: Any
|
||||||
) -> Union[HttpResponseRedirect, HttpResponsePermanentRedirect]: ...
|
) -> Union[HttpResponseRedirect, HttpResponsePermanentRedirect]: ...
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ class Parser:
|
|||||||
builtins: Optional[List[Library]] = ...,
|
builtins: Optional[List[Library]] = ...,
|
||||||
origin: Optional[Origin] = ...,
|
origin: Optional[Origin] = ...,
|
||||||
) -> None: ...
|
) -> None: ...
|
||||||
def parse(self, parse_until: Optional[Tuple[str, ...]] = ...) -> NodeList: ...
|
def parse(self, parse_until: Optional[Tuple[str]] = ...) -> NodeList: ...
|
||||||
def skip_past(self, endtag: str) -> None: ...
|
def skip_past(self, endtag: str) -> None: ...
|
||||||
def extend_nodelist(self, nodelist: NodeList, node: Node, token: Token) -> None: ...
|
def extend_nodelist(self, nodelist: NodeList, node: Node, token: Token) -> None: ...
|
||||||
def error(self, token: Token, e: Union[Exception, str]) -> Exception: ...
|
def error(self, token: Token, e: Union[Exception, str]) -> Exception: ...
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from typing import Any, List, Iterable, Optional, Dict
|
from typing import Any, List, Optional, Dict
|
||||||
|
|
||||||
from django.template.base import Origin, Template
|
from django.template.base import Origin, Template
|
||||||
from django.template.engine import Engine
|
from django.template.engine import Engine
|
||||||
@@ -8,5 +8,5 @@ class Loader:
|
|||||||
get_template_cache: Dict[str, Any] = ...
|
get_template_cache: Dict[str, Any] = ...
|
||||||
def __init__(self, engine: Engine) -> None: ...
|
def __init__(self, engine: Engine) -> None: ...
|
||||||
def get_template(self, template_name: str, skip: Optional[List[Origin]] = ...) -> Template: ...
|
def get_template(self, template_name: str, skip: Optional[List[Origin]] = ...) -> Template: ...
|
||||||
def get_template_sources(self, template_name: str) -> Iterable[Origin]: ...
|
def get_template_sources(self, template_name: str) -> None: ...
|
||||||
def reset(self) -> None: ...
|
def reset(self) -> None: ...
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from types import TracebackType
|
|
||||||
from typing import Any, Dict, List, Optional, Pattern, Tuple, Type, Union
|
from typing import Any, Dict, List, Optional, Pattern, Tuple, Type, Union
|
||||||
|
|
||||||
from django.contrib.auth.base_user import AbstractBaseUser
|
from django.contrib.auth.models import AbstractUser
|
||||||
from django.contrib.sessions.backends.base import SessionBase
|
from django.contrib.sessions.backends.base import SessionBase
|
||||||
from django.core.handlers.base import BaseHandler
|
from django.core.handlers.base import BaseHandler
|
||||||
|
from django.core.serializers.json import DjangoJSONEncoder
|
||||||
from django.http.cookie import SimpleCookie
|
from django.http.cookie import SimpleCookie
|
||||||
from django.http.request import HttpRequest
|
from django.http.request import HttpRequest
|
||||||
from django.http.response import HttpResponse, HttpResponseBase
|
from django.http.response import HttpResponse, HttpResponseBase
|
||||||
|
|
||||||
from django.core.handlers.wsgi import WSGIRequest
|
from django.core.handlers.wsgi import WSGIRequest
|
||||||
from json import JSONEncoder
|
|
||||||
|
|
||||||
BOUNDARY: str = ...
|
BOUNDARY: str = ...
|
||||||
MULTIPART_CONTENT: str = ...
|
MULTIPART_CONTENT: str = ...
|
||||||
@@ -38,11 +37,11 @@ def encode_multipart(boundary: str, data: Dict[str, Any]) -> bytes: ...
|
|||||||
def encode_file(boundary: str, key: str, file: Any) -> List[bytes]: ...
|
def encode_file(boundary: str, key: str, file: Any) -> List[bytes]: ...
|
||||||
|
|
||||||
class RequestFactory:
|
class RequestFactory:
|
||||||
json_encoder: Type[JSONEncoder]
|
json_encoder: Type[DjangoJSONEncoder] = ...
|
||||||
defaults: Dict[str, str]
|
defaults: Dict[str, str] = ...
|
||||||
cookies: SimpleCookie
|
cookies: SimpleCookie = ...
|
||||||
errors: BytesIO
|
errors: BytesIO = ...
|
||||||
def __init__(self, *, json_encoder: Type[JSONEncoder] = ..., **defaults: Any) -> None: ...
|
def __init__(self, *, json_encoder: Any = ..., **defaults: Any) -> None: ...
|
||||||
def request(self, **request: Any) -> WSGIRequest: ...
|
def request(self, **request: Any) -> WSGIRequest: ...
|
||||||
def get(self, path: str, data: Any = ..., secure: bool = ..., **extra: Any) -> WSGIRequest: ...
|
def get(self, path: str, data: Any = ..., secure: bool = ..., **extra: Any) -> WSGIRequest: ...
|
||||||
def post(
|
def post(
|
||||||
@@ -55,7 +54,6 @@ class RequestFactory:
|
|||||||
path: str,
|
path: str,
|
||||||
data: Union[Dict[str, str], str] = ...,
|
data: Union[Dict[str, str], str] = ...,
|
||||||
content_type: str = ...,
|
content_type: str = ...,
|
||||||
follow: bool = ...,
|
|
||||||
secure: bool = ...,
|
secure: bool = ...,
|
||||||
**extra: Any
|
**extra: Any
|
||||||
) -> WSGIRequest: ...
|
) -> WSGIRequest: ...
|
||||||
@@ -78,55 +76,44 @@ class RequestFactory:
|
|||||||
**extra: Any
|
**extra: Any
|
||||||
) -> WSGIRequest: ...
|
) -> WSGIRequest: ...
|
||||||
|
|
||||||
class Client(RequestFactory):
|
class Client:
|
||||||
handler: ClientHandler
|
json_encoder: Type[DjangoJSONEncoder] = ...
|
||||||
raise_request_exception: bool
|
defaults: Dict[str, str] = ...
|
||||||
exc_info: Optional[Tuple[Type[BaseException], BaseException, TracebackType]]
|
cookies: SimpleCookie = ...
|
||||||
def __init__(
|
errors: BytesIO = ...
|
||||||
self,
|
handler: ClientHandler = ...
|
||||||
enforce_csrf_checks: bool = ...,
|
exc_info: None = ...
|
||||||
raise_request_exception: bool = ...,
|
def __init__(self, enforce_csrf_checks: bool = ..., **defaults: Any) -> None: ...
|
||||||
*,
|
def request(self, **request: Any) -> Any: ...
|
||||||
json_encoder: Type[JSONEncoder] = ...,
|
def get(self, path: str, data: Any = ..., secure: bool = ..., **extra: Any) -> Any: ...
|
||||||
**defaults: Any
|
def post(self, path: str, data: Any = ..., content_type: str = ..., secure: bool = ..., **extra: Any) -> Any: ...
|
||||||
) -> None: ...
|
def head(self, path: str, data: Any = ..., secure: bool = ..., **extra: Any) -> Any: ...
|
||||||
# Silence type warnings, since this class overrides arguments and return types in an unsafe manner.
|
def trace(self, path: str, secure: bool = ..., **extra: Any) -> Any: ...
|
||||||
def request(self, **request: Any) -> HttpResponse: ... # type: ignore
|
def options(
|
||||||
def get( # type: ignore
|
|
||||||
self, path: str, data: Any = ..., follow: bool = ..., secure: bool = ..., **extra: Any
|
|
||||||
) -> HttpResponse: ... # type: ignore
|
|
||||||
def post( # type: ignore
|
|
||||||
self, path: str, data: Any = ..., content_type: str = ..., follow: bool = ..., secure: bool = ..., **extra: Any
|
|
||||||
) -> HttpResponse: ... # type: ignore
|
|
||||||
def head( # type: ignore
|
|
||||||
self, path: str, data: Any = ..., follow: bool = ..., secure: bool = ..., **extra: Any
|
|
||||||
) -> HttpResponse: ... # type: ignore
|
|
||||||
def trace( # type: ignore
|
|
||||||
self, path: str, follow: bool = ..., secure: bool = ..., **extra: Any
|
|
||||||
) -> HttpResponse: ... # type: ignore
|
|
||||||
def options( # type: ignore
|
|
||||||
self,
|
self,
|
||||||
path: str,
|
path: str,
|
||||||
data: Union[Dict[str, str], str] = ...,
|
data: Union[Dict[str, str], str] = ...,
|
||||||
content_type: str = ...,
|
content_type: str = ...,
|
||||||
follow: bool = ...,
|
|
||||||
secure: bool = ...,
|
secure: bool = ...,
|
||||||
**extra: Any
|
**extra: Any
|
||||||
) -> HttpResponse: ... # type: ignore
|
) -> Any: ...
|
||||||
def put( # type: ignore
|
def put(self, path: str, data: Any = ..., content_type: str = ..., secure: bool = ..., **extra: Any) -> Any: ...
|
||||||
self, path: str, data: Any = ..., content_type: str = ..., follow: bool = ..., secure: bool = ..., **extra: Any
|
def patch(self, path: str, data: Any = ..., content_type: str = ..., secure: bool = ..., **extra: Any) -> Any: ...
|
||||||
) -> HttpResponse: ... # type: ignore
|
def delete(self, path: str, data: Any = ..., content_type: str = ..., secure: bool = ..., **extra: Any) -> Any: ...
|
||||||
def patch( # type: ignore
|
def generic(
|
||||||
self, path: str, data: Any = ..., content_type: str = ..., follow: bool = ..., secure: bool = ..., **extra: Any
|
self,
|
||||||
) -> HttpResponse: ... # type: ignore
|
method: str,
|
||||||
def delete( # type: ignore
|
path: str,
|
||||||
self, path: str, data: Any = ..., content_type: str = ..., follow: bool = ..., secure: bool = ..., **extra: Any
|
data: Any = ...,
|
||||||
) -> HttpResponse: ... # type: ignore
|
content_type: Optional[str] = ...,
|
||||||
|
secure: bool = ...,
|
||||||
|
**extra: Any
|
||||||
|
) -> Any: ...
|
||||||
def store_exc_info(self, **kwargs: Any) -> None: ...
|
def store_exc_info(self, **kwargs: Any) -> None: ...
|
||||||
@property
|
@property
|
||||||
def session(self) -> SessionBase: ...
|
def session(self) -> SessionBase: ...
|
||||||
def login(self, **credentials: Any) -> bool: ...
|
def login(self, **credentials: Any) -> bool: ...
|
||||||
def force_login(self, user: AbstractBaseUser, backend: Optional[str] = ...) -> None: ...
|
def force_login(self, user: AbstractUser, backend: Optional[str] = ...) -> None: ...
|
||||||
def logout(self) -> None: ...
|
def logout(self) -> None: ...
|
||||||
|
|
||||||
def conditional_content_removal(request: HttpRequest, response: HttpResponseBase) -> HttpResponse: ...
|
def conditional_content_removal(request: HttpRequest, response: HttpResponseBase) -> HttpResponse: ...
|
||||||
|
|||||||
@@ -126,17 +126,9 @@ class SimpleTestCase(unittest.TestCase):
|
|||||||
self, needle: str, haystack: SafeText, count: Optional[int] = ..., msg_prefix: str = ...
|
self, needle: str, haystack: SafeText, count: Optional[int] = ..., msg_prefix: str = ...
|
||||||
) -> None: ...
|
) -> None: ...
|
||||||
def assertJSONEqual(
|
def assertJSONEqual(
|
||||||
self,
|
self, raw: str, expected_data: Union[Dict[str, str], bool, str], msg: Optional[str] = ...
|
||||||
raw: str,
|
|
||||||
expected_data: Union[Dict[str, Any], List[Any], str, int, float, bool, None],
|
|
||||||
msg: Optional[str] = ...,
|
|
||||||
) -> None: ...
|
|
||||||
def assertJSONNotEqual(
|
|
||||||
self,
|
|
||||||
raw: str,
|
|
||||||
expected_data: Union[Dict[str, Any], List[Any], str, int, float, bool, None],
|
|
||||||
msg: Optional[str] = ...,
|
|
||||||
) -> None: ...
|
) -> None: ...
|
||||||
|
def assertJSONNotEqual(self, raw: str, expected_data: str, msg: Optional[str] = ...) -> None: ...
|
||||||
def assertXMLEqual(self, xml1: str, xml2: str, msg: Optional[str] = ...) -> None: ...
|
def assertXMLEqual(self, xml1: str, xml2: str, msg: Optional[str] = ...) -> None: ...
|
||||||
def assertXMLNotEqual(self, xml1: str, xml2: str, msg: Optional[str] = ...) -> None: ...
|
def assertXMLNotEqual(self, xml1: str, xml2: str, msg: Optional[str] = ...) -> None: ...
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ from typing import (
|
|||||||
Type,
|
Type,
|
||||||
Union,
|
Union,
|
||||||
ContextManager,
|
ContextManager,
|
||||||
TypeVar,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
from django.apps.registry import Apps
|
from django.apps.registry import Apps
|
||||||
@@ -30,7 +29,6 @@ from django.conf import LazySettings, Settings
|
|||||||
|
|
||||||
_TestClass = Type[SimpleTestCase]
|
_TestClass = Type[SimpleTestCase]
|
||||||
_DecoratedTest = Union[Callable, _TestClass]
|
_DecoratedTest = Union[Callable, _TestClass]
|
||||||
_C = TypeVar("_C", bound=Callable) # Any callable
|
|
||||||
|
|
||||||
TZ_SUPPORT: bool = ...
|
TZ_SUPPORT: bool = ...
|
||||||
|
|
||||||
@@ -58,7 +56,7 @@ class TestContextDecorator:
|
|||||||
def __enter__(self) -> Optional[Apps]: ...
|
def __enter__(self) -> Optional[Apps]: ...
|
||||||
def __exit__(self, exc_type: None, exc_value: None, traceback: None) -> None: ...
|
def __exit__(self, exc_type: None, exc_value: None, traceback: None) -> None: ...
|
||||||
def decorate_class(self, cls: _TestClass) -> _TestClass: ...
|
def decorate_class(self, cls: _TestClass) -> _TestClass: ...
|
||||||
def decorate_callable(self, func: _C) -> _C: ...
|
def decorate_callable(self, func: Callable) -> Callable: ...
|
||||||
def __call__(self, decorated: _DecoratedTest) -> Any: ...
|
def __call__(self, decorated: _DecoratedTest) -> Any: ...
|
||||||
|
|
||||||
class override_settings(TestContextDecorator):
|
class override_settings(TestContextDecorator):
|
||||||
@@ -148,7 +146,7 @@ def get_unique_databases_and_mirrors() -> Tuple[Dict[_Signature, _TestDatabase],
|
|||||||
def teardown_databases(
|
def teardown_databases(
|
||||||
old_config: Iterable[Tuple[Any, str, bool]], verbosity: int, parallel: int = ..., keepdb: bool = ...
|
old_config: Iterable[Tuple[Any, str, bool]], verbosity: int, parallel: int = ..., keepdb: bool = ...
|
||||||
) -> None: ...
|
) -> None: ...
|
||||||
def require_jinja2(test_func: _C) -> _C: ...
|
def require_jinja2(test_func: Callable) -> Callable: ...
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def register_lookup(
|
def register_lookup(
|
||||||
field: Type[RegisterLookupMixin], *lookups: Type[Union[Lookup, Transform]], lookup_name: Optional[str] = ...
|
field: Type[RegisterLookupMixin], *lookups: Type[Union[Lookup, Transform]], lookup_name: Optional[str] = ...
|
||||||
|
|||||||
@@ -1,31 +1,8 @@
|
|||||||
from typing import Any, List, Optional, Tuple, overload, Callable, Dict, Union
|
from typing import Any, List, Optional, Tuple
|
||||||
|
|
||||||
from .resolvers import URLResolver, URLPattern
|
from .resolvers import URLResolver
|
||||||
from ..conf.urls import IncludedURLConf
|
|
||||||
from ..http.response import HttpResponseBase
|
|
||||||
|
|
||||||
def include(arg: Any, namespace: Optional[str] = ...) -> Tuple[List[URLResolver], Optional[str], Optional[str]]: ...
|
def include(arg: Any, namespace: Optional[str] = ...) -> Tuple[List[URLResolver], Optional[str], Optional[str]]: ...
|
||||||
|
|
||||||
# path()
|
path: Any
|
||||||
@overload
|
re_path: Any
|
||||||
def path(
|
|
||||||
route: str, view: Callable[..., HttpResponseBase], kwargs: Dict[str, Any] = ..., name: str = ...
|
|
||||||
) -> URLPattern: ...
|
|
||||||
@overload
|
|
||||||
def path(route: str, view: IncludedURLConf, kwargs: Dict[str, Any] = ..., name: str = ...) -> URLResolver: ...
|
|
||||||
@overload
|
|
||||||
def path(
|
|
||||||
route: str, view: List[Union[URLResolver, str]], kwargs: Dict[str, Any] = ..., name: str = ...
|
|
||||||
) -> URLResolver: ...
|
|
||||||
|
|
||||||
# re_path()
|
|
||||||
@overload
|
|
||||||
def re_path(
|
|
||||||
route: str, view: Callable[..., HttpResponseBase], kwargs: Dict[str, Any] = ..., name: str = ...
|
|
||||||
) -> URLPattern: ...
|
|
||||||
@overload
|
|
||||||
def re_path(route: str, view: IncludedURLConf, kwargs: Dict[str, Any] = ..., name: str = ...) -> URLResolver: ...
|
|
||||||
@overload
|
|
||||||
def re_path(
|
|
||||||
route: str, view: List[Union[URLResolver, str]], kwargs: Dict[str, Any] = ..., name: str = ...
|
|
||||||
) -> URLResolver: ...
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ class ResolverMatch:
|
|||||||
url_name: Optional[str] = ...,
|
url_name: Optional[str] = ...,
|
||||||
app_names: Optional[List[Optional[str]]] = ...,
|
app_names: Optional[List[Optional[str]]] = ...,
|
||||||
namespaces: Optional[List[Optional[str]]] = ...,
|
namespaces: Optional[List[Optional[str]]] = ...,
|
||||||
route: Optional[str] = ...,
|
|
||||||
) -> None: ...
|
) -> None: ...
|
||||||
def __getitem__(self, index: int) -> Any: ...
|
def __getitem__(self, index: int) -> Any: ...
|
||||||
# for tuple unpacking
|
# for tuple unpacking
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ _V = TypeVar("_V")
|
|||||||
|
|
||||||
class OrderedSet(MutableSet[_K]):
|
class OrderedSet(MutableSet[_K]):
|
||||||
dict: Dict[_K, None] = ...
|
dict: Dict[_K, None] = ...
|
||||||
def __init__(self, iterable: Optional[Iterable[_K]] = ...) -> None: ...
|
|
||||||
def __contains__(self, item: object) -> bool: ...
|
def __contains__(self, item: object) -> bool: ...
|
||||||
def __iter__(self) -> Iterator[_K]: ...
|
def __iter__(self) -> Iterator[_K]: ...
|
||||||
def __len__(self) -> int: ...
|
def __len__(self) -> int: ...
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
from typing import Any, Callable, Iterable, Optional, Type, Union, TypeVar
|
from typing import Any, Callable, Iterable, Optional, Type, Union
|
||||||
|
|
||||||
from django.utils.deprecation import MiddlewareMixin
|
from django.utils.deprecation import MiddlewareMixin
|
||||||
from django.views.generic.base import View
|
|
||||||
|
|
||||||
_T = TypeVar("_T", bound=Union[View, Callable]) # Any callable
|
|
||||||
|
|
||||||
class classonlymethod(classmethod): ...
|
class classonlymethod(classmethod): ...
|
||||||
|
|
||||||
def method_decorator(decorator: Union[Callable, Iterable[Callable]], name: str = ...) -> Callable[[_T], _T]: ...
|
def method_decorator(decorator: Union[Callable, Iterable[Callable]], name: str = ...) -> Callable: ...
|
||||||
def decorator_from_middleware_with_args(middleware_class: type) -> Callable: ...
|
def decorator_from_middleware_with_args(middleware_class: type) -> Callable: ...
|
||||||
def decorator_from_middleware(middleware_class: type) -> Callable: ...
|
def decorator_from_middleware(middleware_class: type) -> Callable: ...
|
||||||
def available_attrs(fn: Callable): ...
|
def available_attrs(fn: Any): ...
|
||||||
def make_middleware_decorator(middleware_class: Type[MiddlewareMixin]) -> Callable: ...
|
def make_middleware_decorator(middleware_class: Type[MiddlewareMixin]) -> Callable: ...
|
||||||
|
|
||||||
class classproperty:
|
class classproperty:
|
||||||
|
|||||||
@@ -56,8 +56,4 @@ class SimpleLazyObject(LazyObject):
|
|||||||
def __copy__(self) -> List[int]: ...
|
def __copy__(self) -> List[int]: ...
|
||||||
def __deepcopy__(self, memo: Dict[Any, Any]) -> List[int]: ...
|
def __deepcopy__(self, memo: Dict[Any, Any]) -> List[int]: ...
|
||||||
|
|
||||||
_PartitionMember = TypeVar("_PartitionMember")
|
def partition(predicate: Callable, values: List[Model]) -> Tuple[List[Model], List[Model]]: ...
|
||||||
|
|
||||||
def partition(
|
|
||||||
predicate: Callable, values: List[_PartitionMember]
|
|
||||||
) -> Tuple[List[_PartitionMember], List[_PartitionMember]]: ...
|
|
||||||
|
|||||||
@@ -13,6 +13,6 @@ NOCOLOR_PALETTE: str
|
|||||||
DARK_PALETTE: str
|
DARK_PALETTE: str
|
||||||
LIGHT_PALETTE: str
|
LIGHT_PALETTE: str
|
||||||
PALETTES: Any
|
PALETTES: Any
|
||||||
DEFAULT_PALETTE: str = ...
|
DEFAULT_PALETTE = DARK_PALETTE
|
||||||
|
|
||||||
def parse_color_setting(config_string: str) -> Optional[Dict[str, Dict[str, Union[Tuple[str], str]]]]: ...
|
def parse_color_setting(config_string: str) -> Optional[Dict[str, Dict[str, Union[Tuple[str], str]]]]: ...
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ class override(ContextDecorator):
|
|||||||
def __enter__(self) -> None: ...
|
def __enter__(self) -> None: ...
|
||||||
def __exit__(self, exc_type: None, exc_value: None, traceback: None) -> None: ...
|
def __exit__(self, exc_type: None, exc_value: None, traceback: None) -> None: ...
|
||||||
|
|
||||||
def get_language() -> str: ...
|
def get_language() -> Optional[str]: ...
|
||||||
def get_language_from_path(path: str) -> Optional[str]: ...
|
def get_language_from_path(path: str) -> Optional[str]: ...
|
||||||
def get_language_bidi() -> bool: ...
|
def get_language_bidi() -> bool: ...
|
||||||
def check_for_language(lang_code: Optional[str]) -> bool: ...
|
def check_for_language(lang_code: Optional[str]) -> bool: ...
|
||||||
@@ -66,7 +66,6 @@ def to_locale(language: str) -> str: ...
|
|||||||
def get_language_from_request(request: WSGIRequest, check_path: bool = ...) -> str: ...
|
def get_language_from_request(request: WSGIRequest, check_path: bool = ...) -> str: ...
|
||||||
def templatize(src: str, **kwargs: Any) -> str: ...
|
def templatize(src: str, **kwargs: Any) -> str: ...
|
||||||
def deactivate_all() -> None: ...
|
def deactivate_all() -> None: ...
|
||||||
def get_supported_language_variant(lang_code: str, strict: bool = ...) -> str: ...
|
|
||||||
def get_language_info(lang_code: str) -> Any: ...
|
def get_language_info(lang_code: str) -> Any: ...
|
||||||
|
|
||||||
from . import trans_real as trans_real
|
from . import trans_real as trans_real
|
||||||
|
|||||||
@@ -1,35 +1,28 @@
|
|||||||
from typing import Any, Callable, Dict, Optional, Sequence, Type, Union
|
from typing import Any, Callable, Dict, Optional, Sequence, Type, Union
|
||||||
|
|
||||||
from django.forms.forms import BaseForm
|
from django.forms.forms import BaseForm
|
||||||
from django.forms.models import BaseModelForm
|
|
||||||
from django.views.generic.base import ContextMixin, TemplateResponseMixin, View
|
from django.views.generic.base import ContextMixin, TemplateResponseMixin, View
|
||||||
from django.views.generic.detail import BaseDetailView, SingleObjectMixin, SingleObjectTemplateResponseMixin
|
from django.views.generic.detail import BaseDetailView, SingleObjectMixin, SingleObjectTemplateResponseMixin
|
||||||
from typing_extensions import Literal
|
from typing_extensions import Literal
|
||||||
|
|
||||||
from django.http import HttpRequest, HttpResponse
|
from django.http import HttpRequest, HttpResponse
|
||||||
|
|
||||||
class AbstractFormMixin(ContextMixin):
|
class FormMixin(ContextMixin):
|
||||||
initial: Dict[str, Any] = ...
|
initial: Dict[str, Any] = ...
|
||||||
form_class: Optional[Type[BaseForm]] = ...
|
form_class: Optional[Type[BaseForm]] = ...
|
||||||
success_url: Optional[Union[str, Callable[..., Any]]] = ...
|
success_url: Optional[Union[str, Callable[..., Any]]] = ...
|
||||||
prefix: Optional[str] = ...
|
prefix: Optional[str] = ...
|
||||||
def get_initial(self) -> Dict[str, Any]: ...
|
def get_initial(self) -> Dict[str, Any]: ...
|
||||||
def get_prefix(self) -> Optional[str]: ...
|
def get_prefix(self) -> Optional[str]: ...
|
||||||
def get_form_kwargs(self) -> Dict[str, Any]: ...
|
|
||||||
def get_success_url(self) -> str: ...
|
|
||||||
|
|
||||||
class FormMixin(AbstractFormMixin):
|
|
||||||
def get_form_class(self) -> Type[BaseForm]: ...
|
def get_form_class(self) -> Type[BaseForm]: ...
|
||||||
def get_form(self, form_class: Optional[Type[BaseForm]] = ...) -> BaseForm: ...
|
def get_form(self, form_class: Optional[Type[BaseForm]] = ...) -> BaseForm: ...
|
||||||
|
def get_form_kwargs(self) -> Dict[str, Any]: ...
|
||||||
|
def get_success_url(self) -> str: ...
|
||||||
def form_valid(self, form: BaseForm) -> HttpResponse: ...
|
def form_valid(self, form: BaseForm) -> HttpResponse: ...
|
||||||
def form_invalid(self, form: BaseForm) -> HttpResponse: ...
|
def form_invalid(self, form: BaseForm) -> HttpResponse: ...
|
||||||
|
|
||||||
class ModelFormMixin(AbstractFormMixin, SingleObjectMixin):
|
class ModelFormMixin(FormMixin, SingleObjectMixin):
|
||||||
fields: Optional[Union[Sequence[str], Literal["__all__"]]] = ...
|
fields: Optional[Union[Sequence[str], Literal["__all__"]]] = ...
|
||||||
def get_form_class(self) -> Type[BaseModelForm]: ...
|
|
||||||
def get_form(self, form_class: Optional[Type[BaseModelForm]] = ...) -> BaseModelForm: ...
|
|
||||||
def form_valid(self, form: BaseModelForm) -> HttpResponse: ...
|
|
||||||
def form_invalid(self, form: BaseModelForm) -> HttpResponse: ...
|
|
||||||
|
|
||||||
class ProcessFormView(View):
|
class ProcessFormView(View):
|
||||||
def get(self, request: HttpRequest, *args: str, **kwargs: Any) -> HttpResponse: ...
|
def get(self, request: HttpRequest, *args: str, **kwargs: Any) -> HttpResponse: ...
|
||||||
|
|||||||
@@ -10,5 +10,3 @@ select = F401, Y
|
|||||||
max_line_length = 120
|
max_line_length = 120
|
||||||
per-file-ignores =
|
per-file-ignores =
|
||||||
*__init__.pyi: F401
|
*__init__.pyi: F401
|
||||||
base_user.pyi: Y003
|
|
||||||
models.pyi: Y003
|
|
||||||
|
|||||||
@@ -311,11 +311,7 @@ def add_new_sym_for_info(info: TypeInfo, *, name: str, sym_type: MypyType) -> No
|
|||||||
|
|
||||||
def build_unannotated_method_args(method_node: FuncDef) -> Tuple[List[Argument], MypyType]:
|
def build_unannotated_method_args(method_node: FuncDef) -> Tuple[List[Argument], MypyType]:
|
||||||
prepared_arguments = []
|
prepared_arguments = []
|
||||||
try:
|
for argument in method_node.arguments[1:]:
|
||||||
arguments = method_node.arguments[1:]
|
|
||||||
except AttributeError:
|
|
||||||
arguments = []
|
|
||||||
for argument in arguments:
|
|
||||||
argument.type_annotation = AnyType(TypeOfAny.unannotated)
|
argument.type_annotation = AnyType(TypeOfAny.unannotated)
|
||||||
prepared_arguments.append(argument)
|
prepared_arguments.append(argument)
|
||||||
return_type = AnyType(TypeOfAny.unannotated)
|
return_type = AnyType(TypeOfAny.unannotated)
|
||||||
@@ -347,7 +343,6 @@ def copy_method_to_another_class(ctx: ClassDefContext, self_type: Instance,
|
|||||||
arguments = []
|
arguments = []
|
||||||
bound_return_type = semanal_api.anal_type(method_type.ret_type,
|
bound_return_type = semanal_api.anal_type(method_type.ret_type,
|
||||||
allow_placeholder=True)
|
allow_placeholder=True)
|
||||||
|
|
||||||
assert bound_return_type is not None
|
assert bound_return_type is not None
|
||||||
|
|
||||||
if isinstance(bound_return_type, PlaceholderNode):
|
if isinstance(bound_return_type, PlaceholderNode):
|
||||||
@@ -357,10 +352,6 @@ def copy_method_to_another_class(ctx: ClassDefContext, self_type: Instance,
|
|||||||
method_type.arg_types[1:],
|
method_type.arg_types[1:],
|
||||||
method_node.arguments[1:]):
|
method_node.arguments[1:]):
|
||||||
bound_arg_type = semanal_api.anal_type(arg_type, allow_placeholder=True)
|
bound_arg_type = semanal_api.anal_type(arg_type, allow_placeholder=True)
|
||||||
if bound_arg_type is None and not semanal_api.final_iteration:
|
|
||||||
semanal_api.defer()
|
|
||||||
return
|
|
||||||
|
|
||||||
assert bound_arg_type is not None
|
assert bound_arg_type is not None
|
||||||
|
|
||||||
if isinstance(bound_arg_type, PlaceholderNode):
|
if isinstance(bound_arg_type, PlaceholderNode):
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import configparser
|
import configparser
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from typing import Callable, Dict, List, NoReturn, Optional, Tuple, cast
|
from typing import Callable, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
from django.db.models.fields.related import RelatedField
|
from django.db.models.fields.related import RelatedField
|
||||||
|
from mypy.errors import Errors
|
||||||
from mypy.nodes import MypyFile, TypeInfo
|
from mypy.nodes import MypyFile, TypeInfo
|
||||||
from mypy.options import Options
|
from mypy.options import Options
|
||||||
from mypy.plugin import (
|
from mypy.plugin import (
|
||||||
@@ -51,40 +52,25 @@ def add_new_manager_base(ctx: ClassDefContext) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def extract_django_settings_module(config_file_path: Optional[str]) -> str:
|
def extract_django_settings_module(config_file_path: Optional[str]) -> str:
|
||||||
|
errors = Errors()
|
||||||
def exit(error_type: int) -> NoReturn:
|
if config_file_path is None:
|
||||||
"""Using mypy's argument parser, raise `SystemExit` to fail hard if validation fails.
|
errors.report(0, None, "'django_settings_module' is not set: no mypy config file specified")
|
||||||
|
errors.raise_error()
|
||||||
Considering that the plugin's startup duration is around double as long as mypy's, this aims to
|
|
||||||
import and construct objects only when that's required - which happens once and terminates the
|
|
||||||
run. Considering that most of the runs are successful, there's no need for this to linger in the
|
|
||||||
global scope.
|
|
||||||
"""
|
|
||||||
from mypy.main import CapturableArgumentParser
|
|
||||||
|
|
||||||
usage = """(config)
|
|
||||||
...
|
|
||||||
[mypy.plugins.django_stubs]
|
|
||||||
django_settings_module: str (required)
|
|
||||||
...
|
|
||||||
""".replace("\n" + 8 * " ", "\n")
|
|
||||||
handler = CapturableArgumentParser(prog='(django-stubs) mypy', usage=usage)
|
|
||||||
messages = {1: 'mypy config file is not specified or found',
|
|
||||||
2: 'no section [mypy.plugins.django-stubs]',
|
|
||||||
3: 'the setting is not provided'}
|
|
||||||
handler.error("'django_settings_module' is not set: " + messages[error_type])
|
|
||||||
|
|
||||||
parser = configparser.ConfigParser()
|
parser = configparser.ConfigParser()
|
||||||
try:
|
parser.read(config_file_path) # type: ignore
|
||||||
parser.read_file(open(cast(str, config_file_path), 'r'), source=config_file_path)
|
|
||||||
except (IsADirectoryError, OSError):
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
section = 'mypy.plugins.django-stubs'
|
if not parser.has_section('mypy.plugins.django-stubs'):
|
||||||
if not parser.has_section(section):
|
errors.report(0, None, "'django_settings_module' is not set: no section [mypy.plugins.django-stubs]",
|
||||||
exit(2)
|
file=config_file_path)
|
||||||
settings = parser.get(section, 'django_settings_module', fallback=None) or exit(3)
|
errors.raise_error()
|
||||||
return cast(str, settings).strip('\'"')
|
if not parser.has_option('mypy.plugins.django-stubs', 'django_settings_module'):
|
||||||
|
errors.report(0, None, "'django_settings_module' is not set: setting is not provided",
|
||||||
|
file=config_file_path)
|
||||||
|
errors.raise_error()
|
||||||
|
|
||||||
|
django_settings_module = parser.get('mypy.plugins.django-stubs', 'django_settings_module').strip('\'"')
|
||||||
|
return django_settings_module
|
||||||
|
|
||||||
|
|
||||||
class NewSemanalDjangoPlugin(Plugin):
|
class NewSemanalDjangoPlugin(Plugin):
|
||||||
|
|||||||
@@ -1,34 +1,16 @@
|
|||||||
from mypy.plugin import AttributeContext
|
from mypy.plugin import AttributeContext
|
||||||
from mypy.types import Instance
|
from mypy.types import Instance
|
||||||
from mypy.types import Type as MypyType
|
from mypy.types import Type as MypyType
|
||||||
from mypy.types import UnionType
|
|
||||||
|
|
||||||
from mypy_django_plugin.django.context import DjangoContext
|
from mypy_django_plugin.django.context import DjangoContext
|
||||||
from mypy_django_plugin.lib import helpers
|
from mypy_django_plugin.lib import helpers
|
||||||
|
|
||||||
|
|
||||||
def set_auth_user_model_as_type_for_request_user(ctx: AttributeContext, django_context: DjangoContext) -> MypyType:
|
def set_auth_user_model_as_type_for_request_user(ctx: AttributeContext, django_context: DjangoContext) -> MypyType:
|
||||||
# Imported here because django isn't properly loaded yet when module is loaded
|
|
||||||
from django.contrib.auth.base_user import AbstractBaseUser
|
|
||||||
from django.contrib.auth.models import AnonymousUser
|
|
||||||
|
|
||||||
abstract_base_user_info = helpers.lookup_class_typeinfo(helpers.get_typechecker_api(ctx), AbstractBaseUser)
|
|
||||||
anonymous_user_info = helpers.lookup_class_typeinfo(helpers.get_typechecker_api(ctx), AnonymousUser)
|
|
||||||
|
|
||||||
# This shouldn't be able to happen, as we managed to import the models above.
|
|
||||||
assert abstract_base_user_info is not None
|
|
||||||
assert anonymous_user_info is not None
|
|
||||||
|
|
||||||
if ctx.default_attr_type != UnionType([Instance(abstract_base_user_info, []), Instance(anonymous_user_info, [])]):
|
|
||||||
# Type has been changed from the default in django-stubs.
|
|
||||||
# I.e. HttpRequest has been subclassed and user-type overridden, so let's leave it as is.
|
|
||||||
return ctx.default_attr_type
|
|
||||||
|
|
||||||
auth_user_model = django_context.settings.AUTH_USER_MODEL
|
auth_user_model = django_context.settings.AUTH_USER_MODEL
|
||||||
user_cls = django_context.apps_registry.get_model(auth_user_model)
|
model_cls = django_context.apps_registry.get_model(auth_user_model)
|
||||||
user_info = helpers.lookup_class_typeinfo(helpers.get_typechecker_api(ctx), user_cls)
|
model_info = helpers.lookup_class_typeinfo(helpers.get_typechecker_api(ctx), model_cls)
|
||||||
|
if model_info is None:
|
||||||
if user_info is None:
|
|
||||||
return ctx.default_attr_type
|
return ctx.default_attr_type
|
||||||
|
|
||||||
return UnionType([Instance(user_info, []), Instance(anonymous_user_info, [])])
|
return Instance(model_info, [])
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
[pytest]
|
[pytest]
|
||||||
testpaths =
|
testpaths = ./test-data
|
||||||
./test-plugin
|
|
||||||
./test-data
|
|
||||||
addopts =
|
addopts =
|
||||||
--tb=native
|
--tb=native
|
||||||
-s
|
-s
|
||||||
|
|||||||
@@ -64,12 +64,7 @@ IGNORED_ERRORS = {
|
|||||||
'Incompatible types in string interpolation',
|
'Incompatible types in string interpolation',
|
||||||
'"None" has no attribute',
|
'"None" has no attribute',
|
||||||
'has no attribute "assert',
|
'has no attribute "assert',
|
||||||
'Unsupported dynamic base class',
|
'Unsupported dynamic base class'
|
||||||
'error: "HttpResponse" has no attribute "streaming_content"',
|
|
||||||
'error: "HttpResponse" has no attribute "context_data"',
|
|
||||||
],
|
|
||||||
'admin_inlines': [
|
|
||||||
'error: "HttpResponse" has no attribute "rendered_content"',
|
|
||||||
],
|
],
|
||||||
'admin_utils': [
|
'admin_utils': [
|
||||||
'"Article" has no attribute "non_field"',
|
'"Article" has no attribute "non_field"',
|
||||||
@@ -109,7 +104,6 @@ IGNORED_ERRORS = {
|
|||||||
],
|
],
|
||||||
'builtin_server': [
|
'builtin_server': [
|
||||||
'"ServerHandler" has no attribute',
|
'"ServerHandler" has no attribute',
|
||||||
'Incompatible types in assignment (expression has type "Tuple[BytesIO, BytesIO]"',
|
|
||||||
],
|
],
|
||||||
'bulk_create': [
|
'bulk_create': [
|
||||||
'has incompatible type "List[Country]"; expected "Iterable[TwoFields]"',
|
'has incompatible type "List[Country]"; expected "Iterable[TwoFields]"',
|
||||||
@@ -170,8 +164,7 @@ IGNORED_ERRORS = {
|
|||||||
'Incompatible types in assignment (expression has type "Optional[Any]", variable has type "FloatModel")'
|
'Incompatible types in assignment (expression has type "Optional[Any]", variable has type "FloatModel")'
|
||||||
],
|
],
|
||||||
'decorators': [
|
'decorators': [
|
||||||
'"Type[object]" has no attribute "method"',
|
'"Type[object]" has no attribute "method"'
|
||||||
'Value of type variable "_T" of function cannot be "descriptor_wrapper"'
|
|
||||||
],
|
],
|
||||||
'expressions_window': [
|
'expressions_window': [
|
||||||
'has incompatible type "str"'
|
'has incompatible type "str"'
|
||||||
@@ -185,8 +178,6 @@ IGNORED_ERRORS = {
|
|||||||
],
|
],
|
||||||
'files': [
|
'files': [
|
||||||
'Incompatible types in assignment (expression has type "IOBase", variable has type "File")',
|
'Incompatible types in assignment (expression has type "IOBase", variable has type "File")',
|
||||||
'Argument 1 to "TextIOWrapper" has incompatible type "File"; expected "BinaryIO"',
|
|
||||||
'Incompatible types in assignment (expression has type "BinaryIO", variable has type "File")',
|
|
||||||
],
|
],
|
||||||
'filtered_relation': [
|
'filtered_relation': [
|
||||||
'has no attribute "name"',
|
'has no attribute "name"',
|
||||||
@@ -200,7 +191,7 @@ IGNORED_ERRORS = {
|
|||||||
],
|
],
|
||||||
'from_db_value': [
|
'from_db_value': [
|
||||||
'"Cash" has no attribute',
|
'"Cash" has no attribute',
|
||||||
'"__str__" of "Decimal"',
|
'Argument 1 to "__str__" of "Decimal"',
|
||||||
],
|
],
|
||||||
'get_object_or_404': [
|
'get_object_or_404': [
|
||||||
'Argument 1 to "get_object_or_404" has incompatible type "str"; '
|
'Argument 1 to "get_object_or_404" has incompatible type "str"; '
|
||||||
@@ -249,7 +240,6 @@ IGNORED_ERRORS = {
|
|||||||
],
|
],
|
||||||
'middleware': [
|
'middleware': [
|
||||||
re.compile(r'"(HttpRequest|WSGIRequest)" has no attribute'),
|
re.compile(r'"(HttpRequest|WSGIRequest)" has no attribute'),
|
||||||
'Incompatible types in assignment (expression has type "HttpResponseBase", variable has type "HttpResponse")',
|
|
||||||
],
|
],
|
||||||
'many_to_many': [
|
'many_to_many': [
|
||||||
'(expression has type "List[Article]", variable has type "Article_RelatedManager2',
|
'(expression has type "List[Article]", variable has type "Article_RelatedManager2',
|
||||||
@@ -286,7 +276,6 @@ IGNORED_ERRORS = {
|
|||||||
'"ImageFile" has no attribute "was_opened"',
|
'"ImageFile" has no attribute "was_opened"',
|
||||||
'Incompatible type for "size" of "FloatModel" (got "object", expected "Union[float, int, str, Combinable]")',
|
'Incompatible type for "size" of "FloatModel" (got "object", expected "Union[float, int, str, Combinable]")',
|
||||||
'Incompatible type for "value" of "IntegerModel" (got "object", expected',
|
'Incompatible type for "value" of "IntegerModel" (got "object", expected',
|
||||||
'"Child" has no attribute "get_foo_display"',
|
|
||||||
],
|
],
|
||||||
'model_forms': [
|
'model_forms': [
|
||||||
'"render" of "Widget"',
|
'"render" of "Widget"',
|
||||||
@@ -380,7 +369,6 @@ IGNORED_ERRORS = {
|
|||||||
'responses': [
|
'responses': [
|
||||||
'Argument 1 to "TextIOWrapper" has incompatible type "HttpResponse"; expected "IO[bytes]"',
|
'Argument 1 to "TextIOWrapper" has incompatible type "HttpResponse"; expected "IO[bytes]"',
|
||||||
'"FileLike" has no attribute "closed"',
|
'"FileLike" has no attribute "closed"',
|
||||||
'Argument 1 to "TextIOWrapper" has incompatible type "HttpResponse"; expected "BinaryIO"',
|
|
||||||
],
|
],
|
||||||
'reverse_lookup': [
|
'reverse_lookup': [
|
||||||
"Cannot resolve keyword 'choice' into field"
|
"Cannot resolve keyword 'choice' into field"
|
||||||
@@ -388,9 +376,6 @@ IGNORED_ERRORS = {
|
|||||||
'settings_tests': [
|
'settings_tests': [
|
||||||
'Argument 1 to "Settings" has incompatible type "Optional[str]"; expected "str"'
|
'Argument 1 to "Settings" has incompatible type "Optional[str]"; expected "str"'
|
||||||
],
|
],
|
||||||
'shortcuts': [
|
|
||||||
'error: "Context" has no attribute "request"',
|
|
||||||
],
|
|
||||||
'signals': [
|
'signals': [
|
||||||
'Argument 1 to "append" of "list" has incompatible type "Tuple[Any, Any, Optional[Any], Any]";'
|
'Argument 1 to "append" of "list" has incompatible type "Tuple[Any, Any, Optional[Any], Any]";'
|
||||||
],
|
],
|
||||||
@@ -402,7 +387,7 @@ IGNORED_ERRORS = {
|
|||||||
'"RequestSite" of "Union[Site, RequestSite]" has no attribute "id"',
|
'"RequestSite" of "Union[Site, RequestSite]" has no attribute "id"',
|
||||||
],
|
],
|
||||||
'syndication_tests': [
|
'syndication_tests': [
|
||||||
'Argument 1 to "add_domain" has incompatible type "*Tuple[object, ...]"',
|
'List or tuple expected as variable arguments'
|
||||||
],
|
],
|
||||||
'sessions_tests': [
|
'sessions_tests': [
|
||||||
'Incompatible types in assignment (expression has type "None", variable has type "int")',
|
'Incompatible types in assignment (expression has type "None", variable has type "int")',
|
||||||
@@ -443,7 +428,6 @@ IGNORED_ERRORS = {
|
|||||||
'test_client_regress': [
|
'test_client_regress': [
|
||||||
'(expression has type "Dict[<nothing>, <nothing>]", variable has type "SessionBase")',
|
'(expression has type "Dict[<nothing>, <nothing>]", variable has type "SessionBase")',
|
||||||
'Unsupported left operand type for + ("None")',
|
'Unsupported left operand type for + ("None")',
|
||||||
'Argument 1 to "len" has incompatible type "Context"; expected "Sized"',
|
|
||||||
],
|
],
|
||||||
'transactions': [
|
'transactions': [
|
||||||
'Incompatible types in assignment (expression has type "Thread", variable has type "Callable[[], Any]")'
|
'Incompatible types in assignment (expression has type "Thread", variable has type "Callable[[], Any]")'
|
||||||
@@ -451,11 +435,9 @@ IGNORED_ERRORS = {
|
|||||||
'urlpatterns': [
|
'urlpatterns': [
|
||||||
'"object" not callable',
|
'"object" not callable',
|
||||||
'"None" not callable',
|
'"None" not callable',
|
||||||
'Argument 2 to "path" has incompatible type "Callable[[Any], None]"',
|
|
||||||
'Incompatible return value type (got "None", expected "HttpResponseBase")',
|
|
||||||
],
|
],
|
||||||
'urlpatterns_reverse': [
|
'urlpatterns_reverse': [
|
||||||
'No overload variant of "path" matches argument types "str", "None"',
|
'List or tuple expected as variable arguments',
|
||||||
'No overload variant of "zip" matches argument types "Any", "object"',
|
'No overload variant of "zip" matches argument types "Any", "object"',
|
||||||
'Argument 1 to "get_callable" has incompatible type "int"'
|
'Argument 1 to "get_callable" has incompatible type "int"'
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from pytest_mypy_plugins.collect import File
|
from pytest_mypy.collect import File
|
||||||
from pytest_mypy_plugins.item import YamlTestItem
|
from pytest_mypy.item import YamlTestItem
|
||||||
|
|
||||||
|
|
||||||
def django_plugin_hook(test_item: YamlTestItem) -> None:
|
def django_plugin_hook(test_item: YamlTestItem) -> None:
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ from scripts.enabled_test_modules import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
DJANGO_COMMIT_REFS: Dict[str, Tuple[str, str]] = {
|
DJANGO_COMMIT_REFS: Dict[str, Tuple[str, str]] = {
|
||||||
'2.2': ('stable/2.2.x', '8093aaa8ff9dd7386a069c6eb49fcc1c5980c033'),
|
'2.2': ('stable/2.2.x', '86befcc172c23170a720b3e0c06db51a99b3da59'),
|
||||||
'3.0': ('stable/3.0.x', '44da7abda848f05caaed74f6a749038c87dedfda')
|
'3.0': ('stable/3.0.x', '6cb30414bc0f83b49afc4cae76d4af5656effe9a')
|
||||||
}
|
}
|
||||||
PROJECT_DIRECTORY = Path(__file__).parent.parent
|
PROJECT_DIRECTORY = Path(__file__).parent.parent
|
||||||
DJANGO_SOURCE_DIRECTORY = PROJECT_DIRECTORY / 'django-sources' # type: Path
|
DJANGO_SOURCE_DIRECTORY = PROJECT_DIRECTORY / 'django-sources' # type: Path
|
||||||
|
|||||||
42
setup.py
42
setup.py
@@ -9,7 +9,7 @@ def find_stub_files(name: str) -> List[str]:
|
|||||||
result = []
|
result = []
|
||||||
for root, dirs, files in os.walk(name):
|
for root, dirs, files in os.walk(name):
|
||||||
for file in files:
|
for file in files:
|
||||||
if file.endswith(".pyi"):
|
if file.endswith('.pyi'):
|
||||||
if os.path.sep in root:
|
if os.path.sep in root:
|
||||||
sub_root = root.split(os.path.sep, 1)[-1]
|
sub_root = root.split(os.path.sep, 1)[-1]
|
||||||
file = os.path.join(sub_root, file)
|
file = os.path.join(sub_root, file)
|
||||||
@@ -17,42 +17,34 @@ def find_stub_files(name: str) -> List[str]:
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
with open("README.md", "r") as f:
|
with open('README.md', 'r') as f:
|
||||||
readme = f.read()
|
readme = f.read()
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"mypy>=0.782,<0.790",
|
'mypy>=0.760,<0.770',
|
||||||
"typing-extensions",
|
'typing-extensions',
|
||||||
"django",
|
'django',
|
||||||
]
|
]
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="django-stubs",
|
name="django-stubs",
|
||||||
version="1.6.0",
|
version="1.4.0",
|
||||||
description="Mypy stubs for Django",
|
description='Mypy stubs for Django',
|
||||||
long_description=readme,
|
long_description=readme,
|
||||||
long_description_content_type="text/markdown",
|
long_description_content_type='text/markdown',
|
||||||
license="MIT",
|
license='MIT',
|
||||||
url="https://github.com/typeddjango/django-stubs",
|
url="https://github.com/typeddjango/django-stubs",
|
||||||
author="Maksim Kurnikov",
|
author="Maksim Kurnikov",
|
||||||
author_email="maxim.kurnikov@gmail.com",
|
author_email="maxim.kurnikov@gmail.com",
|
||||||
py_modules=[],
|
py_modules=[],
|
||||||
python_requires=">=3.6",
|
python_requires='>=3.6',
|
||||||
install_requires=dependencies,
|
install_requires=dependencies,
|
||||||
packages=["django-stubs", *find_packages(exclude=["scripts"])],
|
packages=['django-stubs', *find_packages(exclude=['scripts'])],
|
||||||
package_data={"django-stubs": find_stub_files("django-stubs")},
|
package_data={'django-stubs': find_stub_files('django-stubs')},
|
||||||
classifiers=[
|
classifiers=[
|
||||||
"Development Status :: 3 - Alpha",
|
'Development Status :: 3 - Alpha',
|
||||||
"License :: OSI Approved :: MIT License",
|
'License :: OSI Approved :: MIT License',
|
||||||
"Programming Language :: Python :: 3.6",
|
'Programming Language :: Python :: 3.6',
|
||||||
"Programming Language :: Python :: 3.7",
|
'Programming Language :: Python :: 3.7'
|
||||||
"Programming Language :: Python :: 3.8",
|
]
|
||||||
"Framework :: Django",
|
|
||||||
"Framework :: Django :: 2.2",
|
|
||||||
"Framework :: Django :: 3.0",
|
|
||||||
"Typing :: Typed",
|
|
||||||
],
|
|
||||||
project_urls={
|
|
||||||
"Release notes": "https://github.com/typeddjango/django-stubs/releases",
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,130 +0,0 @@
|
|||||||
# "Happy path" test for model admin, trying to cover as many valid
|
|
||||||
# configurations as possible.
|
|
||||||
- case: test_full_admin
|
|
||||||
main: |
|
|
||||||
from django.contrib import admin
|
|
||||||
from django.forms import Form, Textarea
|
|
||||||
from django.db import models
|
|
||||||
from django.core.paginator import Paginator
|
|
||||||
from django.contrib.admin.sites import AdminSite
|
|
||||||
from django.db.models.options import Options
|
|
||||||
from django.http.request import HttpRequest
|
|
||||||
from django.db.models.query import QuerySet
|
|
||||||
|
|
||||||
def an_action(modeladmin: admin.ModelAdmin, request: HttpRequest, queryset: QuerySet) -> None:
|
|
||||||
pass
|
|
||||||
|
|
||||||
class A(admin.ModelAdmin):
|
|
||||||
# BaseModelAdmin
|
|
||||||
autocomplete_fields = ("strs",)
|
|
||||||
raw_id_fields = ["strs"]
|
|
||||||
fields = (
|
|
||||||
"a field",
|
|
||||||
["a", "list of", "fields"],
|
|
||||||
)
|
|
||||||
exclude = ("a", "b")
|
|
||||||
fieldsets = [
|
|
||||||
(None, {"fields": ["a", "b"]}),
|
|
||||||
("group", {"fields": ("c",), "classes": ("a",), "description": "foo"}),
|
|
||||||
]
|
|
||||||
form = Form
|
|
||||||
filter_vertical = ("fields",)
|
|
||||||
filter_horizontal = ("plenty", "of", "fields")
|
|
||||||
radio_fields = {
|
|
||||||
"some_field": admin.VERTICAL,
|
|
||||||
"another_field": admin.HORIZONTAL,
|
|
||||||
}
|
|
||||||
prepopulated_fields = {"slug": ("title",)}
|
|
||||||
formfield_overrides = {models.TextField: {"widget": Textarea}}
|
|
||||||
readonly_fields = ("date_modified",)
|
|
||||||
ordering = ("-pk", "date_modified")
|
|
||||||
sortable_by = ["pk"]
|
|
||||||
view_on_site = True
|
|
||||||
show_full_result_count = False
|
|
||||||
|
|
||||||
# ModelAdmin
|
|
||||||
list_display = ("pk",)
|
|
||||||
list_display_links = ("str",)
|
|
||||||
list_filter = ("str", admin.SimpleListFilter, ("str", admin.SimpleListFilter))
|
|
||||||
list_select_related = True
|
|
||||||
list_per_page = 1
|
|
||||||
list_max_show_all = 2
|
|
||||||
list_editable = ("a", "b")
|
|
||||||
search_fields = ("c", "d")
|
|
||||||
date_hirearchy = "f"
|
|
||||||
save_as = False
|
|
||||||
save_as_continue = True
|
|
||||||
save_on_top = False
|
|
||||||
paginator = Paginator
|
|
||||||
presserve_filters = False
|
|
||||||
inlines = (admin.TabularInline, admin.StackedInline)
|
|
||||||
add_form_template = "template"
|
|
||||||
change_form_template = "template"
|
|
||||||
change_list_template = "template"
|
|
||||||
delete_confirmation_template = "template"
|
|
||||||
delete_selected_confirmation_template = "template"
|
|
||||||
object_history_template = "template"
|
|
||||||
popup_response_template = "template"
|
|
||||||
actions = (an_action, "a_method_action")
|
|
||||||
actions_on_top = True
|
|
||||||
actions_on_bottom = False
|
|
||||||
actions_selection_counter = True
|
|
||||||
admin_site = AdminSite()
|
|
||||||
|
|
||||||
def a_method_action(self, request, queryset):
|
|
||||||
pass
|
|
||||||
|
|
||||||
# This test is here to make sure we're not running into a mypy issue which is
|
|
||||||
# worked around using a somewhat complicated _ListOrTuple union type. Once the
|
|
||||||
# issue is solved upstream this test should pass even with the workaround
|
|
||||||
# replaced by a simpler Sequence type.
|
|
||||||
# https://github.com/python/mypy/issues/8921
|
|
||||||
- case: test_fieldset_workaround_regression
|
|
||||||
main: |
|
|
||||||
from django.contrib import admin
|
|
||||||
|
|
||||||
class A(admin.ModelAdmin):
|
|
||||||
fieldsets = (
|
|
||||||
(None, {
|
|
||||||
'fields': ('name',),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
- case: errors_on_omitting_fields_from_fieldset_opts
|
|
||||||
main: |
|
|
||||||
from django.contrib import admin
|
|
||||||
|
|
||||||
class A(admin.ModelAdmin):
|
|
||||||
fieldsets = [ # type: ignore
|
|
||||||
(None, {}), # E: Key 'fields' missing for TypedDict "_FieldOpts"
|
|
||||||
]
|
|
||||||
- case: errors_on_invalid_radio_fields
|
|
||||||
main: |
|
|
||||||
from django.contrib import admin
|
|
||||||
|
|
||||||
class A(admin.ModelAdmin):
|
|
||||||
radio_fields = {"some_field": 0} # E: Dict entry 0 has incompatible type "str": "Literal[0]"; expected "str": "Union[Literal[1], Literal[2]]"
|
|
||||||
|
|
||||||
class B(admin.ModelAdmin):
|
|
||||||
radio_fields = {1: admin.VERTICAL} # E: Dict entry 0 has incompatible type "int": "Literal[2]"; expected "str": "Union[Literal[1], Literal[2]]"
|
|
||||||
- case: errors_for_invalid_formfield_overrides
|
|
||||||
main: |
|
|
||||||
from django.contrib import admin
|
|
||||||
from django.forms import Textarea
|
|
||||||
|
|
||||||
class A(admin.ModelAdmin):
|
|
||||||
formfield_overrides = {
|
|
||||||
"not a field": { # E: Dict entry 0 has incompatible type "str": "Dict[str, Any]"; expected "Type[Field[Any, Any]]": "Mapping[str, Any]"
|
|
||||||
"widget": Textarea
|
|
||||||
}
|
|
||||||
}
|
|
||||||
- case: errors_for_invalid_action_signature
|
|
||||||
main: |
|
|
||||||
from django.contrib import admin
|
|
||||||
from django.http.request import HttpRequest
|
|
||||||
from django.db.models.query import QuerySet
|
|
||||||
|
|
||||||
def an_action(modeladmin: None) -> None:
|
|
||||||
pass
|
|
||||||
|
|
||||||
class A(admin.ModelAdmin):
|
|
||||||
actions = [an_action] # E: List item 0 has incompatible type "Callable[[None], None]"; expected "Union[Callable[[ModelAdmin, HttpRequest, QuerySet[Any]], None], str]"
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
- case: login_required_bare
|
|
||||||
main: |
|
|
||||||
from django.contrib.auth.decorators import login_required
|
|
||||||
@login_required
|
|
||||||
def view_func(request): ...
|
|
||||||
reveal_type(view_func) # N: Revealed type is 'def (request: Any) -> Any'
|
|
||||||
- case: login_required_fancy
|
|
||||||
main: |
|
|
||||||
from django.contrib.auth.decorators import login_required
|
|
||||||
from django.core.handlers.wsgi import WSGIRequest
|
|
||||||
from django.http import HttpResponse
|
|
||||||
@login_required(redirect_field_name='a', login_url='b')
|
|
||||||
def view_func(request: WSGIRequest, arg: str) -> HttpResponse: ...
|
|
||||||
reveal_type(view_func) # N: Revealed type is 'def (request: django.core.handlers.wsgi.WSGIRequest, arg: builtins.str) -> django.http.response.HttpResponse'
|
|
||||||
- case: login_required_weird
|
|
||||||
main: |
|
|
||||||
from django.contrib.auth.decorators import login_required
|
|
||||||
# This is non-conventional usage, but covered in Django tests, so we allow it.
|
|
||||||
def view_func(request): ...
|
|
||||||
wrapped_view = login_required(view_func, redirect_field_name='a', login_url='b')
|
|
||||||
reveal_type(wrapped_view) # N: Revealed type is 'def (request: Any) -> Any'
|
|
||||||
- case: login_required_incorrect_return
|
|
||||||
main: |
|
|
||||||
from django.contrib.auth.decorators import login_required
|
|
||||||
@login_required() # E: Value of type variable "_VIEW" of function cannot be "Callable[[Any], str]"
|
|
||||||
def view_func2(request) -> str: ...
|
|
||||||
- case: user_passes_test
|
|
||||||
main: |
|
|
||||||
from django.contrib.auth.decorators import user_passes_test
|
|
||||||
@user_passes_test(lambda u: u.username.startswith('super'))
|
|
||||||
def view_func(request): ...
|
|
||||||
reveal_type(view_func) # N: Revealed type is 'def (request: Any) -> Any'
|
|
||||||
- case: user_passes_test_bare_is_error
|
|
||||||
main: |
|
|
||||||
from django.http.response import HttpResponse
|
|
||||||
from django.contrib.auth.decorators import user_passes_test
|
|
||||||
@user_passes_test # E: Argument 1 to "user_passes_test" has incompatible type "Callable[[Any], HttpResponse]"; expected "Callable[[AbstractUser], bool]"
|
|
||||||
def view_func(request) -> HttpResponse: ...
|
|
||||||
- case: permission_required
|
|
||||||
main: |
|
|
||||||
from django.contrib.auth.decorators import permission_required
|
|
||||||
@permission_required('polls.can_vote')
|
|
||||||
def view_func(request): ...
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
- case: field_to_many_and_to_one_attrs_bool_or_none_in_field_base_class
|
|
||||||
main: |
|
|
||||||
from django.db.models import Field
|
|
||||||
|
|
||||||
field: Field
|
|
||||||
my_bool: bool
|
|
||||||
|
|
||||||
my_bool = field.one_to_many
|
|
||||||
my_bool = field.one_to_one
|
|
||||||
my_bool = field.many_to_many
|
|
||||||
my_bool = field.many_to_one
|
|
||||||
|
|
||||||
# Narrowing the types should give us bool
|
|
||||||
assert field.one_to_many is not None
|
|
||||||
my_bool = field.one_to_many
|
|
||||||
assert field.one_to_one is not None
|
|
||||||
my_bool = field.one_to_one
|
|
||||||
assert field.many_to_many is not None
|
|
||||||
my_bool = field.many_to_many
|
|
||||||
assert field.many_to_one is not None
|
|
||||||
my_bool = field.many_to_one
|
|
||||||
out: |
|
|
||||||
main:6: error: Incompatible types in assignment (expression has type "Optional[bool]", variable has type "bool")
|
|
||||||
main:7: error: Incompatible types in assignment (expression has type "Optional[bool]", variable has type "bool")
|
|
||||||
main:8: error: Incompatible types in assignment (expression has type "Optional[bool]", variable has type "bool")
|
|
||||||
main:9: error: Incompatible types in assignment (expression has type "Optional[bool]", variable has type "bool")
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
- case: atomic_bare
|
|
||||||
main: |
|
|
||||||
from django.db.transaction import atomic
|
|
||||||
@atomic
|
|
||||||
def func(x: int) -> list: ...
|
|
||||||
reveal_type(func) # N: Revealed type is 'def (x: builtins.int) -> builtins.list[Any]'
|
|
||||||
- case: atomic_args
|
|
||||||
main: |
|
|
||||||
from django.db.transaction import atomic
|
|
||||||
@atomic(using='bla', savepoint=False)
|
|
||||||
def func(x: int) -> list: ...
|
|
||||||
reveal_type(func) # N: Revealed type is 'def (x: builtins.int) -> builtins.list[Any]'
|
|
||||||
- case: non_atomic_requests_bare
|
|
||||||
main: |
|
|
||||||
from django.db.transaction import non_atomic_requests
|
|
||||||
@non_atomic_requests
|
|
||||||
def view_func(request): ...
|
|
||||||
reveal_type(view_func) # N: Revealed type is 'def (request: Any) -> Any'
|
|
||||||
|
|
||||||
- case: non_atomic_requests_args
|
|
||||||
main: |
|
|
||||||
from django.http.request import HttpRequest
|
|
||||||
from django.http.response import HttpResponse
|
|
||||||
from django.db.transaction import non_atomic_requests
|
|
||||||
@non_atomic_requests
|
|
||||||
def view_func(request: HttpRequest, arg: str) -> HttpResponse: ...
|
|
||||||
reveal_type(view_func) # N: Revealed type is 'def (request: django.http.request.HttpRequest, arg: builtins.str) -> django.http.response.HttpResponse'
|
|
||||||
|
|
||||||
@@ -335,25 +335,3 @@
|
|||||||
objects = MyManager()
|
objects = MyManager()
|
||||||
class ChildUser(models.Model):
|
class ChildUser(models.Model):
|
||||||
objects = MyManager()
|
objects = MyManager()
|
||||||
|
|
||||||
- case: custom_manager_annotate_method_before_type_declaration
|
|
||||||
main: |
|
|
||||||
from myapp.models import ModelA, ModelB, ManagerA
|
|
||||||
reveal_type(ModelA.objects) # N: Revealed type is 'myapp.models.ModelA_ManagerA1[myapp.models.ModelA]'
|
|
||||||
reveal_type(ModelA.objects.do_something) # N: Revealed type is 'def (other_obj: myapp.models.ModelB) -> builtins.str'
|
|
||||||
installed_apps:
|
|
||||||
- myapp
|
|
||||||
files:
|
|
||||||
- path: myapp/__init__.py
|
|
||||||
- path: myapp/models.py
|
|
||||||
content: |
|
|
||||||
from django.db import models
|
|
||||||
class ManagerA(models.Manager):
|
|
||||||
def do_something(self, other_obj: "ModelB") -> str:
|
|
||||||
return 'test'
|
|
||||||
class ModelA(models.Model):
|
|
||||||
title = models.TextField()
|
|
||||||
objects = ManagerA()
|
|
||||||
class ModelB(models.Model):
|
|
||||||
movie = models.TextField()
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,12 +10,6 @@
|
|||||||
reveal_type(User().is_active) # N: Revealed type is 'builtins.bool*'
|
reveal_type(User().is_active) # N: Revealed type is 'builtins.bool*'
|
||||||
reveal_type(User().date_joined) # N: Revealed type is 'datetime.datetime*'
|
reveal_type(User().date_joined) # N: Revealed type is 'datetime.datetime*'
|
||||||
reveal_type(User().last_login) # N: Revealed type is 'Union[datetime.datetime, None]'
|
reveal_type(User().last_login) # N: Revealed type is 'Union[datetime.datetime, None]'
|
||||||
reveal_type(User().is_authenticated) # N: Revealed type is 'Literal[True]'
|
|
||||||
reveal_type(User().is_anonymous) # N: Revealed type is 'Literal[False]'
|
|
||||||
|
|
||||||
from django.contrib.auth.models import AnonymousUser
|
|
||||||
reveal_type(AnonymousUser().is_authenticated) # N: Revealed type is 'Literal[False]'
|
|
||||||
reveal_type(AnonymousUser().is_anonymous) # N: Revealed type is 'Literal[True]'
|
|
||||||
|
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
reveal_type(Permission().name) # N: Revealed type is 'builtins.str*'
|
reveal_type(Permission().name) # N: Revealed type is 'builtins.str*'
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
- case: state_attribute_has_a_type_of_model_state
|
|
||||||
main: |
|
|
||||||
from myapp.models import MyUser
|
|
||||||
user = MyUser(pk=1)
|
|
||||||
reveal_type(user._state) # N: Revealed type is 'django.db.models.base.ModelState'
|
|
||||||
installed_apps:
|
|
||||||
- myapp
|
|
||||||
files:
|
|
||||||
- path: myapp/__init__.py
|
|
||||||
- path: myapp/models.py
|
|
||||||
content: |
|
|
||||||
from django.db import models
|
|
||||||
class MyUser(models.Model):
|
|
||||||
pass
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
- case: testcase_client_attr
|
|
||||||
main: |
|
|
||||||
from django.test.testcases import TestCase
|
|
||||||
|
|
||||||
class ExampleTestCase(TestCase):
|
|
||||||
def test_method(self) -> None:
|
|
||||||
reveal_type(self.client) # N: Revealed type is 'django.test.client.Client'
|
|
||||||
resp = self.client.post('/url', {'doit': 'srs'}, 'application/json', False, True, extra='value')
|
|
||||||
reveal_type(resp.status_code) # N: Revealed type is 'builtins.int'
|
|
||||||
# Attributes monkey-patched by test Client class:
|
|
||||||
resp.json()
|
|
||||||
reveal_type(resp.wsgi_request) # N: Revealed type is 'django.core.handlers.wsgi.WSGIRequest'
|
|
||||||
@@ -46,18 +46,6 @@
|
|||||||
reveal_type(self.get_form(form_class)) # N: Revealed type is 'main.MyForm'
|
reveal_type(self.get_form(form_class)) # N: Revealed type is 'main.MyForm'
|
||||||
reveal_type(self.get_form(MyForm2)) # N: Revealed type is 'main.MyForm2'
|
reveal_type(self.get_form(MyForm2)) # N: Revealed type is 'main.MyForm2'
|
||||||
|
|
||||||
- case: updateview_form_valid_has_form_save
|
|
||||||
main: |
|
|
||||||
from django import forms
|
|
||||||
from django.views.generic.edit import UpdateView
|
|
||||||
|
|
||||||
class MyForm(forms.ModelForm):
|
|
||||||
pass
|
|
||||||
class MyView(UpdateView):
|
|
||||||
form_class = MyForm
|
|
||||||
def form_valid(self, form: forms.BaseModelForm):
|
|
||||||
reveal_type(form.save) # N: Revealed type is 'def (commit: builtins.bool =) -> Any'
|
|
||||||
|
|
||||||
- case: successmessagemixin_compatible_with_formmixin
|
- case: successmessagemixin_compatible_with_formmixin
|
||||||
main: |
|
main: |
|
||||||
from django.views.generic.edit import FormMixin
|
from django.views.generic.edit import FormMixin
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
disable_cache: true
|
disable_cache: true
|
||||||
main: |
|
main: |
|
||||||
from django.http.request import HttpRequest
|
from django.http.request import HttpRequest
|
||||||
reveal_type(HttpRequest().user) # N: Revealed type is 'Union[myapp.models.MyUser, django.contrib.auth.models.AnonymousUser]'
|
reveal_type(HttpRequest().user) # N: Revealed type is 'myapp.models.MyUser'
|
||||||
# check that other fields work ok
|
# check that other fields work ok
|
||||||
reveal_type(HttpRequest().method) # N: Revealed type is 'Union[builtins.str, None]'
|
reveal_type(HttpRequest().method) # N: Revealed type is 'Union[builtins.str, None]'
|
||||||
custom_settings: |
|
custom_settings: |
|
||||||
INSTALLED_APPS = ('django.contrib.contenttypes', 'django.contrib.auth', 'myapp')
|
INSTALLED_APPS = ('django.contrib.contenttypes', 'myapp')
|
||||||
AUTH_USER_MODEL='myapp.MyUser'
|
AUTH_USER_MODEL='myapp.MyUser'
|
||||||
files:
|
files:
|
||||||
- path: myapp/__init__.py
|
- path: myapp/__init__.py
|
||||||
@@ -15,40 +15,3 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
class MyUser(models.Model):
|
class MyUser(models.Model):
|
||||||
pass
|
pass
|
||||||
- case: request_object_user_can_be_descriminated
|
|
||||||
disable_cache: true
|
|
||||||
main: |
|
|
||||||
from django.http.request import HttpRequest
|
|
||||||
request = HttpRequest()
|
|
||||||
reveal_type(request.user) # N: Revealed type is 'Union[django.contrib.auth.models.User, django.contrib.auth.models.AnonymousUser]'
|
|
||||||
if not request.user.is_anonymous:
|
|
||||||
reveal_type(request.user) # N: Revealed type is 'django.contrib.auth.models.User'
|
|
||||||
if request.user.is_authenticated:
|
|
||||||
reveal_type(request.user) # N: Revealed type is 'django.contrib.auth.models.User'
|
|
||||||
custom_settings: |
|
|
||||||
INSTALLED_APPS = ('django.contrib.contenttypes', 'django.contrib.auth')
|
|
||||||
- case: subclass_request_not_changed_user_type
|
|
||||||
disable_cache: true
|
|
||||||
main: |
|
|
||||||
from django.http.request import HttpRequest
|
|
||||||
class MyRequest(HttpRequest):
|
|
||||||
foo: int # Just do something
|
|
||||||
|
|
||||||
request = MyRequest()
|
|
||||||
reveal_type(request.user) # N: Revealed type is 'Union[django.contrib.auth.models.User, django.contrib.auth.models.AnonymousUser]'
|
|
||||||
custom_settings: |
|
|
||||||
INSTALLED_APPS = ('django.contrib.contenttypes', 'django.contrib.auth')
|
|
||||||
|
|
||||||
- case: subclass_request_changed_user_type
|
|
||||||
disable_cache: true
|
|
||||||
main: |
|
|
||||||
from django.http.request import HttpRequest
|
|
||||||
from django.contrib.auth.models import User
|
|
||||||
class MyRequest(HttpRequest):
|
|
||||||
user: User # Override the type of user
|
|
||||||
|
|
||||||
request = MyRequest()
|
|
||||||
reveal_type(request.user) # N: Revealed type is 'django.contrib.auth.models.User'
|
|
||||||
custom_settings: |
|
|
||||||
INSTALLED_APPS = ('django.contrib.contenttypes', 'django.contrib.auth')
|
|
||||||
|
|
||||||
|
|||||||
@@ -36,24 +36,3 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
class MyUser(models.Model):
|
class MyUser(models.Model):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
- case: check_render_function_arguments_annotations
|
|
||||||
main: |
|
|
||||||
from typing import Any
|
|
||||||
from typing_extensions import TypedDict
|
|
||||||
from django.shortcuts import render
|
|
||||||
from django.http.request import HttpRequest
|
|
||||||
|
|
||||||
TestContext = TypedDict("TestContext", {"user": Any})
|
|
||||||
test_context: TestContext = {"user": "test"}
|
|
||||||
reveal_type(test_context) # N: Revealed type is 'TypedDict('main.TestContext', {'user': Any})'
|
|
||||||
reveal_type(render(HttpRequest(), '', test_context)) # N: Revealed type is 'django.http.response.HttpResponse'
|
|
||||||
|
|
||||||
- case: check_redirect_return_annotation
|
|
||||||
main: |
|
|
||||||
from django.shortcuts import redirect
|
|
||||||
reveal_type(redirect(to = '', permanent = True)) # N: Revealed type is 'django.http.response.HttpResponsePermanentRedirect'
|
|
||||||
reveal_type(redirect(to = '', permanent = False)) # N: Revealed type is 'django.http.response.HttpResponseRedirect'
|
|
||||||
|
|
||||||
var = True
|
|
||||||
reveal_type(redirect(to = '', permanent = var)) # N: Revealed type is 'Union[django.http.response.HttpResponseRedirect, django.http.response.HttpResponsePermanentRedirect]'
|
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
- case: method_decorator_class
|
|
||||||
main: |
|
|
||||||
from django.views.generic.base import View
|
|
||||||
from django.utils.decorators import method_decorator
|
|
||||||
from django.contrib.auth.decorators import login_required
|
|
||||||
@method_decorator(login_required, name='dispatch')
|
|
||||||
class TestView(View): ...
|
|
||||||
reveal_type(TestView()) # N: Revealed type is 'main.TestView'
|
|
||||||
- case: method_decorator_function
|
|
||||||
main: |
|
|
||||||
from django.views.generic.base import View
|
|
||||||
from django.utils.decorators import method_decorator
|
|
||||||
from django.contrib.auth.decorators import login_required
|
|
||||||
from django.http.response import HttpResponse
|
|
||||||
from django.http.request import HttpRequest
|
|
||||||
class TestView(View):
|
|
||||||
@method_decorator(login_required)
|
|
||||||
def dispatch(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
|
||||||
return super().dispatch(request, *args, **kwargs)
|
|
||||||
reveal_type(dispatch) # N: Revealed type is 'def (self: main.TestView, request: django.http.request.HttpRequest, *args: Any, **kwargs: Any) -> django.http.response.HttpResponse'
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
import tempfile
|
|
||||||
import typing
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
from mypy_django_plugin.main import extract_django_settings_module
|
|
||||||
|
|
||||||
TEMPLATE = """usage: (config)
|
|
||||||
...
|
|
||||||
[mypy.plugins.django_stubs]
|
|
||||||
django_settings_module: str (required)
|
|
||||||
...
|
|
||||||
(django-stubs) mypy: error: 'django_settings_module' is not set: {}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
'config_file_contents,message_part',
|
|
||||||
[
|
|
||||||
pytest.param(
|
|
||||||
None,
|
|
||||||
'mypy config file is not specified or found',
|
|
||||||
id='missing-file',
|
|
||||||
),
|
|
||||||
pytest.param(
|
|
||||||
['[not-really-django-stubs]'],
|
|
||||||
'no section [mypy.plugins.django-stubs]',
|
|
||||||
id='missing-section',
|
|
||||||
),
|
|
||||||
pytest.param(
|
|
||||||
['[mypy.plugins.django-stubs]',
|
|
||||||
'\tnot_django_not_settings_module = badbadmodule'],
|
|
||||||
'the setting is not provided',
|
|
||||||
id='missing-settings-module',
|
|
||||||
),
|
|
||||||
pytest.param(
|
|
||||||
['[mypy.plugins.django-stubs]'],
|
|
||||||
'the setting is not provided',
|
|
||||||
id='no-settings-given',
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_misconfiguration_handling(capsys, config_file_contents, message_part):
|
|
||||||
# type: (typing.Any, typing.List[str], str) -> None
|
|
||||||
"""Invalid configuration raises `SystemExit` with a precise error message."""
|
|
||||||
with tempfile.NamedTemporaryFile(mode='w+') as config_file:
|
|
||||||
if not config_file_contents:
|
|
||||||
config_file.close()
|
|
||||||
else:
|
|
||||||
config_file.write('\n'.join(config_file_contents).expandtabs(4))
|
|
||||||
config_file.seek(0)
|
|
||||||
|
|
||||||
with pytest.raises(SystemExit, match='2'):
|
|
||||||
extract_django_settings_module(config_file.name)
|
|
||||||
|
|
||||||
error_message = TEMPLATE.format(message_part)
|
|
||||||
assert error_message == capsys.readouterr().err
|
|
||||||
|
|
||||||
|
|
||||||
def test_correct_configuration() -> None:
|
|
||||||
"""Django settings module gets extracted given valid configuration."""
|
|
||||||
config_file_contents = [
|
|
||||||
'[mypy.plugins.django-stubs]',
|
|
||||||
'\tsome_other_setting = setting',
|
|
||||||
'\tdjango_settings_module = my.module',
|
|
||||||
]
|
|
||||||
with tempfile.NamedTemporaryFile(mode='w+') as config_file:
|
|
||||||
config_file.write('\n'.join(config_file_contents).expandtabs(4))
|
|
||||||
config_file.seek(0)
|
|
||||||
|
|
||||||
extracted = extract_django_settings_module(config_file.name)
|
|
||||||
|
|
||||||
assert extracted == 'my.module'
|
|
||||||
Reference in New Issue
Block a user