mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-04-23 10:51:24 -07:00
When the same role is listed consecutively in a play, the previous role completion detection failed to mark it as complete as it only checked to see if the role changed. This patch addresses that by also keeping track of which task in the role we are on, so that even if the same role is encountered during later passes the task number will be less than or equal to the last noted task position. Related to #15409
579 lines
20 KiB
Python
579 lines
20 KiB
Python
"""Utilities for writing code that runs on Python 2 and 3"""
|
|
|
|
# Copyright (c) 2010-2013 Benjamin Peterson
|
|
#
|
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
# of this software and associated documentation files (the "Software"), to deal
|
|
# in the Software without restriction, including without limitation the rights
|
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
# copies of the Software, and to permit persons to whom the Software is
|
|
# furnished to do so, subject to the following conditions:
|
|
#
|
|
# The above copyright notice and this permission notice shall be included in all
|
|
# copies or substantial portions of the Software.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
# SOFTWARE.
|
|
|
|
import operator
|
|
import sys
|
|
import types
|
|
|
|
__author__ = "Benjamin Peterson <benjamin@python.org>"
|
|
__version__ = "1.4.1"
|
|
|
|
|
|
# Useful for very coarse version differentiation.
|
|
PY2 = sys.version_info[0] == 2
|
|
PY3 = sys.version_info[0] == 3
|
|
|
|
if PY3:
|
|
string_types = str,
|
|
integer_types = int,
|
|
class_types = type,
|
|
text_type = str
|
|
binary_type = bytes
|
|
cmp = lambda a, b: (a > b) - (a < b)
|
|
|
|
MAXSIZE = sys.maxsize
|
|
else:
|
|
string_types = basestring,
|
|
integer_types = (int, long)
|
|
class_types = (type, types.ClassType)
|
|
text_type = unicode
|
|
binary_type = str
|
|
cmp = cmp
|
|
|
|
if sys.platform.startswith("java"):
|
|
# Jython always uses 32 bits.
|
|
MAXSIZE = int((1 << 31) - 1)
|
|
else:
|
|
# It's possible to have sizeof(long) != sizeof(Py_ssize_t).
|
|
class X(object):
|
|
def __len__(self):
|
|
return 1 << 31
|
|
try:
|
|
len(X())
|
|
except OverflowError:
|
|
# 32-bit
|
|
MAXSIZE = int((1 << 31) - 1)
|
|
else:
|
|
# 64-bit
|
|
MAXSIZE = int((1 << 63) - 1)
|
|
del X
|
|
|
|
|
|
def _add_doc(func, doc):
|
|
"""Add documentation to a function."""
|
|
func.__doc__ = doc
|
|
|
|
|
|
def _import_module(name):
|
|
"""Import module, returning the module after the last dot."""
|
|
__import__(name)
|
|
return sys.modules[name]
|
|
|
|
|
|
class _LazyDescr(object):
|
|
|
|
def __init__(self, name):
|
|
self.name = name
|
|
|
|
def __get__(self, obj, tp):
|
|
result = self._resolve()
|
|
setattr(obj, self.name, result)
|
|
# This is a bit ugly, but it avoids running this again.
|
|
delattr(tp, self.name)
|
|
return result
|
|
|
|
|
|
class MovedModule(_LazyDescr):
|
|
|
|
def __init__(self, name, old, new=None):
|
|
super(MovedModule, self).__init__(name)
|
|
if PY3:
|
|
if new is None:
|
|
new = name
|
|
self.mod = new
|
|
else:
|
|
self.mod = old
|
|
|
|
def _resolve(self):
|
|
return _import_module(self.mod)
|
|
|
|
|
|
class MovedAttribute(_LazyDescr):
|
|
|
|
def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
|
|
super(MovedAttribute, self).__init__(name)
|
|
if PY3:
|
|
if new_mod is None:
|
|
new_mod = name
|
|
self.mod = new_mod
|
|
if new_attr is None:
|
|
if old_attr is None:
|
|
new_attr = name
|
|
else:
|
|
new_attr = old_attr
|
|
self.attr = new_attr
|
|
else:
|
|
self.mod = old_mod
|
|
if old_attr is None:
|
|
old_attr = name
|
|
self.attr = old_attr
|
|
|
|
def _resolve(self):
|
|
module = _import_module(self.mod)
|
|
return getattr(module, self.attr)
|
|
|
|
|
|
|
|
class _MovedItems(types.ModuleType):
|
|
"""Lazy loading of moved objects"""
|
|
|
|
|
|
_moved_attributes = [
|
|
MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"),
|
|
MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"),
|
|
MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"),
|
|
MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"),
|
|
MovedAttribute("map", "itertools", "builtins", "imap", "map"),
|
|
MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"),
|
|
MovedAttribute("reload_module", "__builtin__", "imp", "reload"),
|
|
MovedAttribute("reduce", "__builtin__", "functools"),
|
|
MovedAttribute("StringIO", "StringIO", "io"),
|
|
MovedAttribute("UserString", "UserString", "collections"),
|
|
MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"),
|
|
MovedAttribute("zip", "itertools", "builtins", "izip", "zip"),
|
|
MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"),
|
|
|
|
MovedModule("builtins", "__builtin__"),
|
|
MovedModule("configparser", "ConfigParser"),
|
|
MovedModule("copyreg", "copy_reg"),
|
|
MovedModule("http_cookiejar", "cookielib", "http.cookiejar"),
|
|
MovedModule("http_cookies", "Cookie", "http.cookies"),
|
|
MovedModule("html_entities", "htmlentitydefs", "html.entities"),
|
|
MovedModule("html_parser", "HTMLParser", "html.parser"),
|
|
MovedModule("http_client", "httplib", "http.client"),
|
|
MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"),
|
|
MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"),
|
|
MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"),
|
|
MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"),
|
|
MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"),
|
|
MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"),
|
|
MovedModule("cPickle", "cPickle", "pickle"),
|
|
MovedModule("queue", "Queue"),
|
|
MovedModule("reprlib", "repr"),
|
|
MovedModule("socketserver", "SocketServer"),
|
|
MovedModule("tkinter", "Tkinter"),
|
|
MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"),
|
|
MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"),
|
|
MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"),
|
|
MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"),
|
|
MovedModule("tkinter_tix", "Tix", "tkinter.tix"),
|
|
MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"),
|
|
MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"),
|
|
MovedModule("tkinter_colorchooser", "tkColorChooser",
|
|
"tkinter.colorchooser"),
|
|
MovedModule("tkinter_commondialog", "tkCommonDialog",
|
|
"tkinter.commondialog"),
|
|
MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"),
|
|
MovedModule("tkinter_font", "tkFont", "tkinter.font"),
|
|
MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"),
|
|
MovedModule("tkinter_tksimpledialog", "tkSimpleDialog",
|
|
"tkinter.simpledialog"),
|
|
MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"),
|
|
MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"),
|
|
MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"),
|
|
MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"),
|
|
MovedModule("winreg", "_winreg"),
|
|
]
|
|
for attr in _moved_attributes:
|
|
setattr(_MovedItems, attr.name, attr)
|
|
del attr
|
|
|
|
moves = sys.modules[__name__ + ".moves"] = _MovedItems(__name__ + ".moves")
|
|
|
|
|
|
|
|
class Module_six_moves_urllib_parse(types.ModuleType):
|
|
"""Lazy loading of moved objects in six.moves.urllib_parse"""
|
|
|
|
|
|
_urllib_parse_moved_attributes = [
|
|
MovedAttribute("ParseResult", "urlparse", "urllib.parse"),
|
|
MovedAttribute("parse_qs", "urlparse", "urllib.parse"),
|
|
MovedAttribute("parse_qsl", "urlparse", "urllib.parse"),
|
|
MovedAttribute("urldefrag", "urlparse", "urllib.parse"),
|
|
MovedAttribute("urljoin", "urlparse", "urllib.parse"),
|
|
MovedAttribute("urlparse", "urlparse", "urllib.parse"),
|
|
MovedAttribute("urlsplit", "urlparse", "urllib.parse"),
|
|
MovedAttribute("urlunparse", "urlparse", "urllib.parse"),
|
|
MovedAttribute("urlunsplit", "urlparse", "urllib.parse"),
|
|
MovedAttribute("quote", "urllib", "urllib.parse"),
|
|
MovedAttribute("quote_plus", "urllib", "urllib.parse"),
|
|
MovedAttribute("unquote", "urllib", "urllib.parse"),
|
|
MovedAttribute("unquote_plus", "urllib", "urllib.parse"),
|
|
MovedAttribute("urlencode", "urllib", "urllib.parse"),
|
|
]
|
|
for attr in _urllib_parse_moved_attributes:
|
|
setattr(Module_six_moves_urllib_parse, attr.name, attr)
|
|
del attr
|
|
|
|
sys.modules[__name__ + ".moves.urllib_parse"] = Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse")
|
|
sys.modules[__name__ + ".moves.urllib.parse"] = Module_six_moves_urllib_parse(__name__ + ".moves.urllib.parse")
|
|
|
|
|
|
class Module_six_moves_urllib_error(types.ModuleType):
|
|
"""Lazy loading of moved objects in six.moves.urllib_error"""
|
|
|
|
|
|
_urllib_error_moved_attributes = [
|
|
MovedAttribute("URLError", "urllib2", "urllib.error"),
|
|
MovedAttribute("HTTPError", "urllib2", "urllib.error"),
|
|
MovedAttribute("ContentTooShortError", "urllib", "urllib.error"),
|
|
]
|
|
for attr in _urllib_error_moved_attributes:
|
|
setattr(Module_six_moves_urllib_error, attr.name, attr)
|
|
del attr
|
|
|
|
sys.modules[__name__ + ".moves.urllib_error"] = Module_six_moves_urllib_error(__name__ + ".moves.urllib_error")
|
|
sys.modules[__name__ + ".moves.urllib.error"] = Module_six_moves_urllib_error(__name__ + ".moves.urllib.error")
|
|
|
|
|
|
class Module_six_moves_urllib_request(types.ModuleType):
|
|
"""Lazy loading of moved objects in six.moves.urllib_request"""
|
|
|
|
|
|
_urllib_request_moved_attributes = [
|
|
MovedAttribute("urlopen", "urllib2", "urllib.request"),
|
|
MovedAttribute("install_opener", "urllib2", "urllib.request"),
|
|
MovedAttribute("build_opener", "urllib2", "urllib.request"),
|
|
MovedAttribute("pathname2url", "urllib", "urllib.request"),
|
|
MovedAttribute("url2pathname", "urllib", "urllib.request"),
|
|
MovedAttribute("getproxies", "urllib", "urllib.request"),
|
|
MovedAttribute("Request", "urllib2", "urllib.request"),
|
|
MovedAttribute("OpenerDirector", "urllib2", "urllib.request"),
|
|
MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"),
|
|
MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"),
|
|
MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"),
|
|
MovedAttribute("ProxyHandler", "urllib2", "urllib.request"),
|
|
MovedAttribute("BaseHandler", "urllib2", "urllib.request"),
|
|
MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"),
|
|
MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"),
|
|
MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"),
|
|
MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"),
|
|
MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"),
|
|
MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"),
|
|
MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"),
|
|
MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"),
|
|
MovedAttribute("HTTPHandler", "urllib2", "urllib.request"),
|
|
MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"),
|
|
MovedAttribute("FileHandler", "urllib2", "urllib.request"),
|
|
MovedAttribute("FTPHandler", "urllib2", "urllib.request"),
|
|
MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"),
|
|
MovedAttribute("UnknownHandler", "urllib2", "urllib.request"),
|
|
MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"),
|
|
MovedAttribute("urlretrieve", "urllib", "urllib.request"),
|
|
MovedAttribute("urlcleanup", "urllib", "urllib.request"),
|
|
MovedAttribute("URLopener", "urllib", "urllib.request"),
|
|
MovedAttribute("FancyURLopener", "urllib", "urllib.request"),
|
|
]
|
|
for attr in _urllib_request_moved_attributes:
|
|
setattr(Module_six_moves_urllib_request, attr.name, attr)
|
|
del attr
|
|
|
|
sys.modules[__name__ + ".moves.urllib_request"] = Module_six_moves_urllib_request(__name__ + ".moves.urllib_request")
|
|
sys.modules[__name__ + ".moves.urllib.request"] = Module_six_moves_urllib_request(__name__ + ".moves.urllib.request")
|
|
|
|
|
|
class Module_six_moves_urllib_response(types.ModuleType):
|
|
"""Lazy loading of moved objects in six.moves.urllib_response"""
|
|
|
|
|
|
_urllib_response_moved_attributes = [
|
|
MovedAttribute("addbase", "urllib", "urllib.response"),
|
|
MovedAttribute("addclosehook", "urllib", "urllib.response"),
|
|
MovedAttribute("addinfo", "urllib", "urllib.response"),
|
|
MovedAttribute("addinfourl", "urllib", "urllib.response"),
|
|
]
|
|
for attr in _urllib_response_moved_attributes:
|
|
setattr(Module_six_moves_urllib_response, attr.name, attr)
|
|
del attr
|
|
|
|
sys.modules[__name__ + ".moves.urllib_response"] = Module_six_moves_urllib_response(__name__ + ".moves.urllib_response")
|
|
sys.modules[__name__ + ".moves.urllib.response"] = Module_six_moves_urllib_response(__name__ + ".moves.urllib.response")
|
|
|
|
|
|
class Module_six_moves_urllib_robotparser(types.ModuleType):
|
|
"""Lazy loading of moved objects in six.moves.urllib_robotparser"""
|
|
|
|
|
|
_urllib_robotparser_moved_attributes = [
|
|
MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"),
|
|
]
|
|
for attr in _urllib_robotparser_moved_attributes:
|
|
setattr(Module_six_moves_urllib_robotparser, attr.name, attr)
|
|
del attr
|
|
|
|
sys.modules[__name__ + ".moves.urllib_robotparser"] = Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib_robotparser")
|
|
sys.modules[__name__ + ".moves.urllib.robotparser"] = Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser")
|
|
|
|
|
|
class Module_six_moves_urllib(types.ModuleType):
|
|
"""Create a six.moves.urllib namespace that resembles the Python 3 namespace"""
|
|
parse = sys.modules[__name__ + ".moves.urllib_parse"]
|
|
error = sys.modules[__name__ + ".moves.urllib_error"]
|
|
request = sys.modules[__name__ + ".moves.urllib_request"]
|
|
response = sys.modules[__name__ + ".moves.urllib_response"]
|
|
robotparser = sys.modules[__name__ + ".moves.urllib_robotparser"]
|
|
|
|
|
|
sys.modules[__name__ + ".moves.urllib"] = Module_six_moves_urllib(__name__ + ".moves.urllib")
|
|
|
|
|
|
def add_move(move):
|
|
"""Add an item to six.moves."""
|
|
setattr(_MovedItems, move.name, move)
|
|
|
|
|
|
def remove_move(name):
|
|
"""Remove item from six.moves."""
|
|
try:
|
|
delattr(_MovedItems, name)
|
|
except AttributeError:
|
|
try:
|
|
del moves.__dict__[name]
|
|
except KeyError:
|
|
raise AttributeError("no such move, %r" % (name,))
|
|
|
|
|
|
if PY3:
|
|
_meth_func = "__func__"
|
|
_meth_self = "__self__"
|
|
|
|
_func_closure = "__closure__"
|
|
_func_code = "__code__"
|
|
_func_defaults = "__defaults__"
|
|
_func_globals = "__globals__"
|
|
|
|
_iterkeys = "keys"
|
|
_itervalues = "values"
|
|
_iteritems = "items"
|
|
_iterlists = "lists"
|
|
else:
|
|
_meth_func = "im_func"
|
|
_meth_self = "im_self"
|
|
|
|
_func_closure = "func_closure"
|
|
_func_code = "func_code"
|
|
_func_defaults = "func_defaults"
|
|
_func_globals = "func_globals"
|
|
|
|
_iterkeys = "iterkeys"
|
|
_itervalues = "itervalues"
|
|
_iteritems = "iteritems"
|
|
_iterlists = "iterlists"
|
|
|
|
|
|
try:
|
|
advance_iterator = next
|
|
except NameError:
|
|
def advance_iterator(it):
|
|
return it.next()
|
|
next = advance_iterator
|
|
|
|
|
|
try:
|
|
callable = callable
|
|
except NameError:
|
|
def callable(obj):
|
|
return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
|
|
|
|
|
|
if PY3:
|
|
def get_unbound_function(unbound):
|
|
return unbound
|
|
|
|
create_bound_method = types.MethodType
|
|
|
|
Iterator = object
|
|
else:
|
|
def get_unbound_function(unbound):
|
|
return unbound.im_func
|
|
|
|
def create_bound_method(func, obj):
|
|
return types.MethodType(func, obj, obj.__class__)
|
|
|
|
class Iterator(object):
|
|
|
|
def next(self):
|
|
return type(self).__next__(self)
|
|
|
|
callable = callable
|
|
_add_doc(get_unbound_function,
|
|
"""Get the function out of a possibly unbound function""")
|
|
|
|
|
|
get_method_function = operator.attrgetter(_meth_func)
|
|
get_method_self = operator.attrgetter(_meth_self)
|
|
get_function_closure = operator.attrgetter(_func_closure)
|
|
get_function_code = operator.attrgetter(_func_code)
|
|
get_function_defaults = operator.attrgetter(_func_defaults)
|
|
get_function_globals = operator.attrgetter(_func_globals)
|
|
|
|
|
|
def iterkeys(d, **kw):
|
|
"""Return an iterator over the keys of a dictionary."""
|
|
return iter(getattr(d, _iterkeys)(**kw))
|
|
|
|
def itervalues(d, **kw):
|
|
"""Return an iterator over the values of a dictionary."""
|
|
return iter(getattr(d, _itervalues)(**kw))
|
|
|
|
def iteritems(d, **kw):
|
|
"""Return an iterator over the (key, value) pairs of a dictionary."""
|
|
return iter(getattr(d, _iteritems)(**kw))
|
|
|
|
def iterlists(d, **kw):
|
|
"""Return an iterator over the (key, [values]) pairs of a dictionary."""
|
|
return iter(getattr(d, _iterlists)(**kw))
|
|
|
|
|
|
if PY3:
|
|
def b(s):
|
|
return s.encode("latin-1")
|
|
def u(s):
|
|
return s
|
|
unichr = chr
|
|
if sys.version_info[1] <= 1:
|
|
def int2byte(i):
|
|
return bytes((i,))
|
|
else:
|
|
# This is about 2x faster than the implementation above on 3.2+
|
|
int2byte = operator.methodcaller("to_bytes", 1, "big")
|
|
byte2int = operator.itemgetter(0)
|
|
indexbytes = operator.getitem
|
|
iterbytes = iter
|
|
import io
|
|
StringIO = io.StringIO
|
|
BytesIO = io.BytesIO
|
|
else:
|
|
def b(s):
|
|
return s
|
|
def u(s):
|
|
return unicode(s, "unicode_escape")
|
|
unichr = unichr
|
|
int2byte = chr
|
|
def byte2int(bs):
|
|
return ord(bs[0])
|
|
def indexbytes(buf, i):
|
|
return ord(buf[i])
|
|
def iterbytes(buf):
|
|
return (ord(byte) for byte in buf)
|
|
import StringIO
|
|
StringIO = BytesIO = StringIO.StringIO
|
|
_add_doc(b, """Byte literal""")
|
|
_add_doc(u, """Text literal""")
|
|
|
|
|
|
if PY3:
|
|
import builtins
|
|
exec_ = getattr(builtins, "exec")
|
|
|
|
|
|
def reraise(tp, value, tb=None):
|
|
if value.__traceback__ is not tb:
|
|
raise value.with_traceback(tb)
|
|
raise value
|
|
|
|
|
|
print_ = getattr(builtins, "print")
|
|
del builtins
|
|
|
|
else:
|
|
def exec_(_code_, _globs_=None, _locs_=None):
|
|
"""Execute code in a namespace."""
|
|
if _globs_ is None:
|
|
frame = sys._getframe(1)
|
|
_globs_ = frame.f_globals
|
|
if _locs_ is None:
|
|
_locs_ = frame.f_locals
|
|
del frame
|
|
elif _locs_ is None:
|
|
_locs_ = _globs_
|
|
exec("""exec _code_ in _globs_, _locs_""")
|
|
|
|
|
|
exec_("""def reraise(tp, value, tb=None):
|
|
raise tp, value, tb
|
|
""")
|
|
|
|
|
|
def print_(*args, **kwargs):
|
|
"""The new-style print function."""
|
|
fp = kwargs.pop("file", sys.stdout)
|
|
if fp is None:
|
|
return
|
|
def write(data):
|
|
if not isinstance(data, basestring):
|
|
data = str(data)
|
|
fp.write(data)
|
|
want_unicode = False
|
|
sep = kwargs.pop("sep", None)
|
|
if sep is not None:
|
|
if isinstance(sep, unicode):
|
|
want_unicode = True
|
|
elif not isinstance(sep, str):
|
|
raise TypeError("sep must be None or a string")
|
|
end = kwargs.pop("end", None)
|
|
if end is not None:
|
|
if isinstance(end, unicode):
|
|
want_unicode = True
|
|
elif not isinstance(end, str):
|
|
raise TypeError("end must be None or a string")
|
|
if kwargs:
|
|
raise TypeError("invalid keyword arguments to print()")
|
|
if not want_unicode:
|
|
for arg in args:
|
|
if isinstance(arg, unicode):
|
|
want_unicode = True
|
|
break
|
|
if want_unicode:
|
|
newline = unicode("\n")
|
|
space = unicode(" ")
|
|
else:
|
|
newline = "\n"
|
|
space = " "
|
|
if sep is None:
|
|
sep = space
|
|
if end is None:
|
|
end = newline
|
|
for i, arg in enumerate(args):
|
|
if i:
|
|
write(sep)
|
|
write(arg)
|
|
write(end)
|
|
|
|
_add_doc(reraise, """Reraise an exception.""")
|
|
|
|
|
|
def with_metaclass(meta, *bases):
|
|
"""Create a base class with a metaclass."""
|
|
return meta("NewBase", bases, {})
|
|
|
|
def add_metaclass(metaclass):
|
|
"""Class decorator for creating a class with a metaclass."""
|
|
def wrapper(cls):
|
|
orig_vars = cls.__dict__.copy()
|
|
orig_vars.pop('__dict__', None)
|
|
orig_vars.pop('__weakref__', None)
|
|
for slots_var in orig_vars.get('__slots__', ()):
|
|
orig_vars.pop(slots_var)
|
|
return metaclass(cls.__name__, cls.__bases__, orig_vars)
|
|
return wrapper
|