|  | # Copyright (c) 2010-2020 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 | 
|  | import unittest | 
|  | import abc | 
|  |  | 
|  | import pytest | 
|  |  | 
|  | import six | 
|  |  | 
|  |  | 
|  | def test_add_doc(): | 
|  | def f(): | 
|  | """Icky doc""" | 
|  | pass | 
|  | six._add_doc(f, """New doc""") | 
|  | assert f.__doc__ == "New doc" | 
|  |  | 
|  |  | 
|  | def test_import_module(): | 
|  | from logging import handlers | 
|  | m = six._import_module("logging.handlers") | 
|  | assert m is handlers | 
|  |  | 
|  |  | 
|  | def test_integer_types(): | 
|  | assert isinstance(1, six.integer_types) | 
|  | assert isinstance(-1, six.integer_types) | 
|  | assert isinstance(six.MAXSIZE + 23, six.integer_types) | 
|  | assert not isinstance(.1, six.integer_types) | 
|  |  | 
|  |  | 
|  | def test_string_types(): | 
|  | assert isinstance("hi", six.string_types) | 
|  | assert isinstance(six.u("hi"), six.string_types) | 
|  | assert issubclass(six.text_type, six.string_types) | 
|  |  | 
|  |  | 
|  | def test_class_types(): | 
|  | class X: | 
|  | pass | 
|  | class Y(object): | 
|  | pass | 
|  | assert isinstance(X, six.class_types) | 
|  | assert isinstance(Y, six.class_types) | 
|  | assert not isinstance(X(), six.class_types) | 
|  |  | 
|  |  | 
|  | def test_text_type(): | 
|  | assert type(six.u("hi")) is six.text_type | 
|  |  | 
|  |  | 
|  | def test_binary_type(): | 
|  | assert type(six.b("hi")) is six.binary_type | 
|  |  | 
|  |  | 
|  | def test_MAXSIZE(): | 
|  | try: | 
|  | # This shouldn't raise an overflow error. | 
|  | six.MAXSIZE.__index__() | 
|  | except AttributeError: | 
|  | # Before Python 2.6. | 
|  | pass | 
|  | pytest.raises( | 
|  | (ValueError, OverflowError), | 
|  | operator.mul, [None], six.MAXSIZE + 1) | 
|  |  | 
|  |  | 
|  | def test_lazy(): | 
|  | if six.PY3: | 
|  | html_name = "html.parser" | 
|  | else: | 
|  | html_name = "HTMLParser" | 
|  | assert html_name not in sys.modules | 
|  | mod = six.moves.html_parser | 
|  | assert sys.modules[html_name] is mod | 
|  | assert "htmlparser" not in six._MovedItems.__dict__ | 
|  |  | 
|  |  | 
|  | try: | 
|  | import _tkinter | 
|  | except ImportError: | 
|  | have_tkinter = False | 
|  | else: | 
|  | have_tkinter = True | 
|  |  | 
|  | have_gdbm = True | 
|  | try: | 
|  | import gdbm | 
|  | except ImportError: | 
|  | try: | 
|  | import dbm.gnu | 
|  | except ImportError: | 
|  | have_gdbm = False | 
|  |  | 
|  | @pytest.mark.parametrize("item_name", | 
|  | [item.name for item in six._moved_attributes]) | 
|  | def test_move_items(item_name): | 
|  | """Ensure that everything loads correctly.""" | 
|  | try: | 
|  | item = getattr(six.moves, item_name) | 
|  | if isinstance(item, types.ModuleType): | 
|  | __import__("six.moves." + item_name) | 
|  | except ImportError: | 
|  | if item_name == "winreg" and not sys.platform.startswith("win"): | 
|  | pytest.skip("Windows only module") | 
|  | if item_name.startswith("tkinter"): | 
|  | if not have_tkinter: | 
|  | pytest.skip("requires tkinter") | 
|  | if item_name.startswith("dbm_gnu") and not have_gdbm: | 
|  | pytest.skip("requires gdbm") | 
|  | raise | 
|  | assert item_name in dir(six.moves) | 
|  |  | 
|  |  | 
|  | @pytest.mark.parametrize("item_name", | 
|  | [item.name for item in six._urllib_parse_moved_attributes]) | 
|  | def test_move_items_urllib_parse(item_name): | 
|  | """Ensure that everything loads correctly.""" | 
|  | assert item_name in dir(six.moves.urllib.parse) | 
|  | getattr(six.moves.urllib.parse, item_name) | 
|  |  | 
|  |  | 
|  | @pytest.mark.parametrize("item_name", | 
|  | [item.name for item in six._urllib_error_moved_attributes]) | 
|  | def test_move_items_urllib_error(item_name): | 
|  | """Ensure that everything loads correctly.""" | 
|  | assert item_name in dir(six.moves.urllib.error) | 
|  | getattr(six.moves.urllib.error, item_name) | 
|  |  | 
|  |  | 
|  | @pytest.mark.parametrize("item_name", | 
|  | [item.name for item in six._urllib_request_moved_attributes]) | 
|  | def test_move_items_urllib_request(item_name): | 
|  | """Ensure that everything loads correctly.""" | 
|  | assert item_name in dir(six.moves.urllib.request) | 
|  | getattr(six.moves.urllib.request, item_name) | 
|  |  | 
|  |  | 
|  | @pytest.mark.parametrize("item_name", | 
|  | [item.name for item in six._urllib_response_moved_attributes]) | 
|  | def test_move_items_urllib_response(item_name): | 
|  | """Ensure that everything loads correctly.""" | 
|  | assert item_name in dir(six.moves.urllib.response) | 
|  | getattr(six.moves.urllib.response, item_name) | 
|  |  | 
|  |  | 
|  | @pytest.mark.parametrize("item_name", | 
|  | [item.name for item in six._urllib_robotparser_moved_attributes]) | 
|  | def test_move_items_urllib_robotparser(item_name): | 
|  | """Ensure that everything loads correctly.""" | 
|  | assert item_name in dir(six.moves.urllib.robotparser) | 
|  | getattr(six.moves.urllib.robotparser, item_name) | 
|  |  | 
|  |  | 
|  | def test_import_moves_error_1(): | 
|  | from six.moves.urllib.parse import urljoin | 
|  | from six import moves | 
|  | # In 1.4.1: AttributeError: 'Module_six_moves_urllib_parse' object has no attribute 'urljoin' | 
|  | assert moves.urllib.parse.urljoin | 
|  |  | 
|  |  | 
|  | def test_import_moves_error_2(): | 
|  | from six import moves | 
|  | assert moves.urllib.parse.urljoin | 
|  | # In 1.4.1: ImportError: cannot import name urljoin | 
|  | from six.moves.urllib.parse import urljoin | 
|  |  | 
|  |  | 
|  | def test_import_moves_error_3(): | 
|  | from six.moves.urllib.parse import urljoin | 
|  | # In 1.4.1: ImportError: cannot import name urljoin | 
|  | from six.moves.urllib_parse import urljoin | 
|  |  | 
|  |  | 
|  | def test_from_imports(): | 
|  | from six.moves.queue import Queue | 
|  | assert isinstance(Queue, six.class_types) | 
|  | from six.moves.configparser import ConfigParser | 
|  | assert isinstance(ConfigParser, six.class_types) | 
|  |  | 
|  |  | 
|  | def test_filter(): | 
|  | from six.moves import filter | 
|  | f = filter(lambda x: x % 2, range(10)) | 
|  | assert six.advance_iterator(f) == 1 | 
|  |  | 
|  |  | 
|  | def test_filter_false(): | 
|  | from six.moves import filterfalse | 
|  | f = filterfalse(lambda x: x % 3, range(10)) | 
|  | assert six.advance_iterator(f) == 0 | 
|  | assert six.advance_iterator(f) == 3 | 
|  | assert six.advance_iterator(f) == 6 | 
|  |  | 
|  | def test_map(): | 
|  | from six.moves import map | 
|  | assert six.advance_iterator(map(lambda x: x + 1, range(2))) == 1 | 
|  |  | 
|  |  | 
|  | def test_getoutput(): | 
|  | from six.moves import getoutput | 
|  | output = getoutput('echo "foo"') | 
|  | assert output == 'foo' | 
|  |  | 
|  |  | 
|  | def test_zip(): | 
|  | from six.moves import zip | 
|  | assert six.advance_iterator(zip(range(2), range(2))) == (0, 0) | 
|  |  | 
|  |  | 
|  | def test_zip_longest(): | 
|  | from six.moves import zip_longest | 
|  | it = zip_longest(range(2), range(1)) | 
|  |  | 
|  | assert six.advance_iterator(it) == (0, 0) | 
|  | assert six.advance_iterator(it) == (1, None) | 
|  |  | 
|  |  | 
|  | class TestCustomizedMoves: | 
|  |  | 
|  | def teardown_method(self, meth): | 
|  | try: | 
|  | del six._MovedItems.spam | 
|  | except AttributeError: | 
|  | pass | 
|  | try: | 
|  | del six.moves.__dict__["spam"] | 
|  | except KeyError: | 
|  | pass | 
|  |  | 
|  |  | 
|  | def test_moved_attribute(self): | 
|  | attr = six.MovedAttribute("spam", "foo", "bar") | 
|  | if six.PY3: | 
|  | assert attr.mod == "bar" | 
|  | else: | 
|  | assert attr.mod == "foo" | 
|  | assert attr.attr == "spam" | 
|  | attr = six.MovedAttribute("spam", "foo", "bar", "lemma") | 
|  | assert attr.attr == "lemma" | 
|  | attr = six.MovedAttribute("spam", "foo", "bar", "lemma", "theorm") | 
|  | if six.PY3: | 
|  | assert attr.attr == "theorm" | 
|  | else: | 
|  | assert attr.attr == "lemma" | 
|  |  | 
|  |  | 
|  | def test_moved_module(self): | 
|  | attr = six.MovedModule("spam", "foo") | 
|  | if six.PY3: | 
|  | assert attr.mod == "spam" | 
|  | else: | 
|  | assert attr.mod == "foo" | 
|  | attr = six.MovedModule("spam", "foo", "bar") | 
|  | if six.PY3: | 
|  | assert attr.mod == "bar" | 
|  | else: | 
|  | assert attr.mod == "foo" | 
|  |  | 
|  |  | 
|  | def test_custom_move_module(self): | 
|  | attr = six.MovedModule("spam", "six", "six") | 
|  | six.add_move(attr) | 
|  | six.remove_move("spam") | 
|  | assert not hasattr(six.moves, "spam") | 
|  | attr = six.MovedModule("spam", "six", "six") | 
|  | six.add_move(attr) | 
|  | from six.moves import spam | 
|  | assert spam is six | 
|  | six.remove_move("spam") | 
|  | assert not hasattr(six.moves, "spam") | 
|  |  | 
|  |  | 
|  | def test_custom_move_attribute(self): | 
|  | attr = six.MovedAttribute("spam", "six", "six", "u", "u") | 
|  | six.add_move(attr) | 
|  | six.remove_move("spam") | 
|  | assert not hasattr(six.moves, "spam") | 
|  | attr = six.MovedAttribute("spam", "six", "six", "u", "u") | 
|  | six.add_move(attr) | 
|  | from six.moves import spam | 
|  | assert spam is six.u | 
|  | six.remove_move("spam") | 
|  | assert not hasattr(six.moves, "spam") | 
|  |  | 
|  |  | 
|  | def test_empty_remove(self): | 
|  | pytest.raises(AttributeError, six.remove_move, "eggs") | 
|  |  | 
|  |  | 
|  | def test_get_unbound_function(): | 
|  | class X(object): | 
|  | def m(self): | 
|  | pass | 
|  | assert six.get_unbound_function(X.m) is X.__dict__["m"] | 
|  |  | 
|  |  | 
|  | def test_get_method_self(): | 
|  | class X(object): | 
|  | def m(self): | 
|  | pass | 
|  | x = X() | 
|  | assert six.get_method_self(x.m) is x | 
|  | pytest.raises(AttributeError, six.get_method_self, 42) | 
|  |  | 
|  |  | 
|  | def test_get_method_function(): | 
|  | class X(object): | 
|  | def m(self): | 
|  | pass | 
|  | x = X() | 
|  | assert six.get_method_function(x.m) is X.__dict__["m"] | 
|  | pytest.raises(AttributeError, six.get_method_function, hasattr) | 
|  |  | 
|  |  | 
|  | def test_get_function_closure(): | 
|  | def f(): | 
|  | x = 42 | 
|  | def g(): | 
|  | return x | 
|  | return g | 
|  | cell = six.get_function_closure(f())[0] | 
|  | assert type(cell).__name__ == "cell" | 
|  |  | 
|  |  | 
|  | def test_get_function_code(): | 
|  | def f(): | 
|  | pass | 
|  | assert isinstance(six.get_function_code(f), types.CodeType) | 
|  | if not hasattr(sys, "pypy_version_info"): | 
|  | pytest.raises(AttributeError, six.get_function_code, hasattr) | 
|  |  | 
|  |  | 
|  | def test_get_function_defaults(): | 
|  | def f(x, y=3, b=4): | 
|  | pass | 
|  | assert six.get_function_defaults(f) == (3, 4) | 
|  |  | 
|  |  | 
|  | def test_get_function_globals(): | 
|  | def f(): | 
|  | pass | 
|  | assert six.get_function_globals(f) is globals() | 
|  |  | 
|  |  | 
|  | def test_dictionary_iterators(monkeypatch): | 
|  | def stock_method_name(iterwhat): | 
|  | """Given a method suffix like "lists" or "values", return the name | 
|  | of the dict method that delivers those on the version of Python | 
|  | we're running in.""" | 
|  | if six.PY3: | 
|  | return iterwhat | 
|  | return 'iter' + iterwhat | 
|  |  | 
|  | class MyDict(dict): | 
|  | if not six.PY3: | 
|  | def lists(self, **kw): | 
|  | return [1, 2, 3] | 
|  | def iterlists(self, **kw): | 
|  | return iter([1, 2, 3]) | 
|  | f = MyDict.iterlists | 
|  | del MyDict.iterlists | 
|  | setattr(MyDict, stock_method_name('lists'), f) | 
|  |  | 
|  | d = MyDict(zip(range(10), reversed(range(10)))) | 
|  | for name in "keys", "values", "items", "lists": | 
|  | meth = getattr(six, "iter" + name) | 
|  | it = meth(d) | 
|  | assert not isinstance(it, list) | 
|  | assert list(it) == list(getattr(d, name)()) | 
|  | pytest.raises(StopIteration, six.advance_iterator, it) | 
|  | record = [] | 
|  | def with_kw(*args, **kw): | 
|  | record.append(kw["kw"]) | 
|  | return old(*args) | 
|  | old = getattr(MyDict, stock_method_name(name)) | 
|  | monkeypatch.setattr(MyDict, stock_method_name(name), with_kw) | 
|  | meth(d, kw=42) | 
|  | assert record == [42] | 
|  | monkeypatch.undo() | 
|  |  | 
|  |  | 
|  | def test_dictionary_views(): | 
|  | d = dict(zip(range(10), (range(11, 20)))) | 
|  | for name in "keys", "values", "items": | 
|  | meth = getattr(six, "view" + name) | 
|  | view = meth(d) | 
|  | assert set(view) == set(getattr(d, name)()) | 
|  |  | 
|  |  | 
|  | def test_advance_iterator(): | 
|  | assert six.next is six.advance_iterator | 
|  | l = [1, 2] | 
|  | it = iter(l) | 
|  | assert six.next(it) == 1 | 
|  | assert six.next(it) == 2 | 
|  | pytest.raises(StopIteration, six.next, it) | 
|  | pytest.raises(StopIteration, six.next, it) | 
|  |  | 
|  |  | 
|  | def test_iterator(): | 
|  | class myiter(six.Iterator): | 
|  | def __next__(self): | 
|  | return 13 | 
|  | assert six.advance_iterator(myiter()) == 13 | 
|  | class myitersub(myiter): | 
|  | def __next__(self): | 
|  | return 14 | 
|  | assert six.advance_iterator(myitersub()) == 14 | 
|  |  | 
|  |  | 
|  | def test_callable(): | 
|  | class X: | 
|  | def __call__(self): | 
|  | pass | 
|  | def method(self): | 
|  | pass | 
|  | assert six.callable(X) | 
|  | assert six.callable(X()) | 
|  | assert six.callable(test_callable) | 
|  | assert six.callable(hasattr) | 
|  | assert six.callable(X.method) | 
|  | assert six.callable(X().method) | 
|  | assert not six.callable(4) | 
|  | assert not six.callable("string") | 
|  |  | 
|  |  | 
|  | def test_create_bound_method(): | 
|  | class X(object): | 
|  | pass | 
|  | def f(self): | 
|  | return self | 
|  | x = X() | 
|  | b = six.create_bound_method(f, x) | 
|  | assert isinstance(b, types.MethodType) | 
|  | assert b() is x | 
|  |  | 
|  |  | 
|  | def test_create_unbound_method(): | 
|  | class X(object): | 
|  | pass | 
|  |  | 
|  | def f(self): | 
|  | return self | 
|  | u = six.create_unbound_method(f, X) | 
|  | pytest.raises(TypeError, u) | 
|  | if six.PY2: | 
|  | assert isinstance(u, types.MethodType) | 
|  | x = X() | 
|  | assert f(x) is x | 
|  |  | 
|  |  | 
|  | if six.PY3: | 
|  |  | 
|  | def test_b(): | 
|  | data = six.b("\xff") | 
|  | assert isinstance(data, bytes) | 
|  | assert len(data) == 1 | 
|  | assert data == bytes([255]) | 
|  |  | 
|  |  | 
|  | def test_u(): | 
|  | s = six.u("hi \u0439 \U00000439 \\ \\\\ \n") | 
|  | assert isinstance(s, str) | 
|  | assert s == "hi \u0439 \U00000439 \\ \\\\ \n" | 
|  |  | 
|  | else: | 
|  |  | 
|  | def test_b(): | 
|  | data = six.b("\xff") | 
|  | assert isinstance(data, str) | 
|  | assert len(data) == 1 | 
|  | assert data == "\xff" | 
|  |  | 
|  |  | 
|  | def test_u(): | 
|  | s = six.u("hi \u0439 \U00000439 \\ \\\\ \n") | 
|  | assert isinstance(s, unicode) | 
|  | assert s == "hi \xd0\xb9 \xd0\xb9 \\ \\\\ \n".decode("utf8") | 
|  |  | 
|  |  | 
|  | def test_u_escapes(): | 
|  | s = six.u("\u1234") | 
|  | assert len(s) == 1 | 
|  |  | 
|  |  | 
|  | def test_unichr(): | 
|  | assert six.u("\u1234") == six.unichr(0x1234) | 
|  | assert type(six.u("\u1234")) is type(six.unichr(0x1234)) | 
|  |  | 
|  |  | 
|  | def test_int2byte(): | 
|  | assert six.int2byte(3) == six.b("\x03") | 
|  | pytest.raises(Exception, six.int2byte, 256) | 
|  |  | 
|  |  | 
|  | def test_byte2int(): | 
|  | assert six.byte2int(six.b("\x03")) == 3 | 
|  | assert six.byte2int(six.b("\x03\x04")) == 3 | 
|  | pytest.raises(IndexError, six.byte2int, six.b("")) | 
|  |  | 
|  |  | 
|  | def test_bytesindex(): | 
|  | assert six.indexbytes(six.b("hello"), 3) == ord("l") | 
|  |  | 
|  |  | 
|  | def test_bytesiter(): | 
|  | it = six.iterbytes(six.b("hi")) | 
|  | assert six.next(it) == ord("h") | 
|  | assert six.next(it) == ord("i") | 
|  | pytest.raises(StopIteration, six.next, it) | 
|  |  | 
|  |  | 
|  | def test_StringIO(): | 
|  | fp = six.StringIO() | 
|  | fp.write(six.u("hello")) | 
|  | assert fp.getvalue() == six.u("hello") | 
|  |  | 
|  |  | 
|  | def test_BytesIO(): | 
|  | fp = six.BytesIO() | 
|  | fp.write(six.b("hello")) | 
|  | assert fp.getvalue() == six.b("hello") | 
|  |  | 
|  |  | 
|  | def test_exec_(): | 
|  | def f(): | 
|  | l = [] | 
|  | six.exec_("l.append(1)") | 
|  | assert l == [1] | 
|  | f() | 
|  | ns = {} | 
|  | six.exec_("x = 42", ns) | 
|  | assert ns["x"] == 42 | 
|  | glob = {} | 
|  | loc = {} | 
|  | six.exec_("global y; y = 42; x = 12", glob, loc) | 
|  | assert glob["y"] == 42 | 
|  | assert "x" not in glob | 
|  | assert loc["x"] == 12 | 
|  | assert "y" not in loc | 
|  |  | 
|  |  | 
|  | def test_reraise(): | 
|  | def get_next(tb): | 
|  | if six.PY3: | 
|  | return tb.tb_next.tb_next | 
|  | else: | 
|  | return tb.tb_next | 
|  | e = Exception("blah") | 
|  | try: | 
|  | raise e | 
|  | except Exception: | 
|  | tp, val, tb = sys.exc_info() | 
|  | try: | 
|  | six.reraise(tp, val, tb) | 
|  | except Exception: | 
|  | tp2, value2, tb2 = sys.exc_info() | 
|  | assert tp2 is Exception | 
|  | assert value2 is e | 
|  | assert tb is get_next(tb2) | 
|  | try: | 
|  | six.reraise(tp, val) | 
|  | except Exception: | 
|  | tp2, value2, tb2 = sys.exc_info() | 
|  | assert tp2 is Exception | 
|  | assert value2 is e | 
|  | assert tb2 is not tb | 
|  | try: | 
|  | six.reraise(tp, val, tb2) | 
|  | except Exception: | 
|  | tp2, value2, tb3 = sys.exc_info() | 
|  | assert tp2 is Exception | 
|  | assert value2 is e | 
|  | assert get_next(tb3) is tb2 | 
|  | try: | 
|  | six.reraise(tp, None, tb) | 
|  | except Exception: | 
|  | tp2, value2, tb2 = sys.exc_info() | 
|  | assert tp2 is Exception | 
|  | assert value2 is not val | 
|  | assert isinstance(value2, Exception) | 
|  | assert tb is get_next(tb2) | 
|  |  | 
|  |  | 
|  | def test_raise_from(): | 
|  | try: | 
|  | try: | 
|  | raise Exception("blah") | 
|  | except Exception: | 
|  | ctx = sys.exc_info()[1] | 
|  | f = Exception("foo") | 
|  | six.raise_from(f, None) | 
|  | except Exception: | 
|  | tp, val, tb = sys.exc_info() | 
|  | if sys.version_info[:2] > (3, 0): | 
|  | # We should have done a raise f from None equivalent. | 
|  | assert val.__cause__ is None | 
|  | assert val.__context__ is ctx | 
|  | # And that should suppress the context on the exception. | 
|  | assert val.__suppress_context__ | 
|  | # For all versions the outer exception should have raised successfully. | 
|  | assert str(val) == "foo" | 
|  |  | 
|  |  | 
|  | def test_print_(): | 
|  | save = sys.stdout | 
|  | out = sys.stdout = six.moves.StringIO() | 
|  | try: | 
|  | six.print_("Hello,", "person!") | 
|  | finally: | 
|  | sys.stdout = save | 
|  | assert out.getvalue() == "Hello, person!\n" | 
|  | out = six.StringIO() | 
|  | six.print_("Hello,", "person!", file=out) | 
|  | assert out.getvalue() == "Hello, person!\n" | 
|  | out = six.StringIO() | 
|  | six.print_("Hello,", "person!", file=out, end="") | 
|  | assert out.getvalue() == "Hello, person!" | 
|  | out = six.StringIO() | 
|  | six.print_("Hello,", "person!", file=out, sep="X") | 
|  | assert out.getvalue() == "Hello,Xperson!\n" | 
|  | out = six.StringIO() | 
|  | six.print_(six.u("Hello,"), six.u("person!"), file=out) | 
|  | result = out.getvalue() | 
|  | assert isinstance(result, six.text_type) | 
|  | assert result == six.u("Hello, person!\n") | 
|  | six.print_("Hello", file=None) # This works. | 
|  | out = six.StringIO() | 
|  | six.print_(None, file=out) | 
|  | assert out.getvalue() == "None\n" | 
|  | class FlushableStringIO(six.StringIO): | 
|  | def __init__(self): | 
|  | six.StringIO.__init__(self) | 
|  | self.flushed = False | 
|  | def flush(self): | 
|  | self.flushed = True | 
|  | out = FlushableStringIO() | 
|  | six.print_("Hello", file=out) | 
|  | assert not out.flushed | 
|  | six.print_("Hello", file=out, flush=True) | 
|  | assert out.flushed | 
|  |  | 
|  |  | 
|  | def test_print_exceptions(): | 
|  | pytest.raises(TypeError, six.print_, x=3) | 
|  | pytest.raises(TypeError, six.print_, end=3) | 
|  | pytest.raises(TypeError, six.print_, sep=42) | 
|  |  | 
|  |  | 
|  | def test_with_metaclass(): | 
|  | class Meta(type): | 
|  | pass | 
|  | class X(six.with_metaclass(Meta)): | 
|  | pass | 
|  | assert type(X) is Meta | 
|  | assert issubclass(X, object) | 
|  | class Base(object): | 
|  | pass | 
|  | class X(six.with_metaclass(Meta, Base)): | 
|  | pass | 
|  | assert type(X) is Meta | 
|  | assert issubclass(X, Base) | 
|  | class Base2(object): | 
|  | pass | 
|  | class X(six.with_metaclass(Meta, Base, Base2)): | 
|  | pass | 
|  | assert type(X) is Meta | 
|  | assert issubclass(X, Base) | 
|  | assert issubclass(X, Base2) | 
|  | assert X.__mro__ == (X, Base, Base2, object) | 
|  | class X(six.with_metaclass(Meta)): | 
|  | pass | 
|  | class MetaSub(Meta): | 
|  | pass | 
|  | class Y(six.with_metaclass(MetaSub, X)): | 
|  | pass | 
|  | assert type(Y) is MetaSub | 
|  | assert Y.__mro__ == (Y, X, object) | 
|  |  | 
|  |  | 
|  | def test_with_metaclass_typing(): | 
|  | try: | 
|  | import typing | 
|  | except ImportError: | 
|  | pytest.skip("typing module required") | 
|  | class Meta(type): | 
|  | pass | 
|  | if sys.version_info[:2] < (3, 7): | 
|  | # Generics with custom metaclasses were broken on older versions. | 
|  | class Meta(Meta, typing.GenericMeta): | 
|  | pass | 
|  | T = typing.TypeVar('T') | 
|  | class G(six.with_metaclass(Meta, typing.Generic[T])): | 
|  | pass | 
|  | class GA(six.with_metaclass(abc.ABCMeta, typing.Generic[T])): | 
|  | pass | 
|  | assert isinstance(G, Meta) | 
|  | assert isinstance(GA, abc.ABCMeta) | 
|  | assert G[int] is not G[G[int]] | 
|  | assert GA[int] is not GA[GA[int]] | 
|  | assert G.__bases__ == (typing.Generic,) | 
|  | assert G.__orig_bases__ == (typing.Generic[T],) | 
|  |  | 
|  |  | 
|  | @pytest.mark.skipif("sys.version_info[:2] < (3, 7)") | 
|  | def test_with_metaclass_pep_560(): | 
|  | class Meta(type): | 
|  | pass | 
|  | class A: | 
|  | pass | 
|  | class B: | 
|  | pass | 
|  | class Fake: | 
|  | def __mro_entries__(self, bases): | 
|  | return (A, B) | 
|  | fake = Fake() | 
|  | class G(six.with_metaclass(Meta, fake)): | 
|  | pass | 
|  | class GA(six.with_metaclass(abc.ABCMeta, fake)): | 
|  | pass | 
|  | assert isinstance(G, Meta) | 
|  | assert isinstance(GA, abc.ABCMeta) | 
|  | assert G.__bases__ == (A, B) | 
|  | assert G.__orig_bases__ == (fake,) | 
|  |  | 
|  |  | 
|  | @pytest.mark.skipif("sys.version_info[:2] < (3, 0)") | 
|  | def test_with_metaclass_prepare(): | 
|  | """Test that with_metaclass causes Meta.__prepare__ to be called with the correct arguments.""" | 
|  |  | 
|  | class MyDict(dict): | 
|  | pass | 
|  |  | 
|  | class Meta(type): | 
|  |  | 
|  | @classmethod | 
|  | def __prepare__(cls, name, bases): | 
|  | namespace = MyDict(super().__prepare__(name, bases), cls=cls, bases=bases) | 
|  | namespace['namespace'] = namespace | 
|  | return namespace | 
|  |  | 
|  | class Base(object): | 
|  | pass | 
|  |  | 
|  | bases = (Base,) | 
|  |  | 
|  | class X(six.with_metaclass(Meta, *bases)): | 
|  | pass | 
|  |  | 
|  | assert getattr(X, 'cls', type) is Meta | 
|  | assert getattr(X, 'bases', ()) == bases | 
|  | assert isinstance(getattr(X, 'namespace', {}), MyDict) | 
|  |  | 
|  |  | 
|  | def test_wraps(): | 
|  | def f(g): | 
|  | @six.wraps(g) | 
|  | def w(): | 
|  | return 42 | 
|  | return w | 
|  | def k(): | 
|  | pass | 
|  | original_k = k | 
|  | k = f(f(k)) | 
|  | assert hasattr(k, '__wrapped__') | 
|  | k = k.__wrapped__ | 
|  | assert hasattr(k, '__wrapped__') | 
|  | k = k.__wrapped__ | 
|  | assert k is original_k | 
|  | assert not hasattr(k, '__wrapped__') | 
|  |  | 
|  | def f(g, assign, update): | 
|  | def w(): | 
|  | return 42 | 
|  | w.glue = {"foo": "bar"} | 
|  | w.xyzzy = {"qux": "quux"} | 
|  | return six.wraps(g, assign, update)(w) | 
|  | k.glue = {"melon": "egg"} | 
|  | k.turnip = 43 | 
|  | k = f(k, ["turnip", "baz"], ["glue", "xyzzy"]) | 
|  | assert k.__name__ == "w" | 
|  | assert k.turnip == 43 | 
|  | assert not hasattr(k, "baz") | 
|  | assert k.glue == {"melon": "egg", "foo": "bar"} | 
|  | assert k.xyzzy == {"qux": "quux"} | 
|  |  | 
|  |  | 
|  | def test_wraps_raises_on_missing_updated_field_on_wrapper(): | 
|  | """Ensure six.wraps doesn't ignore missing attrs wrapper. | 
|  |  | 
|  | Because that's what happens in Py3's functools.update_wrapper. | 
|  | """ | 
|  | def wrapped(): | 
|  | pass | 
|  |  | 
|  | def wrapper(): | 
|  | pass | 
|  |  | 
|  | with pytest.raises(AttributeError, match='has no attribute.*xyzzy'): | 
|  | six.wraps(wrapped, [], ['xyzzy'])(wrapper) | 
|  |  | 
|  |  | 
|  |  | 
|  | def test_add_metaclass(): | 
|  | class Meta(type): | 
|  | pass | 
|  | class X: | 
|  | "success" | 
|  | X = six.add_metaclass(Meta)(X) | 
|  | assert type(X) is Meta | 
|  | assert issubclass(X, object) | 
|  | assert X.__module__ == __name__ | 
|  | assert X.__doc__ == "success" | 
|  | class Base(object): | 
|  | pass | 
|  | class X(Base): | 
|  | pass | 
|  | X = six.add_metaclass(Meta)(X) | 
|  | assert type(X) is Meta | 
|  | assert issubclass(X, Base) | 
|  | class Base2(object): | 
|  | pass | 
|  | class X(Base, Base2): | 
|  | pass | 
|  | X = six.add_metaclass(Meta)(X) | 
|  | assert type(X) is Meta | 
|  | assert issubclass(X, Base) | 
|  | assert issubclass(X, Base2) | 
|  |  | 
|  | # Test a second-generation subclass of a type. | 
|  | class Meta1(type): | 
|  | m1 = "m1" | 
|  | class Meta2(Meta1): | 
|  | m2 = "m2" | 
|  | class Base: | 
|  | b = "b" | 
|  | Base = six.add_metaclass(Meta1)(Base) | 
|  | class X(Base): | 
|  | x = "x" | 
|  | X = six.add_metaclass(Meta2)(X) | 
|  | assert type(X) is Meta2 | 
|  | assert issubclass(X, Base) | 
|  | assert type(Base) is Meta1 | 
|  | assert "__dict__" not in vars(X) | 
|  | instance = X() | 
|  | instance.attr = "test" | 
|  | assert vars(instance) == {"attr": "test"} | 
|  | assert instance.b == Base.b | 
|  | assert instance.x == X.x | 
|  |  | 
|  | # Test a class with slots. | 
|  | class MySlots(object): | 
|  | __slots__ = ["a", "b"] | 
|  | MySlots = six.add_metaclass(Meta1)(MySlots) | 
|  |  | 
|  | assert MySlots.__slots__ == ["a", "b"] | 
|  | instance = MySlots() | 
|  | instance.a = "foo" | 
|  | pytest.raises(AttributeError, setattr, instance, "c", "baz") | 
|  |  | 
|  | # Test a class with string for slots. | 
|  | class MyStringSlots(object): | 
|  | __slots__ = "ab" | 
|  | MyStringSlots = six.add_metaclass(Meta1)(MyStringSlots) | 
|  | assert MyStringSlots.__slots__ == "ab" | 
|  | instance = MyStringSlots() | 
|  | instance.ab = "foo" | 
|  | pytest.raises(AttributeError, setattr, instance, "a", "baz") | 
|  | pytest.raises(AttributeError, setattr, instance, "b", "baz") | 
|  |  | 
|  | class MySlotsWeakref(object): | 
|  | __slots__ = "__weakref__", | 
|  | MySlotsWeakref = six.add_metaclass(Meta)(MySlotsWeakref) | 
|  | assert type(MySlotsWeakref) is Meta | 
|  |  | 
|  |  | 
|  | @pytest.mark.skipif("sys.version_info[:2] < (3, 3)") | 
|  | def test_add_metaclass_nested(): | 
|  | # Regression test for https://github.com/benjaminp/six/issues/259 | 
|  | class Meta(type): | 
|  | pass | 
|  |  | 
|  | class A: | 
|  | class B: pass | 
|  |  | 
|  | expected = 'test_add_metaclass_nested.<locals>.A.B' | 
|  |  | 
|  | assert A.B.__qualname__ == expected | 
|  |  | 
|  | class A: | 
|  | @six.add_metaclass(Meta) | 
|  | class B: pass | 
|  |  | 
|  | assert A.B.__qualname__ == expected | 
|  |  | 
|  |  | 
|  | def test_assertCountEqual(): | 
|  | class TestAssertCountEqual(unittest.TestCase): | 
|  | def test(self): | 
|  | with self.assertRaises(AssertionError): | 
|  | six.assertCountEqual(self, (1, 2), [3, 4, 5]) | 
|  |  | 
|  | six.assertCountEqual(self, (1, 2), [2, 1]) | 
|  |  | 
|  | TestAssertCountEqual('test').test() | 
|  |  | 
|  |  | 
|  | def test_assertRegex(): | 
|  | class TestAssertRegex(unittest.TestCase): | 
|  | def test(self): | 
|  | with self.assertRaises(AssertionError): | 
|  | six.assertRegex(self, 'test', r'^a') | 
|  |  | 
|  | six.assertRegex(self, 'test', r'^t') | 
|  |  | 
|  | TestAssertRegex('test').test() | 
|  |  | 
|  |  | 
|  | def test_assertNotRegex(): | 
|  | class TestAssertNotRegex(unittest.TestCase): | 
|  | def test(self): | 
|  | with self.assertRaises(AssertionError): | 
|  | six.assertNotRegex(self, 'test', r'^t') | 
|  |  | 
|  | six.assertNotRegex(self, 'test', r'^a') | 
|  |  | 
|  | TestAssertNotRegex('test').test() | 
|  |  | 
|  |  | 
|  | def test_assertRaisesRegex(): | 
|  | class TestAssertRaisesRegex(unittest.TestCase): | 
|  | def test(self): | 
|  | with six.assertRaisesRegex(self, AssertionError, '^Foo'): | 
|  | raise AssertionError('Foo') | 
|  |  | 
|  | with self.assertRaises(AssertionError): | 
|  | with six.assertRaisesRegex(self, AssertionError, r'^Foo'): | 
|  | raise AssertionError('Bar') | 
|  |  | 
|  | TestAssertRaisesRegex('test').test() | 
|  |  | 
|  |  | 
|  | def test_python_2_unicode_compatible(): | 
|  | @six.python_2_unicode_compatible | 
|  | class MyTest(object): | 
|  | def __str__(self): | 
|  | return six.u('hello') | 
|  |  | 
|  | def __bytes__(self): | 
|  | return six.b('hello') | 
|  |  | 
|  | my_test = MyTest() | 
|  |  | 
|  | if six.PY2: | 
|  | assert str(my_test) == six.b("hello") | 
|  | assert unicode(my_test) == six.u("hello") | 
|  | elif six.PY3: | 
|  | assert bytes(my_test) == six.b("hello") | 
|  | assert str(my_test) == six.u("hello") | 
|  |  | 
|  | assert getattr(six.moves.builtins, 'bytes', str)(my_test) == six.b("hello") | 
|  |  | 
|  |  | 
|  | class EnsureTests: | 
|  |  | 
|  | # grinning face emoji | 
|  | UNICODE_EMOJI = six.u("\U0001F600") | 
|  | BINARY_EMOJI = b"\xf0\x9f\x98\x80" | 
|  |  | 
|  | def test_ensure_binary_raise_type_error(self): | 
|  | with pytest.raises(TypeError): | 
|  | six.ensure_str(8) | 
|  |  | 
|  | def test_errors_and_encoding(self): | 
|  | six.ensure_binary(self.UNICODE_EMOJI, encoding='latin-1', errors='ignore') | 
|  | with pytest.raises(UnicodeEncodeError): | 
|  | six.ensure_binary(self.UNICODE_EMOJI, encoding='latin-1', errors='strict') | 
|  |  | 
|  | def test_ensure_binary_raise(self): | 
|  | converted_unicode = six.ensure_binary(self.UNICODE_EMOJI, encoding='utf-8', errors='strict') | 
|  | converted_binary = six.ensure_binary(self.BINARY_EMOJI, encoding="utf-8", errors='strict') | 
|  | if six.PY2: | 
|  | # PY2: unicode -> str | 
|  | assert converted_unicode == self.BINARY_EMOJI and isinstance(converted_unicode, str) | 
|  | # PY2: str -> str | 
|  | assert converted_binary == self.BINARY_EMOJI and isinstance(converted_binary, str) | 
|  | else: | 
|  | # PY3: str -> bytes | 
|  | assert converted_unicode == self.BINARY_EMOJI and isinstance(converted_unicode, bytes) | 
|  | # PY3: bytes -> bytes | 
|  | assert converted_binary == self.BINARY_EMOJI and isinstance(converted_binary, bytes) | 
|  |  | 
|  | def test_ensure_str(self): | 
|  | converted_unicode = six.ensure_str(self.UNICODE_EMOJI, encoding='utf-8', errors='strict') | 
|  | converted_binary = six.ensure_str(self.BINARY_EMOJI, encoding="utf-8", errors='strict') | 
|  | if six.PY2: | 
|  | # PY2: unicode -> str | 
|  | assert converted_unicode == self.BINARY_EMOJI and isinstance(converted_unicode, str) | 
|  | # PY2: str -> str | 
|  | assert converted_binary == self.BINARY_EMOJI and isinstance(converted_binary, str) | 
|  | else: | 
|  | # PY3: str -> str | 
|  | assert converted_unicode == self.UNICODE_EMOJI and isinstance(converted_unicode, str) | 
|  | # PY3: bytes -> str | 
|  | assert converted_binary == self.UNICODE_EMOJI and isinstance(converted_unicode, str) | 
|  |  | 
|  | def test_ensure_text(self): | 
|  | converted_unicode = six.ensure_text(self.UNICODE_EMOJI, encoding='utf-8', errors='strict') | 
|  | converted_binary = six.ensure_text(self.BINARY_EMOJI, encoding="utf-8", errors='strict') | 
|  | if six.PY2: | 
|  | # PY2: unicode -> unicode | 
|  | assert converted_unicode == self.UNICODE_EMOJI and isinstance(converted_unicode, unicode) | 
|  | # PY2: str -> unicode | 
|  | assert converted_binary == self.UNICODE_EMOJI and isinstance(converted_unicode, unicode) | 
|  | else: | 
|  | # PY3: str -> str | 
|  | assert converted_unicode == self.UNICODE_EMOJI and isinstance(converted_unicode, str) | 
|  | # PY3: bytes -> str | 
|  | assert converted_binary == self.UNICODE_EMOJI and isinstance(converted_unicode, str) |