Skip to content

Commit

Permalink
Added follow import tests and one more example to infer numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
Lexxxzy committed Oct 11, 2024
1 parent a5e42c6 commit 6114ee7
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 224 deletions.
133 changes: 133 additions & 0 deletions crates/red_knot_python_semantic/resources/mdtest/imports.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# Follow imports

## Classes

We can follow import to class:

````markdown
```py path=a.py
from b import C as D; E = D
reveal_type(E) # revealed: Literal[C]
```

```py path=b.py
class C: pass
```
````

## Relative

Track that non-existent relative imports resolve to `Unknown`:
````markdown
```py path=package1/__init__.py
```

```py path=package1/bar.py
from .foo import X # error: [unresolved-import]
reveal_type(X) # revealed: Unknown
```
````

Follow relative imports:

````markdown
```py path=package2/__init__.py
```

```py path=package2/foo.py
X = 42
```

```py path=package2/bar.py
from .foo import X
reveal_type(X) # revealed: Literal[42]
```
````

We can also follow dotted relative imports:

````markdown
```py path=package3/__init__.py
```

```py path=package3/foo/bar/baz.py
X = 42
```

```py path=package3/bar.py
from .foo.bar.baz import X
reveal_type(X) # revealed: Literal[42]
```
````

Follow relative import bare to package:

````markdown
```py path=package4/__init__.py
X = 42
```

```py path=package4/bar.py
from . import X
reveal_type(X) # revealed: Literal[42]
```
````

Follow non-existent relative import bare to package:

```py path=package5/bar.py
from . import X # error: [unresolved-import]
reveal_type(X) # revealed: Unknown
```

Follow relative import from dunder init:

````markdown
```py path=package6/__init__.py
from .foo import X
reveal_type(X) # revealed: Literal[42]
```

```py path=package6/foo.py
X = 42
```
````

Follow non-existent relative import from dunder init:

```py path=package7/__init__.py
from .foo import X # error: [unresolved-import]
reveal_type(X) # revealed: Unknown
```

Follow very relative import:

````markdown
```py path=package8/__init__.py
```

```py path=package8/foo.py
X = 42
```

```py path=package8/subpackage/subsubpackage/bar.py
from ...foo import X
reveal_type(X) # revealed: Literal[42]
```
````

Imported unbound symbol is `Unknown`:

````markdown
```py path=package9/__init__.py
```

```py path=package9/foo.py
x
```

