Commit Graph

6666 Commits

Author SHA1 Message Date
Micha Reiser f78c03c5dc
Move more projects to `good.txt` 2025-05-08 19:34:56 +02:00
Brent Westbrook 981bd70d39
Convert `Message::SyntaxError` to use `Diagnostic` internally (#17784)
## Summary

This PR is a first step toward integration of the new `Diagnostic` type
into ruff. There are two main changes:
- A new `UnifiedFile` enum wrapping `File` for red-knot and a
`SourceFile` for ruff
- ruff's `Message::SyntaxError` variant is now a `Diagnostic` instead of
a `SyntaxErrorMessage`

The second of these changes was mostly just a proof of concept for the
first, and it went pretty smoothly. Converting `DiagnosticMessage`s will
be most of the work in replacing `Message` entirely.

## Test Plan

Existing tests, which show no changes.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-05-08 12:45:51 -04:00
Alex Waygood 0763331f7f
[ty] Support extending `__all__` with a literal tuple or set as well as a literal list (#17948) 2025-05-08 17:37:25 +01:00
Alex Waygood da8540862d
[ty] Make `unused-ignore-comment` disabled by default for now (#17955) 2025-05-08 17:21:34 +01:00
Micha Reiser 6a5533c44c
[ty] Change default severity for `unbound-reference` to `error` (#17936) 2025-05-08 17:54:46 +02:00
Micha Reiser d608eae126
[ty] Ignore `possibly-unresolved-reference` by default (#17934) 2025-05-08 17:44:56 +02:00
Micha Reiser 067a8ac574
[ty] Default to latest supported python version (#17938) 2025-05-08 16:58:35 +02:00
Micha Reiser 5eb215e8e5
[ty] Generate and add rules table (#17953) 2025-05-08 16:55:39 +02:00
Brent Westbrook 57bf7dfbd9
[ty] Implement `global` handling and `load-before-global-declaration` syntax error (#17637)
Summary
--

This PR resolves both the typing-related and syntax error TODOs added in
#17563 by tracking a set of `global` bindings for each scope. As
discussed below, we avoid the additional AST traversal from ruff by
collecting `Name`s from `global` statements while building the semantic
index and emit a syntax error if the `Name` is already bound in the
current scope at the point of the `global` statement. This has the
downside of separating the error from the `SemanticSyntaxChecker`, but I
plan to explore using this approach in the `SemanticSyntaxChecker`
itself as a follow-up. It seems like this may be a better approach for
ruff as well.

Test Plan
--

Updated all of the related mdtests to remove the TODOs (and add quotes I
forgot on the messages).

There is one remaining TODO, but it requires `nonlocal` support, which
isn't even incorporated into the `SemanticSyntaxChecker` yet.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Co-authored-by: Carl Meyer <carl@astral.sh>
2025-05-08 10:30:04 -04:00
Alex Waygood 67cd94ed64
[ty] Add missing bitwise-operator branches for boolean and integer arithmetic (#17949) 2025-05-08 14:10:35 +01:00
Wei Lee aac862822f
[`airflow`] Fix `SQLTableCheckOperator` typo (`AIR302`) (#17946) 2025-05-08 14:34:55 +02:00
Micha Reiser 3755ac9fac
Update ty metadata (#17943) 2025-05-08 13:24:31 +02:00
David Peter 4f890b2867
[ty] Update salsa (#17937)
## Summary

* Update salsa to pull in https://github.com/salsa-rs/salsa/pull/850.
* Some refactoring of salsa event callbacks in various `Db`'s due to
https://github.com/salsa-rs/salsa/pull/849

closes https://github.com/astral-sh/ty/issues/108

## Test Plan

Ran `cargo run --bin ty -- -vvv` on a test file to make sure that salsa
Events are still logged.
2025-05-08 12:02:53 +02:00
Shaygan Hooshyari d566636ca5
Support `typing.Self` in methods (#17689)
## Summary

Fixes: astral-sh/ty#159 

This PR adds support for using `Self` in methods.
When the type of an annotation is `TypingSelf` it is converted to a type
var based on:
https://typing.python.org/en/latest/spec/generics.html#self

I just skipped Protocols because it had more problems and the tests was
not useful.
Also I need to create a follow up PR that implicitly assumes `self`
argument has type `Self`.

In order to infer the type in the `in_type_expression` method I needed
to have scope id and semantic index available. I used the idea from
[this PR](https://github.com/astral-sh/ruff/pull/17589/files) to pass
additional context to this method.
Also I think in all places that `in_type_expression` is called we need
to have this context because `Self` can be there so I didn't split the
method into one version with context and one without.

## Test Plan

Added new tests from spec.

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
Co-authored-by: Carl Meyer <carl@astral.sh>
2025-05-07 15:58:00 -07:00
Alex Waygood 51cef5a72b
[ty] Recognise functions containing `yield from` expressions as being generator functions (#17930) 2025-05-07 23:29:44 +01:00
Douglas Creager 2cf5cba7ff
[ty] Check base classes when determining subtyping etc for generic aliases (#17927)
#17897 added variance handling for legacy typevars — but they were only
being considered when checking generic aliases of the same class:

```py
class A: ...
class B(A): ...

class C[T]: ...

static_assert(is_subtype_of(C[B], C[A]))
```

and not for generic subclasses:

```py
class D[U](C[U]): ...

static_assert(is_subtype_of(D[B], C[A]))
```

Now we check those too!

Closes https://github.com/astral-sh/ty/issues/101
2025-05-07 15:21:11 -04:00
yunchi ce0800fccf
[`pylint`] add fix safety section (`PLC2801`) (#17825)
parent: #15584 
fix was introduced at: #9587 
reasoning: #9572
2025-05-07 14:34:34 -04:00
Abhijeet Prasad Bodas f5096f2050
[parser] Flag single unparenthesized generator expr with trailing comma in arguments. (#17893)
Fixes #17867

## Summary

The CPython parser does not allow generator expressions which are the
sole arguments in an argument list to have a trailing comma.
With this change, we start flagging such instances.

## Test Plan

Added new inline tests.
2025-05-07 14:11:35 -04:00
Alex Waygood 895b6161a6
[ty] Ensure that `T` is disjoint from `~T` even when `T` is a TypeVar (#17922)
Same as https://github.com/astral-sh/ruff/pull/17910 but for
disjointness
2025-05-07 10:59:16 -07:00
Alex Waygood 74fe7982ba
[ty] Sort collected diagnostics before snapshotting them in mdtest (#17926) 2025-05-07 18:23:22 +01:00
Micha Reiser 51386b3c7a
[ty] Add basic file watching to server (#17912) 2025-05-07 19:03:30 +02:00
Charlie Marsh 51e2effd2d
Make completions an opt-in LSP feature (#17921)
## Summary

We now expect the client to send initialization options to opt-in to
experimental (but LSP-standardized) features, like completion support.
Specifically, the client should set `"experimental.completions.enable":
true`.

Closes https://github.com/astral-sh/ty/issues/74.
2025-05-07 16:39:35 +00:00
Dhruv Manilawala 78054824c0
[ty] Add support for `__all__` (#17856)
## Summary

This PR adds support for the `__all__` module variable.

Reference spec:
https://typing.python.org/en/latest/spec/distributing.html#library-interface-public-and-private-symbols

This PR adds a new `dunder_all_names` query that returns a set of
`Name`s defined in the `__all__` variable of the given `File`. The query
works by implementing the `StatementVisitor` and collects all the names
by recognizing the supported idioms as mentioned in the spec. Any idiom
that's not recognized are ignored.

The current implementation is minimum to what's required for us to
remove all the false positives that this is causing. Refer to the
"Follow-ups" section below to see what we can do next. I'll a open
separate issue to keep track of them.

Closes: astral-sh/ty#106 
Closes: astral-sh/ty#199

### Follow-ups

* Diagnostics:
* Add warning diagnostics for unrecognized `__all__` idioms, `__all__`
containing non-string element
* Add an error diagnostic for elements that are present in `__all__` but
not defined in the module. This could lead to runtime error
* Maybe we should return `<type>` instead of `Unknown | <type>` for
`module.__all__`. For example:
https://playknot.ruff.rs/2a6fe5d7-4e16-45b1-8ec3-d79f2d4ca894
* Mark a symbol that's mentioned in `__all__` as used otherwise it could
raise (possibly in the future) "unused-name" diagnostic

Supporting diagnostics will require that we update the return type of
the query to be something other than `Option<FxHashSet<Name>>`,
something that behaves like a result and provides a way to check whether
a name exists in `__all__`, loop over elements in `__all__`, loop over
the invalid elements, etc.

## Ecosystem analysis

The following are the maximum amount of diagnostics **removed** in the
ecosystem:

* "Type <module '...'> has no attribute ..."
    * `collections.abc` - 14
    * `numpy` - 35534
    * `numpy.ma` - 296
    * `numpy.char` - 37
    * `numpy.testing` - 175
    * `hashlib` - 311
    * `scipy.fft` - 2
    * `scipy.stats` - 38
* "Module '...' has no member ..."
    * `collections.abc` - 85
    * `numpy` - 508
    * `numpy.testing` - 741
    * `hashlib` - 36
    * `scipy.stats` - 68
    * `scipy.interpolate` - 7
    * `scipy.signal` - 5

The following modules have dynamic `__all__` definition, so `ty` assumes
that `__all__` doesn't exists in that module:
* `scipy.stats`
(95a5d6ea8b/scipy/stats/__init__.py (L665))
* `scipy.interpolate`
(95a5d6ea8b/scipy/interpolate/__init__.py (L221))
* `scipy.signal` (indirectly via
95a5d6ea8b/scipy/signal/_signal_api.py (L30))
* `numpy.testing`
(de784cd6ee/numpy/testing/__init__.py (L16-L18))

~There's this one category of **false positives** that have been added:~
Fixed the false positives by also ignoring `__all__` from a module that
uses unrecognized idioms.

<details><summary>Details about the false postivie:</summary>
<p>

The `scipy.stats` module has dynamic `__all__` and it imports a bunch of
symbols via star imports. Some of those modules have a mix of valid and
invalid `__all__` idioms. For example, in
95a5d6ea8b/scipy/stats/distributions.py (L18-L24),
2 out of 4 `__all__` idioms are invalid but currently `ty` recognizes
two of them and says that the module has a `__all__` with 5 values. This
leads to around **2055** newly added false positives of the form:
```
Type <module 'scipy.stats'> has no attribute ...
```

I think the fix here is to completely ignore `__all__`, not only if
there are invalid elements in it, but also if there are unrecognized
idioms used in the module.

</p>
</details> 

## Test Plan

Add a bunch of test cases using the new `ty_extensions.dunder_all_names`
function to extract a module's `__all__` names.

Update various test cases to remove false positives around `*` imports
and re-export convention.

Add new test cases for named import behavior as `*` imports covers all
of it already (thanks Alex!).
2025-05-07 21:42:42 +05:30
Alex Waygood c6f4929cdc
[ty] fix assigning a typevar to a union with itself (#17910)
Co-authored-by: Carl Meyer <carl@astral.sh>
2025-05-07 15:50:22 +00:00
Alex Waygood 2ec0d7e072
[ty] Improve UX for `[duplicate-base]` diagnostics (#17914) 2025-05-07 15:27:37 +00:00
Charlie Marsh ad658f4d68
Clean up some Ruff references in the ty server (#17920)
## Summary

Anything user-facing, etc.
2025-05-07 10:55:16 -04:00
Abhijeet Prasad Bodas 3dedd70a92
[ty] Detect overloads decorated with `@dataclass_transform` (#17835)
## Summary

Fixes #17541

Before this change, in the case of overloaded functions,
`@dataclass_transform` was detected only when applied to the
implementation, not the overloads.
However, the spec also allows this decorator to be applied to any of the
overloads as well.
With this PR, we start handling `@dataclass_transform`s applied to
overloads.

## Test Plan

Fixed existing TODOs in the test suite.
2025-05-07 15:51:13 +02:00
David Peter fab862c8cd
[ty] Ecosystem checks: activate running on 'manticore' (#17916)
## Summary

This is sort of an anticlimactic resolution to #17863, but now that we
understand what the root cause for the stack overflows was, I think it's
fine to enable running on this project. See the linked ticket for the
full analysis.

closes #17863

## Test Plan

Ran lots of times locally and never observed a crash at worker thread
stack sizes > 8 MiB.
2025-05-07 06:27:36 -07:00
Douglas Creager 0d9b6a0975
[ty] Handle explicit variance in legacy typevars (#17897)
We now track the variance of each typevar, and obey the `covariant` and
`contravariant` parameters to the legacy `TypeVar` constructor. We still
don't yet infer variance for PEP-695 typevars or for the
`infer_variance` legacy constructor parameter.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
Co-authored-by: Carl Meyer <carl@astral.sh>
2025-05-07 08:44:51 -04:00
Victor Hugo Gomes c504001b32
[`pyupgrade`] Add spaces between tokens as necessary to avoid syntax errors in `UP018` autofix (#17648)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-05-07 09:34:08 +02:00
David Peter 04457f99b6
[ty] Protocols: Fixpoint iteration for fully-static check (#17880)
## Summary

A recursive protocol like the following would previously lead to stack
overflows when attempting to create the union type for the `P | None`
member, because `UnionBuilder` checks if element types are fully static,
and the fully-static check on `P` would in turn list all members and
check whether all of them were fully static, leading to a cycle.

```py
from __future__ import annotations

from typing import Protocol

class P(Protocol):
    parent: P | None
```

Here, we make the fully-static check on protocols a salsa query and add
fixpoint iteration, starting with `true` as the initial value (assume
that the recursive protocol is fully-static). If the recursive protocol
has any non-fully-static members, we still return `false` when
re-executing the query (see newly added tests).

closes #17861

## Test Plan

Added regression test
2025-05-07 08:55:21 +02:00
InSync a33d0d4bf4
[ty] Support `generate-shell-completion` (#17879)
## Summary

Resolves #15502.

`ty generate-shell-completion` now works in a similar manner to `ruff
generate-shell-completion`.

## Test Plan

Manually:

<details>

```shell
$ cargo run --package ty generate-shell-completion nushell
module completions {

  # An extremely fast Python type checker.
  export extern ty [
    --help(-h)                # Print help
    --version(-V)             # Print version
  ]
  
  # ...

}

export use completions *
```
</details>
2025-05-06 18:04:57 -07:00
Charlie Marsh 443f62e98d
Remove condensed display type enum (#17902)
## Summary

See: https://github.com/astral-sh/ruff/pull/17889#discussion_r2076556002
2025-05-06 18:04:03 -07:00
Charlie Marsh a2e9a7732a
Update class literal display to use `<class 'Foo'>` style (#17889)
## Summary

Closes https://github.com/astral-sh/ruff/issues/17238.
2025-05-06 20:11:25 -04:00
Micha Reiser b2de749c32
Add a note to diagnostics why the rule is enabled (#17854) 2025-05-06 20:29:03 +02:00
Douglas Creager 9085f18353
[ty] Propagate specializations to ancestor base classes (#17892)
@AlexWaygood discovered that even though we've been propagating
specializations to _parent_ base classes correctly, we haven't been
passing them on to _grandparent_ base classes:
https://github.com/astral-sh/ruff/pull/17832#issuecomment-2854360969

```py
class Bar[T]:
    x: T

class Baz[T](Bar[T]): ...
class Spam[T](Baz[T]): ...

reveal_type(Spam[int]().x) # revealed: `T`, but should be `int`
```

This PR updates the MRO machinery to apply the current specialization
when starting to iterate the MRO of each base class.
2025-05-06 14:25:21 -04:00
Dylan 8152ba7cb7
[ty] Add minimal docs for a few lints (#17874)
Just the bare minimum to remove a few TODOs - omitted examples, and only
did 9 but I will check back tomorrow and try to knock out a few more!
2025-05-06 10:36:47 -07:00
Aria Desires 3d01d3be3e
update the repository for ty (#17891)
This metadata is used by cargo-dist for artifact URLs (in curl-sh
expressions)
2025-05-06 12:03:38 -04:00
Brent Westbrook 4510a236d3
Default to latest supported Python version for version-related syntax errors (#17529)
## Summary

This PR partially addresses #16418 via the following:

- `LinterSettings::unresolved_python_version` is now a `TargetVersion`,
which is a thin wrapper around an `Option<PythonVersion>`
- `Checker::target_version` now calls `TargetVersion::linter_version`
internally, which in turn uses `unwrap_or_default` to preserve the
current default behavior
- Calls to the parser now call `TargetVersion::parser_version`, which
calls `unwrap_or_else(PythonVersion::latest)`
- The `Checker`'s implementation of
`SemanticSyntaxContext::python_version` also uses
`TargetVersion::parser_version` to use `PythonVersion::latest` for
semantic errors

In short, all lint rule behavior should be unchanged, but we default to
the latest Python version for the new syntax errors, which should
minimize confusing version-related syntax errors for users without a
version configured.

## Test Plan

Existing tests, which showed no changes (except for printing default
settings).
2025-05-06 10:19:13 -04:00
Marcus Näslund 76b6d53d8b
Add new rule InEmptyCollection (#16480)
## Summary

Introducing a new rule based on discussions in #15732 and #15729 that
checks for unnecessary in with empty collections.

I called it in_empty_collection and gave the rule number RUF060.

Rule is in preview group.
2025-05-06 13:52:07 +00:00
Zanie Blue f82b72882b
Display `ty version` for `ty --version` and `ty -V` (#17888)
e.g.,

```
❯ uv run -q -- ty -V
ty 0.0.0-alpha.4 (08881edba 2025-05-05)
❯ uv run -q -- ty --version
ty 0.0.0-alpha.4 (08881edba 2025-05-05)
```

Previously, this just displayed `ty 0.0.0` because it didn't use our
custom version implementation. We no longer have a short version —
matching the interface in uv. We could add a variant for it, if it seems
important to people. However, I think we found it more confusing than
not over there and didn't get any complaints about the change.

Closes https://github.com/astral-sh/ty/issues/54
2025-05-06 08:06:41 -05:00
Zanie Blue d07eefc408
Parse `dist-workspace.toml` for version (#17868)
Extends https://github.com/astral-sh/ruff/pull/17866, using
`dist-workspace.toml` as a source of truth for versions to enable
version retrieval in distributions that are not Git repositories (i.e.,
Python source distributions and source tarballs consumed by Linux
distros).

I retain the Git tag lookup from
https://github.com/astral-sh/ruff/pull/17866 as a fallback — it seems
harmless, but we could drop it to simplify things here.

I confirmed this works from the repository as well as Python source and
binary distributions:

```
❯ uv run --refresh-package ty --reinstall-package ty -q --  ty version
ty 0.0.1-alpha.1+5 (2eadc9e61 2025-05-05)
❯ uv build
...
❯ uvx --from ty@dist/ty-0.0.0a1.tar.gz --no-cache -q -- ty version
ty 0.0.1-alpha.1
❯ uvx --from ty@dist/ty-0.0.0a1-py3-none-macosx_11_0_arm64.whl -q -- ty version
ty 0.0.1-alpha.1
```

Requires https://github.com/astral-sh/ty/pull/36

cc @Gankra and @MichaReiser for review.
2025-05-06 12:18:17 +00:00
Zanie Blue f7237e3b69
Update `ty version` to use parent Git repository information (#17866)
Currently, `ty version` pulls its information from the Ruff repository —
but we want this to pull from the repository in the directory _above_
when Ruff is a submodule.

I tested this in the `ty` repository after tagging an arbitrary commit:

```
❯ uv run --refresh-package ty --reinstall-package ty ty version
      Built ty @ file:///Users/zb/workspace/ty
Uninstalled 1 package in 2ms
Installed 1 package in 1ms
ty 0.0.0+3 (34253b1d4 2025-05-05)
```

We also use the last Git tag as the source of truth for the version,
instead of the crate version. However, we'll need a way to set the
version for releases still, as the tag is published _after_ the build.
We can either tag early (without pushing the tag to the remote), or add
another environment variable. (**Note, this approach is changed in a
follow-up. See https://github.com/astral-sh/ruff/pull/17868**)

From this repository, the version will be `unknown`:

```
❯ cargo run -q --bin ty -- version
ty unknown
```

We could add special handling like... `ty unknown (ruff@...)` but I see
that as a secondary goal.

Closes https://github.com/astral-sh/ty/issues/5

The reviewer situation in this repository is unhinged, cc @Gankra and
@MichaReiser for review.
2025-05-06 07:14:30 -05:00
Alex Waygood 2f9992b6ef
[ty] Fix duplicate diagnostics for unresolved module when an `import from` statement imports multiple members (#17886) 2025-05-06 12:37:10 +01:00
Alex Waygood 457ec4dddd
Generalize special-casing for enums constructed with the functional syntax (#17885) 2025-05-06 11:02:55 +01:00
Micha Reiser 24d3fc27fb
Fixup wording of fatal error warning (#17881) 2025-05-06 09:44:23 +02:00
Micha Reiser 6f821ac846
Show a warning at the end of the diagnostic list if there are any fatal warnings (#17855) 2025-05-06 07:14:21 +00:00
Alex Waygood 89424cce5f
[ty] Do not emit errors if enums or NamedTuples constructed using functional syntax are used in type expressions (#17873)
## Summary

This fixes some false positives that showed up in the primer diff for
https://github.com/astral-sh/ruff/pull/17832

## Test Plan

new mdtests added that fail with false-positive diagnostics on `main`
2025-05-06 00:37:24 +01:00
Shunsuke Shibayama fd76d70a31
[red-knot] fix narrowing in nested scopes (#17630)
## Summary

This PR fixes #17595.

## Test Plan

New test cases are added to `mdtest/narrow/conditionals/nested.md`.

---------

Co-authored-by: Carl Meyer <carl@astral.sh>
2025-05-05 16:28:42 -07:00
yunchi a4c8e43c5f
[`pylint`] Add fix safety section (`PLR1722`) (#17826)
parent: #15584 
fix introduced at: #816
2025-05-05 19:13:04 -04:00