Compare commits

...

57 Commits

Author SHA1 Message Date
Carl Meyer
cff8ab1202 [red-knot] add tracing of salsa events in mdtests 2025-05-02 17:31:28 -07:00
Carl Meyer
7ce1db380d add mdtest that repros 2025-05-02 17:22:46 -07:00
Carl Meyer
adb452f6f2 prune to minimal typeshed 2025-05-02 17:21:43 -07:00
Alex Waygood
e55c9e80c9 Special-case is_protocol() for str 2025-04-28 15:36:33 +01:00
Alex Waygood
21b36b015d remove SupportsIndex/Sized workarounds 2025-04-28 14:51:43 +01:00
Alex Waygood
8ab0bd7bd4 fix ProtocolInstanceType::is_equivalent_to and update test assertions 2025-04-28 14:51:43 +01:00
Alex Waygood
ca10890fa0 fix bug 2025-04-28 14:51:43 +01:00
Alex Waygood
d72f767b09 fix compile error after rebase 2025-04-28 14:51:43 +01:00
Alex Waygood
d67207283b A new Type variant 2025-04-28 14:51:43 +01:00
Alex Waygood
454630db2b Add a ProtocolInstanceType 2025-04-28 14:51:43 +01:00
Alex Waygood
f2b329a651 Rename Type::Instance to Type::NominalInstance and InstanceType to NominalInstanceType 2025-04-28 14:51:43 +01:00
Alex Waygood
1ad5015e19 Upgrade Salsa to a more recent commit (#17678) 2025-04-28 13:32:19 +01:00
David Peter
92f95ff494 [red-knot] TypedDict: No errors for introspection dunder attributes (#17677)
## Summary

Do not emit errors when accessing introspection dunder attributes such
as `__required_keys__` on `TypedDict`s.
2025-04-28 13:28:43 +02:00
Victor Hugo Gomes
ceb2bf1168 [flake8-pyi] Ensure Literal[None,] | Literal[None,] is not autofixed to None | None (PYI061) (#17659)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-04-28 12:23:29 +01:00
David Peter
f521358033 [red-knot] No errors for definitions of TypedDicts (#17674)
## Summary

Do not emit errors when defining `TypedDict`s:

```py
from typing_extensions import TypedDict

# No error here
class Person(TypedDict):
    name: str
    age: int | None

# No error for this alternative syntax
Message = TypedDict("Message", {"id": int, "content": str})
```

## Ecosystem analysis

* Removes ~ 450 false positives for `TypedDict` definitions.
* Changes a few diagnostic messages.
* Adds a few (< 10) false positives, for example:
  ```diff
+ error[lint:unresolved-attribute]
/tmp/mypy_primer/projects/hydra-zen/src/hydra_zen/structured_configs/_utils.py:262:5:
Type `Literal[DataclassOptions]` has no attribute `__required_keys__`
+ error[lint:unresolved-attribute]
/tmp/mypy_primer/projects/hydra-zen/src/hydra_zen/structured_configs/_utils.py:262:42:
Type `Literal[DataclassOptions]` has no attribute `__optional_keys__`
  ```
* New true positive

4f8263cd7f/corporate/lib/remote_billing_util.py (L155-L157)
  ```diff
+ error[lint:invalid-assignment]
/tmp/mypy_primer/projects/zulip/corporate/lib/remote_billing_util.py:155:5:
Object of type `RemoteBillingIdentityDict | LegacyServerIdentityDict |
None` is not assignable to `LegacyServerIdentityDict | None`
  ```

## Test Plan

New Markdown tests
2025-04-28 13:13:28 +02:00
renovate[bot]
74081032d9 Update actions/download-artifact digest to d3f86a1 (#17664)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-04-28 10:51:59 +00:00
Micha Reiser
dbc137c951 [red-knot] Use 101 exit code when there's at least one diagnostic with severity 'fatal' (#17640) 2025-04-28 10:03:14 +02:00
Victor Hugo Gomes
826b2c9ff3 [pycodestyle] Fix duplicated diagnostic in E712 (#17651) 2025-04-28 08:31:16 +01:00
jie211
a3e55cfd8f [airflow] fix typos AIR312 (#17673) 2025-04-28 08:31:41 +02:00
justin
d2246278e6 [red-knot] Don't ignore hidden files by default (#17655) 2025-04-28 08:21:11 +02:00
renovate[bot]
6bd1863bf0 Update pre-commit hook astral-sh/ruff-pre-commit to v0.11.7 (#17670)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 08:16:10 +02:00
renovate[bot]
97dc58fc77 Update docker/build-push-action digest to 14487ce (#17665)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 08:15:54 +02:00
renovate[bot]
53a9448fb5 Update taiki-e/install-action digest to ab3728c (#17666)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 08:15:01 +02:00
renovate[bot]
516291b693 Update dependency react-resizable-panels to v2.1.9 (#17667)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 08:10:24 +02:00
renovate[bot]
b09f00a4ef Update dependency ruff to v0.11.7 (#17668)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 08:09:50 +02:00
renovate[bot]
03065c245c Update dependency smol-toml to v1.3.4 (#17669)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 08:09:33 +02:00
renovate[bot]
b45598389d Update Rust crate jiff to v0.2.10 (#17671)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 08:09:10 +02:00
renovate[bot]
4729ff2bc8 Update Rust crate syn to v2.0.101 (#17672)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 08:08:41 +02:00
Micha Reiser
1bdb22c139 [red-knot] Fix offset handling in playground for 2-code-point UTF16 characters (#17520) 2025-04-27 11:44:55 +01:00
Micha Reiser
1c65e0ad25 Split SourceLocation into LineColumn and SourceLocation (#17587) 2025-04-27 11:27:33 +01:00
justin
4443f6653c [red-knot] Add --respect-ignore-files flag (#17645)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-04-27 10:55:41 +01:00
Vasco Schiavo
b0d475f353 [ruff] add fix safety section (RUF027) (#17485)
The PR add the `fix safety` section for rule `RUF027` (#15584 ).

Actually, I have an example of a false positive. Should I include it in
the` fix safety` section?

---------

Co-authored-by: Dylan <dylwil3@gmail.com>
2025-04-26 16:43:53 -05:00
Vasco Schiavo
b578a828ef [ruff] add fix safety section (RUF005) (#17484)
The PR add the `fix safety` section for rule `RUF005` (#15584 ).

---------

Co-authored-by: Dylan <dylwil3@gmail.com>
2025-04-26 16:43:02 -05:00
Vasco Schiavo
64ba39a385 [flynt] add fix safety section (FLY002) (#17496)
The PR add the fix safety section for rule `FLY002` (#15584 )

The motivation for the content of the fix safety section is given by the
following example

```python
foo = 1
bar = [2, 3]

try:
    result_join = " ".join((foo, bar))
    print(f"Join result: {result_join}")
except TypeError as e:
    print(f"Join error: {e}")
```

which print `Join error: sequence item 0: expected str instance, int
found`

But after the fix is applied, we have

```python
foo = 1
bar = [2, 3]

try:
    result_join = f"{foo} {bar}"
    print(f"Join result: {result_join}")
except TypeError as e:
    print(f"Join error: {e}")
```

which print `Join result: 1 [2, 3]`

---------

Co-authored-by: dylwil3 <dylwil3@gmail.com>
2025-04-26 16:00:01 +00:00
Hans
a4e225ee8a [flake8-async] Add fix safety section (ASYNC116) (#17497)
## Summary

This PR add the `fix safety` section for rule `ASYNC116` in
`long_sleep_not_forever.rs` for #15584

---------

Co-authored-by: dylwil3 <dylwil3@gmail.com>
2025-04-26 10:40:51 -05:00
Vasco Schiavo
45d0634b01 [pydocstyle] add fix safety section (D200) (#17502)
The PR add the fix safety section for rule `D200` (#15584 )
2025-04-26 08:59:05 -05:00
Vasco Schiavo
4bcf1778fa [ruff] add fix safety section (RUF057) (#17483)
The PR add the `fix safety` section for rule `RUF057` (#15584 )
2025-04-26 06:58:52 -05:00
Micha Reiser
6044f04137 Revert "[red-knot] Add --respect-ignore-files flag (#17569)" (#17642) 2025-04-26 10:30:50 +00:00
justin
2e95475f57 [red-knot] Add --respect-ignore-files flag (#17569)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-04-26 10:02:03 +00:00
Micha Reiser
cfa1505068 [red-knot] Fix CLI hang when a dependent query panics (#17631) 2025-04-26 06:28:45 +00:00
Dhruv Manilawala
0251679f87 [red-knot] Add new property tests for subtyping with "bottom" callable (#17635)
## Summary

I remember we discussed about adding this as a property tests so here I
am.

## Test Plan

```console
❯ QUICKCHECK_TESTS=10000000 cargo test --locked --release --package red_knot_python_semantic -- --ignored types::property_tests::stable::bottom_callable_is_subtype_of_all_fully_static_callable
    Finished `release` profile [optimized] target(s) in 0.10s
     Running unittests src/lib.rs (target/release/deps/red_knot_python_semantic-e41596ca2dbd0e98)
running 1 test
test types::property_tests::stable::bottom_callable_is_subtype_of_all_fully_static_callable ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 233 filtered out; finished in 30.91s
```
2025-04-26 03:58:13 +05:30
Douglas Creager
6ab32a7746 [red-knot] Create generic context for generic classes lazily (#17617)
As discussed today, this is needed to handle legacy generic classes
without having to infer the types of the class's explicit bases eagerly
at class construction time. Pulling this out into a separate PR so
there's a smaller diff to review.

This also makes our representation of generic classes and functions more
consistent — before, we had separate Rust types and enum variants for
generic/non-generic classes, but a single type for generic functions.
Now we each a single (respective) type for each.

There were very few places we were differentiation between generic and
non-generic _class literals_, and these are handled now by calling the
(salsa cached) `generic_context` _accessor function_.

Note that _`ClassType`_ is still an enum with distinct variants for
non-generic classes and specialized generic classes.
2025-04-25 14:10:03 -04:00
Andrew Gallant
bc0a5aa409 ruff_db: add tests for annotations with no ranges
... and fix the case where an annotation with a `Span` but no
`TextRange` or message gets completely dropped.
2025-04-25 13:25:20 -04:00
Wei Lee
aba21a5d47 [airflow] Extend AIR301 rule (#17598)
## Summary

<!-- What's the purpose of the change? What does it do, and why? -->

Add "airflow.operators.python.get_current_context" →
"airflow.sdk.get_current_context" rule

## Test Plan

<!-- How was it tested? -->

the test fixture has been updated accordingly
2025-04-25 12:49:32 -04:00
Wei Lee
b6281a8805 [airflow] update existing AIR302 rules with better suggestions (#17542)
## Summary

Even though the original suggestion works, they've been removed in later
version and is no longer the best practices.

e.g., many sql realted operators have been removed and are now suggested
to use SQLExecuteQueryOperator instead

## Test Plan

The existing test fixtures have been updated
2025-04-25 12:44:28 -04:00
Andrew Gallant
049280a3bc red_knot_project: sort diagnostics from checking files
Previously, we could iterate over files in an unspecified order (via
`HashSet` iteration) and we could accumulate diagnostics from files in
an unspecified order (via parallelism).

Here, we change the status quo so that diagnostics collected from files
are sorted after checking is complete. For now, we sort by severity
(with higher severity diagnostics appearing first) and then by
diagnostic ID to give a stable ordering.

I'm not sure if this is the best ordering.
2025-04-25 12:38:31 -04:00
Carl Meyer
fa88989ef0 [red-knot] fix detecting a metaclass on a not-explicitly-specialized generic base (#17621)
## Summary

After https://github.com/astral-sh/ruff/pull/17620 (which this PR is
based on), I was looking at other call sites of `Type::into_class_type`,
and I began to feel that _all_ of them were currently buggy due to
silently skipping unspecialized generic class literal types (though in
some cases the bug hadn't shown up yet because we don't understand
legacy generic classes from typeshed), and in every case they would be
better off if an unspecialized generic class literal were implicitly
specialized with the default specialization (which is the usual Python
typing semantics for an unspecialized reference to a generic class),
instead of silently skipped.

So I changed the method to implicitly apply the default specialization,
and added a test that previously failed for detecting metaclasses on an
unspecialized generic base.

I also renamed the method to `to_class_type`, because I feel we have a
strong naming convention where `Type::into_foo` is always a trivial
`const fn` that simply returns `Some()` if the type is of variant `Foo`
and `None` otherwise. Even the existing method (with it handling both
`GenericAlias` and `ClassLiteral`, and distinguishing kinds of
`ClassLiteral`) was stretching this convention, and the new version
definitely breaks that envelope.

## Test Plan

Added a test that failed before this PR.
2025-04-25 06:55:54 -07:00
Carl Meyer
4c3f389598 [red-knot] fix inheritance-cycle detection for generic classes (#17620)
## Summary

The `ClassLiteralType::inheritance_cycle` method is intended to detect
inheritance cycles that would result in cyclic MROs, emit a diagnostic,
and skip actually trying to create the cyclic MRO, falling back to an
"error" MRO instead with just `Unknown` and `object`.

This method didn't work properly for generic classes. It used
`fully_static_explicit_bases`, which filter-maps `explicit_bases` over
`Type::into_class_type`, which returns `None` for an unspecialized
generic class literal. So in a case like `class C[T](C): ...`, because
the explicit base is an unspecialized generic, we just skipped it, and
failed to detect the class as cyclically defined.

Instead, iterate directly over all `explicit_bases`, and explicitly
handle both the specialized (`GenericAlias`) and unspecialized
(`ClassLiteral`) cases, so that we check all bases and correctly detect
cyclic inheritance.

## Test Plan

Added mdtests.
2025-04-25 06:55:00 -07:00
Brent Westbrook
6d3b1d13d6 [pylint] Detect global declarations in module scope (PLE0118) (#17411)
Summary
--

While going through the syntax errors in [this comment], I was surprised
to see the error `name 'x' is assigned to before global declaration`,
which corresponds to [load-before-global-declaration (PLE0118)] and has
also been reimplemented as a syntax error (#17135). However, it looks
like neither of the implementations consider `global` declarations in
the top-level module scope, which is a syntax error in CPython:

```python
# try.py
x = None
global x
```

```shell
> python -m compileall -f try.py
Compiling 'try.py'...
***   File "try.py", line 2
    global x
    ^^^^^^^^
SyntaxError: name 'x' is assigned to before global declaration
```

I'm not sure this is the best or most elegant solution, but it was a
quick fix that passed all of our tests.

Test Plan
--

New PLE0118 test case.

[this comment]:
https://github.com/astral-sh/ruff/issues/7633#issuecomment-1740424031
[load-before-global-declaration (PLE0118)]:
https://docs.astral.sh/ruff/rules/load-before-global-declaration/#load-before-global-declaration-ple0118
2025-04-25 08:37:16 -04:00
Max Mynter
3f84e75e20 Add Semantic Error Test for LateFutureImport (#17612)
Adresses a question in #17526.

## Summary
Adds a syntax error test for `__future__` import not at top of file. 

## Question: 
Is this a redundant with
8d2c79276d/crates/ruff_linter/resources/test/fixtures/pyflakes/F404_0.py (L1-L8)
and
8d2c79276d/crates/ruff_linter/resources/test/fixtures/pyflakes/F404_1.py (L1-L5)

which test pyflake `F404`?
<!-- What's the purpose of the change? What does it do, and why? -->

## Test Plan
This is a test
<!-- How was it tested? -->
2025-04-25 08:32:57 -04:00
Carl Meyer
afc18ff1a1 [red-knot] change TypeVarInstance to be interned, not tracked (#17616)
## Summary

Tracked structs have some issues with fixpoint iteration in Salsa, and
there's not actually any need for this to be tracked, it should be
interned like most of our type structs.

The removed comment was probably never correct (in that we could have
disambiguated sufficiently), and is definitely not relevant now that
`TypeVarInstance` also holds its `Definition`.

## Test Plan

Existing tests.
2025-04-24 14:52:25 -07:00
Dhruv Manilawala
f1a539dac6 [red-knot] Special case @final, @override (#17608)
## Summary

This PR adds special-casing for `@final` and `@override` decorator for a
similar reason as https://github.com/astral-sh/ruff/pull/17591 to
support the invalid overload check.

Both `final` and `override` are identity functions which can be removed
once `TypeVar` support is added.
2025-04-25 03:15:23 +05:30
Carl Meyer
ef0343189c [red-knot] add TODO comment in specialization code (#17615)
## Summary

As promised, this just adds a TODO comment to document something we
discussed today that should probably be improved at some point, but
isn't a priority right now (since it's an issue that in practice would
only affect generic classes with both `__init__` and `__new__` methods,
where some typevar is bound to `Unknown` in one and to some other type
in another.)
2025-04-24 14:41:19 -07:00
Vasco Schiavo
4eecc40110 [semantic-syntax-errors] test for LoadBeforeGlobalDeclaration - ruff linter (#17592)
Hey @ntBre 

just one easy case to see if I understood the issue #17526 

Let me know if is this what you had in mind.
2025-04-24 16:14:33 -04:00
Abhijeet Prasad Bodas
cf59cee928 [syntax-errors] nonlocal declaration at module level (#17559)
## Summary

Part of #17412

Add a new compile-time syntax error for detecting `nonlocal`
declarations at a module level.

## Test Plan

- Added new inline tests for the syntax error
- Updated existing tests for `nonlocal` statement parsing to be inside a
function scope

Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
2025-04-24 16:11:46 -04:00
Wei Lee
538393d1f3 [airflow] Apply auto fix to cases where name has been changed in Airflow 3 (AIR311) (#17571)
## Summary

Apply auto fix to cases where the name has been changed in Airflow 3
(`AIR311`)

## Test Plan

The test features has been updated
2025-04-24 15:48:54 -04:00
Brent Westbrook
92ecfc908b [syntax-errors] Make async-comprehension-in-sync-comprehension more specific (#17460)
## Summary

While adding semantic error support to red-knot, I noticed duplicate
diagnostics for code like this:

```py
# error: [invalid-syntax] "cannot use an asynchronous comprehension outside of an asynchronous function on Python 3.9 (syntax was added in 3.11)"
# error: [invalid-syntax] "`asynchronous comprehension` outside of an asynchronous function"
 [reveal_type(x) async for x in AsyncIterable()]
```

Beyond the duplication, the first error message doesn't make much sense
because this syntax is _not_ allowed on Python 3.11 either.

To fix this, this PR renames the
`async-comprehension-outside-async-function` semantic syntax error to
`async-comprehension-in-sync-comprehension` and fixes the rule to avoid
applying outside of sync comprehensions at all.

## Test Plan

New linter test demonstrating the false positive. The mdtests from my red-knot 
PR also reflect this change.
2025-04-24 15:45:54 -04:00
859 changed files with 3261 additions and 72648 deletions

View File

@@ -79,7 +79,7 @@ jobs:
# Adapted from https://docs.docker.com/build/ci/github-actions/multi-platform/
- name: Build and push by digest
id: build
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6
with:
context: .
platforms: ${{ matrix.platform }}
@@ -231,7 +231,7 @@ jobs:
${{ env.TAG_PATTERNS }}
- name: Build and push
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6
with:
context: .
platforms: linux/amd64,linux/arm64

View File

@@ -239,11 +239,11 @@ jobs:
- name: "Install mold"
uses: rui314/setup-mold@e16410e7f8d9e167b74ad5697a9089a35126eb50 # v1
- name: "Install cargo nextest"
uses: taiki-e/install-action@09dc018eee06ae1c9e0409786563f534210ceb83 # v2
uses: taiki-e/install-action@ab3728c7ba6948b9b429627f4d55a68842b27f18 # v2
with:
tool: cargo-nextest
- name: "Install cargo insta"
uses: taiki-e/install-action@09dc018eee06ae1c9e0409786563f534210ceb83 # v2
uses: taiki-e/install-action@ab3728c7ba6948b9b429627f4d55a68842b27f18 # v2
with:
tool: cargo-insta
- name: Red-knot mdtests (GitHub annotations)
@@ -293,11 +293,11 @@ jobs:
- name: "Install mold"
uses: rui314/setup-mold@e16410e7f8d9e167b74ad5697a9089a35126eb50 # v1
- name: "Install cargo nextest"
uses: taiki-e/install-action@09dc018eee06ae1c9e0409786563f534210ceb83 # v2
uses: taiki-e/install-action@ab3728c7ba6948b9b429627f4d55a68842b27f18 # v2
with:
tool: cargo-nextest
- name: "Install cargo insta"
uses: taiki-e/install-action@09dc018eee06ae1c9e0409786563f534210ceb83 # v2
uses: taiki-e/install-action@ab3728c7ba6948b9b429627f4d55a68842b27f18 # v2
with:
tool: cargo-insta
- name: "Run tests"
@@ -320,7 +320,7 @@ jobs:
- name: "Install Rust toolchain"
run: rustup show
- name: "Install cargo nextest"
uses: taiki-e/install-action@09dc018eee06ae1c9e0409786563f534210ceb83 # v2
uses: taiki-e/install-action@ab3728c7ba6948b9b429627f4d55a68842b27f18 # v2
with:
tool: cargo-nextest
- name: "Run tests"
@@ -403,11 +403,11 @@ jobs:
- name: "Install mold"
uses: rui314/setup-mold@e16410e7f8d9e167b74ad5697a9089a35126eb50 # v1
- name: "Install cargo nextest"
uses: taiki-e/install-action@09dc018eee06ae1c9e0409786563f534210ceb83 # v2
uses: taiki-e/install-action@ab3728c7ba6948b9b429627f4d55a68842b27f18 # v2
with:
tool: cargo-nextest
- name: "Install cargo insta"
uses: taiki-e/install-action@09dc018eee06ae1c9e0409786563f534210ceb83 # v2
uses: taiki-e/install-action@ab3728c7ba6948b9b429627f4d55a68842b27f18 # v2
with:
tool: cargo-insta
- name: "Run tests"
@@ -857,7 +857,7 @@ jobs:
run: rustup show
- name: "Install codspeed"
uses: taiki-e/install-action@09dc018eee06ae1c9e0409786563f534210ceb83 # v2
uses: taiki-e/install-action@ab3728c7ba6948b9b429627f4d55a68842b27f18 # v2
with:
tool: cargo-codspeed

View File

@@ -129,14 +129,14 @@ jobs:
persist-credentials: false
submodules: recursive
- name: Install cached dist
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
with:
name: cargo-dist-cache
path: ~/.cargo/bin/
- run: chmod +x ~/.cargo/bin/dist
# Get all the local artifacts for the global tasks to use (for e.g. checksums)
- name: Fetch local artifacts
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
with:
pattern: artifacts-*
path: target/distrib/
@@ -180,14 +180,14 @@ jobs:
persist-credentials: false
submodules: recursive
- name: Install cached dist
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
with:
name: cargo-dist-cache
path: ~/.cargo/bin/
- run: chmod +x ~/.cargo/bin/dist
# Fetch artifacts from scratch-storage
- name: Fetch artifacts
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
with:
pattern: artifacts-*
path: target/distrib/
@@ -257,7 +257,7 @@ jobs:
submodules: recursive
# Create a GitHub Release while uploading all files to it
- name: "Download GitHub Artifacts"
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
with:
pattern: artifacts-*
path: artifacts

View File

@@ -79,7 +79,7 @@ repos:
pass_filenames: false # This makes it a lot faster
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.11.6
rev: v0.11.7
hooks:
- id: ruff-format
- id: ruff

119
Cargo.lock generated
View File

@@ -394,7 +394,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -490,20 +490,6 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "compact_str"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b79c4069c6cad78e2e0cdfcbd26275770669fb39fd308a752dc110e83b9af32"
dependencies = [
"castaway",
"cfg-if",
"itoa",
"rustversion",
"ryu",
"static_assertions",
]
[[package]]
name = "compact_str"
version = "0.9.0"
@@ -724,7 +710,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -735,7 +721,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
dependencies = [
"darling_core",
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -805,7 +791,7 @@ dependencies = [
"glob",
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -837,7 +823,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -1323,7 +1309,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -1488,7 +1474,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -1553,9 +1539,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "jiff"
version = "0.2.9"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59ec30f7142be6fe14e1b021f50b85db8df2d4324ea6e91ec3e5dcde092021d0"
checksum = "5a064218214dc6a10fbae5ec5fa888d80c45d611aba169222fc272072bf7aef6"
dependencies = [
"jiff-static",
"jiff-tzdb-platform",
@@ -1563,18 +1549,18 @@ dependencies = [
"portable-atomic",
"portable-atomic-util",
"serde",
"windows-sys 0.59.0",
"windows-sys 0.52.0",
]
[[package]]
name = "jiff-static"
version = "0.2.9"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "526b834d727fd59d37b076b0c3236d9adde1b1729a4361e20b2026f738cc1dbe"
checksum = "199b7932d97e325aff3a7030e141eafe7f2c6268e1d1b24859b753a627f45254"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -1671,7 +1657,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa96ed35d0dccc67cf7ba49350cb86de3dcb1d072a7ab28f99117f19d874953"
dependencies = [
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -2180,7 +2166,7 @@ dependencies = [
"pest_meta",
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -2249,7 +2235,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -2572,7 +2558,7 @@ dependencies = [
"anyhow",
"bitflags 2.9.0",
"camino",
"compact_str 0.9.0",
"compact_str",
"countme",
"dir-test",
"drop_bomb",
@@ -2661,6 +2647,7 @@ dependencies = [
"tempfile",
"thiserror 2.0.12",
"toml",
"tracing",
]
[[package]]
@@ -3074,7 +3061,7 @@ dependencies = [
"proc-macro2",
"quote",
"ruff_python_trivia",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -3101,7 +3088,7 @@ version = "0.0.0"
dependencies = [
"aho-corasick",
"bitflags 2.9.0",
"compact_str 0.9.0",
"compact_str",
"is-macro",
"itertools 0.14.0",
"memchr",
@@ -3199,7 +3186,7 @@ dependencies = [
"anyhow",
"bitflags 2.9.0",
"bstr",
"compact_str 0.9.0",
"compact_str",
"insta",
"memchr",
"ruff_annotate_snippets",
@@ -3457,11 +3444,11 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]]
name = "salsa"
version = "0.19.0"
source = "git+https://github.com/salsa-rs/salsa.git?rev=87bf6b6c2d5f6479741271da73bd9d30c2580c26#87bf6b6c2d5f6479741271da73bd9d30c2580c26"
version = "0.20.0"
source = "git+https://github.com/salsa-rs/salsa.git?rev=c75b0161aba55965ab6ad8cc9aaee7dc177967f1#c75b0161aba55965ab6ad8cc9aaee7dc177967f1"
dependencies = [
"boxcar",
"compact_str 0.8.1",
"compact_str",
"crossbeam-queue",
"dashmap 6.1.0",
"hashbrown 0.15.2",
@@ -3480,18 +3467,18 @@ dependencies = [
[[package]]
name = "salsa-macro-rules"
version = "0.19.0"
source = "git+https://github.com/salsa-rs/salsa.git?rev=87bf6b6c2d5f6479741271da73bd9d30c2580c26#87bf6b6c2d5f6479741271da73bd9d30c2580c26"
version = "0.20.0"
source = "git+https://github.com/salsa-rs/salsa.git?rev=c75b0161aba55965ab6ad8cc9aaee7dc177967f1#c75b0161aba55965ab6ad8cc9aaee7dc177967f1"
[[package]]
name = "salsa-macros"
version = "0.19.0"
source = "git+https://github.com/salsa-rs/salsa.git?rev=87bf6b6c2d5f6479741271da73bd9d30c2580c26#87bf6b6c2d5f6479741271da73bd9d30c2580c26"
version = "0.20.0"
source = "git+https://github.com/salsa-rs/salsa.git?rev=c75b0161aba55965ab6ad8cc9aaee7dc177967f1#c75b0161aba55965ab6ad8cc9aaee7dc177967f1"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
"synstructure",
]
@@ -3525,7 +3512,7 @@ dependencies = [
"proc-macro2",
"quote",
"serde_derive_internals",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -3574,7 +3561,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -3585,7 +3572,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -3608,7 +3595,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -3649,7 +3636,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -3780,7 +3767,7 @@ dependencies = [
"proc-macro2",
"quote",
"rustversion",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -3796,9 +3783,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.100"
version = "2.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
dependencies = [
"proc-macro2",
"quote",
@@ -3813,7 +3800,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -3884,7 +3871,7 @@ dependencies = [
"cfg-if",
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -3895,7 +3882,7 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
"test-case-core",
]
@@ -3931,7 +3918,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -3942,7 +3929,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -4073,7 +4060,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -4340,7 +4327,7 @@ checksum = "72dcd78c4f979627a754f5522cea6e6a25e55139056535fe6e69c506cd64a862"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -4462,7 +4449,7 @@ dependencies = [
"log",
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
"wasm-bindgen-shared",
]
@@ -4497,7 +4484,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -4532,7 +4519,7 @@ checksum = "17d5042cc5fa009658f9a7333ef24291b1291a25b6382dd68862a7f3b969f69b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -4647,7 +4634,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -4658,7 +4645,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -4896,7 +4883,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
"synstructure",
]
@@ -4917,7 +4904,7 @@ checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]
@@ -4937,7 +4924,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
"synstructure",
]
@@ -4960,7 +4947,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
"syn 2.0.101",
]
[[package]]

View File

@@ -124,7 +124,7 @@ rayon = { version = "1.10.0" }
regex = { version = "1.10.2" }
rustc-hash = { version = "2.0.0" }
# When updating salsa, make sure to also update the revision in `fuzz/Cargo.toml`
salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "87bf6b6c2d5f6479741271da73bd9d30c2580c26" }
salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "c75b0161aba55965ab6ad8cc9aaee7dc177967f1" }
schemars = { version = "0.8.16" }
seahash = { version = "4.1.0" }
serde = { version = "1.0.197", features = ["derive"] }
@@ -342,5 +342,5 @@ global = "depot-ubuntu-latest-4"
[workspace.metadata.dist.github-action-commits]
"actions/checkout" = "85e6279cec87321a52edac9c87bce653a07cf6c2" # v4
"actions/upload-artifact" = "6027e3dd177782cd8ab9af838c04fd81a07f1d47" # v4.6.2
"actions/download-artifact" = "95815c38cf2ff2164869cbab79da8d1f422bc89e" # v4.2.1
"actions/download-artifact" = "d3f86a106a0bac45b974a628896c90dbdf5c8093" # v4.3.0
"actions/attest-build-provenance" = "c074443f1aee8d4aeeae555aebba3282517141b2" #v2.2.3

View File

@@ -105,6 +105,19 @@ pub(crate) struct CheckCommand {
/// Watch files for changes and recheck files related to the changed files.
#[arg(long, short = 'W')]
pub(crate) watch: bool,
/// Respect file exclusions via `.gitignore` and other standard ignore files.
/// Use `--no-respect-gitignore` to disable.
#[arg(
long,
overrides_with("no_respect_ignore_files"),
help_heading = "File selection",
default_missing_value = "true",
num_args = 0..1
)]
respect_ignore_files: Option<bool>,
#[clap(long, overrides_with("respect_ignore_files"), hide = true)]
no_respect_ignore_files: bool,
}
impl CheckCommand {
@@ -120,6 +133,13 @@ impl CheckCommand {
)
};
// --no-respect-gitignore defaults to false and is set true by CLI flag. If passed, override config file
// Otherwise, only pass this through if explicitly set (don't default to anything here to
// make sure that doesn't take precedence over an explicitly-set config file value)
let respect_ignore_files = self
.no_respect_ignore_files
.then_some(false)
.or(self.respect_ignore_files);
Options {
environment: Some(EnvironmentOptions {
python_version: self
@@ -144,6 +164,7 @@ impl CheckCommand {
error_on_warning: self.error_on_warning,
}),
rules,
respect_ignore_files,
..Default::default()
}
}

View File

@@ -169,8 +169,12 @@ pub enum ExitStatus {
/// Checking was successful but there were errors.
Failure = 1,
/// Checking failed.
/// Checking failed due to an invocation error (e.g. the current directory no longer exists, incorrect CLI arguments, ...)
Error = 2,
/// Internal Red Knot error (panic, or any other error that isn't due to the user using the
/// program incorrectly or transient environment errors).
InternalError = 101,
}
impl Termination for ExitStatus {
@@ -246,11 +250,16 @@ impl MainLoop {
// Spawn a new task that checks the project. This needs to be done in a separate thread
// to prevent blocking the main loop here.
rayon::spawn(move || {
if let Ok(result) = db.check() {
// Send the result back to the main loop for printing.
sender
.send(MainLoopMessage::CheckCompleted { result, revision })
.unwrap();
match db.check() {
Ok(result) => {
// Send the result back to the main loop for printing.
sender
.send(MainLoopMessage::CheckCompleted { result, revision })
.unwrap();
}
Err(cancelled) => {
tracing::debug!("Check has been cancelled: {cancelled:?}");
}
}
});
}
@@ -264,12 +273,6 @@ impl MainLoop {
.format(terminal_settings.output_format)
.color(colored::control::SHOULD_COLORIZE.should_colorize());
let min_error_severity = if terminal_settings.error_on_warning {
Severity::Warning
} else {
Severity::Error
};
if check_revision == revision {
if db.project().files(db).is_empty() {
tracing::warn!("No python files found under the given path(s)");
@@ -284,13 +287,13 @@ impl MainLoop {
return Ok(ExitStatus::Success);
}
} else {
let mut failed = false;
let mut max_severity = Severity::Info;
let diagnostics_count = result.len();
for diagnostic in result {
write!(stdout, "{}", diagnostic.display(db, &display_config))?;
failed |= diagnostic.severity() >= min_error_severity;
max_severity = max_severity.max(diagnostic.severity());
}
writeln!(
@@ -301,10 +304,17 @@ impl MainLoop {
)?;
if self.watcher.is_none() {
return Ok(if failed {
ExitStatus::Failure
} else {
ExitStatus::Success
return Ok(match max_severity {
Severity::Info => ExitStatus::Success,
Severity::Warning => {
if terminal_settings.error_on_warning {
ExitStatus::Failure
} else {
ExitStatus::Success
}
}
Severity::Error => ExitStatus::Failure,
Severity::Fatal => ExitStatus::InternalError,
});
}
}

View File

@@ -5,6 +5,94 @@ use std::path::{Path, PathBuf};
use std::process::Command;
use tempfile::TempDir;
#[test]
fn test_include_hidden_files_by_default() -> anyhow::Result<()> {
let case = TestCase::with_files([(".test.py", "~")])?;
assert_cmd_snapshot!(case.command(), @r"
success: false
exit_code: 1
----- stdout -----
error: invalid-syntax
--> <temp_dir>/.test.py:1:2
|
1 | ~
| ^ Expected an expression
|
Found 1 diagnostic
----- stderr -----
");
Ok(())
}
#[test]
fn test_respect_ignore_files() -> anyhow::Result<()> {
// First test that the default option works correctly (the file is skipped)
let case = TestCase::with_files([(".ignore", "test.py"), ("test.py", "~")])?;
assert_cmd_snapshot!(case.command(), @r"
success: true
exit_code: 0
----- stdout -----
All checks passed!
----- stderr -----
WARN No python files found under the given path(s)
");
// Test that we can set to false via CLI
assert_cmd_snapshot!(case.command().arg("--no-respect-ignore-files"), @r"
success: false
exit_code: 1
----- stdout -----
error: invalid-syntax
--> <temp_dir>/test.py:1:2
|
1 | ~
| ^ Expected an expression
|
Found 1 diagnostic
----- stderr -----
");
// Test that we can set to false via config file
case.write_file("knot.toml", "respect-ignore-files = false")?;
assert_cmd_snapshot!(case.command(), @r"
success: false
exit_code: 1
----- stdout -----
error: invalid-syntax
--> <temp_dir>/test.py:1:2
|
1 | ~
| ^ Expected an expression
|
Found 1 diagnostic
----- stderr -----
");
// Ensure CLI takes precedence
case.write_file("knot.toml", "respect-ignore-files = true")?;
assert_cmd_snapshot!(case.command().arg("--no-respect-ignore-files"), @r"
success: false
exit_code: 1
----- stdout -----
error: invalid-syntax
--> <temp_dir>/test.py:1:2
|
1 | ~
| ^ Expected an expression
|
Found 1 diagnostic
----- stderr -----
");
Ok(())
}
/// Specifying an option on the CLI should take precedence over the same setting in the
/// project's configuration. Here, this is tested for the Python version.
#[test]
@@ -935,13 +1023,6 @@ fn check_specific_paths() -> anyhow::Result<()> {
success: false
exit_code: 1
----- stdout -----
error: lint:unresolved-import: Cannot resolve import `does_not_exist`
--> <temp_dir>/project/tests/test_main.py:2:8
|
2 | import does_not_exist # error: unresolved-import
| ^^^^^^^^^^^^^^
|
error: lint:division-by-zero: Cannot divide object of type `Literal[4]` by zero
--> <temp_dir>/project/main.py:2:5
|
@@ -958,6 +1039,13 @@ fn check_specific_paths() -> anyhow::Result<()> {
4 | print(z)
|
error: lint:unresolved-import: Cannot resolve import `does_not_exist`
--> <temp_dir>/project/tests/test_main.py:2:8
|
2 | import does_not_exist # error: unresolved-import
| ^^^^^^^^^^^^^^
|
Found 3 diagnostics
----- stderr -----
@@ -972,13 +1060,6 @@ fn check_specific_paths() -> anyhow::Result<()> {
success: false
exit_code: 1
----- stdout -----
error: lint:unresolved-import: Cannot resolve import `does_not_exist`
--> <temp_dir>/project/tests/test_main.py:2:8
|
2 | import does_not_exist # error: unresolved-import
| ^^^^^^^^^^^^^^
|
error: lint:unresolved-import: Cannot resolve import `main2`
--> <temp_dir>/project/other.py:2:6
|
@@ -988,6 +1069,13 @@ fn check_specific_paths() -> anyhow::Result<()> {
4 | print(z)
|
error: lint:unresolved-import: Cannot resolve import `does_not_exist`
--> <temp_dir>/project/tests/test_main.py:2:8
|
2 | import does_not_exist # error: unresolved-import
| ^^^^^^^^^^^^^^
|
Found 2 diagnostics
----- stderr -----

View File

@@ -11,7 +11,7 @@ use red_knot_python_semantic::register_lints;
use red_knot_python_semantic::types::check_types;
use ruff_db::diagnostic::{
create_parse_diagnostic, create_unsupported_syntax_diagnostic, Annotation, Diagnostic,
DiagnosticId, Severity, Span,
DiagnosticId, Severity, Span, SubDiagnostic,
};
use ruff_db::files::File;
use ruff_db::parsed::parsed_module;
@@ -20,8 +20,10 @@ use ruff_db::system::{SystemPath, SystemPathBuf};
use rustc_hash::FxHashSet;
use salsa::Durability;
use salsa::Setter;
use std::panic::{catch_unwind, AssertUnwindSafe, UnwindSafe};
use std::sync::Arc;
use thiserror::Error;
use tracing::error;
pub mod combine;
@@ -187,30 +189,66 @@ impl Project {
.map(IOErrorDiagnostic::to_diagnostic),
);
let result = Arc::new(std::sync::Mutex::new(diagnostics));
let inner_result = Arc::clone(&result);
let file_diagnostics = Arc::new(std::sync::Mutex::new(vec![]));
let db = db.clone();
let project_span = project_span.clone();
{
let file_diagnostics = Arc::clone(&file_diagnostics);
let db = db.clone();
let project_span = project_span.clone();
rayon::scope(move |scope| {
for file in &files {
let result = inner_result.clone();
let db = db.clone();
let project_span = project_span.clone();
rayon::scope(move |scope| {
for file in &files {
let result = Arc::clone(&file_diagnostics);
let db = db.clone();
let project_span = project_span.clone();
scope.spawn(move |_| {
let check_file_span =
tracing::debug_span!(parent: &project_span, "check_file", ?file);
let _entered = check_file_span.entered();
scope.spawn(move |_| {
let check_file_span =
tracing::debug_span!(parent: &project_span, "check_file", ?file);
let _entered = check_file_span.entered();
let file_diagnostics = check_file_impl(&db, file);
result.lock().unwrap().extend(file_diagnostics);
});
let file_diagnostics = check_file_impl(&db, file);
result.lock().unwrap().extend(file_diagnostics);
});
}
});
}
let mut file_diagnostics = Arc::into_inner(file_diagnostics)
.unwrap()
.into_inner()
.unwrap();
// We sort diagnostics in a way that keeps them in source order
// and grouped by file. After that, we fall back to severity
// (with fatal messages sorting before info messages) and then
// finally the diagnostic ID.
file_diagnostics.sort_by(|d1, d2| {
if let (Some(span1), Some(span2)) = (d1.primary_span(), d2.primary_span()) {
let order = span1
.file()
.path(db)
.as_str()
.cmp(span2.file().path(db).as_str());
if order.is_ne() {
return order;
}
if let (Some(range1), Some(range2)) = (span1.range(), span2.range()) {
let order = range1.start().cmp(&range2.start());
if order.is_ne() {
return order;
}
}
}
// Reverse so that, e.g., Fatal sorts before Info.
let order = d1.severity().cmp(&d2.severity()).reverse();
if order.is_ne() {
return order;
}
d1.id().cmp(&d2.id())
});
Arc::into_inner(result).unwrap().into_inner().unwrap()
diagnostics.extend(file_diagnostics);
diagnostics
}
pub(crate) fn check_file(self, db: &dyn Db, file: File) -> Vec<Diagnostic> {
@@ -435,7 +473,16 @@ fn check_file_impl(db: &dyn Db, file: File) -> Vec<Diagnostic> {
.map(|error| create_unsupported_syntax_diagnostic(file, error)),
);
diagnostics.extend(check_types(db.upcast(), file).into_iter().cloned());
{
let db = AssertUnwindSafe(db);
match catch(&**db, file, || check_types(db.upcast(), file)) {
Ok(Some(type_check_diagnostics)) => {
diagnostics.extend(type_check_diagnostics.into_iter().cloned());
}
Ok(None) => {}
Err(diagnostic) => diagnostics.push(diagnostic),
}
}
diagnostics.sort_unstable_by_key(|diagnostic| {
diagnostic
@@ -526,6 +573,45 @@ enum IOErrorKind {
SourceText(#[from] SourceTextError),
}
fn catch<F, R>(db: &dyn Db, file: File, f: F) -> Result<Option<R>, Diagnostic>
where
F: FnOnce() -> R + UnwindSafe,
{
match catch_unwind(|| {
// Ignore salsa errors
salsa::Cancelled::catch(f).ok()
}) {
Ok(result) => Ok(result),
Err(error) => {
let payload = if let Some(s) = error.downcast_ref::<&str>() {
Some((*s).to_string())
} else {
error.downcast_ref::<String>().cloned()
};
let message = if let Some(payload) = payload {
format!(
"Panicked while checking `{file}`: `{payload}`",
file = file.path(db)
)
} else {
format!("Panicked while checking `{file}`", file = { file.path(db) })
};
let mut diagnostic = Diagnostic::new(DiagnosticId::Panic, Severity::Fatal, message);
diagnostic.sub(SubDiagnostic::new(
Severity::Info,
"This indicates a bug in Red Knot.",
));
let report_message = "If you could open an issue at https://github.com/astral-sh/ruff/issues/new?title=%5Bred-knot%5D:%20panic we'd be very appreciative!";
diagnostic.sub(SubDiagnostic::new(Severity::Info, report_message));
Err(diagnostic)
}
}
}
#[cfg(test)]
mod tests {
use crate::db::tests::TestDb;

View File

@@ -32,6 +32,9 @@ pub struct Options {
#[serde(skip_serializing_if = "Option::is_none")]
pub terminal: Option<TerminalOptions>,
#[serde(skip_serializing_if = "Option::is_none")]
pub respect_ignore_files: Option<bool>,
}
impl Options {
@@ -133,7 +136,7 @@ impl Options {
pub(crate) fn to_settings(&self, db: &dyn Db) -> (Settings, Vec<OptionDiagnostic>) {
let (rules, diagnostics) = self.to_rule_selection(db);
let mut settings = Settings::new(rules);
let mut settings = Settings::new(rules, self.respect_ignore_files);
if let Some(terminal) = self.terminal.as_ref() {
settings.set_terminal(TerminalSettings {

View File

@@ -21,13 +21,16 @@ pub struct Settings {
rules: Arc<RuleSelection>,
terminal: TerminalSettings,
respect_ignore_files: bool,
}
impl Settings {
pub fn new(rules: RuleSelection) -> Self {
pub fn new(rules: RuleSelection, respect_ignore_files: Option<bool>) -> Self {
Self {
rules: Arc::new(rules),
terminal: TerminalSettings::default(),
respect_ignore_files: respect_ignore_files.unwrap_or(true),
}
}
@@ -35,6 +38,10 @@ impl Settings {
&self.rules
}
pub fn respect_ignore_files(&self) -> bool {
self.respect_ignore_files
}
pub fn to_rules(&self) -> Arc<RuleSelection> {
self.rules.clone()
}

View File

@@ -129,7 +129,11 @@ impl<'a> ProjectFilesWalker<'a> {
{
let mut paths = paths.into_iter();
let mut walker = db.system().walk_directory(paths.next()?.as_ref());
let mut walker = db
.system()
.walk_directory(paths.next()?.as_ref())
.standard_filters(db.project().settings(db).respect_ignore_files())
.ignore_hidden(false);
for path in paths {
walker = walker.add(path);

View File

@@ -38,8 +38,12 @@ bad_nesting: Literal[LiteralString] # error: [invalid-type-form]
```py
from typing_extensions import LiteralString
a: LiteralString[str] # error: [invalid-type-form]
b: LiteralString["foo"] # error: [invalid-type-form]
# error: [invalid-type-form]
a: LiteralString[str]
# error: [invalid-type-form]
# error: [unresolved-reference] "Name `foo` used when not defined"
b: LiteralString["foo"]
```
### As a base class

View File

@@ -89,9 +89,12 @@ python-version = "3.12"
Some of these are not subscriptable:
```py
from typing_extensions import Self, TypeAlias
from typing_extensions import Self, TypeAlias, TypeVar
X: TypeAlias[T] = int # error: [invalid-type-form]
T = TypeVar("T")
# error: [invalid-type-form] "Special form `typing.TypeAlias` expected no type parameter"
X: TypeAlias[T] = int
class Foo[T]:
# error: [invalid-type-form] "Special form `typing.Self` expected no type parameter"

View File

@@ -11,8 +11,6 @@ from typing_extensions import Final, Required, NotRequired, ReadOnly, TypedDict
X: Final = 42
Y: Final[int] = 42
# TODO: `TypedDict` is actually valid as a base
# error: [invalid-base]
class Bar(TypedDict):
x: Required[int]
y: NotRequired[str]

View File

@@ -19,7 +19,7 @@ async def elements(n):
yield n
async def f():
# error: 19 [invalid-syntax] "cannot use an asynchronous comprehension outside of an asynchronous function on Python 3.10 (syntax was added in 3.11)"
# error: 19 [invalid-syntax] "cannot use an asynchronous comprehension inside of a synchronous comprehension on Python 3.10 (syntax was added in 3.11)"
return {n: [x async for x in elements(n)] for n in range(3)}
```

View File

@@ -275,14 +275,16 @@ c: C[int] = C[int]()
reveal_type(c.method("string")) # revealed: Literal["string"]
```
## Cyclic class definition
## Cyclic class definitions
### F-bounded quantification
A class can use itself as the type parameter of one of its superclasses. (This is also known as the
[curiously recurring template pattern][crtp] or [F-bounded quantification][f-bound].)
Here, `Sub` is not a generic class, since it fills its superclass's type parameter (with itself).
#### In a stub file
`stub.pyi`:
Here, `Sub` is not a generic class, since it fills its superclass's type parameter (with itself).
```pyi
class Base[T]: ...
@@ -291,9 +293,9 @@ class Sub(Base[Sub]): ...
reveal_type(Sub) # revealed: Literal[Sub]
```
A similar case can work in a non-stub file, if forward references are stringified:
#### With string forward references
`string_annotation.py`:
A similar case can work in a non-stub file, if forward references are stringified:
```py
class Base[T]: ...
@@ -302,9 +304,9 @@ class Sub(Base["Sub"]): ...
reveal_type(Sub) # revealed: Literal[Sub]
```
In a non-stub file, without stringified forward references, this raises a `NameError`:
#### Without string forward references
`bare_annotation.py`:
In a non-stub file, without stringified forward references, this raises a `NameError`:
```py
class Base[T]: ...
@@ -313,11 +315,23 @@ class Base[T]: ...
class Sub(Base[Sub]): ...
```
## Another cyclic case
### Cyclic inheritance as a generic parameter
```pyi
class Derived[T](list[Derived[T]]): ...
```
### Direct cyclic inheritance
Inheritance that would result in a cyclic MRO is detected as an error.
```py
# error: [cyclic-class-definition]
class C[T](C): ...
# error: [cyclic-class-definition]
class D[T](D[int]): ...
```
[crtp]: https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
[f-bound]: https://en.wikipedia.org/wiki/Bounded_quantification#F-bounded_quantification

View File

@@ -7,7 +7,7 @@ Builtin symbols can be explicitly imported:
```py
import builtins
reveal_type(builtins.chr) # revealed: def chr(i: int | SupportsIndex, /) -> str
reveal_type(builtins.chr) # revealed: def chr(i: SupportsIndex, /) -> str
```
## Implicit use of builtin
@@ -15,7 +15,7 @@ reveal_type(builtins.chr) # revealed: def chr(i: int | SupportsIndex, /) -> str
Or used implicitly:
```py
reveal_type(chr) # revealed: def chr(i: int | SupportsIndex, /) -> str
reveal_type(chr) # revealed: def chr(i: SupportsIndex, /) -> str
reveal_type(str) # revealed: Literal[str]
```

View File

@@ -53,6 +53,25 @@ class B(A): ...
reveal_type(B.__class__) # revealed: Literal[M]
```
## Linear inheritance with PEP 695 generic class
The same is true if the base with the metaclass is a generic class.
```toml
[environment]
python-version = "3.13"
```
```py
class M(type): ...
class A[T](metaclass=M): ...
class B(A): ...
class C(A[int]): ...
reveal_type(B.__class__) # revealed: Literal[M]
reveal_type(C.__class__) # revealed: Literal[M]
```
## Conflict (1)
The metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its

View File

@@ -191,8 +191,8 @@ reveal_type(AA.__mro__) # revealed: tuple[Literal[AA], Literal[Z], Unknown, Lit
## `__bases__` includes a `Union`
We don't support union types in a class's bases; a base must resolve to a single `ClassLiteralType`.
If we find a union type in a class's bases, we infer the class's `__mro__` as being
We don't support union types in a class's bases; a base must resolve to a single `ClassType`. If we
find a union type in a class's bases, we infer the class's `__mro__` as being
`[<class>, Unknown, object]`, the same as for MROs that cause errors at runtime.
```py

View File

@@ -0,0 +1,25 @@
# repro interned panic
## before
```toml
log = "salsa=trace,red_knot_test,ruff_db=trace,red_knot_ide=trace,red_knot_project=trace"
[environment]
python-version = "3.9"
```
```py
None
```
## after
```toml
log = "salsa=trace,red_knot_test,ruff_db=trace,red_knot_ide=trace,red_knot_project=trace"
[environment]
python-version = "3.10"
```
```py
None
```

View File

@@ -230,7 +230,7 @@ And it is also an error to use `Protocol` in type expressions:
def f(
x: Protocol, # error: [invalid-type-form] "`typing.Protocol` is not allowed in type expressions"
y: type[Protocol], # TODO: should emit `[invalid-type-form]` here too
) -> None:
):
reveal_type(x) # revealed: Unknown
# TODO: should be `type[Unknown]`
@@ -266,9 +266,7 @@ class Bar(typing_extensions.Protocol):
static_assert(typing_extensions.is_protocol(Foo))
static_assert(typing_extensions.is_protocol(Bar))
# TODO: should pass
static_assert(is_equivalent_to(Foo, Bar)) # error: [static-assert-error]
static_assert(is_equivalent_to(Foo, Bar))
```
The same goes for `typing.runtime_checkable` and `typing_extensions.runtime_checkable`:
@@ -284,9 +282,7 @@ class RuntimeCheckableBar(typing_extensions.Protocol):
static_assert(typing_extensions.is_protocol(RuntimeCheckableFoo))
static_assert(typing_extensions.is_protocol(RuntimeCheckableBar))
# TODO: should pass
static_assert(is_equivalent_to(RuntimeCheckableFoo, RuntimeCheckableBar)) # error: [static-assert-error]
static_assert(is_equivalent_to(RuntimeCheckableFoo, RuntimeCheckableBar))
# These should not error because the protocols are decorated with `@runtime_checkable`
isinstance(object(), RuntimeCheckableFoo)
@@ -488,21 +484,20 @@ class HasX(Protocol):
class Foo:
x: int
# TODO: these should pass
static_assert(is_subtype_of(Foo, HasX)) # error: [static-assert-error]
static_assert(is_assignable_to(Foo, HasX)) # error: [static-assert-error]
static_assert(is_subtype_of(Foo, HasX))
static_assert(is_assignable_to(Foo, HasX))
class FooSub(Foo): ...
# TODO: these should pass
static_assert(is_subtype_of(FooSub, HasX)) # error: [static-assert-error]
static_assert(is_assignable_to(FooSub, HasX)) # error: [static-assert-error]
static_assert(is_subtype_of(FooSub, HasX))
static_assert(is_assignable_to(FooSub, HasX))
class Bar:
x: str
static_assert(not is_subtype_of(Bar, HasX))
static_assert(not is_assignable_to(Bar, HasX))
# TODO: these should pass
static_assert(not is_subtype_of(Bar, HasX)) # error: [static-assert-error]
static_assert(not is_assignable_to(Bar, HasX)) # error: [static-assert-error]
class Baz:
y: int
@@ -524,14 +519,16 @@ class A:
def x(self) -> int:
return 42
static_assert(not is_subtype_of(A, HasX))
static_assert(not is_assignable_to(A, HasX))
# TODO: these should pass
static_assert(not is_subtype_of(A, HasX)) # error: [static-assert-error]
static_assert(not is_assignable_to(A, HasX)) # error: [static-assert-error]
class B:
x: Final = 42
static_assert(not is_subtype_of(A, HasX))
static_assert(not is_assignable_to(A, HasX))
# TODO: these should pass
static_assert(not is_subtype_of(A, HasX)) # error: [static-assert-error]
static_assert(not is_assignable_to(A, HasX)) # error: [static-assert-error]
class IntSub(int): ...
@@ -541,8 +538,10 @@ class C:
# due to invariance, a type is only a subtype of `HasX`
# if its `x` attribute is of type *exactly* `int`:
# a subclass of `int` does not satisfy the interface
static_assert(not is_subtype_of(C, HasX))
static_assert(not is_assignable_to(C, HasX))
#
# TODO: these should pass
static_assert(not is_subtype_of(C, HasX)) # error: [static-assert-error]
static_assert(not is_assignable_to(C, HasX)) # error: [static-assert-error]
```
All attributes on frozen dataclasses and namedtuples are immutable, so instances of these classes
@@ -556,22 +555,23 @@ from typing import NamedTuple
class MutableDataclass:
x: int
# TODO: these should pass
static_assert(is_subtype_of(MutableDataclass, HasX)) # error: [static-assert-error]
static_assert(is_assignable_to(MutableDataclass, HasX)) # error: [static-assert-error]
static_assert(is_subtype_of(MutableDataclass, HasX))
static_assert(is_assignable_to(MutableDataclass, HasX))
@dataclass(frozen=True)
class ImmutableDataclass:
x: int
static_assert(not is_subtype_of(ImmutableDataclass, HasX))
static_assert(not is_assignable_to(ImmutableDataclass, HasX))
# TODO: these should pass
static_assert(not is_subtype_of(ImmutableDataclass, HasX)) # error: [static-assert-error]
static_assert(not is_assignable_to(ImmutableDataclass, HasX)) # error: [static-assert-error]
class NamedTupleWithX(NamedTuple):
x: int
static_assert(not is_subtype_of(NamedTupleWithX, HasX))
static_assert(not is_assignable_to(NamedTupleWithX, HasX))
# TODO: these should pass
static_assert(not is_subtype_of(NamedTupleWithX, HasX)) # error: [static-assert-error]
static_assert(not is_assignable_to(NamedTupleWithX, HasX)) # error: [static-assert-error]
```
However, a type with a read-write property `x` *does* satisfy the `HasX` protocol. The `HasX`
@@ -590,9 +590,8 @@ class XProperty:
def x(self, x: int) -> None:
self._x = x**2
# TODO: these should pass
static_assert(is_subtype_of(XProperty, HasX)) # error: [static-assert-error]
static_assert(is_assignable_to(XProperty, HasX)) # error: [static-assert-error]
static_assert(is_subtype_of(XProperty, HasX))
static_assert(is_assignable_to(XProperty, HasX))
```
Attribute members on protocol classes are allowed to have default values, just like instance
@@ -717,9 +716,8 @@ from typing import Protocol
class UniversalSet(Protocol): ...
# TODO: these should pass
static_assert(is_assignable_to(object, UniversalSet)) # error: [static-assert-error]
static_assert(is_subtype_of(object, UniversalSet)) # error: [static-assert-error]
static_assert(is_assignable_to(object, UniversalSet))
static_assert(is_subtype_of(object, UniversalSet))
```
Which means that `UniversalSet` here is in fact an equivalent type to `object`:
@@ -727,8 +725,7 @@ Which means that `UniversalSet` here is in fact an equivalent type to `object`:
```py
from knot_extensions import is_equivalent_to
# TODO: this should pass
static_assert(is_equivalent_to(UniversalSet, object)) # error: [static-assert-error]
static_assert(is_equivalent_to(UniversalSet, object))
```
`object` is a subtype of certain other protocols too. Since all fully static types (whether nominal
@@ -739,17 +736,16 @@ means that these protocols are also equivalent to `UniversalSet` and `object`:
class SupportsStr(Protocol):
def __str__(self) -> str: ...
# TODO: these should pass
static_assert(is_equivalent_to(SupportsStr, UniversalSet)) # error: [static-assert-error]
static_assert(is_equivalent_to(SupportsStr, object)) # error: [static-assert-error]
static_assert(is_equivalent_to(SupportsStr, UniversalSet))
static_assert(is_equivalent_to(SupportsStr, object))
class SupportsClass(Protocol):
__class__: type
@property
def __class__(self) -> type: ...
# TODO: these should pass
static_assert(is_equivalent_to(SupportsClass, UniversalSet)) # error: [static-assert-error]
static_assert(is_equivalent_to(SupportsClass, SupportsStr)) # error: [static-assert-error]
static_assert(is_equivalent_to(SupportsClass, object)) # error: [static-assert-error]
static_assert(is_equivalent_to(SupportsClass, UniversalSet))
static_assert(is_equivalent_to(SupportsClass, SupportsStr))
static_assert(is_equivalent_to(SupportsClass, object))
```
If a protocol contains members that are not defined on `object`, then that protocol will (like all
@@ -786,8 +782,7 @@ class HasX(Protocol):
class AlsoHasX(Protocol):
x: int
# TODO: this should pass
static_assert(is_equivalent_to(HasX, AlsoHasX)) # error: [static-assert-error]
static_assert(is_equivalent_to(HasX, AlsoHasX))
```
And unions containing equivalent protocols are recognised as equivalent, even when the order is not
@@ -803,8 +798,7 @@ class AlsoHasY(Protocol):
class A: ...
class B: ...
# TODO: this should pass
static_assert(is_equivalent_to(A | HasX | B | HasY, B | AlsoHasY | AlsoHasX | A)) # error: [static-assert-error]
static_assert(is_equivalent_to(A | HasX | B | HasY, B | AlsoHasY | AlsoHasX | A))
```
## Intersections of protocols
@@ -882,9 +876,9 @@ from knot_extensions import is_subtype_of, is_assignable_to, static_assert, Type
class HasX(Protocol):
x: int
# TODO: these should pass
# TODO: this should pass
static_assert(is_subtype_of(TypeOf[module], HasX)) # error: [static-assert-error]
static_assert(is_assignable_to(TypeOf[module], HasX)) # error: [static-assert-error]
static_assert(is_assignable_to(TypeOf[module], HasX))
class ExplicitProtocolSubtype(HasX, Protocol):
y: int
@@ -896,9 +890,8 @@ class ImplicitProtocolSubtype(Protocol):
x: int
y: str
# TODO: these should pass
static_assert(is_subtype_of(ImplicitProtocolSubtype, HasX)) # error: [static-assert-error]
static_assert(is_assignable_to(ImplicitProtocolSubtype, HasX)) # error: [static-assert-error]
static_assert(is_subtype_of(ImplicitProtocolSubtype, HasX))
static_assert(is_assignable_to(ImplicitProtocolSubtype, HasX))
class Meta(type):
x: int
@@ -933,23 +926,24 @@ def f(obj: ClassVarXProto):
class InstanceAttrX:
x: int
static_assert(not is_assignable_to(InstanceAttrX, ClassVarXProto))
static_assert(not is_subtype_of(InstanceAttrX, ClassVarXProto))
# TODO: these should pass
static_assert(not is_assignable_to(InstanceAttrX, ClassVarXProto)) # error: [static-assert-error]
static_assert(not is_subtype_of(InstanceAttrX, ClassVarXProto)) # error: [static-assert-error]
class PropertyX:
@property
def x(self) -> int:
return 42
static_assert(not is_assignable_to(PropertyX, ClassVarXProto))
static_assert(not is_subtype_of(PropertyX, ClassVarXProto))
# TODO: these should pass
static_assert(not is_assignable_to(PropertyX, ClassVarXProto)) # error: [static-assert-error]
static_assert(not is_subtype_of(PropertyX, ClassVarXProto)) # error: [static-assert-error]
class ClassVarX:
x: ClassVar[int] = 42
# TODO: these should pass
static_assert(is_assignable_to(ClassVarX, ClassVarXProto)) # error: [static-assert-error]
static_assert(is_subtype_of(ClassVarX, ClassVarXProto)) # error: [static-assert-error]
static_assert(is_assignable_to(ClassVarX, ClassVarXProto))
static_assert(is_subtype_of(ClassVarX, ClassVarXProto))
```
This is mentioned by the
@@ -976,18 +970,16 @@ class HasXProperty(Protocol):
class XAttr:
x: int
# TODO: these should pass
static_assert(is_subtype_of(XAttr, HasXProperty)) # error: [static-assert-error]
static_assert(is_assignable_to(XAttr, HasXProperty)) # error: [static-assert-error]
static_assert(is_subtype_of(XAttr, HasXProperty))
static_assert(is_assignable_to(XAttr, HasXProperty))
class XReadProperty:
@property
def x(self) -> int:
return 42
# TODO: these should pass
static_assert(is_subtype_of(XReadProperty, HasXProperty)) # error: [static-assert-error]
static_assert(is_assignable_to(XReadProperty, HasXProperty)) # error: [static-assert-error]
static_assert(is_subtype_of(XReadProperty, HasXProperty))
static_assert(is_assignable_to(XReadProperty, HasXProperty))
class XReadWriteProperty:
@property
@@ -997,22 +989,20 @@ class XReadWriteProperty:
@x.setter
def x(self, val: int) -> None: ...
# TODO: these should pass
static_assert(is_subtype_of(XReadWriteProperty, HasXProperty)) # error: [static-assert-error]
static_assert(is_assignable_to(XReadWriteProperty, HasXProperty)) # error: [static-assert-error]
static_assert(is_subtype_of(XReadWriteProperty, HasXProperty))
static_assert(is_assignable_to(XReadWriteProperty, HasXProperty))
class XClassVar:
x: ClassVar[int] = 42
static_assert(is_subtype_of(XClassVar, HasXProperty)) # error: [static-assert-error]
static_assert(is_assignable_to(XClassVar, HasXProperty)) # error: [static-assert-error]
static_assert(is_subtype_of(XClassVar, HasXProperty))
static_assert(is_assignable_to(XClassVar, HasXProperty))
class XFinal:
x: Final = 42
# TODO: these should pass
static_assert(is_subtype_of(XFinal, HasXProperty)) # error: [static-assert-error]
static_assert(is_assignable_to(XFinal, HasXProperty)) # error: [static-assert-error]
static_assert(is_subtype_of(XFinal, HasXProperty))
static_assert(is_assignable_to(XFinal, HasXProperty))
```
A read-only property on a protocol, unlike a mutable attribute, is covariant: `XSub` in the below
@@ -1025,9 +1015,8 @@ class MyInt(int): ...
class XSub:
x: MyInt
# TODO: these should pass
static_assert(is_subtype_of(XSub, HasXProperty)) # error: [static-assert-error]
static_assert(is_assignable_to(XSub, HasXProperty)) # error: [static-assert-error]
static_assert(is_subtype_of(XSub, HasXProperty))
static_assert(is_assignable_to(XSub, HasXProperty))
```
A read/write property on a protocol, where the getter returns the same type that the setter takes,
@@ -1043,17 +1032,17 @@ class HasMutableXProperty(Protocol):
class XAttr:
x: int
# TODO: these should pass
static_assert(is_subtype_of(XAttr, HasXProperty)) # error: [static-assert-error]
static_assert(is_assignable_to(XAttr, HasXProperty)) # error: [static-assert-error]
static_assert(is_subtype_of(XAttr, HasXProperty))
static_assert(is_assignable_to(XAttr, HasXProperty))
class XReadProperty:
@property
def x(self) -> int:
return 42
static_assert(not is_subtype_of(XReadProperty, HasXProperty))
static_assert(not is_assignable_to(XReadProperty, HasXProperty))
# TODO: these should pass
static_assert(not is_subtype_of(XReadProperty, HasXProperty)) # error: [static-assert-error]
static_assert(not is_assignable_to(XReadProperty, HasXProperty)) # error: [static-assert-error]
class XReadWriteProperty:
@property
@@ -1063,15 +1052,15 @@ class XReadWriteProperty:
@x.setter
def x(self, val: int) -> None: ...
# TODO: these should pass
static_assert(is_subtype_of(XReadWriteProperty, HasXProperty)) # error: [static-assert-error]
static_assert(is_assignable_to(XReadWriteProperty, HasXProperty)) # error: [static-assert-error]
static_assert(is_subtype_of(XReadWriteProperty, HasXProperty))
static_assert(is_assignable_to(XReadWriteProperty, HasXProperty))
class XSub:
x: MyInt
static_assert(not is_subtype_of(XSub, HasXProperty))
static_assert(not is_assignable_to(XSub, HasXProperty))
# TODO: should pass
static_assert(not is_subtype_of(XSub, HasXProperty)) # error: [static-assert-error]
static_assert(not is_assignable_to(XSub, HasXProperty)) # error: [static-assert-error]
```
A protocol with a read/write property `x` is exactly equivalent to a protocol with a mutable
@@ -1083,16 +1072,13 @@ from knot_extensions import is_equivalent_to
class HasMutableXAttr(Protocol):
x: int
# TODO: this should pass
static_assert(is_equivalent_to(HasMutableXAttr, HasMutableXProperty)) # error: [static-assert-error]
static_assert(is_equivalent_to(HasMutableXAttr, HasMutableXProperty))
# TODO: these should pass
static_assert(is_subtype_of(HasMutableXAttr, HasXProperty)) # error: [static-assert-error]
static_assert(is_assignable_to(HasMutableXAttr, HasXProperty)) # error: [static-assert-error]
static_assert(is_subtype_of(HasMutableXAttr, HasXProperty))
static_assert(is_assignable_to(HasMutableXAttr, HasXProperty))
# TODO: these should pass
static_assert(is_subtype_of(HasMutableXProperty, HasXProperty)) # error: [static-assert-error]
static_assert(is_assignable_to(HasMutableXProperty, HasXProperty)) # error: [static-assert-error]
static_assert(is_subtype_of(HasMutableXProperty, HasXProperty))
static_assert(is_assignable_to(HasMutableXProperty, HasXProperty))
```
A read/write property on a protocol, where the setter accepts a subtype of the type returned by the
@@ -1119,9 +1105,8 @@ class HasAsymmetricXProperty(Protocol):
class XAttr:
x: int
# TODO: these should pass
static_assert(is_subtype_of(XAttr, HasAsymmetricXProperty)) # error: [static-assert-error]
static_assert(is_assignable_to(XAttr, HasAsymmetricXProperty)) # error: [static-assert-error]
static_assert(is_subtype_of(XAttr, HasAsymmetricXProperty))
static_assert(is_assignable_to(XAttr, HasAsymmetricXProperty))
```
The end conclusion of this is that the getter-returned type of a property is always covariant and
@@ -1132,9 +1117,8 @@ regular mutable attribute, where the implied getter-returned and setter-accepted
class XAttrSub:
x: MyInt
# TODO: these should pass
static_assert(is_subtype_of(XAttrSub, HasAsymmetricXProperty)) # error: [static-assert-error]
static_assert(is_assignable_to(XAttrSub, HasAsymmetricXProperty)) # error: [static-assert-error]
static_assert(is_subtype_of(XAttrSub, HasAsymmetricXProperty))
static_assert(is_assignable_to(XAttrSub, HasAsymmetricXProperty))
class MyIntSub(MyInt):
pass
@@ -1142,8 +1126,9 @@ class MyIntSub(MyInt):
class XAttrSubSub:
x: MyIntSub
static_assert(not is_subtype_of(XAttrSubSub, HasAsymmetricXProperty))
static_assert(not is_assignable_to(XAttrSubSub, HasAsymmetricXProperty))
# TODO: should pass
static_assert(not is_subtype_of(XAttrSubSub, HasAsymmetricXProperty)) # error: [static-assert-error]
static_assert(not is_assignable_to(XAttrSubSub, HasAsymmetricXProperty)) # error: [static-assert-error]
```
An asymmetric property on a protocol can also be satisfied by an asymmetric property on a nominal
@@ -1159,9 +1144,8 @@ class XAsymmetricProperty:
@x.setter
def x(self, x: int) -> None: ...
# TODO: these should pass
static_assert(is_subtype_of(XAsymmetricProperty, HasAsymmetricXProperty)) # error: [static-assert-error]
static_assert(is_assignable_to(XAsymmetricProperty, HasAsymmetricXProperty)) # error: [static-assert-error]
static_assert(is_subtype_of(XAsymmetricProperty, HasAsymmetricXProperty))
static_assert(is_assignable_to(XAsymmetricProperty, HasAsymmetricXProperty))
```
A custom descriptor attribute on the nominal class will also suffice:
@@ -1176,9 +1160,8 @@ class Descriptor:
class XCustomDescriptor:
x: Descriptor = Descriptor()
# TODO: these should pass
static_assert(is_subtype_of(XCustomDescriptor, HasAsymmetricXProperty)) # error: [static-assert-error]
static_assert(is_assignable_to(XCustomDescriptor, HasAsymmetricXProperty)) # error: [static-assert-error]
static_assert(is_subtype_of(XCustomDescriptor, HasAsymmetricXProperty))
static_assert(is_assignable_to(XCustomDescriptor, HasAsymmetricXProperty))
```
Moreover, a read-only property on a protocol can be satisfied by a nominal class that defines a
@@ -1191,19 +1174,20 @@ class HasGetAttr:
def __getattr__(self, attr: str) -> int:
return 42
# TODO: these should pass
static_assert(is_subtype_of(HasGetAttr, HasXProperty)) # error: [static-assert-error]
static_assert(is_assignable_to(HasGetAttr, HasXProperty)) # error: [static-assert-error]
static_assert(is_subtype_of(HasGetAttr, HasXProperty))
static_assert(is_assignable_to(HasGetAttr, HasXProperty))
static_assert(not is_subtype_of(HasGetAttr, HasMutableXAttr))
static_assert(not is_subtype_of(HasGetAttr, HasMutableXAttr))
# TODO: these should pass
static_assert(not is_subtype_of(HasGetAttr, HasMutableXAttr)) # error: [static-assert-error]
static_assert(not is_subtype_of(HasGetAttr, HasMutableXAttr)) # error: [static-assert-error]
class HasGetAttrWithUnsuitableReturn:
def __getattr__(self, attr: str) -> tuple[int, int]:
return (1, 2)
static_assert(not is_subtype_of(HasGetAttrWithUnsuitableReturn, HasXProperty))
static_assert(not is_assignable_to(HasGetAttrWithUnsuitableReturn, HasXProperty))
# TODO: these should pass
static_assert(not is_subtype_of(HasGetAttrWithUnsuitableReturn, HasXProperty)) # error: [static-assert-error]
static_assert(not is_assignable_to(HasGetAttrWithUnsuitableReturn, HasXProperty)) # error: [static-assert-error]
class HasGetAttrAndSetAttr:
def __getattr__(self, attr: str) -> MyInt:
@@ -1211,9 +1195,10 @@ class HasGetAttrAndSetAttr:
def __setattr__(self, attr: str, value: int) -> None: ...
static_assert(is_subtype_of(HasGetAttrAndSetAttr, HasXProperty))
static_assert(is_assignable_to(HasGetAttrAndSetAttr, HasXProperty))
# TODO: these should pass
static_assert(is_subtype_of(HasGetAttrAndSetAttr, HasXProperty)) # error: [static-assert-error]
static_assert(is_assignable_to(HasGetAttrAndSetAttr, HasXProperty)) # error: [static-assert-error]
static_assert(is_subtype_of(HasGetAttrAndSetAttr, XAsymmetricProperty)) # error: [static-assert-error]
static_assert(is_assignable_to(HasGetAttrAndSetAttr, XAsymmetricProperty)) # error: [static-assert-error]
```
@@ -1314,9 +1299,12 @@ class FalsyFooSubclass(FalsyFoo, Protocol):
y: str
def g(a: Truthy, b: FalsyFoo, c: FalsyFooSubclass):
reveal_type(bool(a)) # revealed: Literal[True]
reveal_type(bool(b)) # revealed: Literal[False]
reveal_type(bool(c)) # revealed: Literal[False]
# TODO should be `Literal[True]
reveal_type(bool(a)) # revealed: bool
# TODO should be `Literal[False]
reveal_type(bool(b)) # revealed: bool
# TODO should be `Literal[False]
reveal_type(bool(c)) # revealed: bool
```
It is not sufficient for a protocol to have a callable `__bool__` instance member that returns
@@ -1363,12 +1351,12 @@ from knot_extensions import is_subtype_of, is_assignable_to
class NominalWithX:
x: int = 42
# TODO: these should pass
static_assert(is_assignable_to(NominalWithX, FullyStatic)) # error: [static-assert-error]
static_assert(is_assignable_to(NominalWithX, NotFullyStatic)) # error: [static-assert-error]
static_assert(is_subtype_of(NominalWithX, FullyStatic)) # error: [static-assert-error]
static_assert(is_assignable_to(NominalWithX, FullyStatic))
static_assert(is_assignable_to(NominalWithX, NotFullyStatic))
static_assert(is_subtype_of(NominalWithX, FullyStatic))
static_assert(not is_subtype_of(NominalWithX, NotFullyStatic))
# TODO: this should pass
static_assert(not is_subtype_of(NominalWithX, NotFullyStatic)) # error: [static-assert-error]
```
Empty protocols are fully static; this follows from the fact that an empty protocol is equivalent to

View File

@@ -13,7 +13,7 @@ if returns_bool():
chr: int = 1
def f():
reveal_type(chr) # revealed: int | (def chr(i: int | SupportsIndex, /) -> str)
reveal_type(chr) # revealed: int | (def chr(i: SupportsIndex, /) -> str)
```
## Conditionally global or builtin, with annotation
@@ -28,5 +28,5 @@ if returns_bool():
chr: int = 1
def f():
reveal_type(chr) # revealed: int | (def chr(i: int | SupportsIndex, /) -> str)
reveal_type(chr) # revealed: int | (def chr(i: SupportsIndex, /) -> str)
```

View File

@@ -16,7 +16,7 @@ mdtest path: crates/red_knot_python_semantic/resources/mdtest/diagnostics/semant
2 | yield n
3 |
4 | async def f():
5 | # error: 19 [invalid-syntax] "cannot use an asynchronous comprehension outside of an asynchronous function on Python 3.10 (syntax was added in 3.11)"
5 | # error: 19 [invalid-syntax] "cannot use an asynchronous comprehension inside of a synchronous comprehension on Python 3.10 (syntax was added in 3.11)"
6 | return {n: [x async for x in elements(n)] for n in range(3)}
7 | async def test():
8 | return [[x async for x in elements(n)] async for n in range(3)]
@@ -36,9 +36,9 @@ error: invalid-syntax
--> /src/mdtest_snippet.py:6:19
|
4 | async def f():
5 | # error: 19 [invalid-syntax] "cannot use an asynchronous comprehension outside of an asynchronous function on Python 3.10 (syntax...
5 | # error: 19 [invalid-syntax] "cannot use an asynchronous comprehension inside of a synchronous comprehension on Python 3.10 (synt...
6 | return {n: [x async for x in elements(n)] for n in range(3)}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot use an asynchronous comprehension outside of an asynchronous function on Python 3.10 (syntax was added in 3.11)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot use an asynchronous comprehension inside of a synchronous comprehension on Python 3.10 (syntax was added in 3.11)
7 | async def test():
8 | return [[x async for x in elements(n)] async for n in range(3)]
|

View File

@@ -0,0 +1,27 @@
# `TypedDict`
We do not support `TypedDict`s yet. This test mainly exists to make sure that we do not emit any
errors for the definition of a `TypedDict`.
```py
from typing_extensions import TypedDict, Required
class Person(TypedDict):
name: str
age: int | None
# TODO: This should not be an error:
# error: [invalid-assignment]
alice: Person = {"name": "Alice", "age": 30}
# Alternative syntax
Message = TypedDict("Message", {"id": Required[int], "content": str}, total=False)
msg = Message(id=1, content="Hello")
# No errors for yet-unsupported features (`closed`):
OtherMessage = TypedDict("OtherMessage", {"id": int, "content": str}, closed=True)
reveal_type(Person.__required_keys__) # revealed: @Todo(TypedDict)
reveal_type(Message.__required_keys__) # revealed: @Todo(TypedDict)
```

View File

@@ -1,3 +1,4 @@
Expression # cycle panic (signature_)
Tanjun # cycle panic (signature_)
aiohttp # missing expression ID
alerta # missing expression ID

View File

@@ -1,5 +1,4 @@
AutoSplit
Expression
PyGithub
PyWinCtl
SinbadCogs

View File

@@ -1114,7 +1114,7 @@ mod tests {
fn assert_bound_string_symbol<'db>(db: &'db dyn Db, symbol: Symbol<'db>) {
assert!(matches!(
symbol,
Symbol::Type(Type::Instance(_), Boundness::Bound)
Symbol::Type(Type::NominalInstance(_), Boundness::Bound)
));
assert_eq!(symbol.expect_type(), KnownClass::Str.to_instance(db));
}

View File

@@ -1,3 +1,4 @@
use instance::{Protocol, ProtocolInstanceType};
use itertools::Either;
use std::slice::Iter;
@@ -49,10 +50,8 @@ use crate::types::mro::{Mro, MroError, MroIterator};
pub(crate) use crate::types::narrow::infer_narrowing_constraint;
use crate::types::signatures::{Parameter, ParameterForm, Parameters};
use crate::{Db, FxOrderSet, Module, Program};
pub(crate) use class::{
Class, ClassLiteralType, ClassType, GenericAlias, GenericClass, KnownClass, NonGenericClass,
};
pub(crate) use instance::InstanceType;
pub(crate) use class::{ClassLiteral, ClassType, GenericAlias, KnownClass};
pub(crate) use instance::NominalInstanceType;
pub(crate) use known_instance::KnownInstanceType;
mod builder;
@@ -470,14 +469,16 @@ pub enum Type<'db> {
/// A specific module object
ModuleLiteral(ModuleLiteralType<'db>),
/// A specific class object
ClassLiteral(ClassLiteralType<'db>),
ClassLiteral(ClassLiteral<'db>),
/// A specialization of a generic class
GenericAlias(GenericAlias<'db>),
/// The set of all class objects that are subclasses of the given class (C), spelled `type[C]`.
SubclassOf(SubclassOfType<'db>),
/// The set of Python objects with the given class in their __class__'s method resolution order.
/// Construct this variant using the `Type::instance` constructor function.
Instance(InstanceType<'db>),
NominalInstance(NominalInstanceType<'db>),
/// The set of Python objects that conform to the interface described by a given protocol.
ProtocolInstance(ProtocolInstanceType<'db>),
/// A single Python object that requires special treatment in the type system
KnownInstance(KnownInstanceType<'db>),
/// An instance of `builtins.property`
@@ -512,7 +513,7 @@ pub enum Type<'db> {
TypeVar(TypeVarInstance<'db>),
// A bound super object like `super()` or `super(A, A())`
// This type doesn't handle an unbound super object like `super(A)`; for that we just use
// a `Type::Instance` of `builtins.super`.
// a `Type::NominalInstance` of `builtins.super`.
BoundSuper(BoundSuperType<'db>),
// TODO protocols, overloads, generics
}
@@ -539,18 +540,23 @@ impl<'db> Type<'db> {
matches!(self, Type::Never)
}
/// Returns `true` if `self` is [`Type::Callable`].
pub const fn is_callable_type(&self) -> bool {
matches!(self, Type::Callable(..))
}
fn is_none(&self, db: &'db dyn Db) -> bool {
self.into_instance()
self.into_nominal_instance()
.is_some_and(|instance| instance.class().is_known(db, KnownClass::NoneType))
}
fn is_bool(&self, db: &'db dyn Db) -> bool {
self.into_instance()
self.into_nominal_instance()
.is_some_and(|instance| instance.class().is_known(db, KnownClass::Bool))
}
pub fn is_notimplemented(&self, db: &'db dyn Db) -> bool {
self.into_instance().is_some_and(|instance| {
self.into_nominal_instance().is_some_and(|instance| {
instance
.class()
.is_known(db, KnownClass::NotImplementedType)
@@ -558,7 +564,7 @@ impl<'db> Type<'db> {
}
pub fn is_object(&self, db: &'db dyn Db) -> bool {
self.into_instance()
self.into_nominal_instance()
.is_some_and(|instance| instance.class().is_object(db))
}
@@ -580,7 +586,7 @@ impl<'db> Type<'db> {
| Self::BooleanLiteral(_)
| Self::BytesLiteral(_)
| Self::FunctionLiteral(_)
| Self::Instance(_)
| Self::NominalInstance(_)
| Self::ModuleLiteral(_)
| Self::ClassLiteral(_)
| Self::KnownInstance(_)
@@ -664,10 +670,12 @@ impl<'db> Type<'db> {
.iter()
.any(|ty| ty.contains_todo(db))
}
Self::ProtocolInstance(protocol) => protocol.contains_todo(),
}
}
pub const fn into_class_literal(self) -> Option<ClassLiteralType<'db>> {
pub const fn into_class_literal(self) -> Option<ClassLiteral<'db>> {
match self {
Type::ClassLiteral(class_type) => Some(class_type),
_ => None,
@@ -675,7 +683,7 @@ impl<'db> Type<'db> {
}
#[track_caller]
pub fn expect_class_literal(self) -> ClassLiteralType<'db> {
pub fn expect_class_literal(self) -> ClassLiteral<'db> {
self.into_class_literal()
.expect("Expected a Type::ClassLiteral variant")
}
@@ -688,27 +696,29 @@ impl<'db> Type<'db> {
matches!(self, Type::ClassLiteral(..))
}
pub const fn into_class_type(self) -> Option<ClassType<'db>> {
/// Turn a class literal (`Type::ClassLiteral` or `Type::GenericAlias`) into a `ClassType`.
/// Since a `ClassType` must be specialized, apply the default specialization to any
/// unspecialized generic class literal.
pub fn to_class_type(self, db: &'db dyn Db) -> Option<ClassType<'db>> {
match self {
Type::ClassLiteral(ClassLiteralType::NonGeneric(non_generic)) => {
Some(ClassType::NonGeneric(non_generic))
}
Type::ClassLiteral(class_literal) => Some(class_literal.default_specialization(db)),
Type::GenericAlias(alias) => Some(ClassType::Generic(alias)),
_ => None,
}
}
#[track_caller]
pub fn expect_class_type(self) -> ClassType<'db> {
self.into_class_type()
.expect("Expected a Type::GenericAlias or non-generic Type::ClassLiteral variant")
pub fn expect_class_type(self, db: &'db dyn Db) -> ClassType<'db> {
self.to_class_type(db)
.expect("Expected a Type::GenericAlias or Type::ClassLiteral variant")
}
pub const fn is_class_type(&self) -> bool {
matches!(
self,
Type::ClassLiteral(ClassLiteralType::NonGeneric(_)) | Type::GenericAlias(_)
)
pub fn is_class_type(&self, db: &'db dyn Db) -> bool {
match self {
Type::ClassLiteral(class) if class.generic_context(db).is_none() => true,
Type::GenericAlias(_) => true,
_ => false,
}
}
pub const fn is_property_instance(&self) -> bool {
@@ -882,8 +892,9 @@ impl<'db> Type<'db> {
Type::Intersection(intersection) => Type::Intersection(intersection.normalized(db)),
Type::Tuple(tuple) => Type::Tuple(tuple.normalized(db)),
Type::Callable(callable) => Type::Callable(callable.normalized(db)),
Type::ProtocolInstance(protocol) => protocol.normalized(db),
Type::LiteralString
| Type::Instance(_)
| Type::NominalInstance(_)
| Type::PropertyInstance(_)
| Type::AlwaysFalsy
| Type::AlwaysTruthy
@@ -975,7 +986,7 @@ impl<'db> Type<'db> {
(_, Type::Never) => false,
// Everything is a subtype of `object`.
(_, Type::Instance(instance)) if instance.class().is_object(db) => true,
(_, Type::NominalInstance(instance)) if instance.class().is_object(db) => true,
// A fully static typevar is always a subtype of itself, and is never a subtype of any
// other typevar, since there is no guarantee that they will be specialized to the same
@@ -1145,6 +1156,14 @@ impl<'db> Type<'db> {
false
}
(Type::ProtocolInstance(left), Type::ProtocolInstance(right)) => {
left.is_subtype_of(db, right)
}
// A protocol instance can never be a subtype of a nominal type, with the *sole* exception of `object`.
// TODO: `Callable` types are also structural types.
(Type::ProtocolInstance(_), _) => false,
(_, Type::ProtocolInstance(protocol)) => self.satisfies_protocol(db, protocol),
// A fully static heterogeneous tuple type `A` is a subtype of a fully static heterogeneous tuple type `B`
// iff the two tuple types have the same number of elements and each element-type in `A` is a subtype
// of the element-type at the same index in `B`. (Now say that 5 times fast.)
@@ -1227,7 +1246,7 @@ impl<'db> Type<'db> {
metaclass_instance_type.is_subtype_of(db, target)
}),
// For example: `Type::KnownInstance(KnownInstanceType::Type)` is a subtype of `Type::Instance(_SpecialForm)`,
// For example: `Type::KnownInstance(KnownInstanceType::Type)` is a subtype of `Type::NominalInstance(_SpecialForm)`,
// because `Type::KnownInstance(KnownInstanceType::Type)` is a set with exactly one runtime value in it
// (the symbol `typing.Type`), and that symbol is known to be an instance of `typing._SpecialForm` at runtime.
(Type::KnownInstance(left), right) => {
@@ -1236,11 +1255,11 @@ impl<'db> Type<'db> {
// `bool` is a subtype of `int`, because `bool` subclasses `int`,
// which means that all instances of `bool` are also instances of `int`
(Type::Instance(self_instance), Type::Instance(target_instance)) => {
(Type::NominalInstance(self_instance), Type::NominalInstance(target_instance)) => {
self_instance.is_subtype_of(db, target_instance)
}
(Type::Instance(_), Type::Callable(_)) => {
(Type::NominalInstance(_), Type::Callable(_)) => {
let call_symbol = self.member(db, "__call__").symbol;
match call_symbol {
Symbol::Type(Type::BoundMethod(call_function), _) => call_function
@@ -1259,7 +1278,7 @@ impl<'db> Type<'db> {
// Other than the special cases enumerated above, `Instance` types and typevars are
// never subtypes of any other variants
(Type::Instance(_) | Type::TypeVar(_), _) => false,
(Type::NominalInstance(_) | Type::TypeVar(_), _) => false,
}
}
@@ -1281,7 +1300,7 @@ impl<'db> Type<'db> {
// All types are assignable to `object`.
// TODO this special case might be removable once the below cases are comprehensive
(_, Type::Instance(instance)) if instance.class().is_object(db) => true,
(_, Type::NominalInstance(instance)) if instance.class().is_object(db) => true,
// A typevar is always assignable to itself, and is never assignable to any other
// typevar, since there is no guarantee that they will be specialized to the same
@@ -1415,7 +1434,7 @@ impl<'db> Type<'db> {
// subtypes of `type[object]` are `type[...]` types (or `Never`), and `type[Any]` can
// materialize to any `type[...]` type (or to `type[Never]`, which is equivalent to
// `Never`.)
(Type::SubclassOf(subclass_of_ty), Type::Instance(_))
(Type::SubclassOf(subclass_of_ty), Type::NominalInstance(_))
if subclass_of_ty.is_dynamic()
&& (KnownClass::Type
.to_instance(db)
@@ -1427,44 +1446,14 @@ impl<'db> Type<'db> {
// Any type that is assignable to `type[object]` is also assignable to `type[Any]`,
// because `type[Any]` can materialize to `type[object]`.
(Type::Instance(_), Type::SubclassOf(subclass_of_ty))
(Type::NominalInstance(_), Type::SubclassOf(subclass_of_ty))
if subclass_of_ty.is_dynamic()
&& self.is_assignable_to(db, KnownClass::Type.to_instance(db)) =>
{
true
}
// TODO: This is a workaround to avoid false positives (e.g. when checking function calls
// with `SupportsIndex` parameters), which should be removed when we understand protocols.
(lhs, Type::Instance(instance))
if instance.class().is_known(db, KnownClass::SupportsIndex) =>
{
match lhs {
Type::Instance(instance)
if matches!(
instance.class().known(db),
Some(KnownClass::Int | KnownClass::SupportsIndex)
) =>
{
true
}
Type::IntLiteral(_) => true,
_ => false,
}
}
// TODO: ditto for avoiding false positives when checking function calls with `Sized` parameters.
(lhs, Type::Instance(instance)) if instance.class().is_known(db, KnownClass::Sized) => {
matches!(
lhs.to_meta_type(db).member(db, "__len__"),
SymbolAndQualifiers {
symbol: Symbol::Type(..),
..
}
)
}
(Type::Instance(self_instance), Type::Instance(target_instance)) => {
(Type::NominalInstance(self_instance), Type::NominalInstance(target_instance)) => {
self_instance.is_assignable_to(db, target_instance)
}
@@ -1472,7 +1461,7 @@ impl<'db> Type<'db> {
self_callable.is_assignable_to(db, target_callable)
}
(Type::Instance(_), Type::Callable(_)) => {
(Type::NominalInstance(_), Type::Callable(_)) => {
let call_symbol = self.member(db, "__call__").symbol;
match call_symbol {
Symbol::Type(Type::BoundMethod(call_function), _) => call_function
@@ -1492,6 +1481,16 @@ impl<'db> Type<'db> {
.into_callable_type(db)
.is_assignable_to(db, target),
(Type::ProtocolInstance(left), Type::ProtocolInstance(right)) => {
left.is_assignable_to(db, right)
}
// Other than the dynamic types such as `Any`/`Unknown`/`Todo` handled above,
// a protocol instance can never be assignable to a nominal type,
// with the *sole* exception of `object`.
// TODO: `Callable` types are also structural types.
(Type::ProtocolInstance(_), _) => false,
(_, Type::ProtocolInstance(protocol)) => self.satisfies_protocol(db, protocol),
// TODO other types containing gradual forms
_ => self.is_subtype_of(db, target),
}
@@ -1512,7 +1511,16 @@ impl<'db> Type<'db> {
}
(Type::Tuple(left), Type::Tuple(right)) => left.is_equivalent_to(db, right),
(Type::Callable(left), Type::Callable(right)) => left.is_equivalent_to(db, right),
(Type::Instance(left), Type::Instance(right)) => left.is_equivalent_to(db, right),
(Type::NominalInstance(left), Type::NominalInstance(right)) => {
left.is_equivalent_to(db, right)
}
(Type::ProtocolInstance(first), Type::ProtocolInstance(right)) => {
first.is_equivalent_to(db, right)
}
(Type::ProtocolInstance(protocol), nominal @ Type::NominalInstance(n))
| (nominal @ Type::NominalInstance(n), Type::ProtocolInstance(protocol)) => {
n.class().is_object(db) && protocol.normalized(db) == nominal
}
_ => self == other && self.is_fully_static(db) && other.is_fully_static(db),
}
}
@@ -1547,7 +1555,7 @@ impl<'db> Type<'db> {
(Type::TypeVar(first), Type::TypeVar(second)) => first == second,
(Type::Instance(first), Type::Instance(second)) => {
(Type::NominalInstance(first), Type::NominalInstance(second)) => {
first.is_gradual_equivalent_to(db, second)
}
@@ -1563,10 +1571,24 @@ impl<'db> Type<'db> {
first.is_gradual_equivalent_to(db, second)
}
(Type::ProtocolInstance(first), Type::ProtocolInstance(right)) => {
first.is_gradual_equivalent_to(db, right)
}
(Type::ProtocolInstance(protocol), nominal @ Type::NominalInstance(n))
| (nominal @ Type::NominalInstance(n), Type::ProtocolInstance(protocol)) => {
n.class().is_object(db) && protocol.normalized(db) == nominal
}
_ => false,
}
}
fn satisfies_protocol(self, db: &'db dyn Db, protocol: ProtocolInstanceType<'db>) -> bool {
protocol
.protocol_members(db)
.iter()
.all(|member| !self.member(db, member).symbol.is_unbound())
}
/// Return true if this type and `other` have no common elements.
///
/// Note: This function aims to have no false positives, but might return
@@ -1763,6 +1785,68 @@ impl<'db> Type<'db> {
ty.bool(db).is_always_true()
}
(Type::ProtocolInstance(left), Type::ProtocolInstance(right)) => {
left.is_disjoint_from(db, right)
}
// TODO: we could also consider `protocol` to be disjoint from `nominal` if `nominal`
// has the right member but the type of its member is disjoint from the type of the
// member on `protocol`.
(Type::ProtocolInstance(protocol), nominal @ Type::NominalInstance(n))
| (nominal @ Type::NominalInstance(n), Type::ProtocolInstance(protocol)) => {
n.class().is_final(db) && !nominal.satisfies_protocol(db, protocol)
}
(
ty @ (Type::LiteralString
| Type::StringLiteral(..)
| Type::BytesLiteral(..)
| Type::BooleanLiteral(..)
| Type::SliceLiteral(..)
| Type::ClassLiteral(..)
| Type::FunctionLiteral(..)
| Type::ModuleLiteral(..)
| Type::GenericAlias(..)
| Type::IntLiteral(..)),
Type::ProtocolInstance(protocol),
)
| (
Type::ProtocolInstance(protocol),
ty @ (Type::LiteralString
| Type::StringLiteral(..)
| Type::BytesLiteral(..)
| Type::BooleanLiteral(..)
| Type::SliceLiteral(..)
| Type::ClassLiteral(..)
| Type::FunctionLiteral(..)
| Type::ModuleLiteral(..)
| Type::GenericAlias(..)
| Type::IntLiteral(..)),
) => !ty.satisfies_protocol(db, protocol),
(Type::ProtocolInstance(protocol), Type::KnownInstance(known_instance))
| (Type::KnownInstance(known_instance), Type::ProtocolInstance(protocol)) => {
!known_instance
.instance_fallback(db)
.satisfies_protocol(db, protocol)
}
(Type::Callable(_), Type::ProtocolInstance(_))
| (Type::ProtocolInstance(_), Type::Callable(_)) => {
// TODO disjointness between `Callable` and `ProtocolInstance`
false
}
(Type::Tuple(..), Type::ProtocolInstance(..))
| (Type::ProtocolInstance(..), Type::Tuple(..)) => {
// Currently we do not make any general assumptions about the disjointness of a `Tuple` type
// and a `ProtocolInstance` type because a `Tuple` type can be an instance of a tuple
// subclass.
//
// TODO when we capture the types of the protocol members, we can improve on this.
false
}
// for `type[Any]`/`type[Unknown]`/`type[Todo]`, we know the type cannot be any larger than `type`,
// so although the type is dynamic we can still determine disjointedness in some situations
(Type::SubclassOf(subclass_of_ty), other)
@@ -1775,8 +1859,8 @@ impl<'db> Type<'db> {
.is_disjoint_from(db, other),
},
(Type::KnownInstance(known_instance), Type::Instance(instance))
| (Type::Instance(instance), Type::KnownInstance(known_instance)) => {
(Type::KnownInstance(known_instance), Type::NominalInstance(instance))
| (Type::NominalInstance(instance), Type::KnownInstance(known_instance)) => {
!known_instance.is_instance_of(db, instance.class())
}
@@ -1785,8 +1869,8 @@ impl<'db> Type<'db> {
known_instance_ty.is_disjoint_from(db, KnownClass::Tuple.to_instance(db))
}
(Type::BooleanLiteral(..), Type::Instance(instance))
| (Type::Instance(instance), Type::BooleanLiteral(..)) => {
(Type::BooleanLiteral(..), Type::NominalInstance(instance))
| (Type::NominalInstance(instance), Type::BooleanLiteral(..)) => {
// A `Type::BooleanLiteral()` must be an instance of exactly `bool`
// (it cannot be an instance of a `bool` subclass)
!KnownClass::Bool.is_subclass_of(db, instance.class())
@@ -1794,8 +1878,8 @@ impl<'db> Type<'db> {
(Type::BooleanLiteral(..), _) | (_, Type::BooleanLiteral(..)) => true,
(Type::IntLiteral(..), Type::Instance(instance))
| (Type::Instance(instance), Type::IntLiteral(..)) => {
(Type::IntLiteral(..), Type::NominalInstance(instance))
| (Type::NominalInstance(instance), Type::IntLiteral(..)) => {
// A `Type::IntLiteral()` must be an instance of exactly `int`
// (it cannot be an instance of an `int` subclass)
!KnownClass::Int.is_subclass_of(db, instance.class())
@@ -1806,8 +1890,8 @@ impl<'db> Type<'db> {
(Type::StringLiteral(..), Type::LiteralString)
| (Type::LiteralString, Type::StringLiteral(..)) => false,
(Type::StringLiteral(..) | Type::LiteralString, Type::Instance(instance))
| (Type::Instance(instance), Type::StringLiteral(..) | Type::LiteralString) => {
(Type::StringLiteral(..) | Type::LiteralString, Type::NominalInstance(instance))
| (Type::NominalInstance(instance), Type::StringLiteral(..) | Type::LiteralString) => {
// A `Type::StringLiteral()` or a `Type::LiteralString` must be an instance of exactly `str`
// (it cannot be an instance of a `str` subclass)
!KnownClass::Str.is_subclass_of(db, instance.class())
@@ -1816,15 +1900,15 @@ impl<'db> Type<'db> {
(Type::LiteralString, Type::LiteralString) => false,
(Type::LiteralString, _) | (_, Type::LiteralString) => true,
(Type::BytesLiteral(..), Type::Instance(instance))
| (Type::Instance(instance), Type::BytesLiteral(..)) => {
(Type::BytesLiteral(..), Type::NominalInstance(instance))
| (Type::NominalInstance(instance), Type::BytesLiteral(..)) => {
// A `Type::BytesLiteral()` must be an instance of exactly `bytes`
// (it cannot be an instance of a `bytes` subclass)
!KnownClass::Bytes.is_subclass_of(db, instance.class())
}
(Type::SliceLiteral(..), Type::Instance(instance))
| (Type::Instance(instance), Type::SliceLiteral(..)) => {
(Type::SliceLiteral(..), Type::NominalInstance(instance))
| (Type::NominalInstance(instance), Type::SliceLiteral(..)) => {
// A `Type::SliceLiteral` must be an instance of exactly `slice`
// (it cannot be an instance of a `slice` subclass)
!KnownClass::Slice.is_subclass_of(db, instance.class())
@@ -1833,17 +1917,19 @@ impl<'db> Type<'db> {
// A class-literal type `X` is always disjoint from an instance type `Y`,
// unless the type expressing "all instances of `Z`" is a subtype of of `Y`,
// where `Z` is `X`'s metaclass.
(Type::ClassLiteral(class), instance @ Type::Instance(_))
| (instance @ Type::Instance(_), Type::ClassLiteral(class)) => !class
.metaclass_instance_type(db)
.is_subtype_of(db, instance),
(Type::GenericAlias(alias), instance @ Type::Instance(_))
| (instance @ Type::Instance(_), Type::GenericAlias(alias)) => !ClassType::from(alias)
(Type::ClassLiteral(class), instance @ Type::NominalInstance(_))
| (instance @ Type::NominalInstance(_), Type::ClassLiteral(class)) => !class
.metaclass_instance_type(db)
.is_subtype_of(db, instance),
(Type::GenericAlias(alias), instance @ Type::NominalInstance(_))
| (instance @ Type::NominalInstance(_), Type::GenericAlias(alias)) => {
!ClassType::from(alias)
.metaclass_instance_type(db)
.is_subtype_of(db, instance)
}
(Type::FunctionLiteral(..), Type::Instance(instance))
| (Type::Instance(instance), Type::FunctionLiteral(..)) => {
(Type::FunctionLiteral(..), Type::NominalInstance(instance))
| (Type::NominalInstance(instance), Type::FunctionLiteral(..)) => {
// A `Type::FunctionLiteral()` must be an instance of exactly `types.FunctionType`
// (it cannot be an instance of a `types.FunctionType` subclass)
!KnownClass::FunctionType.is_subclass_of(db, instance.class())
@@ -1899,13 +1985,15 @@ impl<'db> Type<'db> {
false
}
(Type::ModuleLiteral(..), other @ Type::Instance(..))
| (other @ Type::Instance(..), Type::ModuleLiteral(..)) => {
(Type::ModuleLiteral(..), other @ Type::NominalInstance(..))
| (other @ Type::NominalInstance(..), Type::ModuleLiteral(..)) => {
// Modules *can* actually be instances of `ModuleType` subclasses
other.is_disjoint_from(db, KnownClass::ModuleType.to_instance(db))
}
(Type::Instance(left), Type::Instance(right)) => left.is_disjoint_from(db, right),
(Type::NominalInstance(left), Type::NominalInstance(right)) => {
left.is_disjoint_from(db, right)
}
(Type::Tuple(tuple), Type::Tuple(other_tuple)) => {
let self_elements = tuple.elements(db);
@@ -1917,8 +2005,8 @@ impl<'db> Type<'db> {
.any(|(e1, e2)| e1.is_disjoint_from(db, *e2))
}
(Type::Tuple(..), instance @ Type::Instance(_))
| (instance @ Type::Instance(_), Type::Tuple(..)) => {
(Type::Tuple(..), instance @ Type::NominalInstance(_))
| (instance @ Type::NominalInstance(_), Type::Tuple(..)) => {
// We cannot be sure if the tuple is disjoint from the instance because:
// - 'other' might be the homogeneous arbitrary-length tuple type
// tuple[T, ...] (which we don't have support for yet); if all of
@@ -1964,6 +2052,8 @@ impl<'db> Type<'db> {
| Type::AlwaysTruthy
| Type::PropertyInstance(_) => true,
Type::ProtocolInstance(protocol) => protocol.is_fully_static(),
Type::TypeVar(typevar) => match typevar.bound_or_constraints(db) {
None => true,
Some(TypeVarBoundOrConstraints::UpperBound(bound)) => bound.is_fully_static(db),
@@ -1978,7 +2068,7 @@ impl<'db> Type<'db> {
!matches!(bound_super.pivot_class(db), ClassBase::Dynamic(_))
&& !matches!(bound_super.owner(db), SuperOwnerKind::Dynamic(_))
}
Type::ClassLiteral(_) | Type::GenericAlias(_) | Type::Instance(_) => {
Type::ClassLiteral(_) | Type::GenericAlias(_) | Type::NominalInstance(_) => {
// TODO: Ideally, we would iterate over the MRO of the class, check if all
// bases are fully static, and only return `true` if that is the case.
//
@@ -2029,6 +2119,26 @@ impl<'db> Type<'db> {
false
}
Type::ProtocolInstance(..) => {
// It *might* be possible to have a singleton protocol-instance type...?
//
// E.g.:
//
// ```py
// from typing import Protocol, Callable
//
// class WeirdAndWacky(Protocol):
// @property
// def __class__(self) -> Callable[[], None]: ...
// ```
//
// `WeirdAndWacky` only has a single possible inhabitant: `None`!
// It is thus a singleton type.
// However, going out of our way to recognise it as such is probably not worth it.
// Such cases should anyway be exceedingly rare and/or contrived.
false
}
// An unbounded, unconstrained typevar is not a singleton, because it can be
// specialized to a non-singleton type. A bounded typevar is not a singleton, even if
// the bound is a final singleton class, since it can still be specialized to `Never`.
@@ -2084,7 +2194,7 @@ impl<'db> Type<'db> {
false
}
Type::DataclassDecorator(_) | Type::DataclassTransformer(_) => false,
Type::Instance(instance) => instance.is_singleton(db),
Type::NominalInstance(instance) => instance.is_singleton(db),
Type::PropertyInstance(_) => false,
Type::Tuple(..) => {
// The empty tuple is a singleton on CPython and PyPy, but not on other Python
@@ -2131,6 +2241,11 @@ impl<'db> Type<'db> {
| Type::SliceLiteral(..)
| Type::KnownInstance(..) => true,
Type::ProtocolInstance(..) => {
// See comment in the `Type::ProtocolInstance` branch for `Type::is_singleton`.
false
}
// An unbounded, unconstrained typevar is not single-valued, because it can be
// specialized to a multiple-valued type. A bounded typevar is not single-valued, even
// if the bound is a final single-valued class, since it can still be specialized to
@@ -2156,7 +2271,7 @@ impl<'db> Type<'db> {
.iter()
.all(|elem| elem.is_single_valued(db)),
Type::Instance(instance) => instance.is_single_valued(db),
Type::NominalInstance(instance) => instance.is_single_valued(db),
Type::BoundSuper(_) => {
// At runtime two super instances never compare equal, even if their arguments are identical.
@@ -2294,10 +2409,11 @@ impl<'db> Type<'db> {
.to_class_literal(db)
.find_name_in_mro_with_policy(db, name, policy),
// We eagerly normalize type[object], i.e. Type::SubclassOf(object) to `type`, i.e. Type::Instance(type).
// So looking up a name in the MRO of `Type::Instance(type)` is equivalent to looking up the name in the
// We eagerly normalize type[object], i.e. Type::SubclassOf(object) to `type`,
// i.e. Type::NominalInstance(type). So looking up a name in the MRO of
// `Type::NominalInstance(type)` is equivalent to looking up the name in the
// MRO of the class `object`.
Type::Instance(instance) if instance.class().is_known(db, KnownClass::Type) => {
Type::NominalInstance(instance) if instance.class().is_known(db, KnownClass::Type) => {
KnownClass::Object
.to_class_literal(db)
.find_name_in_mro_with_policy(db, name, policy)
@@ -2322,7 +2438,8 @@ impl<'db> Type<'db> {
| Type::SliceLiteral(_)
| Type::Tuple(_)
| Type::TypeVar(_)
| Type::Instance(_)
| Type::NominalInstance(_)
| Type::ProtocolInstance(_)
| Type::PropertyInstance(_) => None,
}
}
@@ -2387,7 +2504,18 @@ impl<'db> Type<'db> {
Type::Dynamic(_) | Type::Never => Symbol::bound(self).into(),
Type::Instance(instance) => instance.class().instance_member(db, name),
Type::NominalInstance(instance) => instance.class().instance_member(db, name),
Type::ProtocolInstance(protocol) => match protocol.inner() {
Protocol::FromClass(class) => class.instance_member(db, name),
Protocol::Synthesized(synthesized) => {
if synthesized.members(db).contains(name) {
SymbolAndQualifiers::todo("Capture type of synthesized protocol members")
} else {
Symbol::Unbound.into()
}
}
},
Type::FunctionLiteral(_) => KnownClass::FunctionType
.to_instance(db)
@@ -2828,7 +2956,7 @@ impl<'db> Type<'db> {
.to_instance(db)
.member_lookup_with_policy(db, name, policy),
Type::Instance(instance)
Type::NominalInstance(instance)
if matches!(name.as_str(), "major" | "minor")
&& instance.class().is_known(db, KnownClass::VersionInfo) =>
{
@@ -2870,7 +2998,8 @@ impl<'db> Type<'db> {
policy,
),
Type::Instance(..)
Type::NominalInstance(..)
| Type::ProtocolInstance(..)
| Type::BooleanLiteral(..)
| Type::IntLiteral(..)
| Type::StringLiteral(..)
@@ -2901,7 +3030,7 @@ impl<'db> Type<'db> {
// It will need a special handling, so it remember the origin type to properly
// resolve the attribute.
if matches!(
self.into_instance()
self.into_nominal_instance()
.and_then(|instance| instance.class().known(db)),
Some(KnownClass::ModuleType | KnownClass::GenericAlias)
) {
@@ -3162,11 +3291,13 @@ impl<'db> Type<'db> {
}
},
Type::Instance(instance) => match instance.class().known(db) {
Type::NominalInstance(instance) => match instance.class().known(db) {
Some(known_class) => known_class.bool(),
None => try_dunder_bool()?,
},
Type::ProtocolInstance(_) => try_dunder_bool()?,
Type::KnownInstance(known_instance) => known_instance.bool(),
Type::PropertyInstance(_) => Truthiness::AlwaysTrue,
@@ -3885,6 +4016,28 @@ impl<'db> Type<'db> {
}
},
Type::KnownInstance(KnownInstanceType::TypedDict) => {
Signatures::single(CallableSignature::single(
self,
Signature::new(
Parameters::new([
Parameter::positional_only(Some(Name::new_static("typename")))
.with_annotated_type(KnownClass::Str.to_instance(db)),
Parameter::positional_only(Some(Name::new_static("fields")))
.with_annotated_type(KnownClass::Dict.to_instance(db))
.with_default_type(Type::any()),
Parameter::keyword_only(Name::new_static("total"))
.with_annotated_type(KnownClass::Bool.to_instance(db))
.with_default_type(Type::BooleanLiteral(true)),
// Future compatibility, in case new keyword arguments will be added:
Parameter::keyword_variadic(Name::new_static("kwargs"))
.with_annotated_type(Type::any()),
]),
None,
),
))
}
Type::GenericAlias(_) => {
// TODO annotated return type on `__new__` or metaclass `__call__`
// TODO check call vs signatures of `__new__` and/or `__init__`
@@ -3906,7 +4059,7 @@ impl<'db> Type<'db> {
SubclassOfInner::Class(class) => Type::from(class).signatures(db),
},
Type::Instance(_) => {
Type::NominalInstance(_) => {
// Note that for objects that have a (possibly not callable!) `__call__` attribute,
// we will get the signature of the `__call__` attribute, but will pass in the type
// of the original object as the "callable type". That ensures that we get errors
@@ -4192,13 +4345,16 @@ impl<'db> Type<'db> {
// do this, we instead use the _identity_ specialization, which maps each of the class's
// generic typevars to itself.
let (generic_origin, self_type) = match self {
Type::ClassLiteral(ClassLiteralType::Generic(generic)) => {
let specialization = generic.generic_context(db).identity_specialization(db);
(
Some(generic),
Type::GenericAlias(GenericAlias::new(db, generic, specialization)),
)
}
Type::ClassLiteral(class) => match class.generic_context(db) {
Some(generic_context) => {
let specialization = generic_context.identity_specialization(db);
(
Some(class),
Type::GenericAlias(GenericAlias::new(db, class, specialization)),
)
}
_ => (None, self),
},
_ => (None, self),
};
@@ -4298,11 +4454,14 @@ impl<'db> Type<'db> {
};
let specialized = specialization
.map(|specialization| {
Type::instance(ClassType::Generic(GenericAlias::new(
Type::instance(
db,
generic_origin,
specialization,
)))
ClassType::Generic(GenericAlias::new(
db,
generic_origin,
specialization,
)),
)
})
.unwrap_or(instance_ty);
Ok(specialized)
@@ -4333,9 +4492,9 @@ impl<'db> Type<'db> {
pub fn to_instance(&self, db: &'db dyn Db) -> Option<Type<'db>> {
match self {
Type::Dynamic(_) | Type::Never => Some(*self),
Type::ClassLiteral(class) => Some(Type::instance(class.default_specialization(db))),
Type::GenericAlias(alias) => Some(Type::instance(ClassType::from(*alias))),
Type::SubclassOf(subclass_of_ty) => Some(subclass_of_ty.to_instance()),
Type::ClassLiteral(class) => Some(Type::instance(db, class.default_specialization(db))),
Type::GenericAlias(alias) => Some(Type::instance(db, ClassType::from(*alias))),
Type::SubclassOf(subclass_of_ty) => Some(subclass_of_ty.to_instance(db)),
Type::Union(union) => {
let mut builder = UnionBuilder::new(db);
for element in union.elements(db) {
@@ -4353,7 +4512,8 @@ impl<'db> Type<'db> {
| Type::WrapperDescriptor(_)
| Type::DataclassDecorator(_)
| Type::DataclassTransformer(_)
| Type::Instance(_)
| Type::NominalInstance(_)
| Type::ProtocolInstance(_)
| Type::KnownInstance(_)
| Type::PropertyInstance(_)
| Type::ModuleLiteral(_)
@@ -4373,7 +4533,7 @@ impl<'db> Type<'db> {
///
/// For example, the builtin `int` as a value expression is of type
/// `Type::ClassLiteral(builtins.int)`, that is, it is the `int` class itself. As a type
/// expression, it names the type `Type::Instance(builtins.int)`, that is, all objects whose
/// expression, it names the type `Type::NominalInstance(builtins.int)`, that is, all objects whose
/// `__class__` is `int`.
pub fn in_type_expression(
&self,
@@ -4400,11 +4560,11 @@ impl<'db> Type<'db> {
KnownClass::Float.to_instance(db),
],
),
_ => Type::instance(class.default_specialization(db)),
_ => Type::instance(db, class.default_specialization(db)),
};
Ok(ty)
}
Type::GenericAlias(alias) => Ok(Type::instance(ClassType::from(*alias))),
Type::GenericAlias(alias) => Ok(Type::instance(db, ClassType::from(*alias))),
Type::SubclassOf(_)
| Type::BooleanLiteral(_)
@@ -4427,6 +4587,7 @@ impl<'db> Type<'db> {
| Type::Never
| Type::FunctionLiteral(_)
| Type::BoundSuper(_)
| Type::ProtocolInstance(_)
| Type::PropertyInstance(_) => Err(InvalidTypeExpressionError {
invalid_expressions: smallvec::smallvec![InvalidTypeExpression::InvalidType(*self)],
fallback_type: Type::unknown(),
@@ -4463,6 +4624,7 @@ impl<'db> Type<'db> {
KnownInstanceType::TypingSelf => Ok(todo_type!("Support for `typing.Self`")),
KnownInstanceType::TypeAlias => Ok(todo_type!("Support for `typing.TypeAlias`")),
KnownInstanceType::TypedDict => Ok(todo_type!("Support for `typing.TypedDict`")),
KnownInstanceType::Protocol => Err(InvalidTypeExpressionError {
invalid_expressions: smallvec::smallvec![InvalidTypeExpression::Protocol],
@@ -4550,7 +4712,7 @@ impl<'db> Type<'db> {
Type::Dynamic(_) => Ok(*self),
Type::Instance(instance) => match instance.class().known(db) {
Type::NominalInstance(instance) => match instance.class().known(db) {
Some(KnownClass::TypeVar) => Ok(todo_type!(
"Support for `typing.TypeVar` instances in type expressions"
)),
@@ -4626,7 +4788,7 @@ impl<'db> Type<'db> {
pub fn to_meta_type(&self, db: &'db dyn Db) -> Type<'db> {
match self {
Type::Never => Type::Never,
Type::Instance(instance) => instance.to_meta_type(db),
Type::NominalInstance(instance) => instance.to_meta_type(db),
Type::KnownInstance(known_instance) => known_instance.to_meta_type(db),
Type::PropertyInstance(_) => KnownClass::Property.to_class_literal(db),
Type::Union(union) => union.map(db, |ty| ty.to_meta_type(db)),
@@ -4674,6 +4836,7 @@ impl<'db> Type<'db> {
),
Type::AlwaysTruthy | Type::AlwaysFalsy => KnownClass::Type.to_instance(db),
Type::BoundSuper(_) => KnownClass::Super.to_class_literal(db),
Type::ProtocolInstance(protocol) => protocol.to_meta_type(db),
}
}
@@ -4795,9 +4958,11 @@ impl<'db> Type<'db> {
| Type::BytesLiteral(_)
| Type::SliceLiteral(_)
| Type::BoundSuper(_)
// Instance contains a ClassType, which has already been specialized if needed, like
// above with BoundMethod's self_instance.
| Type::Instance(_)
// `NominalInstance` contains a ClassType, which has already been specialized if needed,
// like above with BoundMethod's self_instance.
| Type::NominalInstance(_)
// Same for `ProtocolInstance`
| Type::ProtocolInstance(_)
| Type::KnownInstance(_) => self,
}
}
@@ -4861,7 +5026,7 @@ impl<'db> Type<'db> {
Some(TypeDefinition::Class(class_literal.definition(db)))
}
Self::GenericAlias(alias) => Some(TypeDefinition::Class(alias.definition(db))),
Self::Instance(instance) => {
Self::NominalInstance(instance) => {
Some(TypeDefinition::Class(instance.class().definition(db)))
}
Self::KnownInstance(instance) => match instance {
@@ -4895,6 +5060,11 @@ impl<'db> Type<'db> {
Self::TypeVar(var) => Some(TypeDefinition::TypeVar(var.definition(db))),
Self::ProtocolInstance(protocol) => match protocol.inner() {
Protocol::FromClass(class) => Some(TypeDefinition::Class(class.definition(db))),
Protocol::Synthesized(_) => None,
},
Self::Union(_) | Self::Intersection(_) => None,
// These types have no definition
@@ -5230,11 +5400,7 @@ impl<'db> InvalidTypeExpression<'db> {
/// typevar represents as an annotation: that is, an unknown set of objects, constrained by the
/// upper-bound/constraints on this type var, defaulting to the default type of this type var when
/// not otherwise bound to a type.
///
/// This must be a tracked struct, not an interned one, because typevar equivalence is by identity,
/// not by value. Two typevars that have the same name, bound/constraints, and default, are still
/// different typevars: if used in the same scope, they may be bound to different types.
#[salsa::tracked(debug)]
#[salsa::interned(debug)]
pub struct TypeVarInstance<'db> {
/// The name of this TypeVar (e.g. `T`)
#[return_ref]
@@ -6027,6 +6193,10 @@ bitflags! {
const OVERLOAD = 1 << 2;
/// `@abc.abstractmethod`
const ABSTRACT_METHOD = 1 << 3;
/// `@typing.final`
const FINAL = 1 << 4;
/// `@typing.override`
const OVERRIDE = 1 << 6;
}
}
@@ -6400,6 +6570,8 @@ pub enum KnownFunction {
Cast,
/// `typing(_extensions).overload`
Overload,
/// `typing(_extensions).override`
Override,
/// `typing(_extensions).is_protocol`
IsProtocol,
/// `typing(_extensions).get_protocol_members`
@@ -6467,6 +6639,7 @@ impl KnownFunction {
| Self::AssertNever
| Self::Cast
| Self::Overload
| Self::Override
| Self::RevealType
| Self::Final
| Self::IsProtocol
@@ -6565,6 +6738,18 @@ impl<'db> CallableType<'db> {
)
}
/// Create a callable type which represents a fully-static "bottom" callable.
///
/// Specifically, this represents a callable type with a single signature:
/// `(*args: object, **kwargs: object) -> Never`.
#[cfg(test)]
pub(crate) fn bottom(db: &'db dyn Db) -> Type<'db> {
Type::Callable(CallableType::single(
db,
Signature::new(Parameters::object(db), Some(Type::Never)),
))
}
/// Return a "normalized" version of this `Callable` type.
///
/// See [`Type::normalized`] for more details.
@@ -6802,7 +6987,7 @@ impl<'db> TypeAliasType<'db> {
#[derive(Debug, Clone, PartialEq, Eq, salsa::Update)]
pub(super) struct MetaclassCandidate<'db> {
metaclass: ClassType<'db>,
explicit_metaclass_of: ClassLiteralType<'db>,
explicit_metaclass_of: ClassLiteral<'db>,
}
#[salsa::interned(debug)]
@@ -7434,7 +7619,7 @@ impl BoundSuperError<'_> {
pub enum SuperOwnerKind<'db> {
Dynamic(DynamicType),
Class(ClassType<'db>),
Instance(InstanceType<'db>),
Instance(NominalInstanceType<'db>),
}
impl<'db> SuperOwnerKind<'db> {
@@ -7468,7 +7653,7 @@ impl<'db> SuperOwnerKind<'db> {
Type::ClassLiteral(class_literal) => Some(SuperOwnerKind::Class(
class_literal.apply_optional_specialization(db, None),
)),
Type::Instance(instance) => Some(SuperOwnerKind::Instance(instance)),
Type::NominalInstance(instance) => Some(SuperOwnerKind::Instance(instance)),
Type::BooleanLiteral(_) => {
SuperOwnerKind::try_from_type(db, KnownClass::Bool.to_instance(db))
}
@@ -7651,11 +7836,9 @@ impl<'db> BoundSuperType<'db> {
// super(B, b_int)
// super(B[int], b_unknown)
// ```
match class_literal {
ClassLiteralType::Generic(_) => {
Symbol::bound(todo_type!("super in generic class")).into()
}
ClassLiteralType::NonGeneric(_) => class_literal.class_member_from_mro(
match class_literal.generic_context(db) {
Some(_) => Symbol::bound(todo_type!("super in generic class")).into(),
None => class_literal.class_member_from_mro(
db,
name,
policy,
@@ -7844,6 +8027,7 @@ pub(crate) mod tests {
KnownFunction::Cast
| KnownFunction::Final
| KnownFunction::Overload
| KnownFunction::Override
| KnownFunction::RevealType
| KnownFunction::AssertType
| KnownFunction::AssertNever

View File

@@ -591,7 +591,7 @@ impl<'db> InnerIntersectionBuilder<'db> {
}
_ => {
let known_instance = new_positive
.into_instance()
.into_nominal_instance()
.and_then(|instance| instance.class().known(db));
if known_instance == Some(KnownClass::Object) {
@@ -611,7 +611,7 @@ impl<'db> InnerIntersectionBuilder<'db> {
Type::AlwaysFalsy if addition_is_bool_instance => {
new_positive = Type::BooleanLiteral(false);
}
Type::Instance(instance)
Type::NominalInstance(instance)
if instance.class().is_known(db, KnownClass::Bool) =>
{
match new_positive {
@@ -705,7 +705,7 @@ impl<'db> InnerIntersectionBuilder<'db> {
let contains_bool = || {
self.positive
.iter()
.filter_map(|ty| ty.into_instance())
.filter_map(|ty| ty.into_nominal_instance())
.filter_map(|instance| instance.class().known(db))
.any(KnownClass::is_bool)
};
@@ -722,7 +722,7 @@ impl<'db> InnerIntersectionBuilder<'db> {
Type::Never => {
// Adding ~Never to an intersection is a no-op.
}
Type::Instance(instance) if instance.class().is_object(db) => {
Type::NominalInstance(instance) if instance.class().is_object(db) => {
// Adding ~object to an intersection results in Never.
*self = Self::default();
self.positive.insert(Type::Never);

View File

@@ -19,9 +19,9 @@ use crate::types::diagnostic::{
use crate::types::generics::{Specialization, SpecializationBuilder};
use crate::types::signatures::{Parameter, ParameterForm};
use crate::types::{
BoundMethodType, DataclassParams, DataclassTransformerParams, FunctionDecorators, KnownClass,
KnownFunction, KnownInstanceType, MethodWrapperKind, PropertyInstanceType, TupleType,
UnionType, WrapperDescriptorKind,
todo_type, BoundMethodType, DataclassParams, DataclassTransformerParams, FunctionDecorators,
KnownClass, KnownFunction, KnownInstanceType, MethodWrapperKind, PropertyInstanceType,
TupleType, UnionType, WrapperDescriptorKind,
};
use ruff_db::diagnostic::{Annotation, Severity, SubDiagnostic};
use ruff_python_ast as ast;
@@ -584,6 +584,14 @@ impl<'db> Bindings<'db> {
}
}
Some(KnownFunction::Override) => {
// TODO: This can be removed once we understand legacy generics because the
// typeshed definition for `typing.overload` is an identity function.
if let [Some(ty)] = overload.parameter_types() {
overload.set_return_type(*ty);
}
}
Some(KnownFunction::AbstractMethod) => {
// TODO: This can be removed once we understand legacy generics because the
// typeshed definition for `abc.abstractmethod` is an identity function.
@@ -592,6 +600,14 @@ impl<'db> Bindings<'db> {
}
}
Some(KnownFunction::Final) => {
// TODO: This can be removed once we understand legacy generics because the
// typeshed definition for `abc.abstractmethod` is an identity function.
if let [Some(ty)] = overload.parameter_types() {
overload.set_return_type(*ty);
}
}
Some(KnownFunction::GetattrStatic) => {
let [Some(instance_ty), Some(attr_name), default] =
overload.parameter_types()
@@ -756,6 +772,10 @@ impl<'db> Bindings<'db> {
_ => {}
},
Type::KnownInstance(KnownInstanceType::TypedDict) => {
overload.set_return_type(todo_type!("TypedDict"));
}
// Not a special case
_ => {}
}

View File

@@ -50,14 +50,14 @@ fn explicit_bases_cycle_recover<'db>(
_db: &'db dyn Db,
_value: &[Type<'db>],
_count: u32,
_self: ClassLiteralType<'db>,
_self: ClassLiteral<'db>,
) -> salsa::CycleRecoveryAction<Box<[Type<'db>]>> {
salsa::CycleRecoveryAction::Iterate
}
fn explicit_bases_cycle_initial<'db>(
_db: &'db dyn Db,
_self: ClassLiteralType<'db>,
_self: ClassLiteral<'db>,
) -> Box<[Type<'db>]> {
Box::default()
}
@@ -66,7 +66,7 @@ fn try_mro_cycle_recover<'db>(
_db: &'db dyn Db,
_value: &Result<Mro<'db>, MroError<'db>>,
_count: u32,
_self: ClassLiteralType<'db>,
_self: ClassLiteral<'db>,
_specialization: Option<Specialization<'db>>,
) -> salsa::CycleRecoveryAction<Result<Mro<'db>, MroError<'db>>> {
salsa::CycleRecoveryAction::Iterate
@@ -75,7 +75,7 @@ fn try_mro_cycle_recover<'db>(
#[allow(clippy::unnecessary_wraps)]
fn try_mro_cycle_initial<'db>(
db: &'db dyn Db,
self_: ClassLiteralType<'db>,
self_: ClassLiteral<'db>,
specialization: Option<Specialization<'db>>,
) -> Result<Mro<'db>, MroError<'db>> {
Ok(Mro::from_error(
@@ -89,90 +89,28 @@ fn inheritance_cycle_recover<'db>(
_db: &'db dyn Db,
_value: &Option<InheritanceCycle>,
_count: u32,
_self: ClassLiteralType<'db>,
_self: ClassLiteral<'db>,
) -> salsa::CycleRecoveryAction<Option<InheritanceCycle>> {
salsa::CycleRecoveryAction::Iterate
}
fn inheritance_cycle_initial<'db>(
_db: &'db dyn Db,
_self: ClassLiteralType<'db>,
_self: ClassLiteral<'db>,
) -> Option<InheritanceCycle> {
None
}
/// Representation of a class definition statement in the AST. This does not in itself represent a
/// type, but is used as the inner data for several structs that *do* represent types.
#[derive(Clone, Debug, Eq, Hash, PartialEq, salsa::Update)]
pub struct Class<'db> {
/// Name of the class at definition
pub(crate) name: ast::name::Name,
pub(crate) body_scope: ScopeId<'db>,
pub(crate) known: Option<KnownClass>,
pub(crate) dataclass_params: Option<DataclassParams>,
pub(crate) dataclass_transformer_params: Option<DataclassTransformerParams>,
}
impl<'db> Class<'db> {
fn file(&self, db: &dyn Db) -> File {
self.body_scope.file(db)
}
/// Return the original [`ast::StmtClassDef`] node associated with this class
///
/// ## Note
/// Only call this function from queries in the same file or your
/// query depends on the AST of another file (bad!).
fn node(&self, db: &'db dyn Db) -> &'db ast::StmtClassDef {
self.body_scope.node(db).expect_class()
}
fn definition(&self, db: &'db dyn Db) -> Definition<'db> {
let index = semantic_index(db, self.body_scope.file(db));
index.expect_single_definition(self.body_scope.node(db).expect_class())
}
}
/// A [`Class`] that is not generic.
#[salsa::interned(debug)]
pub struct NonGenericClass<'db> {
#[return_ref]
pub(crate) class: Class<'db>,
}
impl<'db> From<NonGenericClass<'db>> for Type<'db> {
fn from(class: NonGenericClass<'db>) -> Type<'db> {
Type::ClassLiteral(ClassLiteralType::NonGeneric(class))
}
}
/// A [`Class`] that is generic.
#[salsa::interned(debug)]
pub struct GenericClass<'db> {
#[return_ref]
pub(crate) class: Class<'db>,
pub(crate) generic_context: GenericContext<'db>,
}
impl<'db> From<GenericClass<'db>> for Type<'db> {
fn from(class: GenericClass<'db>) -> Type<'db> {
Type::ClassLiteral(ClassLiteralType::Generic(class))
}
}
/// A specialization of a generic class with a particular assignment of types to typevars.
#[salsa::interned(debug)]
pub struct GenericAlias<'db> {
pub(crate) origin: GenericClass<'db>,
pub(crate) origin: ClassLiteral<'db>,
pub(crate) specialization: Specialization<'db>,
}
impl<'db> GenericAlias<'db> {
pub(crate) fn definition(self, db: &'db dyn Db) -> Definition<'db> {
self.origin(db).class(db).definition(db)
self.origin(db).definition(db)
}
}
@@ -188,44 +126,47 @@ impl<'db> From<GenericAlias<'db>> for Type<'db> {
Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, salsa::Supertype, salsa::Update,
)]
pub enum ClassType<'db> {
NonGeneric(NonGenericClass<'db>),
NonGeneric(ClassLiteral<'db>),
Generic(GenericAlias<'db>),
}
#[salsa::tracked]
impl<'db> ClassType<'db> {
fn class(self, db: &'db dyn Db) -> &'db Class<'db> {
match self {
Self::NonGeneric(non_generic) => non_generic.class(db),
Self::Generic(generic) => generic.origin(db).class(db),
}
}
/// Returns the class literal and specialization for this class. For a non-generic class, this
/// is the class itself. For a generic alias, this is the alias's origin.
pub(crate) fn class_literal(
self,
db: &'db dyn Db,
) -> (ClassLiteralType<'db>, Option<Specialization<'db>>) {
) -> (ClassLiteral<'db>, Option<Specialization<'db>>) {
match self {
Self::NonGeneric(non_generic) => (ClassLiteralType::NonGeneric(non_generic), None),
Self::Generic(generic) => (
ClassLiteralType::Generic(generic.origin(db)),
Some(generic.specialization(db)),
),
Self::NonGeneric(non_generic) => (non_generic, None),
Self::Generic(generic) => (generic.origin(db), Some(generic.specialization(db))),
}
}
pub(super) fn is_protocol(self, db: &'db dyn Db) -> bool {
// `str` requires some special-casing here because in order to construct the type "instance of `str`"
// we must evaluate a call to `TypeVar.__new__`, and `TypeVar.__new__` has a parameter annotated with `str`,
// causing a Salsa cycle.
if self.is_known(db, KnownClass::Str) {
return false;
}
self.class_literal(db).0.is_protocol(db)
}
pub(crate) fn name(self, db: &'db dyn Db) -> &'db ast::name::Name {
&self.class(db).name
let (class_literal, _) = self.class_literal(db);
class_literal.name(db)
}
pub(crate) fn known(self, db: &'db dyn Db) -> Option<KnownClass> {
self.class(db).known
let (class_literal, _) = self.class_literal(db);
class_literal.known(db)
}
pub(crate) fn definition(self, db: &'db dyn Db) -> Definition<'db> {
self.class(db).definition(db)
let (class_literal, _) = self.class_literal(db);
class_literal.definition(db)
}
fn specialize_type(self, db: &'db dyn Db, ty: Type<'db>) -> Type<'db> {
@@ -237,7 +178,7 @@ impl<'db> ClassType<'db> {
/// Return `true` if this class represents `known_class`
pub(crate) fn is_known(self, db: &'db dyn Db, known_class: KnownClass) -> bool {
self.class(db).known == Some(known_class)
self.known(db) == Some(known_class)
}
/// Return `true` if this class represents the builtin class `object`
@@ -249,7 +190,7 @@ impl<'db> ClassType<'db> {
///
/// If the MRO could not be accurately resolved, this method falls back to iterating
/// over an MRO that has the class directly inheriting from `Unknown`. Use
/// [`ClassLiteralType::try_mro`] if you need to distinguish between the success and failure
/// [`ClassLiteral::try_mro`] if you need to distinguish between the success and failure
/// cases rather than simply iterating over the inferred resolution order for the class.
///
/// [method resolution order]: https://docs.python.org/3/glossary.html#term-method-resolution-order
@@ -457,47 +398,40 @@ impl<'db> From<ClassType<'db>> for Type<'db> {
}
}
/// Represents a single class object at runtime, which might be a non-generic class, or a generic
/// class that has not been specialized.
#[derive(
Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, salsa::Supertype, salsa::Update,
)]
pub enum ClassLiteralType<'db> {
NonGeneric(NonGenericClass<'db>),
Generic(GenericClass<'db>),
/// Representation of a class definition statement in the AST: either a non-generic class, or a
/// generic class that has not been specialized.
///
/// This does not in itself represent a type, but can be transformed into a [`ClassType`] that
/// does. (For generic classes, this requires specializing its generic context.)
#[salsa::interned(debug)]
pub struct ClassLiteral<'db> {
/// Name of the class at definition
#[return_ref]
pub(crate) name: ast::name::Name,
pub(crate) body_scope: ScopeId<'db>,
pub(crate) known: Option<KnownClass>,
pub(crate) dataclass_params: Option<DataclassParams>,
pub(crate) dataclass_transformer_params: Option<DataclassTransformerParams>,
}
#[salsa::tracked]
impl<'db> ClassLiteralType<'db> {
fn class(self, db: &'db dyn Db) -> &'db Class<'db> {
match self {
Self::NonGeneric(non_generic) => non_generic.class(db),
Self::Generic(generic) => generic.class(db),
}
}
pub(crate) fn name(self, db: &'db dyn Db) -> &'db ast::name::Name {
&self.class(db).name
}
pub(crate) fn known(self, db: &'db dyn Db) -> Option<KnownClass> {
self.class(db).known
}
pub(crate) fn dataclass_params(self, db: &'db dyn Db) -> Option<DataclassParams> {
self.class(db).dataclass_params
}
impl<'db> ClassLiteral<'db> {
/// Return `true` if this class represents `known_class`
pub(crate) fn is_known(self, db: &'db dyn Db, known_class: KnownClass) -> bool {
self.class(db).known == Some(known_class)
self.known(db) == Some(known_class)
}
#[salsa::tracked]
pub(crate) fn generic_context(self, db: &'db dyn Db) -> Option<GenericContext<'db>> {
match self {
Self::NonGeneric(_) => None,
Self::Generic(generic) => Some(generic.generic_context(db)),
}
let scope = self.body_scope(db);
let class_def_node = scope.node(db).expect_class();
class_def_node.type_params.as_ref().map(|type_params| {
let index = semantic_index(db, scope.file(db));
GenericContext::from_type_params(db, index, type_params)
})
}
/// Return `true` if this class represents the builtin class `object`
@@ -505,12 +439,23 @@ impl<'db> ClassLiteralType<'db> {
self.is_known(db, KnownClass::Object)
}
pub(crate) fn body_scope(self, db: &'db dyn Db) -> ScopeId<'db> {
self.class(db).body_scope
fn file(self, db: &dyn Db) -> File {
self.body_scope(db).file(db)
}
/// Return the original [`ast::StmtClassDef`] node associated with this class
///
/// ## Note
/// Only call this function from queries in the same file or your
/// query depends on the AST of another file (bad!).
fn node(self, db: &'db dyn Db) -> &'db ast::StmtClassDef {
self.body_scope(db).node(db).expect_class()
}
pub(crate) fn definition(self, db: &'db dyn Db) -> Definition<'db> {
self.class(db).definition(db)
let body_scope = self.body_scope(db);
let index = semantic_index(db, body_scope.file(db));
index.expect_single_definition(body_scope.node(db).expect_class())
}
pub(crate) fn apply_optional_specialization(
@@ -518,14 +463,14 @@ impl<'db> ClassLiteralType<'db> {
db: &'db dyn Db,
specialization: Option<Specialization<'db>>,
) -> ClassType<'db> {
match (self, specialization) {
(Self::NonGeneric(non_generic), _) => ClassType::NonGeneric(non_generic),
(Self::Generic(generic), None) => {
let specialization = generic.generic_context(db).default_specialization(db);
ClassType::Generic(GenericAlias::new(db, generic, specialization))
match (self.generic_context(db), specialization) {
(None, _) => ClassType::NonGeneric(self),
(Some(generic_context), None) => {
let specialization = generic_context.default_specialization(db);
ClassType::Generic(GenericAlias::new(db, self, specialization))
}
(Self::Generic(generic), Some(specialization)) => {
ClassType::Generic(GenericAlias::new(db, generic, specialization))
(Some(_), Some(specialization)) => {
ClassType::Generic(GenericAlias::new(db, self, specialization))
}
}
}
@@ -534,11 +479,11 @@ impl<'db> ClassLiteralType<'db> {
/// returned unchanged. For a non-specialized generic class, we return a generic alias that
/// applies the default specialization to the class's typevars.
pub(crate) fn default_specialization(self, db: &'db dyn Db) -> ClassType<'db> {
match self {
Self::NonGeneric(non_generic) => ClassType::NonGeneric(non_generic),
Self::Generic(generic) => {
let specialization = generic.generic_context(db).default_specialization(db);
ClassType::Generic(GenericAlias::new(db, generic, specialization))
match self.generic_context(db) {
None => ClassType::NonGeneric(self),
Some(generic_context) => {
let specialization = generic_context.default_specialization(db);
ClassType::Generic(GenericAlias::new(db, self, specialization))
}
}
}
@@ -547,11 +492,11 @@ impl<'db> ClassLiteralType<'db> {
/// returned unchanged. For a non-specialized generic class, we return a generic alias that
/// maps each of the class's typevars to `Unknown`.
pub(crate) fn unknown_specialization(self, db: &'db dyn Db) -> ClassType<'db> {
match self {
Self::NonGeneric(non_generic) => ClassType::NonGeneric(non_generic),
Self::Generic(generic) => {
let specialization = generic.generic_context(db).unknown_specialization(db);
ClassType::Generic(GenericAlias::new(db, generic, specialization))
match self.generic_context(db) {
None => ClassType::NonGeneric(self),
Some(generic_context) => {
let specialization = generic_context.unknown_specialization(db);
ClassType::Generic(GenericAlias::new(db, self, specialization))
}
}
}
@@ -573,22 +518,22 @@ impl<'db> ClassLiteralType<'db> {
self.explicit_bases_query(db)
}
/// Iterate over this class's explicit bases, filtering out any bases that are not class objects.
/// Iterate over this class's explicit bases, filtering out any bases that are not class
/// objects, and applying default specialization to any unspecialized generic class literals.
fn fully_static_explicit_bases(self, db: &'db dyn Db) -> impl Iterator<Item = ClassType<'db>> {
self.explicit_bases(db)
.iter()
.copied()
.filter_map(Type::into_class_type)
.filter_map(|ty| ty.to_class_type(db))
}
#[salsa::tracked(return_ref, cycle_fn=explicit_bases_cycle_recover, cycle_initial=explicit_bases_cycle_initial)]
fn explicit_bases_query(self, db: &'db dyn Db) -> Box<[Type<'db>]> {
let class = self.class(db);
tracing::trace!("ClassLiteralType::explicit_bases_query: {}", class.name);
tracing::trace!("ClassLiteral::explicit_bases_query: {}", self.name(db));
let class_stmt = class.node(db);
let class_stmt = self.node(db);
let class_definition =
semantic_index(db, class.file(db)).expect_single_definition(class_stmt);
semantic_index(db, self.file(db)).expect_single_definition(class_stmt);
class_stmt
.bases()
@@ -611,16 +556,15 @@ impl<'db> ClassLiteralType<'db> {
/// Return the types of the decorators on this class
#[salsa::tracked(return_ref)]
fn decorators(self, db: &'db dyn Db) -> Box<[Type<'db>]> {
let class = self.class(db);
tracing::trace!("ClassLiteralType::decorators: {}", class.name);
tracing::trace!("ClassLiteral::decorators: {}", self.name(db));
let class_stmt = class.node(db);
let class_stmt = self.node(db);
if class_stmt.decorator_list.is_empty() {
return Box::new([]);
}
let class_definition =
semantic_index(db, class.file(db)).expect_single_definition(class_stmt);
semantic_index(db, self.file(db)).expect_single_definition(class_stmt);
class_stmt
.decorator_list
@@ -662,8 +606,7 @@ impl<'db> ClassLiteralType<'db> {
db: &'db dyn Db,
specialization: Option<Specialization<'db>>,
) -> Result<Mro<'db>, MroError<'db>> {
let class = self.class(db);
tracing::trace!("ClassLiteralType::try_mro: {}", class.name);
tracing::trace!("ClassLiteral::try_mro: {}", self.name(db));
Mro::of_class(db, self, specialization)
}
@@ -671,7 +614,7 @@ impl<'db> ClassLiteralType<'db> {
///
/// If the MRO could not be accurately resolved, this method falls back to iterating
/// over an MRO that has the class directly inheriting from `Unknown`. Use
/// [`ClassLiteralType::try_mro`] if you need to distinguish between the success and failure
/// [`ClassLiteral::try_mro`] if you need to distinguish between the success and failure
/// cases rather than simply iterating over the inferred resolution order for the class.
///
/// [method resolution order]: https://docs.python.org/3/glossary.html#term-method-resolution-order
@@ -702,15 +645,14 @@ impl<'db> ClassLiteralType<'db> {
/// Only call this function from queries in the same file or your
/// query depends on the AST of another file (bad!).
fn explicit_metaclass(self, db: &'db dyn Db) -> Option<Type<'db>> {
let class = self.class(db);
let class_stmt = class.node(db);
let class_stmt = self.node(db);
let metaclass_node = &class_stmt
.arguments
.as_ref()?
.find_keyword("metaclass")?
.value;
let class_definition = class.definition(db);
let class_definition = self.definition(db);
Some(definition_expression_type(
db,
@@ -740,8 +682,7 @@ impl<'db> ClassLiteralType<'db> {
self,
db: &'db dyn Db,
) -> Result<(Type<'db>, Option<DataclassTransformerParams>), MetaclassError<'db>> {
let class = self.class(db);
tracing::trace!("ClassLiteralType::try_metaclass: {}", class.name);
tracing::trace!("ClassLiteral::try_metaclass: {}", self.name(db));
// Identify the class's own metaclass (or take the first base class's metaclass).
let mut base_classes = self.fully_static_explicit_bases(db).peekable();
@@ -763,13 +704,13 @@ impl<'db> ClassLiteralType<'db> {
(KnownClass::Type.to_class_literal(db), self)
};
let mut candidate = if let Some(metaclass_ty) = metaclass.into_class_type() {
let mut candidate = if let Some(metaclass_ty) = metaclass.to_class_type(db) {
MetaclassCandidate {
metaclass: metaclass_ty,
explicit_metaclass_of: class_metaclass_was_from,
}
} else {
let name = Type::string_literal(db, &class.name);
let name = Type::string_literal(db, self.name(db));
let bases = TupleType::from_elements(db, self.explicit_bases(db));
// TODO: Should be `dict[str, Any]`
let namespace = KnownClass::Dict.to_instance(db);
@@ -805,7 +746,7 @@ impl<'db> ClassLiteralType<'db> {
// - https://github.com/python/cpython/blob/83ba8c2bba834c0b92de669cac16fcda17485e0e/Objects/typeobject.c#L3629-L3663
for base_class in base_classes {
let metaclass = base_class.metaclass(db);
let Some(metaclass) = metaclass.into_class_type() else {
let Some(metaclass) = metaclass.to_class_type(db) else {
continue;
};
if metaclass.is_subclass_of(db, candidate.metaclass) {
@@ -832,9 +773,10 @@ impl<'db> ClassLiteralType<'db> {
});
}
let (metaclass_literal, _) = candidate.metaclass.class_literal(db);
Ok((
candidate.metaclass.into(),
candidate.metaclass.class(db).dataclass_transformer_params,
metaclass_literal.dataclass_transformer_params(db),
))
}
@@ -1001,7 +943,7 @@ impl<'db> ClassLiteralType<'db> {
/// or those marked as ClassVars are considered.
///
/// Returns [`Symbol::Unbound`] if `name` cannot be found in this class's scope
/// directly. Use [`ClassLiteralType::class_member`] if you require a method that will
/// directly. Use [`ClassLiteral::class_member`] if you require a method that will
/// traverse through the MRO until it finds the member.
pub(super) fn own_class_member(
self,
@@ -1022,14 +964,14 @@ impl<'db> ClassLiteralType<'db> {
// to any method with a `@classmethod` decorator. (`__init__` would remain a special
// case, since it's an _instance_ method where we don't yet know the generic class's
// specialization.)
match (self, ty, specialization, name) {
match (self.generic_context(db), ty, specialization, name) {
(
ClassLiteralType::Generic(origin),
Some(generic_context),
Type::FunctionLiteral(function),
Some(_),
"__new__" | "__init__",
) => Type::FunctionLiteral(
function.with_inherited_generic_context(db, origin.generic_context(db)),
function.with_inherited_generic_context(db, generic_context),
),
_ => ty,
}
@@ -1144,6 +1086,7 @@ impl<'db> ClassLiteralType<'db> {
Parameters::new([Parameter::positional_or_keyword(Name::new_static("other"))
// TODO: could be `Self`.
.with_annotated_type(Type::instance(
db,
self.apply_optional_specialization(db, specialization),
))]),
Some(KnownClass::Bool.to_instance(db)),
@@ -1164,7 +1107,7 @@ impl<'db> ClassLiteralType<'db> {
/// Returns a list of all annotated attributes defined in this class, or any of its superclasses.
///
/// See [`ClassLiteralType::own_dataclass_fields`] for more details.
/// See [`ClassLiteral::own_dataclass_fields`] for more details.
fn dataclass_fields(
self,
db: &'db dyn Db,
@@ -1685,13 +1628,17 @@ impl<'db> ClassLiteralType<'db> {
/// Also, populates `visited_classes` with all base classes of `self`.
fn is_cyclically_defined_recursive<'db>(
db: &'db dyn Db,
class: ClassLiteralType<'db>,
classes_on_stack: &mut IndexSet<ClassLiteralType<'db>>,
visited_classes: &mut IndexSet<ClassLiteralType<'db>>,
class: ClassLiteral<'db>,
classes_on_stack: &mut IndexSet<ClassLiteral<'db>>,
visited_classes: &mut IndexSet<ClassLiteral<'db>>,
) -> bool {
let mut result = false;
for explicit_base_class in class.fully_static_explicit_bases(db) {
let (explicit_base_class_literal, _) = explicit_base_class.class_literal(db);
for explicit_base in class.explicit_bases(db) {
let explicit_base_class_literal = match explicit_base {
Type::ClassLiteral(class_literal) => *class_literal,
Type::GenericAlias(generic_alias) => generic_alias.origin(db),
_ => continue,
};
if !classes_on_stack.insert(explicit_base_class_literal) {
return true;
}
@@ -1705,7 +1652,6 @@ impl<'db> ClassLiteralType<'db> {
visited_classes,
);
}
classes_on_stack.pop();
}
result
@@ -1751,18 +1697,15 @@ impl<'db> ClassLiteralType<'db> {
}
}
impl<'db> From<ClassLiteralType<'db>> for Type<'db> {
fn from(class: ClassLiteralType<'db>) -> Type<'db> {
match class {
ClassLiteralType::NonGeneric(non_generic) => non_generic.into(),
ClassLiteralType::Generic(generic) => generic.into(),
}
impl<'db> From<ClassLiteral<'db>> for Type<'db> {
fn from(class: ClassLiteral<'db>) -> Type<'db> {
Type::ClassLiteral(class)
}
}
/// Representation of a single `Protocol` class definition.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub(super) struct ProtocolClassLiteral<'db>(ClassLiteralType<'db>);
pub(super) struct ProtocolClassLiteral<'db>(ClassLiteral<'db>);
impl<'db> ProtocolClassLiteral<'db> {
/// Returns the protocol members of this class.
@@ -1779,7 +1722,7 @@ impl<'db> ProtocolClassLiteral<'db> {
/// It is illegal for a protocol class to have any instance attributes that are not declared
/// in the protocol's class body. If any are assigned to, they are not taken into account in
/// the protocol's list of members.
pub(super) fn protocol_members(self, db: &'db dyn Db) -> &'db ordermap::set::Slice<Name> {
pub(super) fn protocol_members(self, db: &'db dyn Db) -> FxOrderSet<Name> {
/// The list of excluded members is subject to change between Python versions,
/// especially for dunders, but it probably doesn't matter *too* much if this
/// list goes out of date. It's up to date as of Python commit 87b1ea016b1454b1e83b9113fa9435849b7743aa
@@ -1816,58 +1759,52 @@ impl<'db> ProtocolClassLiteral<'db> {
)
}
#[salsa::tracked(return_ref)]
fn cached_protocol_members<'db>(
db: &'db dyn Db,
class: ClassLiteralType<'db>,
) -> Box<ordermap::set::Slice<Name>> {
let mut members = FxOrderSet::default();
let mut members = FxOrderSet::default();
for parent_protocol in class
.iter_mro(db, None)
.filter_map(ClassBase::into_class)
.filter_map(|class| class.class_literal(db).0.into_protocol_class(db))
{
let parent_scope = parent_protocol.body_scope(db);
let use_def_map = use_def_map(db, parent_scope);
let symbol_table = symbol_table(db, parent_scope);
for parent_protocol in self
.iter_mro(db, None)
.filter_map(ClassBase::into_class)
.filter_map(|class| class.class_literal(db).0.into_protocol_class(db))
{
let parent_scope = parent_protocol.body_scope(db);
let use_def_map = use_def_map(db, parent_scope);
let symbol_table = symbol_table(db, parent_scope);
members.extend(
use_def_map
.all_public_declarations()
.flat_map(|(symbol_id, declarations)| {
symbol_from_declarations(db, declarations)
.map(|symbol| (symbol_id, symbol))
})
.filter_map(|(symbol_id, symbol)| {
symbol.symbol.ignore_possibly_unbound().map(|_| symbol_id)
})
// Bindings in the class body that are not declared in the class body
// are not valid protocol members, and we plan to emit diagnostics for them
// elsewhere. Invalid or not, however, it's important that we still consider
// them to be protocol members. The implementation of `issubclass()` and
// `isinstance()` for runtime-checkable protocols considers them to be protocol
// members at runtime, and it's important that we accurately understand
// type narrowing that uses `isinstance()` or `issubclass()` with
// runtime-checkable protocols.
.chain(use_def_map.all_public_bindings().filter_map(
|(symbol_id, bindings)| {
members.extend(
use_def_map
.all_public_declarations()
.flat_map(|(symbol_id, declarations)| {
symbol_from_declarations(db, declarations).map(|symbol| (symbol_id, symbol))
})
.filter_map(|(symbol_id, symbol)| {
symbol.symbol.ignore_possibly_unbound().map(|_| symbol_id)
})
// Bindings in the class body that are not declared in the class body
// are not valid protocol members, and we plan to emit diagnostics for them
// elsewhere. Invalid or not, however, it's important that we still consider
// them to be protocol members. The implementation of `issubclass()` and
// `isinstance()` for runtime-checkable protocols considers them to be protocol
// members at runtime, and it's important that we accurately understand
// type narrowing that uses `isinstance()` or `issubclass()` with
// runtime-checkable protocols.
.chain(
use_def_map
.all_public_bindings()
.filter_map(|(symbol_id, bindings)| {
symbol_from_bindings(db, bindings)
.ignore_possibly_unbound()
.map(|_| symbol_id)
},
))
.map(|symbol_id| symbol_table.symbol(symbol_id).name())
.filter(|name| !excluded_from_proto_members(name))
.cloned(),
);
}
members.sort();
members.into_boxed_slice()
}),
)
.map(|symbol_id| symbol_table.symbol(symbol_id).name())
.filter(|name| !excluded_from_proto_members(name))
.cloned(),
);
}
cached_protocol_members(db, *self)
members.sort();
members.shrink_to_fit();
members
}
pub(super) fn is_runtime_checkable(self, db: &'db dyn Db) -> bool {
@@ -1877,7 +1814,7 @@ impl<'db> ProtocolClassLiteral<'db> {
}
impl<'db> Deref for ProtocolClassLiteral<'db> {
type Target = ClassLiteralType<'db>;
type Target = ClassLiteral<'db>;
fn deref(&self) -> &Self::Target {
&self.0
@@ -1908,7 +1845,7 @@ impl InheritanceCycle {
/// Note: good candidates are any classes in `[crate::module_resolver::module::KnownModule]`
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(test, derive(strum_macros::EnumIter))]
pub(crate) enum KnownClass {
pub enum KnownClass {
// To figure out where an stdlib symbol is defined, you can go into `crates/red_knot_vendored`
// and grep for the symbol name in any `.pyi` file.
@@ -2157,8 +2094,8 @@ impl<'db> KnownClass {
/// If the class cannot be found in typeshed, a debug-level log message will be emitted stating this.
pub(crate) fn to_instance(self, db: &'db dyn Db) -> Type<'db> {
self.to_class_literal(db)
.into_class_type()
.map(Type::instance)
.to_class_type(db)
.map(|class| Type::instance(db, class))
.unwrap_or_else(Type::unknown)
}
@@ -2169,7 +2106,7 @@ impl<'db> KnownClass {
pub(crate) fn try_to_class_literal(
self,
db: &'db dyn Db,
) -> Result<ClassLiteralType<'db>, KnownClassLookupError<'db>> {
) -> Result<ClassLiteral<'db>, KnownClassLookupError<'db>> {
let symbol = known_module_symbol(db, self.canonical_module(db), self.name(db)).symbol;
match symbol {
Symbol::Type(Type::ClassLiteral(class_literal), Boundness::Bound) => Ok(class_literal),
@@ -2224,7 +2161,7 @@ impl<'db> KnownClass {
/// If the class cannot be found in typeshed, a debug-level log message will be emitted stating this.
pub(crate) fn to_subclass_of(self, db: &'db dyn Db) -> Type<'db> {
self.to_class_literal(db)
.into_class_type()
.to_class_type(db)
.map(|class| SubclassOfType::from(db, class))
.unwrap_or_else(SubclassOfType::subclass_of_unknown)
}
@@ -2575,9 +2512,7 @@ pub(crate) enum KnownClassLookupError<'db> {
SymbolNotAClass { found_type: Type<'db> },
/// There is a symbol by that name in the expected typeshed module,
/// and it's a class definition, but it's possibly unbound.
ClassPossiblyUnbound {
class_literal: ClassLiteralType<'db>,
},
ClassPossiblyUnbound { class_literal: ClassLiteral<'db> },
}
impl<'db> KnownClassLookupError<'db> {

View File

@@ -62,7 +62,7 @@ impl<'db> ClassBase<'db> {
pub(super) fn object(db: &'db dyn Db) -> Self {
KnownClass::Object
.to_class_literal(db)
.into_class_type()
.to_class_type(db)
.map_or(Self::unknown(), Self::Class)
}
@@ -78,12 +78,14 @@ impl<'db> ClassBase<'db> {
Self::Class(literal.default_specialization(db))
}),
Type::GenericAlias(generic) => Some(Self::Class(ClassType::Generic(generic))),
Type::Instance(instance) if instance.class().is_known(db, KnownClass::GenericAlias) => {
Type::NominalInstance(instance)
if instance.class().is_known(db, KnownClass::GenericAlias) =>
{
Self::try_from_type(db, todo_type!("GenericAlias instance"))
}
Type::Union(_) => None, // TODO -- forces consideration of multiple possible MROs?
Type::Intersection(_) => None, // TODO -- probably incorrect?
Type::Instance(_) => None, // TODO -- handle `__mro_entries__`?
Type::NominalInstance(_) => None, // TODO -- handle `__mro_entries__`?
Type::PropertyInstance(_) => None,
Type::Never
| Type::BooleanLiteral(_)
@@ -104,6 +106,7 @@ impl<'db> ClassBase<'db> {
| Type::SubclassOf(_)
| Type::TypeVar(_)
| Type::BoundSuper(_)
| Type::ProtocolInstance(_)
| Type::AlwaysFalsy
| Type::AlwaysTruthy => None,
Type::KnownInstance(known_instance) => match known_instance {
@@ -169,6 +172,7 @@ impl<'db> ClassBase<'db> {
KnownInstanceType::OrderedDict => {
Self::try_from_type(db, KnownClass::OrderedDict.to_class_literal(db))
}
KnownInstanceType::TypedDict => Self::try_from_type(db, todo_type!("TypedDict")),
KnownInstanceType::Callable => {
Self::try_from_type(db, todo_type!("Support for Callable as a base class"))
}

View File

@@ -1,5 +1,5 @@
use super::context::InferContext;
use super::ClassLiteralType;
use super::ClassLiteral;
use crate::declare_lint;
use crate::lint::{Level, LintRegistryBuilder, LintStatus};
use crate::suppression::FileSuppressionId;
@@ -1321,7 +1321,7 @@ pub(crate) fn report_invalid_arguments_to_annotated(
pub(crate) fn report_bad_argument_to_get_protocol_members(
context: &InferContext,
call: &ast::ExprCall,
class: ClassLiteralType,
class: ClassLiteral,
) {
let Some(builder) = context.report_lint(&INVALID_ARGUMENT_TYPE, call) else {
return;

View File

@@ -6,7 +6,7 @@ use ruff_db::display::FormatterJoinExtension;
use ruff_python_ast::str::{Quote, TripleQuotes};
use ruff_python_literal::escape::AsciiEscape;
use crate::types::class::{ClassType, GenericAlias, GenericClass};
use crate::types::class::{ClassLiteral, ClassType, GenericAlias};
use crate::types::generics::{GenericContext, Specialization};
use crate::types::signatures::{Parameter, Parameters, Signature};
use crate::types::{
@@ -17,6 +17,7 @@ use crate::types::{
use crate::Db;
use rustc_hash::FxHashMap;
use super::instance::Protocol;
use super::CallableType;
impl<'db> Type<'db> {
@@ -73,11 +74,32 @@ impl Display for DisplayRepresentation<'_> {
match self.ty {
Type::Dynamic(dynamic) => dynamic.fmt(f),
Type::Never => f.write_str("Never"),
Type::Instance(instance) => match (instance.class(), instance.class().known(self.db)) {
(_, Some(KnownClass::NoneType)) => f.write_str("None"),
(_, Some(KnownClass::NoDefaultType)) => f.write_str("NoDefault"),
(ClassType::NonGeneric(class), _) => f.write_str(&class.class(self.db).name),
(ClassType::Generic(alias), _) => write!(f, "{}", alias.display(self.db)),
Type::NominalInstance(instance) => {
match (instance.class(), instance.class().known(self.db)) {
(_, Some(KnownClass::NoneType)) => f.write_str("None"),
(_, Some(KnownClass::NoDefaultType)) => f.write_str("NoDefault"),
(ClassType::NonGeneric(class), _) => f.write_str(class.name(self.db)),
(ClassType::Generic(alias), _) => write!(f, "{}", alias.display(self.db)),
}
}
Type::ProtocolInstance(protocol) => match protocol.inner() {
Protocol::FromClass(ClassType::NonGeneric(class)) => {
f.write_str(class.name(self.db))
}
Protocol::FromClass(ClassType::Generic(alias)) => alias.display(self.db).fmt(f),
Protocol::Synthesized(synthetic) => {
f.write_str("<Protocol with members ")?;
let member_list = synthetic.members(self.db);
let num_members = member_list.len();
for (i, member) in member_list.iter().enumerate() {
let is_last = i == num_members - 1;
write!(f, "'{member}'")?;
if !is_last {
f.write_str(", ")?;
}
}
f.write_char('>')
}
},
Type::PropertyInstance(_) => f.write_str("property"),
Type::ModuleLiteral(module) => {
@@ -272,7 +294,7 @@ impl<'db> GenericAlias<'db> {
}
pub(crate) struct DisplayGenericAlias<'db> {
origin: GenericClass<'db>,
origin: ClassLiteral<'db>,
specialization: Specialization<'db>,
db: &'db dyn Db,
}
@@ -282,7 +304,7 @@ impl Display for DisplayGenericAlias<'_> {
write!(
f,
"{origin}{specialization}",
origin = self.origin.class(self.db).name,
origin = self.origin.name(self.db),
specialization = self.specialization.display_short(self.db),
)
}

View File

@@ -154,6 +154,10 @@ impl<'db> Specialization<'db> {
pub(crate) fn combine(self, db: &'db dyn Db, other: Self) -> Self {
let generic_context = self.generic_context(db);
assert!(other.generic_context(db) == generic_context);
// TODO special-casing Unknown to mean "no mapping" is not right here, and can give
// confusing/wrong results in cases where there was a mapping found for a typevar, and it
// was of type Unknown. We should probably add a bitset or similar to Specialization that
// explicitly tells us which typevars are mapped.
let types: Box<[_]> = self
.types(db)
.into_iter()

View File

@@ -81,14 +81,13 @@ use crate::types::generics::GenericContext;
use crate::types::mro::MroErrorKind;
use crate::types::unpacker::{UnpackResult, Unpacker};
use crate::types::{
binding_type, todo_type, CallDunderError, CallableSignature, CallableType, Class,
ClassLiteralType, ClassType, DataclassParams, DynamicType, FunctionDecorators, FunctionType,
GenericAlias, GenericClass, IntersectionBuilder, IntersectionType, KnownClass, KnownFunction,
KnownInstanceType, MemberLookupPolicy, MetaclassCandidate, NonGenericClass, Parameter,
ParameterForm, Parameters, Signature, Signatures, SliceLiteralType, StringLiteralType,
SubclassOfType, Symbol, SymbolAndQualifiers, Truthiness, TupleType, Type, TypeAliasType,
TypeAndQualifiers, TypeArrayDisplay, TypeQualifiers, TypeVarBoundOrConstraints,
TypeVarInstance, UnionBuilder, UnionType,
binding_type, todo_type, CallDunderError, CallableSignature, CallableType, ClassLiteral,
ClassType, DataclassParams, DynamicType, FunctionDecorators, FunctionType, GenericAlias,
IntersectionBuilder, IntersectionType, KnownClass, KnownFunction, KnownInstanceType,
MemberLookupPolicy, MetaclassCandidate, Parameter, ParameterForm, Parameters, Signature,
Signatures, SliceLiteralType, StringLiteralType, SubclassOfType, Symbol, SymbolAndQualifiers,
Truthiness, TupleType, Type, TypeAliasType, TypeAndQualifiers, TypeArrayDisplay,
TypeQualifiers, TypeVarBoundOrConstraints, TypeVarInstance, UnionBuilder, UnionType,
};
use crate::unpack::{Unpack, UnpackPosition};
use crate::util::subscript::{PyIndex, PySlice};
@@ -1065,7 +1064,7 @@ impl<'db> TypeInferenceBuilder<'db> {
) -> bool {
match left {
Type::BooleanLiteral(_) | Type::IntLiteral(_) => {}
Type::Instance(instance)
Type::NominalInstance(instance)
if matches!(
instance.class().known(self.db()),
Some(KnownClass::Float | KnownClass::Int | KnownClass::Bool)
@@ -1500,6 +1499,14 @@ impl<'db> TypeInferenceBuilder<'db> {
function_decorators |= FunctionDecorators::ABSTRACT_METHOD;
continue;
}
Some(KnownFunction::Final) => {
function_decorators |= FunctionDecorators::FINAL;
continue;
}
Some(KnownFunction::Override) => {
function_decorators |= FunctionDecorators::OVERRIDE;
continue;
}
_ => {}
}
}
@@ -1825,10 +1832,6 @@ impl<'db> TypeInferenceBuilder<'db> {
}
}
let generic_context = type_params.as_ref().map(|type_params| {
GenericContext::from_type_params(self.db(), self.index, type_params)
});
let body_scope = self
.index
.node_scope(NodeWithScopeRef::Class(class_node))
@@ -1836,20 +1839,14 @@ impl<'db> TypeInferenceBuilder<'db> {
let maybe_known_class = KnownClass::try_from_file_and_name(self.db(), self.file(), name);
let class = Class {
name: name.id.clone(),
let class_ty = Type::from(ClassLiteral::new(
self.db(),
name.id.clone(),
body_scope,
known: maybe_known_class,
maybe_known_class,
dataclass_params,
dataclass_transformer_params,
};
let class_literal = match generic_context {
Some(generic_context) => {
ClassLiteralType::Generic(GenericClass::new(self.db(), class, generic_context))
}
None => ClassLiteralType::NonGeneric(NonGenericClass::new(self.db(), class)),
};
let class_ty = Type::from(class_literal);
));
self.add_declaration_with_binding(
class_node.into(),
@@ -2518,7 +2515,7 @@ impl<'db> TypeInferenceBuilder<'db> {
}
// Super instances do not allow attribute assignment
Type::Instance(instance) if instance.class().is_known(db, KnownClass::Super) => {
Type::NominalInstance(instance) if instance.class().is_known(db, KnownClass::Super) => {
if emit_diagnostics {
if let Some(builder) = self.context.report_lint(&INVALID_ASSIGNMENT, target) {
builder.into_diagnostic(format_args!(
@@ -2543,7 +2540,8 @@ impl<'db> TypeInferenceBuilder<'db> {
Type::Dynamic(..) | Type::Never => true,
Type::Instance(..)
Type::NominalInstance(..)
| Type::ProtocolInstance(_)
| Type::BooleanLiteral(..)
| Type::IntLiteral(..)
| Type::StringLiteral(..)
@@ -3034,7 +3032,7 @@ impl<'db> TypeInferenceBuilder<'db> {
}
// Handle various singletons.
if let Type::Instance(instance) = declared_ty.inner_type() {
if let Type::NominalInstance(instance) = declared_ty.inner_type() {
if instance
.class()
.is_known(self.db(), KnownClass::SpecialForm)
@@ -5010,7 +5008,8 @@ impl<'db> TypeInferenceBuilder<'db> {
| Type::ClassLiteral(_)
| Type::GenericAlias(_)
| Type::SubclassOf(_)
| Type::Instance(_)
| Type::NominalInstance(_)
| Type::ProtocolInstance(_)
| Type::KnownInstance(_)
| Type::PropertyInstance(_)
| Type::Union(_)
@@ -5290,7 +5289,8 @@ impl<'db> TypeInferenceBuilder<'db> {
| Type::ClassLiteral(_)
| Type::GenericAlias(_)
| Type::SubclassOf(_)
| Type::Instance(_)
| Type::NominalInstance(_)
| Type::ProtocolInstance(_)
| Type::KnownInstance(_)
| Type::PropertyInstance(_)
| Type::Intersection(_)
@@ -5315,7 +5315,8 @@ impl<'db> TypeInferenceBuilder<'db> {
| Type::ClassLiteral(_)
| Type::GenericAlias(_)
| Type::SubclassOf(_)
| Type::Instance(_)
| Type::NominalInstance(_)
| Type::ProtocolInstance(_)
| Type::KnownInstance(_)
| Type::PropertyInstance(_)
| Type::Intersection(_)
@@ -5748,13 +5749,13 @@ impl<'db> TypeInferenceBuilder<'db> {
right_ty: right,
}),
},
(Type::IntLiteral(_), Type::Instance(_)) => self.infer_binary_type_comparison(
(Type::IntLiteral(_), Type::NominalInstance(_)) => self.infer_binary_type_comparison(
KnownClass::Int.to_instance(self.db()),
op,
right,
range,
),
(Type::Instance(_), Type::IntLiteral(_)) => self.infer_binary_type_comparison(
(Type::NominalInstance(_), Type::IntLiteral(_)) => self.infer_binary_type_comparison(
left,
op,
KnownClass::Int.to_instance(self.db()),
@@ -5880,7 +5881,7 @@ impl<'db> TypeInferenceBuilder<'db> {
KnownClass::Bytes.to_instance(self.db()),
range,
),
(Type::Tuple(_), Type::Instance(instance))
(Type::Tuple(_), Type::NominalInstance(instance))
if instance
.class()
.is_known(self.db(), KnownClass::VersionInfo) =>
@@ -5892,7 +5893,7 @@ impl<'db> TypeInferenceBuilder<'db> {
range,
)
}
(Type::Instance(instance), Type::Tuple(_))
(Type::NominalInstance(instance), Type::Tuple(_))
if instance
.class()
.is_known(self.db(), KnownClass::VersionInfo) =>
@@ -6210,8 +6211,15 @@ impl<'db> TypeInferenceBuilder<'db> {
// updating all of the subscript logic below to use custom callables for all of the _other_
// special cases, too.
let value_ty = self.infer_expression(value);
if let Type::ClassLiteral(ClassLiteralType::Generic(generic_class)) = value_ty {
return self.infer_explicit_class_specialization(subscript, value_ty, generic_class);
if let Type::ClassLiteral(class) = value_ty {
if let Some(generic_context) = class.generic_context(self.db()) {
return self.infer_explicit_class_specialization(
subscript,
value_ty,
class,
generic_context,
);
}
}
let slice_ty = self.infer_expression(slice);
@@ -6222,7 +6230,8 @@ impl<'db> TypeInferenceBuilder<'db> {
&mut self,
subscript: &ast::ExprSubscript,
value_ty: Type<'db>,
generic_class: GenericClass<'db>,
generic_class: ClassLiteral<'db>,
generic_context: GenericContext<'db>,
) -> Type<'db> {
let slice_node = subscript.slice.as_ref();
let mut call_argument_types = match slice_node {
@@ -6231,7 +6240,6 @@ impl<'db> TypeInferenceBuilder<'db> {
),
_ => CallArgumentTypes::positional([self.infer_type_expression(slice_node)]),
};
let generic_context = generic_class.generic_context(self.db());
let signatures = Signatures::single(CallableSignature::single(
value_ty,
generic_context.signature(self.db()),
@@ -6271,7 +6279,7 @@ impl<'db> TypeInferenceBuilder<'db> {
) -> Type<'db> {
match (value_ty, slice_ty) {
(
Type::Instance(instance),
Type::NominalInstance(instance),
Type::IntLiteral(_) | Type::BooleanLiteral(_) | Type::SliceLiteral(_),
) if instance
.class()
@@ -6503,7 +6511,7 @@ impl<'db> TypeInferenceBuilder<'db> {
return KnownClass::GenericAlias.to_instance(self.db());
}
if let ClassLiteralType::Generic(_) = class {
if class.generic_context(self.db()).is_some() {
// TODO: specialize the generic class using these explicit type
// variable assignments
return value_ty;
@@ -6572,7 +6580,7 @@ impl<'db> TypeInferenceBuilder<'db> {
Err(_) => SliceArg::Unsupported,
},
Some(Type::BooleanLiteral(b)) => SliceArg::Arg(Some(i32::from(b))),
Some(Type::Instance(instance))
Some(Type::NominalInstance(instance))
if instance.class().is_known(self.db(), KnownClass::NoneType) =>
{
SliceArg::Arg(None)
@@ -7361,18 +7369,26 @@ impl<'db> TypeInferenceBuilder<'db> {
self.infer_type_expression(slice);
value_ty
}
Type::ClassLiteral(ClassLiteralType::Generic(generic_class)) => {
let specialized_class =
self.infer_explicit_class_specialization(subscript, value_ty, generic_class);
specialized_class
.in_type_expression(self.db())
.unwrap_or(Type::unknown())
}
Type::ClassLiteral(ClassLiteralType::NonGeneric(_)) => {
// TODO: Once we know that e.g. `list` is generic, emit a diagnostic if you try to
// specialize a non-generic class.
self.infer_type_expression(slice);
todo_type!("specialized non-generic class")
Type::ClassLiteral(class) => {
match class.generic_context(self.db()) {
Some(generic_context) => {
let specialized_class = self.infer_explicit_class_specialization(
subscript,
value_ty,
class,
generic_context,
);
specialized_class
.in_type_expression(self.db())
.unwrap_or(Type::unknown())
}
None => {
// TODO: Once we know that e.g. `list` is generic, emit a diagnostic if you try to
// specialize a non-generic class.
self.infer_type_expression(slice);
todo_type!("specialized non-generic class")
}
}
}
_ => {
// TODO: Emit a diagnostic once we've implemented all valid subscript type
@@ -7698,6 +7714,8 @@ impl<'db> TypeInferenceBuilder<'db> {
| KnownInstanceType::Any
| KnownInstanceType::AlwaysTruthy
| KnownInstanceType::AlwaysFalsy => {
self.infer_type_expression(arguments_slice);
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
builder.into_diagnostic(format_args!(
"Type `{}` expected no type parameter",
@@ -7708,7 +7726,10 @@ impl<'db> TypeInferenceBuilder<'db> {
}
KnownInstanceType::TypingSelf
| KnownInstanceType::TypeAlias
| KnownInstanceType::TypedDict
| KnownInstanceType::Unknown => {
self.infer_type_expression(arguments_slice);
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
builder.into_diagnostic(format_args!(
"Special form `{}` expected no type parameter",
@@ -7718,6 +7739,8 @@ impl<'db> TypeInferenceBuilder<'db> {
Type::unknown()
}
KnownInstanceType::LiteralString => {
self.infer_type_expression(arguments_slice);
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
let mut diag = builder.into_diagnostic(format_args!(
"Type `{}` expected no type parameter",

View File

@@ -1,16 +1,22 @@
//! Instance types: both nominal and structural.
use ruff_python_ast::name::Name;
use super::{ClassType, KnownClass, SubclassOfType, Type};
use crate::Db;
use crate::{Db, FxOrderSet};
impl<'db> Type<'db> {
pub(crate) const fn instance(class: ClassType<'db>) -> Self {
Self::Instance(InstanceType { class })
pub(crate) fn instance(db: &'db dyn Db, class: ClassType<'db>) -> Self {
if class.is_protocol(db) {
Self::ProtocolInstance(ProtocolInstanceType(Protocol::FromClass(class)))
} else {
Self::NominalInstance(NominalInstanceType { class })
}
}
pub(crate) const fn into_instance(self) -> Option<InstanceType<'db>> {
pub(crate) const fn into_nominal_instance(self) -> Option<NominalInstanceType<'db>> {
match self {
Type::Instance(instance_type) => Some(instance_type),
Type::NominalInstance(instance_type) => Some(instance_type),
_ => None,
}
}
@@ -18,13 +24,13 @@ impl<'db> Type<'db> {
/// A type representing the set of runtime objects which are instances of a certain nominal class.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, salsa::Update)]
pub struct InstanceType<'db> {
// Keep this field private, so that the only way of constructing `InstanceType` instances
pub struct NominalInstanceType<'db> {
// Keep this field private, so that the only way of constructing `NominalInstanceType` instances
// is through the `Type::instance` constructor function.
class: ClassType<'db>,
}
impl<'db> InstanceType<'db> {
impl<'db> NominalInstanceType<'db> {
pub(super) fn class(self) -> ClassType<'db> {
self.class
}
@@ -87,8 +93,134 @@ impl<'db> InstanceType<'db> {
}
}
impl<'db> From<InstanceType<'db>> for Type<'db> {
fn from(value: InstanceType<'db>) -> Self {
Self::Instance(value)
impl<'db> From<NominalInstanceType<'db>> for Type<'db> {
fn from(value: NominalInstanceType<'db>) -> Self {
Self::NominalInstance(value)
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord, salsa::Update)]
pub struct ProtocolInstanceType<'db>(
// Keep the inner field here private,
// so that the only way of constructing `ProtocolInstanceType` instances
// is through the `Type::instance` constructor function.
Protocol<'db>,
);
impl<'db> ProtocolInstanceType<'db> {
pub(super) fn protocol_members(self, db: &'db dyn Db) -> &'db FxOrderSet<Name> {
self.0.protocol_members(db)
}
pub(super) fn inner(self) -> Protocol<'db> {
self.0
}
pub(super) fn to_meta_type(self, db: &'db dyn Db) -> Type<'db> {
match self.0 {
Protocol::FromClass(class) => SubclassOfType::from(db, class),
// TODO: we can and should do better here.
//
// This is supported by mypy, and should be supported by us as well.
// We'll need to come up with a better solution for the meta-type of
// synthesized protocols to solve this:
//
// ```py
// from typing import Callable
//
// def foo(x: Callable[[], int]) -> None:
// reveal_type(type(x)) # mypy: "type[def (builtins.int) -> builtins.str]"
// reveal_type(type(x).__call__) # mypy: "def (*args: Any, **kwds: Any) -> Any"
// ```
Protocol::Synthesized(_) => KnownClass::Type.to_instance(db),
}
}
pub(super) fn normalized(self, db: &'db dyn Db) -> Type<'db> {
let object = KnownClass::Object.to_instance(db);
if object.satisfies_protocol(db, self) {
return object;
}
match self.0 {
Protocol::FromClass(_) => Type::ProtocolInstance(Self(Protocol::Synthesized(
SynthesizedProtocolType::new(db, self.protocol_members(db)),
))),
Protocol::Synthesized(_) => Type::ProtocolInstance(self),
}
}
/// TODO: should iterate over the types of the members
/// and check if any of them contain `Todo` types
#[expect(clippy::unused_self)]
pub(super) fn contains_todo(self) -> bool {
false
}
/// TODO: should not be considered fully static if any members do not have fully static types
#[expect(clippy::unused_self)]
pub(super) fn is_fully_static(self) -> bool {
true
}
/// TODO: consider the types of the members as well as their existence
pub(super) fn is_subtype_of(self, db: &'db dyn Db, other: Self) -> bool {
self.protocol_members(db)
.is_superset(other.protocol_members(db))
}
/// TODO: consider the types of the members as well as their existence
pub(super) fn is_assignable_to(self, db: &'db dyn Db, other: Self) -> bool {
self.is_subtype_of(db, other)
}
/// TODO: consider the types of the members as well as their existence
pub(super) fn is_equivalent_to(self, db: &'db dyn Db, other: Self) -> bool {
self.normalized(db) == other.normalized(db)
}
/// TODO: consider the types of the members as well as their existence
pub(super) fn is_gradual_equivalent_to(self, db: &'db dyn Db, other: Self) -> bool {
self.is_equivalent_to(db, other)
}
/// TODO: a protocol `X` is disjoint from a protocol `Y` if `X` and `Y`
/// have a member with the same name but disjoint types
#[expect(clippy::unused_self)]
pub(super) fn is_disjoint_from(self, _db: &'db dyn Db, _other: Self) -> bool {
false
}
}
/// Private inner enum to represent the two kinds of protocol types.
/// This is not exposed publicly, so that the only way of constructing `Protocol` instances
/// is through the [`Type::instance`] constructor function.
#[derive(
Copy, Clone, Debug, Eq, PartialEq, Hash, salsa::Update, salsa::Supertype, PartialOrd, Ord,
)]
pub(super) enum Protocol<'db> {
FromClass(ClassType<'db>),
Synthesized(SynthesizedProtocolType<'db>),
}
#[salsa::tracked]
impl<'db> Protocol<'db> {
#[salsa::tracked(return_ref)]
fn protocol_members(self, db: &'db dyn Db) -> FxOrderSet<Name> {
match self {
Self::FromClass(class) => class
.class_literal(db)
.0
.into_protocol_class(db)
.expect("Protocol class literal should be a protocol class")
.protocol_members(db),
Self::Synthesized(synthesized) => synthesized.members(db).clone(),
}
}
}
#[salsa::interned(debug)]
pub(super) struct SynthesizedProtocolType<'db> {
#[return_ref]
pub(super) members: FxOrderSet<Name>,
}

View File

@@ -1,6 +1,6 @@
//! The `KnownInstance` type.
//!
//! Despite its name, this is quite a different type from [`super::InstanceType`].
//! Despite its name, this is quite a different type from [`super::NominalInstanceType`].
//! For the vast majority of instance-types in Python, we cannot say how many possible
//! inhabitants there are or could be of that type at runtime. Each variant of the
//! [`KnownInstanceType`] enum, however, represents a specific runtime symbol
@@ -95,6 +95,7 @@ pub enum KnownInstanceType<'db> {
NotRequired,
TypeAlias,
TypeGuard,
TypedDict,
TypeIs,
ReadOnly,
// TODO: fill this enum out with more special forms, etc.
@@ -125,6 +126,7 @@ impl<'db> KnownInstanceType<'db> {
| Self::NotRequired
| Self::TypeAlias
| Self::TypeGuard
| Self::TypedDict
| Self::TypeIs
| Self::List
| Self::Dict
@@ -172,6 +174,7 @@ impl<'db> KnownInstanceType<'db> {
Self::NotRequired => "typing.NotRequired",
Self::TypeAlias => "typing.TypeAlias",
Self::TypeGuard => "typing.TypeGuard",
Self::TypedDict => "typing.TypedDict",
Self::TypeIs => "typing.TypeIs",
Self::List => "typing.List",
Self::Dict => "typing.Dict",
@@ -220,6 +223,7 @@ impl<'db> KnownInstanceType<'db> {
Self::NotRequired => KnownClass::SpecialForm,
Self::TypeAlias => KnownClass::SpecialForm,
Self::TypeGuard => KnownClass::SpecialForm,
Self::TypedDict => KnownClass::SpecialForm,
Self::TypeIs => KnownClass::SpecialForm,
Self::ReadOnly => KnownClass::SpecialForm,
Self::List => KnownClass::StdlibAlias,
@@ -249,7 +253,7 @@ impl<'db> KnownInstanceType<'db> {
///
/// For example, the symbol `typing.Literal` is an instance of `typing._SpecialForm`,
/// so `KnownInstanceType::Literal.instance_fallback(db)`
/// returns `Type::Instance(InstanceType { class: <typing._SpecialForm> })`.
/// returns `Type::NominalInstance(NominalInstanceType { class: <typing._SpecialForm> })`.
pub(super) fn instance_fallback(self, db: &dyn Db) -> Type {
self.class().to_instance(db)
}
@@ -293,6 +297,7 @@ impl<'db> KnownInstanceType<'db> {
"Required" => Self::Required,
"TypeAlias" => Self::TypeAlias,
"TypeGuard" => Self::TypeGuard,
"TypedDict" => Self::TypedDict,
"TypeIs" => Self::TypeIs,
"ReadOnly" => Self::ReadOnly,
"Concatenate" => Self::Concatenate,
@@ -350,6 +355,7 @@ impl<'db> KnownInstanceType<'db> {
| Self::NotRequired
| Self::TypeAlias
| Self::TypeGuard
| Self::TypedDict
| Self::TypeIs
| Self::ReadOnly
| Self::TypeAliasType(_)

View File

@@ -5,13 +5,13 @@ use rustc_hash::FxHashSet;
use crate::types::class_base::ClassBase;
use crate::types::generics::Specialization;
use crate::types::{ClassLiteralType, ClassType, Type};
use crate::types::{ClassLiteral, ClassType, Type};
use crate::Db;
/// The inferred method resolution order of a given class.
///
/// An MRO cannot contain non-specialized generic classes. (This is why [`ClassBase`] contains a
/// [`ClassType`], not a [`ClassLiteralType`].) Any generic classes in a base class list are always
/// [`ClassType`], not a [`ClassLiteral`].) Any generic classes in a base class list are always
/// specialized — either because the class is explicitly specialized if there is a subscript
/// expression, or because we create the default specialization if there isn't.
///
@@ -33,7 +33,7 @@ pub(super) struct Mro<'db>(Box<[ClassBase<'db>]>);
impl<'db> Mro<'db> {
/// Attempt to resolve the MRO of a given class. Because we derive the MRO from the list of
/// base classes in the class definition, this operation is performed on a [class
/// literal][ClassLiteralType], not a [class type][ClassType]. (You can _also_ get the MRO of a
/// literal][ClassLiteral], not a [class type][ClassType]. (You can _also_ get the MRO of a
/// class type, but this is done by first getting the MRO of the underlying class literal, and
/// specializing each base class as needed if the class type is a generic alias.)
///
@@ -47,7 +47,7 @@ impl<'db> Mro<'db> {
/// [`super::infer::TypeInferenceBuilder::infer_region_scope`].)
pub(super) fn of_class(
db: &'db dyn Db,
class: ClassLiteralType<'db>,
class: ClassLiteral<'db>,
specialization: Option<Specialization<'db>>,
) -> Result<Self, MroError<'db>> {
Self::of_class_impl(db, class, specialization).map_err(|err| {
@@ -65,7 +65,7 @@ impl<'db> Mro<'db> {
fn of_class_impl(
db: &'db dyn Db,
class: ClassLiteralType<'db>,
class: ClassLiteral<'db>,
specialization: Option<Specialization<'db>>,
) -> Result<Self, MroErrorKind<'db>> {
let class_bases = class.explicit_bases(db);
@@ -220,12 +220,12 @@ impl<'db> FromIterator<ClassBase<'db>> for Mro<'db> {
///
/// Even for first-party code, where we will have to resolve the MRO for every class we encounter,
/// loading the cached MRO comes with a certain amount of overhead, so it's best to avoid calling the
/// Salsa-tracked [`ClassLiteralType::try_mro`] method unless it's absolutely necessary.
/// Salsa-tracked [`ClassLiteral::try_mro`] method unless it's absolutely necessary.
pub(super) struct MroIterator<'db> {
db: &'db dyn Db,
/// The class whose MRO we're iterating over
class: ClassLiteralType<'db>,
class: ClassLiteral<'db>,
/// The specialization to apply to each MRO element, if any
specialization: Option<Specialization<'db>>,
@@ -244,7 +244,7 @@ pub(super) struct MroIterator<'db> {
impl<'db> MroIterator<'db> {
pub(super) fn new(
db: &'db dyn Db,
class: ClassLiteralType<'db>,
class: ClassLiteral<'db>,
specialization: Option<Specialization<'db>>,
) -> Self {
Self {
@@ -326,11 +326,11 @@ pub(super) enum MroErrorKind<'db> {
/// The class has one or more duplicate bases.
///
/// This variant records the indices and [`ClassLiteralType`]s
/// This variant records the indices and [`ClassLiteral`]s
/// of the duplicate bases. The indices are the indices of nodes
/// in the bases list of the class's [`StmtClassDef`](ruff_python_ast::StmtClassDef) node.
/// Each index is the index of a node representing a duplicate base.
DuplicateBases(Box<[(usize, ClassLiteralType<'db>)]>),
DuplicateBases(Box<[(usize, ClassLiteral<'db>)]>),
/// The MRO is otherwise unresolvable through the C3-merge algorithm.
///

View File

@@ -8,8 +8,8 @@ use crate::semantic_index::symbol::{ScopeId, ScopedSymbolId, SymbolTable};
use crate::semantic_index::symbol_table;
use crate::types::infer::infer_same_file_expression_type;
use crate::types::{
infer_expression_types, ClassLiteralType, IntersectionBuilder, KnownClass, SubclassOfType,
Truthiness, Type, UnionBuilder,
infer_expression_types, IntersectionBuilder, KnownClass, SubclassOfType, Truthiness, Type,
UnionBuilder,
};
use crate::Db;
use itertools::Itertools;
@@ -159,7 +159,7 @@ impl KnownConstraintFunction {
/// union types are not yet supported. Returns `None` if the `classinfo` argument has a wrong type.
fn generate_constraint<'db>(self, db: &'db dyn Db, classinfo: Type<'db>) -> Option<Type<'db>> {
let constraint_fn = |class| match self {
KnownConstraintFunction::IsInstance => Type::instance(class),
KnownConstraintFunction::IsInstance => Type::instance(db, class),
KnownConstraintFunction::IsSubclass => SubclassOfType::from(db, class),
};
@@ -472,7 +472,9 @@ impl<'db> NarrowingConstraintsBuilder<'db> {
union.map(db, |ty| filter_to_cannot_be_equal(db, *ty, rhs_ty))
}
// Treat `bool` as `Literal[True, False]`.
Type::Instance(instance) if instance.class().is_known(db, KnownClass::Bool) => {
Type::NominalInstance(instance)
if instance.class().is_known(db, KnownClass::Bool) =>
{
UnionType::from_elements(
db,
[Type::BooleanLiteral(true), Type::BooleanLiteral(false)]
@@ -501,7 +503,7 @@ impl<'db> NarrowingConstraintsBuilder<'db> {
fn evaluate_expr_ne(&mut self, lhs_ty: Type<'db>, rhs_ty: Type<'db>) -> Option<Type<'db>> {
match (lhs_ty, rhs_ty) {
(Type::Instance(instance), Type::IntLiteral(i))
(Type::NominalInstance(instance), Type::IntLiteral(i))
if instance.class().is_known(self.db, KnownClass::Bool) =>
{
if i == 0 {
@@ -648,9 +650,7 @@ impl<'db> NarrowingConstraintsBuilder<'db> {
}) if keywords.is_empty() => {
let rhs_class = match rhs_ty {
Type::ClassLiteral(class) => class,
Type::GenericAlias(alias) => {
ClassLiteralType::Generic(alias.origin(self.db))
}
Type::GenericAlias(alias) => alias.origin(self.db),
_ => {
continue;
}
@@ -684,7 +684,7 @@ impl<'db> NarrowingConstraintsBuilder<'db> {
let symbol = self.expect_expr_name_symbol(id);
constraints.insert(
symbol,
Type::instance(rhs_class.unknown_specialization(self.db)),
Type::instance(self.db, rhs_class.unknown_specialization(self.db)),
);
}
}

View File

@@ -58,7 +58,7 @@ macro_rules! type_property_test {
mod stable {
use super::union;
use crate::types::Type;
use crate::types::{CallableType, Type};
// Reflexivity: `T` is equivalent to itself.
type_property_test!(
@@ -169,6 +169,14 @@ mod stable {
forall types t. t.is_fully_static(db) => Type::Never.is_subtype_of(db, t)
);
// Similar to `Never`, a fully-static "bottom" callable type should be a subtype of all
// fully-static callable types
type_property_test!(
bottom_callable_is_subtype_of_all_fully_static_callable, db,
forall types t. t.is_callable_type() && t.is_fully_static(db)
=> CallableType::bottom(db).is_subtype_of(db, t)
);
// For any two fully static types, each type in the pair must be a subtype of their union.
type_property_test!(
all_fully_static_type_pairs_are_subtype_of_their_union, db,

View File

@@ -934,6 +934,19 @@ impl<'db> Parameters<'db> {
}
}
/// Return parameters that represents `(*args: object, **kwargs: object)`.
#[cfg(test)]
pub(crate) fn object(db: &'db dyn Db) -> Self {
Self {
value: vec![
Parameter::variadic(Name::new_static("args")).with_annotated_type(Type::object(db)),
Parameter::keyword_variadic(Name::new_static("kwargs"))
.with_annotated_type(Type::object(db)),
],
is_gradual: false,
}
}
fn from_parameters(
db: &'db dyn Db,
definition: Definition<'db>,

View File

@@ -4,7 +4,7 @@ use crate::db::Db;
use crate::symbol::{Boundness, Symbol};
use crate::types::class_base::ClassBase;
use crate::types::diagnostic::report_base_with_incompatible_slots;
use crate::types::{ClassLiteralType, Type};
use crate::types::{ClassLiteral, Type};
use super::InferContext;
@@ -23,7 +23,7 @@ enum SlotsKind {
}
impl SlotsKind {
fn from(db: &dyn Db, base: ClassLiteralType) -> Self {
fn from(db: &dyn Db, base: ClassLiteral) -> Self {
let Symbol::Type(slots_ty, bound) = base.own_class_member(db, None, "__slots__").symbol
else {
return Self::NotSpecified;
@@ -53,7 +53,7 @@ impl SlotsKind {
pub(super) fn check_class_slots(
context: &InferContext,
class: ClassLiteralType,
class: ClassLiteral,
node: &ast::StmtClassDef,
) {
let db = context.db();

View File

@@ -16,8 +16,8 @@ impl<'db> SubclassOfType<'db> {
/// This method does not always return a [`Type::SubclassOf`] variant.
/// If the class object is known to be a final class,
/// this method will return a [`Type::ClassLiteral`] variant; this is a more precise type.
/// If the class object is `builtins.object`, `Type::Instance(<builtins.type>)` will be returned;
/// this is no more precise, but it is exactly equivalent to `type[object]`.
/// If the class object is `builtins.object`, `Type::NominalInstance(<builtins.type>)`
/// will be returned; this is no more precise, but it is exactly equivalent to `type[object]`.
///
/// The eager normalization here means that we do not need to worry elsewhere about distinguishing
/// between `@final` classes and other classes when dealing with [`Type::SubclassOf`] variants.
@@ -94,9 +94,9 @@ impl<'db> SubclassOfType<'db> {
}
}
pub(crate) fn to_instance(self) -> Type<'db> {
pub(crate) fn to_instance(self, db: &'db dyn Db) -> Type<'db> {
match self.subclass_of {
SubclassOfInner::Class(class) => Type::instance(class),
SubclassOfInner::Class(class) => Type::instance(db, class),
SubclassOfInner::Dynamic(dynamic_type) => Type::Dynamic(dynamic_type),
}
}

View File

@@ -126,10 +126,20 @@ pub(super) fn union_or_intersection_elements_ordering<'db>(
(Type::SubclassOf(_), _) => Ordering::Less,
(_, Type::SubclassOf(_)) => Ordering::Greater,
(Type::Instance(left), Type::Instance(right)) => left.class().cmp(&right.class()),
(Type::Instance(_), _) => Ordering::Less,
(_, Type::Instance(_)) => Ordering::Greater,
(Type::NominalInstance(left), Type::NominalInstance(right)) => {
left.class().cmp(&right.class())
}
(Type::NominalInstance(_), _) => Ordering::Less,
(_, Type::NominalInstance(_)) => Ordering::Greater,
(Type::ProtocolInstance(left_proto), Type::ProtocolInstance(right_proto)) => {
debug_assert_eq!(*left, left_proto.normalized(db));
debug_assert_eq!(*right, right_proto.normalized(db));
left_proto.cmp(right_proto)
}
(Type::ProtocolInstance(_), _) => Ordering::Less,
(_, Type::ProtocolInstance(_)) => Ordering::Greater,
(Type::TypeVar(left), Type::TypeVar(right)) => left.cmp(right),
(Type::TypeVar(_), _) => Ordering::Less,
@@ -221,6 +231,9 @@ pub(super) fn union_or_intersection_elements_ordering<'db>(
(KnownInstanceType::TypeGuard, _) => Ordering::Less,
(_, KnownInstanceType::TypeGuard) => Ordering::Greater,
(KnownInstanceType::TypedDict, _) => Ordering::Less,
(_, KnownInstanceType::TypedDict) => Ordering::Greater,
(KnownInstanceType::List, _) => Ordering::Less,
(_, KnownInstanceType::List) => Ordering::Greater,

View File

@@ -27,6 +27,16 @@ pub enum PositionEncoding {
UTF8,
}
impl From<PositionEncoding> for ruff_source_file::PositionEncoding {
fn from(value: PositionEncoding) -> Self {
match value {
PositionEncoding::UTF8 => Self::Utf8,
PositionEncoding::UTF16 => Self::Utf16,
PositionEncoding::UTF32 => Self::Utf32,
}
}
}
/// A unique document ID, derived from a URL passed as part of an LSP request.
/// This document ID can point to either be a standalone Python file, a full notebook, or a cell within a notebook.
#[derive(Clone, Debug)]

View File

@@ -9,8 +9,8 @@ use red_knot_python_semantic::Db;
use ruff_db::files::FileRange;
use ruff_db::source::{line_index, source_text};
use ruff_notebook::NotebookIndex;
use ruff_source_file::OneIndexed;
use ruff_source_file::{LineIndex, SourceLocation};
use ruff_source_file::LineIndex;
use ruff_source_file::{OneIndexed, SourceLocation};
use ruff_text_size::{Ranged, TextRange, TextSize};
#[expect(dead_code)]
@@ -46,7 +46,7 @@ impl TextSizeExt for TextSize {
index: &LineIndex,
encoding: PositionEncoding,
) -> types::Position {
let source_location = offset_to_source_location(self, text, index, encoding);
let source_location = index.source_location(self, text, encoding.into());
source_location_to_position(&source_location)
}
}
@@ -75,36 +75,14 @@ fn u32_index_to_usize(index: u32) -> usize {
impl PositionExt for lsp_types::Position {
fn to_text_size(&self, text: &str, index: &LineIndex, encoding: PositionEncoding) -> TextSize {
let start_line = index.line_range(
OneIndexed::from_zero_indexed(u32_index_to_usize(self.line)),
index.offset(
SourceLocation {
line: OneIndexed::from_zero_indexed(u32_index_to_usize(self.line)),
character_offset: OneIndexed::from_zero_indexed(u32_index_to_usize(self.character)),
},
text,
);
let start_column_offset = match encoding {
PositionEncoding::UTF8 => TextSize::new(self.character),
PositionEncoding::UTF16 => {
// Fast path for ASCII only documents
if index.is_ascii() {
TextSize::new(self.character)
} else {
// UTF16 encodes characters either as one or two 16 bit words.
// The position in `range` is the 16-bit word offset from the start of the line (and not the character offset)
// UTF-16 with a text that may use variable-length characters.
utf8_column_offset(self.character, &text[start_line])
}
}
PositionEncoding::UTF32 => {
// UTF-32 uses 4 bytes for each character. Meaning, the position in range is a character offset.
return index.offset(
OneIndexed::from_zero_indexed(u32_index_to_usize(self.line)),
OneIndexed::from_zero_indexed(u32_index_to_usize(self.character)),
text,
);
}
};
start_line.start() + start_column_offset.clamp(TextSize::new(0), start_line.end())
encoding.into(),
)
}
}
@@ -142,26 +120,23 @@ impl ToRangeExt for TextRange {
notebook_index: &NotebookIndex,
encoding: PositionEncoding,
) -> NotebookRange {
let start = offset_to_source_location(self.start(), text, source_index, encoding);
let mut end = offset_to_source_location(self.end(), text, source_index, encoding);
let starting_cell = notebook_index.cell(start.row);
let start = source_index.source_location(self.start(), text, encoding.into());
let mut end = source_index.source_location(self.end(), text, encoding.into());
let starting_cell = notebook_index.cell(start.line);
// weird edge case here - if the end of the range is where the newline after the cell got added (making it 'out of bounds')
// we need to move it one character back (which should place it at the end of the last line).
// we test this by checking if the ending offset is in a different (or nonexistent) cell compared to the cell of the starting offset.
if notebook_index.cell(end.row) != starting_cell {
end.row = end.row.saturating_sub(1);
end.column = offset_to_source_location(
self.end().checked_sub(1.into()).unwrap_or_default(),
text,
source_index,
encoding,
)
.column;
if notebook_index.cell(end.line) != starting_cell {
end.line = end.line.saturating_sub(1);
let offset = self.end().checked_sub(1.into()).unwrap_or_default();
end.character_offset = source_index
.source_location(offset, text, encoding.into())
.character_offset;
}
let start = source_location_to_position(&notebook_index.translate_location(&start));
let end = source_location_to_position(&notebook_index.translate_location(&end));
let start = source_location_to_position(&notebook_index.translate_source_location(&start));
let end = source_location_to_position(&notebook_index.translate_source_location(&end));
NotebookRange {
cell: starting_cell
@@ -172,67 +147,10 @@ impl ToRangeExt for TextRange {
}
}
/// Converts a UTF-16 code unit offset for a given line into a UTF-8 column number.
fn utf8_column_offset(utf16_code_unit_offset: u32, line: &str) -> TextSize {
let mut utf8_code_unit_offset = TextSize::new(0);
let mut i = 0u32;
for c in line.chars() {
if i >= utf16_code_unit_offset {
break;
}
// Count characters encoded as two 16 bit words as 2 characters.
{
utf8_code_unit_offset +=
TextSize::new(u32::try_from(c.len_utf8()).expect("utf8 len always <=4"));
i += u32::try_from(c.len_utf16()).expect("utf16 len always <=2");
}
}
utf8_code_unit_offset
}
fn offset_to_source_location(
offset: TextSize,
text: &str,
index: &LineIndex,
encoding: PositionEncoding,
) -> SourceLocation {
match encoding {
PositionEncoding::UTF8 => {
let row = index.line_index(offset);
let column = offset - index.line_start(row, text);
SourceLocation {
column: OneIndexed::from_zero_indexed(column.to_usize()),
row,
}
}
PositionEncoding::UTF16 => {
let row = index.line_index(offset);
let column = if index.is_ascii() {
(offset - index.line_start(row, text)).to_usize()
} else {
let up_to_line = &text[TextRange::new(index.line_start(row, text), offset)];
up_to_line.encode_utf16().count()
};
SourceLocation {
column: OneIndexed::from_zero_indexed(column),
row,
}
}
PositionEncoding::UTF32 => index.source_location(offset, text),
}
}
fn source_location_to_position(location: &SourceLocation) -> types::Position {
types::Position {
line: u32::try_from(location.row.to_zero_indexed()).expect("row usize fits in u32"),
character: u32::try_from(location.column.to_zero_indexed())
line: u32::try_from(location.line.to_zero_indexed()).expect("line usize fits in u32"),
character: u32::try_from(location.character_offset.to_zero_indexed())
.expect("character usize fits in u32"),
}
}

View File

@@ -33,6 +33,7 @@ smallvec = { workspace = true }
serde = { workspace = true }
tempfile = { workspace = true }
toml = { workspace = true }
tracing = { workspace = true }
thiserror = { workspace = true }
[lints]

View File

@@ -96,7 +96,10 @@ impl SemanticDb for Db {
#[salsa::db]
impl salsa::Database for Db {
fn salsa_event(&self, _event: &dyn Fn() -> salsa::Event) {}
fn salsa_event(&self, event: &dyn Fn() -> salsa::Event) {
let event = event();
tracing::trace!("event: {:?}", event);
}
}
impl DbWithWritableSystem for Db {

View File

@@ -263,7 +263,7 @@ impl Matcher {
.and_then(|span| span.range())
.map(|range| {
self.line_index
.source_location(range.start(), &self.source)
.line_column(range.start(), &self.source)
.column
})
.unwrap_or(OneIndexed::from_zero_indexed(0))

View File

@@ -1,36 +0,0 @@
from typing_extensions import TypeAlias
_VersionInfo: TypeAlias = tuple[int, int, int, str, int]
class _Feature:
def __init__(self, optionalRelease: _VersionInfo, mandatoryRelease: _VersionInfo | None, compiler_flag: int) -> None: ...
def getOptionalRelease(self) -> _VersionInfo: ...
def getMandatoryRelease(self) -> _VersionInfo | None: ...
compiler_flag: int
absolute_import: _Feature
division: _Feature
generators: _Feature
nested_scopes: _Feature
print_function: _Feature
unicode_literals: _Feature
with_statement: _Feature
barry_as_FLUFL: _Feature
generator_stop: _Feature
annotations: _Feature
all_feature_names: list[str] # undocumented
__all__ = [
"all_feature_names",
"absolute_import",
"division",
"generators",
"nested_scopes",
"print_function",
"unicode_literals",
"with_statement",
"barry_as_FLUFL",
"generator_stop",
"annotations",
]

View File

@@ -1,3 +0,0 @@
from typing import Any
def __getattr__(name: str) -> Any: ...

View File

@@ -1,138 +0,0 @@
import sys
from ast import (
AST as AST,
Add as Add,
And as And,
AnnAssign as AnnAssign,
Assert as Assert,
Assign as Assign,
AsyncFor as AsyncFor,
AsyncFunctionDef as AsyncFunctionDef,
AsyncWith as AsyncWith,
Attribute as Attribute,
AugAssign as AugAssign,
Await as Await,
BinOp as BinOp,
BitAnd as BitAnd,
BitOr as BitOr,
BitXor as BitXor,
BoolOp as BoolOp,
Break as Break,
Call as Call,
ClassDef as ClassDef,
Compare as Compare,
Constant as Constant,
Continue as Continue,
Del as Del,
Delete as Delete,
Dict as Dict,
DictComp as DictComp,
Div as Div,
Eq as Eq,
ExceptHandler as ExceptHandler,
Expr as Expr,
Expression as Expression,
FloorDiv as FloorDiv,
For as For,
FormattedValue as FormattedValue,
FunctionDef as FunctionDef,
FunctionType as FunctionType,
GeneratorExp as GeneratorExp,
Global as Global,
Gt as Gt,
GtE as GtE,
If as If,
IfExp as IfExp,
Import as Import,
ImportFrom as ImportFrom,
In as In,
Interactive as Interactive,
Invert as Invert,
Is as Is,
IsNot as IsNot,
JoinedStr as JoinedStr,
Lambda as Lambda,
List as List,
ListComp as ListComp,
Load as Load,
LShift as LShift,
Lt as Lt,
LtE as LtE,
MatMult as MatMult,
Mod as Mod,
Module as Module,
Mult as Mult,
Name as Name,
NamedExpr as NamedExpr,
Nonlocal as Nonlocal,
Not as Not,
NotEq as NotEq,
NotIn as NotIn,
Or as Or,
Pass as Pass,
Pow as Pow,
Raise as Raise,
Return as Return,
RShift as RShift,
Set as Set,
SetComp as SetComp,
Slice as Slice,
Starred as Starred,
Store as Store,
Sub as Sub,
Subscript as Subscript,
Try as Try,
Tuple as Tuple,
TypeIgnore as TypeIgnore,
UAdd as UAdd,
UnaryOp as UnaryOp,
USub as USub,
While as While,
With as With,
Yield as Yield,
YieldFrom as YieldFrom,
alias as alias,
arg as arg,
arguments as arguments,
boolop as boolop,
cmpop as cmpop,
comprehension as comprehension,
excepthandler as excepthandler,
expr as expr,
expr_context as expr_context,
keyword as keyword,
mod as mod,
operator as operator,
stmt as stmt,
type_ignore as type_ignore,
unaryop as unaryop,
withitem as withitem,
)
from typing import Literal
if sys.version_info >= (3, 12):
from ast import ParamSpec as ParamSpec, TypeVar as TypeVar, TypeVarTuple as TypeVarTuple, type_param as type_param
if sys.version_info >= (3, 11):
from ast import TryStar as TryStar
if sys.version_info >= (3, 10):
from ast import (
MatchAs as MatchAs,
MatchClass as MatchClass,
MatchMapping as MatchMapping,
MatchOr as MatchOr,
MatchSequence as MatchSequence,
MatchSingleton as MatchSingleton,
MatchStar as MatchStar,
MatchValue as MatchValue,
match_case as match_case,
pattern as pattern,
)
PyCF_ALLOW_TOP_LEVEL_AWAIT: Literal[8192]
PyCF_ONLY_AST: Literal[1024]
PyCF_TYPE_COMMENTS: Literal[4096]
if sys.version_info >= (3, 13):
PyCF_OPTIMIZED_AST: Literal[33792]

View File

@@ -1,105 +0,0 @@
import sys
from asyncio.events import AbstractEventLoop
from collections.abc import Awaitable, Callable, Coroutine, Generator
from contextvars import Context
from types import FrameType, GenericAlias
from typing import Any, Literal, TextIO, TypeVar
from typing_extensions import Self, TypeAlias
_T = TypeVar("_T")
_T_co = TypeVar("_T_co", covariant=True)
_TaskYieldType: TypeAlias = Future[object] | None
class Future(Awaitable[_T]):
_state: str
@property
def _exception(self) -> BaseException | None: ...
_blocking: bool
@property
def _log_traceback(self) -> bool: ...
@_log_traceback.setter
def _log_traceback(self, val: Literal[False]) -> None: ...
_asyncio_future_blocking: bool # is a part of duck-typing contract for `Future`
def __init__(self, *, loop: AbstractEventLoop | None = ...) -> None: ...
def __del__(self) -> None: ...
def get_loop(self) -> AbstractEventLoop: ...
@property
def _callbacks(self) -> list[tuple[Callable[[Self], Any], Context]]: ...
def add_done_callback(self, fn: Callable[[Self], object], /, *, context: Context | None = None) -> None: ...
def cancel(self, msg: Any | None = None) -> bool: ...
def cancelled(self) -> bool: ...
def done(self) -> bool: ...
def result(self) -> _T: ...
def exception(self) -> BaseException | None: ...
def remove_done_callback(self, fn: Callable[[Self], object], /) -> int: ...
def set_result(self, result: _T, /) -> None: ...
def set_exception(self, exception: type | BaseException, /) -> None: ...
def __iter__(self) -> Generator[Any, None, _T]: ...
def __await__(self) -> Generator[Any, None, _T]: ...
@property
def _loop(self) -> AbstractEventLoop: ...
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
if sys.version_info >= (3, 12):
_TaskCompatibleCoro: TypeAlias = Coroutine[Any, Any, _T_co]
else:
_TaskCompatibleCoro: TypeAlias = Generator[_TaskYieldType, None, _T_co] | Coroutine[Any, Any, _T_co]
# mypy and pyright complain that a subclass of an invariant class shouldn't be covariant.
# While this is true in general, here it's sort-of okay to have a covariant subclass,
# since the only reason why `asyncio.Future` is invariant is the `set_result()` method,
# and `asyncio.Task.set_result()` always raises.
class Task(Future[_T_co]): # type: ignore[type-var] # pyright: ignore[reportInvalidTypeArguments]
if sys.version_info >= (3, 12):
def __init__(
self,
coro: _TaskCompatibleCoro[_T_co],
*,
loop: AbstractEventLoop | None = None,
name: str | None = ...,
context: Context | None = None,
eager_start: bool = False,
) -> None: ...
elif sys.version_info >= (3, 11):
def __init__(
self,
coro: _TaskCompatibleCoro[_T_co],
*,
loop: AbstractEventLoop | None = None,
name: str | None = ...,
context: Context | None = None,
) -> None: ...
else:
def __init__(
self, coro: _TaskCompatibleCoro[_T_co], *, loop: AbstractEventLoop | None = None, name: str | None = ...
) -> None: ...
if sys.version_info >= (3, 12):
def get_coro(self) -> _TaskCompatibleCoro[_T_co] | None: ...
else:
def get_coro(self) -> _TaskCompatibleCoro[_T_co]: ...
def get_name(self) -> str: ...
def set_name(self, value: object, /) -> None: ...
if sys.version_info >= (3, 12):
def get_context(self) -> Context: ...
def get_stack(self, *, limit: int | None = None) -> list[FrameType]: ...
def print_stack(self, *, limit: int | None = None, file: TextIO | None = None) -> None: ...
if sys.version_info >= (3, 11):
def cancelling(self) -> int: ...
def uncancel(self) -> int: ...
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
def get_event_loop() -> AbstractEventLoop: ...
def get_running_loop() -> AbstractEventLoop: ...
def _set_running_loop(loop: AbstractEventLoop | None, /) -> None: ...
def _get_running_loop() -> AbstractEventLoop: ...
def _register_task(task: Task[Any]) -> None: ...
def _unregister_task(task: Task[Any]) -> None: ...
def _enter_task(loop: AbstractEventLoop, task: Task[Any]) -> None: ...
def _leave_task(loop: AbstractEventLoop, task: Task[Any]) -> None: ...
if sys.version_info >= (3, 12):
def current_task(loop: AbstractEventLoop | None = None) -> Task[Any] | None: ...

View File

@@ -1,84 +0,0 @@
import sys
from _typeshed import SupportsLenAndGetItem, SupportsRichComparisonT
from collections.abc import Callable, MutableSequence
from typing import TypeVar, overload
_T = TypeVar("_T")
if sys.version_info >= (3, 10):
@overload
def bisect_left(
a: SupportsLenAndGetItem[SupportsRichComparisonT],
x: SupportsRichComparisonT,
lo: int = 0,
hi: int | None = None,
*,
key: None = None,
) -> int: ...
@overload
def bisect_left(
a: SupportsLenAndGetItem[_T],
x: SupportsRichComparisonT,
lo: int = 0,
hi: int | None = None,
*,
key: Callable[[_T], SupportsRichComparisonT],
) -> int: ...
@overload
def bisect_right(
a: SupportsLenAndGetItem[SupportsRichComparisonT],
x: SupportsRichComparisonT,
lo: int = 0,
hi: int | None = None,
*,
key: None = None,
) -> int: ...
@overload
def bisect_right(
a: SupportsLenAndGetItem[_T],
x: SupportsRichComparisonT,
lo: int = 0,
hi: int | None = None,
*,
key: Callable[[_T], SupportsRichComparisonT],
) -> int: ...
@overload
def insort_left(
a: MutableSequence[SupportsRichComparisonT],
x: SupportsRichComparisonT,
lo: int = 0,
hi: int | None = None,
*,
key: None = None,
) -> None: ...
@overload
def insort_left(
a: MutableSequence[_T], x: _T, lo: int = 0, hi: int | None = None, *, key: Callable[[_T], SupportsRichComparisonT]
) -> None: ...
@overload
def insort_right(
a: MutableSequence[SupportsRichComparisonT],
x: SupportsRichComparisonT,
lo: int = 0,
hi: int | None = None,
*,
key: None = None,
) -> None: ...
@overload
def insort_right(
a: MutableSequence[_T], x: _T, lo: int = 0, hi: int | None = None, *, key: Callable[[_T], SupportsRichComparisonT]
) -> None: ...
else:
def bisect_left(
a: SupportsLenAndGetItem[SupportsRichComparisonT], x: SupportsRichComparisonT, lo: int = 0, hi: int | None = None
) -> int: ...
def bisect_right(
a: SupportsLenAndGetItem[SupportsRichComparisonT], x: SupportsRichComparisonT, lo: int = 0, hi: int | None = None
) -> int: ...
def insort_left(
a: MutableSequence[SupportsRichComparisonT], x: SupportsRichComparisonT, lo: int = 0, hi: int | None = None
) -> None: ...
def insort_right(
a: MutableSequence[SupportsRichComparisonT], x: SupportsRichComparisonT, lo: int = 0, hi: int | None = None
) -> None: ...

View File

@@ -1,76 +0,0 @@
from _typeshed import ReadableBuffer
from typing import ClassVar, final
from typing_extensions import Self
BLAKE2B_MAX_DIGEST_SIZE: int = 64
BLAKE2B_MAX_KEY_SIZE: int = 64
BLAKE2B_PERSON_SIZE: int = 16
BLAKE2B_SALT_SIZE: int = 16
BLAKE2S_MAX_DIGEST_SIZE: int = 32
BLAKE2S_MAX_KEY_SIZE: int = 32
BLAKE2S_PERSON_SIZE: int = 8
BLAKE2S_SALT_SIZE: int = 8
@final
class blake2b:
MAX_DIGEST_SIZE: ClassVar[int] = 64
MAX_KEY_SIZE: ClassVar[int] = 64
PERSON_SIZE: ClassVar[int] = 16
SALT_SIZE: ClassVar[int] = 16
block_size: int
digest_size: int
name: str
def __new__(
cls,
data: ReadableBuffer = b"",
/,
*,
digest_size: int = 64,
key: ReadableBuffer = b"",
salt: ReadableBuffer = b"",
person: ReadableBuffer = b"",
fanout: int = 1,
depth: int = 1,
leaf_size: int = 0,
node_offset: int = 0,
node_depth: int = 0,
inner_size: int = 0,
last_node: bool = False,
usedforsecurity: bool = True,
) -> Self: ...
def copy(self) -> Self: ...
def digest(self) -> bytes: ...
def hexdigest(self) -> str: ...
def update(self, data: ReadableBuffer, /) -> None: ...
@final
class blake2s:
MAX_DIGEST_SIZE: ClassVar[int] = 32
MAX_KEY_SIZE: ClassVar[int] = 32
PERSON_SIZE: ClassVar[int] = 8
SALT_SIZE: ClassVar[int] = 8
block_size: int
digest_size: int
name: str
def __new__(
cls,
data: ReadableBuffer = b"",
/,
*,
digest_size: int = 32,
key: ReadableBuffer = b"",
salt: ReadableBuffer = b"",
person: ReadableBuffer = b"",
fanout: int = 1,
depth: int = 1,
leaf_size: int = 0,
node_offset: int = 0,
node_depth: int = 0,
inner_size: int = 0,
last_node: bool = False,
usedforsecurity: bool = True,
) -> Self: ...
def copy(self) -> Self: ...
def digest(self) -> bytes: ...
def hexdigest(self) -> str: ...
def update(self, data: ReadableBuffer, /) -> None: ...

View File

@@ -1 +0,0 @@
def getpreferredencoding(do_setlocale: bool = True) -> str: ...

View File

@@ -1,24 +0,0 @@
import sys
from _typeshed import ReadableBuffer
from typing import final
from typing_extensions import Self
@final
class BZ2Compressor:
if sys.version_info >= (3, 12):
def __new__(cls, compresslevel: int = 9, /) -> Self: ...
else:
def __init__(self, compresslevel: int = 9, /) -> None: ...
def compress(self, data: ReadableBuffer, /) -> bytes: ...
def flush(self) -> bytes: ...
@final
class BZ2Decompressor:
def decompress(self, data: ReadableBuffer, max_length: int = -1) -> bytes: ...
@property
def eof(self) -> bool: ...
@property
def needs_input(self) -> bool: ...
@property
def unused_data(self) -> bytes: ...

View File

@@ -1,122 +0,0 @@
import codecs
import sys
from _typeshed import ReadableBuffer
from collections.abc import Callable
from typing import Literal, final, overload, type_check_only
from typing_extensions import TypeAlias
# This type is not exposed; it is defined in unicodeobject.c
# At runtime it calls itself builtins.EncodingMap
@final
@type_check_only
class _EncodingMap:
def size(self) -> int: ...
_CharMap: TypeAlias = dict[int, int] | _EncodingMap
_Handler: TypeAlias = Callable[[UnicodeError], tuple[str | bytes, int]]
_SearchFunction: TypeAlias = Callable[[str], codecs.CodecInfo | None]
def register(search_function: _SearchFunction, /) -> None: ...
if sys.version_info >= (3, 10):
def unregister(search_function: _SearchFunction, /) -> None: ...
def register_error(errors: str, handler: _Handler, /) -> None: ...
def lookup_error(name: str, /) -> _Handler: ...
# The type ignore on `encode` and `decode` is to avoid issues with overlapping overloads, for more details, see #300
# https://docs.python.org/3/library/codecs.html#binary-transforms
_BytesToBytesEncoding: TypeAlias = Literal[
"base64",
"base_64",
"base64_codec",
"bz2",
"bz2_codec",
"hex",
"hex_codec",
"quopri",
"quotedprintable",
"quoted_printable",
"quopri_codec",
"uu",
"uu_codec",
"zip",
"zlib",
"zlib_codec",
]
# https://docs.python.org/3/library/codecs.html#text-transforms
_StrToStrEncoding: TypeAlias = Literal["rot13", "rot_13"]
@overload
def encode(obj: ReadableBuffer, encoding: _BytesToBytesEncoding, errors: str = "strict") -> bytes: ...
@overload
def encode(obj: str, encoding: _StrToStrEncoding, errors: str = "strict") -> str: ... # type: ignore[overload-overlap]
@overload
def encode(obj: str, encoding: str = "utf-8", errors: str = "strict") -> bytes: ...
@overload
def decode(obj: ReadableBuffer, encoding: _BytesToBytesEncoding, errors: str = "strict") -> bytes: ... # type: ignore[overload-overlap]
@overload
def decode(obj: str, encoding: _StrToStrEncoding, errors: str = "strict") -> str: ...
# these are documented as text encodings but in practice they also accept str as input
@overload
def decode(
obj: str,
encoding: Literal["unicode_escape", "unicode-escape", "raw_unicode_escape", "raw-unicode-escape"],
errors: str = "strict",
) -> str: ...
# hex is officially documented as a bytes to bytes encoding, but it appears to also work with str
@overload
def decode(obj: str, encoding: Literal["hex", "hex_codec"], errors: str = "strict") -> bytes: ...
@overload
def decode(obj: ReadableBuffer, encoding: str = "utf-8", errors: str = "strict") -> str: ...
def lookup(encoding: str, /) -> codecs.CodecInfo: ...
def charmap_build(map: str, /) -> _CharMap: ...
def ascii_decode(data: ReadableBuffer, errors: str | None = None, /) -> tuple[str, int]: ...
def ascii_encode(str: str, errors: str | None = None, /) -> tuple[bytes, int]: ...
def charmap_decode(data: ReadableBuffer, errors: str | None = None, mapping: _CharMap | None = None, /) -> tuple[str, int]: ...
def charmap_encode(str: str, errors: str | None = None, mapping: _CharMap | None = None, /) -> tuple[bytes, int]: ...
def escape_decode(data: str | ReadableBuffer, errors: str | None = None, /) -> tuple[str, int]: ...
def escape_encode(data: bytes, errors: str | None = None, /) -> tuple[bytes, int]: ...
def latin_1_decode(data: ReadableBuffer, errors: str | None = None, /) -> tuple[str, int]: ...
def latin_1_encode(str: str, errors: str | None = None, /) -> tuple[bytes, int]: ...
def raw_unicode_escape_decode(
data: str | ReadableBuffer, errors: str | None = None, final: bool = True, /
) -> tuple[str, int]: ...
def raw_unicode_escape_encode(str: str, errors: str | None = None, /) -> tuple[bytes, int]: ...
def readbuffer_encode(data: str | ReadableBuffer, errors: str | None = None, /) -> tuple[bytes, int]: ...
def unicode_escape_decode(data: str | ReadableBuffer, errors: str | None = None, final: bool = True, /) -> tuple[str, int]: ...
def unicode_escape_encode(str: str, errors: str | None = None, /) -> tuple[bytes, int]: ...
def utf_16_be_decode(data: ReadableBuffer, errors: str | None = None, final: bool = False, /) -> tuple[str, int]: ...
def utf_16_be_encode(str: str, errors: str | None = None, /) -> tuple[bytes, int]: ...
def utf_16_decode(data: ReadableBuffer, errors: str | None = None, final: bool = False, /) -> tuple[str, int]: ...
def utf_16_encode(str: str, errors: str | None = None, byteorder: int = 0, /) -> tuple[bytes, int]: ...
def utf_16_ex_decode(
data: ReadableBuffer, errors: str | None = None, byteorder: int = 0, final: bool = False, /
) -> tuple[str, int, int]: ...
def utf_16_le_decode(data: ReadableBuffer, errors: str | None = None, final: bool = False, /) -> tuple[str, int]: ...
def utf_16_le_encode(str: str, errors: str | None = None, /) -> tuple[bytes, int]: ...
def utf_32_be_decode(data: ReadableBuffer, errors: str | None = None, final: bool = False, /) -> tuple[str, int]: ...
def utf_32_be_encode(str: str, errors: str | None = None, /) -> tuple[bytes, int]: ...
def utf_32_decode(data: ReadableBuffer, errors: str | None = None, final: bool = False, /) -> tuple[str, int]: ...
def utf_32_encode(str: str, errors: str | None = None, byteorder: int = 0, /) -> tuple[bytes, int]: ...
def utf_32_ex_decode(
data: ReadableBuffer, errors: str | None = None, byteorder: int = 0, final: bool = False, /
) -> tuple[str, int, int]: ...
def utf_32_le_decode(data: ReadableBuffer, errors: str | None = None, final: bool = False, /) -> tuple[str, int]: ...
def utf_32_le_encode(str: str, errors: str | None = None, /) -> tuple[bytes, int]: ...
def utf_7_decode(data: ReadableBuffer, errors: str | None = None, final: bool = False, /) -> tuple[str, int]: ...
def utf_7_encode(str: str, errors: str | None = None, /) -> tuple[bytes, int]: ...
def utf_8_decode(data: ReadableBuffer, errors: str | None = None, final: bool = False, /) -> tuple[str, int]: ...
def utf_8_encode(str: str, errors: str | None = None, /) -> tuple[bytes, int]: ...
if sys.platform == "win32":
def mbcs_decode(data: ReadableBuffer, errors: str | None = None, final: bool = False, /) -> tuple[str, int]: ...
def mbcs_encode(str: str, errors: str | None = None, /) -> tuple[bytes, int]: ...
def code_page_decode(
codepage: int, data: ReadableBuffer, errors: str | None = None, final: bool = False, /
) -> tuple[str, int]: ...
def code_page_encode(code_page: int, str: str, errors: str | None = None, /) -> tuple[bytes, int]: ...
def oem_decode(data: ReadableBuffer, errors: str | None = None, final: bool = False, /) -> tuple[str, int]: ...
def oem_encode(str: str, errors: str | None = None, /) -> tuple[bytes, int]: ...

View File

@@ -1,107 +0,0 @@
import sys
from abc import abstractmethod
from types import MappingProxyType
from typing import ( # noqa: Y022,Y038,UP035
AbstractSet as Set,
AsyncGenerator as AsyncGenerator,
AsyncIterable as AsyncIterable,
AsyncIterator as AsyncIterator,
Awaitable as Awaitable,
Callable as Callable,
ClassVar,
Collection as Collection,
Container as Container,
Coroutine as Coroutine,
Generator as Generator,
Generic,
Hashable as Hashable,
ItemsView as ItemsView,
Iterable as Iterable,
Iterator as Iterator,
KeysView as KeysView,
Mapping as Mapping,
MappingView as MappingView,
MutableMapping as MutableMapping,
MutableSequence as MutableSequence,
MutableSet as MutableSet,
Protocol,
Reversible as Reversible,
Sequence as Sequence,
Sized as Sized,
TypeVar,
ValuesView as ValuesView,
final,
runtime_checkable,
)
__all__ = [
"Awaitable",
"Coroutine",
"AsyncIterable",
"AsyncIterator",
"AsyncGenerator",
"Hashable",
"Iterable",
"Iterator",
"Generator",
"Reversible",
"Sized",
"Container",
"Callable",
"Collection",
"Set",
"MutableSet",
"Mapping",
"MutableMapping",
"MappingView",
"KeysView",
"ItemsView",
"ValuesView",
"Sequence",
"MutableSequence",
]
if sys.version_info < (3, 14):
from typing import ByteString as ByteString # noqa: Y057,UP035
__all__ += ["ByteString"]
if sys.version_info >= (3, 12):
__all__ += ["Buffer"]
_KT_co = TypeVar("_KT_co", covariant=True) # Key type covariant containers.
_VT_co = TypeVar("_VT_co", covariant=True) # Value type covariant containers.
@final
class dict_keys(KeysView[_KT_co], Generic[_KT_co, _VT_co]): # undocumented
def __eq__(self, value: object, /) -> bool: ...
def __reversed__(self) -> Iterator[_KT_co]: ...
__hash__: ClassVar[None] # type: ignore[assignment]
if sys.version_info >= (3, 13):
def isdisjoint(self, other: Iterable[_KT_co], /) -> bool: ...
if sys.version_info >= (3, 10):
@property
def mapping(self) -> MappingProxyType[_KT_co, _VT_co]: ...
@final
class dict_values(ValuesView[_VT_co], Generic[_KT_co, _VT_co]): # undocumented
def __reversed__(self) -> Iterator[_VT_co]: ...
if sys.version_info >= (3, 10):
@property
def mapping(self) -> MappingProxyType[_KT_co, _VT_co]: ...
@final
class dict_items(ItemsView[_KT_co, _VT_co]): # undocumented
def __eq__(self, value: object, /) -> bool: ...
def __reversed__(self) -> Iterator[tuple[_KT_co, _VT_co]]: ...
__hash__: ClassVar[None] # type: ignore[assignment]
if sys.version_info >= (3, 13):
def isdisjoint(self, other: Iterable[tuple[_KT_co, _VT_co]], /) -> bool: ...
if sys.version_info >= (3, 10):
@property
def mapping(self) -> MappingProxyType[_KT_co, _VT_co]: ...
if sys.version_info >= (3, 12):
@runtime_checkable
class Buffer(Protocol):
@abstractmethod
def __buffer__(self, flags: int, /) -> memoryview: ...

View File

@@ -1,8 +0,0 @@
IMPORT_MAPPING: dict[str, str]
NAME_MAPPING: dict[tuple[str, str], tuple[str, str]]
PYTHON2_EXCEPTIONS: tuple[str, ...]
MULTIPROCESSING_EXCEPTIONS: tuple[str, ...]
REVERSE_IMPORT_MAPPING: dict[str, str]
REVERSE_NAME_MAPPING: dict[tuple[str, str], tuple[str, str]]
PYTHON3_OSERROR_EXCEPTIONS: tuple[str, ...]
PYTHON3_IMPORTERROR_EXCEPTIONS: tuple[str, ...]

View File

@@ -1,25 +0,0 @@
from _typeshed import WriteableBuffer
from collections.abc import Callable
from io import DEFAULT_BUFFER_SIZE, BufferedIOBase, RawIOBase
from typing import Any, Protocol
BUFFER_SIZE = DEFAULT_BUFFER_SIZE
class _Reader(Protocol):
def read(self, n: int, /) -> bytes: ...
def seekable(self) -> bool: ...
def seek(self, n: int, /) -> Any: ...
class BaseStream(BufferedIOBase): ...
class DecompressReader(RawIOBase):
def __init__(
self,
fp: _Reader,
decomp_factory: Callable[..., object],
trailing_error: type[Exception] | tuple[type[Exception], ...] = (),
**decomp_args: Any,
) -> None: ...
def readinto(self, b: WriteableBuffer) -> int: ...
def read(self, size: int = -1) -> bytes: ...
def seek(self, offset: int, whence: int = 0) -> int: ...

View File

@@ -1,58 +0,0 @@
from collections.abc import Callable, Iterator, Mapping
from types import GenericAlias
from typing import Any, ClassVar, Generic, TypeVar, final, overload
from typing_extensions import ParamSpec, Self
_T = TypeVar("_T")
_D = TypeVar("_D")
_P = ParamSpec("_P")
@final
class ContextVar(Generic[_T]):
@overload
def __new__(cls, name: str) -> Self: ...
@overload
def __new__(cls, name: str, *, default: _T) -> Self: ...
def __hash__(self) -> int: ...
@property
def name(self) -> str: ...
@overload
def get(self) -> _T: ...
@overload
def get(self, default: _T, /) -> _T: ...
@overload
def get(self, default: _D, /) -> _D | _T: ...
def set(self, value: _T, /) -> Token[_T]: ...
def reset(self, token: Token[_T], /) -> None: ...
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
@final
class Token(Generic[_T]):
@property
def var(self) -> ContextVar[_T]: ...
@property
def old_value(self) -> Any: ... # returns either _T or MISSING, but that's hard to express
MISSING: ClassVar[object]
__hash__: ClassVar[None] # type: ignore[assignment]
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
def copy_context() -> Context: ...
# It doesn't make sense to make this generic, because for most Contexts each ContextVar will have
# a different value.
@final
class Context(Mapping[ContextVar[Any], Any]):
def __init__(self) -> None: ...
@overload
def get(self, key: ContextVar[_T], default: None = None, /) -> _T | None: ...
@overload
def get(self, key: ContextVar[_T], default: _T, /) -> _T: ...
@overload
def get(self, key: ContextVar[_T], default: _D, /) -> _T | _D: ...
def run(self, callable: Callable[_P, _T], *args: _P.args, **kwargs: _P.kwargs) -> _T: ...
def copy(self) -> Context: ...
__hash__: ClassVar[None] # type: ignore[assignment]
def __getitem__(self, key: ContextVar[_T], /) -> _T: ...
def __iter__(self) -> Iterator[ContextVar[Any]]: ...
def __len__(self) -> int: ...
def __eq__(self, value: object, /) -> bool: ...

View File

@@ -1,132 +0,0 @@
import csv
import sys
from _typeshed import SupportsWrite
from collections.abc import Iterable
from typing import Any, Final, type_check_only
from typing_extensions import Self, TypeAlias
__version__: Final[str]
QUOTE_ALL: Final = 1
QUOTE_MINIMAL: Final = 0
QUOTE_NONE: Final = 3
QUOTE_NONNUMERIC: Final = 2
if sys.version_info >= (3, 12):
QUOTE_STRINGS: Final = 4
QUOTE_NOTNULL: Final = 5
# Ideally this would be `QUOTE_ALL | QUOTE_MINIMAL | QUOTE_NONE | QUOTE_NONNUMERIC`
# However, using literals in situations like these can cause false-positives (see #7258)
_QuotingType: TypeAlias = int
class Error(Exception): ...
_DialectLike: TypeAlias = str | Dialect | csv.Dialect | type[Dialect | csv.Dialect]
class Dialect:
delimiter: str
quotechar: str | None
escapechar: str | None
doublequote: bool
skipinitialspace: bool
lineterminator: str
quoting: _QuotingType
strict: bool
def __new__(
cls,
dialect: _DialectLike | None = ...,
delimiter: str = ",",
doublequote: bool = True,
escapechar: str | None = None,
lineterminator: str = "\r\n",
quotechar: str | None = '"',
quoting: _QuotingType = 0,
skipinitialspace: bool = False,
strict: bool = False,
) -> Self: ...
if sys.version_info >= (3, 10):
# This class calls itself _csv.reader.
class Reader:
@property
def dialect(self) -> Dialect: ...
line_num: int
def __iter__(self) -> Self: ...
def __next__(self) -> list[str]: ...
# This class calls itself _csv.writer.
class Writer:
@property
def dialect(self) -> Dialect: ...
if sys.version_info >= (3, 13):
def writerow(self, row: Iterable[Any], /) -> Any: ...
def writerows(self, rows: Iterable[Iterable[Any]], /) -> None: ...
else:
def writerow(self, row: Iterable[Any]) -> Any: ...
def writerows(self, rows: Iterable[Iterable[Any]]) -> None: ...
# For the return types below.
# These aliases can be removed when typeshed drops support for 3.9.
_reader = Reader
_writer = Writer
else:
# This class is not exposed. It calls itself _csv.reader.
@type_check_only
class _reader:
@property
def dialect(self) -> Dialect: ...
line_num: int
def __iter__(self) -> Self: ...
def __next__(self) -> list[str]: ...
# This class is not exposed. It calls itself _csv.writer.
@type_check_only
class _writer:
@property
def dialect(self) -> Dialect: ...
def writerow(self, row: Iterable[Any]) -> Any: ...
def writerows(self, rows: Iterable[Iterable[Any]]) -> None: ...
def writer(
csvfile: SupportsWrite[str],
dialect: _DialectLike = "excel",
*,
delimiter: str = ",",
quotechar: str | None = '"',
escapechar: str | None = None,
doublequote: bool = True,
skipinitialspace: bool = False,
lineterminator: str = "\r\n",
quoting: _QuotingType = 0,
strict: bool = False,
) -> _writer: ...
def reader(
csvfile: Iterable[str],
dialect: _DialectLike = "excel",
*,
delimiter: str = ",",
quotechar: str | None = '"',
escapechar: str | None = None,
doublequote: bool = True,
skipinitialspace: bool = False,
lineterminator: str = "\r\n",
quoting: _QuotingType = 0,
strict: bool = False,
) -> _reader: ...
def register_dialect(
name: str,
dialect: type[Dialect | csv.Dialect] = ...,
*,
delimiter: str = ",",
quotechar: str | None = '"',
escapechar: str | None = None,
doublequote: bool = True,
skipinitialspace: bool = False,
lineterminator: str = "\r\n",
quoting: _QuotingType = 0,
strict: bool = False,
) -> None: ...
def unregister_dialect(name: str) -> None: ...
def get_dialect(name: str) -> Dialect: ...
def list_dialects() -> list[str]: ...
def field_size_limit(new_limit: int = ...) -> int: ...

View File

@@ -1,331 +0,0 @@
import _typeshed
import sys
from _typeshed import ReadableBuffer, StrOrBytesPath, WriteableBuffer
from abc import abstractmethod
from collections.abc import Callable, Iterable, Iterator, Mapping, Sequence
from ctypes import CDLL, ArgumentError as ArgumentError, c_void_p
from types import GenericAlias
from typing import Any, ClassVar, Generic, TypeVar, final, overload, type_check_only
from typing_extensions import Self, TypeAlias
_T = TypeVar("_T")
_CT = TypeVar("_CT", bound=_CData)
FUNCFLAG_CDECL: int
FUNCFLAG_PYTHONAPI: int
FUNCFLAG_USE_ERRNO: int
FUNCFLAG_USE_LASTERROR: int
RTLD_GLOBAL: int
RTLD_LOCAL: int
if sys.version_info >= (3, 11):
CTYPES_MAX_ARGCOUNT: int
if sys.version_info >= (3, 12):
SIZEOF_TIME_T: int
if sys.platform == "win32":
# Description, Source, HelpFile, HelpContext, scode
_COMError_Details: TypeAlias = tuple[str | None, str | None, str | None, int | None, int | None]
class COMError(Exception):
hresult: int
text: str | None
details: _COMError_Details
def __init__(self, hresult: int, text: str | None, details: _COMError_Details) -> None: ...
def CopyComPointer(src: _PointerLike, dst: _PointerLike | _CArgObject) -> int: ...
FUNCFLAG_HRESULT: int
FUNCFLAG_STDCALL: int
def FormatError(code: int = ...) -> str: ...
def get_last_error() -> int: ...
def set_last_error(value: int) -> int: ...
def LoadLibrary(name: str, load_flags: int = 0, /) -> int: ...
def FreeLibrary(handle: int, /) -> None: ...
else:
def dlclose(handle: int, /) -> None: ...
# The default for flag is RTLD_GLOBAL|RTLD_LOCAL, which is platform dependent.
def dlopen(name: StrOrBytesPath, flag: int = ..., /) -> int: ...
def dlsym(handle: int, name: str, /) -> int: ...
if sys.version_info >= (3, 13):
# This class is not exposed. It calls itself _ctypes.CType_Type.
@type_check_only
class _CType_Type(type):
# By default mypy complains about the following two methods, because strictly speaking cls
# might not be a Type[_CT]. However this doesn't happen because this is only a
# metaclass for subclasses of _CData.
def __mul__(cls: type[_CT], other: int) -> type[Array[_CT]]: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
def __rmul__(cls: type[_CT], other: int) -> type[Array[_CT]]: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
_CTypeBaseType = _CType_Type
else:
_CTypeBaseType = type
# This class is not exposed.
@type_check_only
class _CData:
_b_base_: int
_b_needsfree_: bool
_objects: Mapping[Any, int] | None
def __buffer__(self, flags: int, /) -> memoryview: ...
def __ctypes_from_outparam__(self, /) -> Self: ...
# this is a union of all the subclasses of _CData, which is useful because of
# the methods that are present on each of those subclasses which are not present
# on _CData itself.
_CDataType: TypeAlias = _SimpleCData[Any] | _Pointer[Any] | CFuncPtr | Union | Structure | Array[Any]
# This class is not exposed. It calls itself _ctypes.PyCSimpleType.
@type_check_only
class _PyCSimpleType(_CTypeBaseType):
def from_address(self: type[_typeshed.Self], value: int, /) -> _typeshed.Self: ...
def from_buffer(self: type[_typeshed.Self], obj: WriteableBuffer, offset: int = 0, /) -> _typeshed.Self: ...
def from_buffer_copy(self: type[_typeshed.Self], buffer: ReadableBuffer, offset: int = 0, /) -> _typeshed.Self: ...
def from_param(self: type[_typeshed.Self], value: Any, /) -> _typeshed.Self | _CArgObject: ...
def in_dll(self: type[_typeshed.Self], dll: CDLL, name: str, /) -> _typeshed.Self: ...
if sys.version_info < (3, 13):
# Inherited from CType_Type starting on 3.13
def __mul__(self: type[_CT], value: int, /) -> type[Array[_CT]]: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
def __rmul__(self: type[_CT], value: int, /) -> type[Array[_CT]]: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
class _SimpleCData(_CData, Generic[_T], metaclass=_PyCSimpleType):
value: _T
# The TypeVar can be unsolved here,
# but we can't use overloads without creating many, many mypy false-positive errors
def __init__(self, value: _T = ...) -> None: ... # pyright: ignore[reportInvalidTypeVarUse]
def __ctypes_from_outparam__(self, /) -> _T: ... # type: ignore[override]
class _CanCastTo(_CData): ...
class _PointerLike(_CanCastTo): ...
# This type is not exposed. It calls itself _ctypes.PyCPointerType.
@type_check_only
class _PyCPointerType(_CTypeBaseType):
def from_address(self: type[_typeshed.Self], value: int, /) -> _typeshed.Self: ...
def from_buffer(self: type[_typeshed.Self], obj: WriteableBuffer, offset: int = 0, /) -> _typeshed.Self: ...
def from_buffer_copy(self: type[_typeshed.Self], buffer: ReadableBuffer, offset: int = 0, /) -> _typeshed.Self: ...
def from_param(self: type[_typeshed.Self], value: Any, /) -> _typeshed.Self | _CArgObject: ...
def in_dll(self: type[_typeshed.Self], dll: CDLL, name: str, /) -> _typeshed.Self: ...
def set_type(self, type: Any, /) -> None: ...
if sys.version_info < (3, 13):
# Inherited from CType_Type starting on 3.13
def __mul__(cls: type[_CT], other: int) -> type[Array[_CT]]: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
def __rmul__(cls: type[_CT], other: int) -> type[Array[_CT]]: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
class _Pointer(_PointerLike, _CData, Generic[_CT], metaclass=_PyCPointerType):
_type_: type[_CT]
contents: _CT
@overload
def __init__(self) -> None: ...
@overload
def __init__(self, arg: _CT) -> None: ...
@overload
def __getitem__(self, key: int, /) -> Any: ...
@overload
def __getitem__(self, key: slice, /) -> list[Any]: ...
def __setitem__(self, key: int, value: Any, /) -> None: ...
@overload
def POINTER(type: None, /) -> type[c_void_p]: ...
@overload
def POINTER(type: type[_CT], /) -> type[_Pointer[_CT]]: ...
def pointer(obj: _CT, /) -> _Pointer[_CT]: ...
# This class is not exposed. It calls itself _ctypes.CArgObject.
@final
@type_check_only
class _CArgObject: ...
def byref(obj: _CData | _CDataType, offset: int = ...) -> _CArgObject: ...
_ECT: TypeAlias = Callable[[_CData | _CDataType | None, CFuncPtr, tuple[_CData | _CDataType, ...]], _CDataType]
_PF: TypeAlias = tuple[int] | tuple[int, str | None] | tuple[int, str | None, Any]
# This class is not exposed. It calls itself _ctypes.PyCFuncPtrType.
@type_check_only
class _PyCFuncPtrType(_CTypeBaseType):
def from_address(self: type[_typeshed.Self], value: int, /) -> _typeshed.Self: ...
def from_buffer(self: type[_typeshed.Self], obj: WriteableBuffer, offset: int = 0, /) -> _typeshed.Self: ...
def from_buffer_copy(self: type[_typeshed.Self], buffer: ReadableBuffer, offset: int = 0, /) -> _typeshed.Self: ...
def from_param(self: type[_typeshed.Self], value: Any, /) -> _typeshed.Self | _CArgObject: ...
def in_dll(self: type[_typeshed.Self], dll: CDLL, name: str, /) -> _typeshed.Self: ...
if sys.version_info < (3, 13):
# Inherited from CType_Type starting on 3.13
def __mul__(cls: type[_CT], other: int) -> type[Array[_CT]]: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
def __rmul__(cls: type[_CT], other: int) -> type[Array[_CT]]: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
class CFuncPtr(_PointerLike, _CData, metaclass=_PyCFuncPtrType):
restype: type[_CDataType] | Callable[[int], Any] | None
argtypes: Sequence[type[_CDataType]]
errcheck: _ECT
# Abstract attribute that must be defined on subclasses
_flags_: ClassVar[int]
@overload
def __new__(cls) -> Self: ...
@overload
def __new__(cls, address: int, /) -> Self: ...
@overload
def __new__(cls, callable: Callable[..., Any], /) -> Self: ...
@overload
def __new__(cls, func_spec: tuple[str | int, CDLL], paramflags: tuple[_PF, ...] | None = ..., /) -> Self: ...
if sys.platform == "win32":
@overload
def __new__(
cls, vtbl_index: int, name: str, paramflags: tuple[_PF, ...] | None = ..., iid: _CData | _CDataType | None = ..., /
) -> Self: ...
def __call__(self, *args: Any, **kwargs: Any) -> Any: ...
_GetT = TypeVar("_GetT")
_SetT = TypeVar("_SetT")
# This class is not exposed. It calls itself _ctypes.CField.
@final
@type_check_only
class _CField(Generic[_CT, _GetT, _SetT]):
offset: int
size: int
if sys.version_info >= (3, 10):
@overload
def __get__(self, instance: None, owner: type[Any] | None = None, /) -> Self: ...
@overload
def __get__(self, instance: Any, owner: type[Any] | None = None, /) -> _GetT: ...
else:
@overload
def __get__(self, instance: None, owner: type[Any] | None, /) -> Self: ...
@overload
def __get__(self, instance: Any, owner: type[Any] | None, /) -> _GetT: ...
def __set__(self, instance: Any, value: _SetT, /) -> None: ...
# This class is not exposed. It calls itself _ctypes.UnionType.
@type_check_only
class _UnionType(_CTypeBaseType):
def from_address(self: type[_typeshed.Self], value: int, /) -> _typeshed.Self: ...
def from_buffer(self: type[_typeshed.Self], obj: WriteableBuffer, offset: int = 0, /) -> _typeshed.Self: ...
def from_buffer_copy(self: type[_typeshed.Self], buffer: ReadableBuffer, offset: int = 0, /) -> _typeshed.Self: ...
def from_param(self: type[_typeshed.Self], value: Any, /) -> _typeshed.Self | _CArgObject: ...
def in_dll(self: type[_typeshed.Self], dll: CDLL, name: str, /) -> _typeshed.Self: ...
# At runtime, various attributes are created on a Union subclass based
# on its _fields_. This method doesn't exist, but represents those
# dynamically created attributes.
def __getattr__(self, name: str) -> _CField[Any, Any, Any]: ...
if sys.version_info < (3, 13):
# Inherited from CType_Type starting on 3.13
def __mul__(cls: type[_CT], other: int) -> type[Array[_CT]]: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
def __rmul__(cls: type[_CT], other: int) -> type[Array[_CT]]: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
class Union(_CData, metaclass=_UnionType):
_fields_: ClassVar[Sequence[tuple[str, type[_CDataType]] | tuple[str, type[_CDataType], int]]]
_pack_: ClassVar[int]
_anonymous_: ClassVar[Sequence[str]]
if sys.version_info >= (3, 13):
_align_: ClassVar[int]
def __init__(self, *args: Any, **kw: Any) -> None: ...
def __getattr__(self, name: str) -> Any: ...
def __setattr__(self, name: str, value: Any) -> None: ...
# This class is not exposed. It calls itself _ctypes.PyCStructType.
@type_check_only
class _PyCStructType(_CTypeBaseType):
def from_address(self: type[_typeshed.Self], value: int, /) -> _typeshed.Self: ...
def from_buffer(self: type[_typeshed.Self], obj: WriteableBuffer, offset: int = 0, /) -> _typeshed.Self: ...
def from_buffer_copy(self: type[_typeshed.Self], buffer: ReadableBuffer, offset: int = 0, /) -> _typeshed.Self: ...
def from_param(self: type[_typeshed.Self], value: Any, /) -> _typeshed.Self | _CArgObject: ...
def in_dll(self: type[_typeshed.Self], dll: CDLL, name: str, /) -> _typeshed.Self: ...
# At runtime, various attributes are created on a Structure subclass based
# on its _fields_. This method doesn't exist, but represents those
# dynamically created attributes.
def __getattr__(self, name: str) -> _CField[Any, Any, Any]: ...
if sys.version_info < (3, 13):
# Inherited from CType_Type starting on 3.13
def __mul__(cls: type[_CT], other: int) -> type[Array[_CT]]: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
def __rmul__(cls: type[_CT], other: int) -> type[Array[_CT]]: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
class Structure(_CData, metaclass=_PyCStructType):
_fields_: ClassVar[Sequence[tuple[str, type[_CDataType]] | tuple[str, type[_CDataType], int]]]
_pack_: ClassVar[int]
_anonymous_: ClassVar[Sequence[str]]
if sys.version_info >= (3, 13):
_align_: ClassVar[int]
def __init__(self, *args: Any, **kw: Any) -> None: ...
def __getattr__(self, name: str) -> Any: ...
def __setattr__(self, name: str, value: Any) -> None: ...
# This class is not exposed. It calls itself _ctypes.PyCArrayType.
@type_check_only
class _PyCArrayType(_CTypeBaseType):
def from_address(self: type[_typeshed.Self], value: int, /) -> _typeshed.Self: ...
def from_buffer(self: type[_typeshed.Self], obj: WriteableBuffer, offset: int = 0, /) -> _typeshed.Self: ...
def from_buffer_copy(self: type[_typeshed.Self], buffer: ReadableBuffer, offset: int = 0, /) -> _typeshed.Self: ...
def from_param(self: type[_typeshed.Self], value: Any, /) -> _typeshed.Self | _CArgObject: ...
def in_dll(self: type[_typeshed.Self], dll: CDLL, name: str, /) -> _typeshed.Self: ...
if sys.version_info < (3, 13):
# Inherited from CType_Type starting on 3.13
def __mul__(cls: type[_CT], other: int) -> type[Array[_CT]]: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
def __rmul__(cls: type[_CT], other: int) -> type[Array[_CT]]: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
class Array(_CData, Generic[_CT], metaclass=_PyCArrayType):
@property
@abstractmethod
def _length_(self) -> int: ...
@_length_.setter
def _length_(self, value: int) -> None: ...
@property
@abstractmethod
def _type_(self) -> type[_CT]: ...
@_type_.setter
def _type_(self, value: type[_CT]) -> None: ...
# Note: only available if _CT == c_char
@property
def raw(self) -> bytes: ...
@raw.setter
def raw(self, value: ReadableBuffer) -> None: ...
value: Any # Note: bytes if _CT == c_char, str if _CT == c_wchar, unavailable otherwise
# TODO: These methods cannot be annotated correctly at the moment.
# All of these "Any"s stand for the array's element type, but it's not possible to use _CT
# here, because of a special feature of ctypes.
# By default, when accessing an element of an Array[_CT], the returned object has type _CT.
# However, when _CT is a "simple type" like c_int, ctypes automatically "unboxes" the object
# and converts it to the corresponding Python primitive. For example, when accessing an element
# of an Array[c_int], a Python int object is returned, not a c_int.
# This behavior does *not* apply to subclasses of "simple types".
# If MyInt is a subclass of c_int, then accessing an element of an Array[MyInt] returns
# a MyInt, not an int.
# This special behavior is not easy to model in a stub, so for now all places where
# the array element type would belong are annotated with Any instead.
def __init__(self, *args: Any) -> None: ...
@overload
def __getitem__(self, key: int, /) -> Any: ...
@overload
def __getitem__(self, key: slice, /) -> list[Any]: ...
@overload
def __setitem__(self, key: int, value: Any, /) -> None: ...
@overload
def __setitem__(self, key: slice, value: Iterable[Any], /) -> None: ...
def __iter__(self) -> Iterator[Any]: ...
# Can't inherit from Sized because the metaclass conflict between
# Sized and _CData prevents using _CDataMeta.
def __len__(self) -> int: ...
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
def addressof(obj: _CData | _CDataType, /) -> int: ...
def alignment(obj_or_type: _CData | _CDataType | type[_CData | _CDataType], /) -> int: ...
def get_errno() -> int: ...
def resize(obj: _CData | _CDataType, size: int, /) -> None: ...
def set_errno(value: int, /) -> int: ...
def sizeof(obj_or_type: _CData | _CDataType | type[_CData | _CDataType], /) -> int: ...
def PyObj_FromPtr(address: int, /) -> Any: ...
def Py_DECREF(o: _T, /) -> _T: ...
def Py_INCREF(o: _T, /) -> _T: ...
def buffer_info(o: _CData | _CDataType | type[_CData | _CDataType], /) -> tuple[str, int, tuple[int, ...]]: ...
def call_cdeclfunction(address: int, arguments: tuple[Any, ...], /) -> Any: ...
def call_function(address: int, arguments: tuple[Any, ...], /) -> Any: ...

View File

@@ -1,548 +0,0 @@
import sys
from _typeshed import ReadOnlyBuffer, SupportsRead, SupportsWrite
from curses import _ncurses_version
from typing import Any, final, overload
from typing_extensions import TypeAlias
# NOTE: This module is ordinarily only available on Unix, but the windows-curses
# package makes it available on Windows as well with the same contents.
# Handled by PyCurses_ConvertToChtype in _cursesmodule.c.
_ChType: TypeAlias = str | bytes | int
# ACS codes are only initialized after initscr is called
ACS_BBSS: int
ACS_BLOCK: int
ACS_BOARD: int
ACS_BSBS: int
ACS_BSSB: int
ACS_BSSS: int
ACS_BTEE: int
ACS_BULLET: int
ACS_CKBOARD: int
ACS_DARROW: int
ACS_DEGREE: int
ACS_DIAMOND: int
ACS_GEQUAL: int
ACS_HLINE: int
ACS_LANTERN: int
ACS_LARROW: int
ACS_LEQUAL: int
ACS_LLCORNER: int
ACS_LRCORNER: int
ACS_LTEE: int
ACS_NEQUAL: int
ACS_PI: int
ACS_PLMINUS: int
ACS_PLUS: int
ACS_RARROW: int
ACS_RTEE: int
ACS_S1: int
ACS_S3: int
ACS_S7: int
ACS_S9: int
ACS_SBBS: int
ACS_SBSB: int
ACS_SBSS: int
ACS_SSBB: int
ACS_SSBS: int
ACS_SSSB: int
ACS_SSSS: int
ACS_STERLING: int
ACS_TTEE: int
ACS_UARROW: int
ACS_ULCORNER: int
ACS_URCORNER: int
ACS_VLINE: int
ALL_MOUSE_EVENTS: int
A_ALTCHARSET: int
A_ATTRIBUTES: int
A_BLINK: int
A_BOLD: int
A_CHARTEXT: int
A_COLOR: int
A_DIM: int
A_HORIZONTAL: int
A_INVIS: int
A_ITALIC: int
A_LEFT: int
A_LOW: int
A_NORMAL: int
A_PROTECT: int
A_REVERSE: int
A_RIGHT: int
A_STANDOUT: int
A_TOP: int
A_UNDERLINE: int
A_VERTICAL: int
BUTTON1_CLICKED: int
BUTTON1_DOUBLE_CLICKED: int
BUTTON1_PRESSED: int
BUTTON1_RELEASED: int
BUTTON1_TRIPLE_CLICKED: int
BUTTON2_CLICKED: int
BUTTON2_DOUBLE_CLICKED: int
BUTTON2_PRESSED: int
BUTTON2_RELEASED: int
BUTTON2_TRIPLE_CLICKED: int
BUTTON3_CLICKED: int
BUTTON3_DOUBLE_CLICKED: int
BUTTON3_PRESSED: int
BUTTON3_RELEASED: int
BUTTON3_TRIPLE_CLICKED: int
BUTTON4_CLICKED: int
BUTTON4_DOUBLE_CLICKED: int
BUTTON4_PRESSED: int
BUTTON4_RELEASED: int
BUTTON4_TRIPLE_CLICKED: int
# Darwin ncurses doesn't provide BUTTON5_* constants prior to 3.12.10 and 3.13.3
if sys.version_info >= (3, 10):
if sys.version_info >= (3, 12) or sys.platform != "darwin":
BUTTON5_PRESSED: int
BUTTON5_RELEASED: int
BUTTON5_CLICKED: int
BUTTON5_DOUBLE_CLICKED: int
BUTTON5_TRIPLE_CLICKED: int
BUTTON_ALT: int
BUTTON_CTRL: int
BUTTON_SHIFT: int
COLOR_BLACK: int
COLOR_BLUE: int
COLOR_CYAN: int
COLOR_GREEN: int
COLOR_MAGENTA: int
COLOR_RED: int
COLOR_WHITE: int
COLOR_YELLOW: int
ERR: int
KEY_A1: int
KEY_A3: int
KEY_B2: int
KEY_BACKSPACE: int
KEY_BEG: int
KEY_BREAK: int
KEY_BTAB: int
KEY_C1: int
KEY_C3: int
KEY_CANCEL: int
KEY_CATAB: int
KEY_CLEAR: int
KEY_CLOSE: int
KEY_COMMAND: int
KEY_COPY: int
KEY_CREATE: int
KEY_CTAB: int
KEY_DC: int
KEY_DL: int
KEY_DOWN: int
KEY_EIC: int
KEY_END: int
KEY_ENTER: int
KEY_EOL: int
KEY_EOS: int
KEY_EXIT: int
KEY_F0: int
KEY_F1: int
KEY_F10: int
KEY_F11: int
KEY_F12: int
KEY_F13: int
KEY_F14: int
KEY_F15: int
KEY_F16: int
KEY_F17: int
KEY_F18: int
KEY_F19: int
KEY_F2: int
KEY_F20: int
KEY_F21: int
KEY_F22: int
KEY_F23: int
KEY_F24: int
KEY_F25: int
KEY_F26: int
KEY_F27: int
KEY_F28: int
KEY_F29: int
KEY_F3: int
KEY_F30: int
KEY_F31: int
KEY_F32: int
KEY_F33: int
KEY_F34: int
KEY_F35: int
KEY_F36: int
KEY_F37: int
KEY_F38: int
KEY_F39: int
KEY_F4: int
KEY_F40: int
KEY_F41: int
KEY_F42: int
KEY_F43: int
KEY_F44: int
KEY_F45: int
KEY_F46: int
KEY_F47: int
KEY_F48: int
KEY_F49: int
KEY_F5: int
KEY_F50: int
KEY_F51: int
KEY_F52: int
KEY_F53: int
KEY_F54: int
KEY_F55: int
KEY_F56: int
KEY_F57: int
KEY_F58: int
KEY_F59: int
KEY_F6: int
KEY_F60: int
KEY_F61: int
KEY_F62: int
KEY_F63: int
KEY_F7: int
KEY_F8: int
KEY_F9: int
KEY_FIND: int
KEY_HELP: int
KEY_HOME: int
KEY_IC: int
KEY_IL: int
KEY_LEFT: int
KEY_LL: int
KEY_MARK: int
KEY_MAX: int
KEY_MESSAGE: int
KEY_MIN: int
KEY_MOUSE: int
KEY_MOVE: int
KEY_NEXT: int
KEY_NPAGE: int
KEY_OPEN: int
KEY_OPTIONS: int
KEY_PPAGE: int
KEY_PREVIOUS: int
KEY_PRINT: int
KEY_REDO: int
KEY_REFERENCE: int
KEY_REFRESH: int
KEY_REPLACE: int
KEY_RESET: int
KEY_RESIZE: int
KEY_RESTART: int
KEY_RESUME: int
KEY_RIGHT: int
KEY_SAVE: int
KEY_SBEG: int
KEY_SCANCEL: int
KEY_SCOMMAND: int
KEY_SCOPY: int
KEY_SCREATE: int
KEY_SDC: int
KEY_SDL: int
KEY_SELECT: int
KEY_SEND: int
KEY_SEOL: int
KEY_SEXIT: int
KEY_SF: int
KEY_SFIND: int
KEY_SHELP: int
KEY_SHOME: int
KEY_SIC: int
KEY_SLEFT: int
KEY_SMESSAGE: int
KEY_SMOVE: int
KEY_SNEXT: int
KEY_SOPTIONS: int
KEY_SPREVIOUS: int
KEY_SPRINT: int
KEY_SR: int
KEY_SREDO: int
KEY_SREPLACE: int
KEY_SRESET: int
KEY_SRIGHT: int
KEY_SRSUME: int
KEY_SSAVE: int
KEY_SSUSPEND: int
KEY_STAB: int
KEY_SUNDO: int
KEY_SUSPEND: int
KEY_UNDO: int
KEY_UP: int
OK: int
REPORT_MOUSE_POSITION: int
_C_API: Any
version: bytes
def baudrate() -> int: ...
def beep() -> None: ...
def can_change_color() -> bool: ...
def cbreak(flag: bool = True, /) -> None: ...
def color_content(color_number: int, /) -> tuple[int, int, int]: ...
def color_pair(pair_number: int, /) -> int: ...
def curs_set(visibility: int, /) -> int: ...
def def_prog_mode() -> None: ...
def def_shell_mode() -> None: ...
def delay_output(ms: int, /) -> None: ...
def doupdate() -> None: ...
def echo(flag: bool = True, /) -> None: ...
def endwin() -> None: ...
def erasechar() -> bytes: ...
def filter() -> None: ...
def flash() -> None: ...
def flushinp() -> None: ...
def get_escdelay() -> int: ...
def get_tabsize() -> int: ...
def getmouse() -> tuple[int, int, int, int, int]: ...
def getsyx() -> tuple[int, int]: ...
def getwin(file: SupportsRead[bytes], /) -> window: ...
def halfdelay(tenths: int, /) -> None: ...
def has_colors() -> bool: ...
if sys.version_info >= (3, 10):
def has_extended_color_support() -> bool: ...
def has_ic() -> bool: ...
def has_il() -> bool: ...
def has_key(key: int, /) -> bool: ...
def init_color(color_number: int, r: int, g: int, b: int, /) -> None: ...
def init_pair(pair_number: int, fg: int, bg: int, /) -> None: ...
def initscr() -> window: ...
def intrflush(flag: bool, /) -> None: ...
def is_term_resized(nlines: int, ncols: int, /) -> bool: ...
def isendwin() -> bool: ...
def keyname(key: int, /) -> bytes: ...
def killchar() -> bytes: ...
def longname() -> bytes: ...
def meta(yes: bool, /) -> None: ...
def mouseinterval(interval: int, /) -> None: ...
def mousemask(newmask: int, /) -> tuple[int, int]: ...
def napms(ms: int, /) -> int: ...
def newpad(nlines: int, ncols: int, /) -> window: ...
def newwin(nlines: int, ncols: int, begin_y: int = ..., begin_x: int = ..., /) -> window: ...
def nl(flag: bool = True, /) -> None: ...
def nocbreak() -> None: ...
def noecho() -> None: ...
def nonl() -> None: ...
def noqiflush() -> None: ...
def noraw() -> None: ...
def pair_content(pair_number: int, /) -> tuple[int, int]: ...
def pair_number(attr: int, /) -> int: ...
def putp(string: ReadOnlyBuffer, /) -> None: ...
def qiflush(flag: bool = True, /) -> None: ...
def raw(flag: bool = True, /) -> None: ...
def reset_prog_mode() -> None: ...
def reset_shell_mode() -> None: ...
def resetty() -> None: ...
def resize_term(nlines: int, ncols: int, /) -> None: ...
def resizeterm(nlines: int, ncols: int, /) -> None: ...
def savetty() -> None: ...
def set_escdelay(ms: int, /) -> None: ...
def set_tabsize(size: int, /) -> None: ...
def setsyx(y: int, x: int, /) -> None: ...
def setupterm(term: str | None = None, fd: int = -1) -> None: ...
def start_color() -> None: ...
def termattrs() -> int: ...
def termname() -> bytes: ...
def tigetflag(capname: str, /) -> int: ...
def tigetnum(capname: str, /) -> int: ...
def tigetstr(capname: str, /) -> bytes | None: ...
def tparm(
str: ReadOnlyBuffer,
i1: int = 0,
i2: int = 0,
i3: int = 0,
i4: int = 0,
i5: int = 0,
i6: int = 0,
i7: int = 0,
i8: int = 0,
i9: int = 0,
/,
) -> bytes: ...
def typeahead(fd: int, /) -> None: ...
def unctrl(ch: _ChType, /) -> bytes: ...
def unget_wch(ch: int | str, /) -> None: ...
def ungetch(ch: _ChType, /) -> None: ...
def ungetmouse(id: int, x: int, y: int, z: int, bstate: int, /) -> None: ...
def update_lines_cols() -> None: ...
def use_default_colors() -> None: ...
def use_env(flag: bool, /) -> None: ...
class error(Exception): ...
@final
class window: # undocumented
encoding: str
@overload
def addch(self, ch: _ChType, attr: int = ...) -> None: ...
@overload
def addch(self, y: int, x: int, ch: _ChType, attr: int = ...) -> None: ...
@overload
def addnstr(self, str: str, n: int, attr: int = ...) -> None: ...
@overload
def addnstr(self, y: int, x: int, str: str, n: int, attr: int = ...) -> None: ...
@overload
def addstr(self, str: str, attr: int = ...) -> None: ...
@overload
def addstr(self, y: int, x: int, str: str, attr: int = ...) -> None: ...
def attroff(self, attr: int, /) -> None: ...
def attron(self, attr: int, /) -> None: ...
def attrset(self, attr: int, /) -> None: ...
def bkgd(self, ch: _ChType, attr: int = ..., /) -> None: ...
def bkgdset(self, ch: _ChType, attr: int = ..., /) -> None: ...
def border(
self,
ls: _ChType = ...,
rs: _ChType = ...,
ts: _ChType = ...,
bs: _ChType = ...,
tl: _ChType = ...,
tr: _ChType = ...,
bl: _ChType = ...,
br: _ChType = ...,
) -> None: ...
@overload
def box(self) -> None: ...
@overload
def box(self, vertch: _ChType = ..., horch: _ChType = ...) -> None: ...
@overload
def chgat(self, attr: int) -> None: ...
@overload
def chgat(self, num: int, attr: int) -> None: ...
@overload
def chgat(self, y: int, x: int, attr: int) -> None: ...
@overload
def chgat(self, y: int, x: int, num: int, attr: int) -> None: ...
def clear(self) -> None: ...
def clearok(self, yes: int) -> None: ...
def clrtobot(self) -> None: ...
def clrtoeol(self) -> None: ...
def cursyncup(self) -> None: ...
@overload
def delch(self) -> None: ...
@overload
def delch(self, y: int, x: int) -> None: ...
def deleteln(self) -> None: ...
@overload
def derwin(self, begin_y: int, begin_x: int) -> window: ...
@overload
def derwin(self, nlines: int, ncols: int, begin_y: int, begin_x: int) -> window: ...
def echochar(self, ch: _ChType, attr: int = ..., /) -> None: ...
def enclose(self, y: int, x: int, /) -> bool: ...
def erase(self) -> None: ...
def getbegyx(self) -> tuple[int, int]: ...
def getbkgd(self) -> tuple[int, int]: ...
@overload
def getch(self) -> int: ...
@overload
def getch(self, y: int, x: int) -> int: ...
@overload
def get_wch(self) -> int | str: ...
@overload
def get_wch(self, y: int, x: int) -> int | str: ...
@overload
def getkey(self) -> str: ...
@overload
def getkey(self, y: int, x: int) -> str: ...
def getmaxyx(self) -> tuple[int, int]: ...
def getparyx(self) -> tuple[int, int]: ...
@overload
def getstr(self) -> bytes: ...
@overload
def getstr(self, n: int) -> bytes: ...
@overload
def getstr(self, y: int, x: int) -> bytes: ...
@overload
def getstr(self, y: int, x: int, n: int) -> bytes: ...
def getyx(self) -> tuple[int, int]: ...
@overload
def hline(self, ch: _ChType, n: int) -> None: ...
@overload
def hline(self, y: int, x: int, ch: _ChType, n: int) -> None: ...
def idcok(self, flag: bool) -> None: ...
def idlok(self, yes: bool) -> None: ...
def immedok(self, flag: bool) -> None: ...
@overload
def inch(self) -> int: ...
@overload
def inch(self, y: int, x: int) -> int: ...
@overload
def insch(self, ch: _ChType, attr: int = ...) -> None: ...
@overload
def insch(self, y: int, x: int, ch: _ChType, attr: int = ...) -> None: ...
def insdelln(self, nlines: int) -> None: ...
def insertln(self) -> None: ...
@overload
def insnstr(self, str: str, n: int, attr: int = ...) -> None: ...
@overload
def insnstr(self, y: int, x: int, str: str, n: int, attr: int = ...) -> None: ...
@overload
def insstr(self, str: str, attr: int = ...) -> None: ...
@overload
def insstr(self, y: int, x: int, str: str, attr: int = ...) -> None: ...
@overload
def instr(self, n: int = ...) -> bytes: ...
@overload
def instr(self, y: int, x: int, n: int = ...) -> bytes: ...
def is_linetouched(self, line: int, /) -> bool: ...
def is_wintouched(self) -> bool: ...
def keypad(self, yes: bool, /) -> None: ...
def leaveok(self, yes: bool) -> None: ...
def move(self, new_y: int, new_x: int) -> None: ...
def mvderwin(self, y: int, x: int) -> None: ...
def mvwin(self, new_y: int, new_x: int) -> None: ...
def nodelay(self, yes: bool) -> None: ...
def notimeout(self, yes: bool) -> None: ...
@overload
def noutrefresh(self) -> None: ...
@overload
def noutrefresh(self, pminrow: int, pmincol: int, sminrow: int, smincol: int, smaxrow: int, smaxcol: int) -> None: ...
@overload
def overlay(self, destwin: window) -> None: ...
@overload
def overlay(
self, destwin: window, sminrow: int, smincol: int, dminrow: int, dmincol: int, dmaxrow: int, dmaxcol: int
) -> None: ...
@overload
def overwrite(self, destwin: window) -> None: ...
@overload
def overwrite(
self, destwin: window, sminrow: int, smincol: int, dminrow: int, dmincol: int, dmaxrow: int, dmaxcol: int
) -> None: ...
def putwin(self, file: SupportsWrite[bytes], /) -> None: ...
def redrawln(self, beg: int, num: int, /) -> None: ...
def redrawwin(self) -> None: ...
@overload
def refresh(self) -> None: ...
@overload
def refresh(self, pminrow: int, pmincol: int, sminrow: int, smincol: int, smaxrow: int, smaxcol: int) -> None: ...
def resize(self, nlines: int, ncols: int) -> None: ...
def scroll(self, lines: int = ...) -> None: ...
def scrollok(self, flag: bool) -> None: ...
def setscrreg(self, top: int, bottom: int, /) -> None: ...
def standend(self) -> None: ...
def standout(self) -> None: ...
@overload
def subpad(self, begin_y: int, begin_x: int) -> window: ...
@overload
def subpad(self, nlines: int, ncols: int, begin_y: int, begin_x: int) -> window: ...
@overload
def subwin(self, begin_y: int, begin_x: int) -> window: ...
@overload
def subwin(self, nlines: int, ncols: int, begin_y: int, begin_x: int) -> window: ...
def syncdown(self) -> None: ...
def syncok(self, flag: bool) -> None: ...
def syncup(self) -> None: ...
def timeout(self, delay: int) -> None: ...
def touchline(self, start: int, count: int, changed: bool = ...) -> None: ...
def touchwin(self) -> None: ...
def untouchwin(self) -> None: ...
@overload
def vline(self, ch: _ChType, n: int) -> None: ...
@overload
def vline(self, y: int, x: int, ch: _ChType, n: int) -> None: ...
ncurses_version: _ncurses_version

View File

@@ -1,27 +0,0 @@
from _curses import window
from typing import final
__version__: str
version: str
class error(Exception): ...
@final
class panel:
def above(self) -> panel: ...
def below(self) -> panel: ...
def bottom(self) -> None: ...
def hidden(self) -> bool: ...
def hide(self) -> None: ...
def move(self, y: int, x: int, /) -> None: ...
def replace(self, win: window, /) -> None: ...
def set_userptr(self, obj: object, /) -> None: ...
def show(self) -> None: ...
def top(self) -> None: ...
def userptr(self) -> object: ...
def window(self) -> window: ...
def bottom_panel() -> panel: ...
def new_panel(win: window, /) -> panel: ...
def top_panel() -> panel: ...
def update_panels() -> panel: ...

View File

@@ -1,44 +0,0 @@
import sys
from _typeshed import ReadOnlyBuffer, StrOrBytesPath
from types import TracebackType
from typing import TypeVar, final, overload, type_check_only
from typing_extensions import Self, TypeAlias
if sys.platform != "win32":
_T = TypeVar("_T")
_KeyType: TypeAlias = str | ReadOnlyBuffer
_ValueType: TypeAlias = str | ReadOnlyBuffer
class error(OSError): ...
library: str
# Actual typename dbm, not exposed by the implementation
@final
@type_check_only
class _dbm:
def close(self) -> None: ...
if sys.version_info >= (3, 13):
def clear(self) -> None: ...
def __getitem__(self, item: _KeyType) -> bytes: ...
def __setitem__(self, key: _KeyType, value: _ValueType) -> None: ...
def __delitem__(self, key: _KeyType) -> None: ...
def __len__(self) -> int: ...
def __enter__(self) -> Self: ...
def __exit__(
self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None
) -> None: ...
@overload
def get(self, k: _KeyType, /) -> bytes | None: ...
@overload
def get(self, k: _KeyType, default: _T, /) -> bytes | _T: ...
def keys(self) -> list[bytes]: ...
def setdefault(self, k: _KeyType, default: _ValueType = ..., /) -> bytes: ...
# This isn't true, but the class can't be instantiated. See #13024
__new__: None # type: ignore[assignment]
__init__: None # type: ignore[assignment]
if sys.version_info >= (3, 11):
def open(filename: StrOrBytesPath, flags: str = "r", mode: int = 0o666, /) -> _dbm: ...
else:
def open(filename: str, flags: str = "r", mode: int = 0o666, /) -> _dbm: ...

View File

@@ -1,67 +0,0 @@
import sys
from decimal import (
Clamped as Clamped,
Context as Context,
ConversionSyntax as ConversionSyntax,
Decimal as Decimal,
DecimalException as DecimalException,
DecimalTuple as DecimalTuple,
DivisionByZero as DivisionByZero,
DivisionImpossible as DivisionImpossible,
DivisionUndefined as DivisionUndefined,
FloatOperation as FloatOperation,
Inexact as Inexact,
InvalidContext as InvalidContext,
InvalidOperation as InvalidOperation,
Overflow as Overflow,
Rounded as Rounded,
Subnormal as Subnormal,
Underflow as Underflow,
_ContextManager,
)
from typing import Final
from typing_extensions import TypeAlias
_TrapType: TypeAlias = type[DecimalException]
__version__: Final[str]
__libmpdec_version__: Final[str]
ROUND_DOWN: Final = "ROUND_DOWN"
ROUND_HALF_UP: Final = "ROUND_HALF_UP"
ROUND_HALF_EVEN: Final = "ROUND_HALF_EVEN"
ROUND_CEILING: Final = "ROUND_CEILING"
ROUND_FLOOR: Final = "ROUND_FLOOR"
ROUND_UP: Final = "ROUND_UP"
ROUND_HALF_DOWN: Final = "ROUND_HALF_DOWN"
ROUND_05UP: Final = "ROUND_05UP"
HAVE_CONTEXTVAR: Final[bool]
HAVE_THREADS: Final[bool]
MAX_EMAX: Final[int]
MAX_PREC: Final[int]
MIN_EMIN: Final[int]
MIN_ETINY: Final[int]
def setcontext(context: Context, /) -> None: ...
def getcontext() -> Context: ...
if sys.version_info >= (3, 11):
def localcontext(
ctx: Context | None = None,
*,
prec: int | None = ...,
rounding: str | None = ...,
Emin: int | None = ...,
Emax: int | None = ...,
capitals: int | None = ...,
clamp: int | None = ...,
traps: dict[_TrapType, bool] | None = ...,
flags: dict[_TrapType, bool] | None = ...,
) -> _ContextManager: ...
else:
def localcontext(ctx: Context | None = None) -> _ContextManager: ...
DefaultContext: Context
BasicContext: Context
ExtendedContext: Context

View File

@@ -1,113 +0,0 @@
import importlib.abc
import importlib.machinery
import sys
import types
from _typeshed.importlib import LoaderProtocol
from collections.abc import Mapping, Sequence
from types import ModuleType
from typing import Any, ClassVar
# Signature of `builtins.__import__` should be kept identical to `importlib.__import__`
def __import__(
name: str,
globals: Mapping[str, object] | None = None,
locals: Mapping[str, object] | None = None,
fromlist: Sequence[str] = (),
level: int = 0,
) -> ModuleType: ...
def spec_from_loader(
name: str, loader: LoaderProtocol | None, *, origin: str | None = None, is_package: bool | None = None
) -> importlib.machinery.ModuleSpec | None: ...
def module_from_spec(spec: importlib.machinery.ModuleSpec) -> types.ModuleType: ...
def _init_module_attrs(
spec: importlib.machinery.ModuleSpec, module: types.ModuleType, *, override: bool = False
) -> types.ModuleType: ...
class ModuleSpec:
def __init__(
self,
name: str,
loader: importlib.abc.Loader | None,
*,
origin: str | None = None,
loader_state: Any = None,
is_package: bool | None = None,
) -> None: ...
name: str
loader: importlib.abc.Loader | None
origin: str | None
submodule_search_locations: list[str] | None
loader_state: Any
cached: str | None
@property
def parent(self) -> str | None: ...
has_location: bool
def __eq__(self, other: object) -> bool: ...
__hash__: ClassVar[None] # type: ignore[assignment]
class BuiltinImporter(importlib.abc.MetaPathFinder, importlib.abc.InspectLoader):
# MetaPathFinder
if sys.version_info < (3, 12):
@classmethod
def find_module(cls, fullname: str, path: Sequence[str] | None = None) -> importlib.abc.Loader | None: ...
@classmethod
def find_spec(
cls, fullname: str, path: Sequence[str] | None = None, target: types.ModuleType | None = None
) -> ModuleSpec | None: ...
# InspectLoader
@classmethod
def is_package(cls, fullname: str) -> bool: ...
@classmethod
def load_module(cls, fullname: str) -> types.ModuleType: ...
@classmethod
def get_code(cls, fullname: str) -> None: ...
@classmethod
def get_source(cls, fullname: str) -> None: ...
# Loader
if sys.version_info < (3, 12):
@staticmethod
def module_repr(module: types.ModuleType) -> str: ...
if sys.version_info >= (3, 10):
@staticmethod
def create_module(spec: ModuleSpec) -> types.ModuleType | None: ...
@staticmethod
def exec_module(module: types.ModuleType) -> None: ...
else:
@classmethod
def create_module(cls, spec: ModuleSpec) -> types.ModuleType | None: ...
@classmethod
def exec_module(cls, module: types.ModuleType) -> None: ...
class FrozenImporter(importlib.abc.MetaPathFinder, importlib.abc.InspectLoader):
# MetaPathFinder
if sys.version_info < (3, 12):
@classmethod
def find_module(cls, fullname: str, path: Sequence[str] | None = None) -> importlib.abc.Loader | None: ...
@classmethod
def find_spec(
cls, fullname: str, path: Sequence[str] | None = None, target: types.ModuleType | None = None
) -> ModuleSpec | None: ...
# InspectLoader
@classmethod
def is_package(cls, fullname: str) -> bool: ...
@classmethod
def load_module(cls, fullname: str) -> types.ModuleType: ...
@classmethod
def get_code(cls, fullname: str) -> None: ...
@classmethod
def get_source(cls, fullname: str) -> None: ...
# Loader
if sys.version_info < (3, 12):
@staticmethod
def module_repr(m: types.ModuleType) -> str: ...
if sys.version_info >= (3, 10):
@staticmethod
def create_module(spec: ModuleSpec) -> types.ModuleType | None: ...
else:
@classmethod
def create_module(cls, spec: ModuleSpec) -> types.ModuleType | None: ...
@staticmethod
def exec_module(module: types.ModuleType) -> None: ...

View File

@@ -1,178 +0,0 @@
import _ast
import _io
import importlib.abc
import importlib.machinery
import sys
import types
from _typeshed import ReadableBuffer, StrOrBytesPath, StrPath
from _typeshed.importlib import LoaderProtocol
from collections.abc import Callable, Iterable, Iterator, Mapping, MutableSequence, Sequence
from importlib.machinery import ModuleSpec
from importlib.metadata import DistributionFinder, PathDistribution
from typing import Any, Literal
from typing_extensions import Self, deprecated
if sys.version_info >= (3, 10):
import importlib.readers
if sys.platform == "win32":
path_separators: Literal["\\/"]
path_sep: Literal["\\"]
path_sep_tuple: tuple[Literal["\\"], Literal["/"]]
else:
path_separators: Literal["/"]
path_sep: Literal["/"]
path_sep_tuple: tuple[Literal["/"]]
MAGIC_NUMBER: bytes
def cache_from_source(path: StrPath, debug_override: bool | None = None, *, optimization: Any | None = None) -> str: ...
def source_from_cache(path: StrPath) -> str: ...
def decode_source(source_bytes: ReadableBuffer) -> str: ...
def spec_from_file_location(
name: str,
location: StrOrBytesPath | None = None,
*,
loader: LoaderProtocol | None = None,
submodule_search_locations: list[str] | None = ...,
) -> importlib.machinery.ModuleSpec | None: ...
class WindowsRegistryFinder(importlib.abc.MetaPathFinder):
if sys.version_info < (3, 12):
@classmethod
def find_module(cls, fullname: str, path: Sequence[str] | None = None) -> importlib.abc.Loader | None: ...
@classmethod
def find_spec(
cls, fullname: str, path: Sequence[str] | None = None, target: types.ModuleType | None = None
) -> ModuleSpec | None: ...
class PathFinder(importlib.abc.MetaPathFinder):
if sys.version_info >= (3, 10):
@staticmethod
def invalidate_caches() -> None: ...
else:
@classmethod
def invalidate_caches(cls) -> None: ...
if sys.version_info >= (3, 10):
@staticmethod
def find_distributions(context: DistributionFinder.Context = ...) -> Iterable[PathDistribution]: ...
else:
@classmethod
def find_distributions(cls, context: DistributionFinder.Context = ...) -> Iterable[PathDistribution]: ...
@classmethod
def find_spec(
cls, fullname: str, path: Sequence[str] | None = None, target: types.ModuleType | None = None
) -> ModuleSpec | None: ...
if sys.version_info < (3, 12):
@classmethod
def find_module(cls, fullname: str, path: Sequence[str] | None = None) -> importlib.abc.Loader | None: ...
SOURCE_SUFFIXES: list[str]
DEBUG_BYTECODE_SUFFIXES: list[str]
OPTIMIZED_BYTECODE_SUFFIXES: list[str]
BYTECODE_SUFFIXES: list[str]
EXTENSION_SUFFIXES: list[str]
class FileFinder(importlib.abc.PathEntryFinder):
path: str
def __init__(self, path: str, *loader_details: tuple[type[importlib.abc.Loader], list[str]]) -> None: ...
@classmethod
def path_hook(
cls, *loader_details: tuple[type[importlib.abc.Loader], list[str]]
) -> Callable[[str], importlib.abc.PathEntryFinder]: ...
class _LoaderBasics:
def is_package(self, fullname: str) -> bool: ...
def create_module(self, spec: ModuleSpec) -> types.ModuleType | None: ...
def exec_module(self, module: types.ModuleType) -> None: ...
def load_module(self, fullname: str) -> types.ModuleType: ...
class SourceLoader(_LoaderBasics):
def path_mtime(self, path: str) -> float: ...
def set_data(self, path: str, data: bytes) -> None: ...
def get_source(self, fullname: str) -> str | None: ...
def path_stats(self, path: str) -> Mapping[str, Any]: ...
def source_to_code(
self, data: ReadableBuffer | str | _ast.Module | _ast.Expression | _ast.Interactive, path: ReadableBuffer | StrPath
) -> types.CodeType: ...
def get_code(self, fullname: str) -> types.CodeType | None: ...
class FileLoader:
name: str
path: str
def __init__(self, fullname: str, path: str) -> None: ...
def get_data(self, path: str) -> bytes: ...
def get_filename(self, name: str | None = None) -> str: ...
def load_module(self, name: str | None = None) -> types.ModuleType: ...
if sys.version_info >= (3, 10):
def get_resource_reader(self, name: str | None = None) -> importlib.readers.FileReader: ...
else:
def get_resource_reader(self, name: str | None = None) -> Self | None: ...
def open_resource(self, resource: str) -> _io.FileIO: ...
def resource_path(self, resource: str) -> str: ...
def is_resource(self, name: str) -> bool: ...
def contents(self) -> Iterator[str]: ...
class SourceFileLoader(importlib.abc.FileLoader, FileLoader, importlib.abc.SourceLoader, SourceLoader): # type: ignore[misc] # incompatible method arguments in base classes
def set_data(self, path: str, data: ReadableBuffer, *, _mode: int = 0o666) -> None: ...
def path_stats(self, path: str) -> Mapping[str, Any]: ...
class SourcelessFileLoader(importlib.abc.FileLoader, FileLoader, _LoaderBasics):
def get_code(self, fullname: str) -> types.CodeType | None: ...
def get_source(self, fullname: str) -> None: ...
class ExtensionFileLoader(FileLoader, _LoaderBasics, importlib.abc.ExecutionLoader):
def __init__(self, name: str, path: str) -> None: ...
def get_filename(self, name: str | None = None) -> str: ...
def get_source(self, fullname: str) -> None: ...
def create_module(self, spec: ModuleSpec) -> types.ModuleType: ...
def exec_module(self, module: types.ModuleType) -> None: ...
def get_code(self, fullname: str) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __hash__(self) -> int: ...
if sys.version_info >= (3, 11):
class NamespaceLoader(importlib.abc.InspectLoader):
def __init__(
self, name: str, path: MutableSequence[str], path_finder: Callable[[str, tuple[str, ...]], ModuleSpec]
) -> None: ...
def is_package(self, fullname: str) -> Literal[True]: ...
def get_source(self, fullname: str) -> Literal[""]: ...
def get_code(self, fullname: str) -> types.CodeType: ...
def create_module(self, spec: ModuleSpec) -> None: ...
def exec_module(self, module: types.ModuleType) -> None: ...
@deprecated("load_module() is deprecated; use exec_module() instead")
def load_module(self, fullname: str) -> types.ModuleType: ...
def get_resource_reader(self, module: types.ModuleType) -> importlib.readers.NamespaceReader: ...
if sys.version_info < (3, 12):
@staticmethod
@deprecated("module_repr() is deprecated, and has been removed in Python 3.12")
def module_repr(module: types.ModuleType) -> str: ...
_NamespaceLoader = NamespaceLoader
else:
class _NamespaceLoader:
def __init__(
self, name: str, path: MutableSequence[str], path_finder: Callable[[str, tuple[str, ...]], ModuleSpec]
) -> None: ...
def is_package(self, fullname: str) -> Literal[True]: ...
def get_source(self, fullname: str) -> Literal[""]: ...
def get_code(self, fullname: str) -> types.CodeType: ...
def create_module(self, spec: ModuleSpec) -> None: ...
def exec_module(self, module: types.ModuleType) -> None: ...
@deprecated("load_module() is deprecated; use exec_module() instead")
def load_module(self, fullname: str) -> types.ModuleType: ...
if sys.version_info >= (3, 10):
@staticmethod
@deprecated("module_repr() is deprecated, and has been removed in Python 3.12")
def module_repr(module: types.ModuleType) -> str: ...
def get_resource_reader(self, module: types.ModuleType) -> importlib.readers.NamespaceReader: ...
else:
@classmethod
@deprecated("module_repr() is deprecated, and has been removed in Python 3.12")
def module_repr(cls, module: types.ModuleType) -> str: ...
if sys.version_info >= (3, 13):
class AppleFrameworkLoader(ExtensionFileLoader, importlib.abc.ExecutionLoader): ...

View File

@@ -1,47 +0,0 @@
import sys
from _typeshed import ReadOnlyBuffer, StrOrBytesPath
from types import TracebackType
from typing import TypeVar, overload
from typing_extensions import Self, TypeAlias
if sys.platform != "win32":
_T = TypeVar("_T")
_KeyType: TypeAlias = str | ReadOnlyBuffer
_ValueType: TypeAlias = str | ReadOnlyBuffer
open_flags: str
class error(OSError): ...
# Actual typename gdbm, not exposed by the implementation
class _gdbm:
def firstkey(self) -> bytes | None: ...
def nextkey(self, key: _KeyType) -> bytes | None: ...
def reorganize(self) -> None: ...
def sync(self) -> None: ...
def close(self) -> None: ...
if sys.version_info >= (3, 13):
def clear(self) -> None: ...
def __getitem__(self, item: _KeyType) -> bytes: ...
def __setitem__(self, key: _KeyType, value: _ValueType) -> None: ...
def __delitem__(self, key: _KeyType) -> None: ...
def __contains__(self, key: _KeyType) -> bool: ...
def __len__(self) -> int: ...
def __enter__(self) -> Self: ...
def __exit__(
self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None
) -> None: ...
@overload
def get(self, k: _KeyType) -> bytes | None: ...
@overload
def get(self, k: _KeyType, default: _T) -> bytes | _T: ...
def keys(self) -> list[bytes]: ...
def setdefault(self, k: _KeyType, default: _ValueType = ...) -> bytes: ...
# Don't exist at runtime
__new__: None # type: ignore[assignment]
__init__: None # type: ignore[assignment]
if sys.version_info >= (3, 11):
def open(filename: StrOrBytesPath, flags: str = "r", mode: int = 0o666, /) -> _gdbm: ...
else:
def open(filename: str, flags: str = "r", mode: int = 0o666, /) -> _gdbm: ...

View File

@@ -1,82 +0,0 @@
import sys
from _typeshed import ReadableBuffer
from collections.abc import Callable
from types import ModuleType
from typing import AnyStr, Protocol, final, overload, type_check_only
from typing_extensions import Self, TypeAlias
_DigestMod: TypeAlias = str | Callable[[], _HashObject] | ModuleType | None
openssl_md_meth_names: frozenset[str]
@type_check_only
class _HashObject(Protocol):
@property
def digest_size(self) -> int: ...
@property
def block_size(self) -> int: ...
@property
def name(self) -> str: ...
def copy(self) -> Self: ...
def digest(self) -> bytes: ...
def hexdigest(self) -> str: ...
def update(self, obj: ReadableBuffer, /) -> None: ...
class HASH:
@property
def digest_size(self) -> int: ...
@property
def block_size(self) -> int: ...
@property
def name(self) -> str: ...
def copy(self) -> Self: ...
def digest(self) -> bytes: ...
def hexdigest(self) -> str: ...
def update(self, obj: ReadableBuffer, /) -> None: ...
if sys.version_info >= (3, 10):
class UnsupportedDigestmodError(ValueError): ...
class HASHXOF(HASH):
def digest(self, length: int) -> bytes: ... # type: ignore[override]
def hexdigest(self, length: int) -> str: ... # type: ignore[override]
@final
class HMAC:
@property
def digest_size(self) -> int: ...
@property
def block_size(self) -> int: ...
@property
def name(self) -> str: ...
def copy(self) -> Self: ...
def digest(self) -> bytes: ...
def hexdigest(self) -> str: ...
def update(self, msg: ReadableBuffer) -> None: ...
@overload
def compare_digest(a: ReadableBuffer, b: ReadableBuffer, /) -> bool: ...
@overload
def compare_digest(a: AnyStr, b: AnyStr, /) -> bool: ...
def get_fips_mode() -> int: ...
def hmac_new(key: bytes | bytearray, msg: ReadableBuffer = b"", digestmod: _DigestMod = None) -> HMAC: ...
def new(name: str, string: ReadableBuffer = b"", *, usedforsecurity: bool = True) -> HASH: ...
def openssl_md5(string: ReadableBuffer = b"", *, usedforsecurity: bool = True) -> HASH: ...
def openssl_sha1(string: ReadableBuffer = b"", *, usedforsecurity: bool = True) -> HASH: ...
def openssl_sha224(string: ReadableBuffer = b"", *, usedforsecurity: bool = True) -> HASH: ...
def openssl_sha256(string: ReadableBuffer = b"", *, usedforsecurity: bool = True) -> HASH: ...
def openssl_sha384(string: ReadableBuffer = b"", *, usedforsecurity: bool = True) -> HASH: ...
def openssl_sha512(string: ReadableBuffer = b"", *, usedforsecurity: bool = True) -> HASH: ...
def openssl_sha3_224(string: ReadableBuffer = b"", *, usedforsecurity: bool = True) -> HASH: ...
def openssl_sha3_256(string: ReadableBuffer = b"", *, usedforsecurity: bool = True) -> HASH: ...
def openssl_sha3_384(string: ReadableBuffer = b"", *, usedforsecurity: bool = True) -> HASH: ...
def openssl_sha3_512(string: ReadableBuffer = b"", *, usedforsecurity: bool = True) -> HASH: ...
def openssl_shake_128(string: ReadableBuffer = b"", *, usedforsecurity: bool = True) -> HASHXOF: ...
def openssl_shake_256(string: ReadableBuffer = b"", *, usedforsecurity: bool = True) -> HASHXOF: ...
def hmac_digest(key: bytes | bytearray, msg: ReadableBuffer, digest: str) -> bytes: ...
def pbkdf2_hmac(
hash_name: str, password: ReadableBuffer, salt: ReadableBuffer, iterations: int, dklen: int | None = None
) -> bytes: ...
def scrypt(
password: ReadableBuffer, *, salt: ReadableBuffer, n: int, r: int, p: int, maxmem: int = 0, dklen: int = 64
) -> bytes: ...

View File

@@ -1,11 +0,0 @@
from typing import Any, Final, TypeVar
_T = TypeVar("_T")
__about__: Final[str]
def heapify(heap: list[Any], /) -> None: ...
def heappop(heap: list[_T], /) -> _T: ...
def heappush(heap: list[_T], item: _T, /) -> None: ...
def heappushpop(heap: list[_T], item: _T, /) -> _T: ...
def heapreplace(heap: list[_T], item: _T, /) -> _T: ...

View File

@@ -1,28 +0,0 @@
import sys
import types
from _typeshed import ReadableBuffer
from importlib.machinery import ModuleSpec
from typing import Any
check_hash_based_pycs: str
def source_hash(key: int, source: ReadableBuffer) -> bytes: ...
def create_builtin(spec: ModuleSpec, /) -> types.ModuleType: ...
def create_dynamic(spec: ModuleSpec, file: Any = None, /) -> types.ModuleType: ...
def acquire_lock() -> None: ...
def exec_builtin(mod: types.ModuleType, /) -> int: ...
def exec_dynamic(mod: types.ModuleType, /) -> int: ...
def extension_suffixes() -> list[str]: ...
def init_frozen(name: str, /) -> types.ModuleType: ...
def is_builtin(name: str, /) -> int: ...
def is_frozen(name: str, /) -> bool: ...
def is_frozen_package(name: str, /) -> bool: ...
def lock_held() -> bool: ...
def release_lock() -> None: ...
if sys.version_info >= (3, 11):
def find_frozen(name: str, /, *, withdata: bool = False) -> tuple[memoryview | None, bool, str | None] | None: ...
def get_frozen_object(name: str, data: ReadableBuffer | None = None, /) -> types.CodeType: ...
else:
def get_frozen_object(name: str, /) -> types.CodeType: ...

View File

@@ -1,86 +0,0 @@
from _typeshed import structseq
from typing import Any, Final, Literal, SupportsIndex, final
from typing_extensions import Buffer, Self
class ChannelError(RuntimeError): ...
class ChannelClosedError(ChannelError): ...
class ChannelEmptyError(ChannelError): ...
class ChannelNotEmptyError(ChannelError): ...
class ChannelNotFoundError(ChannelError): ...
# Mark as final, since instantiating ChannelID is not supported.
@final
class ChannelID:
@property
def end(self) -> Literal["send", "recv", "both"]: ...
@property
def send(self) -> Self: ...
@property
def recv(self) -> Self: ...
def __eq__(self, other: object) -> bool: ...
def __ge__(self, other: ChannelID) -> bool: ...
def __gt__(self, other: ChannelID) -> bool: ...
def __hash__(self) -> int: ...
def __index__(self) -> int: ...
def __int__(self) -> int: ...
def __le__(self, other: ChannelID) -> bool: ...
def __lt__(self, other: ChannelID) -> bool: ...
def __ne__(self, other: object) -> bool: ...
@final
class ChannelInfo(structseq[int], tuple[bool, bool, bool, int, int, int, int, int]):
__match_args__: Final = (
"open",
"closing",
"closed",
"count",
"num_interp_send",
"num_interp_send_released",
"num_interp_recv",
"num_interp_recv_released",
)
@property
def open(self) -> bool: ...
@property
def closing(self) -> bool: ...
@property
def closed(self) -> bool: ...
@property
def count(self) -> int: ... # type: ignore[override]
@property
def num_interp_send(self) -> int: ...
@property
def num_interp_send_released(self) -> int: ...
@property
def num_interp_recv(self) -> int: ...
@property
def num_interp_recv_released(self) -> int: ...
@property
def num_interp_both(self) -> int: ...
@property
def num_interp_both_recv_released(self) -> int: ...
@property
def num_interp_both_send_released(self) -> int: ...
@property
def num_interp_both_released(self) -> int: ...
@property
def recv_associated(self) -> bool: ...
@property
def recv_released(self) -> bool: ...
@property
def send_associated(self) -> bool: ...
@property
def send_released(self) -> bool: ...
def create(unboundop: Literal[1, 2, 3]) -> ChannelID: ...
def destroy(cid: SupportsIndex) -> None: ...
def list_all() -> list[ChannelID]: ...
def list_interpreters(cid: SupportsIndex, *, send: bool) -> list[int]: ...
def send(cid: SupportsIndex, obj: object, *, blocking: bool = True, timeout: float | None = None) -> None: ...
def send_buffer(cid: SupportsIndex, obj: Buffer, *, blocking: bool = True, timeout: float | None = None) -> None: ...
def recv(cid: SupportsIndex, default: object = ...) -> tuple[Any, Literal[1, 2, 3]]: ...
def close(cid: SupportsIndex, *, send: bool = False, recv: bool = False) -> None: ...
def get_count(cid: SupportsIndex) -> int: ...
def get_info(cid: SupportsIndex) -> ChannelInfo: ...
def get_channel_defaults(cid: SupportsIndex) -> Literal[1, 2, 3]: ...
def release(cid: SupportsIndex, *, send: bool = False, recv: bool = False, force: bool = False) -> None: ...

View File

@@ -1,19 +0,0 @@
from typing import Any, Literal, SupportsIndex
from typing_extensions import TypeAlias
_UnboundOp: TypeAlias = Literal[1, 2, 3]
class QueueError(RuntimeError): ...
class QueueNotFoundError(QueueError): ...
def bind(qid: SupportsIndex) -> None: ...
def create(maxsize: SupportsIndex, fmt: SupportsIndex, unboundop: _UnboundOp) -> int: ...
def destroy(qid: SupportsIndex) -> None: ...
def get(qid: SupportsIndex) -> tuple[Any, int, _UnboundOp | None]: ...
def get_count(qid: SupportsIndex) -> int: ...
def get_maxsize(qid: SupportsIndex) -> int: ...
def get_queue_defaults(qid: SupportsIndex) -> tuple[int, _UnboundOp]: ...
def is_full(qid: SupportsIndex) -> bool: ...
def list_all() -> list[tuple[int, int, _UnboundOp]]: ...
def put(qid: SupportsIndex, obj: Any, fmt: SupportsIndex, unboundop: _UnboundOp) -> None: ...
def release(qid: SupportsIndex) -> None: ...

View File

@@ -1,52 +0,0 @@
import types
from collections.abc import Callable, Mapping
from typing import Final, Literal, SupportsIndex
from typing_extensions import TypeAlias
_Configs: TypeAlias = Literal["default", "isolated", "legacy", "empty", ""]
class InterpreterError(Exception): ...
class InterpreterNotFoundError(InterpreterError): ...
class NotShareableError(ValueError): ...
class CrossInterpreterBufferView:
def __buffer__(self, flags: int, /) -> memoryview: ...
def new_config(name: _Configs = "isolated", /, **overides: object) -> types.SimpleNamespace: ...
def create(config: types.SimpleNamespace | _Configs | None = "isolated", *, reqrefs: bool = False) -> int: ...
def destroy(id: SupportsIndex, *, restrict: bool = False) -> None: ...
def list_all(*, require_ready: bool) -> list[tuple[int, int]]: ...
def get_current() -> tuple[int, int]: ...
def get_main() -> tuple[int, int]: ...
def is_running(id: SupportsIndex, *, restrict: bool = False) -> bool: ...
def get_config(id: SupportsIndex, *, restrict: bool = False) -> types.SimpleNamespace: ...
def whence(id: SupportsIndex) -> int: ...
def exec(
id: SupportsIndex, code: str | types.CodeType | Callable[[], object], shared: bool | None = None, *, restrict: bool = False
) -> None | types.SimpleNamespace: ...
def call(
id: SupportsIndex,
callable: Callable[..., object],
args: tuple[object, ...] | None = None,
kwargs: dict[str, object] | None = None,
*,
restrict: bool = False,
) -> object: ...
def run_string(
id: SupportsIndex, script: str | types.CodeType | Callable[[], object], shared: bool | None = None, *, restrict: bool = False
) -> None: ...
def run_func(
id: SupportsIndex, func: types.CodeType | Callable[[], object], shared: bool | None = None, *, restrict: bool = False
) -> None: ...
def set___main___attrs(id: SupportsIndex, updates: Mapping[str, object], *, restrict: bool = False) -> None: ...
def incref(id: SupportsIndex, *, implieslink: bool = False, restrict: bool = False) -> None: ...
def decref(id: SupportsIndex, *, restrict: bool = False) -> None: ...
def is_shareable(obj: object) -> bool: ...
def capture_exception(exc: BaseException | None = None) -> types.SimpleNamespace: ...
WHENCE_UNKNOWN: Final = 0
WHENCE_RUNTIME: Final = 1
WHENCE_LEGACY_CAPI: Final = 2
WHENCE_CAPI: Final = 3
WHENCE_XI: Final = 4
WHENCE_STDLIB: Final = 5

View File

@@ -1,216 +0,0 @@
import builtins
import codecs
import sys
from _typeshed import FileDescriptorOrPath, MaybeNone, ReadableBuffer, WriteableBuffer
from collections.abc import Callable, Iterable, Iterator
from io import BufferedIOBase, RawIOBase, TextIOBase, UnsupportedOperation as UnsupportedOperation
from os import _Opener
from types import TracebackType
from typing import IO, Any, BinaryIO, Final, Generic, Literal, Protocol, TextIO, TypeVar, overload, type_check_only
from typing_extensions import Self
_T = TypeVar("_T")
DEFAULT_BUFFER_SIZE: Final = 8192
open = builtins.open
def open_code(path: str) -> IO[bytes]: ...
BlockingIOError = builtins.BlockingIOError
class _IOBase:
def __iter__(self) -> Iterator[bytes]: ...
def __next__(self) -> bytes: ...
def __enter__(self) -> Self: ...
def __exit__(
self, exc_type: type[BaseException] | None, exc_val: BaseException | None, exc_tb: TracebackType | None
) -> None: ...
def close(self) -> None: ...
def fileno(self) -> int: ...
def flush(self) -> None: ...
def isatty(self) -> bool: ...
def readable(self) -> bool: ...
read: Callable[..., Any]
def readlines(self, hint: int = -1, /) -> list[bytes]: ...
def seek(self, offset: int, whence: int = 0, /) -> int: ...
def seekable(self) -> bool: ...
def tell(self) -> int: ...
def truncate(self, size: int | None = None, /) -> int: ...
def writable(self) -> bool: ...
write: Callable[..., Any]
def writelines(self, lines: Iterable[ReadableBuffer], /) -> None: ...
def readline(self, size: int | None = -1, /) -> bytes: ...
def __del__(self) -> None: ...
@property
def closed(self) -> bool: ...
def _checkClosed(self) -> None: ... # undocumented
class _RawIOBase(_IOBase):
def readall(self) -> bytes: ...
# The following methods can return None if the file is in non-blocking mode
# and no data is available.
def readinto(self, buffer: WriteableBuffer, /) -> int | MaybeNone: ...
def write(self, b: ReadableBuffer, /) -> int | MaybeNone: ...
def read(self, size: int = -1, /) -> bytes | MaybeNone: ...
class _BufferedIOBase(_IOBase):
def detach(self) -> RawIOBase: ...
def readinto(self, buffer: WriteableBuffer, /) -> int: ...
def write(self, buffer: ReadableBuffer, /) -> int: ...
def readinto1(self, buffer: WriteableBuffer, /) -> int: ...
def read(self, size: int | None = -1, /) -> bytes: ...
def read1(self, size: int = -1, /) -> bytes: ...
class FileIO(RawIOBase, _RawIOBase, BinaryIO): # type: ignore[misc] # incompatible definitions of writelines in the base classes
mode: str
# The type of "name" equals the argument passed in to the constructor,
# but that can make FileIO incompatible with other I/O types that assume
# "name" is a str. In the future, making FileIO generic might help.
name: Any
def __init__(
self, file: FileDescriptorOrPath, mode: str = "r", closefd: bool = True, opener: _Opener | None = None
) -> None: ...
@property
def closefd(self) -> bool: ...
def seek(self, pos: int, whence: int = 0, /) -> int: ...
def read(self, size: int | None = -1, /) -> bytes | MaybeNone: ...
class BytesIO(BufferedIOBase, _BufferedIOBase, BinaryIO): # type: ignore[misc] # incompatible definitions of methods in the base classes
def __init__(self, initial_bytes: ReadableBuffer = b"") -> None: ...
# BytesIO does not contain a "name" field. This workaround is necessary
# to allow BytesIO sub-classes to add this field, as it is defined
# as a read-only property on IO[].
name: Any
def getvalue(self) -> bytes: ...
def getbuffer(self) -> memoryview: ...
def read1(self, size: int | None = -1, /) -> bytes: ...
def readlines(self, size: int | None = None, /) -> list[bytes]: ...
def seek(self, pos: int, whence: int = 0, /) -> int: ...
class BufferedReader(BufferedIOBase, _BufferedIOBase, BinaryIO): # type: ignore[misc] # incompatible definitions of methods in the base classes
raw: RawIOBase
def __init__(self, raw: RawIOBase, buffer_size: int = 8192) -> None: ...
def peek(self, size: int = 0, /) -> bytes: ...
def seek(self, target: int, whence: int = 0, /) -> int: ...
def truncate(self, pos: int | None = None, /) -> int: ...
class BufferedWriter(BufferedIOBase, _BufferedIOBase, BinaryIO): # type: ignore[misc] # incompatible definitions of writelines in the base classes
raw: RawIOBase
def __init__(self, raw: RawIOBase, buffer_size: int = 8192) -> None: ...
def write(self, buffer: ReadableBuffer, /) -> int: ...
def seek(self, target: int, whence: int = 0, /) -> int: ...
def truncate(self, pos: int | None = None, /) -> int: ...
class BufferedRandom(BufferedIOBase, _BufferedIOBase, BinaryIO): # type: ignore[misc] # incompatible definitions of methods in the base classes
mode: str
name: Any
raw: RawIOBase
def __init__(self, raw: RawIOBase, buffer_size: int = 8192) -> None: ...
def seek(self, target: int, whence: int = 0, /) -> int: ... # stubtest needs this
def peek(self, size: int = 0, /) -> bytes: ...
def truncate(self, pos: int | None = None, /) -> int: ...
class BufferedRWPair(BufferedIOBase, _BufferedIOBase):
def __init__(self, reader: RawIOBase, writer: RawIOBase, buffer_size: int = 8192, /) -> None: ...
def peek(self, size: int = 0, /) -> bytes: ...
class _TextIOBase(_IOBase):
encoding: str
errors: str | None
newlines: str | tuple[str, ...] | None
def __iter__(self) -> Iterator[str]: ... # type: ignore[override]
def __next__(self) -> str: ... # type: ignore[override]
def detach(self) -> BinaryIO: ...
def write(self, s: str, /) -> int: ...
def writelines(self, lines: Iterable[str], /) -> None: ... # type: ignore[override]
def readline(self, size: int = -1, /) -> str: ... # type: ignore[override]
def readlines(self, hint: int = -1, /) -> list[str]: ... # type: ignore[override]
def read(self, size: int | None = -1, /) -> str: ...
@type_check_only
class _WrappedBuffer(Protocol):
# "name" is wrapped by TextIOWrapper. Its type is inconsistent between
# the various I/O types, see the comments on TextIOWrapper.name and
# TextIO.name.
@property
def name(self) -> Any: ...
@property
def closed(self) -> bool: ...
def read(self, size: int = ..., /) -> ReadableBuffer: ...
# Optional: def read1(self, size: int, /) -> ReadableBuffer: ...
def write(self, b: bytes, /) -> object: ...
def flush(self) -> object: ...
def close(self) -> object: ...
def seekable(self) -> bool: ...
def readable(self) -> bool: ...
def writable(self) -> bool: ...
def truncate(self, size: int, /) -> int: ...
def fileno(self) -> int: ...
def isatty(self) -> bool: ...
# Optional: Only needs to be present if seekable() returns True.
# def seek(self, offset: Literal[0], whence: Literal[2]) -> int: ...
# def tell(self) -> int: ...
_BufferT_co = TypeVar("_BufferT_co", bound=_WrappedBuffer, default=_WrappedBuffer, covariant=True)
class TextIOWrapper(TextIOBase, _TextIOBase, TextIO, Generic[_BufferT_co]): # type: ignore[misc] # incompatible definitions of write in the base classes
def __init__(
self,
buffer: _BufferT_co,
encoding: str | None = None,
errors: str | None = None,
newline: str | None = None,
line_buffering: bool = False,
write_through: bool = False,
) -> None: ...
# Equals the "buffer" argument passed in to the constructor.
@property
def buffer(self) -> _BufferT_co: ... # type: ignore[override]
@property
def line_buffering(self) -> bool: ...
@property
def write_through(self) -> bool: ...
def reconfigure(
self,
*,
encoding: str | None = None,
errors: str | None = None,
newline: str | None = None,
line_buffering: bool | None = None,
write_through: bool | None = None,
) -> None: ...
def readline(self, size: int = -1, /) -> str: ... # type: ignore[override]
# Equals the "buffer" argument passed in to the constructor.
def detach(self) -> _BufferT_co: ... # type: ignore[override]
# TextIOWrapper's version of seek only supports a limited subset of
# operations.
def seek(self, cookie: int, whence: int = 0, /) -> int: ...
def truncate(self, pos: int | None = None, /) -> int: ...
class StringIO(TextIOBase, _TextIOBase, TextIO): # type: ignore[misc] # incompatible definitions of write in the base classes
def __init__(self, initial_value: str | None = "", newline: str | None = "\n") -> None: ...
# StringIO does not contain a "name" field. This workaround is necessary
# to allow StringIO sub-classes to add this field, as it is defined
# as a read-only property on IO[].
name: Any
def getvalue(self) -> str: ...
@property
def line_buffering(self) -> bool: ...
def seek(self, pos: int, whence: int = 0, /) -> int: ...
def truncate(self, pos: int | None = None, /) -> int: ...
class IncrementalNewlineDecoder:
def __init__(self, decoder: codecs.IncrementalDecoder | None, translate: bool, errors: str = "strict") -> None: ...
def decode(self, input: ReadableBuffer | str, final: bool = False) -> str: ...
@property
def newlines(self) -> str | tuple[str, ...] | None: ...
def getstate(self) -> tuple[bytes, int]: ...
def reset(self) -> None: ...
def setstate(self, state: tuple[bytes, int], /) -> None: ...
if sys.version_info >= (3, 10):
@overload
def text_encoding(encoding: None, stacklevel: int = 2, /) -> Literal["locale", "utf-8"]: ...
@overload
def text_encoding(encoding: _T, stacklevel: int = 2, /) -> _T: ...

View File

@@ -1,51 +0,0 @@
from collections.abc import Callable
from typing import Any, final
from typing_extensions import Self
@final
class make_encoder:
@property
def sort_keys(self) -> bool: ...
@property
def skipkeys(self) -> bool: ...
@property
def key_separator(self) -> str: ...
@property
def indent(self) -> int | None: ...
@property
def markers(self) -> dict[int, Any] | None: ...
@property
def default(self) -> Callable[[Any], Any]: ...
@property
def encoder(self) -> Callable[[str], str]: ...
@property
def item_separator(self) -> str: ...
def __new__(
cls,
markers: dict[int, Any] | None,
default: Callable[[Any], Any],
encoder: Callable[[str], str],
indent: int | None,
key_separator: str,
item_separator: str,
sort_keys: bool,
skipkeys: bool,
allow_nan: bool,
) -> Self: ...
def __call__(self, obj: object, _current_indent_level: int) -> Any: ...
@final
class make_scanner:
object_hook: Any
object_pairs_hook: Any
parse_int: Any
parse_constant: Any
parse_float: Any
strict: bool
# TODO: 'context' needs the attrs above (ducktype), but not __call__.
def __new__(cls, context: make_scanner) -> Self: ...
def __call__(self, string: str, index: int) -> tuple[Any, int]: ...
def encode_basestring(s: str, /) -> str: ...
def encode_basestring_ascii(s: str, /) -> str: ...
def scanstring(string: str, end: int, strict: bool = ...) -> tuple[str, int]: ...

View File

@@ -1,121 +0,0 @@
import sys
from _typeshed import StrPath
from typing import Final, Literal, TypedDict, type_check_only
@type_check_only
class _LocaleConv(TypedDict):
decimal_point: str
grouping: list[int]
thousands_sep: str
int_curr_symbol: str
currency_symbol: str
p_cs_precedes: Literal[0, 1, 127]
n_cs_precedes: Literal[0, 1, 127]
p_sep_by_space: Literal[0, 1, 127]
n_sep_by_space: Literal[0, 1, 127]
mon_decimal_point: str
frac_digits: int
int_frac_digits: int
mon_thousands_sep: str
mon_grouping: list[int]
positive_sign: str
negative_sign: str
p_sign_posn: Literal[0, 1, 2, 3, 4, 127]
n_sign_posn: Literal[0, 1, 2, 3, 4, 127]
LC_CTYPE: Final[int]
LC_COLLATE: Final[int]
LC_TIME: Final[int]
LC_MONETARY: Final[int]
LC_NUMERIC: Final[int]
LC_ALL: Final[int]
CHAR_MAX: Final = 127
def setlocale(category: int, locale: str | None = None, /) -> str: ...
def localeconv() -> _LocaleConv: ...
if sys.version_info >= (3, 11):
def getencoding() -> str: ...
def strcoll(os1: str, os2: str, /) -> int: ...
def strxfrm(string: str, /) -> str: ...
# native gettext functions
# https://docs.python.org/3/library/locale.html#access-to-message-catalogs
# https://github.com/python/cpython/blob/f4c03484da59049eb62a9bf7777b963e2267d187/Modules/_localemodule.c#L626
if sys.platform != "win32":
LC_MESSAGES: int
ABDAY_1: Final[int]
ABDAY_2: Final[int]
ABDAY_3: Final[int]
ABDAY_4: Final[int]
ABDAY_5: Final[int]
ABDAY_6: Final[int]
ABDAY_7: Final[int]
ABMON_1: Final[int]
ABMON_2: Final[int]
ABMON_3: Final[int]
ABMON_4: Final[int]
ABMON_5: Final[int]
ABMON_6: Final[int]
ABMON_7: Final[int]
ABMON_8: Final[int]
ABMON_9: Final[int]
ABMON_10: Final[int]
ABMON_11: Final[int]
ABMON_12: Final[int]
DAY_1: Final[int]
DAY_2: Final[int]
DAY_3: Final[int]
DAY_4: Final[int]
DAY_5: Final[int]
DAY_6: Final[int]
DAY_7: Final[int]
ERA: Final[int]
ERA_D_T_FMT: Final[int]
ERA_D_FMT: Final[int]
ERA_T_FMT: Final[int]
MON_1: Final[int]
MON_2: Final[int]
MON_3: Final[int]
MON_4: Final[int]
MON_5: Final[int]
MON_6: Final[int]
MON_7: Final[int]
MON_8: Final[int]
MON_9: Final[int]
MON_10: Final[int]
MON_11: Final[int]
MON_12: Final[int]
CODESET: Final[int]
D_T_FMT: Final[int]
D_FMT: Final[int]
T_FMT: Final[int]
T_FMT_AMPM: Final[int]
AM_STR: Final[int]
PM_STR: Final[int]
RADIXCHAR: Final[int]
THOUSEP: Final[int]
YESEXPR: Final[int]
NOEXPR: Final[int]
CRNCYSTR: Final[int]
ALT_DIGITS: Final[int]
def nl_langinfo(key: int, /) -> str: ...
# This is dependent on `libintl.h` which is a part of `gettext`
# system dependency. These functions might be missing.
# But, we always say that they are present.
def gettext(msg: str, /) -> str: ...
def dgettext(domain: str | None, msg: str, /) -> str: ...
def dcgettext(domain: str | None, msg: str, category: int, /) -> str: ...
def textdomain(domain: str | None, /) -> str: ...
def bindtextdomain(domain: str, dir: StrPath | None, /) -> str: ...
def bind_textdomain_codeset(domain: str, codeset: str | None, /) -> str | None: ...

View File

@@ -1,35 +0,0 @@
import sys
from _typeshed import structseq
from collections.abc import Callable
from types import CodeType
from typing import Any, Final, final
class Profiler:
def __init__(
self, timer: Callable[[], float] | None = None, timeunit: float = 0.0, subcalls: bool = True, builtins: bool = True
) -> None: ...
def getstats(self) -> list[profiler_entry]: ...
def enable(self, subcalls: bool = True, builtins: bool = True) -> None: ...
def disable(self) -> None: ...
def clear(self) -> None: ...
@final
class profiler_entry(structseq[Any], tuple[CodeType | str, int, int, float, float, list[profiler_subentry]]):
if sys.version_info >= (3, 10):
__match_args__: Final = ("code", "callcount", "reccallcount", "totaltime", "inlinetime", "calls")
code: CodeType | str
callcount: int
reccallcount: int
totaltime: float
inlinetime: float
calls: list[profiler_subentry]
@final
class profiler_subentry(structseq[Any], tuple[CodeType | str, int, int, float, float]):
if sys.version_info >= (3, 10):
__match_args__: Final = ("code", "callcount", "reccallcount", "totaltime", "inlinetime")
code: CodeType | str
callcount: int
reccallcount: int
totaltime: float
inlinetime: float

View File

@@ -1,71 +0,0 @@
import sys
from _typeshed import ReadableBuffer
from collections.abc import Mapping, Sequence
from typing import Any, Final, final
from typing_extensions import Self, TypeAlias
_FilterChain: TypeAlias = Sequence[Mapping[str, Any]]
FORMAT_AUTO: Final = 0
FORMAT_XZ: Final = 1
FORMAT_ALONE: Final = 2
FORMAT_RAW: Final = 3
CHECK_NONE: Final = 0
CHECK_CRC32: Final = 1
CHECK_CRC64: Final = 4
CHECK_SHA256: Final = 10
CHECK_ID_MAX: Final = 15
CHECK_UNKNOWN: Final = 16
FILTER_LZMA1: int # v big number
FILTER_LZMA2: Final = 33
FILTER_DELTA: Final = 3
FILTER_X86: Final = 4
FILTER_IA64: Final = 6
FILTER_ARM: Final = 7
FILTER_ARMTHUMB: Final = 8
FILTER_SPARC: Final = 9
FILTER_POWERPC: Final = 5
MF_HC3: Final = 3
MF_HC4: Final = 4
MF_BT2: Final = 18
MF_BT3: Final = 19
MF_BT4: Final = 20
MODE_FAST: Final = 1
MODE_NORMAL: Final = 2
PRESET_DEFAULT: Final = 6
PRESET_EXTREME: int # v big number
@final
class LZMADecompressor:
if sys.version_info >= (3, 12):
def __new__(cls, format: int | None = ..., memlimit: int | None = ..., filters: _FilterChain | None = ...) -> Self: ...
else:
def __init__(self, format: int | None = ..., memlimit: int | None = ..., filters: _FilterChain | None = ...) -> None: ...
def decompress(self, data: ReadableBuffer, max_length: int = -1) -> bytes: ...
@property
def check(self) -> int: ...
@property
def eof(self) -> bool: ...
@property
def unused_data(self) -> bytes: ...
@property
def needs_input(self) -> bool: ...
@final
class LZMACompressor:
if sys.version_info >= (3, 12):
def __new__(
cls, format: int | None = ..., check: int = ..., preset: int | None = ..., filters: _FilterChain | None = ...
) -> Self: ...
else:
def __init__(
self, format: int | None = ..., check: int = ..., preset: int | None = ..., filters: _FilterChain | None = ...
) -> None: ...
def compress(self, data: ReadableBuffer, /) -> bytes: ...
def flush(self) -> bytes: ...
class LZMAError(Exception): ...
def is_check_supported(check_id: int, /) -> bool: ...

View File

@@ -1,16 +0,0 @@
import sys
from typing import Any
class ParserBase:
def reset(self) -> None: ...
def getpos(self) -> tuple[int, int]: ...
def unknown_decl(self, data: str) -> None: ...
def parse_comment(self, i: int, report: int = 1) -> int: ... # undocumented
def parse_declaration(self, i: int) -> int: ... # undocumented
def parse_marked_section(self, i: int, report: int = 1) -> int: ... # undocumented
def updatepos(self, i: int, j: int) -> int: ... # undocumented
if sys.version_info < (3, 10):
# Removed from ParserBase: https://bugs.python.org/issue31844
def error(self, message: str) -> Any: ... # undocumented
lineno: int # undocumented
offset: int # undocumented

View File

@@ -1,92 +0,0 @@
import sys
if sys.platform == "win32":
class MSIError(Exception): ...
# Actual typename View, not exposed by the implementation
class _View:
def Execute(self, params: _Record | None = ...) -> None: ...
def GetColumnInfo(self, kind: int) -> _Record: ...
def Fetch(self) -> _Record: ...
def Modify(self, mode: int, record: _Record) -> None: ...
def Close(self) -> None: ...
# Don't exist at runtime
__new__: None # type: ignore[assignment]
__init__: None # type: ignore[assignment]
# Actual typename SummaryInformation, not exposed by the implementation
class _SummaryInformation:
def GetProperty(self, field: int) -> int | bytes | None: ...
def GetPropertyCount(self) -> int: ...
def SetProperty(self, field: int, value: int | str) -> None: ...
def Persist(self) -> None: ...
# Don't exist at runtime
__new__: None # type: ignore[assignment]
__init__: None # type: ignore[assignment]
# Actual typename Database, not exposed by the implementation
class _Database:
def OpenView(self, sql: str) -> _View: ...
def Commit(self) -> None: ...
def GetSummaryInformation(self, updateCount: int) -> _SummaryInformation: ...
def Close(self) -> None: ...
# Don't exist at runtime
__new__: None # type: ignore[assignment]
__init__: None # type: ignore[assignment]
# Actual typename Record, not exposed by the implementation
class _Record:
def GetFieldCount(self) -> int: ...
def GetInteger(self, field: int) -> int: ...
def GetString(self, field: int) -> str: ...
def SetString(self, field: int, str: str) -> None: ...
def SetStream(self, field: int, stream: str) -> None: ...
def SetInteger(self, field: int, int: int) -> None: ...
def ClearData(self) -> None: ...
# Don't exist at runtime
__new__: None # type: ignore[assignment]
__init__: None # type: ignore[assignment]
def UuidCreate() -> str: ...
def FCICreate(cabname: str, files: list[str], /) -> None: ...
def OpenDatabase(path: str, persist: int, /) -> _Database: ...
def CreateRecord(count: int, /) -> _Record: ...
MSICOLINFO_NAMES: int
MSICOLINFO_TYPES: int
MSIDBOPEN_CREATE: int
MSIDBOPEN_CREATEDIRECT: int
MSIDBOPEN_DIRECT: int
MSIDBOPEN_PATCHFILE: int
MSIDBOPEN_READONLY: int
MSIDBOPEN_TRANSACT: int
MSIMODIFY_ASSIGN: int
MSIMODIFY_DELETE: int
MSIMODIFY_INSERT: int
MSIMODIFY_INSERT_TEMPORARY: int
MSIMODIFY_MERGE: int
MSIMODIFY_REFRESH: int
MSIMODIFY_REPLACE: int
MSIMODIFY_SEEK: int
MSIMODIFY_UPDATE: int
MSIMODIFY_VALIDATE: int
MSIMODIFY_VALIDATE_DELETE: int
MSIMODIFY_VALIDATE_FIELD: int
MSIMODIFY_VALIDATE_NEW: int
PID_APPNAME: int
PID_AUTHOR: int
PID_CHARCOUNT: int
PID_CODEPAGE: int
PID_COMMENTS: int
PID_CREATE_DTM: int
PID_KEYWORDS: int
PID_LASTAUTHOR: int
PID_LASTPRINTED: int
PID_LASTSAVE_DTM: int
PID_PAGECOUNT: int
PID_REVNUMBER: int
PID_SECURITY: int
PID_SUBJECT: int
PID_TEMPLATE: int
PID_TITLE: int
PID_WORDCOUNT: int

View File

@@ -1,44 +0,0 @@
from _typeshed import ReadableBuffer
from codecs import _ReadableStream, _WritableStream
from collections.abc import Iterable
from typing import final, type_check_only
# This class is not exposed. It calls itself _multibytecodec.MultibyteCodec.
@final
@type_check_only
class _MultibyteCodec:
def decode(self, input: ReadableBuffer, errors: str | None = None) -> str: ...
def encode(self, input: str, errors: str | None = None) -> bytes: ...
class MultibyteIncrementalDecoder:
errors: str
def __init__(self, errors: str = "strict") -> None: ...
def decode(self, input: ReadableBuffer, final: bool = False) -> str: ...
def getstate(self) -> tuple[bytes, int]: ...
def reset(self) -> None: ...
def setstate(self, state: tuple[bytes, int], /) -> None: ...
class MultibyteIncrementalEncoder:
errors: str
def __init__(self, errors: str = "strict") -> None: ...
def encode(self, input: str, final: bool = False) -> bytes: ...
def getstate(self) -> int: ...
def reset(self) -> None: ...
def setstate(self, state: int, /) -> None: ...
class MultibyteStreamReader:
errors: str
stream: _ReadableStream
def __init__(self, stream: _ReadableStream, errors: str = "strict") -> None: ...
def read(self, sizeobj: int | None = None, /) -> str: ...
def readline(self, sizeobj: int | None = None, /) -> str: ...
def readlines(self, sizehintobj: int | None = None, /) -> list[str]: ...
def reset(self) -> None: ...
class MultibyteStreamWriter:
errors: str
stream: _WritableStream
def __init__(self, stream: _WritableStream, errors: str = "strict") -> None: ...
def reset(self) -> None: ...
def write(self, strobj: str, /) -> None: ...
def writelines(self, lines: Iterable[str], /) -> None: ...

View File

@@ -1,115 +0,0 @@
import sys
from _typeshed import SupportsGetItem
from collections.abc import Callable, Container, Iterable, MutableMapping, MutableSequence, Sequence
from operator import attrgetter as attrgetter, itemgetter as itemgetter, methodcaller as methodcaller
from typing import Any, AnyStr, Protocol, SupportsAbs, SupportsIndex, TypeVar, overload
from typing_extensions import ParamSpec, TypeAlias, TypeIs
_R = TypeVar("_R")
_T = TypeVar("_T")
_T_co = TypeVar("_T_co", covariant=True)
_K = TypeVar("_K")
_V = TypeVar("_V")
_P = ParamSpec("_P")
# The following protocols return "Any" instead of bool, since the comparison
# operators can be overloaded to return an arbitrary object. For example,
# the numpy.array comparison dunders return another numpy.array.
class _SupportsDunderLT(Protocol):
def __lt__(self, other: Any, /) -> Any: ...
class _SupportsDunderGT(Protocol):
def __gt__(self, other: Any, /) -> Any: ...
class _SupportsDunderLE(Protocol):
def __le__(self, other: Any, /) -> Any: ...
class _SupportsDunderGE(Protocol):
def __ge__(self, other: Any, /) -> Any: ...
_SupportsComparison: TypeAlias = _SupportsDunderLE | _SupportsDunderGE | _SupportsDunderGT | _SupportsDunderLT
class _SupportsInversion(Protocol[_T_co]):
def __invert__(self) -> _T_co: ...
class _SupportsNeg(Protocol[_T_co]):
def __neg__(self) -> _T_co: ...
class _SupportsPos(Protocol[_T_co]):
def __pos__(self) -> _T_co: ...
# All four comparison functions must have the same signature, or we get false-positive errors
def lt(a: _SupportsComparison, b: _SupportsComparison, /) -> Any: ...
def le(a: _SupportsComparison, b: _SupportsComparison, /) -> Any: ...
def eq(a: object, b: object, /) -> Any: ...
def ne(a: object, b: object, /) -> Any: ...
def ge(a: _SupportsComparison, b: _SupportsComparison, /) -> Any: ...
def gt(a: _SupportsComparison, b: _SupportsComparison, /) -> Any: ...
def not_(a: object, /) -> bool: ...
def truth(a: object, /) -> bool: ...
def is_(a: object, b: object, /) -> bool: ...
def is_not(a: object, b: object, /) -> bool: ...
def abs(a: SupportsAbs[_T], /) -> _T: ...
def add(a: Any, b: Any, /) -> Any: ...
def and_(a: Any, b: Any, /) -> Any: ...
def floordiv(a: Any, b: Any, /) -> Any: ...
def index(a: SupportsIndex, /) -> int: ...
def inv(a: _SupportsInversion[_T_co], /) -> _T_co: ...
def invert(a: _SupportsInversion[_T_co], /) -> _T_co: ...
def lshift(a: Any, b: Any, /) -> Any: ...
def mod(a: Any, b: Any, /) -> Any: ...
def mul(a: Any, b: Any, /) -> Any: ...
def matmul(a: Any, b: Any, /) -> Any: ...
def neg(a: _SupportsNeg[_T_co], /) -> _T_co: ...
def or_(a: Any, b: Any, /) -> Any: ...
def pos(a: _SupportsPos[_T_co], /) -> _T_co: ...
def pow(a: Any, b: Any, /) -> Any: ...
def rshift(a: Any, b: Any, /) -> Any: ...
def sub(a: Any, b: Any, /) -> Any: ...
def truediv(a: Any, b: Any, /) -> Any: ...
def xor(a: Any, b: Any, /) -> Any: ...
def concat(a: Sequence[_T], b: Sequence[_T], /) -> Sequence[_T]: ...
def contains(a: Container[object], b: object, /) -> bool: ...
def countOf(a: Iterable[object], b: object, /) -> int: ...
@overload
def delitem(a: MutableSequence[Any], b: SupportsIndex, /) -> None: ...
@overload
def delitem(a: MutableSequence[Any], b: slice, /) -> None: ...
@overload
def delitem(a: MutableMapping[_K, Any], b: _K, /) -> None: ...
@overload
def getitem(a: Sequence[_T], b: slice, /) -> Sequence[_T]: ...
@overload
def getitem(a: SupportsGetItem[_K, _V], b: _K, /) -> _V: ...
def indexOf(a: Iterable[_T], b: _T, /) -> int: ...
@overload
def setitem(a: MutableSequence[_T], b: SupportsIndex, c: _T, /) -> None: ...
@overload
def setitem(a: MutableSequence[_T], b: slice, c: Sequence[_T], /) -> None: ...
@overload
def setitem(a: MutableMapping[_K, _V], b: _K, c: _V, /) -> None: ...
def length_hint(obj: object, default: int = 0, /) -> int: ...
def iadd(a: Any, b: Any, /) -> Any: ...
def iand(a: Any, b: Any, /) -> Any: ...
def iconcat(a: Any, b: Any, /) -> Any: ...
def ifloordiv(a: Any, b: Any, /) -> Any: ...
def ilshift(a: Any, b: Any, /) -> Any: ...
def imod(a: Any, b: Any, /) -> Any: ...
def imul(a: Any, b: Any, /) -> Any: ...
def imatmul(a: Any, b: Any, /) -> Any: ...
def ior(a: Any, b: Any, /) -> Any: ...
def ipow(a: Any, b: Any, /) -> Any: ...
def irshift(a: Any, b: Any, /) -> Any: ...
def isub(a: Any, b: Any, /) -> Any: ...
def itruediv(a: Any, b: Any, /) -> Any: ...
def ixor(a: Any, b: Any, /) -> Any: ...
if sys.version_info >= (3, 11):
def call(obj: Callable[_P, _R], /, *args: _P.args, **kwargs: _P.kwargs) -> _R: ...
def _compare_digest(a: AnyStr, b: AnyStr, /) -> bool: ...
if sys.version_info >= (3, 14):
def is_none(a: object, /) -> TypeIs[None]: ...
def is_not_none(a: _T | None, /) -> TypeIs[_T]: ...

View File

@@ -1,34 +0,0 @@
from collections.abc import Iterable, Sequence
from typing import Final, TypeVar
_T = TypeVar("_T")
_K = TypeVar("_K")
_V = TypeVar("_V")
__all__ = ["compiler_fixup", "customize_config_vars", "customize_compiler", "get_platform_osx"]
_UNIVERSAL_CONFIG_VARS: Final[tuple[str, ...]] # undocumented
_COMPILER_CONFIG_VARS: Final[tuple[str, ...]] # undocumented
_INITPRE: Final[str] # undocumented
def _find_executable(executable: str, path: str | None = None) -> str | None: ... # undocumented
def _read_output(commandstring: str, capture_stderr: bool = False) -> str | None: ... # undocumented
def _find_build_tool(toolname: str) -> str: ... # undocumented
_SYSTEM_VERSION: Final[str | None] # undocumented
def _get_system_version() -> str: ... # undocumented
def _remove_original_values(_config_vars: dict[str, str]) -> None: ... # undocumented
def _save_modified_value(_config_vars: dict[str, str], cv: str, newvalue: str) -> None: ... # undocumented
def _supports_universal_builds() -> bool: ... # undocumented
def _find_appropriate_compiler(_config_vars: dict[str, str]) -> dict[str, str]: ... # undocumented
def _remove_universal_flags(_config_vars: dict[str, str]) -> dict[str, str]: ... # undocumented
def _remove_unsupported_archs(_config_vars: dict[str, str]) -> dict[str, str]: ... # undocumented
def _override_all_archs(_config_vars: dict[str, str]) -> dict[str, str]: ... # undocumented
def _check_for_unavailable_sdk(_config_vars: dict[str, str]) -> dict[str, str]: ... # undocumented
def compiler_fixup(compiler_so: Iterable[str], cc_args: Sequence[str]) -> list[str]: ...
def customize_config_vars(_config_vars: dict[str, str]) -> dict[str, str]: ...
def customize_compiler(_config_vars: dict[str, str]) -> dict[str, str]: ...
def get_platform_osx(
_config_vars: dict[str, str], osname: _T, release: _K, machine: _V
) -> tuple[str | _T, str | _K, str | _V]: ...

View File

@@ -1,104 +0,0 @@
from _typeshed import ReadableBuffer, SupportsWrite
from collections.abc import Callable, Iterable, Iterator, Mapping
from pickle import PickleBuffer as PickleBuffer
from typing import Any, Protocol, type_check_only
from typing_extensions import TypeAlias
class _ReadableFileobj(Protocol):
def read(self, n: int, /) -> bytes: ...
def readline(self) -> bytes: ...
_BufferCallback: TypeAlias = Callable[[PickleBuffer], Any] | None
_ReducedType: TypeAlias = (
str
| tuple[Callable[..., Any], tuple[Any, ...]]
| tuple[Callable[..., Any], tuple[Any, ...], Any]
| tuple[Callable[..., Any], tuple[Any, ...], Any, Iterator[Any] | None]
| tuple[Callable[..., Any], tuple[Any, ...], Any, Iterator[Any] | None, Iterator[Any] | None]
)
def dump(
obj: Any,
file: SupportsWrite[bytes],
protocol: int | None = None,
*,
fix_imports: bool = True,
buffer_callback: _BufferCallback = None,
) -> None: ...
def dumps(
obj: Any, protocol: int | None = None, *, fix_imports: bool = True, buffer_callback: _BufferCallback = None
) -> bytes: ...
def load(
file: _ReadableFileobj,
*,
fix_imports: bool = True,
encoding: str = "ASCII",
errors: str = "strict",
buffers: Iterable[Any] | None = (),
) -> Any: ...
def loads(
data: ReadableBuffer,
/,
*,
fix_imports: bool = True,
encoding: str = "ASCII",
errors: str = "strict",
buffers: Iterable[Any] | None = (),
) -> Any: ...
class PickleError(Exception): ...
class PicklingError(PickleError): ...
class UnpicklingError(PickleError): ...
@type_check_only
class PicklerMemoProxy:
def clear(self, /) -> None: ...
def copy(self, /) -> dict[int, tuple[int, Any]]: ...
class Pickler:
fast: bool
dispatch_table: Mapping[type, Callable[[Any], _ReducedType]]
reducer_override: Callable[[Any], Any]
bin: bool # undocumented
def __init__(
self,
file: SupportsWrite[bytes],
protocol: int | None = None,
fix_imports: bool = True,
buffer_callback: _BufferCallback = None,
) -> None: ...
@property
def memo(self) -> PicklerMemoProxy: ...
@memo.setter
def memo(self, value: PicklerMemoProxy | dict[int, tuple[int, Any]]) -> None: ...
def dump(self, obj: Any, /) -> None: ...
def clear_memo(self) -> None: ...
# this method has no default implementation for Python < 3.13
def persistent_id(self, obj: Any, /) -> Any: ...
@type_check_only
class UnpicklerMemoProxy:
def clear(self, /) -> None: ...
def copy(self, /) -> dict[int, tuple[int, Any]]: ...
class Unpickler:
def __init__(
self,
file: _ReadableFileobj,
*,
fix_imports: bool = True,
encoding: str = "ASCII",
errors: str = "strict",
buffers: Iterable[Any] | None = (),
) -> None: ...
@property
def memo(self) -> UnpicklerMemoProxy: ...
@memo.setter
def memo(self, value: UnpicklerMemoProxy | dict[int, tuple[int, Any]]) -> None: ...
def load(self) -> Any: ...
def find_class(self, module_name: str, global_name: str, /) -> Any: ...
# this method has no default implementation for Python < 3.13
def persistent_load(self, pid: Any, /) -> Any: ...

View File

@@ -1,32 +0,0 @@
import sys
from _typeshed import StrOrBytesPath
from collections.abc import Callable, Sequence
from typing import SupportsIndex
if sys.platform != "win32":
def fork_exec(
args: Sequence[StrOrBytesPath] | None,
executable_list: Sequence[bytes],
close_fds: bool,
pass_fds: tuple[int, ...],
cwd: str,
env: Sequence[bytes] | None,
p2cread: int,
p2cwrite: int,
c2pread: int,
c2pwrite: int,
errread: int,
errwrite: int,
errpipe_read: int,
errpipe_write: int,
restore_signals: int,
call_setsid: int,
pgid_to_set: int,
gid: SupportsIndex | None,
extra_groups: list[int] | None,
uid: SupportsIndex | None,
child_umask: int,
preexec_fn: Callable[[], None],
allow_vfork: bool,
/,
) -> int: ...

View File

@@ -1,14 +0,0 @@
import _typeshed
from typing import Any, NewType, TypeVar
_T = TypeVar("_T")
_CacheToken = NewType("_CacheToken", int)
def get_cache_token() -> _CacheToken: ...
class ABCMeta(type):
def __new__(
mcls: type[_typeshed.Self], name: str, bases: tuple[type[Any], ...], namespace: dict[str, Any], /
) -> _typeshed.Self: ...
def register(cls, subclass: type[_T]) -> type[_T]: ...

View File

@@ -1,43 +0,0 @@
# This is a slight lie, the implementations aren't exactly identical
# However, in all likelihood, the differences are inconsequential
from _decimal import *
__all__ = [
"Decimal",
"Context",
"DecimalTuple",
"DefaultContext",
"BasicContext",
"ExtendedContext",
"DecimalException",
"Clamped",
"InvalidOperation",
"DivisionByZero",
"Inexact",
"Rounded",
"Subnormal",
"Overflow",
"Underflow",
"FloatOperation",
"DivisionImpossible",
"InvalidContext",
"ConversionSyntax",
"DivisionUndefined",
"ROUND_DOWN",
"ROUND_HALF_UP",
"ROUND_HALF_EVEN",
"ROUND_CEILING",
"ROUND_FLOOR",
"ROUND_UP",
"ROUND_HALF_DOWN",
"ROUND_05UP",
"setcontext",
"getcontext",
"localcontext",
"MAX_PREC",
"MAX_EMAX",
"MIN_EMIN",
"MIN_ETINY",
"HAVE_THREADS",
"HAVE_CONTEXTVAR",
]

View File

@@ -1,16 +0,0 @@
from types import GenericAlias
from typing import Any, Generic, TypeVar
_T = TypeVar("_T")
class Empty(Exception): ...
class SimpleQueue(Generic[_T]):
def __init__(self) -> None: ...
def empty(self) -> bool: ...
def get(self, block: bool = True, timeout: float | None = None) -> _T: ...
def get_nowait(self) -> _T: ...
def put(self, item: _T, block: bool = True, timeout: float | None = None) -> None: ...
def put_nowait(self, item: _T) -> None: ...
def qsize(self) -> int: ...
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...

View File

@@ -1,12 +0,0 @@
from typing_extensions import TypeAlias
# Actually Tuple[(int,) * 625]
_State: TypeAlias = tuple[int, ...]
class Random:
def __init__(self, seed: object = ...) -> None: ...
def seed(self, n: object = None, /) -> None: ...
def getstate(self) -> _State: ...
def setstate(self, state: _State, /) -> None: ...
def random(self) -> float: ...
def getrandbits(self, k: int, /) -> int: ...

View File

@@ -1,17 +0,0 @@
import sys
from collections.abc import Iterable
from typing import ClassVar, Literal, NoReturn
class Quitter:
name: str
eof: str
def __init__(self, name: str, eof: str) -> None: ...
def __call__(self, code: sys._ExitCode = None) -> NoReturn: ...
class _Printer:
MAXLINES: ClassVar[Literal[23]]
def __init__(self, name: str, data: str, files: Iterable[str] = (), dirs: Iterable[str] = ()) -> None: ...
def __call__(self) -> None: ...
class _Helper:
def __call__(self, request: object = ...) -> None: ...

View File

@@ -1,834 +0,0 @@
import sys
from _typeshed import ReadableBuffer, WriteableBuffer
from collections.abc import Iterable
from socket import error as error, gaierror as gaierror, herror as herror, timeout as timeout
from typing import Any, SupportsIndex, overload
from typing_extensions import CapsuleType, TypeAlias
_CMSG: TypeAlias = tuple[int, int, bytes]
_CMSGArg: TypeAlias = tuple[int, int, ReadableBuffer]
# Addresses can be either tuples of varying lengths (AF_INET, AF_INET6,
# AF_NETLINK, AF_TIPC) or strings/buffers (AF_UNIX).
# See getsockaddrarg() in socketmodule.c.
_Address: TypeAlias = tuple[Any, ...] | str | ReadableBuffer
_RetAddress: TypeAlias = Any
# ===== Constants =====
# This matches the order in the CPython documentation
# https://docs.python.org/3/library/socket.html#constants
if sys.platform != "win32":
AF_UNIX: int
AF_INET: int
AF_INET6: int
AF_UNSPEC: int
SOCK_STREAM: int
SOCK_DGRAM: int
SOCK_RAW: int
SOCK_RDM: int
SOCK_SEQPACKET: int
if sys.platform == "linux":
# Availability: Linux >= 2.6.27
SOCK_CLOEXEC: int
SOCK_NONBLOCK: int
# --------------------
# Many constants of these forms, documented in the Unix documentation on
# sockets and/or the IP protocol, are also defined in the socket module.
# SO_*
# socket.SOMAXCONN
# MSG_*
# SOL_*
# SCM_*
# IPPROTO_*
# IPPORT_*
# INADDR_*
# IP_*
# IPV6_*
# EAI_*
# AI_*
# NI_*
# TCP_*
# --------------------
SO_ACCEPTCONN: int
SO_BROADCAST: int
SO_DEBUG: int
SO_DONTROUTE: int
SO_ERROR: int
SO_KEEPALIVE: int
SO_LINGER: int
SO_OOBINLINE: int
SO_RCVBUF: int
SO_RCVLOWAT: int
SO_RCVTIMEO: int
SO_REUSEADDR: int
SO_SNDBUF: int
SO_SNDLOWAT: int
SO_SNDTIMEO: int
SO_TYPE: int
if sys.platform != "linux":
SO_USELOOPBACK: int
if sys.platform == "win32":
SO_EXCLUSIVEADDRUSE: int
if sys.platform != "win32":
SO_REUSEPORT: int
if sys.platform != "darwin" or sys.version_info >= (3, 13):
SO_BINDTODEVICE: int
if sys.platform != "win32" and sys.platform != "darwin":
SO_DOMAIN: int
SO_MARK: int
SO_PASSCRED: int
SO_PASSSEC: int
SO_PEERCRED: int
SO_PEERSEC: int
SO_PRIORITY: int
SO_PROTOCOL: int
if sys.platform != "win32" and sys.platform != "darwin" and sys.platform != "linux":
SO_SETFIB: int
if sys.platform == "linux" and sys.version_info >= (3, 13):
SO_BINDTOIFINDEX: int
SOMAXCONN: int
MSG_CTRUNC: int
MSG_DONTROUTE: int
MSG_OOB: int
MSG_PEEK: int
MSG_TRUNC: int
MSG_WAITALL: int
if sys.platform != "win32":
MSG_DONTWAIT: int
MSG_EOR: int
MSG_NOSIGNAL: int # Sometimes this exists on darwin, sometimes not
if sys.platform != "darwin":
MSG_ERRQUEUE: int
if sys.platform == "win32":
MSG_BCAST: int
MSG_MCAST: int
if sys.platform != "win32" and sys.platform != "darwin":
MSG_CMSG_CLOEXEC: int
MSG_CONFIRM: int
MSG_FASTOPEN: int
MSG_MORE: int
if sys.platform != "win32" and sys.platform != "linux":
MSG_EOF: int
if sys.platform != "win32" and sys.platform != "linux" and sys.platform != "darwin":
MSG_NOTIFICATION: int
MSG_BTAG: int # Not FreeBSD either
MSG_ETAG: int # Not FreeBSD either
SOL_IP: int
SOL_SOCKET: int
SOL_TCP: int
SOL_UDP: int
if sys.platform != "win32" and sys.platform != "darwin":
# Defined in socket.h for Linux, but these aren't always present for
# some reason.
SOL_ATALK: int
SOL_AX25: int
SOL_HCI: int
SOL_IPX: int
SOL_NETROM: int
SOL_ROSE: int
if sys.platform != "win32":
SCM_RIGHTS: int
if sys.platform != "win32" and sys.platform != "darwin":
SCM_CREDENTIALS: int
if sys.platform != "win32" and sys.platform != "linux":
SCM_CREDS: int
IPPROTO_ICMP: int
IPPROTO_IP: int
IPPROTO_RAW: int
IPPROTO_TCP: int
IPPROTO_UDP: int
IPPROTO_AH: int
IPPROTO_DSTOPTS: int
IPPROTO_EGP: int
IPPROTO_ESP: int
IPPROTO_FRAGMENT: int
IPPROTO_HOPOPTS: int
IPPROTO_ICMPV6: int
IPPROTO_IDP: int
IPPROTO_IGMP: int
IPPROTO_IPV6: int
IPPROTO_NONE: int
IPPROTO_PIM: int
IPPROTO_PUP: int
IPPROTO_ROUTING: int
IPPROTO_SCTP: int
if sys.platform != "linux":
IPPROTO_GGP: int
IPPROTO_IPV4: int
IPPROTO_MAX: int
IPPROTO_ND: int
if sys.platform == "win32":
IPPROTO_CBT: int
IPPROTO_ICLFXBM: int
IPPROTO_IGP: int
IPPROTO_L2TP: int
IPPROTO_PGM: int
IPPROTO_RDP: int
IPPROTO_ST: int
if sys.platform != "win32":
IPPROTO_GRE: int
IPPROTO_IPIP: int
IPPROTO_RSVP: int
IPPROTO_TP: int
if sys.platform != "win32" and sys.platform != "linux":
IPPROTO_EON: int
IPPROTO_HELLO: int
IPPROTO_IPCOMP: int
IPPROTO_XTP: int
if sys.platform != "win32" and sys.platform != "darwin" and sys.platform != "linux":
IPPROTO_BIP: int # Not FreeBSD either
IPPROTO_MOBILE: int # Not FreeBSD either
IPPROTO_VRRP: int # Not FreeBSD either
if sys.platform == "linux":
# Availability: Linux >= 2.6.20, FreeBSD >= 10.1
IPPROTO_UDPLITE: int
if sys.version_info >= (3, 10) and sys.platform == "linux":
IPPROTO_MPTCP: int
IPPORT_RESERVED: int
IPPORT_USERRESERVED: int
INADDR_ALLHOSTS_GROUP: int
INADDR_ANY: int
INADDR_BROADCAST: int
INADDR_LOOPBACK: int
INADDR_MAX_LOCAL_GROUP: int
INADDR_NONE: int
INADDR_UNSPEC_GROUP: int
IP_ADD_MEMBERSHIP: int
IP_DROP_MEMBERSHIP: int
IP_HDRINCL: int
IP_MULTICAST_IF: int
IP_MULTICAST_LOOP: int
IP_MULTICAST_TTL: int
IP_OPTIONS: int
if sys.platform != "linux":
IP_RECVDSTADDR: int
if sys.version_info >= (3, 10):
IP_RECVTOS: int
IP_TOS: int
IP_TTL: int
if sys.platform != "win32":
IP_DEFAULT_MULTICAST_LOOP: int
IP_DEFAULT_MULTICAST_TTL: int
IP_MAX_MEMBERSHIPS: int
IP_RECVOPTS: int
IP_RECVRETOPTS: int
IP_RETOPTS: int
if sys.platform != "win32" and sys.platform != "darwin":
IP_TRANSPARENT: int
if sys.platform != "win32" and sys.platform != "darwin" and sys.version_info >= (3, 11):
IP_BIND_ADDRESS_NO_PORT: int
if sys.version_info >= (3, 12):
IP_ADD_SOURCE_MEMBERSHIP: int
IP_BLOCK_SOURCE: int
IP_DROP_SOURCE_MEMBERSHIP: int
IP_PKTINFO: int
IP_UNBLOCK_SOURCE: int
IPV6_CHECKSUM: int
IPV6_JOIN_GROUP: int
IPV6_LEAVE_GROUP: int
IPV6_MULTICAST_HOPS: int
IPV6_MULTICAST_IF: int
IPV6_MULTICAST_LOOP: int
IPV6_RECVTCLASS: int
IPV6_TCLASS: int
IPV6_UNICAST_HOPS: int
IPV6_V6ONLY: int
IPV6_DONTFRAG: int
IPV6_HOPLIMIT: int
IPV6_HOPOPTS: int
IPV6_PKTINFO: int
IPV6_RECVRTHDR: int
IPV6_RTHDR: int
if sys.platform != "win32":
IPV6_RTHDR_TYPE_0: int
IPV6_DSTOPTS: int
IPV6_NEXTHOP: int
IPV6_PATHMTU: int
IPV6_RECVDSTOPTS: int
IPV6_RECVHOPLIMIT: int
IPV6_RECVHOPOPTS: int
IPV6_RECVPATHMTU: int
IPV6_RECVPKTINFO: int
IPV6_RTHDRDSTOPTS: int
if sys.platform != "win32" and sys.platform != "linux":
IPV6_USE_MIN_MTU: int
EAI_AGAIN: int
EAI_BADFLAGS: int
EAI_FAIL: int
EAI_FAMILY: int
EAI_MEMORY: int
EAI_NODATA: int
EAI_NONAME: int
EAI_SERVICE: int
EAI_SOCKTYPE: int
if sys.platform != "win32":
EAI_ADDRFAMILY: int
EAI_OVERFLOW: int
EAI_SYSTEM: int
if sys.platform != "win32" and sys.platform != "linux":
EAI_BADHINTS: int
EAI_MAX: int
EAI_PROTOCOL: int
AI_ADDRCONFIG: int
AI_ALL: int
AI_CANONNAME: int
AI_NUMERICHOST: int
AI_NUMERICSERV: int
AI_PASSIVE: int
AI_V4MAPPED: int
if sys.platform != "win32" and sys.platform != "linux":
AI_DEFAULT: int
AI_MASK: int
AI_V4MAPPED_CFG: int
NI_DGRAM: int
NI_MAXHOST: int
NI_MAXSERV: int
NI_NAMEREQD: int
NI_NOFQDN: int
NI_NUMERICHOST: int
NI_NUMERICSERV: int
if sys.platform == "linux" and sys.version_info >= (3, 13):
NI_IDN: int
TCP_FASTOPEN: int
TCP_KEEPCNT: int
TCP_KEEPINTVL: int
TCP_MAXSEG: int
TCP_NODELAY: int
if sys.platform != "win32":
TCP_NOTSENT_LOWAT: int
if sys.platform != "darwin":
TCP_KEEPIDLE: int
if sys.version_info >= (3, 10) and sys.platform == "darwin":
TCP_KEEPALIVE: int
if sys.version_info >= (3, 11) and sys.platform == "darwin":
TCP_CONNECTION_INFO: int
if sys.platform != "win32" and sys.platform != "darwin":
TCP_CONGESTION: int
TCP_CORK: int
TCP_DEFER_ACCEPT: int
TCP_INFO: int
TCP_LINGER2: int
TCP_QUICKACK: int
TCP_SYNCNT: int
TCP_USER_TIMEOUT: int
TCP_WINDOW_CLAMP: int
if sys.platform == "linux" and sys.version_info >= (3, 12):
TCP_CC_INFO: int
TCP_FASTOPEN_CONNECT: int
TCP_FASTOPEN_KEY: int
TCP_FASTOPEN_NO_COOKIE: int
TCP_INQ: int
TCP_MD5SIG: int
TCP_MD5SIG_EXT: int
TCP_QUEUE_SEQ: int
TCP_REPAIR: int
TCP_REPAIR_OPTIONS: int
TCP_REPAIR_QUEUE: int
TCP_REPAIR_WINDOW: int
TCP_SAVED_SYN: int
TCP_SAVE_SYN: int
TCP_THIN_DUPACK: int
TCP_THIN_LINEAR_TIMEOUTS: int
TCP_TIMESTAMP: int
TCP_TX_DELAY: int
TCP_ULP: int
TCP_ZEROCOPY_RECEIVE: int
# --------------------
# Specifically documented constants
# --------------------
if sys.platform == "linux":
# Availability: Linux >= 2.6.25, NetBSD >= 8
AF_CAN: int
PF_CAN: int
SOL_CAN_BASE: int
SOL_CAN_RAW: int
CAN_EFF_FLAG: int
CAN_EFF_MASK: int
CAN_ERR_FLAG: int
CAN_ERR_MASK: int
CAN_RAW: int
CAN_RAW_FILTER: int
CAN_RAW_LOOPBACK: int
CAN_RAW_RECV_OWN_MSGS: int
CAN_RTR_FLAG: int
CAN_SFF_MASK: int
if sys.version_info < (3, 11):
CAN_RAW_ERR_FILTER: int
if sys.platform == "linux":
# Availability: Linux >= 2.6.25
CAN_BCM: int
CAN_BCM_TX_SETUP: int
CAN_BCM_TX_DELETE: int
CAN_BCM_TX_READ: int
CAN_BCM_TX_SEND: int
CAN_BCM_RX_SETUP: int
CAN_BCM_RX_DELETE: int
CAN_BCM_RX_READ: int
CAN_BCM_TX_STATUS: int
CAN_BCM_TX_EXPIRED: int
CAN_BCM_RX_STATUS: int
CAN_BCM_RX_TIMEOUT: int
CAN_BCM_RX_CHANGED: int
CAN_BCM_SETTIMER: int
CAN_BCM_STARTTIMER: int
CAN_BCM_TX_COUNTEVT: int
CAN_BCM_TX_ANNOUNCE: int
CAN_BCM_TX_CP_CAN_ID: int
CAN_BCM_RX_FILTER_ID: int
CAN_BCM_RX_CHECK_DLC: int
CAN_BCM_RX_NO_AUTOTIMER: int
CAN_BCM_RX_ANNOUNCE_RESUME: int
CAN_BCM_TX_RESET_MULTI_IDX: int
CAN_BCM_RX_RTR_FRAME: int
CAN_BCM_CAN_FD_FRAME: int
if sys.platform == "linux":
# Availability: Linux >= 3.6
CAN_RAW_FD_FRAMES: int
# Availability: Linux >= 4.1
CAN_RAW_JOIN_FILTERS: int
# Availability: Linux >= 2.6.25
CAN_ISOTP: int
# Availability: Linux >= 5.4
CAN_J1939: int
J1939_MAX_UNICAST_ADDR: int
J1939_IDLE_ADDR: int
J1939_NO_ADDR: int
J1939_NO_NAME: int
J1939_PGN_REQUEST: int
J1939_PGN_ADDRESS_CLAIMED: int
J1939_PGN_ADDRESS_COMMANDED: int
J1939_PGN_PDU1_MAX: int
J1939_PGN_MAX: int
J1939_NO_PGN: int
SO_J1939_FILTER: int
SO_J1939_PROMISC: int
SO_J1939_SEND_PRIO: int
SO_J1939_ERRQUEUE: int
SCM_J1939_DEST_ADDR: int
SCM_J1939_DEST_NAME: int
SCM_J1939_PRIO: int
SCM_J1939_ERRQUEUE: int
J1939_NLA_PAD: int
J1939_NLA_BYTES_ACKED: int
J1939_EE_INFO_NONE: int
J1939_EE_INFO_TX_ABORT: int
J1939_FILTER_MAX: int
if sys.version_info >= (3, 12) and sys.platform != "linux" and sys.platform != "win32" and sys.platform != "darwin":
# Availability: FreeBSD >= 14.0
AF_DIVERT: int
PF_DIVERT: int
if sys.platform == "linux":
# Availability: Linux >= 2.2
AF_PACKET: int
PF_PACKET: int
PACKET_BROADCAST: int
PACKET_FASTROUTE: int
PACKET_HOST: int
PACKET_LOOPBACK: int
PACKET_MULTICAST: int
PACKET_OTHERHOST: int
PACKET_OUTGOING: int
if sys.version_info >= (3, 12) and sys.platform == "linux":
ETH_P_ALL: int
if sys.platform == "linux":
# Availability: Linux >= 2.6.30
AF_RDS: int
PF_RDS: int
SOL_RDS: int
# These are present in include/linux/rds.h but don't always show up
# here.
RDS_CANCEL_SENT_TO: int
RDS_CMSG_RDMA_ARGS: int
RDS_CMSG_RDMA_DEST: int
RDS_CMSG_RDMA_MAP: int
RDS_CMSG_RDMA_STATUS: int
RDS_CONG_MONITOR: int
RDS_FREE_MR: int
RDS_GET_MR: int
RDS_GET_MR_FOR_DEST: int
RDS_RDMA_DONTWAIT: int
RDS_RDMA_FENCE: int
RDS_RDMA_INVALIDATE: int
RDS_RDMA_NOTIFY_ME: int
RDS_RDMA_READWRITE: int
RDS_RDMA_SILENT: int
RDS_RDMA_USE_ONCE: int
RDS_RECVERR: int
# This is supported by CPython but doesn't seem to be a real thing.
# The closest existing constant in rds.h is RDS_CMSG_CONG_UPDATE
# RDS_CMSG_RDMA_UPDATE: int
if sys.platform == "win32":
SIO_RCVALL: int
SIO_KEEPALIVE_VALS: int
SIO_LOOPBACK_FAST_PATH: int
RCVALL_MAX: int
RCVALL_OFF: int
RCVALL_ON: int
RCVALL_SOCKETLEVELONLY: int
if sys.platform == "linux":
AF_TIPC: int
SOL_TIPC: int
TIPC_ADDR_ID: int
TIPC_ADDR_NAME: int
TIPC_ADDR_NAMESEQ: int
TIPC_CFG_SRV: int
TIPC_CLUSTER_SCOPE: int
TIPC_CONN_TIMEOUT: int
TIPC_CRITICAL_IMPORTANCE: int
TIPC_DEST_DROPPABLE: int
TIPC_HIGH_IMPORTANCE: int
TIPC_IMPORTANCE: int
TIPC_LOW_IMPORTANCE: int
TIPC_MEDIUM_IMPORTANCE: int
TIPC_NODE_SCOPE: int
TIPC_PUBLISHED: int
TIPC_SRC_DROPPABLE: int
TIPC_SUBSCR_TIMEOUT: int
TIPC_SUB_CANCEL: int
TIPC_SUB_PORTS: int
TIPC_SUB_SERVICE: int
TIPC_TOP_SRV: int
TIPC_WAIT_FOREVER: int
TIPC_WITHDRAWN: int
TIPC_ZONE_SCOPE: int
if sys.platform == "linux":
# Availability: Linux >= 2.6.38
AF_ALG: int
SOL_ALG: int
ALG_OP_DECRYPT: int
ALG_OP_ENCRYPT: int
ALG_OP_SIGN: int
ALG_OP_VERIFY: int
ALG_SET_AEAD_ASSOCLEN: int
ALG_SET_AEAD_AUTHSIZE: int
ALG_SET_IV: int
ALG_SET_KEY: int
ALG_SET_OP: int
ALG_SET_PUBKEY: int
if sys.platform == "linux":
# Availability: Linux >= 4.8 (or maybe 3.9, CPython docs are confusing)
AF_VSOCK: int
IOCTL_VM_SOCKETS_GET_LOCAL_CID: int
VMADDR_CID_ANY: int
VMADDR_CID_HOST: int
VMADDR_PORT_ANY: int
SO_VM_SOCKETS_BUFFER_MAX_SIZE: int
SO_VM_SOCKETS_BUFFER_SIZE: int
SO_VM_SOCKETS_BUFFER_MIN_SIZE: int
VM_SOCKETS_INVALID_VERSION: int # undocumented
# Documented as only available on BSD, macOS, but empirically sometimes
# available on Windows
if sys.platform != "linux":
AF_LINK: int
has_ipv6: bool
if sys.platform != "darwin" and sys.platform != "linux":
BDADDR_ANY: str
BDADDR_LOCAL: str
if sys.platform != "win32" and sys.platform != "darwin" and sys.platform != "linux":
HCI_FILTER: int # not in NetBSD or DragonFlyBSD
HCI_TIME_STAMP: int # not in FreeBSD, NetBSD, or DragonFlyBSD
HCI_DATA_DIR: int # not in FreeBSD, NetBSD, or DragonFlyBSD
if sys.platform == "linux":
AF_QIPCRTR: int # Availability: Linux >= 4.7
if sys.version_info >= (3, 11) and sys.platform != "linux" and sys.platform != "win32" and sys.platform != "darwin":
# FreeBSD
SCM_CREDS2: int
LOCAL_CREDS: int
LOCAL_CREDS_PERSISTENT: int
if sys.version_info >= (3, 11) and sys.platform == "linux":
SO_INCOMING_CPU: int # Availability: Linux >= 3.9
if sys.version_info >= (3, 12) and sys.platform == "win32":
# Availability: Windows
AF_HYPERV: int
HV_PROTOCOL_RAW: int
HVSOCKET_CONNECT_TIMEOUT: int
HVSOCKET_CONNECT_TIMEOUT_MAX: int
HVSOCKET_CONNECTED_SUSPEND: int
HVSOCKET_ADDRESS_FLAG_PASSTHRU: int
HV_GUID_ZERO: str
HV_GUID_WILDCARD: str
HV_GUID_BROADCAST: str
HV_GUID_CHILDREN: str
HV_GUID_LOOPBACK: str
HV_GUID_PARENT: str
if sys.version_info >= (3, 12):
if sys.platform != "win32":
# Availability: Linux, FreeBSD, macOS
ETHERTYPE_ARP: int
ETHERTYPE_IP: int
ETHERTYPE_IPV6: int
ETHERTYPE_VLAN: int
# --------------------
# Semi-documented constants
# These are alluded to under the "Socket families" section in the docs
# https://docs.python.org/3/library/socket.html#socket-families
# --------------------
if sys.platform == "linux":
# Netlink is defined by Linux
AF_NETLINK: int
NETLINK_CRYPTO: int
NETLINK_DNRTMSG: int
NETLINK_FIREWALL: int
NETLINK_IP6_FW: int
NETLINK_NFLOG: int
NETLINK_ROUTE: int
NETLINK_USERSOCK: int
NETLINK_XFRM: int
# Technically still supported by CPython
# NETLINK_ARPD: int # linux 2.0 to 2.6.12 (EOL August 2005)
# NETLINK_ROUTE6: int # linux 2.2 to 2.6.12 (EOL August 2005)
# NETLINK_SKIP: int # linux 2.0 to 2.6.12 (EOL August 2005)
# NETLINK_TAPBASE: int # linux 2.2 to 2.6.12 (EOL August 2005)
# NETLINK_TCPDIAG: int # linux 2.6.0 to 2.6.13 (EOL December 2005)
# NETLINK_W1: int # linux 2.6.13 to 2.6.17 (EOL October 2006)
if sys.platform == "darwin":
PF_SYSTEM: int
SYSPROTO_CONTROL: int
if sys.platform != "darwin" and sys.platform != "linux":
AF_BLUETOOTH: int
if sys.platform != "win32" and sys.platform != "darwin" and sys.platform != "linux":
# Linux and some BSD support is explicit in the docs
# Windows and macOS do not support in practice
BTPROTO_HCI: int
BTPROTO_L2CAP: int
BTPROTO_SCO: int # not in FreeBSD
if sys.platform != "darwin" and sys.platform != "linux":
BTPROTO_RFCOMM: int
if sys.platform == "linux":
UDPLITE_RECV_CSCOV: int
UDPLITE_SEND_CSCOV: int
# --------------------
# Documented under socket.shutdown
# --------------------
SHUT_RD: int
SHUT_RDWR: int
SHUT_WR: int
# --------------------
# Undocumented constants
# --------------------
# Undocumented address families
AF_APPLETALK: int
AF_DECnet: int
AF_IPX: int
AF_SNA: int
if sys.platform != "win32":
AF_ROUTE: int
if sys.platform == "darwin":
AF_SYSTEM: int
if sys.platform != "darwin":
AF_IRDA: int
if sys.platform != "win32" and sys.platform != "darwin":
AF_ASH: int
AF_ATMPVC: int
AF_ATMSVC: int
AF_AX25: int
AF_BRIDGE: int
AF_ECONET: int
AF_KEY: int
AF_LLC: int
AF_NETBEUI: int
AF_NETROM: int
AF_PPPOX: int
AF_ROSE: int
AF_SECURITY: int
AF_WANPIPE: int
AF_X25: int
# Miscellaneous undocumented
if sys.platform != "win32" and sys.platform != "linux":
LOCAL_PEERCRED: int
if sys.platform != "win32" and sys.platform != "darwin":
# Defined in linux socket.h, but this isn't always present for
# some reason.
IPX_TYPE: int
# ===== Classes =====
class socket:
@property
def family(self) -> int: ...
@property
def type(self) -> int: ...
@property
def proto(self) -> int: ...
# F811: "Redefinition of unused `timeout`"
@property
def timeout(self) -> float | None: ... # noqa: F811
if sys.platform == "win32":
def __init__(
self, family: int = ..., type: int = ..., proto: int = ..., fileno: SupportsIndex | bytes | None = ...
) -> None: ...
else:
def __init__(self, family: int = ..., type: int = ..., proto: int = ..., fileno: SupportsIndex | None = ...) -> None: ...
def bind(self, address: _Address, /) -> None: ...
def close(self) -> None: ...
def connect(self, address: _Address, /) -> None: ...
def connect_ex(self, address: _Address, /) -> int: ...
def detach(self) -> int: ...
def fileno(self) -> int: ...
def getpeername(self) -> _RetAddress: ...
def getsockname(self) -> _RetAddress: ...
@overload
def getsockopt(self, level: int, optname: int, /) -> int: ...
@overload
def getsockopt(self, level: int, optname: int, buflen: int, /) -> bytes: ...
def getblocking(self) -> bool: ...
def gettimeout(self) -> float | None: ...
if sys.platform == "win32":
def ioctl(self, control: int, option: int | tuple[int, int, int] | bool, /) -> None: ...
def listen(self, backlog: int = ..., /) -> None: ...
def recv(self, bufsize: int, flags: int = ..., /) -> bytes: ...
def recvfrom(self, bufsize: int, flags: int = ..., /) -> tuple[bytes, _RetAddress]: ...
if sys.platform != "win32":
def recvmsg(self, bufsize: int, ancbufsize: int = ..., flags: int = ..., /) -> tuple[bytes, list[_CMSG], int, Any]: ...
def recvmsg_into(
self, buffers: Iterable[WriteableBuffer], ancbufsize: int = ..., flags: int = ..., /
) -> tuple[int, list[_CMSG], int, Any]: ...
def recvfrom_into(self, buffer: WriteableBuffer, nbytes: int = ..., flags: int = ...) -> tuple[int, _RetAddress]: ...
def recv_into(self, buffer: WriteableBuffer, nbytes: int = ..., flags: int = ...) -> int: ...
def send(self, data: ReadableBuffer, flags: int = ..., /) -> int: ...
def sendall(self, data: ReadableBuffer, flags: int = ..., /) -> None: ...
@overload
def sendto(self, data: ReadableBuffer, address: _Address, /) -> int: ...
@overload
def sendto(self, data: ReadableBuffer, flags: int, address: _Address, /) -> int: ...
if sys.platform != "win32":
def sendmsg(
self,
buffers: Iterable[ReadableBuffer],
ancdata: Iterable[_CMSGArg] = ...,
flags: int = ...,
address: _Address | None = ...,
/,
) -> int: ...
if sys.platform == "linux":
def sendmsg_afalg(
self, msg: Iterable[ReadableBuffer] = ..., *, op: int, iv: Any = ..., assoclen: int = ..., flags: int = ...
) -> int: ...
def setblocking(self, flag: bool, /) -> None: ...
def settimeout(self, value: float | None, /) -> None: ...
@overload
def setsockopt(self, level: int, optname: int, value: int | ReadableBuffer, /) -> None: ...
@overload
def setsockopt(self, level: int, optname: int, value: None, optlen: int, /) -> None: ...
if sys.platform == "win32":
def share(self, process_id: int, /) -> bytes: ...
def shutdown(self, how: int, /) -> None: ...
SocketType = socket
# ===== Functions =====
def close(fd: SupportsIndex, /) -> None: ...
def dup(fd: SupportsIndex, /) -> int: ...
# the 5th tuple item is an address
def getaddrinfo(
host: bytes | str | None,
port: bytes | str | int | None,
family: int = ...,
type: int = ...,
proto: int = ...,
flags: int = ...,
) -> list[tuple[int, int, int, str, tuple[str, int] | tuple[str, int, int, int] | tuple[int, bytes]]]: ...
def gethostbyname(hostname: str, /) -> str: ...
def gethostbyname_ex(hostname: str, /) -> tuple[str, list[str], list[str]]: ...
def gethostname() -> str: ...
def gethostbyaddr(ip_address: str, /) -> tuple[str, list[str], list[str]]: ...
def getnameinfo(sockaddr: tuple[str, int] | tuple[str, int, int, int] | tuple[int, bytes], flags: int, /) -> tuple[str, str]: ...
def getprotobyname(protocolname: str, /) -> int: ...
def getservbyname(servicename: str, protocolname: str = ..., /) -> int: ...
def getservbyport(port: int, protocolname: str = ..., /) -> str: ...
def ntohl(x: int, /) -> int: ... # param & ret val are 32-bit ints
def ntohs(x: int, /) -> int: ... # param & ret val are 16-bit ints
def htonl(x: int, /) -> int: ... # param & ret val are 32-bit ints
def htons(x: int, /) -> int: ... # param & ret val are 16-bit ints
def inet_aton(ip_addr: str, /) -> bytes: ... # ret val 4 bytes in length
def inet_ntoa(packed_ip: ReadableBuffer, /) -> str: ...
def inet_pton(address_family: int, ip_string: str, /) -> bytes: ...
def inet_ntop(address_family: int, packed_ip: ReadableBuffer, /) -> str: ...
def getdefaulttimeout() -> float | None: ...
# F811: "Redefinition of unused `timeout`"
def setdefaulttimeout(timeout: float | None, /) -> None: ... # noqa: F811
if sys.platform != "win32":
def sethostname(name: str, /) -> None: ...
def CMSG_LEN(length: int, /) -> int: ...
def CMSG_SPACE(length: int, /) -> int: ...
def socketpair(family: int = ..., type: int = ..., proto: int = ..., /) -> tuple[socket, socket]: ...
def if_nameindex() -> list[tuple[int, str]]: ...
def if_nametoindex(oname: str, /) -> int: ...
def if_indextoname(index: int, /) -> str: ...
CAPI: CapsuleType

View File

@@ -1,312 +0,0 @@
import sys
from _typeshed import ReadableBuffer, StrOrBytesPath
from collections.abc import Callable
from sqlite3 import (
Connection as Connection,
Cursor as Cursor,
DatabaseError as DatabaseError,
DataError as DataError,
Error as Error,
IntegrityError as IntegrityError,
InterfaceError as InterfaceError,
InternalError as InternalError,
NotSupportedError as NotSupportedError,
OperationalError as OperationalError,
PrepareProtocol as PrepareProtocol,
ProgrammingError as ProgrammingError,
Row as Row,
Warning as Warning,
)
from typing import Any, Final, Literal, TypeVar, overload
from typing_extensions import TypeAlias
if sys.version_info >= (3, 11):
from sqlite3 import Blob as Blob
_T = TypeVar("_T")
_ConnectionT = TypeVar("_ConnectionT", bound=Connection)
_SqliteData: TypeAlias = str | ReadableBuffer | int | float | None
_Adapter: TypeAlias = Callable[[_T], _SqliteData]
_Converter: TypeAlias = Callable[[bytes], Any]
PARSE_COLNAMES: Final[int]
PARSE_DECLTYPES: Final[int]
SQLITE_ALTER_TABLE: Final[int]
SQLITE_ANALYZE: Final[int]
SQLITE_ATTACH: Final[int]
SQLITE_CREATE_INDEX: Final[int]
SQLITE_CREATE_TABLE: Final[int]
SQLITE_CREATE_TEMP_INDEX: Final[int]
SQLITE_CREATE_TEMP_TABLE: Final[int]
SQLITE_CREATE_TEMP_TRIGGER: Final[int]
SQLITE_CREATE_TEMP_VIEW: Final[int]
SQLITE_CREATE_TRIGGER: Final[int]
SQLITE_CREATE_VIEW: Final[int]
SQLITE_CREATE_VTABLE: Final[int]
SQLITE_DELETE: Final[int]
SQLITE_DENY: Final[int]
SQLITE_DETACH: Final[int]
SQLITE_DONE: Final[int]
SQLITE_DROP_INDEX: Final[int]
SQLITE_DROP_TABLE: Final[int]
SQLITE_DROP_TEMP_INDEX: Final[int]
SQLITE_DROP_TEMP_TABLE: Final[int]
SQLITE_DROP_TEMP_TRIGGER: Final[int]
SQLITE_DROP_TEMP_VIEW: Final[int]
SQLITE_DROP_TRIGGER: Final[int]
SQLITE_DROP_VIEW: Final[int]
SQLITE_DROP_VTABLE: Final[int]
SQLITE_FUNCTION: Final[int]
SQLITE_IGNORE: Final[int]
SQLITE_INSERT: Final[int]
SQLITE_OK: Final[int]
SQLITE_PRAGMA: Final[int]
SQLITE_READ: Final[int]
SQLITE_RECURSIVE: Final[int]
SQLITE_REINDEX: Final[int]
SQLITE_SAVEPOINT: Final[int]
SQLITE_SELECT: Final[int]
SQLITE_TRANSACTION: Final[int]
SQLITE_UPDATE: Final[int]
adapters: dict[tuple[type[Any], type[Any]], _Adapter[Any]]
converters: dict[str, _Converter]
sqlite_version: str
if sys.version_info < (3, 12):
version: str
if sys.version_info >= (3, 12):
LEGACY_TRANSACTION_CONTROL: Final[int]
SQLITE_DBCONFIG_DEFENSIVE: Final[int]
SQLITE_DBCONFIG_DQS_DDL: Final[int]
SQLITE_DBCONFIG_DQS_DML: Final[int]
SQLITE_DBCONFIG_ENABLE_FKEY: Final[int]
SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER: Final[int]
SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION: Final[int]
SQLITE_DBCONFIG_ENABLE_QPSG: Final[int]
SQLITE_DBCONFIG_ENABLE_TRIGGER: Final[int]
SQLITE_DBCONFIG_ENABLE_VIEW: Final[int]
SQLITE_DBCONFIG_LEGACY_ALTER_TABLE: Final[int]
SQLITE_DBCONFIG_LEGACY_FILE_FORMAT: Final[int]
SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE: Final[int]
SQLITE_DBCONFIG_RESET_DATABASE: Final[int]
SQLITE_DBCONFIG_TRIGGER_EQP: Final[int]
SQLITE_DBCONFIG_TRUSTED_SCHEMA: Final[int]
SQLITE_DBCONFIG_WRITABLE_SCHEMA: Final[int]
if sys.version_info >= (3, 11):
SQLITE_ABORT: Final[int]
SQLITE_ABORT_ROLLBACK: Final[int]
SQLITE_AUTH: Final[int]
SQLITE_AUTH_USER: Final[int]
SQLITE_BUSY: Final[int]
SQLITE_BUSY_RECOVERY: Final[int]
SQLITE_BUSY_SNAPSHOT: Final[int]
SQLITE_BUSY_TIMEOUT: Final[int]
SQLITE_CANTOPEN: Final[int]
SQLITE_CANTOPEN_CONVPATH: Final[int]
SQLITE_CANTOPEN_DIRTYWAL: Final[int]
SQLITE_CANTOPEN_FULLPATH: Final[int]
SQLITE_CANTOPEN_ISDIR: Final[int]
SQLITE_CANTOPEN_NOTEMPDIR: Final[int]
SQLITE_CANTOPEN_SYMLINK: Final[int]
SQLITE_CONSTRAINT: Final[int]
SQLITE_CONSTRAINT_CHECK: Final[int]
SQLITE_CONSTRAINT_COMMITHOOK: Final[int]
SQLITE_CONSTRAINT_FOREIGNKEY: Final[int]
SQLITE_CONSTRAINT_FUNCTION: Final[int]
SQLITE_CONSTRAINT_NOTNULL: Final[int]
SQLITE_CONSTRAINT_PINNED: Final[int]
SQLITE_CONSTRAINT_PRIMARYKEY: Final[int]
SQLITE_CONSTRAINT_ROWID: Final[int]
SQLITE_CONSTRAINT_TRIGGER: Final[int]
SQLITE_CONSTRAINT_UNIQUE: Final[int]
SQLITE_CONSTRAINT_VTAB: Final[int]
SQLITE_CORRUPT: Final[int]
SQLITE_CORRUPT_INDEX: Final[int]
SQLITE_CORRUPT_SEQUENCE: Final[int]
SQLITE_CORRUPT_VTAB: Final[int]
SQLITE_EMPTY: Final[int]
SQLITE_ERROR: Final[int]
SQLITE_ERROR_MISSING_COLLSEQ: Final[int]
SQLITE_ERROR_RETRY: Final[int]
SQLITE_ERROR_SNAPSHOT: Final[int]
SQLITE_FORMAT: Final[int]
SQLITE_FULL: Final[int]
SQLITE_INTERNAL: Final[int]
SQLITE_INTERRUPT: Final[int]
SQLITE_IOERR: Final[int]
SQLITE_IOERR_ACCESS: Final[int]
SQLITE_IOERR_AUTH: Final[int]
SQLITE_IOERR_BEGIN_ATOMIC: Final[int]
SQLITE_IOERR_BLOCKED: Final[int]
SQLITE_IOERR_CHECKRESERVEDLOCK: Final[int]
SQLITE_IOERR_CLOSE: Final[int]
SQLITE_IOERR_COMMIT_ATOMIC: Final[int]
SQLITE_IOERR_CONVPATH: Final[int]
SQLITE_IOERR_CORRUPTFS: Final[int]
SQLITE_IOERR_DATA: Final[int]
SQLITE_IOERR_DELETE: Final[int]
SQLITE_IOERR_DELETE_NOENT: Final[int]
SQLITE_IOERR_DIR_CLOSE: Final[int]
SQLITE_IOERR_DIR_FSYNC: Final[int]
SQLITE_IOERR_FSTAT: Final[int]
SQLITE_IOERR_FSYNC: Final[int]
SQLITE_IOERR_GETTEMPPATH: Final[int]
SQLITE_IOERR_LOCK: Final[int]
SQLITE_IOERR_MMAP: Final[int]
SQLITE_IOERR_NOMEM: Final[int]
SQLITE_IOERR_RDLOCK: Final[int]
SQLITE_IOERR_READ: Final[int]
SQLITE_IOERR_ROLLBACK_ATOMIC: Final[int]
SQLITE_IOERR_SEEK: Final[int]
SQLITE_IOERR_SHMLOCK: Final[int]
SQLITE_IOERR_SHMMAP: Final[int]
SQLITE_IOERR_SHMOPEN: Final[int]
SQLITE_IOERR_SHMSIZE: Final[int]
SQLITE_IOERR_SHORT_READ: Final[int]
SQLITE_IOERR_TRUNCATE: Final[int]
SQLITE_IOERR_UNLOCK: Final[int]
SQLITE_IOERR_VNODE: Final[int]
SQLITE_IOERR_WRITE: Final[int]
SQLITE_LIMIT_ATTACHED: Final[int]
SQLITE_LIMIT_COLUMN: Final[int]
SQLITE_LIMIT_COMPOUND_SELECT: Final[int]
SQLITE_LIMIT_EXPR_DEPTH: Final[int]
SQLITE_LIMIT_FUNCTION_ARG: Final[int]
SQLITE_LIMIT_LENGTH: Final[int]
SQLITE_LIMIT_LIKE_PATTERN_LENGTH: Final[int]
SQLITE_LIMIT_SQL_LENGTH: Final[int]
SQLITE_LIMIT_TRIGGER_DEPTH: Final[int]
SQLITE_LIMIT_VARIABLE_NUMBER: Final[int]
SQLITE_LIMIT_VDBE_OP: Final[int]
SQLITE_LIMIT_WORKER_THREADS: Final[int]
SQLITE_LOCKED: Final[int]
SQLITE_LOCKED_SHAREDCACHE: Final[int]
SQLITE_LOCKED_VTAB: Final[int]
SQLITE_MISMATCH: Final[int]
SQLITE_MISUSE: Final[int]
SQLITE_NOLFS: Final[int]
SQLITE_NOMEM: Final[int]
SQLITE_NOTADB: Final[int]
SQLITE_NOTFOUND: Final[int]
SQLITE_NOTICE: Final[int]
SQLITE_NOTICE_RECOVER_ROLLBACK: Final[int]
SQLITE_NOTICE_RECOVER_WAL: Final[int]
SQLITE_OK_LOAD_PERMANENTLY: Final[int]
SQLITE_OK_SYMLINK: Final[int]
SQLITE_PERM: Final[int]
SQLITE_PROTOCOL: Final[int]
SQLITE_RANGE: Final[int]
SQLITE_READONLY: Final[int]
SQLITE_READONLY_CANTINIT: Final[int]
SQLITE_READONLY_CANTLOCK: Final[int]
SQLITE_READONLY_DBMOVED: Final[int]
SQLITE_READONLY_DIRECTORY: Final[int]
SQLITE_READONLY_RECOVERY: Final[int]
SQLITE_READONLY_ROLLBACK: Final[int]
SQLITE_ROW: Final[int]
SQLITE_SCHEMA: Final[int]
SQLITE_TOOBIG: Final[int]
SQLITE_WARNING: Final[int]
SQLITE_WARNING_AUTOINDEX: Final[int]
threadsafety: Final[int]
# Can take or return anything depending on what's in the registry.
@overload
def adapt(obj: Any, proto: Any, /) -> Any: ...
@overload
def adapt(obj: Any, proto: Any, alt: _T, /) -> Any | _T: ...
def complete_statement(statement: str) -> bool: ...
if sys.version_info >= (3, 12):
@overload
def connect(
database: StrOrBytesPath,
timeout: float = 5.0,
detect_types: int = 0,
isolation_level: Literal["DEFERRED", "EXCLUSIVE", "IMMEDIATE"] | None = "DEFERRED",
check_same_thread: bool = True,
cached_statements: int = 128,
uri: bool = False,
*,
autocommit: bool = ...,
) -> Connection: ...
@overload
def connect(
database: StrOrBytesPath,
timeout: float,
detect_types: int,
isolation_level: Literal["DEFERRED", "EXCLUSIVE", "IMMEDIATE"] | None,
check_same_thread: bool,
factory: type[_ConnectionT],
cached_statements: int = 128,
uri: bool = False,
*,
autocommit: bool = ...,
) -> _ConnectionT: ...
@overload
def connect(
database: StrOrBytesPath,
timeout: float = 5.0,
detect_types: int = 0,
isolation_level: Literal["DEFERRED", "EXCLUSIVE", "IMMEDIATE"] | None = "DEFERRED",
check_same_thread: bool = True,
*,
factory: type[_ConnectionT],
cached_statements: int = 128,
uri: bool = False,
autocommit: bool = ...,
) -> _ConnectionT: ...
else:
@overload
def connect(
database: StrOrBytesPath,
timeout: float = 5.0,
detect_types: int = 0,
isolation_level: Literal["DEFERRED", "EXCLUSIVE", "IMMEDIATE"] | None = "DEFERRED",
check_same_thread: bool = True,
cached_statements: int = 128,
uri: bool = False,
) -> Connection: ...
@overload
def connect(
database: StrOrBytesPath,
timeout: float,
detect_types: int,
isolation_level: Literal["DEFERRED", "EXCLUSIVE", "IMMEDIATE"] | None,
check_same_thread: bool,
factory: type[_ConnectionT],
cached_statements: int = 128,
uri: bool = False,
) -> _ConnectionT: ...
@overload
def connect(
database: StrOrBytesPath,
timeout: float = 5.0,
detect_types: int = 0,
isolation_level: Literal["DEFERRED", "EXCLUSIVE", "IMMEDIATE"] | None = "DEFERRED",
check_same_thread: bool = True,
*,
factory: type[_ConnectionT],
cached_statements: int = 128,
uri: bool = False,
) -> _ConnectionT: ...
def enable_callback_tracebacks(enable: bool, /) -> None: ...
if sys.version_info < (3, 12):
# takes a pos-or-keyword argument because there is a C wrapper
def enable_shared_cache(do_enable: int) -> None: ...
if sys.version_info >= (3, 10):
def register_adapter(type: type[_T], adapter: _Adapter[_T], /) -> None: ...
def register_converter(typename: str, converter: _Converter, /) -> None: ...
else:
def register_adapter(type: type[_T], caster: _Adapter[_T], /) -> None: ...
def register_converter(name: str, converter: _Converter, /) -> None: ...
if sys.version_info < (3, 10):
OptimizedUnicode = str

View File

@@ -1,291 +0,0 @@
import sys
from _typeshed import ReadableBuffer, StrOrBytesPath
from collections.abc import Callable
from ssl import (
SSLCertVerificationError as SSLCertVerificationError,
SSLContext,
SSLEOFError as SSLEOFError,
SSLError as SSLError,
SSLObject,
SSLSyscallError as SSLSyscallError,
SSLWantReadError as SSLWantReadError,
SSLWantWriteError as SSLWantWriteError,
SSLZeroReturnError as SSLZeroReturnError,
)
from typing import Any, ClassVar, Literal, TypedDict, final, overload
from typing_extensions import NotRequired, Self, TypeAlias
_PasswordType: TypeAlias = Callable[[], str | bytes | bytearray] | str | bytes | bytearray
_PCTRTT: TypeAlias = tuple[tuple[str, str], ...]
_PCTRTTT: TypeAlias = tuple[_PCTRTT, ...]
_PeerCertRetDictType: TypeAlias = dict[str, str | _PCTRTTT | _PCTRTT]
class _Cipher(TypedDict):
aead: bool
alg_bits: int
auth: str
description: str
digest: str | None
id: int
kea: str
name: str
protocol: str
strength_bits: int
symmetric: str
class _CertInfo(TypedDict):
subject: tuple[tuple[tuple[str, str], ...], ...]
issuer: tuple[tuple[tuple[str, str], ...], ...]
version: int
serialNumber: str
notBefore: str
notAfter: str
subjectAltName: NotRequired[tuple[tuple[str, str], ...] | None]
OCSP: NotRequired[tuple[str, ...] | None]
caIssuers: NotRequired[tuple[str, ...] | None]
crlDistributionPoints: NotRequired[tuple[str, ...] | None]
def RAND_add(string: str | ReadableBuffer, entropy: float, /) -> None: ...
def RAND_bytes(n: int, /) -> bytes: ...
if sys.version_info < (3, 12):
def RAND_pseudo_bytes(n: int, /) -> tuple[bytes, bool]: ...
if sys.version_info < (3, 10):
def RAND_egd(path: str) -> None: ...
def RAND_status() -> bool: ...
def get_default_verify_paths() -> tuple[str, str, str, str]: ...
if sys.platform == "win32":
_EnumRetType: TypeAlias = list[tuple[bytes, str, set[str] | bool]]
def enum_certificates(store_name: str) -> _EnumRetType: ...
def enum_crls(store_name: str) -> _EnumRetType: ...
def txt2obj(txt: str, name: bool = False) -> tuple[int, str, str, str]: ...
def nid2obj(nid: int, /) -> tuple[int, str, str, str]: ...
class _SSLContext:
check_hostname: bool
keylog_filename: str | None
maximum_version: int
minimum_version: int
num_tickets: int
options: int
post_handshake_auth: bool
protocol: int
if sys.version_info >= (3, 10):
security_level: int
sni_callback: Callable[[SSLObject, str, SSLContext], None | int] | None
verify_flags: int
verify_mode: int
def __new__(cls, protocol: int, /) -> Self: ...
def cert_store_stats(self) -> dict[str, int]: ...
@overload
def get_ca_certs(self, binary_form: Literal[False] = False) -> list[_PeerCertRetDictType]: ...
@overload
def get_ca_certs(self, binary_form: Literal[True]) -> list[bytes]: ...
@overload
def get_ca_certs(self, binary_form: bool = False) -> Any: ...
def get_ciphers(self) -> list[_Cipher]: ...
def load_cert_chain(
self, certfile: StrOrBytesPath, keyfile: StrOrBytesPath | None = None, password: _PasswordType | None = None
) -> None: ...
def load_dh_params(self, path: str, /) -> None: ...
def load_verify_locations(
self,
cafile: StrOrBytesPath | None = None,
capath: StrOrBytesPath | None = None,
cadata: str | ReadableBuffer | None = None,
) -> None: ...
def session_stats(self) -> dict[str, int]: ...
def set_ciphers(self, cipherlist: str, /) -> None: ...
def set_default_verify_paths(self) -> None: ...
def set_ecdh_curve(self, name: str, /) -> None: ...
if sys.version_info >= (3, 13):
def set_psk_client_callback(self, callback: Callable[[str | None], tuple[str | None, bytes]] | None) -> None: ...
def set_psk_server_callback(
self, callback: Callable[[str | None], bytes] | None, identity_hint: str | None = None
) -> None: ...
@final
class MemoryBIO:
eof: bool
pending: int
def __new__(self) -> Self: ...
def read(self, size: int = -1, /) -> bytes: ...
def write(self, b: ReadableBuffer, /) -> int: ...
def write_eof(self) -> None: ...
@final
class SSLSession:
__hash__: ClassVar[None] # type: ignore[assignment]
@property
def has_ticket(self) -> bool: ...
@property
def id(self) -> bytes: ...
@property
def ticket_lifetime_hint(self) -> int: ...
@property
def time(self) -> int: ...
@property
def timeout(self) -> int: ...
# _ssl.Certificate is weird: it can't be instantiated or subclassed.
# Instances can only be created via methods of the private _ssl._SSLSocket class,
# for which the relevant method signatures are:
#
# class _SSLSocket:
# def get_unverified_chain(self) -> list[Certificate] | None: ...
# def get_verified_chain(self) -> list[Certificate] | None: ...
#
# You can find a _ssl._SSLSocket object as the _sslobj attribute of a ssl.SSLSocket object
if sys.version_info >= (3, 10):
@final
class Certificate:
def get_info(self) -> _CertInfo: ...
@overload
def public_bytes(self) -> str: ...
@overload
def public_bytes(self, format: Literal[1] = 1, /) -> str: ... # ENCODING_PEM
@overload
def public_bytes(self, format: Literal[2], /) -> bytes: ... # ENCODING_DER
@overload
def public_bytes(self, format: int, /) -> str | bytes: ...
if sys.version_info < (3, 12):
err_codes_to_names: dict[tuple[int, int], str]
err_names_to_codes: dict[str, tuple[int, int]]
lib_codes_to_names: dict[int, str]
_DEFAULT_CIPHERS: str
# SSL error numbers
SSL_ERROR_ZERO_RETURN: int
SSL_ERROR_WANT_READ: int
SSL_ERROR_WANT_WRITE: int
SSL_ERROR_WANT_X509_LOOKUP: int
SSL_ERROR_SYSCALL: int
SSL_ERROR_SSL: int
SSL_ERROR_WANT_CONNECT: int
SSL_ERROR_EOF: int
SSL_ERROR_INVALID_ERROR_CODE: int
# verify modes
CERT_NONE: int
CERT_OPTIONAL: int
CERT_REQUIRED: int
# verify flags
VERIFY_DEFAULT: int
VERIFY_CRL_CHECK_LEAF: int
VERIFY_CRL_CHECK_CHAIN: int
VERIFY_X509_STRICT: int
VERIFY_X509_TRUSTED_FIRST: int
if sys.version_info >= (3, 10):
VERIFY_ALLOW_PROXY_CERTS: int
VERIFY_X509_PARTIAL_CHAIN: int
# alert descriptions
ALERT_DESCRIPTION_CLOSE_NOTIFY: int
ALERT_DESCRIPTION_UNEXPECTED_MESSAGE: int
ALERT_DESCRIPTION_BAD_RECORD_MAC: int
ALERT_DESCRIPTION_RECORD_OVERFLOW: int
ALERT_DESCRIPTION_DECOMPRESSION_FAILURE: int
ALERT_DESCRIPTION_HANDSHAKE_FAILURE: int
ALERT_DESCRIPTION_BAD_CERTIFICATE: int
ALERT_DESCRIPTION_UNSUPPORTED_CERTIFICATE: int
ALERT_DESCRIPTION_CERTIFICATE_REVOKED: int
ALERT_DESCRIPTION_CERTIFICATE_EXPIRED: int
ALERT_DESCRIPTION_CERTIFICATE_UNKNOWN: int
ALERT_DESCRIPTION_ILLEGAL_PARAMETER: int
ALERT_DESCRIPTION_UNKNOWN_CA: int
ALERT_DESCRIPTION_ACCESS_DENIED: int
ALERT_DESCRIPTION_DECODE_ERROR: int
ALERT_DESCRIPTION_DECRYPT_ERROR: int
ALERT_DESCRIPTION_PROTOCOL_VERSION: int
ALERT_DESCRIPTION_INSUFFICIENT_SECURITY: int
ALERT_DESCRIPTION_INTERNAL_ERROR: int
ALERT_DESCRIPTION_USER_CANCELLED: int
ALERT_DESCRIPTION_NO_RENEGOTIATION: int
ALERT_DESCRIPTION_UNSUPPORTED_EXTENSION: int
ALERT_DESCRIPTION_CERTIFICATE_UNOBTAINABLE: int
ALERT_DESCRIPTION_UNRECOGNIZED_NAME: int
ALERT_DESCRIPTION_BAD_CERTIFICATE_STATUS_RESPONSE: int
ALERT_DESCRIPTION_BAD_CERTIFICATE_HASH_VALUE: int
ALERT_DESCRIPTION_UNKNOWN_PSK_IDENTITY: int
# protocol versions
PROTOCOL_SSLv23: int
PROTOCOL_TLS: int
PROTOCOL_TLS_CLIENT: int
PROTOCOL_TLS_SERVER: int
PROTOCOL_TLSv1: int
PROTOCOL_TLSv1_1: int
PROTOCOL_TLSv1_2: int
# protocol options
OP_ALL: int
OP_NO_SSLv2: int
OP_NO_SSLv3: int
OP_NO_TLSv1: int
OP_NO_TLSv1_1: int
OP_NO_TLSv1_2: int
OP_NO_TLSv1_3: int
OP_CIPHER_SERVER_PREFERENCE: int
OP_SINGLE_DH_USE: int
OP_NO_TICKET: int
OP_SINGLE_ECDH_USE: int
OP_NO_COMPRESSION: int
OP_ENABLE_MIDDLEBOX_COMPAT: int
OP_NO_RENEGOTIATION: int
if sys.version_info >= (3, 11) or sys.platform == "linux":
OP_IGNORE_UNEXPECTED_EOF: int
if sys.version_info >= (3, 12):
OP_LEGACY_SERVER_CONNECT: int
OP_ENABLE_KTLS: int
# host flags
HOSTFLAG_ALWAYS_CHECK_SUBJECT: int
HOSTFLAG_NEVER_CHECK_SUBJECT: int
HOSTFLAG_NO_WILDCARDS: int
HOSTFLAG_NO_PARTIAL_WILDCARDS: int
HOSTFLAG_MULTI_LABEL_WILDCARDS: int
HOSTFLAG_SINGLE_LABEL_SUBDOMAINS: int
if sys.version_info >= (3, 10):
# certificate file types
# Typed as Literal so the overload on Certificate.public_bytes can work properly.
ENCODING_PEM: Literal[1]
ENCODING_DER: Literal[2]
# protocol versions
PROTO_MINIMUM_SUPPORTED: int
PROTO_MAXIMUM_SUPPORTED: int
PROTO_SSLv3: int
PROTO_TLSv1: int
PROTO_TLSv1_1: int
PROTO_TLSv1_2: int
PROTO_TLSv1_3: int
# feature support
HAS_SNI: bool
HAS_TLS_UNIQUE: bool
HAS_ECDH: bool
HAS_NPN: bool
if sys.version_info >= (3, 13):
HAS_PSK: bool
HAS_ALPN: bool
HAS_SSLv2: bool
HAS_SSLv3: bool
HAS_TLSv1: bool
HAS_TLSv1_1: bool
HAS_TLSv1_2: bool
HAS_TLSv1_3: bool
# version info
OPENSSL_VERSION_NUMBER: int
OPENSSL_VERSION_INFO: tuple[int, int, int, int, int]
OPENSSL_VERSION: str
_OPENSSL_API_VERSION: tuple[int, int, int, int, int]

Some files were not shown because too many files have changed in this diff Show More