Exemple #1
0
 def is_async_fn(self, obj):
     if hasattr(obj, "__self__"):
         if isinstance(
             obj.__self__, asynq.decorators.AsyncDecorator
         ) or asynq.is_async_fn(obj.__self__):
             return True
     return asynq.is_async_fn(obj)
Exemple #2
0
def is_impure_async_fn(value):
    """Returns whether the given Value is an impure async call.

    This can be used to detect places where async functions are called synchronously.

    """
    if isinstance(value, KnownValue):
        return asynq.is_async_fn(value.val) and not asynq.is_pure_async_fn(value.val)
    elif isinstance(value, UnboundMethodValue):
        method = value.get_method()
        if method is None:
            return False
        return asynq.is_async_fn(method) and not asynq.is_pure_async_fn(method)
    return False
Exemple #3
0
 def _should_record_usage(self, value, include_modules=False):
     # also include async functions, but don't call is_async_fn on modules because it can fail
     if inspect.isfunction(value) or (not inspect.ismodule(value)
                                      and asynq.is_async_fn(value)):
         registered = self.config.registered_values()
         try:
             return value not in registered
         except TypeError:
             return False  # mock.call can get here
     elif inspect.isclass(value):
         # can't reliably detect usage of classes with a metaclass
         metaclass = type(value)
         try:
             is_allowed = metaclass in self.config.ALLOWED_METACLASSES
         except TypeError:
             # apparently mock objects have a dictionary as their metaclass
             is_allowed = False
         if not is_allowed:
             return False
         # controllers are called directly by Pylons
         if any(
                 issubclass(value, cls)
                 for cls in self.config.USED_BASE_CLASSES):
             return False
         return value not in self.config.registered_values()
     elif include_modules and inspect.ismodule(value):
         return True
     else:
         return False
Exemple #4
0
 def _check_attribute_access_in_async(self, root_value, attr_name, node):
     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, root_value.typ, "asynq")
                 )
                 method_node = ast.Attribute(value=node.value, attr=async_name)
                 func_node = ast.Attribute(value=method_node, attr="asynq")
                 kwargs = {"args": [], "keywords": []}
                 if six.PY2:
                     kwargs["starargs"] = kwargs["kwargs"] = None
                 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,
                 )
Exemple #5
0
def _unwrap_value_from_typed(result: Value, typ: type,
                             ctx: AttrContext) -> Value:
    if not isinstance(result, KnownValue):
        return result
    cls_val = result.val
    if isinstance(cls_val, property):
        typ = ctx.get_property_type_from_config(cls_val)
        if typ is not UNRESOLVED_VALUE:
            return typ
        return ctx.get_property_type_from_argspec(cls_val)
    elif qcore.inspection.is_classmethod(cls_val):
        return KnownValue(cls_val)
    elif inspect.ismethod(cls_val):
        return UnboundMethodValue(ctx.attr, ctx.root_value)
    elif inspect.isfunction(cls_val):
        # either a staticmethod or an unbound method
        try:
            descriptor = inspect.getattr_static(typ, ctx.attr)
        except AttributeError:
            # probably a super call; assume unbound method
            if ctx.attr != "__new__":
                return UnboundMethodValue(ctx.attr, ctx.root_value)
            else:
                # __new__ is implicitly a staticmethod
                return KnownValue(cls_val)
        if isinstance(descriptor, staticmethod) or ctx.attr == "__new__":
            return KnownValue(cls_val)
        else:
            return UnboundMethodValue(ctx.attr, ctx.root_value)
    elif isinstance(cls_val, (MethodDescriptorType, SlotWrapperType)):
        # built-in method; e.g. scope_lib.tests.SimpleDatabox.get
        return UnboundMethodValue(ctx.attr, ctx.root_value)
    elif (_static_hasattr(cls_val, "decorator")
          and _static_hasattr(cls_val, "instance")
          and not isinstance(cls_val.instance, type)):
        # non-static method
        return UnboundMethodValue(ctx.attr, ctx.root_value)
    elif asynq.is_async_fn(cls_val):
        # static or class method
        return KnownValue(cls_val)
    elif _static_hasattr(cls_val, "__get__"):
        return ctx.get_property_type_from_config(cls_val)
    elif ctx.should_ignore_class_attribute(cls_val):
        return UNRESOLVED_VALUE
    else:
        return KnownValue(cls_val)
Exemple #6
0
 def _should_record_as_unused(self, module, attr, value):
     if self.config.should_ignore_unused(module, attr, value):
         return False
     # TODO: remove most of the below and just rely on @used and
     # should_ignore_unused()
     # also include async functions, but don't call is_async_fn on modules because it can fail
     if inspect.isfunction(value) or (
         not inspect.ismodule(value) and asynq.is_async_fn(value)
     ):
         registered = self.config.registered_values()
         try:
             if value in registered:
                 return False
         except TypeError:
             return False  # mock.call can get here
     elif inspect.isclass(value):
         # can't reliably detect usage of classes with a metaclass
         metaclass = type(value)
         try:
             is_allowed = metaclass in self.config.ALLOWED_METACLASSES
         except TypeError:
             # apparently mock objects have a dictionary as their metaclass
             is_allowed = False
         if not is_allowed:
             return False
         # controllers are called directly by Pylons
         if any(issubclass(value, cls) for cls in self.config.USED_BASE_CLASSES):
             return False
         if value in self.config.registered_values():
             return False
     elif inspect.ismodule(value):
         # test modules will usually show up as unused
         if value.__name__.split(".")[-1].startswith("test"):
             return False
         # if it was ever import *ed from, don't treat it as unused
         if value in self.import_stars:
             return False
     try:
         # __future__ imports are usually unused
         return value not in _used_objects and not isinstance(
             value, __future__._Feature
         )
     except Exception:
         return True
Exemple #7
0
def _unwrap_value_from_subclass(result: Value, ctx: AttrContext) -> Value:
    if not isinstance(result, KnownValue):
        return result
    cls_val = result.val
    if (qcore.inspection.is_classmethod(cls_val) or inspect.ismethod(cls_val)
            or inspect.isfunction(cls_val)
            or isinstance(cls_val,
                          (MethodDescriptorType, SlotWrapperType)) or (
                              # non-static method
                              _static_hasattr(cls_val, "decorator")
                              and _static_hasattr(cls_val, "instance")
                              and not isinstance(cls_val.instance, type))
            or asynq.is_async_fn(cls_val)):
        # static or class method
        return KnownValue(cls_val)
    elif _static_hasattr(cls_val, "__get__"):
        return UNRESOLVED_VALUE  # can't figure out what this will return
    elif ctx.should_ignore_class_attribute(cls_val):
        return UNRESOLVED_VALUE
    else:
        return KnownValue(cls_val)
Exemple #8
0
def is_dot_asynq_function(obj: Any) -> bool:
    """Returns whether obj is the .asynq member on an async function."""
    try:
        self_obj = obj.__self__
    except AttributeError:
        # the attribute doesn't exist
        return False
    except Exception:
        # The object has a buggy __getattr__ that threw an error. Just ignore it.
        return False
    if qcore.inspection.is_classmethod(obj):
        return False
    if obj is self_obj:
        return False
    try:
        is_async_fn = asynq.is_async_fn(self_obj)
    except Exception:
        # The object may have a buggy __getattr__. Ignore it. This happens with
        # pylons request objects.
        return False
    if not is_async_fn:
        return False

    return getattr(obj, "__name__", None) in ("async", "asynq")