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

Add typing to scope() #1170

Merged
merged 16 commits into from Sep 15, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 5 additions & 2 deletions astroid/nodes/node_classes.py
Expand Up @@ -40,7 +40,7 @@
import sys
import typing
from functools import lru_cache
from typing import Callable, Generator, Optional
from typing import TYPE_CHECKING, Callable, Generator, Optional

from astroid import decorators, mixins, util
from astroid.bases import Instance, _infer_stmts
Expand All @@ -61,6 +61,9 @@
else:
from typing_extensions import Literal

if TYPE_CHECKING:
from astroid.scoped_nodes import LocalsDictNodeNG
Pierre-Sassoulas marked this conversation as resolved.
Show resolved Hide resolved


def _is_const(value):
return isinstance(value, tuple(CONST_CLS))
Expand Down Expand Up @@ -2020,7 +2023,7 @@ def postinit(self, nodes: typing.List[NodeNG]) -> None:
"""
self.nodes = nodes

def scope(self):
def scope(self) -> Optional["LocalsDictNodeNG"]:
cdce8p marked this conversation as resolved.
Show resolved Hide resolved
cdce8p marked this conversation as resolved.
Show resolved Hide resolved
"""The first parent node defining a new scope.

:returns: The first parent scope node.
Expand Down
17 changes: 15 additions & 2 deletions astroid/nodes/node_ng.py
@@ -1,14 +1,27 @@
import pprint
import typing
from functools import singledispatch as _singledispatch
from typing import ClassVar, Iterator, Optional, Tuple, Type, TypeVar, Union, overload
from typing import (
TYPE_CHECKING,
ClassVar,
Iterator,
Optional,
Tuple,
Type,
TypeVar,
Union,
overload,
)

from astroid import decorators, util
from astroid.exceptions import AstroidError, InferenceError, UseInferenceDefault
from astroid.manager import AstroidManager
from astroid.nodes.as_string import AsStringVisitor
from astroid.nodes.const import OP_PRECEDENCE

if TYPE_CHECKING:
from astroid.scoped_nodes import LocalsDictNodeNG

# Types for 'NodeNG.nodes_of_class()'
T_Nodes = TypeVar("T_Nodes", bound="NodeNG")
T_Nodes2 = TypeVar("T_Nodes2", bound="NodeNG")
Expand Down Expand Up @@ -246,7 +259,7 @@ def frame(self):
"""
return self.parent.frame()

def scope(self):
def scope(self) -> Optional["LocalsDictNodeNG"]:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding LocalsDictNodeNG: I fear that at some point it will just create another circular dependency. Maybe we should start looking into Protocol classes for that 🤔 Haven't really done so myself, thus don't know for certain if it would work.

https://docs.python.org/3/library/typing.html#typing.Protocol

--
Another issue: If at some point some scoped node inherits from another mixin class (not LocalsDictNodeNG, this will break.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure? Doesn't using "Class" prevent circular dependency?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current code is fine. As you said, using a string as type annotation does prevent the circular dependency.
It's probably just that I'm not really a fan of the class name itself (LocalsDictNodeNG). Maybe that should be changed at some point 🤔

Anyway, let's leave it for now.

"""The first parent node defining a new scope.
cdce8p marked this conversation as resolved.
Show resolved Hide resolved

:returns: The first parent scope node.
Expand Down
7 changes: 5 additions & 2 deletions astroid/nodes/scoped_nodes.py
Expand Up @@ -43,7 +43,7 @@
import io
import itertools
import typing
from typing import List, Optional
from typing import List, Optional, TypeVar

from astroid import bases
from astroid import decorators as decorators_mod
Expand Down Expand Up @@ -77,6 +77,9 @@
{"classmethod", "staticmethod", "builtins.classmethod", "builtins.staticmethod"}
)

# # Type for 'LocalsDictNodeNG.scope()'
T_LocalsDictScope = TypeVar("T_LocalsDictScope", bound="LocalsDictNodeNG")
cdce8p marked this conversation as resolved.
Show resolved Hide resolved


def _c3_merge(sequences, cls, context):
"""Merges MROs in *sequences* to a single MRO using the C3 algorithm.
Expand Down Expand Up @@ -237,7 +240,7 @@ def frame(self):
"""
return self

def scope(self):
def scope(self: T_LocalsDictScope) -> T_LocalsDictScope:
"""The first parent node defining a new scope.

:returns: The first parent scope node.
Expand Down