```py path=package9/bar.py
from .foo import x # error: [unresolved-import]
reveal_type(x) # revealed: Unknown
```
````
7 changes: 7 additions & 0 deletions crates/red_knot_python_semantic/resources/mdtest/numbers.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ We can infer an integer literal type:
reveal_type(1) # revealed: Literal[1]
```

We can track that variable as an integer:

```py path=a.py
x = 1
reveal_type(x) # revealed: Literal[1]
```

### Overflow

We only track integer literals within the range of an i64:
Expand Down
224 changes: 0 additions & 224 deletions crates/red_knot_python_semantic/src/types/infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3352,167 +3352,6 @@ mod tests {
assert_diagnostic_messages(&diagnostics, expected);
}

#[test]
fn reveal_type() -> anyhow::Result<()> {
let mut db = setup_db();

db.write_dedented(
"/src/a.py",
"
from typing import reveal_type
x = 1
reveal_type(x)
",
)?;

assert_file_diagnostics(&db, "/src/a.py", &["Revealed type is `Literal[1]`"]);

Ok(())
}

#[test]
fn reveal_type_aliased() -> anyhow::Result<()> {
let mut db = setup_db();

db.write_dedented(
"/src/a.py",
"
from typing import reveal_type as rt
x = 1
rt(x)
",
)?;

assert_file_diagnostics(&db, "/src/a.py", &["Revealed type is `Literal[1]`"]);

Ok(())
}

#[test]
fn reveal_type_typing_extensions() -> anyhow::Result<()> {
let mut db = setup_db();

db.write_dedented(
"/src/a.py",
"
import typing_extensions
x = 1
typing_extensions.reveal_type(x)
",
)?;

assert_file_diagnostics(&db, "/src/a.py", &["Revealed type is `Literal[1]`"]);

Ok(())
}

#[test]
fn reveal_type_builtin() -> anyhow::Result<()> {
let mut db = setup_db();

db.write_dedented(
"/src/a.py",
"
x = 1
reveal_type(x)
",
)?;

assert_file_diagnostics(
&db,
"/src/a.py",
&[
"`reveal_type` used without importing it; this is allowed for debugging convenience but will fail at runtime",
"Revealed type is `Literal[1]`",
],
);

Ok(())
}

#[test]
fn follow_import_to_class() -> anyhow::Result<()> {
let mut db = setup_db();

db.write_files([
("src/a.py", "from b import C as D; E = D"),
("src/b.py", "class C: pass"),
])?;

assert_public_ty(&db, "src/a.py", "E", "Literal[C]");

Ok(())
}

#[test]
fn follow_relative_import_simple() -> anyhow::Result<()> {
let mut db = setup_db();

db.write_files([
("src/package/__init__.py", ""),
("src/package/foo.py", "X = 42"),
("src/package/bar.py", "from .foo import X"),
])?;

assert_public_ty(&db, "src/package/bar.py", "X", "Literal[42]");

Ok(())
}

#[test]
fn follow_nonexistent_relative_import_simple() -> anyhow::Result<()> {
let mut db = setup_db();

db.write_files([
("src/package/__init__.py", ""),
("src/package/bar.py", "from .foo import X"),
])?;

assert_public_ty(&db, "src/package/bar.py", "X", "Unknown");

Ok(())
}

#[test]
fn follow_relative_import_dotted() -> anyhow::Result<()> {
let mut db = setup_db();

db.write_files([
("src/package/__init__.py", ""),
("src/package/foo/bar/baz.py", "X = 42"),
("src/package/bar.py", "from .foo.bar.baz import X"),
])?;

assert_public_ty(&db, "src/package/bar.py", "X", "Literal[42]");

Ok(())
}

#[test]
fn follow_relative_import_bare_to_package() -> anyhow::Result<()> {
let mut db = setup_db();

db.write_files([
("src/package/__init__.py", "X = 42"),
("src/package/bar.py", "from . import X"),
])?;

assert_public_ty(&db, "src/package/bar.py", "X", "Literal[42]");

Ok(())
}

#[test]
fn follow_nonexistent_relative_import_bare_to_package() -> anyhow::Result<()> {
let mut db = setup_db();
db.write_files([("src/package/bar.py", "from . import X")])?;
assert_public_ty(&db, "src/package/bar.py", "X", "Unknown");
Ok(())
}

#[ignore = "TODO: Submodule imports possibly not supported right now?"]
#[test]
fn follow_relative_import_bare_to_module() -> anyhow::Result<()> {
Expand Down Expand Up @@ -3544,69 +3383,6 @@ mod tests {
Ok(())
}

#[test]
fn follow_relative_import_from_dunder_init() -> anyhow::Result<()> {
let mut db = setup_db();

db.write_files([
("src/package/__init__.py", "from .foo import X"),
("src/package/foo.py", "X = 42"),
])?;

assert_public_ty(&db, "src/package/__init__.py", "X", "Literal[42]");

Ok(())
}

#[test]
fn follow_nonexistent_relative_import_from_dunder_init() -> anyhow::Result<()> {
let mut db = setup_db();
db.write_files([("src/package/__init__.py", "from .foo import X")])?;
assert_public_ty(&db, "src/package/__init__.py", "X", "Unknown");
Ok(())
}

#[test]
fn follow_very_relative_import() -> anyhow::Result<()> {
let mut db = setup_db();

db.write_files([
("src/package/__init__.py", ""),
("src/package/foo.py", "X = 42"),
(
"src/package/subpackage/subsubpackage/bar.py",
"from ...foo import X",
),
])?;

assert_public_ty(
&db,
"src/package/subpackage/subsubpackage/bar.py",
"X",
"Literal[42]",
);

Ok(())
}

#[test]
fn imported_unbound_symbol_is_unknown() -> anyhow::Result<()> {
let mut db = setup_db();

db.write_files([
("src/package/__init__.py", ""),
("src/package/foo.py", "x"),
("src/package/bar.py", "from package.foo import x"),
])?;

// the type as seen from external modules (`Unknown`)
// is different from the type inside the module itself (`Unbound`):
assert_public_ty(&db, "src/package/foo.py", "x", "Unbound");
assert_public_ty(&db, "src/package/bar.py", "x", "Unknown");

Ok(())
}

#[test]
fn from_import_with_no_module_name() -> anyhow::Result<()> {
// This test checks that invalid syntax in a `StmtImportFrom` node
Expand Down

0 comments on commit 6114ee7

Please sign in to comment.