mirror of
https://github.com/davidhalter/django-stubs.git
synced 2025-12-06 12:14:28 +08:00
enable tests typechecking using django submodule
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,7 +5,6 @@ out/
|
||||
/django
|
||||
.idea/
|
||||
.mypy_cache/
|
||||
django-sources
|
||||
build/
|
||||
dist/
|
||||
pip-wheel-metadata/
|
||||
|
||||
4
.gitmodules
vendored
Normal file
4
.gitmodules
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
[submodule "django-sources"]
|
||||
path = django-sources
|
||||
url = https://github.com/django/django.git
|
||||
branch = stable/2.2.x
|
||||
@@ -30,5 +30,4 @@ before_install: |
|
||||
# Upgrade pip, setuptools, and wheel
|
||||
pip install -U pip setuptools wheel
|
||||
install: |
|
||||
pip install -r ./dev-requirements.txt
|
||||
pip install -r ./scripts/typecheck-tests-requirements.txt
|
||||
pip install -r ./dev-requirements.txt
|
||||
@@ -1,5 +1,5 @@
|
||||
black
|
||||
pytest-mypy-plugins
|
||||
pytest-mypy-plugins==1.0.3
|
||||
flake8
|
||||
isort==4.3.4
|
||||
-e .
|
||||
|
||||
1
django-sources
Submodule
1
django-sources
Submodule
Submodule django-sources added at 4d6449e125
229
scripts/django_tests_settings.py
Normal file
229
scripts/django_tests_settings.py
Normal file
@@ -0,0 +1,229 @@
|
||||
SECRET_KEY = '1'
|
||||
SITE_ID = 1
|
||||
|
||||
INSTALLED_APPS = [
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.sites',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.admin.apps.SimpleAdminConfig',
|
||||
'django.contrib.staticfiles',
|
||||
]
|
||||
|
||||
test_modules = [
|
||||
'absolute_url_overrides',
|
||||
'admin_autodiscover',
|
||||
'admin_changelist',
|
||||
'admin_checks',
|
||||
'admin_custom_urls',
|
||||
'admin_default_site',
|
||||
'admin_docs',
|
||||
'admin_filters',
|
||||
'admin_inlines',
|
||||
'admin_ordering',
|
||||
'admin_registration',
|
||||
'admin_scripts',
|
||||
'admin_utils',
|
||||
'admin_views',
|
||||
'admin_widgets',
|
||||
'aggregation',
|
||||
'aggregation_regress',
|
||||
'annotations',
|
||||
'app_loading',
|
||||
'apps',
|
||||
'auth_tests',
|
||||
'backends',
|
||||
'base',
|
||||
'bash_completion',
|
||||
'basic',
|
||||
'builtin_server',
|
||||
'bulk_create',
|
||||
'cache',
|
||||
'check_framework',
|
||||
'choices',
|
||||
'conditional_processing',
|
||||
'constraints',
|
||||
'contenttypes_tests',
|
||||
'context_processors',
|
||||
'csrf_tests',
|
||||
'custom_columns',
|
||||
'custom_lookups',
|
||||
'custom_managers',
|
||||
'custom_methods',
|
||||
'custom_migration_operations',
|
||||
'custom_pk',
|
||||
'datatypes',
|
||||
'dates',
|
||||
'datetimes',
|
||||
'db_functions',
|
||||
'db_typecasts',
|
||||
'db_utils',
|
||||
'dbshell',
|
||||
'decorators',
|
||||
'defer',
|
||||
'defer_regress',
|
||||
'delete',
|
||||
'delete_regress',
|
||||
'deprecation',
|
||||
'dispatch',
|
||||
'distinct_on_fields',
|
||||
'empty',
|
||||
'expressions',
|
||||
'expressions_case',
|
||||
'expressions_window',
|
||||
'extra_regress',
|
||||
'field_deconstruction',
|
||||
'field_defaults',
|
||||
'field_subclassing',
|
||||
'file_storage',
|
||||
'file_uploads',
|
||||
'files',
|
||||
'filtered_relation',
|
||||
'fixtures',
|
||||
'fixtures_model_package',
|
||||
'fixtures_regress',
|
||||
'flatpages_tests',
|
||||
'force_insert_update',
|
||||
'foreign_object',
|
||||
'forms_tests',
|
||||
'from_db_value',
|
||||
'generic_inline_admin',
|
||||
'generic_relations',
|
||||
'generic_relations_regress',
|
||||
'generic_views',
|
||||
'get_earliest_or_latest',
|
||||
'get_object_or_404',
|
||||
'get_or_create',
|
||||
'gis_tests',
|
||||
'handlers',
|
||||
'httpwrappers',
|
||||
'humanize_tests',
|
||||
'i18n',
|
||||
'import_error_package',
|
||||
'indexes',
|
||||
'inline_formsets',
|
||||
'inspectdb',
|
||||
'introspection',
|
||||
'invalid_models_tests',
|
||||
'known_related_objects',
|
||||
'logging_tests',
|
||||
'lookup',
|
||||
'm2m_and_m2o',
|
||||
'm2m_intermediary',
|
||||
'm2m_multiple',
|
||||
'm2m_recursive',
|
||||
'm2m_regress',
|
||||
'm2m_signals',
|
||||
'm2m_through',
|
||||
'm2m_through_regress',
|
||||
'm2o_recursive',
|
||||
'mail',
|
||||
'managers_regress',
|
||||
'many_to_many',
|
||||
'many_to_one',
|
||||
'many_to_one_null',
|
||||
'max_lengths',
|
||||
'messages_tests',
|
||||
'middleware',
|
||||
'middleware_exceptions',
|
||||
'migrate_signals',
|
||||
'migration_test_data_persistence',
|
||||
'migrations',
|
||||
'migrations2',
|
||||
'model_fields',
|
||||
'model_forms',
|
||||
'model_formsets',
|
||||
'model_formsets_regress',
|
||||
'model_indexes',
|
||||
'model_inheritance',
|
||||
'model_inheritance_regress',
|
||||
'model_meta',
|
||||
'model_options',
|
||||
'model_package',
|
||||
'model_regress',
|
||||
'modeladmin',
|
||||
'multiple_database',
|
||||
'mutually_referential',
|
||||
'nested_foreign_keys',
|
||||
'no_models',
|
||||
'null_fk',
|
||||
'null_fk_ordering',
|
||||
'null_queries',
|
||||
'one_to_one',
|
||||
'or_lookups',
|
||||
'order_with_respect_to',
|
||||
'ordering',
|
||||
'pagination',
|
||||
'postgres_tests',
|
||||
'prefetch_related',
|
||||
'project_template',
|
||||
'properties',
|
||||
'proxy_model_inheritance',
|
||||
'proxy_models',
|
||||
'queries',
|
||||
'queryset_pickle',
|
||||
'raw_query',
|
||||
'redirects_tests',
|
||||
'requests',
|
||||
'reserved_names',
|
||||
'resolve_url',
|
||||
'responses',
|
||||
'reverse_lookup',
|
||||
'save_delete_hooks',
|
||||
'schema',
|
||||
'select_for_update',
|
||||
'select_related',
|
||||
'select_related_onetoone',
|
||||
'select_related_regress',
|
||||
'serializers',
|
||||
'servers',
|
||||
'sessions_tests',
|
||||
'settings_tests',
|
||||
'shell',
|
||||
'shortcuts',
|
||||
'signals',
|
||||
'signed_cookies_tests',
|
||||
'signing',
|
||||
'sitemaps_tests',
|
||||
'sites_framework',
|
||||
'sites_tests',
|
||||
'staticfiles_tests',
|
||||
'str',
|
||||
'string_lookup',
|
||||
'swappable_models',
|
||||
'syndication_tests',
|
||||
'template_backends',
|
||||
'template_loader',
|
||||
'template_tests',
|
||||
'test_client',
|
||||
'test_client_regress',
|
||||
'test_exceptions',
|
||||
'test_runner',
|
||||
'test_runner_apps',
|
||||
'test_utils',
|
||||
'timezones',
|
||||
'transaction_hooks',
|
||||
'transactions',
|
||||
'unmanaged_models',
|
||||
'update',
|
||||
'update_only_fields',
|
||||
'urlpatterns',
|
||||
'urlpatterns_reverse',
|
||||
'user_commands',
|
||||
'utils_tests',
|
||||
'validation',
|
||||
'validators',
|
||||
'version',
|
||||
'view_tests',
|
||||
'wsgi',
|
||||
]
|
||||
|
||||
invalid_apps = {
|
||||
'import_error_package',
|
||||
}
|
||||
|
||||
for app in invalid_apps:
|
||||
test_modules.remove(app)
|
||||
|
||||
INSTALLED_APPS += test_modules
|
||||
337
scripts/enabled_test_modules.py
Normal file
337
scripts/enabled_test_modules.py
Normal file
@@ -0,0 +1,337 @@
|
||||
# Some errors occur for the test suite itself, and cannot be addressed via django-stubs. They should be ignored
|
||||
# using this constant.
|
||||
import re
|
||||
|
||||
IGNORED_MODULES = {'schema', 'gis_tests', 'admin_widgets', 'admin_filters', 'migrations',
|
||||
'sitemaps_tests', 'staticfiles_tests', 'modeladmin', 'model_forms',
|
||||
'generic_views', 'forms_tests', 'flatpages_tests', 'admin_utils',
|
||||
'admin_ordering', 'admin_changelist', 'admin_views', 'mail', 'redirects_tests',
|
||||
'invalid_models_tests', 'i18n', 'migrate_signals', 'model_formsets',
|
||||
'template_tests', 'template_backends', 'test_runner', 'admin_scripts',
|
||||
'sites_tests', 'inline_formsets', 'foreign_object', 'cache', 'test_client', 'test_client_regress'}
|
||||
|
||||
MOCK_OBJECTS = ['MockRequest', 'MockCompiler', 'modelz', 'call_count', 'call_args_list',
|
||||
'call_args', 'MockUser', 'Xtemplate', 'DummyRequest', 'DummyUser', 'MinimalUser']
|
||||
EXTERNAL_MODULES = ['psycopg2', 'PIL', 'selenium', 'oracle', 'mysql', 'sqlite3', 'sqlparse', 'tblib', 'numpy',
|
||||
'bcrypt', 'argon2', 'xml.dom']
|
||||
IGNORED_ERRORS = {
|
||||
'__new_common__': [
|
||||
*MOCK_OBJECTS,
|
||||
*EXTERNAL_MODULES,
|
||||
'SupportsFloat',
|
||||
'Need type annotation for',
|
||||
'has no attribute "getvalue"',
|
||||
'Cannot assign to a method',
|
||||
'Cannot infer type of lambda',
|
||||
'already defined (possibly by an import)',
|
||||
'already defined on line',
|
||||
'Cannot assign to a type',
|
||||
'"HttpResponse" has no attribute',
|
||||
'"HttpResponseBase" has no attribute',
|
||||
# '"HttpRequest" has no attribute',
|
||||
'"object" has no attribute',
|
||||
'defined in the current module',
|
||||
re.compile(r'"Callable\[(\[(Any(, )?)*((, )?VarArg\(Any\))?((, )?KwArg\(Any\))?\]|\.\.\.), Any\]" '
|
||||
r'has no attribute'),
|
||||
'has no attribute "deconstruct"',
|
||||
# private members
|
||||
re.compile(r'has no attribute ("|\')_[a-zA-Z_]+("|\')'),
|
||||
"'Settings' object has no attribute",
|
||||
'**Dict',
|
||||
re.compile(r"Expression of type '.*' is not supported"),
|
||||
'has incompatible type "object"',
|
||||
'undefined in superclass',
|
||||
'Argument after ** must be a mapping, not "object"',
|
||||
'note:',
|
||||
re.compile(r'Item "None" of "[a-zA-Z_ ,\[\]]+" has no attribute'),
|
||||
'"Optional[List[_Record]]"',
|
||||
'"Callable[..., None]" has no attribute',
|
||||
'does not return a value',
|
||||
'has no attribute "alternatives"',
|
||||
'gets multiple values for keyword argument',
|
||||
'"Handler" has no attribute',
|
||||
'Module has no attribute',
|
||||
"No installed app with label 'missing'",
|
||||
'namedtuple',
|
||||
'Lookups not supported yet',
|
||||
'Argument 1 to "loads" has incompatible type',
|
||||
# TODO: see test in managers/test_managers.yml
|
||||
"Cannot determine type of",
|
||||
'cache_clear',
|
||||
'cache_info',
|
||||
'Incompatible types in assignment (expression has type "None", variable has type Module)',
|
||||
"Module 'django.contrib.messages.storage.fallback' has no attribute 'CookieStorage'",
|
||||
# TODO: not supported yet
|
||||
'GenericRelation',
|
||||
'RelatedObjectDoesNotExist',
|
||||
# Rel's attributes are not accessible from `get_field()`
|
||||
re.compile(r'"Field\[Any, Any\]" has no attribute '
|
||||
r'"(through|field_name|field|get_related_field|related_model|related_name'
|
||||
r'|get_accessor_name|empty_strings_allowed|many_to_many)"'),
|
||||
# TODO: multitable inheritance
|
||||
'ptr',
|
||||
'Incompatible types in assignment (expression has type "Callable[',
|
||||
'SimpleLazyObject'
|
||||
],
|
||||
'apps': [
|
||||
'Incompatible types in assignment (expression has type "str", target has type "type")',
|
||||
],
|
||||
'auth_tests': [
|
||||
'"PasswordValidator" has no attribute "min_length"',
|
||||
'AbstractBaseUser',
|
||||
'Argument "password_validators" to "password_changed" has incompatible type "Tuple[Validator]"; '
|
||||
+ 'expected "Optional[Sequence[PasswordValidator]]"',
|
||||
'Unsupported right operand type for in ("object")',
|
||||
'mock_getpass',
|
||||
'Unsupported left operand type for + ("Sequence[str]")',
|
||||
'AuthenticationFormWithInactiveUsersOkay',
|
||||
'Incompatible types in assignment (expression has type "Dict[str, Any]", variable has type "QueryDict")',
|
||||
],
|
||||
'basic': [
|
||||
'Unexpected keyword argument "unknown_kwarg" for "refresh_from_db" of "Model"',
|
||||
'Unexpected attribute "foo" for model "Article"',
|
||||
'has no attribute "touched"'
|
||||
],
|
||||
'backends': [
|
||||
'"DatabaseError" has no attribute "pgcode"'
|
||||
],
|
||||
'check_framework': [
|
||||
'base class "Model" defined the type as "Callable',
|
||||
],
|
||||
'constraints': [
|
||||
'Argument "condition" to "UniqueConstraint" has incompatible type "str"; expected "Optional[Q]"'
|
||||
],
|
||||
'contenttypes_tests': [
|
||||
# 'Item "Model" of "Union[GenericForeignKey, Model, None]" has no attribute'
|
||||
'base class "BaseOrderWithRespectToTests" defined the type as "None"'
|
||||
],
|
||||
'custom_lookups': [
|
||||
'in base class "SQLFuncMixin"'
|
||||
],
|
||||
'custom_pk': [
|
||||
'"Employee" has no attribute "id"'
|
||||
],
|
||||
'custom_managers': [
|
||||
'Unsupported dynamic base class',
|
||||
'"Book" has no attribute "favorite_avg"',
|
||||
'Incompatible types in assignment (expression has type "CharField'
|
||||
],
|
||||
'csrf_tests': [
|
||||
'Incompatible types in assignment (expression has type "property", ' +
|
||||
'base class "HttpRequest" defined the type as "QueryDict")'
|
||||
],
|
||||
'dates': [
|
||||
'Too few arguments for "dates" of "QuerySet"',
|
||||
],
|
||||
'defer': [
|
||||
'Too many arguments for "refresh_from_db" of "Model"'
|
||||
],
|
||||
'dispatch': [
|
||||
'Item "str" of "Union[ValueError, str]" has no attribute "args"'
|
||||
],
|
||||
'deprecation': [
|
||||
'"Manager" has no attribute "old"',
|
||||
'"Manager" has no attribute "new"'
|
||||
],
|
||||
'db_functions': [
|
||||
'"FloatModel" has no attribute',
|
||||
],
|
||||
'decorators': [
|
||||
'"Type[object]" has no attribute "method"'
|
||||
],
|
||||
'expressions_case': [
|
||||
'Item "Field[Any, Any]" of "Union[Field[Any, Any], ForeignObjectRel]" has no attribute "is_relation"'
|
||||
],
|
||||
'expressions_window': [
|
||||
'has incompatible type "str"'
|
||||
],
|
||||
'file_uploads': [
|
||||
'"Iterable[Any]" has no attribute',
|
||||
'"IO[Any]" has no attribute'
|
||||
],
|
||||
'file_storage': [
|
||||
'Incompatible types in assignment (expression has type "Callable"'
|
||||
],
|
||||
'files': [
|
||||
'Incompatible types in assignment (expression has type "IOBase", variable has type "File")',
|
||||
],
|
||||
'fixtures': [
|
||||
'Incompatible types in assignment (expression has type "int", target has type "Iterable[str]")',
|
||||
'Incompatible types in assignment (expression has type "SpyManager[Spy]"'
|
||||
],
|
||||
'from_db_value': [
|
||||
'"Cash" has no attribute'
|
||||
],
|
||||
'get_object_or_404': [
|
||||
'Argument 1 to "get_object_or_404" has incompatible type "str"; '
|
||||
+ 'expected "Union[Type[<nothing>], QuerySet[<nothing>, <nothing>]]"',
|
||||
'Argument 1 to "get_list_or_404" has incompatible type "List[Type[Article]]"; '
|
||||
+ 'expected "Union[Type[<nothing>], QuerySet[<nothing>, <nothing>]]"',
|
||||
'CustomClass'
|
||||
],
|
||||
'generic_relations_regress': [
|
||||
'"Link" has no attribute'
|
||||
],
|
||||
'httpwrappers': [
|
||||
'Argument 2 to "appendlist" of "QueryDict"',
|
||||
'Incompatible types in assignment (expression has type "int", target has type "Union[str, List[str]]")',
|
||||
'Argument 1 to "fromkeys" of "QueryDict" has incompatible type "int"'
|
||||
],
|
||||
'humanize_tests': [
|
||||
'Argument 1 to "append" of "list" has incompatible type "None"; expected "str"'
|
||||
],
|
||||
'lookup': [
|
||||
'Unexpected keyword argument "headline__startswith" for "in_bulk" of "QuerySet"',
|
||||
'is called with more than one field'
|
||||
],
|
||||
'messages_tests': [
|
||||
'List item 0 has incompatible type "Dict[str, Message]"; expected "Message"'
|
||||
],
|
||||
'middleware': [
|
||||
'"HttpRequest" has no attribute'
|
||||
],
|
||||
'managers_regress': [
|
||||
'"Type[AbstractBase3]" has no attribute "objects"'
|
||||
],
|
||||
'many_to_one': [
|
||||
'Incompatible type for "parent" of "Child" (got "None", expected "Union[Parent, Combinable]")',
|
||||
'Incompatible type for "parent" of "Child" (got "Child", expected "Union[Parent, Combinable]")'
|
||||
],
|
||||
'middleware_exceptions': [
|
||||
'Argument 1 to "append" of "list" has incompatible type "Tuple[Any, Any]"; expected "str"'
|
||||
],
|
||||
'model_fields': [
|
||||
'Item "Field[Any, Any]" of "Union[Field[Any, Any], ForeignObjectRel]" has no attribute',
|
||||
'has no attribute "field"',
|
||||
'Incompatible types in assignment (expression has type "Type[Person',
|
||||
'base class "IntegerFieldTests"',
|
||||
'ImageFieldTestMixin',
|
||||
'Incompatible types in assignment (expression has type "FloatModel", variable has type',
|
||||
],
|
||||
'model_indexes': [
|
||||
'Argument "condition" to "Index" has incompatible type "str"; expected "Optional[Q]"'
|
||||
],
|
||||
'model_inheritance': [
|
||||
'base class "AbstractBase" defined',
|
||||
'base class "AbstractModel" defined',
|
||||
'Definition of "name" in base class "ConcreteParent"',
|
||||
' Definition of "name" in base class "AbstractParent"',
|
||||
'referent_references'
|
||||
],
|
||||
'model_meta': [
|
||||
'List item 0 has incompatible type "str"; expected "Union[Field[Any, Any], ForeignObjectRel]"'
|
||||
],
|
||||
'model_regress': [
|
||||
'Incompatible type for "department" of "Worker"',
|
||||
'"PickledModel" has no attribute',
|
||||
'"Department" has no attribute "evaluate"',
|
||||
],
|
||||
'multiple_database': [
|
||||
'Unexpected attribute "extra_arg" for model "Book"'
|
||||
],
|
||||
'order_with_respect_to': [
|
||||
'BaseOrderWithRespectToTests',
|
||||
'"Dimension" has no attribute "set_component_order"',
|
||||
],
|
||||
'one_to_one': [
|
||||
'expression has type "None", variable has type "UndergroundBar"'
|
||||
],
|
||||
'postgres_tests': [
|
||||
'DummyArrayField',
|
||||
'DummyJSONField',
|
||||
'Incompatible types in assignment (expression has type "Type[Field[Any, Any]]',
|
||||
'Argument "encoder" to "JSONField" has incompatible type "DjangoJSONEncoder";',
|
||||
re.compile(r'Incompatible types in assignment \(expression has type "Type\[.+?\]", '
|
||||
r'base class "(UnaccentTest|TrigramTest)" defined the type as "Type\[CharFieldModel\]"\)'),
|
||||
'("None" and "SearchQuery")',
|
||||
# TODO:
|
||||
'django.contrib.postgres.forms',
|
||||
'django.contrib.postgres.aggregates',
|
||||
],
|
||||
'properties': [
|
||||
re.compile('Unexpected attribute "(full_name|full_name_2)" for model "Person"')
|
||||
],
|
||||
'prefetch_related': [
|
||||
'"Person" has no attribute "houses_lst"',
|
||||
'"Book" has no attribute "first_authors"',
|
||||
'"Book" has no attribute "the_authors"',
|
||||
'Incompatible types in assignment (expression has type "List[Room]", variable has type "QuerySet[Room, Room]")',
|
||||
'"Room" has no attribute "main_room_of_attr"',
|
||||
'"Room" has no attribute "house_attr"'
|
||||
],
|
||||
'proxy_models': [
|
||||
'Incompatible types in assignment',
|
||||
'in base class "User"'
|
||||
],
|
||||
'queries': [
|
||||
'Incompatible types in assignment (expression has type "None", variable has type "str")',
|
||||
'Invalid index type "Optional[str]" for "Dict[str, int]"; expected type "str"',
|
||||
'Unsupported operand types for & ("QuerySet[Author, Author]" and "QuerySet[Tag, Tag]")',
|
||||
'Unsupported operand types for | ("QuerySet[Author, Author]" and "QuerySet[Tag, Tag]")',
|
||||
'ObjectA',
|
||||
'ObjectB',
|
||||
'ObjectC',
|
||||
"'flat' and 'named' can't be used together",
|
||||
],
|
||||
'requests': [
|
||||
'Incompatible types in assignment (expression has type "Dict[str, str]", variable has type "QueryDict")'
|
||||
],
|
||||
'responses': [
|
||||
'Argument 1 to "TextIOWrapper" has incompatible type "HttpResponse"; expected "IO[bytes]"'
|
||||
],
|
||||
'settings_tests': [
|
||||
'Argument 1 to "Settings" has incompatible type "Optional[str]"; expected "str"'
|
||||
],
|
||||
'signals': [
|
||||
'Argument 1 to "append" of "list" has incompatible type "Tuple[Any, Any, Optional[Any], Any]";'
|
||||
],
|
||||
'syndication_tests': [
|
||||
'List or tuple expected as variable arguments'
|
||||
],
|
||||
'sessions_tests': [
|
||||
'base class "SessionTestsMixin" defined the type as "None")',
|
||||
'Incompatible types in assignment (expression has type "None", variable has type "int")',
|
||||
'"AbstractBaseSession" has no attribute'
|
||||
],
|
||||
'select_related_onetoone': [
|
||||
'Incompatible types in assignment (expression has type "Parent2", variable has type "Parent1")',
|
||||
'"Parent1" has no attribute'
|
||||
],
|
||||
'servers': [
|
||||
re.compile('Argument [0-9] to "WSGIRequestHandler"'),
|
||||
'"HTTPResponse" has no attribute',
|
||||
'"type" has no attribute',
|
||||
'"WSGIRequest" has no attribute "makefile"'
|
||||
],
|
||||
'serializers': [
|
||||
'"SerializersTestBase" defined the type as "None"',
|
||||
'"Model" has no attribute "data"',
|
||||
'"Iterable[Any]" has no attribute "content"',
|
||||
],
|
||||
'transactions': [
|
||||
'Incompatible types in assignment (expression has type "Thread", variable has type "Callable[[], Any]")'
|
||||
],
|
||||
'urlpatterns': [
|
||||
'"object" not callable'
|
||||
],
|
||||
'urlpatterns_reverse': [
|
||||
'List or tuple expected as variable arguments',
|
||||
'No overload variant of "zip" matches argument types "Any", "object"',
|
||||
'Argument 1 to "get_callable" has incompatible type "int"'
|
||||
],
|
||||
'utils_tests': [
|
||||
'Too few arguments for "__init__"',
|
||||
'Argument 1 to "activate" has incompatible type "None"; expected "Union[tzinfo, str]"',
|
||||
'Incompatible types in assignment (expression has type "None", base class "object" defined the type as',
|
||||
'Class',
|
||||
'has no attribute "cp"',
|
||||
'Argument "name" to "cached_property" has incompatible type "int"; expected "Optional[str]"',
|
||||
'has no attribute "sort"',
|
||||
'Unsupported target for indexed assignment',
|
||||
'defined the type as "None"',
|
||||
'Argument 1 to "Path" has incompatible type "Optional[str]"'
|
||||
],
|
||||
'view_tests': [
|
||||
"Module 'django.views.debug' has no attribute 'Path'"
|
||||
]
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
[mypy]
|
||||
strict_optional = True
|
||||
ignore_missing_imports = False
|
||||
ignore_missing_imports = True
|
||||
check_untyped_defs = True
|
||||
warn_no_return = False
|
||||
show_traceback = True
|
||||
@@ -9,3 +9,6 @@ incremental = True
|
||||
|
||||
plugins =
|
||||
mypy_django_plugin.main
|
||||
|
||||
[mypy.plugins.django-stubs]
|
||||
django_settings_module = 'django_tests_settings'
|
||||
@@ -1 +0,0 @@
|
||||
gitpython
|
||||
@@ -1,809 +1,23 @@
|
||||
import itertools
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
from typing import Pattern
|
||||
from re import Pattern
|
||||
|
||||
from git import Repo
|
||||
from mypy import build
|
||||
from mypy.main import process_options
|
||||
from scripts.enabled_test_modules import IGNORED_ERRORS, IGNORED_MODULES
|
||||
|
||||
PROJECT_DIRECTORY = Path(__file__).parent.parent
|
||||
|
||||
# Django branch to typecheck against
|
||||
DJANGO_BRANCH = 'stable/2.2.x'
|
||||
|
||||
# Specific commit in the Django repository to check against
|
||||
DJANGO_COMMIT_SHA = '395cf7c37514b642c4bcf30e01fc1a2c4f82b2fe'
|
||||
|
||||
# Some errors occur for the test suite itself, and cannot be addressed via django-stubs. They should be ignored
|
||||
# using this constant.
|
||||
MOCK_OBJECTS = ['MockRequest', 'MockCompiler', 'modelz', 'call_count', 'call_args_list', 'call_args', 'MockUser']
|
||||
IGNORED_ERRORS = {
|
||||
'__common__': [
|
||||
*MOCK_OBJECTS,
|
||||
'LazySettings',
|
||||
'NullTranslations',
|
||||
'Need type annotation for',
|
||||
'Invalid value for a to= parameter',
|
||||
'already defined (possibly by an import)',
|
||||
'already defined on line',
|
||||
'gets multiple values for keyword argument',
|
||||
'Cannot assign to a type',
|
||||
re.compile(r'Cannot assign to class variable "[a-z_]+" via instance'),
|
||||
# forms <-> models plugin support
|
||||
# '"Model" has no attribute',
|
||||
re.compile(r'Cannot determine type of \'(objects|stuff)\''),
|
||||
# settings
|
||||
re.compile(r'Module has no attribute "[A-Z_]+"'),
|
||||
# attributes assigned to test functions
|
||||
re.compile(
|
||||
r'"Callable\[(\[(Any(, )?)*((, )?VarArg\(Any\))?((, )?KwArg\(Any\))?\]|\.\.\.), Any\]" has no attribute'),
|
||||
# assign empty tuple
|
||||
re.compile(r'Incompatible types in assignment \(expression has type "Tuple\[\]", '
|
||||
r'variable has type "Tuple\[[A-Za-z, ]+\]"'),
|
||||
# assign method to a method
|
||||
'Cannot assign to a method',
|
||||
'Cannot infer type of lambda',
|
||||
re.compile(r'Incompatible types in assignment \(expression has type "Callable\[\[(Any(, )?)+\], Any\]", '
|
||||
r'variable has type "Callable\['),
|
||||
# cookies private attribute
|
||||
'full_clean" of "Model" does not return a value',
|
||||
# private members
|
||||
re.compile(r'has no attribute ("|\')_[a-zA-Z_]+("|\')'),
|
||||
'Invalid base class',
|
||||
'ValuesIterable',
|
||||
'Value of type "Optional[Dict[str, Any]]" is not indexable',
|
||||
'Argument 1 to "len" has incompatible type "Optional[List[_Record]]"; expected "Sized"',
|
||||
'Argument 1 to "loads" has incompatible type "Union[bytes, str, None]"; '
|
||||
+ 'expected "Union[str, bytes, bytearray]"',
|
||||
'Incompatible types in assignment (expression has type "None", variable has type Module)',
|
||||
'note:',
|
||||
'\'Settings\' object has no attribute',
|
||||
re.compile(r'"Type\[Model\]" has no attribute "[a-zA-Z_]+"'),
|
||||
re.compile(r'Item "None" of "[a-zA-Z_ ,\[\]]+" has no attribute'),
|
||||
'Xtemplate',
|
||||
re.compile(r'has no attribute "get_[a-z_]+_display"'),
|
||||
re.compile(r'has no attribute "get_next_by_[a-z_]+"'),
|
||||
re.compile(r'has no attribute "get_previous_by_[a-z_]+"'),
|
||||
re.compile(r'has no attribute "set_[a-z_]+_order"'),
|
||||
'psycopg2',
|
||||
'PIL',
|
||||
'has no attribute "getvalue"',
|
||||
'MySQLdb',
|
||||
'sqlparse',
|
||||
'selenium',
|
||||
'oracle',
|
||||
'mysql',
|
||||
'sqlite3',
|
||||
'LogEntry',
|
||||
'"HttpResponse" has no attribute',
|
||||
'"HttpResponseBase" has no attribute',
|
||||
'"object" has no attribute',
|
||||
'"HttpRequest" has no attribute',
|
||||
'xml.dom',
|
||||
'numpy',
|
||||
'tblib',
|
||||
'bcrypt',
|
||||
'argon2',
|
||||
# TODO: values().annotate()
|
||||
'TypedDict',
|
||||
'namedtuple',
|
||||
'has no attribute "deconstruct"',
|
||||
'**Dict',
|
||||
'undefined in superclass',
|
||||
'SimpleLazyObject'
|
||||
],
|
||||
'admin_scripts': [
|
||||
'Incompatible types in assignment (expression has type "Callable['
|
||||
],
|
||||
'admin_utils': [
|
||||
re.compile(r'Argument [0-9] to "lookup_field" has incompatible type'),
|
||||
'MockModelAdmin',
|
||||
'Incompatible types in assignment (expression has type "str", variable has type "Callable[..., Any]")',
|
||||
'"Article" has no attribute "non_field"'
|
||||
],
|
||||
'admin_views': [
|
||||
'Argument 1 to "FileWrapper" has incompatible type "StringIO"; expected "IO[bytes]"',
|
||||
'Incompatible types in assignment',
|
||||
'"object" not callable',
|
||||
'"Type[SubscriberAdmin]" has no attribute "overridden"'
|
||||
],
|
||||
'admin_ordering': [
|
||||
'"Band" has no attribute "field"'
|
||||
],
|
||||
'aggregation': [
|
||||
'Incompatible type for "contact" of "Book" (got "Optional[Author]", expected "Union[Author, Combinable]")',
|
||||
'Incompatible type for "publisher" of "Book" (got "Optional[Publisher]", '
|
||||
+ 'expected "Union[Publisher, Combinable]")',
|
||||
'has no attribute'
|
||||
],
|
||||
'aggregation_regress': [
|
||||
'has no attribute'
|
||||
],
|
||||
'annotations': [
|
||||
'Incompatible type for "store" of "Employee" (got "Optional[Store]", expected "Union[Store, Combinable]")',
|
||||
'"Book" has no attribute',
|
||||
'"Employee" has no attribute',
|
||||
'Item "Book" of',
|
||||
'Item "Ticket" of'
|
||||
],
|
||||
'apps': [
|
||||
'Incompatible types in assignment (expression has type "str", target has type "type")',
|
||||
'"Callable[[bool, bool], List[Type[Model]]]" has no attribute "cache_clear"'
|
||||
],
|
||||
'auth_tests': [
|
||||
'"PasswordValidator" has no attribute "min_length"',
|
||||
'"validate_password" does not return a value',
|
||||
'"password_changed" does not return a value',
|
||||
re.compile(r'"validate" of "([A-Za-z]+)" does not return a value'),
|
||||
'Module has no attribute "SessionStore"',
|
||||
'AbstractBaseUser',
|
||||
'Argument "user" to "password_changed" has incompatible type "object"',
|
||||
'Argument "password_validators" to "password_changed" has incompatible type "Tuple[Validator]"; '
|
||||
+ 'expected "Optional[Sequence[PasswordValidator]]"',
|
||||
'Value of type "Optional[List[_Record]]" is not indexable',
|
||||
'"Model" has no attribute',
|
||||
'Incompatible type for "id" of "User"',
|
||||
re.compile(r'Module has no attribute "(update|revert)_proxy_model_permissions"'),
|
||||
'Unsupported right operand type for in ("object")',
|
||||
'mock_getpass',
|
||||
'Unsupported left operand type for + ("Sequence[str]")',
|
||||
'AuthenticationFormWithInactiveUsersOkay',
|
||||
'has no attribute "alternatives"',
|
||||
'Incompatible types in assignment (expression has type "Dict[str, Any]", variable has type "QueryDict")'
|
||||
],
|
||||
'basic': [
|
||||
'Unexpected keyword argument "unknown_kwarg" for "refresh_from_db" of "Model"',
|
||||
'Unexpected attribute "foo" for model "Article"',
|
||||
'has no attribute'
|
||||
],
|
||||
'backends': [
|
||||
'"DatabaseError" has no attribute "pgcode"'
|
||||
],
|
||||
'check_framework': [
|
||||
'base class "Model" defined the type as "Callable',
|
||||
'Cannot determine type of \'check\''
|
||||
],
|
||||
'constraints': [
|
||||
'Argument "condition" to "UniqueConstraint" has incompatible type "str"; expected "Optional[Q]"'
|
||||
],
|
||||
'contenttypes_tests': [
|
||||
'Item "Model" of "Union[GenericForeignKey, Model, None]" has no attribute'
|
||||
],
|
||||
'custom_lookups': [
|
||||
'in base class "SQLFuncMixin"'
|
||||
],
|
||||
'custom_pk': [
|
||||
'"Employee" has no attribute "id"'
|
||||
],
|
||||
'custom_managers': [
|
||||
'"Type[Book]" has no attribute "objects"'
|
||||
],
|
||||
'csrf_tests': [
|
||||
'Incompatible types in assignment (expression has type "property", ' +
|
||||
'base class "HttpRequest" defined the type as "QueryDict")'
|
||||
],
|
||||
'dates': [
|
||||
'Too few arguments for "dates" of "QuerySet"',
|
||||
],
|
||||
'defer': [
|
||||
'Too many arguments for "refresh_from_db" of "Model"'
|
||||
],
|
||||
'dispatch': [
|
||||
'Argument 1 to "connect" of "Signal" has incompatible type "object"; expected "Callable[..., Any]"',
|
||||
'Item "str" of "Union[ValueError, str]" has no attribute "args"'
|
||||
],
|
||||
'deprecation': [
|
||||
'"Manager" has no attribute "old"',
|
||||
'"Manager" has no attribute "new"'
|
||||
],
|
||||
'db_functions': [
|
||||
'for **',
|
||||
'expected "float"',
|
||||
'Incompatible types in assignment (expression has type "Optional[FloatModel]", variable has type "FloatModel")',
|
||||
re.compile(r'Item .* has no attribute'),
|
||||
'Module has no attribute',
|
||||
'Module \'datetime\' has no attribute',
|
||||
'"DTModel" has no attribute',
|
||||
'"Author" has no attribute',
|
||||
'"FloatModel" has no attribute',
|
||||
'"Article" has no attribute'
|
||||
],
|
||||
'decorators': [
|
||||
'DummyRequest',
|
||||
'DummyUser',
|
||||
'"Type[object]" has no attribute "method"'
|
||||
],
|
||||
'defer_regress': [
|
||||
'"Base" has no attribute "derived"'
|
||||
],
|
||||
'delete': [
|
||||
'"RChild" has no attribute',
|
||||
'"Child" has no attribute "parent_ptr"'
|
||||
],
|
||||
'expressions': [
|
||||
'Item "Experiment" of',
|
||||
'Item "Time" of',
|
||||
'"Experiment" has no attribute',
|
||||
'"Time" has no attribute',
|
||||
],
|
||||
'expressions_case': [
|
||||
'"CaseTestModel" has no attribute "selected"'
|
||||
],
|
||||
'expressions_window': [
|
||||
'has incompatible type "str"'
|
||||
],
|
||||
'extra_regress': [
|
||||
'"User" has no attribute "alpha"'
|
||||
],
|
||||
'file_uploads': [
|
||||
'"Iterable[Any]" has no attribute',
|
||||
'"IO[Any]" has no attribute'
|
||||
],
|
||||
'file_storage': [
|
||||
'Incompatible types in assignment (expression has type "Callable[[], Any]"'
|
||||
],
|
||||
'files': [
|
||||
'"file_move_safe" does not return a value',
|
||||
'Incompatible types in assignment (expression has type "IOBase", variable has type "File")',
|
||||
'Module has no attribute "open"'
|
||||
],
|
||||
'fixtures': [
|
||||
'Incompatible types in assignment (expression has type "int", target has type "Iterable[str]")'
|
||||
],
|
||||
'flatpages_tests': [
|
||||
'"Site" has no attribute "add"',
|
||||
],
|
||||
'forms_tests': [
|
||||
'List item 0 has incompatible type "Jinja2"; expected "DjangoTemplates"',
|
||||
'Not enough arguments for format string',
|
||||
'Argument after ** must be a mapping, not "object"',
|
||||
'expression has type "None", base class "TestFormParent"',
|
||||
'variable has type "SongForm"',
|
||||
'"full_clean" of "BaseForm" does not return a value',
|
||||
'No overload variant of "zip" matches argument types "Tuple[str, str, str]", "object"',
|
||||
'Incompatible types in assignment (expression has type "GetDateShowHiddenInitial", '
|
||||
+ 'variable has type "GetDate")',
|
||||
re.compile(r'Incompatible types in assignment \(expression has type "[a-zA-Z]+Field", '
|
||||
r'base class "BaseForm" defined the type as "Dict\[str, Any\]"\)'),
|
||||
'List or tuple expected as variable arguments',
|
||||
'Argument 1 to "__init__" of "MultiWidget" has incompatible type "List[object]"; '
|
||||
+ 'expected "Sequence[Union[Widget, Type[Widget]]]"',
|
||||
'Argument 1 to "issubclass" has incompatible type "ModelFormMetaclass"; expected "type"',
|
||||
'Incompatible types in assignment (expression has type "List[str]", target has type "str")',
|
||||
'Incompatible types in assignment (expression has type "TestForm", variable has type "Person")',
|
||||
'Incompatible types in assignment (expression has type "Type[Textarea]", '
|
||||
+ 'base class "Field" defined the type as "Widget")',
|
||||
'Incompatible types in assignment (expression has type "SimpleUploadedFile", variable has type "BinaryIO")',
|
||||
'has no attribute',
|
||||
'Name \'forms.Field\' is not defined'
|
||||
],
|
||||
'foreign_object': [
|
||||
'"Person" has no attribute',
|
||||
'"SlugPage" has no attribute'
|
||||
],
|
||||
'from_db_value': [
|
||||
'"Cash" has no attribute'
|
||||
],
|
||||
'get_object_or_404': [
|
||||
'Argument 1 to "get_object_or_404" has incompatible type "str"; '
|
||||
+ 'expected "Union[Type[<nothing>], QuerySet[<nothing>, <nothing>]]"',
|
||||
'Argument 1 to "get_list_or_404" has incompatible type "List[Type[Article]]"; '
|
||||
+ 'expected "Union[Type[<nothing>], QuerySet[<nothing>, <nothing>]]"',
|
||||
'CustomClass'
|
||||
],
|
||||
'generic_relations': [
|
||||
'has no attribute "id"',
|
||||
'has no attribute "pk"'
|
||||
],
|
||||
'generic_relations_regress': [
|
||||
'"HasLinkThing" has no attribute',
|
||||
'"Link" has no attribute'
|
||||
],
|
||||
'httpwrappers': [
|
||||
'Argument 2 to "appendlist" of "QueryDict"',
|
||||
'Incompatible types in assignment (expression has type "int", target has type "Union[str, List[str]]")',
|
||||
'Argument 1 to "fromkeys" of "QueryDict" has incompatible type "int"'
|
||||
],
|
||||
'humanize_tests': [
|
||||
'Argument 1 to "append" of "list" has incompatible type "None"; expected "str"'
|
||||
],
|
||||
'inline_formsets': [
|
||||
'has no attribute "form"'
|
||||
],
|
||||
'i18n': [
|
||||
'Incompatible types in assignment (expression has type "I18nForm", variable has type "SelectDateForm")',
|
||||
'has incompatible type "object"',
|
||||
'Value of type "Optional[List[_Record]]" is not indexable',
|
||||
'"Command" has no attribute'
|
||||
],
|
||||
'logging_tests': [
|
||||
'"Handler" has no attribute "stream"'
|
||||
],
|
||||
'lookup': [
|
||||
'Unexpected keyword argument "headline__startswith" for "in_bulk" of "QuerySet"',
|
||||
'\'flat\' is not valid when values_list is called with more than one field.'
|
||||
],
|
||||
'm2o_recursive': [
|
||||
'Incompatible type for "id" of "Category" (got "None", expected "int")'
|
||||
],
|
||||
'many_to_one': [
|
||||
'Incompatible type for "parent" of "Child" (got "None", expected "Union[Parent, Combinable]")',
|
||||
'Incompatible type for "parent" of "Child" (got "Child", expected "Union[Parent, Combinable]")'
|
||||
],
|
||||
'managers_regress': [
|
||||
'"Type[AbstractBase3]" has no attribute "objects"'
|
||||
],
|
||||
'middleware_exceptions': [
|
||||
'Argument 1 to "append" of "list" has incompatible type "Tuple[Any, Any]"; expected "str"'
|
||||
],
|
||||
'model_fields': [
|
||||
'Incompatible types in assignment (expression has type "Type[Person]", variable has type',
|
||||
'Unexpected keyword argument "name" for "Person"',
|
||||
'Cannot assign multiple types to name "PersonTwoImages" without an explicit "Type[...]" annotation',
|
||||
re.compile(
|
||||
r'Incompatible types in assignment \(expression has type "Type\[.+?\]", base class "IntegerFieldTests"'
|
||||
r' defined the type as "Type\[IntegerModel\]"\)'),
|
||||
re.compile(r'Incompatible types in assignment \(expression has type "Type\[.+?\]", base class'
|
||||
r' "ImageFieldTestMixin" defined the type as "Type\[PersonWithHeightAndWidth\]"\)'),
|
||||
'Incompatible import of "Person"',
|
||||
'Incompatible types in assignment (expression has type "FloatModel", variable has type '
|
||||
'"Union[float, int, str, Combinable]")',
|
||||
'"UUIDGrandchild" has no attribute "uuidchild_ptr_id"',
|
||||
'"Person" has no attribute',
|
||||
'"Foo" has no attribute',
|
||||
],
|
||||
'model_formsets': [
|
||||
'has no attribute'
|
||||
],
|
||||
'model_indexes': [
|
||||
'Argument "condition" to "Index" has incompatible type "str"; expected "Optional[Q]"'
|
||||
],
|
||||
'model_inheritance_regress': [
|
||||
'"Restaurant" has no attribute',
|
||||
'"ArticleWithAuthor" has no attribute',
|
||||
'"Person" has no attribute',
|
||||
'"MessyBachelorParty" has no attribute',
|
||||
'"Place" has no attribute',
|
||||
'"ItalianRestaurant" has no attribute'
|
||||
],
|
||||
'model_meta': [
|
||||
'"Field[Any, Any]" has no attribute "many_to_many"'
|
||||
],
|
||||
'model_regress': [
|
||||
re.compile(r'Incompatible type for "[a-z]+" of "Worker" \(got "int", expected'),
|
||||
'"PickledModel" has no attribute',
|
||||
'"Department" has no attribute'
|
||||
],
|
||||
'modeladmin': [
|
||||
'BandAdmin',
|
||||
'base class "ModelAdmin" defined the type a',
|
||||
'base class "InlineModelAdmin" defined the type a',
|
||||
'List item 0 has incompatible type',
|
||||
'Incompatible types in assignment (expression has type "None", base class "AdminBase" '
|
||||
+ 'defined the type as "List[str]")'
|
||||
],
|
||||
'migrate_signals': [
|
||||
'Value of type "None" is not indexable',
|
||||
'Argument 1 to "set" has incompatible type "None"; expected "Iterable[<nothing>]"'
|
||||
],
|
||||
'migrations': [
|
||||
'FakeMigration',
|
||||
'FakeLoader',
|
||||
'Dict entry 0 has incompatible type "Any": "Set[Tuple[Any, ...]]"; expected "Any": "str"',
|
||||
'Argument 1 to "RunPython" has incompatible type "str"; expected "Callable[..., Any]"',
|
||||
'Argument 1 to "append" of "list" has incompatible type "AddIndex"; expected "CreateModel"',
|
||||
'Argument 2 to "register_serializer" of "MigrationWriter" has incompatible type '
|
||||
+ '"Type[TestModel1]"; expected "Type[BaseSerializer]"',
|
||||
'Argument 1 to "append" of "list" has incompatible type "AddConstraint"; expected "CreateModel"'
|
||||
],
|
||||
'multiple_database': [
|
||||
'Too many arguments for "create" of "QuerySet"',
|
||||
'"User" has no attribute "userprofile"',
|
||||
'Item "GenericForeignKey" of',
|
||||
'Item "Model" of'
|
||||
],
|
||||
'known_related_objects': [
|
||||
'"Pool" has no attribute'
|
||||
],
|
||||
'one_to_one': [
|
||||
'"Place" has no attribute',
|
||||
'"Type[Place]" has no attribute',
|
||||
'"ManualPrimaryKey" has no attribute'
|
||||
],
|
||||
'postgres_tests': [
|
||||
'DummyArrayField',
|
||||
'DummyJSONField',
|
||||
'Cannot assign multiple types to name',
|
||||
'Incompatible types in assignment (expression has type "Type[Field[Any, Any]]',
|
||||
'Argument "encoder" to "JSONField" has incompatible type "DjangoJSONEncoder"; '
|
||||
+ 'expected "Optional[Type[JSONEncoder]]"',
|
||||
'Incompatible type for "field" of "IntegerArrayModel" (got "None", '
|
||||
+ 'expected "Union[Sequence[int], Combinable]")',
|
||||
re.compile(r'Incompatible types in assignment \(expression has type "Type\[.+?\]", '
|
||||
r'base class "(UnaccentTest|TrigramTest)" defined the type as "Type\[CharFieldModel\]"\)'),
|
||||
'"Type[PostgreSQLModel]" has no attribute "objects"',
|
||||
'("None" and "SearchQuery")',
|
||||
# TODO:
|
||||
'django.contrib.postgres.forms',
|
||||
'django.contrib.postgres.aggregates',
|
||||
],
|
||||
'properties': [
|
||||
re.compile('Unexpected attribute "(full_name|full_name_2)" for model "Person"')
|
||||
],
|
||||
'prefetch_related': [
|
||||
'Incompatible types in assignment (expression has type "List[Room]", variable has type "QuerySet[Room, Room]")',
|
||||
'"Person" has no attribute',
|
||||
'"Author" has no attribute',
|
||||
'"Book" has no attribute',
|
||||
'Item "Room" of',
|
||||
'"AuthorWithAge" has no attribute',
|
||||
'has no attribute "read_by"'
|
||||
],
|
||||
'proxy_model_inheritance': [
|
||||
'Incompatible import of "ProxyModel"'
|
||||
],
|
||||
'queries': [
|
||||
'Incompatible types in assignment (expression has type "None", variable has type "str")',
|
||||
'Invalid index type "Optional[str]" for "Dict[str, int]"; expected type "str"',
|
||||
'No overload variant of "values_list" of "QuerySet" matches argument types "str", "bool", "bool"',
|
||||
'Unsupported operand types for & ("QuerySet[Author, Author]" and "QuerySet[Tag, Tag]")',
|
||||
'Unsupported operand types for | ("QuerySet[Author, Author]" and "QuerySet[Tag, Tag]")',
|
||||
'Incompatible types in assignment (expression has type "ObjectB", variable has type "ObjectA")',
|
||||
'Incompatible types in assignment (expression has type "ObjectC", variable has type "ObjectA")',
|
||||
'Incompatible type for "objectb" of "ObjectC" (got "ObjectA", expected'
|
||||
' "Union[ObjectB, Combinable, None, None]")',
|
||||
'"Note" has no attribute',
|
||||
'"Ranking" has no attribute',
|
||||
'"BaseUser" has no attribute',
|
||||
'"Item" has no attribute',
|
||||
"'flat' and 'named' can't be used together.",
|
||||
],
|
||||
'queryset_pickle': [
|
||||
'RelatedObjectDoesNotExist',
|
||||
'"Type[Event]" has no attribute "happening"'
|
||||
],
|
||||
'requests': [
|
||||
'Incompatible types in assignment (expression has type "Dict[str, str]", variable has type "QueryDict")'
|
||||
],
|
||||
'responses': [
|
||||
'Argument 1 to "TextIOWrapper" has incompatible type "HttpResponse"; expected "IO[bytes]"'
|
||||
],
|
||||
'schema': [
|
||||
'Incompatible type for "info" of "Note" (got "None", expected "Union[str, Combinable]")',
|
||||
'Incompatible type for "detail_info" of "NoteRename" (got "None", expected "Union[str, Combinable]")',
|
||||
'Incompatible type for "year" of "UniqueTest" (got "None", expected "Union[float, int, str, Combinable]")'
|
||||
],
|
||||
'settings_tests': [
|
||||
'Argument 1 to "Settings" has incompatible type "Optional[str]"; expected "str"'
|
||||
],
|
||||
'signals': [
|
||||
'Argument 1 to "append" of "list" has incompatible type "Tuple[Any, Any, Optional[Any], Any]"; '
|
||||
+ 'expected "Tuple[Any, Any, Any]"'
|
||||
],
|
||||
'sites_tests': [
|
||||
'Item "RequestSite" of "Union[Site, RequestSite]" has no attribute "id"'
|
||||
],
|
||||
'syndication_tests': [
|
||||
'List or tuple expected as variable arguments'
|
||||
],
|
||||
'sessions_tests': [
|
||||
'base class "SessionTestsMixin" defined the type as "None")',
|
||||
'Incompatible types in assignment (expression has type "None", variable has type "int")',
|
||||
'"AbstractBaseSession" has no attribute'
|
||||
],
|
||||
'select_related': [
|
||||
'"Species" has no attribute',
|
||||
'Item "object" of "Union[object, Any]" has no attribute "first"'
|
||||
],
|
||||
'select_related_onetoone': [
|
||||
'Incompatible types in assignment (expression has type "Parent2", variable has type "Parent1")',
|
||||
'has no attribute'
|
||||
],
|
||||
'select_for_update': [
|
||||
'has incompatible type "object"'
|
||||
],
|
||||
'servers': [
|
||||
re.compile('Argument [0-9] to "WSGIRequestHandler"'),
|
||||
'"HTTPResponse" has no attribute',
|
||||
'"type" has no attribute',
|
||||
'"WSGIRequest" has no attribute "makefile"'
|
||||
],
|
||||
'template_tests': [
|
||||
re.compile(r'Argument 1 to "[a-zA-Z_]+" has incompatible type "int"; expected "str"'),
|
||||
'TestObject',
|
||||
'variable has type "Callable[[Any], Any]',
|
||||
'Value of type variable "AnyStr" of "urljoin" cannot be "Optional[str]"',
|
||||
'has no attribute "template_debug"',
|
||||
"Module 'django.template.base' has no attribute 'TemplateSyntaxError'"
|
||||
],
|
||||
'template_backends': [
|
||||
'Incompatible import of "Jinja2" (imported name has type "Type[Jinja2]", local name has type "object")',
|
||||
'TemplateStringsTests',
|
||||
"Cannot find module named 'DoesNotExist'"
|
||||
],
|
||||
'test_client': [
|
||||
'Incompatible types in assignment (expression has type "HttpResponse", '
|
||||
+ 'variable has type "StreamingHttpResponse")'
|
||||
],
|
||||
'test_client_regress': [
|
||||
'Incompatible types in assignment (expression has type "Dict[<nothing>, <nothing>]", '
|
||||
+ 'variable has type "SessionBase")',
|
||||
'Unsupported left operand type for + ("None")',
|
||||
],
|
||||
'test_runner': [
|
||||
'Argument "result" to "run" of "TestCase" has incompatible type "RemoteTestResult"; '
|
||||
+ 'expected "Optional[TestResult]"',
|
||||
'has no attribute "id"',
|
||||
'MockTestRunner'
|
||||
],
|
||||
'transactions': [
|
||||
'Incompatible types in assignment (expression has type "Thread", variable has type "Callable[[], Any]")'
|
||||
],
|
||||
'urlpatterns': [
|
||||
'"object" not callable'
|
||||
],
|
||||
'user_commands': [
|
||||
'Incompatible types in assignment (expression has type "Callable[[Any, KwArg(Any)], Any]", variable has type',
|
||||
'Cannot find module named \'user_commands.management.commands\''
|
||||
],
|
||||
'utils_tests': [
|
||||
'a_package_name_that_does_not_exist',
|
||||
'Too few arguments for "__init__"',
|
||||
'Argument 1 to "activate" has incompatible type "None"; expected "Union[tzinfo, str]"',
|
||||
'Module has no attribute "content"',
|
||||
'Argument 1 to "int_to_base36" has incompatible type "object"; expected "int"',
|
||||
'Argument 1 to "base36_to_int" has incompatible type "object"; expected "str"',
|
||||
'Incompatible types in assignment (expression has type "None", base class "object" defined the type as',
|
||||
'Invalid type "Class"',
|
||||
'has no attribute "cp"',
|
||||
'Argument "name" to "cached_property" has incompatible type "int"; expected "Optional[str]"',
|
||||
'foo',
|
||||
'"ImmutableList[int]" has no attribute "sort"',
|
||||
'has no attribute "cache_clear"',
|
||||
'has no attribute "cache_info"',
|
||||
'Argument 1 to "Path" has incompatible type "Optional[str]"; expected "Union[str, _PathLike[str]]"',
|
||||
'defined the type as "None"'
|
||||
],
|
||||
'view_tests': [
|
||||
'"EmailMessage" has no attribute "alternatives"',
|
||||
'"Handler" has no attribute "include_html"',
|
||||
"Module 'django.views.debug' has no attribute 'Path'"
|
||||
]
|
||||
}
|
||||
# Test folders to typecheck
|
||||
TESTS_DIRS = [
|
||||
'absolute_url_overrides',
|
||||
'admin_autodiscover',
|
||||
'admin_changelist',
|
||||
'admin_checks',
|
||||
'admin_custom_urls',
|
||||
'admin_default_site',
|
||||
'admin_docs',
|
||||
# TODO: 'admin_filters',
|
||||
'admin_inlines',
|
||||
'admin_ordering',
|
||||
'admin_registration',
|
||||
'admin_scripts',
|
||||
'admin_utils',
|
||||
'admin_views',
|
||||
'admin_widgets',
|
||||
'aggregation',
|
||||
'aggregation_regress',
|
||||
'annotations',
|
||||
'app_loading',
|
||||
'apps',
|
||||
'auth_tests',
|
||||
'backends',
|
||||
'base',
|
||||
'bash_completion',
|
||||
'basic',
|
||||
'builtin_server',
|
||||
'bulk_create',
|
||||
# TODO: 'cache',
|
||||
'check_framework',
|
||||
'choices',
|
||||
'conditional_processing',
|
||||
'constraints',
|
||||
'contenttypes_tests',
|
||||
'context_processors',
|
||||
'csrf_tests',
|
||||
'custom_columns',
|
||||
'custom_lookups',
|
||||
'custom_managers',
|
||||
'custom_methods',
|
||||
'custom_migration_operations',
|
||||
'custom_pk',
|
||||
'datatypes',
|
||||
'dates',
|
||||
'datetimes',
|
||||
'db_functions',
|
||||
'db_typecasts',
|
||||
'db_utils',
|
||||
'dbshell',
|
||||
'decorators',
|
||||
'defer',
|
||||
'defer_regress',
|
||||
'delete',
|
||||
'delete_regress',
|
||||
'deprecation',
|
||||
'dispatch',
|
||||
'distinct_on_fields',
|
||||
'empty',
|
||||
'expressions',
|
||||
'expressions_case',
|
||||
'expressions_window',
|
||||
'extra_regress',
|
||||
'field_deconstruction',
|
||||
'field_defaults',
|
||||
'field_subclassing',
|
||||
'file_storage',
|
||||
'file_uploads',
|
||||
'files',
|
||||
'filtered_relation',
|
||||
'fixtures',
|
||||
'fixtures_model_package',
|
||||
'fixtures_regress',
|
||||
'flatpages_tests',
|
||||
'force_insert_update',
|
||||
'foreign_object',
|
||||
'forms_tests',
|
||||
'from_db_value',
|
||||
'generic_inline_admin',
|
||||
'generic_relations',
|
||||
'generic_relations_regress',
|
||||
# TODO: 'generic_views',
|
||||
'get_earliest_or_latest',
|
||||
'get_object_or_404',
|
||||
'get_or_create',
|
||||
# TODO: 'gis_tests',
|
||||
'handlers',
|
||||
'httpwrappers',
|
||||
'humanize_tests',
|
||||
'i18n',
|
||||
'import_error_package',
|
||||
'indexes',
|
||||
'inline_formsets',
|
||||
'inspectdb',
|
||||
'introspection',
|
||||
# not practical
|
||||
# 'invalid_models_tests',
|
||||
'known_related_objects',
|
||||
'logging_tests',
|
||||
'lookup',
|
||||
'm2m_and_m2o',
|
||||
'm2m_intermediary',
|
||||
'm2m_multiple',
|
||||
'm2m_recursive',
|
||||
'm2m_regress',
|
||||
'm2m_signals',
|
||||
'm2m_through',
|
||||
'm2m_through_regress',
|
||||
'm2o_recursive',
|
||||
# TODO: 'mail',
|
||||
'managers_regress',
|
||||
'many_to_many',
|
||||
'many_to_one',
|
||||
'many_to_one_null',
|
||||
'max_lengths',
|
||||
# TODO: 'messages_tests',
|
||||
'middleware',
|
||||
'middleware_exceptions',
|
||||
'migrate_signals',
|
||||
'migration_test_data_persistence',
|
||||
'migrations',
|
||||
'migrations2',
|
||||
'model_fields',
|
||||
# TODO: 'model_forms',
|
||||
'model_formsets',
|
||||
'model_formsets_regress',
|
||||
'model_indexes',
|
||||
# TODO: 'model_inheritance',
|
||||
'model_inheritance_regress',
|
||||
'model_meta',
|
||||
'model_options',
|
||||
'model_package',
|
||||
'model_regress',
|
||||
'modeladmin',
|
||||
'multiple_database',
|
||||
'mutually_referential',
|
||||
'nested_foreign_keys',
|
||||
'no_models',
|
||||
'null_fk',
|
||||
'null_fk_ordering',
|
||||
'null_queries',
|
||||
'one_to_one',
|
||||
'or_lookups',
|
||||
'order_with_respect_to',
|
||||
'ordering',
|
||||
'pagination',
|
||||
'postgres_tests',
|
||||
'prefetch_related',
|
||||
'project_template',
|
||||
'properties',
|
||||
'proxy_model_inheritance',
|
||||
# TODO: 'proxy_models',
|
||||
'queries',
|
||||
'queryset_pickle',
|
||||
'raw_query',
|
||||
'redirects_tests',
|
||||
'requests',
|
||||
'reserved_names',
|
||||
'resolve_url',
|
||||
'responses',
|
||||
'reverse_lookup',
|
||||
'save_delete_hooks',
|
||||
'schema',
|
||||
'select_for_update',
|
||||
'select_related',
|
||||
'select_related_onetoone',
|
||||
'select_related_regress',
|
||||
# TODO: 'serializers',
|
||||
'servers',
|
||||
'sessions_tests',
|
||||
'settings_tests',
|
||||
'shell',
|
||||
'shortcuts',
|
||||
'signals',
|
||||
'signed_cookies_tests',
|
||||
'signing',
|
||||
# TODO: 'sitemaps_tests',
|
||||
'sites_framework',
|
||||
'sites_tests',
|
||||
# TODO: 'staticfiles_tests',
|
||||
'str',
|
||||
'string_lookup',
|
||||
'swappable_models',
|
||||
'syndication_tests',
|
||||
'template_backends',
|
||||
'template_loader',
|
||||
'template_tests',
|
||||
'test_client',
|
||||
'test_client_regress',
|
||||
'test_exceptions',
|
||||
'test_runner',
|
||||
'test_runner_apps',
|
||||
'test_utils',
|
||||
'timezones',
|
||||
'transaction_hooks',
|
||||
'transactions',
|
||||
'unmanaged_models',
|
||||
'update',
|
||||
'update_only_fields',
|
||||
'urlpatterns',
|
||||
# not annotatable without annotation in test
|
||||
# 'urlpatterns_reverse',
|
||||
'user_commands',
|
||||
'utils_tests',
|
||||
'validation',
|
||||
'validators',
|
||||
'version',
|
||||
'view_tests',
|
||||
'wsgi',
|
||||
]
|
||||
|
||||
|
||||
@contextmanager
|
||||
def cd(path):
|
||||
"""Context manager to temporarily change working directories"""
|
||||
if not path:
|
||||
return
|
||||
prev_cwd = Path.cwd().as_posix()
|
||||
if isinstance(path, Path):
|
||||
path = path.as_posix()
|
||||
os.chdir(str(path))
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
os.chdir(prev_cwd)
|
||||
|
||||
|
||||
def is_ignored(line: str, test_folder_name: str) -> bool:
|
||||
for pattern in itertools.chain(IGNORED_ERRORS['__common__'],
|
||||
if 'runtests' in line:
|
||||
return True
|
||||
|
||||
if test_folder_name in IGNORED_MODULES:
|
||||
return True
|
||||
|
||||
for pattern in itertools.chain(IGNORED_ERRORS['__new_common__'],
|
||||
IGNORED_ERRORS.get(test_folder_name, [])):
|
||||
if isinstance(pattern, Pattern):
|
||||
if pattern.search(line):
|
||||
@@ -828,24 +42,6 @@ def replace_with_clickable_location(error: str, abs_test_folder: Path) -> str:
|
||||
return error.replace(raw_path, clickable_location)
|
||||
|
||||
|
||||
def check_with_mypy(abs_path: Path, config_file_path: Path) -> int:
|
||||
error_happened = False
|
||||
with cd(abs_path):
|
||||
sources, options = process_options(['--cache-dir', str(config_file_path.parent / '.mypy_cache'),
|
||||
'--config-file', str(config_file_path),
|
||||
str(abs_path)])
|
||||
res = build.build(sources, options)
|
||||
for error_line in res.errors:
|
||||
if not is_ignored(error_line, abs_path.name):
|
||||
error_happened = True
|
||||
print(replace_with_clickable_location(error_line, abs_test_folder=abs_path))
|
||||
return int(error_happened)
|
||||
|
||||
|
||||
def get_absolute_path_for_test(test_dirname: str):
|
||||
return (PROJECT_DIRECTORY / tests_root / test_dirname).absolute()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
mypy_config_file = (PROJECT_DIRECTORY / 'scripts' / 'mypy.ini').absolute()
|
||||
repo_directory = PROJECT_DIRECTORY / 'django-sources'
|
||||
@@ -853,28 +49,31 @@ if __name__ == '__main__':
|
||||
tests_root = repo_directory / 'tests'
|
||||
global_rc = 0
|
||||
|
||||
# clone Django repository, if it does not exist
|
||||
if not repo_directory.exists():
|
||||
repo = Repo.clone_from('https://github.com/django/django.git', repo_directory)
|
||||
else:
|
||||
repo = Repo(repo_directory)
|
||||
repo.remotes['origin'].pull(DJANGO_BRANCH)
|
||||
|
||||
repo.git.checkout(DJANGO_COMMIT_SHA)
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
tests_to_run = sys.argv[1:]
|
||||
else:
|
||||
tests_to_run = TESTS_DIRS
|
||||
# copy django settings to the tests_root directory
|
||||
shutil.copy(PROJECT_DIRECTORY / 'scripts' / 'django_tests_settings.py', tests_root)
|
||||
|
||||
try:
|
||||
for dirname in tests_to_run:
|
||||
abs_path = get_absolute_path_for_test(dirname)
|
||||
print(f'Checking {abs_path}')
|
||||
mypy_options = ['--cache-dir', str(mypy_config_file.parent / '.mypy_cache'),
|
||||
'--config-file', str(mypy_config_file)]
|
||||
mypy_options += [str(tests_root)]
|
||||
|
||||
rc = check_with_mypy(abs_path, mypy_config_file)
|
||||
if rc != 0:
|
||||
global_rc = 1
|
||||
import distutils.spawn
|
||||
|
||||
mypy_executable = distutils.spawn.find_executable('mypy')
|
||||
completed = subprocess.run([mypy_executable, *mypy_options], env={'PYTHONPATH': str(tests_root)},
|
||||
stdout=subprocess.PIPE, cwd=str(tests_root))
|
||||
sorted_lines = sorted(completed.stdout.decode().splitlines())
|
||||
for line in sorted_lines:
|
||||
try:
|
||||
module_name = line.split('/')[0]
|
||||
except IndexError:
|
||||
module_name = 'unknown'
|
||||
|
||||
if not is_ignored(line, module_name):
|
||||
if line.startswith(module_name):
|
||||
print(replace_with_clickable_location(line, abs_test_folder=tests_root))
|
||||
else:
|
||||
print(line)
|
||||
|
||||
sys.exit(global_rc)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user