Commit graph

6616 commits

Author SHA1 Message Date
Alex Waygood
1389cb8e59
[red-knot] Emit an error if a bare Annotated or Literal is used in a type expression (#14973) 2024-12-15 02:00:52 +00:00
Alex Waygood
fa46ba2306
[red-knot] Fix bugs relating to assignability of dynamic type[] types (#14972) 2024-12-15 01:15:10 +00:00
github-actions[bot]
53c7ef8bfe
Sync vendored typeshed stubs (#14977)
Co-authored-by: typeshedbot <>
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2024-12-15 01:02:41 +00:00
Alex Waygood
4d64cdb83c
[red-knot] ClassLiteral(<T>) is not a disjoint type from Instance(<metaclass of T>) (#14970)
## Summary

A class is an instance of its metaclass, so `ClassLiteral("ABC")` is not
disjoint from `Instance("ABCMeta")`. However, we erroneously consider
the two types disjoint on the `main` branch. This PR fixes that.

This bug was uncovered by adding some more core types to the property
tests that provide coverage for classes that have custom metaclasses.
The additions to the property tests are included in this PR.

## Test Plan

New unit tests and property tests added. Tested with:
- `cargo test -p red_knot_python_semantic`
- `QUICKCHECK_TESTS=100000 cargo test -p red_knot_python_semantic --
--ignored types::property_tests::stable`

The assignability property test fails on this branch, but that's a known
issue that exists on `main`, due to
https://github.com/astral-sh/ruff/issues/14899.
2024-12-14 11:28:09 -08:00
Carl Meyer
ac31b26a0e
[red-knot] type[] is disjoint from None, LiteralString (#14967)
## Summary

Teach red-knot that `type[...]` is always disjoint from `None` and from
`LiteralString`. Fixes #14925.

This should properly be generalized to "all instances of final types
which are not subclasses of `type`", but until we support finality,
hardcoding `None` (which is known to be final) allows us to fix the
subtype transitivity property test.

## Test Plan

Existing tests pass, added new unit tests for `is_disjoint_from` and
`is_subtype_of`.

`QUICKCHECK_TESTS=100000 cargo test -p red_knot_python_semantic --
--ignored types::property_tests::stable` fails only the "assignability
is reflexive" test, which is known to fail on `main` (#14899).

The same command, with `property_tests.rs` edited to prevent generating
intersection tests (the cause of #14899), passes all quickcheck tests.
2024-12-14 11:02:49 +01:00
InSync
a80e934838
[red-knot] Error out when an mdtest code block is unterminated (#14965)
## Summary

Resolves #14934.

## Test Plan

Added a unit test.
2024-12-13 21:51:21 -08:00
Alex Waygood
224c8438bd
[red-knot] Minor simplifications to types.rs (#14962) 2024-12-13 20:31:51 +00:00
Alex Waygood
90a5439791
[red-knot] Use type[Unknown] rather than Unknown as the fallback metaclass for invalid classes (#14961) 2024-12-13 19:48:51 +00:00
Alex Waygood
4b2b126b9f
[red-knot] Make is_subtype_of exhaustive (#14924) 2024-12-13 19:31:22 +00:00
InSync
9798556eb5
[red-knot] Alphabetize rules (#14960)
## Summary

Follow-up from #14950.

## Test Plan

Purely stylistic change. Shouldn't affect any functionalities.
2024-12-13 10:39:18 -08:00
InSync
aa1938f6ba
[red-knot] Understand Annotated (#14950)
## Summary

Resolves #14922.

## Test Plan

Markdown tests.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Co-authored-by: Carl Meyer <carl@astral.sh>
2024-12-13 09:41:37 -08:00
Dhruv Manilawala
3533d7f5b4
[red-knot] Display definition range in trace logs (#14955)
I've mainly opened this PR to get some opinions. I've found having some
additional information in the tracing logs to be useful to determine
what we are currently inferring. For the `Definition` ingredient, the
range seems to be much useful. I thought of using the identifier name
but we would have to deconstruct the `Expr` to find out the identifier
which seems a lot for just trace logs. Additionally, multiple
identifiers _could_ have the same name where range would be useful.

The ranges are isolated to the names that have been defined by the
definition except for the `except` block where the entire range is being
used because the name is optional.

***Before:***

```
3      ├─   0.074671s  54ms TRACE red_knot_workspace::db Salsa event: Event { thread_id: ThreadId(3), kind: WillExecute { database_key: infer_definition_types(Id(1402)) } }
3      └─┐red_knot_python_semantic::types::infer::infer_definition_types{definition=Id(1402), file=/Users/dhruv/playground/ruff/type_inference/isolated3/play.py}
3      ┌─┘
3      ├─   0.074768s  54ms TRACE red_knot_workspace::db Salsa event: Event { thread_id: ThreadId(3), kind: WillExecute { database_key: inner_fn_name_(Id(2800)) } }
3      ├─   0.074807s  54ms TRACE red_knot_workspace::db Salsa event: Event { thread_id: ThreadId(3), kind: WillExecute { database_key: infer_deferred_types(Id(1735)) } }
3      └─┐red_knot_python_semantic::types::infer::infer_deferred_types{definition=Id(1735), file=vendored://stdlib/typing.pyi}
3        ├─   0.074842s   0ms TRACE red_knot_workspace::db Salsa event: Event { thread_id: ThreadId(3), kind: WillExecute { database_key: infer_definition_types(Id(14f3)) } }
3        └─┐red_knot_python_semantic::types::infer::infer_definition_types{definition=Id(14f3), file=vendored://stdlib/typing.pyi}
3          ├─   0.074871s   0ms TRACE red_knot_workspace::db Salsa event: Event { thread_id: ThreadId(3), kind: WillExecute { database_key: infer_expression_types(Id(1820)) } }
3          └─┐red_knot_python_semantic::types::infer::infer_expression_types{expression=Id(1820), file=vendored://stdlib/typing.pyi}
3            ├─   0.074924s   0ms TRACE red_knot_workspace::db Salsa event: Event { thread_id: ThreadId(3), kind: WillExecute { database_key: infer_definition_types(Id(1429)) } }
3            └─┐red_knot_python_semantic::types::infer::infer_definition_types{definition=Id(1429), file=vendored://stdlib/typing.pyi}
3              ├─   0.074958s   0ms TRACE red_knot_workspace::db Salsa event: Event { thread_id: ThreadId(3), kind: WillExecute { database_key: infer_definition_types(Id(1428)) } }
3              └─┐red_knot_python_semantic::types::infer::infer_definition_types{definition=Id(1428), file=vendored://stdlib/typing.pyi}
3              ┌─┘
```

***After:***

```
12      ├─   0.074609s  55ms TRACE red_knot_workspace::db Salsa event: Event { thread_id: ThreadId(12), kind: WillExecute { database_key: infer_definition_types(Id(1402)) } }
12      └─┐red_knot_python_semantic::types::infer::infer_definition_types{definition=Id(1402), range=36..37, file=/Users/dhruv/playground/ruff/type_inference/isolated3/play.py}
12      ┌─┘
12      ├─   0.074705s  55ms TRACE red_knot_workspace::db Salsa event: Event { thread_id: ThreadId(12), kind: WillExecute { database_key: inner_fn_name_(Id(2800)) } }
12      ├─   0.074742s  55ms TRACE red_knot_workspace::db Salsa event: Event { thread_id: ThreadId(12), kind: WillExecute { database_key: infer_deferred_types(Id(1735)) } }
12      └─┐red_knot_python_semantic::types::infer::infer_deferred_types{definition=Id(1735), range=30225..30236, file=vendored://stdlib/typing.pyi}
12        ├─   0.074775s   0ms TRACE red_knot_workspace::db Salsa event: Event { thread_id: ThreadId(12), kind: WillExecute { database_key: infer_definition_types(Id(14f3)) } }
12        └─┐red_knot_python_semantic::types::infer::infer_definition_types{definition=Id(14f3), range=9472..9474, file=vendored://stdlib/typing.pyi}
12          ├─   0.074803s   0ms TRACE red_knot_workspace::db Salsa event: Event { thread_id: ThreadId(12), kind: WillExecute { database_key: infer_expression_types(Id(1820)) } }
12          └─┐red_knot_python_semantic::types::infer::infer_expression_types{expression=Id(1820), range=9477..9490, file=vendored://stdlib/typing.pyi}
12            ├─   0.074855s   0ms TRACE red_knot_workspace::db Salsa event: Event { thread_id: ThreadId(12), kind: WillExecute { database_key: infer_definition_types(Id(1429)) } }
12            └─┐red_knot_python_semantic::types::infer::infer_definition_types{definition=Id(1429), range=3139..3146, file=vendored://stdlib/typing.pyi}
12              ├─   0.074892s   0ms TRACE red_knot_workspace::db Salsa event: Event { thread_id: ThreadId(12), kind: WillExecute { database_key: infer_definition_types(Id(1428)) } }
12              └─┐red_knot_python_semantic::types::infer::infer_definition_types{definition=Id(1428), range=3102..3107, file=vendored://stdlib/typing.pyi}
12              ┌─┘
```
2024-12-13 14:29:53 +00:00
Alex Waygood
0bbe166720
[red-knot] Move the ClassBase enum to its own submodule (#14957) 2024-12-13 13:12:39 +00:00
David Peter
c3a64b44b7
[red-knot] mdtest: python version requirements (#14954)
## Summary

This is not strictly required yet, but makes these tests future-proof.
They need a `python-version` requirement as they rely on language
features that are not available in 3.9.
2024-12-13 10:40:38 +01:00
Wei Lee
dfd7f38009
[airflow]: Import modules that has been moved to airflow providers (AIR303) (#14764)
## Summary

Many core Airflow features have been deprecated and moved to Airflow
Providers since users might need to install an additional package (e.g.,
`apache-airflow-provider-fab==1.0.0`); a separate rule (AIR303) is
created for this.

As some of the changes only relate to the module/package moved, instead
of listing out all the functions, variables, and classes in a module or
a package, it warns the user to import from the new path instead of the
specific name.

The following is the ones that has been moved to
`apache-airflow-provider-fab==1.0.0`

* module moved
* `airflow.api.auth.backend.basic_auth` →
`airflow.providers.fab.auth_manager.api.auth.backend.basic_auth`
* `airflow.api.auth.backend.kerberos_auth` →
`airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth`
* `airflow.auth.managers.fab.api.auth.backend.kerberos_auth` →
`airflow.providers.fab.auth_manager.api.auth.backend.kerberos_auth`
* `airflow.auth.managers.fab.security_manager.override` →
`airflow.providers.fab.auth_manager.security_manager.override`
* classes (e.g., functions, classes) moved
* `airflow.www.security.FabAirflowSecurityManagerOverride` →
`airflow.providers.fab.auth_manager.security_manager.override.FabAirflowSecurityManagerOverride`
* `airflow.auth.managers.fab.fab_auth_manager.FabAuthManager` →
`airflow.providers.fab.auth_manager.security_manager.FabAuthManager`

## Test Plan


A test fixture has been included for the rule.
2024-12-13 10:38:07 +01:00
David Peter
e96b13c027
[red-knot] Support typing.TYPE_CHECKING (#14952)
## Summary

Add support for `typing.TYPE_CHECKING` and
`typing_extensions.TYPE_CHECKING`.

relates to: https://github.com/astral-sh/ruff/issues/14170

## Test Plan

New Markdown-based tests
2024-12-13 09:24:48 +00:00
Micha Reiser
f52b1f4a4d
Add tracing support to mdtest (#14935)
## Summary

This PR extends the mdtest configuration with a `log` setting that can
be any of:

* `true`: Enables tracing
* `false`: Disables tracing (default)
* String: An ENV_FILTER similar to `RED_KNOT_LOG`

```toml
log = true
```

Closes https://github.com/astral-sh/ruff/issues/13865

## Test Plan

I changed a test and tried `log=true`, `log=false`, and `log=INFO`
2024-12-13 09:10:01 +00:00
David Peter
2ccc9b19a7
[red-knot] Improve match mdtests (#14951)
## Summary

Minor improvement for the `match` tests to make sure we can't infer
statically whether or not a certain `case` applies.
2024-12-13 09:50:17 +01:00
Micha Reiser
c1837e4189
Rename custom-typeshed-dir, target-version and current-directory CLI options (#14930)
## Summary

This PR renames the `--custom-typeshed-dir`, `target-version`, and
`--current-directory` cli options to `--typeshed`,
`--python-version`, and `--project` as discussed in the CLI proposal
document.
I added aliases for `--target-version` (for Ruff compat) and
`--custom-typeshed-dir` (for Alex)

## Test Plan

Long help

```
An extremely fast Python type checker.

Usage: red_knot [OPTIONS] [COMMAND]

Commands:
  server  Start the language server
  help    Print this message or the help of the given subcommand(s)

Options:
      --project <PROJECT>
          Run the command within the given project directory.
          
          All `pyproject.toml` files will be discovered by walking up the directory tree from the project root, as will the project's virtual environment (`.venv`).
          
          Other command-line arguments (such as relative paths) will be resolved relative to the current working directory."#,

      --venv-path <PATH>
          Path to the virtual environment the project uses.
          
          If provided, red-knot will use the `site-packages` directory of this virtual environment to resolve type information for the project's third-party dependencies.

      --typeshed-path <PATH>
          Custom directory to use for stdlib typeshed stubs

      --extra-search-path <PATH>
          Additional path to use as a module-resolution source (can be passed multiple times)

      --python-version <VERSION>
          Python version to assume when resolving types
          
          [possible values: 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13]

  -v, --verbose...
          Use verbose output (or `-vv` and `-vvv` for more verbose output)

  -W, --watch
          Run in watch mode by re-running whenever files change

  -h, --help
          Print help (see a summary with '-h')

  -V, --version
          Print version
```

Short help 

```
An extremely fast Python type checker.

Usage: red_knot [OPTIONS] [COMMAND]

Commands:
  server  Start the language server
  help    Print this message or the help of the given subcommand(s)

Options:
      --project <PROJECT>         Run the command within the given project directory
      --venv-path <PATH>          Path to the virtual environment the project uses
      --typeshed-path <PATH>      Custom directory to use for stdlib typeshed stubs
      --extra-search-path <PATH>  Additional path to use as a module-resolution source (can be passed multiple times)
      --python-version <VERSION>  Python version to assume when resolving types [possible values: 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13]
  -v, --verbose...                Use verbose output (or `-vv` and `-vvv` for more verbose output)
  -W, --watch                     Run in watch mode by re-running whenever files change
  -h, --help                      Print help (see more with '--help')
  -V, --version                   Print version

```

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2024-12-13 08:21:52 +00:00
David Peter
d7ce548893
[red-knot] Add narrowing for 'while' loops (#14947)
## Summary

Add type narrowing for `while` loops and corresponding `else` branches.

closes #14861 

## Test Plan

New Markdown tests.
2024-12-13 07:40:14 +01:00
Krishnan Chandra
be4ce16735
[ruff] Skip SQLModel base classes for mutable-class-default (RUF012) (#14949)
## Summary

Closes https://github.com/astral-sh/ruff/issues/14892, by adding
`sqlmodel.SQLModel` to the list of classes with default copy semantics.

## Test Plan

Added a test into `RUF012.py` containing the example from the original
issue.
2024-12-12 22:19:21 -06:00
David Peter
657d26ff20
[red-knot] Tests for 'while' loop boundness (#14944)
## Summary

Regression test(s) for something that broken while implementing #14759.
We have similar tests for other control flow elements, but feel free to
let me know if this seems superfluous.

## Test Plan

New mdtests
2024-12-12 21:06:56 +01:00
Alex Waygood
dbc191d2d6
[red-knot] Fixes to Type::to_meta_type (#14942) 2024-12-12 19:55:11 +00:00
David Peter
d2712c7669
ruff_python_ast: Make Singleton Copy (#14943)
## Summary

Minor changed pulled out from #14759, as it seems to make sense in
isolation.

## Test Plan

—
2024-12-12 20:49:54 +01:00
Chandra Kiran G
e5cb4d6388
[flake8-pyi]: More autofixes for redundant-none-literal (PYI061) (#14872)
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2024-12-12 19:44:32 +00:00
Sergey Mezentsev
68e8496260
[flake8-use-pathlib] Extend check for invalid path suffix to include the case "." (PTH210) (#14902)
## Summary

`PTH210` renamed to `invalid-pathlib-with-suffix` and extended to check for `.with_suffix(".")`. This caused the fix availability to be downgraded to "Sometimes", since there is no fix offered in this case.

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
Co-authored-by: Dylan <53534755+dylwil3@users.noreply.github.com>
2024-12-12 13:30:17 -06:00
Alex Waygood
71239f248e
[red-knot] Add explicit TODO branches for many typing special forms and qualifiers (#14936) 2024-12-12 17:57:26 +00:00
Alex Waygood
58930905eb
[red-knot] Fixup a few edge cases regarding type[] (#14918) 2024-12-12 16:53:03 +00:00
Dylan
37f433814c
Bump version to 0.8.3 (#14937)
Co-authored-by: Dhruv Manilawala <dhruvmanila@gmail.com>
2024-12-12 14:13:06 +00:00
Alex Waygood
45b565cbb5
[red-knot] Any cannot be parameterized (#14933) 2024-12-12 11:50:34 +00:00
Micha Reiser
82faa9bb62
Add tests demonstrating f-strings with debug expressions in replacements that contain escaped characters (#14929) 2024-12-12 09:33:20 +00:00
w0nder1ng
2eac00c60f
[perflint] fix invalid hoist in perf401 (#14369)
Co-authored-by: Micha Reiser <micha@reiser.io>
2024-12-12 09:11:09 +01:00
InSync
e4885a2fb2
[red-knot] Understand typing.Tuple (#14927)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2024-12-12 00:58:06 +00:00
David Peter
a7e5e42b88
[red-knot] Make attributes.md test future-proof (#14923)
## Summary

Using `typing.LiteralString` breaks as soon as we understand
`sys.version_info` branches, as it's only available in 3.11 and later.

## Test Plan

Made sure it didn't fail on my #14759 branch anymore.
2024-12-11 20:46:24 +01:00
Alex Waygood
c361cf66ad
[red-knot] Precise inference for __class__ attributes on objects of all types (#14921) 2024-12-11 17:30:34 +00:00
Alex Waygood
a54353392f
[red-knot] Add failing test for use of type[] as a base class (#14913)
We support using `typing.Type[]` as a base class (and we have tests for
it), but not yet `builtins.type[]`. At some point we should fix that,
but I don't think it';s worth spending much time on now (and it might be
easier once we've implemented generics?). This PR just adds a failing
test with a TODO.
2024-12-11 17:08:00 +00:00
Alex Waygood
ef153a0cce
[red-knot] Remove an unnecessary branch and a confusing TODO comment (#14915) 2024-12-11 16:57:40 +00:00
InSync
0c85023cd9
Fix a typo in if_key_in_dict_del.rs (#14920)
(Accidentally introduced in #14553).
2024-12-11 16:28:27 +00:00
Alex Waygood
7135a49aea
[red-knot] Record the TODO message in ClassBase::Todo, same as in Type::Todo (#14919) 2024-12-11 15:17:56 +00:00
Micha Reiser
6e11086c98
Support lint:<rule> in mdtests (#14914)
## Summary

Fixes a small scoping issue in `DiagnosticId::matches`

Note: I don't think we should use `lint:id` in mdtests just yet. I worry
that it could lead to many unnecessary churns if we decide **not** to
use `lint:<id>` as the format (e.g., `lint/id`).

The reason why users even see `lint:<rule>` is because the mdtest
framework uses the diagnostic infrastructure

Closes #14910

## Test Plan

Added tests
2024-12-11 14:37:12 +01:00
Micha Reiser
28653c7c47
Strip lint: prefix from mdtest diagnostics 2024-12-11 14:33:31 +01:00
Alex Waygood
1d91dae11f
[red-knot] Minor simplifications to mro.rs (#14912) 2024-12-11 13:14:12 +00:00
Micha Reiser
881375a8d9
[red-knot] Lint registry and rule selection (#14874)
## Summary

This is the third and last PR in this stack that adds support for
toggling lints at a per-rule level.

This PR introduces a new `LintRegistry`, a central index of known lints.
The registry is required because we want to support lint rules from many
different crates but need a way to look them up by name, e.g., when
resolving a lint from a name in the configuration or analyzing a
suppression comment.

Adding a lint now requires two steps:

1. Declare the lint with `declare_lint`
2. Register the lint in the registry inside the `register_lints`
function.

I considered some more involved macros to avoid changes in two places.
Still, I ultimately decided against it because a) it's just two places
and b) I'd expect that registering a type checker lint will differ from
registering a lint that runs as a rule in the linter. I worry that any
more opinionated design could limit our options when working on the
linter, so I kept it simple.

The second part of this PR is the `RuleSelection`. It stores which lints
are enabled and what severity they should use for created diagnostics.
For now, the `RuleSelection` always gets initialized with all known
lints and it uses their default level.

## Linter crates

Each crate that defines lints should export a `register_lints` function
that accepts a `&mut LintRegistryBuilder` to register all its known
lints in the registry. This should make registering all known lints in a
top-level crate easy: Just call `register_lints` of every crate that
defines lint rules.

I considered defining a `LintCollection` trait and even some fancy
macros to accomplish the same but decided to go for this very simplistic
approach for now. We can add more abstraction once needed.

## Lint rules

This is a bit hand-wavy. I don't have a good sense for how our linter
infrastructure will look like, but I expect we'll need a way to register
the rules that should run as part of the red knot linter. One way is to
keep doing what Ruff does by having one massive `checker` and each lint
rule adds a call to itself in the relevant AST visitor methods. An
alternative is that we have a `LintRule` trait that provides common
hooks and implementations will be called at the "right time". Such a
design would need a way to register all known lint implementations,
possibly with the lint. This is where we'd probably want a dedicated
`register_rule` method. A third option is that lint rules are handled
separately from the `LintRegistry` and are specific to the linter crate.

The current design should be flexible enough to support the three
options.


## Documentation generation

The documentation for all known lints can be generated by creating a
factory, registering all lints by calling the `register_lints` methods,
and then querying the registry for the metadata.

## Deserialization and Schema generation

I haven't fully decided what the best approach is when it comes to
deserializing lint rule names:

* Reject invalid names in the deserializer. This gives us error messages
with line and column numbers (by serde)
* Don't validate lint rule names during deserialization; defer the
validation until the configuration is resolved. This gives us more
control over handling the error, e.g. emit a warning diagnostic instead
of aborting when a rule isn't known.

One technical challenge for both deserialization and schema generation
is that the `Deserialize` and `JSONSchema` traits do not allow passing
the `LintRegistry`, which is required to look up the lints by name. I
suggest that we either rely on the salsa db being set for the current
thread (`salsa::Attach`) or build our own thread-local storage for the
`LintRegistry`. It's the caller's responsibility to make the lint
registry available before calling `Deserialize` or `JSONSchema`.


## CLI support

I prefer deferring adding support for enabling and disabling lints from
the CLI for now because I think it will be easier
to add once I've figured out how to handle configurations. 

## Bitset optimization

Ruff tracks the enabled rules using a cheap copyable `Bitset` instead of
a hash map. This helped improve performance by a few percent (see
https://github.com/astral-sh/ruff/pull/3606). However, this approach is
no longer possible because lints have no "cheap" way to compute their
index inside the registry (other than using a hash map).

We could consider doing something similar to Salsa where each
`LintMetadata` stores a `LazyLintIndex`.

```
pub struct LazyLintIndex {
	cached: OnceLock<(Nonce, LintIndex)>
}

impl LazyLintIndex {
	pub fn get(registry: &LintRegistry, lint: &'static LintMetadata) {
	
	let (nonce, index) = self.cached.get_or_init(|| registry.lint_index(lint));

	if registry.nonce() == nonce {
		index
	} else {
		registry.lint_index(lint)
	}
}
```

Each registry keeps a map from `LintId` to `LintIndex` where `LintIndex`
is in the range of `0...registry.len()`. The `LazyLintIndex` is based on
the assumption that every program has exactly **one** registry. This
assumption allows to cache the `LintIndex` directly on the
`LintMetadata`. The implementation falls back to the "slow" path if
there is more than one registry at runtime.

I was very close to implementing this optimization because it's kind of
fun to implement. I ultimately decided against it because it adds
complexity and I don't think it's worth doing in Red Knot today:

* Red Knot only queries the rule selection when deciding whether or not
to emit a diagnostic. It is rarely used to detect if a certain code
block should run. This is different from Ruff where the rule selection
is queried many times for every single AST node to determine which rules
*should* run.
* I'm not sure if a 2-3% performance improvement is worth the complexity

I suggest revisiting this decision when working on the linter where a
fast path for deciding if a rule is enabled might be more important (but
that depends on how lint rules are implemented)


## Test Plan

I removed a lint from the default rule registry, and the MD tests
started failing because the diagnostics were no longer emitted.
2024-12-11 13:25:19 +01:00
InSync
6f8d8fa36b
[ruff] if k in d: del d[k] (RUF051) (#14553)
## Summary

Resolves #7537.

## Test Plan

`cargo nextest run` and `cargo insta test`.

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2024-12-11 11:12:23 +00:00
InSync
f30227c436
[red-knot] Understand typing.Type (#14904)
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
2024-12-11 11:01:38 +00:00
InSync
c8d505c8ea
[pyupgrade] Do not report when a UTF-8 comment is followed by a non-UTF-8 one (UP009) (#14728)
## Summary

Resolves #14704.

## Test Plan

`cargo nextest run` and `cargo insta test`.

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
2024-12-11 10:30:41 +00:00
Dimitri Papadopoulos Orfanos
a55722e740
Revert disjointness->disjointedness (#14906)
## Summary

Partially revert #14880. While `disjointness` is missing from the
[OED](https://www.oed.com/search/dictionary/?q=disjointness) and [SCOWL
(And
Friends)](http://app.aspell.net/lookup?dict=en_US-large;words=disjointness),
it is commonly used in mathematics to describe disjoint sets.

## Test Plan

CI tests.
2024-12-11 08:26:45 +00:00
Dylan
a3bb0cd5ec
Raise syntax error for mixing except and except* (#14895)
This PR adds a syntax error if the parser encounters a `TryStmt` that
has except clauses both with and without a star.

The displayed error points to each except clause that contradicts the
original except clause kind. So, for example,

```python
try:
    ....
except:     #<-- we assume this is the desired except kind
    ....
except*:    #<---  error will point here
    ....
except*:    #<--- and here
    ....
```

Closes #14860
2024-12-10 17:50:55 -06:00
Douglas Creager
d4126f6049
Handle type[Any] correctly (#14876)
This adds support for `type[Any]`, which represents an unknown type (not
an instance of an unknown type), and `type`, which we are choosing to
interpret as `type[object]`.

Closes #14546
2024-12-10 16:12:37 -05:00
Carl Meyer
03fb2e5ac1
[red-knot] split call-outcome enums to their own submodule (#14898)
## Summary

This is already several hundred lines of code, and it will get more
complex with call-signature checking.

## Test Plan

This is a pure code move; the moved code wasn't changed, just imports.
Existing tests pass.
2024-12-10 12:03:29 -08:00