mirror of https://github.com/astral-sh/ruff
Add Python 3.13 guard
This commit is contained in:
parent
d625a304ce
commit
acb9e1563e
|
|
@ -2,17 +2,45 @@
|
|||
|
||||
## Class body implicit attributes
|
||||
|
||||
Python makes certain names available implicitly inside class body scopes. These are `__qualname__`,
|
||||
`__module__`, and `__firstlineno__`, as documented at
|
||||
Python makes certain names available implicitly inside class body scopes. These are `__qualname__`
|
||||
and `__module__`, as documented at
|
||||
<https://docs.python.org/3/reference/datamodel.html#creating-the-class-object>.
|
||||
|
||||
```py
|
||||
class Foo:
|
||||
reveal_type(__qualname__) # revealed: str
|
||||
reveal_type(__module__) # revealed: str
|
||||
```
|
||||
|
||||
## `__firstlineno__` (Python 3.13+)
|
||||
|
||||
Python 3.13 added `__firstlineno__` to the class body namespace.
|
||||
|
||||
### Available in Python 3.13+
|
||||
|
||||
```toml
|
||||
[environment]
|
||||
python-version = "3.13"
|
||||
```
|
||||
|
||||
```py
|
||||
class Foo:
|
||||
reveal_type(__firstlineno__) # revealed: int
|
||||
```
|
||||
|
||||
### Not available in Python 3.12 and earlier
|
||||
|
||||
```toml
|
||||
[environment]
|
||||
python-version = "3.12"
|
||||
```
|
||||
|
||||
```py
|
||||
class Foo:
|
||||
# error: [unresolved-reference]
|
||||
__firstlineno__
|
||||
```
|
||||
|
||||
## Nested classes
|
||||
|
||||
These implicit attributes are also available in nested classes, and refer to the nested class:
|
||||
|
|
@ -32,17 +60,32 @@ within the class body:
|
|||
```py
|
||||
__qualname__ = 42
|
||||
__module__ = 42
|
||||
__firstlineno__ = "not an int"
|
||||
|
||||
class Foo:
|
||||
# Inside the class body, these are the implicit class attributes
|
||||
reveal_type(__qualname__) # revealed: str
|
||||
reveal_type(__module__) # revealed: str
|
||||
reveal_type(__firstlineno__) # revealed: int
|
||||
|
||||
# Outside the class, the globals are visible
|
||||
reveal_type(__qualname__) # revealed: Literal[42]
|
||||
reveal_type(__module__) # revealed: Literal[42]
|
||||
```
|
||||
|
||||
## `__firstlineno__` has priority over globals (Python 3.13+)
|
||||
|
||||
The same applies to `__firstlineno__` on Python 3.13+:
|
||||
|
||||
```toml
|
||||
[environment]
|
||||
python-version = "3.13"
|
||||
```
|
||||
|
||||
```py
|
||||
__firstlineno__ = "not an int"
|
||||
|
||||
class Foo:
|
||||
reveal_type(__firstlineno__) # revealed: int
|
||||
|
||||
reveal_type(__firstlineno__) # revealed: Literal["not an int"]
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use ruff_db::files::File;
|
||||
use ruff_python_ast::PythonVersion;
|
||||
|
||||
use crate::dunder_all::dunder_all_names;
|
||||
use crate::module_resolver::{KnownModule, file_to_module, resolve_module_confident};
|
||||
|
|
@ -1646,17 +1647,11 @@ pub(crate) fn class_body_implicit_symbol<'db>(
|
|||
name: &str,
|
||||
) -> PlaceAndQualifiers<'db> {
|
||||
match name {
|
||||
// __qualname__ is the fully-qualified name of the class
|
||||
"__qualname__" => Place::bound(KnownClass::Str.to_instance(db)).into(),
|
||||
|
||||
// __module__ is the module name where the class is defined
|
||||
"__module__" => Place::bound(KnownClass::Str.to_instance(db)).into(),
|
||||
|
||||
// __firstlineno__ was added in Python 3.13, but we don't version-check since
|
||||
// it's always available in the class body namespace (just the __firstlineno__
|
||||
// attribute on the class itself may not be present)
|
||||
"__firstlineno__" => Place::bound(KnownClass::Int.to_instance(db)).into(),
|
||||
|
||||
"__firstlineno__" if Program::get(db).python_version(db) >= PythonVersion::PY313 => {
|
||||
Place::bound(KnownClass::Int.to_instance(db)).into()
|
||||
}
|
||||
_ => Place::Undefined.into(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue