Skip to content

Commit

Permalink
Remove support for detecting properties that represent synchronous eq…
Browse files Browse the repository at this point in the history
…uivalents of asynq methods (#493)
  • Loading branch information
JelleZijlstra committed Mar 7, 2022
1 parent fdeabd1 commit 2a25a69
Show file tree
Hide file tree
Showing 4 changed files with 2 additions and 66 deletions.
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

0 comments on commit 2a25a69

Please sign in to comment.