diff options
Diffstat (limited to 'testing/web-platform/tests/tools/six/test_six.py')
-rw-r--r-- | testing/web-platform/tests/tools/six/test_six.py | 787 |
1 files changed, 787 insertions, 0 deletions
diff --git a/testing/web-platform/tests/tools/six/test_six.py b/testing/web-platform/tests/tools/six/test_six.py new file mode 100644 index 000000000..d5555e8ac --- /dev/null +++ b/testing/web-platform/tests/tools/six/test_six.py @@ -0,0 +1,787 @@ +import operator +import sys +import types + +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_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 + + +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((OverflowError, ValueError), 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" + + +@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) + + +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 |