Add typechecking for 'file_storage', 'files' test folders (#101)

* add typechecking for 'file_storage', 'files' test folders

* fix File class annotations
This commit is contained in:
Maxim Kurnikov
2019-07-07 03:58:00 +03:00
committed by GitHub
parent 861c6653fd
commit d8230a4147
4 changed files with 22 additions and 24 deletions

View File

@@ -1,12 +1,13 @@
from io import StringIO from io import StringIO
from typing import Any, Iterator, Optional, Union from typing import Any, Iterator, Optional, Union, IO, Type
from types import TracebackType
from django.core.files.utils import FileProxyMixin from django.core.files.utils import FileProxyMixin
class File(FileProxyMixin): class File(FileProxyMixin, IO[Any]):
DEFAULT_CHUNK_SIZE: Any = ... DEFAULT_CHUNK_SIZE: Any = ...
file: StringIO = ... file: StringIO = ...
name: Optional[str] = ... name: str = ...
mode: str = ... mode: str = ...
def __init__(self, file: Any, name: Optional[str] = ...) -> None: ... def __init__(self, file: Any, name: Optional[str] = ...) -> None: ...
def __bool__(self) -> bool: ... def __bool__(self) -> bool: ...
@@ -15,8 +16,11 @@ class File(FileProxyMixin):
def chunks(self, chunk_size: Optional[int] = ...) -> Iterator[Union[bytes, bytearray]]: ... def chunks(self, chunk_size: Optional[int] = ...) -> Iterator[Union[bytes, bytearray]]: ...
def multiple_chunks(self, chunk_size: Optional[Any] = ...): ... def multiple_chunks(self, chunk_size: Optional[Any] = ...): ...
def __iter__(self) -> Iterator[Union[bytes, str]]: ... def __iter__(self) -> Iterator[Union[bytes, str]]: ...
def __next__(self) -> Union[bytes, str]: ...
def __enter__(self) -> File: ... def __enter__(self) -> File: ...
def __exit__(self, exc_type: None, exc_value: None, tb: None) -> None: ... def __exit__(
self, exc_type: Optional[Type[BaseException]], exc_value: Optional[BaseException], tb: Optional[TracebackType]
) -> bool: ...
def open(self, mode: Optional[str] = ...) -> File: ... def open(self, mode: Optional[str] = ...) -> File: ...
def close(self) -> None: ... def close(self) -> None: ...

View File

@@ -1,5 +1,4 @@
from io import BytesIO from typing import Any, IO, Union
from typing import Any, Union
from django.core.files import File from django.core.files import File
@@ -11,4 +10,4 @@ class ImageFile(File):
@property @property
def height(self) -> int: ... def height(self) -> int: ...
def get_image_dimensions(file_or_path: Union[BytesIO, str], close: bool = ...) -> Any: ... def get_image_dimensions(file_or_path: Union[str, IO[bytes]], close: bool = ...) -> Any: ...

View File

@@ -1,5 +1,5 @@
from datetime import datetime from datetime import datetime
from typing import Any, IO, List, Optional, Tuple from typing import Any, List, Optional, Tuple, IO
from django.core.files.base import File from django.core.files.base import File
from django.utils.functional import LazyObject from django.utils.functional import LazyObject

View File

@@ -61,6 +61,8 @@ IGNORED_ERRORS = {
+ 'expected "Union[str, bytes, bytearray]"', + 'expected "Union[str, bytes, bytearray]"',
'Incompatible types in assignment (expression has type "None", variable has type Module)', 'Incompatible types in assignment (expression has type "None", variable has type Module)',
'note:', 'note:',
'undefined in superclass',
'**Dict'
], ],
'admin_scripts': [ 'admin_scripts': [
'Incompatible types in assignment (expression has type "Callable[' 'Incompatible types in assignment (expression has type "Callable['
@@ -76,7 +78,6 @@ IGNORED_ERRORS = {
'"object" not callable', '"object" not callable',
], ],
'aggregation': [ 'aggregation': [
'"as_sql" undefined in superclass',
'Incompatible type for "contact" of "Book" (got "Optional[Author]", expected "Union[Author, Combinable]")', 'Incompatible type for "contact" of "Book" (got "Optional[Author]", expected "Union[Author, Combinable]")',
'Incompatible type for "publisher" of "Book" (got "Optional[Publisher]", ' 'Incompatible type for "publisher" of "Book" (got "Optional[Publisher]", '
+ 'expected "Union[Publisher, Combinable]")' + 'expected "Union[Publisher, Combinable]")'
@@ -114,16 +115,18 @@ IGNORED_ERRORS = {
'dispatch': [ 'dispatch': [
'Argument 1 to "connect" of "Signal" has incompatible type "object"; expected "Callable[..., Any]"' 'Argument 1 to "connect" of "Signal" has incompatible type "object"; expected "Callable[..., Any]"'
], ],
'deprecation': [
re.compile('"(old|new)" undefined in superclass')
],
'db_functions': [ 'db_functions': [
'for **', 'for **',
'expected "float"', 'expected "float"',
'Incompatible types in assignment (expression has type "Optional[FloatModel]", variable has type "FloatModel")' 'Incompatible types in assignment (expression has type "Optional[FloatModel]", variable has type "FloatModel")'
], ],
'file_uploads': [ 'file_storage': [
'"handle_uncaught_exception" undefined in superclass' 'Incompatible types in assignment (expression has type "Callable[[], Any]"'
],
'files': [
'"file_move_safe" does not return a value',
'Argument 1 to "unlink" has incompatible type "Optional[str]"; expected "Union[bytes, str, _PathLike[Any]]"',
'Incompatible types in assignment (expression has type "IOBase", variable has type "File")'
], ],
'fixtures': [ 'fixtures': [
'Incompatible types in assignment (expression has type "int", target has type "Iterable[str]")' 'Incompatible types in assignment (expression has type "int", target has type "Iterable[str]")'
@@ -132,7 +135,6 @@ IGNORED_ERRORS = {
'List item 0 has incompatible type "Jinja2"; expected "DjangoTemplates"', 'List item 0 has incompatible type "Jinja2"; expected "DjangoTemplates"',
'Not enough arguments for format string', 'Not enough arguments for format string',
'Argument after ** must be a mapping, not "object"', 'Argument after ** must be a mapping, not "object"',
'"media" undefined in superclass',
'expression has type "None", base class "TestFormParent"', 'expression has type "None", base class "TestFormParent"',
'variable has type "SongForm"', 'variable has type "SongForm"',
'"full_clean" of "BaseForm" does not return a value', '"full_clean" of "BaseForm" does not return a value',
@@ -158,16 +160,9 @@ IGNORED_ERRORS = {
+ 'expected "Union[Type[<nothing>], QuerySet[<nothing>, <nothing>]]"', + 'expected "Union[Type[<nothing>], QuerySet[<nothing>, <nothing>]]"',
'CustomClass' 'CustomClass'
], ],
'get_or_create': [
'Argument 1 to "update_or_create" of "QuerySet" has incompatible type "**Dict[str, object]"; '
+ 'expected "Optional[MutableMapping[str, Any]]"'
],
'humanize_tests': [ 'humanize_tests': [
'Argument 1 to "append" of "list" has incompatible type "None"; expected "str"' 'Argument 1 to "append" of "list" has incompatible type "None"; expected "str"'
], ],
'logging_tests': [
re.compile('"(setUpClass|tearDownClass)" undefined in superclass')
],
'lookup': [ 'lookup': [
'Unexpected keyword argument "headline__startswith" for "in_bulk" of "QuerySet"', 'Unexpected keyword argument "headline__startswith" for "in_bulk" of "QuerySet"',
], ],
@@ -385,9 +380,9 @@ TESTS_DIRS = [
'field_deconstruction', 'field_deconstruction',
'field_defaults', 'field_defaults',
'field_subclassing', 'field_subclassing',
# TODO: 'file_storage', 'file_storage',
'file_uploads', 'file_uploads',
# TODO: 'files', 'files',
'filtered_relation', 'filtered_relation',
'fixtures', 'fixtures',
'fixtures_model_package', 'fixtures_model_package',