Commit c16237d
authored
## Summary
This PR fixes #16302.
The PR reworks `Type::to_instance()` to return `Option<Type>` rather
than `Type`. This reflects more accurately the fact that some variants
cannot be "turned into an instance", since they _already_ represent
instances of some kind. On `main`, we silently fallback to `Unknown` for
these variants, but this implicit behaviour can be somewhat surprising
and lead to unexpected bugs.
Returning `Option<Type>` rather than `Type` means that each callsite has
to account for the possibility that the type might already represent an
instance, and decide what to do about it.
In general, I think this increases the robustness of the code. Working
on this PR revealed two latent bugs in the code:
- One which has already been fixed by
#16427
- One which is fixed as part of #16608
I added special handling to `KnownClass::to_instance()`: If we fail to find one of these classes and the `test` feature is
_not_ enabled, we log a warning to the terminal saying that we failed to
find the class in typeshed and that we will be falling back to
`Type::Unknown`. A cache is maintained so that we record all classes
that we have already logged a warning for; we only log a warning for
failing to lookup a `KnownClass` if we know that it's the first time
we're looking it up.
## Test Plan
- All existing tests pass
- I ran the property tests via `QUICKCHECK_TESTS=1000000 cargo test
--release -p red_knot_python_semantic -- --ignored
types::property_tests::stable`
I also manually checked that warnings are appropriately printed to the
terminal when `KnownClass::to_instance()` falls back to `Unknown` and
the `test` feature is not enabled. To do this, I applied this diff to
the PR branch:
<details>
<summary>Patch deleting `int` and `str` from buitins</summary>
```diff
diff --git a/crates/red_knot_vendored/vendor/typeshed/stdlib/builtins.pyi b/crates/red_knot_vendored/vendor/typeshed/stdlib/builtins.pyi
index 0a6dc57..86636a05b 100644
--- a/crates/red_knot_vendored/vendor/typeshed/stdlib/builtins.pyi
+++ b/crates/red_knot_vendored/vendor/typeshed/stdlib/builtins.pyi
@@ -228,111 +228,6 @@ _PositiveInteger: TypeAlias = Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
_NegativeInteger: TypeAlias = Literal[-1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17, -18, -19, -20]
_LiteralInteger = _PositiveInteger | _NegativeInteger | Literal[0] # noqa: Y026 # TODO: Use TypeAlias once mypy bugs are fixed
-class int:
- @overload
- def __new__(cls, x: ConvertibleToInt = ..., /) -> Self: ...
- @overload
- def __new__(cls, x: str | bytes | bytearray, /, base: SupportsIndex) -> Self: ...
- def as_integer_ratio(self) -> tuple[int, Literal[1]]: ...
- @Property
- def real(self) -> int: ...
- @Property
- def imag(self) -> Literal[0]: ...
- @Property
- def numerator(self) -> int: ...
- @Property
- def denominator(self) -> Literal[1]: ...
- def conjugate(self) -> int: ...
- def bit_length(self) -> int: ...
- if sys.version_info >= (3, 10):
- def bit_count(self) -> int: ...
-
- if sys.version_info >= (3, 11):
- def to_bytes(
- self, length: SupportsIndex = 1, byteorder: Literal["little", "big"] = "big", *, signed: bool = False
- ) -> bytes: ...
- @classmethod
- def from_bytes(
- cls,
- bytes: Iterable[SupportsIndex] | SupportsBytes | ReadableBuffer,
- byteorder: Literal["little", "big"] = "big",
- *,
- signed: bool = False,
- ) -> Self: ...
- else:
- def to_bytes(self, length: SupportsIndex, byteorder: Literal["little", "big"], *, signed: bool = False) -> bytes: ...
- @classmethod
- def from_bytes(
- cls,
- bytes: Iterable[SupportsIndex] | SupportsBytes | ReadableBuffer,
- byteorder: Literal["little", "big"],
- *,
- signed: bool = False,
- ) -> Self: ...
-
- if sys.version_info >= (3, 12):
- def is_integer(self) -> Literal[True]: ...
-
- def __add__(self, value: int, /) -> int: ...
- def __sub__(self, value: int, /) -> int: ...
- def __mul__(self, value: int, /) -> int: ...
- def __floordiv__(self, value: int, /) -> int: ...
- def __truediv__(self, value: int, /) -> float: ...
- def __mod__(self, value: int, /) -> int: ...
- def __divmod__(self, value: int, /) -> tuple[int, int]: ...
- def __radd__(self, value: int, /) -> int: ...
- def __rsub__(self, value: int, /) -> int: ...
- def __rmul__(self, value: int, /) -> int: ...
- def __rfloordiv__(self, value: int, /) -> int: ...
- def __rtruediv__(self, value: int, /) -> float: ...
- def __rmod__(self, value: int, /) -> int: ...
- def __rdivmod__(self, value: int, /) -> tuple[int, int]: ...
- @overload
- def __pow__(self, x: Literal[0], /) -> Literal[1]: ...
- @overload
- def __pow__(self, value: Literal[0], mod: None, /) -> Literal[1]: ...
- @overload
- def __pow__(self, value: _PositiveInteger, mod: None = None, /) -> int: ...
- @overload
- def __pow__(self, value: _NegativeInteger, mod: None = None, /) -> float: ...
- # positive __value -> int; negative __value -> float
- # return type must be Any as `int | float` causes too many false-positive errors
- @overload
- def __pow__(self, value: int, mod: None = None, /) -> Any: ...
- @overload
- def __pow__(self, value: int, mod: int, /) -> int: ...
- def __rpow__(self, value: int, mod: int | None = None, /) -> Any: ...
- def __and__(self, value: int, /) -> int: ...
- def __or__(self, value: int, /) -> int: ...
- def __xor__(self, value: int, /) -> int: ...
- def __lshift__(self, value: int, /) -> int: ...
- def __rshift__(self, value: int, /) -> int: ...
- def __rand__(self, value: int, /) -> int: ...
- def __ror__(self, value: int, /) -> int: ...
- def __rxor__(self, value: int, /) -> int: ...
- def __rlshift__(self, value: int, /) -> int: ...
- def __rrshift__(self, value: int, /) -> int: ...
- def __neg__(self) -> int: ...
- def __pos__(self) -> int: ...
- def __invert__(self) -> int: ...
- def __trunc__(self) -> int: ...
- def __ceil__(self) -> int: ...
- def __floor__(self) -> int: ...
- def __round__(self, ndigits: SupportsIndex = ..., /) -> int: ...
- def __getnewargs__(self) -> tuple[int]: ...
- def __eq__(self, value: object, /) -> bool: ...
- def __ne__(self, value: object, /) -> bool: ...
- def __lt__(self, value: int, /) -> bool: ...
- def __le__(self, value: int, /) -> bool: ...
- def __gt__(self, value: int, /) -> bool: ...
- def __ge__(self, value: int, /) -> bool: ...
- def __float__(self) -> float: ...
- def __int__(self) -> int: ...
- def __abs__(self) -> int: ...
- def __hash__(self) -> int: ...
- def __bool__(self) -> bool: ...
- def __index__(self) -> int: ...
-
class float:
def __new__(cls, x: ConvertibleToFloat = ..., /) -> Self: ...
def as_integer_ratio(self) -> tuple[int, int]: ...
@@ -437,190 +332,6 @@ class _FormatMapMapping(Protocol):
class _TranslateTable(Protocol):
def __getitem__(self, key: int, /) -> str | int | None: ...
-class str(Sequence[str]):
- @overload
- def __new__(cls, object: object = ...) -> Self: ...
- @overload
- def __new__(cls, object: ReadableBuffer, encoding: str = ..., errors: str = ...) -> Self: ...
- @overload
- def capitalize(self: LiteralString) -> LiteralString: ...
- @overload
- def capitalize(self) -> str: ... # type: ignore[misc]
- @overload
- def casefold(self: LiteralString) -> LiteralString: ...
- @overload
- def casefold(self) -> str: ... # type: ignore[misc]
- @overload
- def center(self: LiteralString, width: SupportsIndex, fillchar: LiteralString = " ", /) -> LiteralString: ...
- @overload
- def center(self, width: SupportsIndex, fillchar: str = " ", /) -> str: ... # type: ignore[misc]
- def count(self, sub: str, start: SupportsIndex | None = ..., end: SupportsIndex | None = ..., /) -> int: ...
- def encode(self, encoding: str = "utf-8", errors: str = "strict") -> bytes: ...
- def endswith(
- self, suffix: str | tuple[str, ...], start: SupportsIndex | None = ..., end: SupportsIndex | None = ..., /
- ) -> bool: ...
- @overload
- def expandtabs(self: LiteralString, tabsize: SupportsIndex = 8) -> LiteralString: ...
- @overload
- def expandtabs(self, tabsize: SupportsIndex = 8) -> str: ... # type: ignore[misc]
- def find(self, sub: str, start: SupportsIndex | None = ..., end: SupportsIndex | None = ..., /) -> int: ...
- @overload
- def format(self: LiteralString, *args: LiteralString, **kwargs: LiteralString) -> LiteralString: ...
- @overload
- def format(self, *args: object, **kwargs: object) -> str: ...
- def format_map(self, mapping: _FormatMapMapping, /) -> str: ...
- def index(self, sub: str, start: SupportsIndex | None = ..., end: SupportsIndex | None = ..., /) -> int: ...
- def isalnum(self) -> bool: ...
- def isalpha(self) -> bool: ...
- def isascii(self) -> bool: ...
- def isdecimal(self) -> bool: ...
- def isdigit(self) -> bool: ...
- def isidentifier(self) -> bool: ...
- def islower(self) -> bool: ...
- def isnumeric(self) -> bool: ...
- def isprintable(self) -> bool: ...
- def isspace(self) -> bool: ...
- def istitle(self) -> bool: ...
- def isupper(self) -> bool: ...
- @overload
- def join(self: LiteralString, iterable: Iterable[LiteralString], /) -> LiteralString: ...
- @overload
- def join(self, iterable: Iterable[str], /) -> str: ... # type: ignore[misc]
- @overload
- def ljust(self: LiteralString, width: SupportsIndex, fillchar: LiteralString = " ", /) -> LiteralString: ...
- @overload
- def ljust(self, width: SupportsIndex, fillchar: str = " ", /) -> str: ... # type: ignore[misc]
- @overload
- def lower(self: LiteralString) -> LiteralString: ...
- @overload
- def lower(self) -> str: ... # type: ignore[misc]
- @overload
- def lstrip(self: LiteralString, chars: LiteralString | None = None, /) -> LiteralString: ...
- @overload
- def lstrip(self, chars: str | None = None, /) -> str: ... # type: ignore[misc]
- @overload
- def partition(self: LiteralString, sep: LiteralString, /) -> tuple[LiteralString, LiteralString, LiteralString]: ...
- @overload
- def partition(self, sep: str, /) -> tuple[str, str, str]: ... # type: ignore[misc]
- if sys.version_info >= (3, 13):
- @overload
- def replace(
- self: LiteralString, old: LiteralString, new: LiteralString, /, count: SupportsIndex = -1
- ) -> LiteralString: ...
- @overload
- def replace(self, old: str, new: str, /, count: SupportsIndex = -1) -> str: ... # type: ignore[misc]
- else:
- @overload
- def replace(
- self: LiteralString, old: LiteralString, new: LiteralString, count: SupportsIndex = -1, /
- ) -> LiteralString: ...
- @overload
- def replace(self, old: str, new: str, count: SupportsIndex = -1, /) -> str: ... # type: ignore[misc]
- if sys.version_info >= (3, 9):
- @overload
- def removeprefix(self: LiteralString, prefix: LiteralString, /) -> LiteralString: ...
- @overload
- def removeprefix(self, prefix: str, /) -> str: ... # type: ignore[misc]
- @overload
- def removesuffix(self: LiteralString, suffix: LiteralString, /) -> LiteralString: ...
- @overload
- def removesuffix(self, suffix: str, /) -> str: ... # type: ignore[misc]
-
- def rfind(self, sub: str, start: SupportsIndex | None = ..., end: SupportsIndex | None = ..., /) -> int: ...
- def rindex(self, sub: str, start: SupportsIndex | None = ..., end: SupportsIndex | None = ..., /) -> int: ...
- @overload
- def rjust(self: LiteralString, width: SupportsIndex, fillchar: LiteralString = " ", /) -> LiteralString: ...
- @overload
- def rjust(self, width: SupportsIndex, fillchar: str = " ", /) -> str: ... # type: ignore[misc]
- @overload
- def rpartition(self: LiteralString, sep: LiteralString, /) -> tuple[LiteralString, LiteralString, LiteralString]: ...
- @overload
- def rpartition(self, sep: str, /) -> tuple[str, str, str]: ... # type: ignore[misc]
- @overload
- def rsplit(self: LiteralString, sep: LiteralString | None = None, maxsplit: SupportsIndex = -1) -> list[LiteralString]: ...
- @overload
- def rsplit(self, sep: str | None = None, maxsplit: SupportsIndex = -1) -> list[str]: ... # type: ignore[misc]
- @overload
- def rstrip(self: LiteralString, chars: LiteralString | None = None, /) -> LiteralString: ...
- @overload
- def rstrip(self, chars: str | None = None, /) -> str: ... # type: ignore[misc]
- @overload
- def split(self: LiteralString, sep: LiteralString | None = None, maxsplit: SupportsIndex = -1) -> list[LiteralString]: ...
- @overload
- def split(self, sep: str | None = None, maxsplit: SupportsIndex = -1) -> list[str]: ... # type: ignore[misc]
- @overload
- def splitlines(self: LiteralString, keepends: bool = False) -> list[LiteralString]: ...
- @overload
- def splitlines(self, keepends: bool = False) -> list[str]: ... # type: ignore[misc]
- def startswith(
- self, prefix: str | tuple[str, ...], start: SupportsIndex | None = ..., end: SupportsIndex | None = ..., /
- ) -> bool: ...
- @overload
- def strip(self: LiteralString, chars: LiteralString | None = None, /) -> LiteralString: ...
- @overload
- def strip(self, chars: str | None = None, /) -> str: ... # type: ignore[misc]
- @overload
- def swapcase(self: LiteralString) -> LiteralString: ...
- @overload
- def swapcase(self) -> str: ... # type: ignore[misc]
- @overload
- def title(self: LiteralString) -> LiteralString: ...
- @overload
- def title(self) -> str: ... # type: ignore[misc]
- def translate(self, table: _TranslateTable, /) -> str: ...
- @overload
- def upper(self: LiteralString) -> LiteralString: ...
- @overload
- def upper(self) -> str: ... # type: ignore[misc]
- @overload
- def zfill(self: LiteralString, width: SupportsIndex, /) -> LiteralString: ...
- @overload
- def zfill(self, width: SupportsIndex, /) -> str: ... # type: ignore[misc]
- @staticmethod
- @overload
- def maketrans(x: dict[int, _T] | dict[str, _T] | dict[str | int, _T], /) -> dict[int, _T]: ...
- @staticmethod
- @overload
- def maketrans(x: str, y: str, /) -> dict[int, int]: ...
- @staticmethod
- @overload
- def maketrans(x: str, y: str, z: str, /) -> dict[int, int | None]: ...
- @overload
- def __add__(self: LiteralString, value: LiteralString, /) -> LiteralString: ...
- @overload
- def __add__(self, value: str, /) -> str: ... # type: ignore[misc]
- # Incompatible with Sequence.__contains__
- def __contains__(self, key: str, /) -> bool: ... # type: ignore[override]
- def __eq__(self, value: object, /) -> bool: ...
- def __ge__(self, value: str, /) -> bool: ...
- @overload
- def __getitem__(self: LiteralString, key: SupportsIndex | slice, /) -> LiteralString: ...
- @overload
- def __getitem__(self, key: SupportsIndex | slice, /) -> str: ... # type: ignore[misc]
- def __gt__(self, value: str, /) -> bool: ...
- def __hash__(self) -> int: ...
- @overload
- def __iter__(self: LiteralString) -> Iterator[LiteralString]: ...
- @overload
- def __iter__(self) -> Iterator[str]: ... # type: ignore[misc]
- def __le__(self, value: str, /) -> bool: ...
- def __len__(self) -> int: ...
- def __lt__(self, value: str, /) -> bool: ...
- @overload
- def __mod__(self: LiteralString, value: LiteralString | tuple[LiteralString, ...], /) -> LiteralString: ...
- @overload
- def __mod__(self, value: Any, /) -> str: ...
- @overload
- def __mul__(self: LiteralString, value: SupportsIndex, /) -> LiteralString: ...
- @overload
- def __mul__(self, value: SupportsIndex, /) -> str: ... # type: ignore[misc]
- def __ne__(self, value: object, /) -> bool: ...
- @overload
- def __rmul__(self: LiteralString, value: SupportsIndex, /) -> LiteralString: ...
- @overload
- def __rmul__(self, value: SupportsIndex, /) -> str: ... # type: ignore[misc]
- def __getnewargs__(self) -> tuple[str]: ...
-
class bytes(Sequence[int]):
```
</details>
And then ran red-knot on my
[typeshed-stats](https://github.com/AlexWaygood/typeshed-stats) project
using the command
```
cargo run -p red_knot -- check --project ../typeshed-stats --python-version="3.12" --verbose
```
I observed that the following logs were printed to the terminal, but
that each warning was only printed once (the desired behaviour):
```
INFO Python version: Python 3.12, platform: all
INFO Indexed 15 file(s)
INFO Could not find class `builtins.int` in typeshed on Python 3.12. Falling back to `Unknown` for the symbol instead.
INFO Could not find class `builtins.str` in typeshed on Python 3.12. Falling back to `Unknown` for the symbol instead.
```
1 parent 989075d commit c16237d
File tree
7 files changed
+245
-80
lines changed- crates/red_knot_python_semantic/src
- module_resolver
- types
7 files changed
+245
-80
lines changedLines changed: 8 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
134 | 134 | | |
135 | 135 | | |
136 | 136 | | |
137 | | - | |
138 | | - | |
139 | | - | |
| 137 | + | |
| 138 | + | |
140 | 139 | | |
141 | 140 | | |
142 | 141 | | |
| |||
167 | 166 | | |
168 | 167 | | |
169 | 168 | | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
170 | 175 | | |
171 | 176 | | |
172 | 177 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
730 | 730 | | |
731 | 731 | | |
732 | 732 | | |
733 | | - | |
734 | | - | |
735 | | - | |
736 | | - | |
| 733 | + | |
| 734 | + | |
| 735 | + | |
737 | 736 | | |
738 | 737 | | |
739 | 738 | | |
| |||
745 | 744 | | |
746 | 745 | | |
747 | 746 | | |
748 | | - | |
749 | | - | |
750 | | - | |
751 | | - | |
752 | | - | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
753 | 750 | | |
754 | 751 | | |
755 | 752 | | |
| |||
1122 | 1119 | | |
1123 | 1120 | | |
1124 | 1121 | | |
| 1122 | + | |
| 1123 | + | |
1125 | 1124 | | |
1126 | | - | |
1127 | | - | |
1128 | | - | |
1129 | | - | |
1130 | | - | |
1131 | | - | |
1132 | | - | |
1133 | | - | |
1134 | | - | |
| 1125 | + | |
| 1126 | + | |
| 1127 | + | |
| 1128 | + | |
| 1129 | + | |
| 1130 | + | |
| 1131 | + | |
| 1132 | + | |
1135 | 1133 | | |
1136 | 1134 | | |
1137 | 1135 | | |
| |||
1200 | 1198 | | |
1201 | 1199 | | |
1202 | 1200 | | |
1203 | | - | |
1204 | | - | |
| 1201 | + | |
1205 | 1202 | | |
1206 | 1203 | | |
1207 | 1204 | | |
| |||
2106 | 2103 | | |
2107 | 2104 | | |
2108 | 2105 | | |
2109 | | - | |
2110 | | - | |
2111 | | - | |
2112 | | - | |
2113 | | - | |
2114 | | - | |
| 2106 | + | |
| 2107 | + | |
| 2108 | + | |
2115 | 2109 | | |
2116 | 2110 | | |
2117 | 2111 | | |
2118 | | - | |
2119 | | - | |
2120 | | - | |
2121 | | - | |
| 2112 | + | |
2122 | 2113 | | |
2123 | 2114 | | |
2124 | 2115 | | |
| |||
2948 | 2939 | | |
2949 | 2940 | | |
2950 | 2941 | | |
2951 | | - | |
| 2942 | + | |
2952 | 2943 | | |
2953 | | - | |
2954 | | - | |
2955 | | - | |
2956 | | - | |
2957 | | - | |
2958 | | - | |
2959 | | - | |
2960 | | - | |
2961 | | - | |
2962 | | - | |
2963 | | - | |
| 2944 | + | |
| 2945 | + | |
| 2946 | + | |
| 2947 | + | |
| 2948 | + | |
| 2949 | + | |
| 2950 | + | |
| 2951 | + | |
| 2952 | + | |
| 2953 | + | |
| 2954 | + | |
2964 | 2955 | | |
2965 | 2956 | | |
2966 | 2957 | | |
| |||
2974 | 2965 | | |
2975 | 2966 | | |
2976 | 2967 | | |
2977 | | - | |
| 2968 | + | |
2978 | 2969 | | |
2979 | 2970 | | |
2980 | 2971 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
1 | 3 | | |
2 | 4 | | |
3 | 5 | | |
| |||
18 | 20 | | |
19 | 21 | | |
20 | 22 | | |
| 23 | + | |
21 | 24 | | |
22 | 25 | | |
23 | 26 | | |
| |||
185 | 188 | | |
186 | 189 | | |
187 | 190 | | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
188 | 199 | | |
189 | 200 | | |
190 | 201 | | |
| |||
879 | 890 | | |
880 | 891 | | |
881 | 892 | | |
882 | | - | |
| 893 | + | |
883 | 894 | | |
884 | 895 | | |
885 | 896 | | |
| |||
937 | 948 | | |
938 | 949 | | |
939 | 950 | | |
| 951 | + | |
| 952 | + | |
| 953 | + | |
| 954 | + | |
| 955 | + | |
| 956 | + | |
| 957 | + | |
| 958 | + | |
| 959 | + | |
| 960 | + | |
| 961 | + | |
| 962 | + | |
| 963 | + | |
| 964 | + | |
| 965 | + | |
| 966 | + | |
| 967 | + | |
| 968 | + | |
| 969 | + | |
| 970 | + | |
| 971 | + | |
| 972 | + | |
| 973 | + | |
| 974 | + | |
| 975 | + | |
| 976 | + | |
| 977 | + | |
| 978 | + | |
940 | 979 | | |
941 | | - | |
| 980 | + | |
| 981 | + | |
| 982 | + | |
| 983 | + | |
942 | 984 | | |
943 | 985 | | |
| 986 | + | |
| 987 | + | |
| 988 | + | |
| 989 | + | |
| 990 | + | |
| 991 | + | |
| 992 | + | |
| 993 | + | |
| 994 | + | |
| 995 | + | |
| 996 | + | |
| 997 | + | |
| 998 | + | |
| 999 | + | |
| 1000 | + | |
| 1001 | + | |
| 1002 | + | |
| 1003 | + | |
| 1004 | + | |
| 1005 | + | |
| 1006 | + | |
| 1007 | + | |
| 1008 | + | |
| 1009 | + | |
944 | 1010 | | |
945 | | - | |
946 | | - | |
947 | | - | |
948 | | - | |
| 1011 | + | |
| 1012 | + | |
| 1013 | + | |
| 1014 | + | |
| 1015 | + | |
| 1016 | + | |
| 1017 | + | |
| 1018 | + | |
| 1019 | + | |
| 1020 | + | |
| 1021 | + | |
| 1022 | + | |
| 1023 | + | |
| 1024 | + | |
| 1025 | + | |
| 1026 | + | |
| 1027 | + | |
| 1028 | + | |
| 1029 | + | |
| 1030 | + | |
| 1031 | + | |
| 1032 | + | |
| 1033 | + | |
| 1034 | + | |
| 1035 | + | |
| 1036 | + | |
| 1037 | + | |
| 1038 | + | |
| 1039 | + | |
949 | 1040 | | |
950 | 1041 | | |
| 1042 | + | |
| 1043 | + | |
| 1044 | + | |
| 1045 | + | |
951 | 1046 | | |
952 | 1047 | | |
953 | 1048 | | |
| |||
958 | 1053 | | |
959 | 1054 | | |
960 | 1055 | | |
961 | | - | |
962 | | - | |
963 | | - | |
964 | | - | |
965 | | - | |
| 1056 | + | |
| 1057 | + | |
966 | 1058 | | |
967 | 1059 | | |
968 | 1060 | | |
| |||
1227 | 1319 | | |
1228 | 1320 | | |
1229 | 1321 | | |
| 1322 | + | |
| 1323 | + | |
| 1324 | + | |
| 1325 | + | |
| 1326 | + | |
| 1327 | + | |
| 1328 | + | |
| 1329 | + | |
| 1330 | + | |
| 1331 | + | |
| 1332 | + | |
| 1333 | + | |
| 1334 | + | |
| 1335 | + | |
| 1336 | + | |
| 1337 | + | |
| 1338 | + | |
| 1339 | + | |
| 1340 | + | |
| 1341 | + | |
| 1342 | + | |
| 1343 | + | |
| 1344 | + | |
| 1345 | + | |
| 1346 | + | |
| 1347 | + | |
| 1348 | + | |
| 1349 | + | |
| 1350 | + | |
| 1351 | + | |
| 1352 | + | |
| 1353 | + | |
| 1354 | + | |
| 1355 | + | |
| 1356 | + | |
| 1357 | + | |
| 1358 | + | |
| 1359 | + | |
| 1360 | + | |
| 1361 | + | |
| 1362 | + | |
| 1363 | + | |
| 1364 | + | |
| 1365 | + | |
| 1366 | + | |
| 1367 | + | |
| 1368 | + | |
| 1369 | + | |
| 1370 | + | |
| 1371 | + | |
| 1372 | + | |
| 1373 | + | |
| 1374 | + | |
| 1375 | + | |
| 1376 | + | |
| 1377 | + | |
1230 | 1378 | | |
1231 | 1379 | | |
1232 | 1380 | | |
| |||
1609 | 1757 | | |
1610 | 1758 | | |
1611 | 1759 | | |
1612 | | - | |
| 1760 | + | |
1613 | 1761 | | |
1614 | 1762 | | |
1615 | 1763 | | |
| |||
0 commit comments