test_six.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858
  1. import operator
  2. import sys
  3. import types
  4. import unittest
  5. import py
  6. import six
  7. def test_add_doc():
  8. def f():
  9. """Icky doc"""
  10. pass
  11. six._add_doc(f, """New doc""")
  12. assert f.__doc__ == "New doc"
  13. def test_import_module():
  14. from logging import handlers
  15. m = six._import_module("logging.handlers")
  16. assert m is handlers
  17. def test_integer_types():
  18. assert isinstance(1, six.integer_types)
  19. assert isinstance(-1, six.integer_types)
  20. assert isinstance(six.MAXSIZE + 23, six.integer_types)
  21. assert not isinstance(.1, six.integer_types)
  22. def test_string_types():
  23. assert isinstance("hi", six.string_types)
  24. assert isinstance(six.u("hi"), six.string_types)
  25. assert issubclass(six.text_type, six.string_types)
  26. def test_class_types():
  27. class X:
  28. pass
  29. class Y(object):
  30. pass
  31. assert isinstance(X, six.class_types)
  32. assert isinstance(Y, six.class_types)
  33. assert not isinstance(X(), six.class_types)
  34. def test_text_type():
  35. assert type(six.u("hi")) is six.text_type
  36. def test_binary_type():
  37. assert type(six.b("hi")) is six.binary_type
  38. def test_MAXSIZE():
  39. try:
  40. # This shouldn't raise an overflow error.
  41. six.MAXSIZE.__index__()
  42. except AttributeError:
  43. # Before Python 2.6.
  44. pass
  45. py.test.raises(
  46. (ValueError, OverflowError),
  47. operator.mul, [None], six.MAXSIZE + 1)
  48. def test_lazy():
  49. if six.PY3:
  50. html_name = "html.parser"
  51. else:
  52. html_name = "HTMLParser"
  53. assert html_name not in sys.modules
  54. mod = six.moves.html_parser
  55. assert sys.modules[html_name] is mod
  56. assert "htmlparser" not in six._MovedItems.__dict__
  57. try:
  58. import _tkinter
  59. except ImportError:
  60. have_tkinter = False
  61. else:
  62. have_tkinter = True
  63. have_gdbm = True
  64. try:
  65. import gdbm
  66. except ImportError:
  67. try:
  68. import dbm.gnu
  69. except ImportError:
  70. have_gdbm = False
  71. @py.test.mark.parametrize("item_name",
  72. [item.name for item in six._moved_attributes])
  73. def test_move_items(item_name):
  74. """Ensure that everything loads correctly."""
  75. try:
  76. item = getattr(six.moves, item_name)
  77. if isinstance(item, types.ModuleType):
  78. __import__("six.moves." + item_name)
  79. except AttributeError:
  80. if item_name == "zip_longest" and sys.version_info < (2, 6):
  81. py.test.skip("zip_longest only available on 2.6+")
  82. except ImportError:
  83. if item_name == "winreg" and not sys.platform.startswith("win"):
  84. py.test.skip("Windows only module")
  85. if item_name.startswith("tkinter"):
  86. if not have_tkinter:
  87. py.test.skip("requires tkinter")
  88. if item_name == "tkinter_ttk" and sys.version_info[:2] <= (2, 6):
  89. py.test.skip("ttk only available on 2.7+")
  90. if item_name.startswith("dbm_gnu") and not have_gdbm:
  91. py.test.skip("requires gdbm")
  92. raise
  93. if sys.version_info[:2] >= (2, 6):
  94. assert item_name in dir(six.moves)
  95. @py.test.mark.parametrize("item_name",
  96. [item.name for item in six._urllib_parse_moved_attributes])
  97. def test_move_items_urllib_parse(item_name):
  98. """Ensure that everything loads correctly."""
  99. if item_name == "ParseResult" and sys.version_info < (2, 5):
  100. py.test.skip("ParseResult is only found on 2.5+")
  101. if item_name in ("parse_qs", "parse_qsl") and sys.version_info < (2, 6):
  102. py.test.skip("parse_qs[l] is new in 2.6")
  103. if sys.version_info[:2] >= (2, 6):
  104. assert item_name in dir(six.moves.urllib.parse)
  105. getattr(six.moves.urllib.parse, item_name)
  106. @py.test.mark.parametrize("item_name",
  107. [item.name for item in six._urllib_error_moved_attributes])
  108. def test_move_items_urllib_error(item_name):
  109. """Ensure that everything loads correctly."""
  110. if sys.version_info[:2] >= (2, 6):
  111. assert item_name in dir(six.moves.urllib.error)
  112. getattr(six.moves.urllib.error, item_name)
  113. @py.test.mark.parametrize("item_name",
  114. [item.name for item in six._urllib_request_moved_attributes])
  115. def test_move_items_urllib_request(item_name):
  116. """Ensure that everything loads correctly."""
  117. if sys.version_info[:2] >= (2, 6):
  118. assert item_name in dir(six.moves.urllib.request)
  119. getattr(six.moves.urllib.request, item_name)
  120. @py.test.mark.parametrize("item_name",
  121. [item.name for item in six._urllib_response_moved_attributes])
  122. def test_move_items_urllib_response(item_name):
  123. """Ensure that everything loads correctly."""
  124. if sys.version_info[:2] >= (2, 6):
  125. assert item_name in dir(six.moves.urllib.response)
  126. getattr(six.moves.urllib.response, item_name)
  127. @py.test.mark.parametrize("item_name",
  128. [item.name for item in six._urllib_robotparser_moved_attributes])
  129. def test_move_items_urllib_robotparser(item_name):
  130. """Ensure that everything loads correctly."""
  131. if sys.version_info[:2] >= (2, 6):
  132. assert item_name in dir(six.moves.urllib.robotparser)
  133. getattr(six.moves.urllib.robotparser, item_name)
  134. def test_import_moves_error_1():
  135. from six.moves.urllib.parse import urljoin
  136. from six import moves
  137. # In 1.4.1: AttributeError: 'Module_six_moves_urllib_parse' object has no attribute 'urljoin'
  138. assert moves.urllib.parse.urljoin
  139. def test_import_moves_error_2():
  140. from six import moves
  141. assert moves.urllib.parse.urljoin
  142. # In 1.4.1: ImportError: cannot import name urljoin
  143. from six.moves.urllib.parse import urljoin
  144. def test_import_moves_error_3():
  145. from six.moves.urllib.parse import urljoin
  146. # In 1.4.1: ImportError: cannot import name urljoin
  147. from six.moves.urllib_parse import urljoin
  148. def test_from_imports():
  149. from six.moves.queue import Queue
  150. assert isinstance(Queue, six.class_types)
  151. from six.moves.configparser import ConfigParser
  152. assert isinstance(ConfigParser, six.class_types)
  153. def test_filter():
  154. from six.moves import filter
  155. f = filter(lambda x: x % 2, range(10))
  156. assert six.advance_iterator(f) == 1
  157. def test_filter_false():
  158. from six.moves import filterfalse
  159. f = filterfalse(lambda x: x % 3, range(10))
  160. assert six.advance_iterator(f) == 0
  161. assert six.advance_iterator(f) == 3
  162. assert six.advance_iterator(f) == 6
  163. def test_map():
  164. from six.moves import map
  165. assert six.advance_iterator(map(lambda x: x + 1, range(2))) == 1
  166. def test_zip():
  167. from six.moves import zip
  168. assert six.advance_iterator(zip(range(2), range(2))) == (0, 0)
  169. @py.test.mark.skipif("sys.version_info < (2, 6)")
  170. def test_zip_longest():
  171. from six.moves import zip_longest
  172. it = zip_longest(range(2), range(1))
  173. assert six.advance_iterator(it) == (0, 0)
  174. assert six.advance_iterator(it) == (1, None)
  175. class TestCustomizedMoves:
  176. def teardown_method(self, meth):
  177. try:
  178. del six._MovedItems.spam
  179. except AttributeError:
  180. pass
  181. try:
  182. del six.moves.__dict__["spam"]
  183. except KeyError:
  184. pass
  185. def test_moved_attribute(self):
  186. attr = six.MovedAttribute("spam", "foo", "bar")
  187. if six.PY3:
  188. assert attr.mod == "bar"
  189. else:
  190. assert attr.mod == "foo"
  191. assert attr.attr == "spam"
  192. attr = six.MovedAttribute("spam", "foo", "bar", "lemma")
  193. assert attr.attr == "lemma"
  194. attr = six.MovedAttribute("spam", "foo", "bar", "lemma", "theorm")
  195. if six.PY3:
  196. assert attr.attr == "theorm"
  197. else:
  198. assert attr.attr == "lemma"
  199. def test_moved_module(self):
  200. attr = six.MovedModule("spam", "foo")
  201. if six.PY3:
  202. assert attr.mod == "spam"
  203. else:
  204. assert attr.mod == "foo"
  205. attr = six.MovedModule("spam", "foo", "bar")
  206. if six.PY3:
  207. assert attr.mod == "bar"
  208. else:
  209. assert attr.mod == "foo"
  210. def test_custom_move_module(self):
  211. attr = six.MovedModule("spam", "six", "six")
  212. six.add_move(attr)
  213. six.remove_move("spam")
  214. assert not hasattr(six.moves, "spam")
  215. attr = six.MovedModule("spam", "six", "six")
  216. six.add_move(attr)
  217. from six.moves import spam
  218. assert spam is six
  219. six.remove_move("spam")
  220. assert not hasattr(six.moves, "spam")
  221. def test_custom_move_attribute(self):
  222. attr = six.MovedAttribute("spam", "six", "six", "u", "u")
  223. six.add_move(attr)
  224. six.remove_move("spam")
  225. assert not hasattr(six.moves, "spam")
  226. attr = six.MovedAttribute("spam", "six", "six", "u", "u")
  227. six.add_move(attr)
  228. from six.moves import spam
  229. assert spam is six.u
  230. six.remove_move("spam")
  231. assert not hasattr(six.moves, "spam")
  232. def test_empty_remove(self):
  233. py.test.raises(AttributeError, six.remove_move, "eggs")
  234. def test_get_unbound_function():
  235. class X(object):
  236. def m(self):
  237. pass
  238. assert six.get_unbound_function(X.m) is X.__dict__["m"]
  239. def test_get_method_self():
  240. class X(object):
  241. def m(self):
  242. pass
  243. x = X()
  244. assert six.get_method_self(x.m) is x
  245. py.test.raises(AttributeError, six.get_method_self, 42)
  246. def test_get_method_function():
  247. class X(object):
  248. def m(self):
  249. pass
  250. x = X()
  251. assert six.get_method_function(x.m) is X.__dict__["m"]
  252. py.test.raises(AttributeError, six.get_method_function, hasattr)
  253. def test_get_function_closure():
  254. def f():
  255. x = 42
  256. def g():
  257. return x
  258. return g
  259. cell = six.get_function_closure(f())[0]
  260. assert type(cell).__name__ == "cell"
  261. def test_get_function_code():
  262. def f():
  263. pass
  264. assert isinstance(six.get_function_code(f), types.CodeType)
  265. if not hasattr(sys, "pypy_version_info"):
  266. py.test.raises(AttributeError, six.get_function_code, hasattr)
  267. def test_get_function_defaults():
  268. def f(x, y=3, b=4):
  269. pass
  270. assert six.get_function_defaults(f) == (3, 4)
  271. def test_get_function_globals():
  272. def f():
  273. pass
  274. assert six.get_function_globals(f) is globals()
  275. def test_dictionary_iterators(monkeypatch):
  276. def stock_method_name(iterwhat):
  277. """Given a method suffix like "lists" or "values", return the name
  278. of the dict method that delivers those on the version of Python
  279. we're running in."""
  280. if six.PY3:
  281. return iterwhat
  282. return 'iter' + iterwhat
  283. class MyDict(dict):
  284. if not six.PY3:
  285. def lists(self, **kw):
  286. return [1, 2, 3]
  287. def iterlists(self, **kw):
  288. return iter([1, 2, 3])
  289. f = MyDict.iterlists
  290. del MyDict.iterlists
  291. setattr(MyDict, stock_method_name('lists'), f)
  292. d = MyDict(zip(range(10), reversed(range(10))))
  293. for name in "keys", "values", "items", "lists":
  294. meth = getattr(six, "iter" + name)
  295. it = meth(d)
  296. assert not isinstance(it, list)
  297. assert list(it) == list(getattr(d, name)())
  298. py.test.raises(StopIteration, six.advance_iterator, it)
  299. record = []
  300. def with_kw(*args, **kw):
  301. record.append(kw["kw"])
  302. return old(*args)
  303. old = getattr(MyDict, stock_method_name(name))
  304. monkeypatch.setattr(MyDict, stock_method_name(name), with_kw)
  305. meth(d, kw=42)
  306. assert record == [42]
  307. monkeypatch.undo()
  308. @py.test.mark.skipif(sys.version_info[:2] < (2, 7),
  309. reason="view methods on dictionaries only available on 2.7+")
  310. def test_dictionary_views():
  311. def stock_method_name(viewwhat):
  312. """Given a method suffix like "keys" or "values", return the name
  313. of the dict method that delivers those on the version of Python
  314. we're running in."""
  315. if six.PY3:
  316. return viewwhat
  317. return 'view' + viewwhat
  318. d = dict(zip(range(10), (range(11, 20))))
  319. for name in "keys", "values", "items":
  320. meth = getattr(six, "view" + name)
  321. view = meth(d)
  322. assert set(view) == set(getattr(d, name)())
  323. def test_advance_iterator():
  324. assert six.next is six.advance_iterator
  325. l = [1, 2]
  326. it = iter(l)
  327. assert six.next(it) == 1
  328. assert six.next(it) == 2
  329. py.test.raises(StopIteration, six.next, it)
  330. py.test.raises(StopIteration, six.next, it)
  331. def test_iterator():
  332. class myiter(six.Iterator):
  333. def __next__(self):
  334. return 13
  335. assert six.advance_iterator(myiter()) == 13
  336. class myitersub(myiter):
  337. def __next__(self):
  338. return 14
  339. assert six.advance_iterator(myitersub()) == 14
  340. def test_callable():
  341. class X:
  342. def __call__(self):
  343. pass
  344. def method(self):
  345. pass
  346. assert six.callable(X)
  347. assert six.callable(X())
  348. assert six.callable(test_callable)
  349. assert six.callable(hasattr)
  350. assert six.callable(X.method)
  351. assert six.callable(X().method)
  352. assert not six.callable(4)
  353. assert not six.callable("string")
  354. def test_create_bound_method():
  355. class X(object):
  356. pass
  357. def f(self):
  358. return self
  359. x = X()
  360. b = six.create_bound_method(f, x)
  361. assert isinstance(b, types.MethodType)
  362. assert b() is x
  363. if six.PY3:
  364. def test_b():
  365. data = six.b("\xff")
  366. assert isinstance(data, bytes)
  367. assert len(data) == 1
  368. assert data == bytes([255])
  369. def test_u():
  370. s = six.u("hi \u0439 \U00000439 \\ \\\\ \n")
  371. assert isinstance(s, str)
  372. assert s == "hi \u0439 \U00000439 \\ \\\\ \n"
  373. else:
  374. def test_b():
  375. data = six.b("\xff")
  376. assert isinstance(data, str)
  377. assert len(data) == 1
  378. assert data == "\xff"
  379. def test_u():
  380. s = six.u("hi \u0439 \U00000439 \\ \\\\ \n")
  381. assert isinstance(s, unicode)
  382. assert s == "hi \xd0\xb9 \xd0\xb9 \\ \\\\ \n".decode("utf8")
  383. def test_u_escapes():
  384. s = six.u("\u1234")
  385. assert len(s) == 1
  386. def test_unichr():
  387. assert six.u("\u1234") == six.unichr(0x1234)
  388. assert type(six.u("\u1234")) is type(six.unichr(0x1234))
  389. def test_int2byte():
  390. assert six.int2byte(3) == six.b("\x03")
  391. py.test.raises((OverflowError, ValueError), six.int2byte, 256)
  392. def test_byte2int():
  393. assert six.byte2int(six.b("\x03")) == 3
  394. assert six.byte2int(six.b("\x03\x04")) == 3
  395. py.test.raises(IndexError, six.byte2int, six.b(""))
  396. def test_bytesindex():
  397. assert six.indexbytes(six.b("hello"), 3) == ord("l")
  398. def test_bytesiter():
  399. it = six.iterbytes(six.b("hi"))
  400. assert six.next(it) == ord("h")
  401. assert six.next(it) == ord("i")
  402. py.test.raises(StopIteration, six.next, it)
  403. def test_StringIO():
  404. fp = six.StringIO()
  405. fp.write(six.u("hello"))
  406. assert fp.getvalue() == six.u("hello")
  407. def test_BytesIO():
  408. fp = six.BytesIO()
  409. fp.write(six.b("hello"))
  410. assert fp.getvalue() == six.b("hello")
  411. def test_exec_():
  412. def f():
  413. l = []
  414. six.exec_("l.append(1)")
  415. assert l == [1]
  416. f()
  417. ns = {}
  418. six.exec_("x = 42", ns)
  419. assert ns["x"] == 42
  420. glob = {}
  421. loc = {}
  422. six.exec_("global y; y = 42; x = 12", glob, loc)
  423. assert glob["y"] == 42
  424. assert "x" not in glob
  425. assert loc["x"] == 12
  426. assert "y" not in loc
  427. def test_reraise():
  428. def get_next(tb):
  429. if six.PY3:
  430. return tb.tb_next.tb_next
  431. else:
  432. return tb.tb_next
  433. e = Exception("blah")
  434. try:
  435. raise e
  436. except Exception:
  437. tp, val, tb = sys.exc_info()
  438. try:
  439. six.reraise(tp, val, tb)
  440. except Exception:
  441. tp2, value2, tb2 = sys.exc_info()
  442. assert tp2 is Exception
  443. assert value2 is e
  444. assert tb is get_next(tb2)
  445. try:
  446. six.reraise(tp, val)
  447. except Exception:
  448. tp2, value2, tb2 = sys.exc_info()
  449. assert tp2 is Exception
  450. assert value2 is e
  451. assert tb2 is not tb
  452. try:
  453. six.reraise(tp, val, tb2)
  454. except Exception:
  455. tp2, value2, tb3 = sys.exc_info()
  456. assert tp2 is Exception
  457. assert value2 is e
  458. assert get_next(tb3) is tb2
  459. try:
  460. six.reraise(tp, None, tb)
  461. except Exception:
  462. tp2, value2, tb2 = sys.exc_info()
  463. assert tp2 is Exception
  464. assert value2 is not val
  465. assert isinstance(value2, Exception)
  466. assert tb is get_next(tb2)
  467. def test_raise_from():
  468. try:
  469. try:
  470. raise Exception("blah")
  471. except Exception:
  472. ctx = sys.exc_info()[1]
  473. f = Exception("foo")
  474. six.raise_from(f, None)
  475. except Exception:
  476. tp, val, tb = sys.exc_info()
  477. if sys.version_info[:2] > (3, 0):
  478. # We should have done a raise f from None equivalent.
  479. assert val.__cause__ is None
  480. assert val.__context__ is ctx
  481. if sys.version_info[:2] >= (3, 3):
  482. # And that should suppress the context on the exception.
  483. assert val.__suppress_context__
  484. # For all versions the outer exception should have raised successfully.
  485. assert str(val) == "foo"
  486. def test_print_():
  487. save = sys.stdout
  488. out = sys.stdout = six.moves.StringIO()
  489. try:
  490. six.print_("Hello,", "person!")
  491. finally:
  492. sys.stdout = save
  493. assert out.getvalue() == "Hello, person!\n"
  494. out = six.StringIO()
  495. six.print_("Hello,", "person!", file=out)
  496. assert out.getvalue() == "Hello, person!\n"
  497. out = six.StringIO()
  498. six.print_("Hello,", "person!", file=out, end="")
  499. assert out.getvalue() == "Hello, person!"
  500. out = six.StringIO()
  501. six.print_("Hello,", "person!", file=out, sep="X")
  502. assert out.getvalue() == "Hello,Xperson!\n"
  503. out = six.StringIO()
  504. six.print_(six.u("Hello,"), six.u("person!"), file=out)
  505. result = out.getvalue()
  506. assert isinstance(result, six.text_type)
  507. assert result == six.u("Hello, person!\n")
  508. six.print_("Hello", file=None) # This works.
  509. out = six.StringIO()
  510. six.print_(None, file=out)
  511. assert out.getvalue() == "None\n"
  512. class FlushableStringIO(six.StringIO):
  513. def __init__(self):
  514. six.StringIO.__init__(self)
  515. self.flushed = False
  516. def flush(self):
  517. self.flushed = True
  518. out = FlushableStringIO()
  519. six.print_("Hello", file=out)
  520. assert not out.flushed
  521. six.print_("Hello", file=out, flush=True)
  522. assert out.flushed
  523. @py.test.mark.skipif("sys.version_info[:2] >= (2, 6)")
  524. def test_print_encoding(monkeypatch):
  525. # Fool the type checking in print_.
  526. monkeypatch.setattr(six, "file", six.BytesIO, raising=False)
  527. out = six.BytesIO()
  528. out.encoding = "utf-8"
  529. out.errors = None
  530. six.print_(six.u("\u053c"), end="", file=out)
  531. assert out.getvalue() == six.b("\xd4\xbc")
  532. out = six.BytesIO()
  533. out.encoding = "ascii"
  534. out.errors = "strict"
  535. py.test.raises(UnicodeEncodeError, six.print_, six.u("\u053c"), file=out)
  536. out.errors = "backslashreplace"
  537. six.print_(six.u("\u053c"), end="", file=out)
  538. assert out.getvalue() == six.b("\\u053c")
  539. def test_print_exceptions():
  540. py.test.raises(TypeError, six.print_, x=3)
  541. py.test.raises(TypeError, six.print_, end=3)
  542. py.test.raises(TypeError, six.print_, sep=42)
  543. def test_with_metaclass():
  544. class Meta(type):
  545. pass
  546. class X(six.with_metaclass(Meta)):
  547. pass
  548. assert type(X) is Meta
  549. assert issubclass(X, object)
  550. class Base(object):
  551. pass
  552. class X(six.with_metaclass(Meta, Base)):
  553. pass
  554. assert type(X) is Meta
  555. assert issubclass(X, Base)
  556. class Base2(object):
  557. pass
  558. class X(six.with_metaclass(Meta, Base, Base2)):
  559. pass
  560. assert type(X) is Meta
  561. assert issubclass(X, Base)
  562. assert issubclass(X, Base2)
  563. assert X.__mro__ == (X, Base, Base2, object)
  564. def test_wraps():
  565. def f(g):
  566. @six.wraps(g)
  567. def w():
  568. return 42
  569. return w
  570. def k():
  571. pass
  572. original_k = k
  573. k = f(f(k))
  574. assert hasattr(k, '__wrapped__')
  575. k = k.__wrapped__
  576. assert hasattr(k, '__wrapped__')
  577. k = k.__wrapped__
  578. assert k is original_k
  579. assert not hasattr(k, '__wrapped__')
  580. def f(g, assign, update):
  581. def w():
  582. return 42
  583. w.glue = {"foo" : "bar"}
  584. return six.wraps(g, assign, update)(w)
  585. k.glue = {"melon" : "egg"}
  586. k.turnip = 43
  587. k = f(k, ["turnip"], ["glue"])
  588. assert k.__name__ == "w"
  589. assert k.turnip == 43
  590. assert k.glue == {"melon" : "egg", "foo" : "bar"}
  591. def test_add_metaclass():
  592. class Meta(type):
  593. pass
  594. class X:
  595. "success"
  596. X = six.add_metaclass(Meta)(X)
  597. assert type(X) is Meta
  598. assert issubclass(X, object)
  599. assert X.__module__ == __name__
  600. assert X.__doc__ == "success"
  601. class Base(object):
  602. pass
  603. class X(Base):
  604. pass
  605. X = six.add_metaclass(Meta)(X)
  606. assert type(X) is Meta
  607. assert issubclass(X, Base)
  608. class Base2(object):
  609. pass
  610. class X(Base, Base2):
  611. pass
  612. X = six.add_metaclass(Meta)(X)
  613. assert type(X) is Meta
  614. assert issubclass(X, Base)
  615. assert issubclass(X, Base2)
  616. # Test a second-generation subclass of a type.
  617. class Meta1(type):
  618. m1 = "m1"
  619. class Meta2(Meta1):
  620. m2 = "m2"
  621. class Base:
  622. b = "b"
  623. Base = six.add_metaclass(Meta1)(Base)
  624. class X(Base):
  625. x = "x"
  626. X = six.add_metaclass(Meta2)(X)
  627. assert type(X) is Meta2
  628. assert issubclass(X, Base)
  629. assert type(Base) is Meta1
  630. assert "__dict__" not in vars(X)
  631. instance = X()
  632. instance.attr = "test"
  633. assert vars(instance) == {"attr": "test"}
  634. assert instance.b == Base.b
  635. assert instance.x == X.x
  636. # Test a class with slots.
  637. class MySlots(object):
  638. __slots__ = ["a", "b"]
  639. MySlots = six.add_metaclass(Meta1)(MySlots)
  640. assert MySlots.__slots__ == ["a", "b"]
  641. instance = MySlots()
  642. instance.a = "foo"
  643. py.test.raises(AttributeError, setattr, instance, "c", "baz")
  644. # Test a class with string for slots.
  645. class MyStringSlots(object):
  646. __slots__ = "ab"
  647. MyStringSlots = six.add_metaclass(Meta1)(MyStringSlots)
  648. assert MyStringSlots.__slots__ == "ab"
  649. instance = MyStringSlots()
  650. instance.ab = "foo"
  651. py.test.raises(AttributeError, setattr, instance, "a", "baz")
  652. py.test.raises(AttributeError, setattr, instance, "b", "baz")
  653. class MySlotsWeakref(object):
  654. __slots__ = "__weakref__",
  655. MySlotsWeakref = six.add_metaclass(Meta)(MySlotsWeakref)
  656. assert type(MySlotsWeakref) is Meta
  657. @py.test.mark.skipif("sys.version_info[:2] < (2, 7)")
  658. def test_assertCountEqual():
  659. class TestAssertCountEqual(unittest.TestCase):
  660. def test(self):
  661. with self.assertRaises(AssertionError):
  662. six.assertCountEqual(self, (1, 2), [3, 4, 5])
  663. six.assertCountEqual(self, (1, 2), [2, 1])
  664. TestAssertCountEqual('test').test()
  665. @py.test.mark.skipif("sys.version_info[:2] < (2, 7)")
  666. def test_assertRegex():
  667. class TestAssertRegex(unittest.TestCase):
  668. def test(self):
  669. with self.assertRaises(AssertionError):
  670. six.assertRegex(self, 'test', r'^a')
  671. six.assertRegex(self, 'test', r'^t')
  672. TestAssertRegex('test').test()
  673. @py.test.mark.skipif("sys.version_info[:2] < (2, 7)")
  674. def test_assertRaisesRegex():
  675. class TestAssertRaisesRegex(unittest.TestCase):
  676. def test(self):
  677. with six.assertRaisesRegex(self, AssertionError, '^Foo'):
  678. raise AssertionError('Foo')
  679. with self.assertRaises(AssertionError):
  680. with six.assertRaisesRegex(self, AssertionError, r'^Foo'):
  681. raise AssertionError('Bar')
  682. TestAssertRaisesRegex('test').test()
  683. def test_python_2_unicode_compatible():
  684. @six.python_2_unicode_compatible
  685. class MyTest(object):
  686. def __str__(self):
  687. return six.u('hello')
  688. def __bytes__(self):
  689. return six.b('hello')
  690. my_test = MyTest()
  691. if six.PY2:
  692. assert str(my_test) == six.b("hello")
  693. assert unicode(my_test) == six.u("hello")
  694. elif six.PY3:
  695. assert bytes(my_test) == six.b("hello")
  696. assert str(my_test) == six.u("hello")
  697. assert getattr(six.moves.builtins, 'bytes', str)(my_test) == six.b("hello")