docs: def _is_propertyable(
      names,  # type: List[str]
      attrs,  # type: Dict[str, Any]
      annotations,  # type: Dict[str, type]
      attr,  # Dict[str, Any]
  ):
      # type: (...) -> bool
      """Determine if an attribute can be replaced with a property.
  
      Args:
          names: The complete list of all attribute names for the class.
          attrs: The attribute dict returned by __prepare__.
          annotations: A mapping of all defined annotations for the class.
          attr: The attribute to test.
  
      Returns:
          True if the attribute can be replaced with a property; else False.
      """
      return (
          attr in annotations
          and not attr.startswith("_")
          and not attr.isupper()
          and "__{}".format(attr) not in names
          and not isinstance(getattr(attrs, attr, None), types.MethodType)
      )