123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041 |
- # 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)
|