mirror of
https://github.com/davidhalter/django-stubs.git
synced 2025-12-10 05:51:53 +08:00
Add Django 3.0 testing to CI (#246)
* add Django 3.0 testing to CI * remove importlib_metadata usage * conditionally load choices module for tests
This commit is contained in:
4
.gitmodules
vendored
4
.gitmodules
vendored
@@ -1,4 +0,0 @@
|
|||||||
[submodule "django-sources"]
|
|
||||||
path = django-sources
|
|
||||||
url = https://github.com/django/django.git
|
|
||||||
branch = stable/2.2.x
|
|
||||||
18
.travis.yml
18
.travis.yml
@@ -8,13 +8,23 @@ jobs:
|
|||||||
python: 3.7
|
python: 3.7
|
||||||
script: 'pytest'
|
script: 'pytest'
|
||||||
|
|
||||||
- name: Typecheck Django test suite with python 3.7
|
- name: Typecheck Django 3.0 test suite with python 3.7
|
||||||
python: 3.7
|
python: 3.7
|
||||||
script: 'python ./scripts/typecheck_tests.py'
|
script: |
|
||||||
|
pip install Django==3.0.*
|
||||||
|
python ./scripts/typecheck_tests.py --django_version=3.0
|
||||||
|
|
||||||
- name: Typecheck Django test suite with python 3.6
|
- name: Typecheck Django 3.0 test suite with python 3.6
|
||||||
python: 3.6
|
python: 3.6
|
||||||
script: 'python ./scripts/typecheck_tests.py'
|
script: |
|
||||||
|
pip install Django==3.0.*
|
||||||
|
python ./scripts/typecheck_tests.py --django_version=3.0
|
||||||
|
|
||||||
|
- name: Typecheck Django 2.2 test suite with python 3.7
|
||||||
|
python: 3.7
|
||||||
|
script: |
|
||||||
|
pip install Django==2.2.*
|
||||||
|
python ./scripts/typecheck_tests.py --django_version=2.2
|
||||||
|
|
||||||
- name: Mypy for plugin code
|
- name: Mypy for plugin code
|
||||||
python: 3.7
|
python: 3.7
|
||||||
|
|||||||
@@ -4,4 +4,5 @@ psycopg2
|
|||||||
flake8==3.7.8
|
flake8==3.7.8
|
||||||
flake8-pyi==19.3.0
|
flake8-pyi==19.3.0
|
||||||
isort==4.3.21
|
isort==4.3.21
|
||||||
|
gitpython==3.0.5
|
||||||
-e .
|
-e .
|
||||||
|
|||||||
Submodule django-sources deleted from 9a17ae50c6
@@ -129,3 +129,5 @@ from .constraints import (
|
|||||||
CheckConstraint as CheckConstraint,
|
CheckConstraint as CheckConstraint,
|
||||||
UniqueConstraint as UniqueConstraint,
|
UniqueConstraint as UniqueConstraint,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from .enums import Choices as Choices, IntegerChoices as IntegerChoices, TextChoices as TextChoices
|
||||||
|
|||||||
30
django-stubs/db/models/enums.pyi
Normal file
30
django-stubs/db/models/enums.pyi
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import enum
|
||||||
|
from typing import Any, List, Tuple
|
||||||
|
|
||||||
|
class ChoicesMeta(enum.EnumMeta):
|
||||||
|
names: List[str] = ...
|
||||||
|
choices: List[Tuple[Any, str]] = ...
|
||||||
|
labels: List[str] = ...
|
||||||
|
values: List[Any] = ...
|
||||||
|
def __contains__(self, item: Any) -> bool: ...
|
||||||
|
|
||||||
|
class Choices(enum.Enum, metaclass=ChoicesMeta):
|
||||||
|
def __str__(self): ...
|
||||||
|
|
||||||
|
# fake
|
||||||
|
class _IntegerChoicesMeta(ChoicesMeta):
|
||||||
|
names: List[str] = ...
|
||||||
|
choices: List[Tuple[int, str]] = ...
|
||||||
|
labels: List[str] = ...
|
||||||
|
values: List[int] = ...
|
||||||
|
|
||||||
|
class IntegerChoices(int, Choices, metaclass=_IntegerChoicesMeta): ...
|
||||||
|
|
||||||
|
# fake
|
||||||
|
class _TextChoicesMeta(ChoicesMeta):
|
||||||
|
names: List[str] = ...
|
||||||
|
choices: List[Tuple[str, str]] = ...
|
||||||
|
labels: List[str] = ...
|
||||||
|
values: List[str] = ...
|
||||||
|
|
||||||
|
class TextChoices(str, Choices, metaclass=_TextChoicesMeta): ...
|
||||||
@@ -108,7 +108,8 @@ class Field(RegisterLookupMixin, Generic[_ST, _GT]):
|
|||||||
def db_parameters(self, connection: Any) -> Dict[str, str]: ...
|
def db_parameters(self, connection: Any) -> Dict[str, str]: ...
|
||||||
def get_prep_value(self, value: Any) -> Any: ...
|
def get_prep_value(self, value: Any) -> Any: ...
|
||||||
def get_internal_type(self) -> str: ...
|
def get_internal_type(self) -> str: ...
|
||||||
def formfield(self, **kwargs) -> FormField: ...
|
# TODO: plugin support
|
||||||
|
def formfield(self, **kwargs) -> Any: ...
|
||||||
def save_form_data(self, instance: Model, data: Any) -> None: ...
|
def save_form_data(self, instance: Model, data: Any) -> None: ...
|
||||||
def contribute_to_class(self, cls: Type[Model], name: str, private_only: bool = ...) -> None: ...
|
def contribute_to_class(self, cls: Type[Model], name: str, private_only: bool = ...) -> None: ...
|
||||||
def to_python(self, value: Any) -> Any: ...
|
def to_python(self, value: Any) -> Any: ...
|
||||||
@@ -361,20 +362,20 @@ class UUIDField(Field[_ST, _GT]):
|
|||||||
_pyi_private_get_type: uuid.UUID
|
_pyi_private_get_type: uuid.UUID
|
||||||
|
|
||||||
class FilePathField(Field[_ST, _GT]):
|
class FilePathField(Field[_ST, _GT]):
|
||||||
path: str = ...
|
path: Any = ...
|
||||||
match: Optional[Any] = ...
|
match: Optional[str] = ...
|
||||||
recursive: bool = ...
|
recursive: bool = ...
|
||||||
allow_files: bool = ...
|
allow_files: bool = ...
|
||||||
allow_folders: bool = ...
|
allow_folders: bool = ...
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
verbose_name: Optional[Union[str, bytes]] = ...,
|
path: Union[str, Callable[..., str]] = ...,
|
||||||
name: Optional[str] = ...,
|
match: Optional[str] = ...,
|
||||||
path: str = ...,
|
|
||||||
match: Optional[Any] = ...,
|
|
||||||
recursive: bool = ...,
|
recursive: bool = ...,
|
||||||
allow_files: bool = ...,
|
allow_files: bool = ...,
|
||||||
allow_folders: bool = ...,
|
allow_folders: bool = ...,
|
||||||
|
verbose_name: Optional[str] = ...,
|
||||||
|
name: Optional[str] = ...,
|
||||||
primary_key: bool = ...,
|
primary_key: bool = ...,
|
||||||
max_length: int = ...,
|
max_length: int = ...,
|
||||||
unique: bool = ...,
|
unique: bool = ...,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
from pathlib import Path
|
||||||
from typing import Any, Callable, Iterable, List, Optional, Tuple, Type, TypeVar, Union, overload
|
from typing import Any, Callable, Iterable, List, Optional, Tuple, Type, TypeVar, Union, overload
|
||||||
|
|
||||||
from django.core.files.base import File
|
from django.core.files.base import File
|
||||||
@@ -39,11 +40,10 @@ class FileField(Field):
|
|||||||
upload_to: Union[str, Callable] = ...
|
upload_to: Union[str, Callable] = ...
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
upload_to: Union[str, Callable, Path] = ...,
|
||||||
|
storage: Optional[Storage] = ...,
|
||||||
verbose_name: Optional[Union[str, bytes]] = ...,
|
verbose_name: Optional[Union[str, bytes]] = ...,
|
||||||
name: Optional[str] = ...,
|
name: Optional[str] = ...,
|
||||||
upload_to: Union[str, Callable] = ...,
|
|
||||||
storage: Optional[Storage] = ...,
|
|
||||||
primary_key: bool = ...,
|
|
||||||
max_length: Optional[int] = ...,
|
max_length: Optional[int] = ...,
|
||||||
unique: bool = ...,
|
unique: bool = ...,
|
||||||
blank: bool = ...,
|
blank: bool = ...,
|
||||||
|
|||||||
@@ -108,6 +108,8 @@ class Options(Generic[_M]):
|
|||||||
def managers(self) -> List[Manager]: ...
|
def managers(self) -> List[Manager]: ...
|
||||||
@property
|
@property
|
||||||
def managers_map(self) -> Dict[str, Manager]: ...
|
def managers_map(self) -> Dict[str, Manager]: ...
|
||||||
|
@property
|
||||||
|
def db_returning_fields(self) -> List[Field]: ...
|
||||||
def get_field(self, field_name: Union[Callable, str]) -> Field: ...
|
def get_field(self, field_name: Union[Callable, str]) -> Field: ...
|
||||||
def get_base_chain(self, model: Type[Model]) -> List[Type[Model]]: ...
|
def get_base_chain(self, model: Type[Model]) -> List[Type[Model]]: ...
|
||||||
def get_parent_list(self) -> List[Type[Model]]: ...
|
def get_parent_list(self) -> List[Type[Model]]: ...
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ class Q(tree.Node):
|
|||||||
|
|
||||||
class DeferredAttribute:
|
class DeferredAttribute:
|
||||||
field_name: str = ...
|
field_name: str = ...
|
||||||
|
field: Field
|
||||||
def __init__(self, field_name: str) -> None: ...
|
def __init__(self, field_name: str) -> None: ...
|
||||||
|
|
||||||
class RegisterLookupMixin:
|
class RegisterLookupMixin:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import collections
|
import collections
|
||||||
from collections import OrderedDict, namedtuple
|
from collections import OrderedDict, namedtuple
|
||||||
from typing import Any, Callable, Dict, Iterator, List, Optional, Sequence, Set, Tuple, Type, Union
|
from typing import Any, Callable, Dict, Iterator, List, Optional, Sequence, Set, Tuple, Type, Union, Iterable
|
||||||
|
|
||||||
from django.db.models.lookups import Lookup, Transform
|
from django.db.models.lookups import Lookup, Transform
|
||||||
from django.db.models.query_utils import PathInfo, RegisterLookupMixin
|
from django.db.models.query_utils import PathInfo, RegisterLookupMixin
|
||||||
@@ -155,19 +155,19 @@ class Query:
|
|||||||
def add_ordering(self, *ordering: Any) -> None: ...
|
def add_ordering(self, *ordering: Any) -> None: ...
|
||||||
def clear_ordering(self, force_empty: bool) -> None: ...
|
def clear_ordering(self, force_empty: bool) -> None: ...
|
||||||
def set_group_by(self) -> None: ...
|
def set_group_by(self) -> None: ...
|
||||||
def add_select_related(self, fields: Tuple[str]) -> None: ...
|
def add_select_related(self, fields: Iterable[str]) -> None: ...
|
||||||
def add_extra(
|
def add_extra(
|
||||||
self,
|
self,
|
||||||
select: Optional[Union[Dict[str, int], Dict[str, str], OrderedDict]],
|
select: Optional[Dict[str, Any]],
|
||||||
select_params: Optional[Union[List[int], List[str], Tuple[int]]],
|
select_params: Optional[Iterable[Any]],
|
||||||
where: Optional[List[str]],
|
where: Optional[Sequence[str]],
|
||||||
params: Optional[List[str]],
|
params: Optional[Sequence[str]],
|
||||||
tables: Optional[List[str]],
|
tables: Optional[Sequence[str]],
|
||||||
order_by: Optional[Union[List[str], Tuple[str]]],
|
order_by: Optional[Sequence[str]],
|
||||||
) -> None: ...
|
) -> None: ...
|
||||||
def clear_deferred_loading(self) -> None: ...
|
def clear_deferred_loading(self) -> None: ...
|
||||||
def add_deferred_loading(self, field_names: Tuple[str]) -> None: ...
|
def add_deferred_loading(self, field_names: Iterable[str]) -> None: ...
|
||||||
def add_immediate_loading(self, field_names: Tuple[str]) -> None: ...
|
def add_immediate_loading(self, field_names: Iterable[str]) -> None: ...
|
||||||
def get_loaded_field_names(self) -> Dict[Type[Model], Set[str]]: ...
|
def get_loaded_field_names(self) -> Dict[Type[Model], Set[str]]: ...
|
||||||
def get_loaded_field_names_cb(
|
def get_loaded_field_names_cb(
|
||||||
self, target: Dict[Type[Model], Set[str]], model: Type[Model], fields: Set[Field]
|
self, target: Dict[Type[Model], Set[str]], model: Type[Model], fields: Set[Field]
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from os.path import abspath
|
from os.path import abspath
|
||||||
|
from pathlib import Path
|
||||||
from typing import Any, Union
|
from typing import Any, Union
|
||||||
|
|
||||||
abspathu = abspath
|
abspathu = abspath
|
||||||
@@ -7,3 +8,4 @@ def upath(path: Any): ...
|
|||||||
def npath(path: Any): ...
|
def npath(path: Any): ...
|
||||||
def safe_join(base: Union[bytes, str], *paths: Any) -> str: ...
|
def safe_join(base: Union[bytes, str], *paths: Any) -> str: ...
|
||||||
def symlinks_supported() -> Any: ...
|
def symlinks_supported() -> Any: ...
|
||||||
|
def to_path(value: Union[Path, str]) -> Path: ...
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from django.http.response import HttpResponse
|
|||||||
|
|
||||||
class RemovedInDjango30Warning(PendingDeprecationWarning): ...
|
class RemovedInDjango30Warning(PendingDeprecationWarning): ...
|
||||||
class RemovedInDjango31Warning(PendingDeprecationWarning): ...
|
class RemovedInDjango31Warning(PendingDeprecationWarning): ...
|
||||||
|
class RemovedInDjango40Warning(PendingDeprecationWarning): ...
|
||||||
class RemovedInNextVersionWarning(DeprecationWarning): ...
|
class RemovedInNextVersionWarning(DeprecationWarning): ...
|
||||||
|
|
||||||
class warn_about_renamed_method:
|
class warn_about_renamed_method:
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ def urlsafe_base64_decode(s: Union[bytes, str]) -> bytes: ...
|
|||||||
def parse_etags(etag_str: str) -> List[str]: ...
|
def parse_etags(etag_str: str) -> List[str]: ...
|
||||||
def quote_etag(etag_str: str) -> str: ...
|
def quote_etag(etag_str: str) -> str: ...
|
||||||
def is_same_domain(host: str, pattern: str) -> bool: ...
|
def is_same_domain(host: str, pattern: str) -> bool: ...
|
||||||
|
def url_has_allowed_host_and_scheme(
|
||||||
|
url: Optional[str], allowed_hosts: Optional[Union[str, Iterable[str]]], require_https: bool = ...
|
||||||
|
) -> bool: ...
|
||||||
def is_safe_url(
|
def is_safe_url(
|
||||||
url: Optional[str], allowed_hosts: Optional[Union[str, Iterable[str]]], require_https: bool = ...
|
url: Optional[str], allowed_hosts: Optional[Union[str, Iterable[str]]], require_https: bool = ...
|
||||||
) -> bool: ...
|
) -> bool: ...
|
||||||
|
|||||||
@@ -63,4 +63,4 @@ class ExceptionReporter:
|
|||||||
): ...
|
): ...
|
||||||
|
|
||||||
def technical_404_response(request: HttpRequest, exception: Http404) -> HttpResponse: ...
|
def technical_404_response(request: HttpRequest, exception: Http404) -> HttpResponse: ...
|
||||||
def default_urlconf(request: HttpRequest) -> HttpResponse: ...
|
def default_urlconf(request: Optional[HttpResponse]) -> HttpResponse: ...
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import django
|
||||||
|
|
||||||
SECRET_KEY = '1'
|
SECRET_KEY = '1'
|
||||||
SITE_ID = 1
|
SITE_ID = 1
|
||||||
|
|
||||||
@@ -41,7 +43,6 @@ test_modules = [
|
|||||||
'bulk_create',
|
'bulk_create',
|
||||||
'cache',
|
'cache',
|
||||||
'check_framework',
|
'check_framework',
|
||||||
'choices',
|
|
||||||
'conditional_processing',
|
'conditional_processing',
|
||||||
'constraints',
|
'constraints',
|
||||||
'contenttypes_tests',
|
'contenttypes_tests',
|
||||||
@@ -219,6 +220,9 @@ test_modules = [
|
|||||||
'wsgi',
|
'wsgi',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if django.VERSION[0] == 2:
|
||||||
|
test_modules += ['choices']
|
||||||
|
|
||||||
invalid_apps = {
|
invalid_apps = {
|
||||||
'import_error_package',
|
'import_error_package',
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -264,6 +264,8 @@ IGNORED_ERRORS = {
|
|||||||
'Incompatible types in assignment (expression has type "Type[Person',
|
'Incompatible types in assignment (expression has type "Type[Person',
|
||||||
'Incompatible types in assignment (expression has type "FloatModel", variable has type',
|
'Incompatible types in assignment (expression has type "FloatModel", variable has type',
|
||||||
'"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 "value" of "IntegerModel" (got "object", expected',
|
||||||
],
|
],
|
||||||
'model_indexes': [
|
'model_indexes': [
|
||||||
'Argument "condition" to "Index" has incompatible type "str"; expected "Optional[Q]"'
|
'Argument "condition" to "Index" has incompatible type "str"; expected "Optional[Q]"'
|
||||||
@@ -291,6 +293,9 @@ IGNORED_ERRORS = {
|
|||||||
'model_options': [
|
'model_options': [
|
||||||
'expression has type "Dict[str, Type[Model]]", target has type "OrderedDict',
|
'expression has type "Dict[str, Type[Model]]", target has type "OrderedDict',
|
||||||
],
|
],
|
||||||
|
'model_enums': [
|
||||||
|
"'bool' is not a valid base class",
|
||||||
|
],
|
||||||
'multiple_database': [
|
'multiple_database': [
|
||||||
'Unexpected attribute "extra_arg" for model "Book"'
|
'Unexpected attribute "extra_arg" for model "Book"'
|
||||||
],
|
],
|
||||||
@@ -341,12 +346,14 @@ IGNORED_ERRORS = {
|
|||||||
'"Collection[Any]" has no attribute "explain"',
|
'"Collection[Any]" has no attribute "explain"',
|
||||||
"Cannot resolve keyword 'unknown_field' into field",
|
"Cannot resolve keyword 'unknown_field' into field",
|
||||||
'Incompatible type for lookup \'tag\': (got "str", expected "Union[Tag, int, None]")',
|
'Incompatible type for lookup \'tag\': (got "str", expected "Union[Tag, int, None]")',
|
||||||
|
'No overload variant of "__getitem__" of "QuerySet" matches argument type "str"',
|
||||||
],
|
],
|
||||||
'requests': [
|
'requests': [
|
||||||
'Incompatible types in assignment (expression has type "Dict[str, str]", variable has type "QueryDict")'
|
'Incompatible types in assignment (expression has type "Dict[str, str]", variable has type "QueryDict")'
|
||||||
],
|
],
|
||||||
'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"',
|
||||||
],
|
],
|
||||||
'reverse_lookup': [
|
'reverse_lookup': [
|
||||||
"Cannot resolve keyword 'choice' into field"
|
"Cannot resolve keyword 'choice' into field"
|
||||||
@@ -424,6 +431,7 @@ IGNORED_ERRORS = {
|
|||||||
'"WSGIRequest" has no attribute "process_response_content"',
|
'"WSGIRequest" has no attribute "process_response_content"',
|
||||||
'No overload variant of "join" matches argument types "str", "None"',
|
'No overload variant of "join" matches argument types "str", "None"',
|
||||||
'Argument 1 to "Archive" has incompatible type "None"; expected "str"',
|
'Argument 1 to "Archive" has incompatible type "None"; expected "str"',
|
||||||
|
'Argument 1 to "to_path" has incompatible type "int"; expected "Union[Path, str]"',
|
||||||
|
|
||||||
],
|
],
|
||||||
'view_tests': [
|
'view_tests': [
|
||||||
@@ -431,10 +439,15 @@ IGNORED_ERRORS = {
|
|||||||
'Value of type "Optional[List[str]]" is not indexable',
|
'Value of type "Optional[List[str]]" is not indexable',
|
||||||
'ExceptionUser',
|
'ExceptionUser',
|
||||||
'view_tests.tests.test_debug.User',
|
'view_tests.tests.test_debug.User',
|
||||||
|
'Exception must be derived from BaseException',
|
||||||
|
"No binding for nonlocal 'tb_frames' found",
|
||||||
],
|
],
|
||||||
'validation': [
|
'validation': [
|
||||||
'has no attribute "name"',
|
'has no attribute "name"',
|
||||||
],
|
],
|
||||||
|
'wsgi': [
|
||||||
|
'"HttpResponse" has no attribute "block_size"',
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,15 +2,23 @@ import itertools
|
|||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
from argparse import ArgumentParser
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, List, Pattern, Union
|
from typing import Dict, List, Pattern, Union
|
||||||
|
|
||||||
|
from git import Repo
|
||||||
|
|
||||||
from scripts.enabled_test_modules import (
|
from scripts.enabled_test_modules import (
|
||||||
EXTERNAL_MODULES, IGNORED_ERRORS, IGNORED_MODULES, MOCK_OBJECTS,
|
EXTERNAL_MODULES, IGNORED_ERRORS, IGNORED_MODULES, MOCK_OBJECTS,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
DJANGO_COMMIT_REFS = {
|
||||||
|
'2.2': 'e8b0903976077b951795938b260211214ed7fe41',
|
||||||
|
'3.0': '7ec5962638144cbf4c2e47ea7d8dc02d1ce44394'
|
||||||
|
}
|
||||||
PROJECT_DIRECTORY = Path(__file__).parent.parent
|
PROJECT_DIRECTORY = Path(__file__).parent.parent
|
||||||
|
DJANGO_SOURCE_DIRECTORY = PROJECT_DIRECTORY / 'django-sources' # type: Path
|
||||||
|
|
||||||
|
|
||||||
def get_unused_ignores(ignored_message_freq: Dict[str, Dict[Union[str, Pattern], int]]) -> List[str]:
|
def get_unused_ignores(ignored_message_freq: Dict[str, Dict[Union[str, Pattern], int]]) -> List[str]:
|
||||||
@@ -67,11 +75,29 @@ def replace_with_clickable_location(error: str, abs_test_folder: Path) -> str:
|
|||||||
return error.replace(raw_path, clickable_location)
|
return error.replace(raw_path, clickable_location)
|
||||||
|
|
||||||
|
|
||||||
|
def get_django_repo_object() -> Repo:
|
||||||
|
if not DJANGO_SOURCE_DIRECTORY.exists():
|
||||||
|
DJANGO_SOURCE_DIRECTORY.mkdir(exist_ok=True, parents=False)
|
||||||
|
return Repo.clone_from('https://github.com/django/django.git', DJANGO_SOURCE_DIRECTORY)
|
||||||
|
else:
|
||||||
|
repo = Repo(DJANGO_SOURCE_DIRECTORY)
|
||||||
|
return repo
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
parser = ArgumentParser()
|
||||||
|
parser.add_argument('--django_version', choices=['2.2', '3.0'], required=True)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
commit_sha = DJANGO_COMMIT_REFS[args.django_version]
|
||||||
|
repo = get_django_repo_object()
|
||||||
|
if repo.head.commit.hexsha != commit_sha:
|
||||||
|
repo.git.fetch('origin')
|
||||||
|
repo.git.checkout(commit_sha)
|
||||||
|
|
||||||
mypy_config_file = (PROJECT_DIRECTORY / 'scripts' / 'mypy.ini').absolute()
|
mypy_config_file = (PROJECT_DIRECTORY / 'scripts' / 'mypy.ini').absolute()
|
||||||
repo_directory = PROJECT_DIRECTORY / 'django-sources'
|
|
||||||
mypy_cache_dir = Path(__file__).parent / '.mypy_cache'
|
mypy_cache_dir = Path(__file__).parent / '.mypy_cache'
|
||||||
tests_root = repo_directory / 'tests'
|
tests_root = DJANGO_SOURCE_DIRECTORY / 'tests'
|
||||||
global_rc = 0
|
global_rc = 0
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
Reference in New Issue
Block a user