| # Copyright (c) 2010-2018 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 py |
| |
| 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 |
| py.test.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 |
| |
| @py.test.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 AttributeError: |
| if item_name == "zip_longest" and sys.version_info < (2, 6): |
| py.test.skip("zip_longest only available on 2.6+") |
| except ImportError: |
| if item_name == "winreg" and not sys.platform.startswith("win"): |
| py.test.skip("Windows only module") |
| if item_name.startswith("tkinter"): |
| if not have_tkinter: |
| py.test.skip("requires tkinter") |
| if item_name == "tkinter_ttk" and sys.version_info[:2] <= (2, 6): |
| py.test.skip("ttk only available on 2.7+") |
| if item_name.startswith("dbm_gnu") and not have_gdbm: |
| py.test.skip("requires gdbm") |
| raise |
| if sys.version_info[:2] >= (2, 6): |
| assert item_name in dir(six.moves) |
| |
| |
| @py.test.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.""" |
| if item_name == "ParseResult" and sys.version_info < (2, 5): |
| py.test.skip("ParseResult is only found on 2.5+") |
| if item_name in ("parse_qs", "parse_qsl") and sys.version_info < (2, 6): |
| py.test.skip("parse_qs[l] is new in 2.6") |
| if sys.version_info[:2] >= (2, 6): |
| assert item_name in dir(six.moves.urllib.parse) |
| getattr(six.moves.urllib.parse, item_name) |
| |
| |
| @py.test.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.""" |
| if sys.version_info[:2] >= (2, 6): |
| assert item_name in dir(six.moves.urllib.error) |
| getattr(six.moves.urllib.error, item_name) |
| |
| |
| @py.test.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.""" |
| if sys.version_info[:2] >= (2, 6): |
| assert item_name in dir(six.moves.urllib.request) |
| getattr(six.moves.urllib.request, item_name) |
| |
| |
| @py.test.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.""" |
| if sys.version_info[:2] >= (2, 6): |
| assert item_name in dir(six.moves.urllib.response) |
| getattr(six.moves.urllib.response, item_name) |
| |
| |
| @py.test.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.""" |
| if sys.version_info[:2] >= (2, 6): |
| 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) |
| |
| |
| @py.test.mark.skipif("sys.version_info < (2, 6)") |
| 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): |
| py.test.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 |
| py.test.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"] |
| py.test.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"): |
| py.test.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)()) |
| py.test.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() |
| |
| |
| @py.test.mark.skipif("sys.version_info[:2] < (2, 7)", |
| reason="view methods on dictionaries only available on 2.7+") |
| def test_dictionary_views(): |
| def stock_method_name(viewwhat): |
| """Given a method suffix like "keys" 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 viewwhat |
| return 'view' + viewwhat |
| |
| 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 |
| py.test.raises(StopIteration, six.next, it) |
| py.test.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) |
| py.test.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") |
| py.test.raises(Exception, six.int2byte, 256) |
| |
| |
| def test_byte2int(): |
| assert six.byte2int(six.b("\x03")) == 3 |
| assert six.byte2int(six.b("\x03\x04")) == 3 |
| py.test.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") |
| py.test.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 |
| if sys.version_info[:2] >= (3, 3): |
| # 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 |
| |
| |
| @py.test.mark.skipif("sys.version_info[:2] >= (2, 6)") |
| def test_print_encoding(monkeypatch): |
| # Fool the type checking in print_. |
| monkeypatch.setattr(six, "file", six.BytesIO, raising=False) |
| out = six.BytesIO() |
| out.encoding = "utf-8" |
| out.errors = None |
| six.print_(six.u("\u053c"), end="", file=out) |
| assert out.getvalue() == six.b("\xd4\xbc") |
| out = six.BytesIO() |
| out.encoding = "ascii" |
| out.errors = "strict" |
| py.test.raises(UnicodeEncodeError, six.print_, six.u("\u053c"), file=out) |
| out.errors = "backslashreplace" |
| six.print_(six.u("\u053c"), end="", file=out) |
| assert out.getvalue() == six.b("\\u053c") |
| |
| |
| def test_print_exceptions(): |
| py.test.raises(TypeError, six.print_, x=3) |
| py.test.raises(TypeError, six.print_, end=3) |
| py.test.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) |
| |
| |
| @py.test.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"} |
| return six.wraps(g, assign, update)(w) |
| k.glue = {"melon" : "egg"} |
| k.turnip = 43 |
| k = f(k, ["turnip"], ["glue"]) |
| assert k.__name__ == "w" |
| assert k.turnip == 43 |
| assert k.glue == {"melon" : "egg", "foo" : "bar"} |
| |
| |
| 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" |
| py.test.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" |
| py.test.raises(AttributeError, setattr, instance, "a", "baz") |
| py.test.raises(AttributeError, setattr, instance, "b", "baz") |
| |
| class MySlotsWeakref(object): |
| __slots__ = "__weakref__", |
| MySlotsWeakref = six.add_metaclass(Meta)(MySlotsWeakref) |
| assert type(MySlotsWeakref) is Meta |
| |
| |
| @py.test.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 |
| |
| |
| @py.test.mark.skipif("sys.version_info[:2] < (2, 7) or sys.version_info[:2] in ((3, 0), (3, 1))") |
| 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() |
| |
| |
| @py.test.mark.skipif("sys.version_info[:2] < (2, 7)") |
| 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() |
| |
| |
| @py.test.mark.skipif("sys.version_info[:2] < (2, 7)") |
| 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 py.test.raises(TypeError): |
| six.ensure_str(8) |
| |
| def test_errors_and_encoding(self): |
| six.ensure_binary(self.UNICODE_EMOJI, encoding='latin-1', errors='ignore') |
| with py.test.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) |