1# Copyright (c) 2010-2015 Benjamin Peterson 2# 3# Permission is hereby granted, free of charge, to any person obtaining a copy 4# of this software and associated documentation files (the "Software"), to deal 5# in the Software without restriction, including without limitation the rights 6# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7# copies of the Software, and to permit persons to whom the Software is 8# furnished to do so, subject to the following conditions: 9# 10# The above copyright notice and this permission notice shall be included in all 11# copies or substantial portions of the Software. 12# 13# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19# SOFTWARE. 20 21import operator 22import sys 23import types 24import unittest 25 26import py 27 28import six 29 30 31def test_add_doc(): 32 def f(): 33 """Icky doc""" 34 pass 35 six._add_doc(f, """New doc""") 36 assert f.__doc__ == "New doc" 37 38 39def test_import_module(): 40 from logging import handlers 41 m = six._import_module("logging.handlers") 42 assert m is handlers 43 44 45def test_integer_types(): 46 assert isinstance(1, six.integer_types) 47 assert isinstance(-1, six.integer_types) 48 assert isinstance(six.MAXSIZE + 23, six.integer_types) 49 assert not isinstance(.1, six.integer_types) 50 51 52def test_string_types(): 53 assert isinstance("hi", six.string_types) 54 assert isinstance(six.u("hi"), six.string_types) 55 assert issubclass(six.text_type, six.string_types) 56 57 58def test_class_types(): 59 class X: 60 pass 61 class Y(object): 62 pass 63 assert isinstance(X, six.class_types) 64 assert isinstance(Y, six.class_types) 65 assert not isinstance(X(), six.class_types) 66 67 68def test_text_type(): 69 assert type(six.u("hi")) is six.text_type 70 71 72def test_binary_type(): 73 assert type(six.b("hi")) is six.binary_type 74 75 76def test_MAXSIZE(): 77 try: 78 # This shouldn't raise an overflow error. 79 six.MAXSIZE.__index__() 80 except AttributeError: 81 # Before Python 2.6. 82 pass 83 py.test.raises( 84 (ValueError, OverflowError), 85 operator.mul, [None], six.MAXSIZE + 1) 86 87 88def test_lazy(): 89 if six.PY3: 90 html_name = "html.parser" 91 else: 92 html_name = "HTMLParser" 93 assert html_name not in sys.modules 94 mod = six.moves.html_parser 95 assert sys.modules[html_name] is mod 96 assert "htmlparser" not in six._MovedItems.__dict__ 97 98 99try: 100 import _tkinter 101except ImportError: 102 have_tkinter = False 103else: 104 have_tkinter = True 105 106have_gdbm = True 107try: 108 import gdbm 109except ImportError: 110 try: 111 import dbm.gnu 112 except ImportError: 113 have_gdbm = False 114 115@py.test.mark.parametrize("item_name", 116 [item.name for item in six._moved_attributes]) 117def test_move_items(item_name): 118 """Ensure that everything loads correctly.""" 119 try: 120 item = getattr(six.moves, item_name) 121 if isinstance(item, types.ModuleType): 122 __import__("six.moves." + item_name) 123 except AttributeError: 124 if item_name == "zip_longest" and sys.version_info < (2, 6): 125 py.test.skip("zip_longest only available on 2.6+") 126 except ImportError: 127 if item_name == "winreg" and not sys.platform.startswith("win"): 128 py.test.skip("Windows only module") 129 if item_name.startswith("tkinter"): 130 if not have_tkinter: 131 py.test.skip("requires tkinter") 132 if item_name == "tkinter_ttk" and sys.version_info[:2] <= (2, 6): 133 py.test.skip("ttk only available on 2.7+") 134 if item_name.startswith("dbm_gnu") and not have_gdbm: 135 py.test.skip("requires gdbm") 136 raise 137 if sys.version_info[:2] >= (2, 6): 138 assert item_name in dir(six.moves) 139 140 141@py.test.mark.parametrize("item_name", 142 [item.name for item in six._urllib_parse_moved_attributes]) 143def test_move_items_urllib_parse(item_name): 144 """Ensure that everything loads correctly.""" 145 if item_name == "ParseResult" and sys.version_info < (2, 5): 146 py.test.skip("ParseResult is only found on 2.5+") 147 if item_name in ("parse_qs", "parse_qsl") and sys.version_info < (2, 6): 148 py.test.skip("parse_qs[l] is new in 2.6") 149 if sys.version_info[:2] >= (2, 6): 150 assert item_name in dir(six.moves.urllib.parse) 151 getattr(six.moves.urllib.parse, item_name) 152 153 154@py.test.mark.parametrize("item_name", 155 [item.name for item in six._urllib_error_moved_attributes]) 156def test_move_items_urllib_error(item_name): 157 """Ensure that everything loads correctly.""" 158 if sys.version_info[:2] >= (2, 6): 159 assert item_name in dir(six.moves.urllib.error) 160 getattr(six.moves.urllib.error, item_name) 161 162 163@py.test.mark.parametrize("item_name", 164 [item.name for item in six._urllib_request_moved_attributes]) 165def test_move_items_urllib_request(item_name): 166 """Ensure that everything loads correctly.""" 167 if sys.version_info[:2] >= (2, 6): 168 assert item_name in dir(six.moves.urllib.request) 169 getattr(six.moves.urllib.request, item_name) 170 171 172@py.test.mark.parametrize("item_name", 173 [item.name for item in six._urllib_response_moved_attributes]) 174def test_move_items_urllib_response(item_name): 175 """Ensure that everything loads correctly.""" 176 if sys.version_info[:2] >= (2, 6): 177 assert item_name in dir(six.moves.urllib.response) 178 getattr(six.moves.urllib.response, item_name) 179 180 181@py.test.mark.parametrize("item_name", 182 [item.name for item in six._urllib_robotparser_moved_attributes]) 183def test_move_items_urllib_robotparser(item_name): 184 """Ensure that everything loads correctly.""" 185 if sys.version_info[:2] >= (2, 6): 186 assert item_name in dir(six.moves.urllib.robotparser) 187 getattr(six.moves.urllib.robotparser, item_name) 188 189 190def test_import_moves_error_1(): 191 from six.moves.urllib.parse import urljoin 192 from six import moves 193 # In 1.4.1: AttributeError: 'Module_six_moves_urllib_parse' object has no attribute 'urljoin' 194 assert moves.urllib.parse.urljoin 195 196 197def test_import_moves_error_2(): 198 from six import moves 199 assert moves.urllib.parse.urljoin 200 # In 1.4.1: ImportError: cannot import name urljoin 201 from six.moves.urllib.parse import urljoin 202 203 204def test_import_moves_error_3(): 205 from six.moves.urllib.parse import urljoin 206 # In 1.4.1: ImportError: cannot import name urljoin 207 from six.moves.urllib_parse import urljoin 208 209 210def test_from_imports(): 211 from six.moves.queue import Queue 212 assert isinstance(Queue, six.class_types) 213 from six.moves.configparser import ConfigParser 214 assert isinstance(ConfigParser, six.class_types) 215 216 217def test_filter(): 218 from six.moves import filter 219 f = filter(lambda x: x % 2, range(10)) 220 assert six.advance_iterator(f) == 1 221 222 223def test_filter_false(): 224 from six.moves import filterfalse 225 f = filterfalse(lambda x: x % 3, range(10)) 226 assert six.advance_iterator(f) == 0 227 assert six.advance_iterator(f) == 3 228 assert six.advance_iterator(f) == 6 229 230def test_map(): 231 from six.moves import map 232 assert six.advance_iterator(map(lambda x: x + 1, range(2))) == 1 233 234 235def test_zip(): 236 from six.moves import zip 237 assert six.advance_iterator(zip(range(2), range(2))) == (0, 0) 238 239 240@py.test.mark.skipif("sys.version_info < (2, 6)") 241def test_zip_longest(): 242 from six.moves import zip_longest 243 it = zip_longest(range(2), range(1)) 244 245 assert six.advance_iterator(it) == (0, 0) 246 assert six.advance_iterator(it) == (1, None) 247 248 249class TestCustomizedMoves: 250 251 def teardown_method(self, meth): 252 try: 253 del six._MovedItems.spam 254 except AttributeError: 255 pass 256 try: 257 del six.moves.__dict__["spam"] 258 except KeyError: 259 pass 260 261 262 def test_moved_attribute(self): 263 attr = six.MovedAttribute("spam", "foo", "bar") 264 if six.PY3: 265 assert attr.mod == "bar" 266 else: 267 assert attr.mod == "foo" 268 assert attr.attr == "spam" 269 attr = six.MovedAttribute("spam", "foo", "bar", "lemma") 270 assert attr.attr == "lemma" 271 attr = six.MovedAttribute("spam", "foo", "bar", "lemma", "theorm") 272 if six.PY3: 273 assert attr.attr == "theorm" 274 else: 275 assert attr.attr == "lemma" 276 277 278 def test_moved_module(self): 279 attr = six.MovedModule("spam", "foo") 280 if six.PY3: 281 assert attr.mod == "spam" 282 else: 283 assert attr.mod == "foo" 284 attr = six.MovedModule("spam", "foo", "bar") 285 if six.PY3: 286 assert attr.mod == "bar" 287 else: 288 assert attr.mod == "foo" 289 290 291 def test_custom_move_module(self): 292 attr = six.MovedModule("spam", "six", "six") 293 six.add_move(attr) 294 six.remove_move("spam") 295 assert not hasattr(six.moves, "spam") 296 attr = six.MovedModule("spam", "six", "six") 297 six.add_move(attr) 298 from six.moves import spam 299 assert spam is six 300 six.remove_move("spam") 301 assert not hasattr(six.moves, "spam") 302 303 304 def test_custom_move_attribute(self): 305 attr = six.MovedAttribute("spam", "six", "six", "u", "u") 306 six.add_move(attr) 307 six.remove_move("spam") 308 assert not hasattr(six.moves, "spam") 309 attr = six.MovedAttribute("spam", "six", "six", "u", "u") 310 six.add_move(attr) 311 from six.moves import spam 312 assert spam is six.u 313 six.remove_move("spam") 314 assert not hasattr(six.moves, "spam") 315 316 317 def test_empty_remove(self): 318 py.test.raises(AttributeError, six.remove_move, "eggs") 319 320 321def test_get_unbound_function(): 322 class X(object): 323 def m(self): 324 pass 325 assert six.get_unbound_function(X.m) is X.__dict__["m"] 326 327 328def test_get_method_self(): 329 class X(object): 330 def m(self): 331 pass 332 x = X() 333 assert six.get_method_self(x.m) is x 334 py.test.raises(AttributeError, six.get_method_self, 42) 335 336 337def test_get_method_function(): 338 class X(object): 339 def m(self): 340 pass 341 x = X() 342 assert six.get_method_function(x.m) is X.__dict__["m"] 343 py.test.raises(AttributeError, six.get_method_function, hasattr) 344 345 346def test_get_function_closure(): 347 def f(): 348 x = 42 349 def g(): 350 return x 351 return g 352 cell = six.get_function_closure(f())[0] 353 assert type(cell).__name__ == "cell" 354 355 356def test_get_function_code(): 357 def f(): 358 pass 359 assert isinstance(six.get_function_code(f), types.CodeType) 360 if not hasattr(sys, "pypy_version_info"): 361 py.test.raises(AttributeError, six.get_function_code, hasattr) 362 363 364def test_get_function_defaults(): 365 def f(x, y=3, b=4): 366 pass 367 assert six.get_function_defaults(f) == (3, 4) 368 369 370def test_get_function_globals(): 371 def f(): 372 pass 373 assert six.get_function_globals(f) is globals() 374 375 376def test_dictionary_iterators(monkeypatch): 377 def stock_method_name(iterwhat): 378 """Given a method suffix like "lists" or "values", return the name 379 of the dict method that delivers those on the version of Python 380 we're running in.""" 381 if six.PY3: 382 return iterwhat 383 return 'iter' + iterwhat 384 385 class MyDict(dict): 386 if not six.PY3: 387 def lists(self, **kw): 388 return [1, 2, 3] 389 def iterlists(self, **kw): 390 return iter([1, 2, 3]) 391 f = MyDict.iterlists 392 del MyDict.iterlists 393 setattr(MyDict, stock_method_name('lists'), f) 394 395 d = MyDict(zip(range(10), reversed(range(10)))) 396 for name in "keys", "values", "items", "lists": 397 meth = getattr(six, "iter" + name) 398 it = meth(d) 399 assert not isinstance(it, list) 400 assert list(it) == list(getattr(d, name)()) 401 py.test.raises(StopIteration, six.advance_iterator, it) 402 record = [] 403 def with_kw(*args, **kw): 404 record.append(kw["kw"]) 405 return old(*args) 406 old = getattr(MyDict, stock_method_name(name)) 407 monkeypatch.setattr(MyDict, stock_method_name(name), with_kw) 408 meth(d, kw=42) 409 assert record == [42] 410 monkeypatch.undo() 411 412 413@py.test.mark.skipif("sys.version_info[:2] < (2, 7)", 414 reason="view methods on dictionaries only available on 2.7+") 415def test_dictionary_views(): 416 def stock_method_name(viewwhat): 417 """Given a method suffix like "keys" or "values", return the name 418 of the dict method that delivers those on the version of Python 419 we're running in.""" 420 if six.PY3: 421 return viewwhat 422 return 'view' + viewwhat 423 424 d = dict(zip(range(10), (range(11, 20)))) 425 for name in "keys", "values", "items": 426 meth = getattr(six, "view" + name) 427 view = meth(d) 428 assert set(view) == set(getattr(d, name)()) 429 430 431def test_advance_iterator(): 432 assert six.next is six.advance_iterator 433 l = [1, 2] 434 it = iter(l) 435 assert six.next(it) == 1 436 assert six.next(it) == 2 437 py.test.raises(StopIteration, six.next, it) 438 py.test.raises(StopIteration, six.next, it) 439 440 441def test_iterator(): 442 class myiter(six.Iterator): 443 def __next__(self): 444 return 13 445 assert six.advance_iterator(myiter()) == 13 446 class myitersub(myiter): 447 def __next__(self): 448 return 14 449 assert six.advance_iterator(myitersub()) == 14 450 451 452def test_callable(): 453 class X: 454 def __call__(self): 455 pass 456 def method(self): 457 pass 458 assert six.callable(X) 459 assert six.callable(X()) 460 assert six.callable(test_callable) 461 assert six.callable(hasattr) 462 assert six.callable(X.method) 463 assert six.callable(X().method) 464 assert not six.callable(4) 465 assert not six.callable("string") 466 467 468def test_create_bound_method(): 469 class X(object): 470 pass 471 def f(self): 472 return self 473 x = X() 474 b = six.create_bound_method(f, x) 475 assert isinstance(b, types.MethodType) 476 assert b() is x 477 478 479def test_create_unbound_method(): 480 class X(object): 481 pass 482 483 def f(self): 484 return self 485 u = six.create_unbound_method(f, X) 486 py.test.raises(TypeError, u) 487 if six.PY2: 488 assert isinstance(u, types.MethodType) 489 x = X() 490 assert f(x) is x 491 492 493if six.PY3: 494 495 def test_b(): 496 data = six.b("\xff") 497 assert isinstance(data, bytes) 498 assert len(data) == 1 499 assert data == bytes([255]) 500 501 502 def test_u(): 503 s = six.u("hi \u0439 \U00000439 \\ \\\\ \n") 504 assert isinstance(s, str) 505 assert s == "hi \u0439 \U00000439 \\ \\\\ \n" 506 507else: 508 509 def test_b(): 510 data = six.b("\xff") 511 assert isinstance(data, str) 512 assert len(data) == 1 513 assert data == "\xff" 514 515 516 def test_u(): 517 s = six.u("hi \u0439 \U00000439 \\ \\\\ \n") 518 assert isinstance(s, unicode) 519 assert s == "hi \xd0\xb9 \xd0\xb9 \\ \\\\ \n".decode("utf8") 520 521 522def test_u_escapes(): 523 s = six.u("\u1234") 524 assert len(s) == 1 525 526 527def test_unichr(): 528 assert six.u("\u1234") == six.unichr(0x1234) 529 assert type(six.u("\u1234")) is type(six.unichr(0x1234)) 530 531 532def test_int2byte(): 533 assert six.int2byte(3) == six.b("\x03") 534 py.test.raises(Exception, six.int2byte, 256) 535 536 537def test_byte2int(): 538 assert six.byte2int(six.b("\x03")) == 3 539 assert six.byte2int(six.b("\x03\x04")) == 3 540 py.test.raises(IndexError, six.byte2int, six.b("")) 541 542 543def test_bytesindex(): 544 assert six.indexbytes(six.b("hello"), 3) == ord("l") 545 546 547def test_bytesiter(): 548 it = six.iterbytes(six.b("hi")) 549 assert six.next(it) == ord("h") 550 assert six.next(it) == ord("i") 551 py.test.raises(StopIteration, six.next, it) 552 553 554def test_StringIO(): 555 fp = six.StringIO() 556 fp.write(six.u("hello")) 557 assert fp.getvalue() == six.u("hello") 558 559 560def test_BytesIO(): 561 fp = six.BytesIO() 562 fp.write(six.b("hello")) 563 assert fp.getvalue() == six.b("hello") 564 565 566def test_exec_(): 567 def f(): 568 l = [] 569 six.exec_("l.append(1)") 570 assert l == [1] 571 f() 572 ns = {} 573 six.exec_("x = 42", ns) 574 assert ns["x"] == 42 575 glob = {} 576 loc = {} 577 six.exec_("global y; y = 42; x = 12", glob, loc) 578 assert glob["y"] == 42 579 assert "x" not in glob 580 assert loc["x"] == 12 581 assert "y" not in loc 582 583 584def test_reraise(): 585 def get_next(tb): 586 if six.PY3: 587 return tb.tb_next.tb_next 588 else: 589 return tb.tb_next 590 e = Exception("blah") 591 try: 592 raise e 593 except Exception: 594 tp, val, tb = sys.exc_info() 595 try: 596 six.reraise(tp, val, tb) 597 except Exception: 598 tp2, value2, tb2 = sys.exc_info() 599 assert tp2 is Exception 600 assert value2 is e 601 assert tb is get_next(tb2) 602 try: 603 six.reraise(tp, val) 604 except Exception: 605 tp2, value2, tb2 = sys.exc_info() 606 assert tp2 is Exception 607 assert value2 is e 608 assert tb2 is not tb 609 try: 610 six.reraise(tp, val, tb2) 611 except Exception: 612 tp2, value2, tb3 = sys.exc_info() 613 assert tp2 is Exception 614 assert value2 is e 615 assert get_next(tb3) is tb2 616 try: 617 six.reraise(tp, None, tb) 618 except Exception: 619 tp2, value2, tb2 = sys.exc_info() 620 assert tp2 is Exception 621 assert value2 is not val 622 assert isinstance(value2, Exception) 623 assert tb is get_next(tb2) 624 625 626def test_raise_from(): 627 try: 628 try: 629 raise Exception("blah") 630 except Exception: 631 ctx = sys.exc_info()[1] 632 f = Exception("foo") 633 six.raise_from(f, None) 634 except Exception: 635 tp, val, tb = sys.exc_info() 636 if sys.version_info[:2] > (3, 0): 637 # We should have done a raise f from None equivalent. 638 assert val.__cause__ is None 639 assert val.__context__ is ctx 640 if sys.version_info[:2] >= (3, 3): 641 # And that should suppress the context on the exception. 642 assert val.__suppress_context__ 643 # For all versions the outer exception should have raised successfully. 644 assert str(val) == "foo" 645 646 647def test_print_(): 648 save = sys.stdout 649 out = sys.stdout = six.moves.StringIO() 650 try: 651 six.print_("Hello,", "person!") 652 finally: 653 sys.stdout = save 654 assert out.getvalue() == "Hello, person!\n" 655 out = six.StringIO() 656 six.print_("Hello,", "person!", file=out) 657 assert out.getvalue() == "Hello, person!\n" 658 out = six.StringIO() 659 six.print_("Hello,", "person!", file=out, end="") 660 assert out.getvalue() == "Hello, person!" 661 out = six.StringIO() 662 six.print_("Hello,", "person!", file=out, sep="X") 663 assert out.getvalue() == "Hello,Xperson!\n" 664 out = six.StringIO() 665 six.print_(six.u("Hello,"), six.u("person!"), file=out) 666 result = out.getvalue() 667 assert isinstance(result, six.text_type) 668 assert result == six.u("Hello, person!\n") 669 six.print_("Hello", file=None) # This works. 670 out = six.StringIO() 671 six.print_(None, file=out) 672 assert out.getvalue() == "None\n" 673 class FlushableStringIO(six.StringIO): 674 def __init__(self): 675 six.StringIO.__init__(self) 676 self.flushed = False 677 def flush(self): 678 self.flushed = True 679 out = FlushableStringIO() 680 six.print_("Hello", file=out) 681 assert not out.flushed 682 six.print_("Hello", file=out, flush=True) 683 assert out.flushed 684 685 686@py.test.mark.skipif("sys.version_info[:2] >= (2, 6)") 687def test_print_encoding(monkeypatch): 688 # Fool the type checking in print_. 689 monkeypatch.setattr(six, "file", six.BytesIO, raising=False) 690 out = six.BytesIO() 691 out.encoding = "utf-8" 692 out.errors = None 693 six.print_(six.u("\u053c"), end="", file=out) 694 assert out.getvalue() == six.b("\xd4\xbc") 695 out = six.BytesIO() 696 out.encoding = "ascii" 697 out.errors = "strict" 698 py.test.raises(UnicodeEncodeError, six.print_, six.u("\u053c"), file=out) 699 out.errors = "backslashreplace" 700 six.print_(six.u("\u053c"), end="", file=out) 701 assert out.getvalue() == six.b("\\u053c") 702 703 704def test_print_exceptions(): 705 py.test.raises(TypeError, six.print_, x=3) 706 py.test.raises(TypeError, six.print_, end=3) 707 py.test.raises(TypeError, six.print_, sep=42) 708 709 710def test_with_metaclass(): 711 class Meta(type): 712 pass 713 class X(six.with_metaclass(Meta)): 714 pass 715 assert type(X) is Meta 716 assert issubclass(X, object) 717 class Base(object): 718 pass 719 class X(six.with_metaclass(Meta, Base)): 720 pass 721 assert type(X) is Meta 722 assert issubclass(X, Base) 723 class Base2(object): 724 pass 725 class X(six.with_metaclass(Meta, Base, Base2)): 726 pass 727 assert type(X) is Meta 728 assert issubclass(X, Base) 729 assert issubclass(X, Base2) 730 assert X.__mro__ == (X, Base, Base2, object) 731 732 733def test_wraps(): 734 def f(g): 735 @six.wraps(g) 736 def w(): 737 return 42 738 return w 739 def k(): 740 pass 741 original_k = k 742 k = f(f(k)) 743 assert hasattr(k, '__wrapped__') 744 k = k.__wrapped__ 745 assert hasattr(k, '__wrapped__') 746 k = k.__wrapped__ 747 assert k is original_k 748 assert not hasattr(k, '__wrapped__') 749 750 def f(g, assign, update): 751 def w(): 752 return 42 753 w.glue = {"foo" : "bar"} 754 return six.wraps(g, assign, update)(w) 755 k.glue = {"melon" : "egg"} 756 k.turnip = 43 757 k = f(k, ["turnip"], ["glue"]) 758 assert k.__name__ == "w" 759 assert k.turnip == 43 760 assert k.glue == {"melon" : "egg", "foo" : "bar"} 761 762 763def test_add_metaclass(): 764 class Meta(type): 765 pass 766 class X: 767 "success" 768 X = six.add_metaclass(Meta)(X) 769 assert type(X) is Meta 770 assert issubclass(X, object) 771 assert X.__module__ == __name__ 772 assert X.__doc__ == "success" 773 class Base(object): 774 pass 775 class X(Base): 776 pass 777 X = six.add_metaclass(Meta)(X) 778 assert type(X) is Meta 779 assert issubclass(X, Base) 780 class Base2(object): 781 pass 782 class X(Base, Base2): 783 pass 784 X = six.add_metaclass(Meta)(X) 785 assert type(X) is Meta 786 assert issubclass(X, Base) 787 assert issubclass(X, Base2) 788 789 # Test a second-generation subclass of a type. 790 class Meta1(type): 791 m1 = "m1" 792 class Meta2(Meta1): 793 m2 = "m2" 794 class Base: 795 b = "b" 796 Base = six.add_metaclass(Meta1)(Base) 797 class X(Base): 798 x = "x" 799 X = six.add_metaclass(Meta2)(X) 800 assert type(X) is Meta2 801 assert issubclass(X, Base) 802 assert type(Base) is Meta1 803 assert "__dict__" not in vars(X) 804 instance = X() 805 instance.attr = "test" 806 assert vars(instance) == {"attr": "test"} 807 assert instance.b == Base.b 808 assert instance.x == X.x 809 810 # Test a class with slots. 811 class MySlots(object): 812 __slots__ = ["a", "b"] 813 MySlots = six.add_metaclass(Meta1)(MySlots) 814 815 assert MySlots.__slots__ == ["a", "b"] 816 instance = MySlots() 817 instance.a = "foo" 818 py.test.raises(AttributeError, setattr, instance, "c", "baz") 819 820 # Test a class with string for slots. 821 class MyStringSlots(object): 822 __slots__ = "ab" 823 MyStringSlots = six.add_metaclass(Meta1)(MyStringSlots) 824 assert MyStringSlots.__slots__ == "ab" 825 instance = MyStringSlots() 826 instance.ab = "foo" 827 py.test.raises(AttributeError, setattr, instance, "a", "baz") 828 py.test.raises(AttributeError, setattr, instance, "b", "baz") 829 830 class MySlotsWeakref(object): 831 __slots__ = "__weakref__", 832 MySlotsWeakref = six.add_metaclass(Meta)(MySlotsWeakref) 833 assert type(MySlotsWeakref) is Meta 834 835 836@py.test.mark.skipif("sys.version_info[:2] < (2, 7) or sys.version_info[:2] in ((3, 0), (3, 1))") 837def test_assertCountEqual(): 838 class TestAssertCountEqual(unittest.TestCase): 839 def test(self): 840 with self.assertRaises(AssertionError): 841 six.assertCountEqual(self, (1, 2), [3, 4, 5]) 842 843 six.assertCountEqual(self, (1, 2), [2, 1]) 844 845 TestAssertCountEqual('test').test() 846 847 848@py.test.mark.skipif("sys.version_info[:2] < (2, 7)") 849def test_assertRegex(): 850 class TestAssertRegex(unittest.TestCase): 851 def test(self): 852 with self.assertRaises(AssertionError): 853 six.assertRegex(self, 'test', r'^a') 854 855 six.assertRegex(self, 'test', r'^t') 856 857 TestAssertRegex('test').test() 858 859 860@py.test.mark.skipif("sys.version_info[:2] < (2, 7)") 861def test_assertRaisesRegex(): 862 class TestAssertRaisesRegex(unittest.TestCase): 863 def test(self): 864 with six.assertRaisesRegex(self, AssertionError, '^Foo'): 865 raise AssertionError('Foo') 866 867 with self.assertRaises(AssertionError): 868 with six.assertRaisesRegex(self, AssertionError, r'^Foo'): 869 raise AssertionError('Bar') 870 871 TestAssertRaisesRegex('test').test() 872 873 874def test_python_2_unicode_compatible(): 875 @six.python_2_unicode_compatible 876 class MyTest(object): 877 def __str__(self): 878 return six.u('hello') 879 880 def __bytes__(self): 881 return six.b('hello') 882 883 my_test = MyTest() 884 885 if six.PY2: 886 assert str(my_test) == six.b("hello") 887 assert unicode(my_test) == six.u("hello") 888 elif six.PY3: 889 assert bytes(my_test) == six.b("hello") 890 assert str(my_test) == six.u("hello") 891 892 assert getattr(six.moves.builtins, 'bytes', str)(my_test) == six.b("hello") 893