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

wrap GeneratorModel methods into BoundMethod; remove redundant test #2584

Merged
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
4 changes: 4 additions & 0 deletions astroid/bases.py
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,10 @@ def __str__(self) -> str:
class AsyncGenerator(Generator):
"""Special node representing an async generator."""

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
AsyncGenerator.special_attributes = objectmodel.AsyncGeneratorModel()

def pytype(self) -> Literal["builtins.async_generator"]:
return "builtins.async_generator"

Expand Down
26 changes: 11 additions & 15 deletions astroid/interpreter/objectmodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -695,19 +695,19 @@ def attr___self__(self):


class GeneratorModel(FunctionModel, ContextManagerModel):
def __new__(cls, *args, **kwargs):
def __init__(self):
# Append the values from the GeneratorType unto this object.
ret = super().__new__(cls, *args, **kwargs)
super().__init__()
generator = AstroidManager().builtins_module["generator"]
for name, values in generator.locals.items():
method = values[0]
if isinstance(method, nodes.FunctionDef):
method = bases.BoundMethod(method, _get_bound_node(self))

def patched(cls, meth=method):
return meth

setattr(type(ret), IMPL_PREFIX + name, property(patched))

return ret
setattr(type(self), IMPL_PREFIX + name, property(patched))

@property
def attr___name__(self):
Expand All @@ -724,24 +724,20 @@ def attr___doc__(self):


class AsyncGeneratorModel(GeneratorModel):
def __new__(cls, *args, **kwargs):
def __init__(self):
# Append the values from the AGeneratorType unto this object.
ret = super().__new__(cls, *args, **kwargs)
super().__init__()
astroid_builtins = AstroidManager().builtins_module
generator = astroid_builtins.get("async_generator")
if generator is None:
# Make it backward compatible.
generator = astroid_builtins.get("generator")

generator = astroid_builtins["async_generator"]
for name, values in generator.locals.items():
method = values[0]
if isinstance(method, nodes.FunctionDef):
method = bases.BoundMethod(method, _get_bound_node(self))

def patched(cls, meth=method):
return meth

setattr(type(ret), IMPL_PREFIX + name, property(patched))

return ret
setattr(type(self), IMPL_PREFIX + name, property(patched))


class InstanceModel(ObjectModel):
Expand Down
6 changes: 2 additions & 4 deletions astroid/raw_building.py
Original file line number Diff line number Diff line change
Expand Up @@ -627,9 +627,8 @@ def _astroid_bootstrapping() -> None:
col_offset=0,
end_lineno=0,
end_col_offset=0,
parent=nodes.Unknown(),
parent=astroid_builtin,
)
_GeneratorType.parent = astroid_builtin
generator_doc_node = (
nodes.Const(value=types.GeneratorType.__doc__)
if types.GeneratorType.__doc__
Expand All @@ -651,9 +650,8 @@ def _astroid_bootstrapping() -> None:
col_offset=0,
end_lineno=0,
end_col_offset=0,
parent=nodes.Unknown(),
parent=astroid_builtin,
)
_AsyncGeneratorType.parent = astroid_builtin
async_generator_doc_node = (
nodes.Const(value=types.AsyncGeneratorType.__doc__)
if types.AsyncGeneratorType.__doc__
Expand Down
18 changes: 0 additions & 18 deletions tests/test_lookup.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,24 +322,6 @@ class _Inner:
self.assertEqual(len(name.lookup("x")[1]), 1, repr(name))
self.assertEqual(name.lookup("x")[1][0].lineno, 3, repr(name))

def test_generator_attributes(self) -> None:
tree = builder.parse(
"""
def count():
"test"
yield 0

iterer = count()
num = iterer.next()
"""
)
next_node = tree.body[2].value.func
gener = next_node.expr.inferred()[0]
self.assertIsInstance(gener.getattr("__next__")[0], nodes.FunctionDef)
self.assertIsInstance(gener.getattr("send")[0], nodes.FunctionDef)
self.assertIsInstance(gener.getattr("throw")[0], nodes.FunctionDef)
self.assertIsInstance(gener.getattr("close")[0], nodes.FunctionDef)

def test_explicit___name__(self) -> None:
code = """
class Pouet:
Expand Down
19 changes: 1 addition & 18 deletions tests/test_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1454,7 +1454,7 @@ def test(self):
assert bool(inferred.is_generator())


class AsyncGeneratorTest:
class AsyncGeneratorTest(unittest.TestCase):
def test_async_generator(self):
node = astroid.extract_node(
"""
Expand All @@ -1472,23 +1472,6 @@ async def a_iter(n):
assert inferred.pytype() == "builtins.async_generator"
assert inferred.display_type() == "AsyncGenerator"

def test_async_generator_is_generator_on_older_python(self):
node = astroid.extract_node(
"""
async def a_iter(n):
for i in range(1, n + 1):
yield i
await asyncio.sleep(1)
a_iter(2) #@
"""
)
inferred = next(node.infer())
assert isinstance(inferred, bases.Generator)
assert inferred.getattr("__iter__")
assert inferred.getattr("__next__")
assert inferred.pytype() == "builtins.generator"
assert inferred.display_type() == "Generator"


def test_f_string_correct_line_numbering() -> None:
"""Test that we generate correct line numbers for f-strings."""
Expand Down
Loading