Skip to content

Commit

Permalink
[red-knot] Migrate is_fully_static/is_single_valued/`is_singleton…
Browse files Browse the repository at this point in the history
…` unit tests to Markdown tests (#15533)

## Summary

Part of #15397.

## Test Plan

Markdown tests.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
  • Loading branch information
InSyncWithFoo and AlexWaygood authored Jan 16, 2025
1 parent aed0bf1 commit 6f0b662
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 87 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Fully-static types

A type is fully static iff it does not contain any gradual forms.

## Fully-static

```py
from typing_extensions import Literal, LiteralString, Never
from knot_extensions import Intersection, Not, TypeOf, is_fully_static, static_assert

static_assert(is_fully_static(Never))
static_assert(is_fully_static(None))

static_assert(is_fully_static(Literal[1]))
static_assert(is_fully_static(Literal[True]))
static_assert(is_fully_static(Literal["abc"]))
static_assert(is_fully_static(Literal[b"abc"]))

static_assert(is_fully_static(LiteralString))

static_assert(is_fully_static(str))
static_assert(is_fully_static(object))
static_assert(is_fully_static(type))

static_assert(is_fully_static(TypeOf[str]))
static_assert(is_fully_static(TypeOf[Literal]))

static_assert(is_fully_static(str | None))
static_assert(is_fully_static(Intersection[str, Not[LiteralString]]))

static_assert(is_fully_static(tuple[()]))
static_assert(is_fully_static(tuple[int, object]))

static_assert(is_fully_static(type[str]))
static_assert(is_fully_static(type[object]))
```

## Non-fully-static

```py
from typing_extensions import Any, Literal, LiteralString
from knot_extensions import Intersection, Not, TypeOf, Unknown, is_fully_static, static_assert

static_assert(not is_fully_static(Any))
static_assert(not is_fully_static(Unknown))

static_assert(not is_fully_static(Any | str))
static_assert(not is_fully_static(str | Unknown))
static_assert(not is_fully_static(Intersection[Any, Not[LiteralString]]))

static_assert(not is_fully_static(tuple[Any, ...]))
static_assert(not is_fully_static(tuple[int, Any]))
static_assert(not is_fully_static(type[Any]))
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
## Single-valued types

A type is single-valued iff it is not empty and all inhabitants of it compare equal.

```py
from typing_extensions import Any, Literal, LiteralString, Never
from knot_extensions import is_single_valued, static_assert

static_assert(is_single_valued(None))
static_assert(is_single_valued(Literal[True]))
static_assert(is_single_valued(Literal[1]))
static_assert(is_single_valued(Literal["abc"]))
static_assert(is_single_valued(Literal[b"abc"]))

static_assert(is_single_valued(tuple[()]))
static_assert(is_single_valued(tuple[Literal[True], Literal[1]]))

static_assert(not is_single_valued(str))
static_assert(not is_single_valued(Never))
static_assert(not is_single_valued(Any))

static_assert(not is_single_valued(Literal[1, 2]))

static_assert(not is_single_valued(tuple[None, int]))
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Singleton types

A type is a singleton type iff it has exactly one inhabitant.

## Basic

```py
from typing_extensions import Literal, Never
from knot_extensions import is_singleton, static_assert

static_assert(is_singleton(None))
static_assert(is_singleton(Literal[True]))
static_assert(is_singleton(Literal[False]))

static_assert(is_singleton(type[bool]))

static_assert(not is_singleton(Never))
static_assert(not is_singleton(str))

static_assert(not is_singleton(Literal[345]))
static_assert(not is_singleton(Literal[1, 2]))

static_assert(not is_singleton(tuple[()]))
static_assert(not is_singleton(tuple[None]))
static_assert(not is_singleton(tuple[None, Literal[True]]))
```

## `NoDefault`

### 3.12

```toml
[environment]
python-version = "3.12"
```

```py
from typing_extensions import _NoDefaultType
from knot_extensions import is_singleton, static_assert

static_assert(is_singleton(_NoDefaultType))
```

### 3.13

```toml
[environment]
python-version = "3.13"
```

```py
from typing import _NoDefaultType
from knot_extensions import is_singleton, static_assert

static_assert(is_singleton(_NoDefaultType))
```
87 changes: 0 additions & 87 deletions crates/red_knot_python_semantic/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4533,16 +4533,6 @@ pub(crate) mod tests {
));
}

#[test_case(Ty::None)]
#[test_case(Ty::BooleanLiteral(true))]
#[test_case(Ty::BooleanLiteral(false))]
#[test_case(Ty::SubclassOfBuiltinClass("bool"))] // a `@final` class
fn is_singleton(from: Ty) {
let db = setup_db();

assert!(from.into_type(&db).is_singleton(&db));
}

