Commit 5d1155c0 authored by Florent Xicluna's avatar Florent Xicluna

Closes #13258: Use callable() built-in in the standard library.

parent f99e4b5d
...@@ -92,10 +92,6 @@ import textwrap as _textwrap ...@@ -92,10 +92,6 @@ import textwrap as _textwrap
from gettext import gettext as _, ngettext from gettext import gettext as _, ngettext
def _callable(obj):
return hasattr(obj, '__call__') or hasattr(obj, '__bases__')
SUPPRESS = '==SUPPRESS==' SUPPRESS = '==SUPPRESS=='
OPTIONAL = '?' OPTIONAL = '?'
...@@ -1286,13 +1282,13 @@ class _ActionsContainer(object): ...@@ -1286,13 +1282,13 @@ class _ActionsContainer(object):
# create the action object, and add it to the parser # create the action object, and add it to the parser
action_class = self._pop_action_class(kwargs) action_class = self._pop_action_class(kwargs)
if not _callable(action_class): if not callable(action_class):
raise ValueError('unknown action "%s"' % (action_class,)) raise ValueError('unknown action "%s"' % (action_class,))
action = action_class(**kwargs) action = action_class(**kwargs)
# raise an error if the action type is not callable # raise an error if the action type is not callable
type_func = self._registry_get('type', action.type, action.type) type_func = self._registry_get('type', action.type, action.type)
if not _callable(type_func): if not callable(type_func):
raise ValueError('%r is not callable' % (type_func,)) raise ValueError('%r is not callable' % (type_func,))
# raise an error if the metavar does not match the type # raise an error if the metavar does not match the type
...@@ -2240,7 +2236,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): ...@@ -2240,7 +2236,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer):
def _get_value(self, action, arg_string): def _get_value(self, action, arg_string):
type_func = self._registry_get('type', action.type, action.type) type_func = self._registry_get('type', action.type, action.type)
if not _callable(type_func): if not callable(type_func):
msg = _('%r is not callable') msg = _('%r is not callable')
raise ArgumentError(action, msg % type_func) raise ArgumentError(action, msg % type_func)
......
...@@ -10,7 +10,7 @@ __all__ = ["pickle", "constructor", ...@@ -10,7 +10,7 @@ __all__ = ["pickle", "constructor",
dispatch_table = {} dispatch_table = {}
def pickle(ob_type, pickle_function, constructor_ob=None): def pickle(ob_type, pickle_function, constructor_ob=None):
if not hasattr(pickle_function, '__call__'): if not callable(pickle_function):
raise TypeError("reduction functions must be callable") raise TypeError("reduction functions must be callable")
dispatch_table[ob_type] = pickle_function dispatch_table[ob_type] = pickle_function
...@@ -20,7 +20,7 @@ def pickle(ob_type, pickle_function, constructor_ob=None): ...@@ -20,7 +20,7 @@ def pickle(ob_type, pickle_function, constructor_ob=None):
constructor(constructor_ob) constructor(constructor_ob)
def constructor(object): def constructor(object):
if not hasattr(object, '__call__'): if not callable(object):
raise TypeError("constructors must be callable") raise TypeError("constructors must be callable")
# Example: provide pickling support for complex numbers. # Example: provide pickling support for complex numbers.
......
...@@ -537,7 +537,7 @@ Common commands: (see '--help-commands' for more) ...@@ -537,7 +537,7 @@ Common commands: (see '--help-commands' for more)
for (help_option, short, desc, func) in cmd_class.help_options: for (help_option, short, desc, func) in cmd_class.help_options:
if hasattr(opts, parser.get_attr_name(help_option)): if hasattr(opts, parser.get_attr_name(help_option)):
help_option_found=1 help_option_found=1
if hasattr(func, '__call__'): if callable(func):
func() func()
else: else:
raise DistutilsClassError( raise DistutilsClassError(
......
...@@ -120,12 +120,11 @@ def search_function(encoding): ...@@ -120,12 +120,11 @@ def search_function(encoding):
if not 4 <= len(entry) <= 7: if not 4 <= len(entry) <= 7:
raise CodecRegistryError('module "%s" (%s) failed to register' raise CodecRegistryError('module "%s" (%s) failed to register'
% (mod.__name__, mod.__file__)) % (mod.__name__, mod.__file__))
if not hasattr(entry[0], '__call__') or \ if not callable(entry[0]) or not callable(entry[1]) or \
not hasattr(entry[1], '__call__') or \ (entry[2] is not None and not callable(entry[2])) or \
(entry[2] is not None and not hasattr(entry[2], '__call__')) or \ (entry[3] is not None and not callable(entry[3])) or \
(entry[3] is not None and not hasattr(entry[3], '__call__')) or \ (len(entry) > 4 and entry[4] is not None and not callable(entry[4])) or \
(len(entry) > 4 and entry[4] is not None and not hasattr(entry[4], '__call__')) or \ (len(entry) > 5 and entry[5] is not None and not callable(entry[5])):
(len(entry) > 5 and entry[5] is not None and not hasattr(entry[5], '__call__')):
raise CodecRegistryError('incompatible codecs in module "%s" (%s)' raise CodecRegistryError('incompatible codecs in module "%s" (%s)'
% (mod.__name__, mod.__file__)) % (mod.__name__, mod.__file__))
if len(entry)<7 or entry[6] is None: if len(entry)<7 or entry[6] is None:
......
...@@ -225,10 +225,11 @@ class FileInput: ...@@ -225,10 +225,11 @@ class FileInput:
raise ValueError("FileInput opening mode must be one of " raise ValueError("FileInput opening mode must be one of "
"'r', 'rU', 'U' and 'rb'") "'r', 'rU', 'U' and 'rb'")
self._mode = mode self._mode = mode
if inplace and openhook: if openhook:
raise ValueError("FileInput cannot use an opening hook in inplace mode") if inplace:
elif openhook and not hasattr(openhook, '__call__'): raise ValueError("FileInput cannot use an opening hook in inplace mode")
raise ValueError("FileInput openhook must be callable") if not callable(openhook):
raise ValueError("FileInput openhook must be callable")
self._openhook = openhook self._openhook = openhook
def __del__(self): def __del__(self):
......
...@@ -39,7 +39,7 @@ class HMAC: ...@@ -39,7 +39,7 @@ class HMAC:
import hashlib import hashlib
digestmod = hashlib.md5 digestmod = hashlib.md5
if hasattr(digestmod, '__call__'): if callable(digestmod):
self.digest_cons = digestmod self.digest_cons = digestmod
else: else:
self.digest_cons = lambda d=b'': digestmod.new(d) self.digest_cons = lambda d=b'': digestmod.new(d)
......
...@@ -570,7 +570,7 @@ def _getmethods(obj, methods): ...@@ -570,7 +570,7 @@ def _getmethods(obj, methods):
# Adds names to dictionary argument 'methods' # Adds names to dictionary argument 'methods'
for name in dir(obj): for name in dir(obj):
attr = getattr(obj, name) attr = getattr(obj, name)
if hasattr(attr, '__call__'): if callable(attr):
methods[name] = 1 methods[name] = 1
if isinstance(obj, type): if isinstance(obj, type):
for super in obj.__bases__: for super in obj.__bases__:
...@@ -579,7 +579,7 @@ def _getmethods(obj, methods): ...@@ -579,7 +579,7 @@ def _getmethods(obj, methods):
def _getattributes(obj, attributes): def _getattributes(obj, attributes):
for name in dir(obj): for name in dir(obj):
attr = getattr(obj, name) attr = getattr(obj, name)
if not hasattr(attr, '__call__'): if not callable(attr):
attributes[name] = 1 attributes[name] = 1
class MethodProxy(object): class MethodProxy(object):
......
...@@ -471,7 +471,7 @@ class BaseConfigurator(object): ...@@ -471,7 +471,7 @@ class BaseConfigurator(object):
def configure_custom(self, config): def configure_custom(self, config):
"""Configure an object with a user-supplied factory.""" """Configure an object with a user-supplied factory."""
c = config.pop('()') c = config.pop('()')
if not hasattr(c, '__call__'): if not callable(c):
c = self.resolve(c) c = self.resolve(c)
props = config.pop('.', None) props = config.pop('.', None)
# Check for valid identifiers # Check for valid identifiers
...@@ -690,7 +690,7 @@ class DictConfigurator(BaseConfigurator): ...@@ -690,7 +690,7 @@ class DictConfigurator(BaseConfigurator):
filters = config.pop('filters', None) filters = config.pop('filters', None)
if '()' in config: if '()' in config:
c = config.pop('()') c = config.pop('()')
if not hasattr(c, '__call__') and hasattr(types, 'ClassType') and type(c) != types.ClassType: if not callable(c):
c = self.resolve(c) c = self.resolve(c)
factory = c factory = c
else: else:
......
...@@ -134,7 +134,7 @@ def all_methods(obj): ...@@ -134,7 +134,7 @@ def all_methods(obj):
temp = [] temp = []
for name in dir(obj): for name in dir(obj):
func = getattr(obj, name) func = getattr(obj, name)
if hasattr(func, '__call__'): if callable(func):
temp.append(name) temp.append(name)
return temp return temp
...@@ -510,7 +510,7 @@ class BaseManager(object): ...@@ -510,7 +510,7 @@ class BaseManager(object):
''' '''
assert self._state.value == State.INITIAL assert self._state.value == State.INITIAL
if initializer is not None and not hasattr(initializer, '__call__'): if initializer is not None and not callable(initializer):
raise TypeError('initializer must be a callable') raise TypeError('initializer must be a callable')
# pipe over which we will retrieve address of server # pipe over which we will retrieve address of server
......
...@@ -151,7 +151,7 @@ class Pool(object): ...@@ -151,7 +151,7 @@ class Pool(object):
if processes < 1: if processes < 1:
raise ValueError("Number of processes must be at least 1") raise ValueError("Number of processes must be at least 1")
if initializer is not None and not hasattr(initializer, '__call__'): if initializer is not None and not callable(initializer):
raise TypeError('initializer must be a callable') raise TypeError('initializer must be a callable')
self._processes = processes self._processes = processes
......
...@@ -705,7 +705,7 @@ class Option: ...@@ -705,7 +705,7 @@ class Option:
def _check_callback(self): def _check_callback(self):
if self.action == "callback": if self.action == "callback":
if not hasattr(self.callback, '__call__'): if not callable(self.callback):
raise OptionError( raise OptionError(
"callback not callable: %r" % self.callback, self) "callback not callable: %r" % self.callback, self)
if (self.callback_args is not None and if (self.callback_args is not None and
......
...@@ -364,7 +364,7 @@ class _Pickler: ...@@ -364,7 +364,7 @@ class _Pickler:
raise PicklingError("args from save_reduce() should be a tuple") raise PicklingError("args from save_reduce() should be a tuple")
# Assert that func is callable # Assert that func is callable
if not hasattr(func, '__call__'): if not callable(func):
raise PicklingError("func from save_reduce() should be callable") raise PicklingError("func from save_reduce() should be callable")
save = self.save save = self.save
......
...@@ -775,7 +775,7 @@ class HTMLDoc(Doc): ...@@ -775,7 +775,7 @@ class HTMLDoc(Doc):
push(msg) push(msg)
for name, kind, homecls, value in ok: for name, kind, homecls, value in ok:
base = self.docother(getattr(object, name), name, mod) base = self.docother(getattr(object, name), name, mod)
if hasattr(value, '__call__') or inspect.isdatadescriptor(value): if callable(value) or inspect.isdatadescriptor(value):
doc = getattr(value, "__doc__", None) doc = getattr(value, "__doc__", None)
else: else:
doc = None doc = None
...@@ -1199,7 +1199,7 @@ location listed above. ...@@ -1199,7 +1199,7 @@ location listed above.
hr.maybe() hr.maybe()
push(msg) push(msg)
for name, kind, homecls, value in ok: for name, kind, homecls, value in ok:
if hasattr(value, '__call__') or inspect.isdatadescriptor(value): if callable(value) or inspect.isdatadescriptor(value):
doc = getdoc(value) doc = getdoc(value)
else: else:
doc = None doc = None
......
...@@ -326,7 +326,7 @@ class Scanner: ...@@ -326,7 +326,7 @@ class Scanner:
if i == j: if i == j:
break break
action = self.lexicon[m.lastindex-1][1] action = self.lexicon[m.lastindex-1][1]
if hasattr(action, "__call__"): if callable(action):
self.match = m self.match = m
action = action(self, m.group()) action = action(self, m.group())
if action is not None: if action is not None:
......
...@@ -87,7 +87,7 @@ class Completer: ...@@ -87,7 +87,7 @@ class Completer:
return None return None
def _callable_postfix(self, val, word): def _callable_postfix(self, val, word):
if hasattr(val, '__call__'): if callable(val):
word = word + "(" word = word + "("
return word return word
......
...@@ -523,7 +523,7 @@ def register_archive_format(name, function, extra_args=None, description=''): ...@@ -523,7 +523,7 @@ def register_archive_format(name, function, extra_args=None, description=''):
""" """
if extra_args is None: if extra_args is None:
extra_args = [] extra_args = []
if not isinstance(function, collections.Callable): if not callable(function):
raise TypeError('The %s object is not callable' % function) raise TypeError('The %s object is not callable' % function)
if not isinstance(extra_args, (tuple, list)): if not isinstance(extra_args, (tuple, list)):
raise TypeError('extra_args needs to be a sequence') raise TypeError('extra_args needs to be a sequence')
...@@ -616,7 +616,7 @@ def _check_unpack_options(extensions, function, extra_args): ...@@ -616,7 +616,7 @@ def _check_unpack_options(extensions, function, extra_args):
raise RegistryError(msg % (extension, raise RegistryError(msg % (extension,
existing_extensions[extension])) existing_extensions[extension]))
if not isinstance(function, collections.Callable): if not callable(function):
raise TypeError('The registered function must be a callable') raise TypeError('The registered function must be a callable')
......
...@@ -4,7 +4,6 @@ import textwrap ...@@ -4,7 +4,6 @@ import textwrap
import unittest import unittest
import functools import functools
import contextlib import contextlib
import collections
from test import support from test import support
from nntplib import NNTP, GroupInfo, _have_ssl from nntplib import NNTP, GroupInfo, _have_ssl
import nntplib import nntplib
...@@ -246,7 +245,7 @@ class NetworkedNNTPTestsMixin: ...@@ -246,7 +245,7 @@ class NetworkedNNTPTestsMixin:
if not name.startswith('test_'): if not name.startswith('test_'):
continue continue
meth = getattr(cls, name) meth = getattr(cls, name)
if not isinstance(meth, collections.Callable): if not callable(meth):
continue continue
# Need to use a closure so that meth remains bound to its current # Need to use a closure so that meth remains bound to its current
# value # value
......
...@@ -127,7 +127,7 @@ class Timer: ...@@ -127,7 +127,7 @@ class Timer:
if isinstance(setup, str): if isinstance(setup, str):
setup = reindent(setup, 4) setup = reindent(setup, 4)
src = template % {'stmt': stmt, 'setup': setup} src = template % {'stmt': stmt, 'setup': setup}
elif hasattr(setup, '__call__'): elif callable(setup):
src = template % {'stmt': stmt, 'setup': '_setup()'} src = template % {'stmt': stmt, 'setup': '_setup()'}
ns['_setup'] = setup ns['_setup'] = setup
else: else:
...@@ -136,13 +136,13 @@ class Timer: ...@@ -136,13 +136,13 @@ class Timer:
code = compile(src, dummy_src_name, "exec") code = compile(src, dummy_src_name, "exec")
exec(code, globals(), ns) exec(code, globals(), ns)
self.inner = ns["inner"] self.inner = ns["inner"]
elif hasattr(stmt, '__call__'): elif callable(stmt):
self.src = None self.src = None
if isinstance(setup, str): if isinstance(setup, str):
_setup = setup _setup = setup
def setup(): def setup():
exec(_setup, globals(), ns) exec(_setup, globals(), ns)
elif not hasattr(setup, '__call__'): elif not callable(setup):
raise ValueError("setup is neither a string nor callable") raise ValueError("setup is neither a string nor callable")
self.inner = _template_func(setup, stmt) self.inner = _template_func(setup, stmt)
else: else:
......
...@@ -1039,7 +1039,7 @@ class Misc: ...@@ -1039,7 +1039,7 @@ class Misc:
for k, v in cnf.items(): for k, v in cnf.items():
if v is not None: if v is not None:
if k[-1] == '_': k = k[:-1] if k[-1] == '_': k = k[:-1]
if hasattr(v, '__call__'): if callable(v):
v = self._register(v) v = self._register(v)
elif isinstance(v, (tuple, list)): elif isinstance(v, (tuple, list)):
nv = [] nv = []
...@@ -1608,7 +1608,7 @@ class Wm: ...@@ -1608,7 +1608,7 @@ class Wm:
"""Bind function FUNC to command NAME for this widget. """Bind function FUNC to command NAME for this widget.
Return the function bound to NAME if None is given. NAME could be Return the function bound to NAME if None is given. NAME could be
e.g. "WM_SAVE_YOURSELF" or "WM_DELETE_WINDOW".""" e.g. "WM_SAVE_YOURSELF" or "WM_DELETE_WINDOW"."""
if hasattr(func, '__call__'): if callable(func):
command = self._register(func) command = self._register(func)
else: else:
command = func command = func
...@@ -3178,7 +3178,7 @@ class Image: ...@@ -3178,7 +3178,7 @@ class Image:
elif kw: cnf = kw elif kw: cnf = kw
options = () options = ()
for k, v in cnf.items(): for k, v in cnf.items():
if hasattr(v, '__call__'): if callable(v):
v = self._register(v) v = self._register(v)
options = options + ('-'+k, v) options = options + ('-'+k, v)
self.tk.call(('image', 'create', imgtype, name,) + options) self.tk.call(('image', 'create', imgtype, name,) + options)
...@@ -3201,7 +3201,7 @@ class Image: ...@@ -3201,7 +3201,7 @@ class Image:
for k, v in _cnfmerge(kw).items(): for k, v in _cnfmerge(kw).items():
if v is not None: if v is not None:
if k[-1] == '_': k = k[:-1] if k[-1] == '_': k = k[:-1]
if hasattr(v, '__call__'): if callable(v):
v = self._register(v) v = self._register(v)
res = res + ('-'+k, v) res = res + ('-'+k, v)
self.tk.call((self.name, 'config') + res) self.tk.call((self.name, 'config') + res)
......
...@@ -405,7 +405,7 @@ class TixWidget(tkinter.Widget): ...@@ -405,7 +405,7 @@ class TixWidget(tkinter.Widget):
elif kw: cnf = kw elif kw: cnf = kw
options = () options = ()
for k, v in cnf.items(): for k, v in cnf.items():
if hasattr(v, '__call__'): if callable(v):
v = self._register(v) v = self._register(v)
options = options + ('-'+k, v) options = options + ('-'+k, v)
return master.tk.call(('image', 'create', imgtype,) + options) return master.tk.call(('image', 'create', imgtype,) + options)
......
...@@ -113,7 +113,7 @@ class TestLoader(object): ...@@ -113,7 +113,7 @@ class TestLoader(object):
return self.suiteClass([inst]) return self.suiteClass([inst])
elif isinstance(obj, suite.TestSuite): elif isinstance(obj, suite.TestSuite):
return obj return obj
if hasattr(obj, '__call__'): if callable(obj):
test = obj() test = obj()
if isinstance(test, suite.TestSuite): if isinstance(test, suite.TestSuite):
return test return test
...@@ -138,7 +138,7 @@ class TestLoader(object): ...@@ -138,7 +138,7 @@ class TestLoader(object):
def isTestMethod(attrname, testCaseClass=testCaseClass, def isTestMethod(attrname, testCaseClass=testCaseClass,
prefix=self.testMethodPrefix): prefix=self.testMethodPrefix):
return attrname.startswith(prefix) and \ return attrname.startswith(prefix) and \
hasattr(getattr(testCaseClass, attrname), '__call__') callable(getattr(testCaseClass, attrname))
testFnNames = testFnNames = list(filter(isTestMethod, testFnNames = testFnNames = list(filter(isTestMethod,
dir(testCaseClass))) dir(testCaseClass)))
if self.sortTestMethodsUsing: if self.sortTestMethodsUsing:
......
...@@ -42,7 +42,7 @@ class BaseTestSuite(object): ...@@ -42,7 +42,7 @@ class BaseTestSuite(object):
def addTest(self, test): def addTest(self, test):
# sanity checks # sanity checks
if not hasattr(test, '__call__'): if not callable(test):
raise TypeError("{} is not callable".format(repr(test))) raise TypeError("{} is not callable".format(repr(test)))
if isinstance(test, type) and issubclass(test, if isinstance(test, type) and issubclass(test,
(case.TestCase, TestSuite)): (case.TestCase, TestSuite)):
......
...@@ -259,7 +259,7 @@ def warn_explicit(message, category, filename, lineno, ...@@ -259,7 +259,7 @@ def warn_explicit(message, category, filename, lineno,
raise RuntimeError( raise RuntimeError(
"Unrecognized action (%r) in warnings.filters:\n %s" % "Unrecognized action (%r) in warnings.filters:\n %s" %
(action, item)) (action, item))
if not hasattr(showwarning, "__call__"): if not callable(showwarning):
raise TypeError("warnings.showwarning() must be set to a " raise TypeError("warnings.showwarning() must be set to a "
"function or method") "function or method")
# Print message and context # Print message and context
......
...@@ -149,7 +149,7 @@ def list_public_methods(obj): ...@@ -149,7 +149,7 @@ def list_public_methods(obj):
return [member for member in dir(obj) return [member for member in dir(obj)
if not member.startswith('_') and if not member.startswith('_') and
hasattr(getattr(obj, member), '__call__')] callable(getattr(obj, member))]
class SimpleXMLRPCDispatcher: class SimpleXMLRPCDispatcher:
"""Mix-in class that dispatches XML-RPC requests. """Mix-in class that dispatches XML-RPC requests.
......
...@@ -61,6 +61,8 @@ Core and Builtins ...@@ -61,6 +61,8 @@ Core and Builtins
Library Library
------- -------
- Issue #13258: Use callable() built-in in the standard library.
- Issue #13273: fix a bug that prevented HTMLParser to properly detect some - Issue #13273: fix a bug that prevented HTMLParser to properly detect some
tags when strict=False. tags when strict=False.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment