Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove newstyle variable given old-style class support should be removed #2561

Merged
merged 2 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions astroid/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,10 @@ def _object_type(

for inferred in node.infer(context=context):
if isinstance(inferred, scoped_nodes.ClassDef):
if inferred.newstyle:
metaclass = inferred.metaclass(context=context)
if metaclass:
yield metaclass
continue
metaclass = inferred.metaclass(context=context)
if metaclass:
yield metaclass
continue
yield builtins.getattr("type")[0]
elif isinstance(
inferred,
Expand Down Expand Up @@ -194,8 +193,6 @@ def _type_check(type1, type2) -> bool:
if not all(map(has_known_bases, (type1, type2))):
raise _NonDeducibleTypeHierarchy

if not all([type1.newstyle, type2.newstyle]):
return False
try:
return type1 in type2.mro()[:-1]
except MroError as e:
Expand Down
10 changes: 0 additions & 10 deletions astroid/interpreter/objectmodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -514,19 +514,13 @@ def attr___doc__(self):

@property
def attr___mro__(self):
if not self._instance.newstyle:
raise AttributeInferenceError(target=self._instance, attribute="__mro__")

mro = self._instance.mro()
obj = node_classes.Tuple(parent=self._instance)
obj.postinit(mro)
return obj

@property
def attr_mro(self):
if not self._instance.newstyle:
raise AttributeInferenceError(target=self._instance, attribute="mro")

other_self = self

# Cls.mro is a method and we need to return one in order to have a proper inference.
Expand Down Expand Up @@ -565,10 +559,6 @@ def attr___subclasses__(self):
This looks only in the current module for retrieving the subclasses,
thus it might miss a couple of them.
"""
if not self._instance.newstyle:
raise AttributeInferenceError(
target=self._instance, attribute="__subclasses__"
)

qname = self._instance.qname()
root = self._instance.root()
Expand Down
67 changes: 8 additions & 59 deletions astroid/nodes/scoped_nodes/scoped_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1882,8 +1882,7 @@ def my_meth(self, arg):
),
)
_other_fields = ("name", "is_dataclass", "position")
_other_other_fields = ("locals", "_newstyle")
_newstyle: bool | None = None
_other_other_fields = "locals"

def __init__(
self,
Expand Down Expand Up @@ -1983,36 +1982,11 @@ def postinit(
self.bases = bases
self.body = body
self.decorators = decorators
self._newstyle = newstyle
self._metaclass = metaclass
self.position = position
self.doc_node = doc_node
self.type_params = type_params or []

def _newstyle_impl(self, context: InferenceContext | None = None):
if context is None:
context = InferenceContext()
if self._newstyle is not None:
return self._newstyle
for base in self.ancestors(recurs=False, context=context):
if base._newstyle_impl(context):
self._newstyle = True
break
klass = self.declared_metaclass()
# could be any callable, we'd need to infer the result of klass(name,
# bases, dict). punt if it's not a class node.
if klass is not None and isinstance(klass, ClassDef):
self._newstyle = klass._newstyle_impl(context)
if self._newstyle is None:
self._newstyle = False
return self._newstyle

_newstyle = None
newstyle = property(
_newstyle_impl,
doc=("Whether this is a new style class or not\n\n" ":type: bool or None"),
)

@cached_property
def blockstart_tolineno(self):
"""The line on which the beginning of this block ends.
Expand All @@ -2033,14 +2007,12 @@ def block_range(self, lineno: int) -> tuple[int, int]:
"""
return self.fromlineno, self.tolineno

def pytype(self) -> Literal["builtins.type", "builtins.classobj"]:
def pytype(self) -> Literal["builtins.type"]:
"""Get the name of the type that this node represents.

:returns: The name of the type.
"""
if self.newstyle:
return "builtins.type"
return "builtins.classobj"
return "builtins.type"

def display_type(self) -> str:
"""A human readable type of this node.
Expand Down Expand Up @@ -2580,7 +2552,6 @@ def _valid_getattr(node):
try:
return _valid_getattr(self.getattr("__getattr__", context)[0])
except AttributeInferenceError:
# if self.newstyle: XXX cause an infinite recursion error
try:
getattribute = self.getattr("__getattribute__", context)[0]
return _valid_getattr(getattribute)
Expand Down Expand Up @@ -2667,16 +2638,12 @@ def mymethods(self):
def implicit_metaclass(self):
"""Get the implicit metaclass of the current class.

For newstyle classes, this will return an instance of builtins.type.
For oldstyle classes, it will simply return None, since there's
no implicit metaclass there.
This will return an instance of builtins.type.

:returns: The metaclass.
:rtype: builtins.type or None
:rtype: builtins.type
"""
if self.newstyle:
return builtin_lookup("type")[1][0]
return None
return builtin_lookup("type")[1][0]

def declared_metaclass(
self, context: InferenceContext | None = None
Expand Down Expand Up @@ -2799,10 +2766,6 @@ def _islots(self):
return None

def _slots(self):
if not self.newstyle:
raise NotImplementedError(
"The concept of slots is undefined for old-style classes."
)

slots = self._islots()
try:
Expand Down Expand Up @@ -2842,11 +2805,6 @@ def grouped_slots(
else:
yield None

if not self.newstyle:
raise NotImplementedError(
"The concept of slots is undefined for old-style classes."
)

try:
mro = self.mro()
except MroError as e:
Expand Down Expand Up @@ -2912,17 +2870,8 @@ def _compute_mro(self, context: InferenceContext | None = None):
if base is self:
continue

try:
mro = base._compute_mro(context=context)
bases_mro.append(mro)
except NotImplementedError:
# Some classes have in their ancestors both newstyle and
# old style classes. For these we can't retrieve the .mro,
# although in Python it's possible, since the class we are
# currently working is in fact new style.
# So, we fallback to ancestors here.
ancestors = list(base.ancestors(context=context))
bases_mro.append(ancestors)
mro = base._compute_mro(context=context)
bases_mro.append(mro)

unmerged_mro: list[list[ClassDef]] = [[self], *bases_mro, inferred_bases]
unmerged_mro = clean_duplicates_mro(unmerged_mro, self, context)
Expand Down
3 changes: 0 additions & 3 deletions astroid/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,6 @@ def super_mro(self):
super_=self,
)

if not mro_type.newstyle:
raise SuperError("Unable to call super on old-style classes.", super_=self)

mro = mro_type.mro()
if self.mro_pointer not in mro:
raise SuperError(
Expand Down
31 changes: 0 additions & 31 deletions tests/test_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -519,36 +519,6 @@ def test_object(self) -> None:
obj_ast = self.builder.inspect_build(object)
self.assertIn("__setattr__", obj_ast)

def test_newstyle_detection(self) -> None:
data = """
class A:
"old style"

class B(A):
"old style"

class C(object):
"new style"

class D(C):
"new style"

__metaclass__ = type

class E(A):
"old style"

class F:
"new style"
"""
mod_ast = builder.parse(data, __name__)
self.assertTrue(mod_ast["A"].newstyle)
self.assertTrue(mod_ast["B"].newstyle)
self.assertTrue(mod_ast["E"].newstyle)
self.assertTrue(mod_ast["C"].newstyle)
self.assertTrue(mod_ast["D"].newstyle)
self.assertTrue(mod_ast["F"].newstyle)

def test_globals(self) -> None:
data = """
CSTE = 1
Expand Down Expand Up @@ -833,7 +803,6 @@ def test_class_base_props(self) -> None:
self.assertEqual(klass.parent.frame(), module)
self.assertEqual(klass.root(), module)
self.assertEqual(klass.basenames, [])
self.assertTrue(klass.newstyle)

def test_class_locals(self) -> None:
"""Test the 'locals' dictionary of an astroid class."""
Expand Down
1 change: 0 additions & 1 deletion tests/test_python3.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,6 @@ class SubTest(Test): pass
)
)
klass = astroid["SubTest"]
self.assertTrue(klass.newstyle)
metaclass = klass.metaclass()
self.assertIsInstance(metaclass, nodes.ClassDef)
self.assertEqual(metaclass.name, "ABCMeta")
Expand Down
3 changes: 1 addition & 2 deletions tests/test_scoped_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1002,8 +1002,7 @@ def test_cls_special_attributes_1(self) -> None:
self.assertIsInstance(cls.getattr("__module__")[0], nodes.Const)
self.assertEqual(cls.getattr("__module__")[0].value, "data.module")
self.assertEqual(len(cls.getattr("__dict__")), 1)
if not cls.newstyle:
self.assertRaises(AttributeInferenceError, cls.getattr, "__mro__")

for cls in (nodes.List._proxied, nodes.Const(1)._proxied):
self.assertEqual(len(cls.getattr("__bases__")), 1)
self.assertEqual(len(cls.getattr("__name__")), 1)
Expand Down
Loading