/// Explicitly test for Python version <3.13 and >=3.13, to ensure that
/// the fallback to `typing_extensions` is working correctly.
/// See [`KnownClass::canonical_module`] for more information.
Expand All @@ -4559,83 +4549,6 @@ pub(crate) mod tests {
assert!(no_default.is_singleton(&db));
}

#[test_case(Ty::None)]
#[test_case(Ty::BooleanLiteral(true))]
#[test_case(Ty::IntLiteral(1))]
#[test_case(Ty::StringLiteral("abc"))]
#[test_case(Ty::BytesLiteral("abc"))]
#[test_case(Ty::Tuple(vec![]))]
#[test_case(Ty::Tuple(vec![Ty::BooleanLiteral(true), Ty::IntLiteral(1)]))]
fn is_single_valued(from: Ty) {
let db = setup_db();

assert!(from.into_type(&db).is_single_valued(&db));
}

#[test_case(Ty::Never)]
#[test_case(Ty::Any)]
#[test_case(Ty::Union(vec![Ty::IntLiteral(1), Ty::IntLiteral(2)]))]
#[test_case(Ty::Tuple(vec![Ty::None, Ty::BuiltinInstance("int")]))]
#[test_case(Ty::BuiltinInstance("str"))]
#[test_case(Ty::LiteralString)]
fn is_not_single_valued(from: Ty) {
let db = setup_db();

assert!(!from.into_type(&db).is_single_valued(&db));
}

#[test_case(Ty::Never)]
#[test_case(Ty::IntLiteral(345))]
#[test_case(Ty::BuiltinInstance("str"))]
#[test_case(Ty::Union(vec![Ty::IntLiteral(1), Ty::IntLiteral(2)]))]
#[test_case(Ty::Tuple(vec![]))]
#[test_case(Ty::Tuple(vec![Ty::None]))]
#[test_case(Ty::Tuple(vec![Ty::None, Ty::BooleanLiteral(true)]))]
fn is_not_singleton(from: Ty) {
let db = setup_db();

assert!(!from.into_type(&db).is_singleton(&db));
}

#[test_case(Ty::Never)]
#[test_case(Ty::None)]
#[test_case(Ty::IntLiteral(1))]
#[test_case(Ty::BooleanLiteral(true))]
#[test_case(Ty::StringLiteral("abc"))]
#[test_case(Ty::LiteralString)]
#[test_case(Ty::BytesLiteral("abc"))]
#[test_case(Ty::KnownClassInstance(KnownClass::Str))]
#[test_case(Ty::KnownClassInstance(KnownClass::Object))]
#[test_case(Ty::KnownClassInstance(KnownClass::Type))]
#[test_case(Ty::BuiltinClassLiteral("str"))]
#[test_case(Ty::TypingLiteral)]
#[test_case(Ty::Union(vec![Ty::KnownClassInstance(KnownClass::Str), Ty::None]))]
#[test_case(Ty::Intersection{pos: vec![Ty::KnownClassInstance(KnownClass::Str)], neg: vec![Ty::LiteralString]})]
#[test_case(Ty::Tuple(vec![]))]
#[test_case(Ty::Tuple(vec![Ty::KnownClassInstance(KnownClass::Int), Ty::KnownClassInstance(KnownClass::Object)]))]
#[test_case(Ty::BuiltinInstance("type"))]
#[test_case(Ty::SubclassOfBuiltinClass("object"))]
#[test_case(Ty::SubclassOfBuiltinClass("str"))]
fn is_fully_static(from: Ty) {
let db = setup_db();

assert!(from.into_type(&db).is_fully_static(&db));
}

#[test_case(Ty::Any)]
#[test_case(Ty::Unknown)]
#[test_case(Ty::Todo)]
#[test_case(Ty::Union(vec![Ty::Any, Ty::KnownClassInstance(KnownClass::Str)]))]
#[test_case(Ty::Union(vec![Ty::KnownClassInstance(KnownClass::Str), Ty::Unknown]))]
#[test_case(Ty::Intersection{pos: vec![Ty::Any], neg: vec![Ty::LiteralString]})]
#[test_case(Ty::Tuple(vec![Ty::KnownClassInstance(KnownClass::Int), Ty::Any]))]
#[test_case(Ty::SubclassOfAny)]
fn is_not_fully_static(from: Ty) {
let db = setup_db();

assert!(!from.into_type(&db).is_fully_static(&db));
}

#[test_case(Ty::Todo, Ty::Todo)]
#[test_case(Ty::Any, Ty::Any)]
#[test_case(Ty::Unknown, Ty::Unknown)]
Expand Down

0 comments on commit 6f0b662

Please sign in to comment.