mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-03 18:28:56 +00:00
[red-knot] Consistent spelling of "metaclass" and "meta-type" (#16576)
## Summary Fixes a small nit of mine -- we are currently inconsistent in our spelling between "metaclass" and "meta class", and between "meta type" and "meta-type". This PR means that we consistently use "metaclass" and "meta-type". ## Test Plan `uvx pre-commit run -a`
This commit is contained in:
parent
0361021863
commit
335b264fe2
6 changed files with 37 additions and 35 deletions
|
@ -731,20 +731,20 @@ object first, i.e. on the metaclass:
|
|||
from typing import Literal
|
||||
|
||||
class Meta1:
|
||||
attr: Literal["meta class value"] = "meta class value"
|
||||
attr: Literal["metaclass value"] = "metaclass value"
|
||||
|
||||
class C1(metaclass=Meta1): ...
|
||||
|
||||
reveal_type(C1.attr) # revealed: Literal["meta class value"]
|
||||
reveal_type(C1.attr) # revealed: Literal["metaclass value"]
|
||||
```
|
||||
|
||||
However, the meta class attribute only takes precedence over a class-level attribute if it is a data
|
||||
However, the metaclass attribute only takes precedence over a class-level attribute if it is a data
|
||||
descriptor. If it is a non-data descriptor or a normal attribute, the class-level attribute is used
|
||||
instead (see the [descriptor protocol tests] for data/non-data descriptor attributes):
|
||||
|
||||
```py
|
||||
class Meta2:
|
||||
attr: str = "meta class value"
|
||||
attr: str = "metaclass value"
|
||||
|
||||
class C2(metaclass=Meta2):
|
||||
attr: Literal["class value"] = "class value"
|
||||
|
@ -752,14 +752,14 @@ class C2(metaclass=Meta2):
|
|||
reveal_type(C2.attr) # revealed: Literal["class value"]
|
||||
```
|
||||
|
||||
If the class-level attribute is only partially defined, we union the meta class attribute with the
|
||||
If the class-level attribute is only partially defined, we union the metaclass attribute with the
|
||||
class-level attribute:
|
||||
|
||||
```py
|
||||
def _(flag: bool):
|
||||
class Meta3:
|
||||
attr1 = "meta class value"
|
||||
attr2: Literal["meta class value"] = "meta class value"
|
||||
attr1 = "metaclass value"
|
||||
attr2: Literal["metaclass value"] = "metaclass value"
|
||||
|
||||
class C3(metaclass=Meta3):
|
||||
if flag:
|
||||
|
@ -767,39 +767,39 @@ def _(flag: bool):
|
|||
# TODO: Neither mypy nor pyright show an error here, but we could consider emitting a conflicting-declaration diagnostic here.
|
||||
attr2: Literal["class value"] = "class value"
|
||||
|
||||
reveal_type(C3.attr1) # revealed: Unknown | Literal["meta class value", "class value"]
|
||||
reveal_type(C3.attr2) # revealed: Literal["meta class value", "class value"]
|
||||
reveal_type(C3.attr1) # revealed: Unknown | Literal["metaclass value", "class value"]
|
||||
reveal_type(C3.attr2) # revealed: Literal["metaclass value", "class value"]
|
||||
```
|
||||
|
||||
If the *meta class* attribute is only partially defined, we emit a `possibly-unbound-attribute`
|
||||
If the *metaclass* attribute is only partially defined, we emit a `possibly-unbound-attribute`
|
||||
diagnostic:
|
||||
|
||||
```py
|
||||
def _(flag: bool):
|
||||
class Meta4:
|
||||
if flag:
|
||||
attr1: str = "meta class value"
|
||||
attr1: str = "metaclass value"
|
||||
|
||||
class C4(metaclass=Meta4): ...
|
||||
# error: [possibly-unbound-attribute]
|
||||
reveal_type(C4.attr1) # revealed: str
|
||||
```
|
||||
|
||||
Finally, if both the meta class attribute and the class-level attribute are only partially defined,
|
||||
Finally, if both the metaclass attribute and the class-level attribute are only partially defined,
|
||||
we union them and emit a `possibly-unbound-attribute` diagnostic:
|
||||
|
||||
```py
|
||||
def _(flag1: bool, flag2: bool):
|
||||
class Meta5:
|
||||
if flag1:
|
||||
attr1 = "meta class value"
|
||||
attr1 = "metaclass value"
|
||||
|
||||
class C5(metaclass=Meta5):
|
||||
if flag2:
|
||||
attr1 = "class value"
|
||||
|
||||
# error: [possibly-unbound-attribute]
|
||||
reveal_type(C5.attr1) # revealed: Unknown | Literal["meta class value", "class value"]
|
||||
reveal_type(C5.attr1) # revealed: Unknown | Literal["metaclass value", "class value"]
|
||||
```
|
||||
|
||||
## Union of attributes
|
||||
|
|
|
@ -40,10 +40,10 @@ class Meta(type):
|
|||
def __getitem__(cls, key: int) -> str:
|
||||
return str(key)
|
||||
|
||||
class DunderOnMetaClass(metaclass=Meta):
|
||||
class DunderOnMetaclass(metaclass=Meta):
|
||||
pass
|
||||
|
||||
reveal_type(DunderOnMetaClass[0]) # revealed: str
|
||||
reveal_type(DunderOnMetaclass[0]) # revealed: str
|
||||
```
|
||||
|
||||
If the dunder method is only present on the class itself, it will not be called:
|
||||
|
|
|
@ -640,7 +640,7 @@ reveal_type(C.d) # revealed: int
|
|||
|
||||
## Dunder methods
|
||||
|
||||
Dunder methods are looked up on the meta type, but we still need to invoke the descriptor protocol:
|
||||
Dunder methods are looked up on the meta-type, but we still need to invoke the descriptor protocol:
|
||||
|
||||
```py
|
||||
class SomeCallable:
|
||||
|
|
|
@ -163,7 +163,7 @@ reveal_type(B.__class__) # revealed: Literal[M]
|
|||
## Non-class
|
||||
|
||||
When a class has an explicit `metaclass` that is not a class, but is a callable that accepts
|
||||
`type.__new__` arguments, we should return the meta type of its return type.
|
||||
`type.__new__` arguments, we should return the meta-type of its return type.
|
||||
|
||||
```py
|
||||
def f(*args, **kwargs) -> int: ...
|
||||
|
|
|
@ -383,7 +383,7 @@ static_assert(is_subtype_of(LiteralStr, type[object]))
|
|||
|
||||
static_assert(not is_subtype_of(type[str], LiteralStr))
|
||||
|
||||
# custom meta classes
|
||||
# custom metaclasses
|
||||
|
||||
type LiteralHasCustomMetaclass = TypeOf[HasCustomMetaclass]
|
||||
|
||||
|
|
|
@ -136,9 +136,9 @@ enum AttributeKind {
|
|||
|
||||
/// This enum is used to control the behavior of the descriptor protocol implementation.
|
||||
/// When invoked on a class object, the fallback type (a class attribute) can shadow a
|
||||
/// non-data descriptor of the meta type (the class's metaclass). However, this is not
|
||||
/// non-data descriptor of the meta-type (the class's metaclass). However, this is not
|
||||
/// true for instances. When invoked on an instance, the fallback type (an attribute on
|
||||
/// the instance) can not completely shadow a non-data descriptor of the meta type (the
|
||||
/// the instance) can not completely shadow a non-data descriptor of the meta-type (the
|
||||
/// class), because we do not currently attempt to statically infer if an instance
|
||||
/// attribute is definitely defined (i.e. to check whether a particular method has been
|
||||
/// called).
|
||||
|
@ -148,17 +148,17 @@ enum InstanceFallbackShadowsNonDataDescriptor {
|
|||
No,
|
||||
}
|
||||
|
||||
/// Dunder methods are looked up on the meta type of a type without potentially falling
|
||||
/// Dunder methods are looked up on the meta-type of a type without potentially falling
|
||||
/// back on attributes on the type itself. For example, when implicitly invoked on an
|
||||
/// instance, dunder methods are not looked up as instance attributes. And when invoked
|
||||
/// on a class, dunder methods are only looked up on the meta class, not the class itself.
|
||||
/// on a class, dunder methods are only looked up on the metaclass, not the class itself.
|
||||
///
|
||||
/// All other attributes use the `WithInstanceFallback` policy.
|
||||
#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash)]
|
||||
enum MemberLookupPolicy {
|
||||
/// Only look up the attribute on the meta type.
|
||||
/// Only look up the attribute on the meta-type.
|
||||
NoInstanceFallback,
|
||||
/// Look up the attribute on the meta type, but fall back to attributes on the instance
|
||||
/// Look up the attribute on the meta-type, but fall back to attributes on the instance
|
||||
/// if the meta-type attribute is not found or if the meta-type attribute is not a data
|
||||
/// descriptor.
|
||||
WithInstanceFallback,
|
||||
|
@ -1540,7 +1540,7 @@ impl<'db> Type<'db> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Look up an attribute in the MRO of the meta type of `self`. This returns class-level attributes
|
||||
/// Look up an attribute in the MRO of the meta-type of `self`. This returns class-level attributes
|
||||
/// when called on an instance-like type, and metaclass attributes when called on a class-like type.
|
||||
///
|
||||
/// Basically corresponds to `self.to_meta_type().find_name_in_mro(name)`, except for the handling
|
||||
|
@ -1555,7 +1555,9 @@ impl<'db> Type<'db> {
|
|||
_ => self
|
||||
.to_meta_type(db)
|
||||
.find_name_in_mro(db, name.as_str())
|
||||
.expect("was called on meta type"),
|
||||
.expect(
|
||||
"`Type::find_name_in_mro()` should return `Some()` when called on a meta-type",
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1652,14 +1654,14 @@ impl<'db> Type<'db> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Look up `__get__` on the meta type of self, and call it with the arguments `self`, `instance`,
|
||||
/// Look up `__get__` on the meta-type of self, and call it with the arguments `self`, `instance`,
|
||||
/// and `owner`. `__get__` is different than other dunder methods in that it is not looked up using
|
||||
/// the descriptor protocol itself.
|
||||
///
|
||||
/// In addition to the return type of `__get__`, this method also returns the *kind* of attribute
|
||||
/// that `self` represents: (1) a data descriptor or (2) a non-data descriptor / normal attribute.
|
||||
///
|
||||
/// If `__get__` is not defined on the meta type, this method returns `None`.
|
||||
/// If `__get__` is not defined on the meta-type, this method returns `None`.
|
||||
#[salsa::tracked]
|
||||
fn try_call_dunder_get(
|
||||
self,
|
||||
|
@ -1698,7 +1700,7 @@ impl<'db> Type<'db> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Look up `__get__` on the meta type of `attribute`, and call it with `attribute`, `instance`,
|
||||
/// Look up `__get__` on the meta-type of `attribute`, and call it with `attribute`, `instance`,
|
||||
/// and `owner` as arguments. This method exists as a separate step as we need to handle unions
|
||||
/// and intersections explicitly.
|
||||
fn try_call_dunder_get_on_attribute(
|
||||
|
@ -1783,7 +1785,7 @@ impl<'db> Type<'db> {
|
|||
///
|
||||
/// This method roughly performs the following steps:
|
||||
///
|
||||
/// - Look up the attribute `name` on the meta type of `self`. Call the result `meta_attr`.
|
||||
/// - Look up the attribute `name` on the meta-type of `self`. Call the result `meta_attr`.
|
||||
/// - Call `__get__` on the meta-type of `meta_attr`, if it exists. If the call succeeds,
|
||||
/// replace `meta_attr` with the result of the call. Also check if `meta_attr` is a *data*
|
||||
/// descriptor by testing if `__set__` or `__delete__` exist.
|
||||
|
@ -1832,7 +1834,7 @@ impl<'db> Type<'db> {
|
|||
}
|
||||
|
||||
// `meta_attr` is the return type of a data descriptor, but the attribute on the
|
||||
// meta type is possibly-unbound. This means that we "fall through" to the next
|
||||
// meta-type is possibly-unbound. This means that we "fall through" to the next
|
||||
// stage of the descriptor protocol and union with the fallback type.
|
||||
(
|
||||
Symbol::Type(meta_attr_ty, Boundness::PossiblyUnbound),
|
||||
|
@ -1873,7 +1875,7 @@ impl<'db> Type<'db> {
|
|||
)
|
||||
.with_qualifiers(meta_attr_qualifiers.union(fallback_qualifiers)),
|
||||
|
||||
// If the attribute is not found on the meta type, we simply return the fallback.
|
||||
// If the attribute is not found on the meta-type, we simply return the fallback.
|
||||
(Symbol::Unbound, _, fallback) => fallback.with_qualifiers(fallback_qualifiers),
|
||||
}
|
||||
}
|
||||
|
@ -2736,7 +2738,7 @@ impl<'db> Type<'db> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Look up a dunder method on the meta type of `self` and call it.
|
||||
/// Look up a dunder method on the meta-type of `self` and call it.
|
||||
///
|
||||
/// Returns an `Err` if the dunder method can't be called,
|
||||
/// or the given arguments are not valid.
|
||||
|
@ -3163,7 +3165,7 @@ impl<'db> Type<'db> {
|
|||
KnownClass::WrapperDescriptorType.to_class_literal(db)
|
||||
}
|
||||
Type::Callable(CallableType::General(_)) => {
|
||||
// TODO: Get the meta type
|
||||
// TODO: Get the meta-type
|
||||
todo_type!(".to_meta_type() for general callable type")
|
||||
}
|
||||
Type::ModuleLiteral(_) => KnownClass::ModuleType.to_class_literal(db),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue