Skip to content

Commit 130339f

Browse files
authored
[red-knot] Fix str(…) calls (#17163)
## Summary The existing signature for `str` calls had various problems, one of which I noticed while looking at some ecosystem projects (`scrapy`, added as a project to mypy_primer in this PR). ## Test Plan - New tests for `str(…)` calls. - Observed reduction of false positives in ecosystem checks
1 parent e50fc04 commit 130339f

File tree

4 files changed

+68
-11
lines changed

4 files changed

+68
-11
lines changed

.github/workflows/mypy_primer.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ jobs:
6868
--type-checker knot \
6969
--old base_commit \
7070
--new "$GITHUB_SHA" \
71-
--project-selector '/(mypy_primer|black|pyp|git-revise|zipp|arrow|isort|itsdangerous|rich|packaging|pybind11|pyinstrument|typeshed-stats)$' \
71+
--project-selector '/(mypy_primer|black|pyp|git-revise|zipp|arrow|isort|itsdangerous|rich|packaging|pybind11|pyinstrument|typeshed-stats|scrapy)$' \
7272
--output concise \
7373
--debug > mypy_primer.diff || [ $? -eq 1 ]
7474

crates/red_knot_python_semantic/resources/mdtest/call/builtins.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,42 @@ type("Foo", ())
3838
# error: [no-matching-overload] "No overload of class `type` matches arguments"
3939
type("Foo", (), {}, weird_other_arg=42)
4040
```
41+
42+
## Calls to `str()`
43+
44+
### Valid calls
45+
46+
```py
47+
str()
48+
str("")
49+
str(b"")
50+
str(1)
51+
str(object=1)
52+
53+
str(b"M\xc3\xbcsli", "utf-8")
54+
str(b"M\xc3\xbcsli", "utf-8", "replace")
55+
56+
str(b"M\x00\xfc\x00s\x00l\x00i\x00", encoding="utf-16")
57+
str(b"M\x00\xfc\x00s\x00l\x00i\x00", encoding="utf-16", errors="ignore")
58+
59+
str(bytearray.fromhex("4d c3 bc 73 6c 69"), "utf-8")
60+
str(bytearray(), "utf-8")
61+
62+
str(encoding="utf-8", object=b"M\xc3\xbcsli")
63+
str(b"", errors="replace")
64+
str(encoding="utf-8")
65+
str(errors="replace")
66+
```
67+
68+
### Invalid calls
69+
70+
```py
71+
str(1, 2) # error: [no-matching-overload]
72+
str(o=1) # error: [no-matching-overload]
73+
74+
# First argument is not a bytes-like object:
75+
str("Müsli", "utf-8") # error: [no-matching-overload]
76+
77+
# Second argument is not a valid encoding:
78+
str(b"M\xc3\xbcsli", b"utf-8") # error: [no-matching-overload]
79+
```

crates/red_knot_python_semantic/src/types.rs

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2850,21 +2850,31 @@ impl<'db> Type<'db> {
28502850
self,
28512851
[
28522852
Signature::new(
2853-
Parameters::new([Parameter::positional_only(Some(
2854-
Name::new_static("o"),
2855-
))
2856-
.with_annotated_type(Type::any())
2853+
Parameters::new([Parameter::positional_or_keyword(
2854+
Name::new_static("object"),
2855+
)
2856+
.with_annotated_type(Type::object(db))
28572857
.with_default_type(Type::string_literal(db, ""))]),
28582858
Some(KnownClass::Str.to_instance(db)),
28592859
),
28602860
Signature::new(
28612861
Parameters::new([
2862-
Parameter::positional_only(Some(Name::new_static("o")))
2863-
.with_annotated_type(Type::any()), // TODO: ReadableBuffer
2864-
Parameter::positional_only(Some(Name::new_static("encoding")))
2865-
.with_annotated_type(KnownClass::Str.to_instance(db)),
2866-
Parameter::positional_only(Some(Name::new_static("errors")))
2867-
.with_annotated_type(KnownClass::Str.to_instance(db)),
2862+
Parameter::positional_or_keyword(Name::new_static("object"))
2863+
// TODO: Should be `ReadableBuffer` instead of this union type:
2864+
.with_annotated_type(UnionType::from_elements(
2865+
db,
2866+
[
2867+
KnownClass::Bytes.to_instance(db),
2868+
KnownClass::Bytearray.to_instance(db),
2869+
],
2870+
))
2871+
.with_default_type(Type::bytes_literal(db, b"")),
2872+
Parameter::positional_or_keyword(Name::new_static("encoding"))
2873+
.with_annotated_type(KnownClass::Str.to_instance(db))
2874+
.with_default_type(Type::string_literal(db, "utf-8")),
2875+
Parameter::positional_or_keyword(Name::new_static("errors"))
2876+
.with_annotated_type(KnownClass::Str.to_instance(db))
2877+
.with_default_type(Type::string_literal(db, "strict")),
28682878
]),
28692879
Some(KnownClass::Str.to_instance(db)),
28702880
),

crates/red_knot_python_semantic/src/types/class.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,7 @@ pub enum KnownClass {
820820
Bool,
821821
Object,
822822
Bytes,
823+
Bytearray,
823824
Type,
824825
Int,
825826
Float,
@@ -930,6 +931,7 @@ impl<'db> KnownClass {
930931
| Self::Int
931932
| Self::Type
932933
| Self::Bytes
934+
| Self::Bytearray
933935
| Self::FrozenSet
934936
| Self::Range
935937
| Self::Property
@@ -959,6 +961,7 @@ impl<'db> KnownClass {
959961
Self::Bool => "bool",
960962
Self::Object => "object",
961963
Self::Bytes => "bytes",
964+
Self::Bytearray => "bytearray",
962965
Self::Tuple => "tuple",
963966
Self::Int => "int",
964967
Self::Float => "float",
@@ -1136,6 +1139,7 @@ impl<'db> KnownClass {
11361139
Self::Bool
11371140
| Self::Object
11381141
| Self::Bytes
1142+
| Self::Bytearray
11391143
| Self::Type
11401144
| Self::Int
11411145
| Self::Float
@@ -1218,6 +1222,7 @@ impl<'db> KnownClass {
12181222
| Self::Bool
12191223
| Self::Object
12201224
| Self::Bytes
1225+
| Self::Bytearray
12211226
| Self::Type
12221227
| Self::Int
12231228
| Self::Float
@@ -1276,6 +1281,7 @@ impl<'db> KnownClass {
12761281
| Self::Bool
12771282
| Self::Object
12781283
| Self::Bytes
1284+
| Self::Bytearray
12791285
| Self::Tuple
12801286
| Self::Int
12811287
| Self::Float
@@ -1330,6 +1336,7 @@ impl<'db> KnownClass {
13301336
"bool" => Self::Bool,
13311337
"object" => Self::Object,
13321338
"bytes" => Self::Bytes,
1339+
"bytearray" => Self::Bytearray,
13331340
"tuple" => Self::Tuple,
13341341
"type" => Self::Type,
13351342
"int" => Self::Int,
@@ -1395,6 +1402,7 @@ impl<'db> KnownClass {
13951402
| Self::Bool
13961403
| Self::Object
13971404
| Self::Bytes
1405+
| Self::Bytearray
13981406
| Self::Type
13991407
| Self::Int
14001408
| Self::Float

0 commit comments

Comments
 (0)