def sniff_options(obj):
options = set()
# We walk the __wrapped__ chain to collect properties.
while True:
if getattr(obj, "__isabstractmethod__", False):
options.add("abstractmethod")
if isinstance(obj, classmethod):
options.add("classmethod")
if isinstance(obj, staticmethod):
options.add("staticmethod")
# if isinstance(obj, property):
# options.add("property")
# Only check for these if we haven't seen any of them yet:
if not (options & EXCLUSIVE_OPTIONS):
if inspect.iscoroutinefunction(obj):
options.add("async")
# in some versions of Python, isgeneratorfunction returns true for
# coroutines, so we use elif
elif inspect.isgeneratorfunction(obj):
options.add("for")
if isasyncgenfunction(obj):
options.add("async-for")
# Some heuristics to detect when something is a context manager
if getattr(obj, "__code__", None) in CM_CODES:
options.add("with")
if getattr(obj, "__returns_contextmanager__", False):
options.add("with")
if getattr(obj, "__returns_acontextmanager__", False):
options.add("async-with")
if hasattr(obj, "__wrapped__"):
obj = obj.__wrapped__
elif hasattr(obj, "__func__"): # for staticmethod & classmethod
obj = obj.__func__
else:
break
return options
评论列表
文章目录