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 support for detecting properties that represent synchronous equivalents of asynq methods #493

Merged
merged 1 commit into from
Mar 7, 2022
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
2 changes: 2 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

- Remove support for detecting properties that represent
synchronous equivalents of asynq methods (#493)
- Enable exhaustive checking of enums and booleans (#492)
- Fix type narrowing in else branch if constraint is stored in a
variable (#491)
Expand Down
41 changes: 0 additions & 41 deletions pyanalyze/asynq_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
from .functions import AsyncFunctionKind
from .options import Options, PyObjectSequenceOption, StringSequenceOption
from .safe import safe_getattr, safe_hasattr
from .stacked_scopes import Composite
from .value import AnnotatedValue, Value, KnownValue, TypedValue, UnboundMethodValue


Expand Down Expand Up @@ -121,46 +120,6 @@ def check_call(self, value: Value, node: ast.Call) -> None:
replacement_node=replacement_node,
)

def record_attribute_access(
self, root_value: Value, attr_name: str, node: ast.Attribute
) -> None:
"""Records that the given attribute of root_value was accessed."""
if isinstance(root_value, TypedValue):
if hasattr(root_value.typ, attr_name) and callable(
getattr(root_value.typ, attr_name)
):
return
if self.should_perform_async_checks():
self._check_attribute_access_in_async(root_value, attr_name, node)

def _check_attribute_access_in_async(
self, root_value: Value, attr_name: str, node: ast.Attribute
) -> None:
if isinstance(root_value, TypedValue):
if not (
hasattr(root_value.typ, attr_name)
and isinstance(getattr(root_value.typ, attr_name), property)
):
return
async_names = ("get_" + attr_name, "is_" + attr_name)
for async_name in async_names:
if hasattr(root_value.typ, async_name) and asynq.is_async_fn(
getattr(root_value.typ, async_name)
):
replacement_call = _stringify_async_fn(
UnboundMethodValue(async_name, Composite(root_value), "asynq")
)
method_node = ast.Attribute(value=node.value, attr=async_name)
func_node = ast.Attribute(value=method_node, attr="asynq")
kwargs = {"args": [], "keywords": []}
call_node = ast.Call(func=func_node, **kwargs)
replacement_node = ast.Yield(value=call_node)
self._show_impure_async_error(
node,
replacement_call=replacement_call,
replacement_node=replacement_node,
)

def should_perform_async_checks(self) -> bool:
if self.current_async_kind in (
AsyncFunctionKind.normal,
Expand Down
3 changes: 0 additions & 3 deletions pyanalyze/name_check_visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -4060,9 +4060,6 @@ def composite_from_attribute(self, node: ast.Attribute) -> Composite:
return Composite(self.being_assigned, composite, node)
elif self._is_read_ctx(node.ctx):
if self._is_checking():
self.asynq_checker.record_attribute_access(
root_composite.value, node.attr, node
)
if (
isinstance(root_composite.value, KnownValue)
and isinstance(root_composite.value.val, types.ModuleType)
Expand Down
22 changes: 0 additions & 22 deletions pyanalyze/test_asynq_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,16 +83,6 @@ def tree(self):
log = PropertyObject.async_staticmethod() # E: impure_async_call
return str(log)

@assert_passes()
def test_impure_async_property_access(self):
from pyanalyze.tests import PropertyObject
from asynq import asynq

@asynq()
def get_capybara(qid):
po = PropertyObject(qid)
return po.prop_with_get # E: impure_async_call

@assert_passes()
def test_async_property_access(self):
from pyanalyze.tests import PropertyObject
Expand Down Expand Up @@ -208,18 +198,6 @@ def tree(self):
z += self.render_stuff() # E: impure_async_call
return z

@assert_passes()
def test_impure_async_for_attributes(self):
from pyanalyze.tests import PropertyObject, CheckedForAsynq

class Capybara(CheckedForAsynq):
def init(self, qid):
self.qid = qid

def tree(self):
PropertyObject(self.qid).prop_with_get # E: impure_async_call
return []

@assert_passes()
def test_pure_async_for_attributes(self):
from asynq import asynq, result
Expand Down