Keun Soo Yim | 3b10a5a | 2017-12-22 19:03:44 -0800 | [diff] [blame] | 1 | # Copyright (c) 2010-2017 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 | |
| 21 | import operator |
| 22 | import sys |
| 23 | import types |
| 24 | import unittest |
| 25 | |
| 26 | import py |
| 27 | |
| 28 | import six |
| 29 | |
| 30 | |
| 31 | def 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 | |
| 39 | def test_import_module(): |
| 40 | from logging import handlers |
| 41 | m = six._import_module("logging.handlers") |
| 42 | assert m is handlers |
| 43 | |
| 44 | |
| 45 | def 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 | |
| 52 | def 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 | |
| 58 | def 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 | |
| 68 | def test_text_type(): |
| 69 | assert type(six.u("hi")) is six.text_type |
| 70 | |
| 71 | |
| 72 | def test_binary_type(): |
| 73 | assert type(six.b("hi")) is six.binary_type |
| 74 | |
| 75 | |
| 76 | def 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 | |
| 88 | def 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 | |
| 99 | try: |
| 100 | import _tkinter |
| 101 | except ImportError: |
| 102 | have_tkinter = False |
| 103 | else: |
| 104 | have_tkinter = True |
| 105 | |
| 106 | have_gdbm = True |
| 107 | try: |
| 108 | import gdbm |
| 109 | except 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]) |
| 117 | def 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]) |
| 143 | def 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]) |
| 156 | def 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]) |
| 165 | def 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]) |
| 174 | def 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]) |
| 183 | def 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 | |
| 190 | def 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 | |
| 197 | def 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 | |
| 204 | def 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 | |
| 210 | def 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 | |
| 217 | def 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 | |
| 223 | def 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 | |
| 230 | def test_map(): |
| 231 | from six.moves import map |
| 232 | assert six.advance_iterator(map(lambda x: x + 1, range(2))) == 1 |
| 233 | |
| 234 | |
| 235 | def test_getoutput(): |
| 236 | from six.moves import getoutput |
| 237 | output = getoutput('echo "foo"') |
| 238 | assert output == 'foo' |
| 239 | |
| 240 | |
| 241 | def test_zip(): |
| 242 | from six.moves import zip |
| 243 | assert six.advance_iterator(zip(range(2), range(2))) == (0, 0) |
| 244 | |
| 245 | |
| 246 | @py.test.mark.skipif("sys.version_info < (2, 6)") |
| 247 | def test_zip_longest(): |
| 248 | from six.moves import zip_longest |
| 249 | it = zip_longest(range(2), range(1)) |
| 250 | |
| 251 | assert six.advance_iterator(it) == (0, 0) |
| 252 | assert six.advance_iterator(it) == (1, None) |
| 253 | |
| 254 | |
| 255 | class TestCustomizedMoves: |
| 256 | |
| 257 | def teardown_method(self, meth): |
| 258 | try: |
| 259 | del six._MovedItems.spam |
| 260 | except AttributeError: |
| 261 | pass |
| 262 | try: |
| 263 | del six.moves.__dict__["spam"] |
| 264 | except KeyError: |
| 265 | pass |
| 266 | |
| 267 | |
| 268 | def test_moved_attribute(self): |
| 269 | attr = six.MovedAttribute("spam", "foo", "bar") |
| 270 | if six.PY3: |
| 271 | assert attr.mod == "bar" |
| 272 | else: |
| 273 | assert attr.mod == "foo" |
| 274 | assert attr.attr == "spam" |
| 275 | attr = six.MovedAttribute("spam", "foo", "bar", "lemma") |
| 276 | assert attr.attr == "lemma" |
| 277 | attr = six.MovedAttribute("spam", "foo", "bar", "lemma", "theorm") |
| 278 | if six.PY3: |
| 279 | assert attr.attr == "theorm" |
| 280 | else: |
| 281 | assert attr.attr == "lemma" |
| 282 | |
| 283 | |
| 284 | def test_moved_module(self): |
| 285 | attr = six.MovedModule("spam", "foo") |
| 286 | if six.PY3: |
| 287 | assert attr.mod == "spam" |
| 288 | else: |
| 289 | assert attr.mod == "foo" |
| 290 | attr = six.MovedModule("spam", "foo", "bar") |
| 291 | if six.PY3: |
| 292 | assert attr.mod == "bar" |
| 293 | else: |
| 294 | assert attr.mod == "foo" |
| 295 | |
| 296 | |
| 297 | def test_custom_move_module(self): |
| 298 | attr = six.MovedModule("spam", "six", "six") |
| 299 | six.add_move(attr) |
| 300 | six.remove_move("spam") |
| 301 | assert not hasattr(six.moves, "spam") |
| 302 | attr = six.MovedModule("spam", "six", "six") |
| 303 | six.add_move(attr) |
| 304 | from six.moves import spam |
| 305 | assert spam is six |
| 306 | six.remove_move("spam") |
| 307 | assert not hasattr(six.moves, "spam") |
| 308 | |
| 309 | |
| 310 | def test_custom_move_attribute(self): |
| 311 | attr = six.MovedAttribute("spam", "six", "six", "u", "u") |
| 312 | six.add_move(attr) |
| 313 | six.remove_move("spam") |
| 314 | assert not hasattr(six.moves, "spam") |
| 315 | attr = six.MovedAttribute("spam", "six", "six", "u", "u") |
| 316 | six.add_move(attr) |
| 317 | from six.moves import spam |
| 318 | assert spam is six.u |
| 319 | six.remove_move("spam") |
| 320 | assert not hasattr(six.moves, "spam") |
| 321 | |
| 322 | |
| 323 | def test_empty_remove(self): |
| 324 | py.test.raises(AttributeError, six.remove_move, "eggs") |
| 325 | |
| 326 | |
| 327 | def test_get_unbound_function(): |
| 328 | class X(object): |
| 329 | def m(self): |
| 330 | pass |
| 331 | assert six.get_unbound_function(X.m) is X.__dict__["m"] |
| 332 | |
| 333 | |
| 334 | def test_get_method_self(): |
| 335 | class X(object): |
| 336 | def m(self): |
| 337 | pass |
| 338 | x = X() |
| 339 | assert six.get_method_self(x.m) is x |
| 340 | py.test.raises(AttributeError, six.get_method_self, 42) |
| 341 | |
| 342 | |
| 343 | def test_get_method_function(): |
| 344 | class X(object): |
| 345 | def m(self): |
| 346 | pass |
| 347 | x = X() |
| 348 | assert six.get_method_function(x.m) is X.__dict__["m"] |
| 349 | py.test.raises(AttributeError, six.get_method_function, hasattr) |
| 350 | |
| 351 | |
| 352 | def test_get_function_closure(): |
| 353 | def f(): |
| 354 | x = 42 |
| 355 | def g(): |
| 356 | return x |
| 357 | return g |
| 358 | cell = six.get_function_closure(f())[0] |
| 359 | assert type(cell).__name__ == "cell" |
| 360 | |
| 361 | |
| 362 | def test_get_function_code(): |
| 363 | def f(): |
| 364 | pass |
| 365 | assert isinstance(six.get_function_code(f), types.CodeType) |
| 366 | if not hasattr(sys, "pypy_version_info"): |
| 367 | py.test.raises(AttributeError, six.get_function_code, hasattr) |
| 368 | |
| 369 | |
| 370 | def test_get_function_defaults(): |
| 371 | def f(x, y=3, b=4): |
| 372 | pass |
| 373 | assert six.get_function_defaults(f) == (3, 4) |
| 374 | |
| 375 | |
| 376 | def test_get_function_globals(): |
| 377 | def f(): |
| 378 | pass |
| 379 | assert six.get_function_globals(f) is globals() |
| 380 | |
| 381 | |
| 382 | def test_dictionary_iterators(monkeypatch): |
| 383 | def stock_method_name(iterwhat): |
| 384 | """Given a method suffix like "lists" or "values", return the name |
| 385 | of the dict method that delivers those on the version of Python |
| 386 | we're running in.""" |
| 387 | if six.PY3: |
| 388 | return iterwhat |
| 389 | return 'iter' + iterwhat |
| 390 | |
| 391 | class MyDict(dict): |
| 392 | if not six.PY3: |
| 393 | def lists(self, **kw): |
| 394 | return [1, 2, 3] |
| 395 | def iterlists(self, **kw): |
| 396 | return iter([1, 2, 3]) |
| 397 | f = MyDict.iterlists |
| 398 | del MyDict.iterlists |
| 399 | setattr(MyDict, stock_method_name('lists'), f) |
| 400 | |
| 401 | d = MyDict(zip(range(10), reversed(range(10)))) |
| 402 | for name in "keys", "values", "items", "lists": |
| 403 | meth = getattr(six, "iter" + name) |
| 404 | it = meth(d) |
| 405 | assert not isinstance(it, list) |
| 406 | assert list(it) == list(getattr(d, name)()) |
| 407 | py.test.raises(StopIteration, six.advance_iterator, it) |
| 408 | record = [] |
| 409 | def with_kw(*args, **kw): |
| 410 | record.append(kw["kw"]) |
| 411 | return old(*args) |
| 412 | old = getattr(MyDict, stock_method_name(name)) |
| 413 | monkeypatch.setattr(MyDict, stock_method_name(name), with_kw) |
| 414 | meth(d, kw=42) |
| 415 | assert record == [42] |
| 416 | monkeypatch.undo() |
| 417 | |
| 418 | |
| 419 | @py.test.mark.skipif("sys.version_info[:2] < (2, 7)", |
| 420 | reason="view methods on dictionaries only available on 2.7+") |
| 421 | def test_dictionary_views(): |
| 422 | def stock_method_name(viewwhat): |
| 423 | """Given a method suffix like "keys" or "values", return the name |
| 424 | of the dict method that delivers those on the version of Python |
| 425 | we're running in.""" |
| 426 | if six.PY3: |
| 427 | return viewwhat |
| 428 | return 'view' + viewwhat |
| 429 | |
| 430 | d = dict(zip(range(10), (range(11, 20)))) |
| 431 | for name in "keys", "values", "items": |
| 432 | meth = getattr(six, "view" + name) |
| 433 | view = meth(d) |
| 434 | assert set(view) == set(getattr(d, name)()) |
| 435 | |
| 436 | |
| 437 | def test_advance_iterator(): |
| 438 | assert six.next is six.advance_iterator |
| 439 | l = [1, 2] |
| 440 | it = iter(l) |
| 441 | assert six.next(it) == 1 |
| 442 | assert six.next(it) == 2 |
| 443 | py.test.raises(StopIteration, six.next, it) |
| 444 | py.test.raises(StopIteration, six.next, it) |
| 445 | |
| 446 | |
| 447 | def test_iterator(): |
| 448 | class myiter(six.Iterator): |
| 449 | def __next__(self): |
| 450 | return 13 |
| 451 | assert six.advance_iterator(myiter()) == 13 |
| 452 | class myitersub(myiter): |
| 453 | def __next__(self): |
| 454 | return 14 |
| 455 | assert six.advance_iterator(myitersub()) == 14 |
| 456 | |
| 457 | |
| 458 | def test_callable(): |
| 459 | class X: |
| 460 | def __call__(self): |
| 461 | pass |
| 462 | def method(self): |
| 463 | pass |
| 464 | assert six.callable(X) |
| 465 | assert six.callable(X()) |
| 466 | assert six.callable(test_callable) |
| 467 | assert six.callable(hasattr) |
| 468 | assert six.callable(X.method) |
| 469 | assert six.callable(X().method) |
| 470 | assert not six.callable(4) |
| 471 | assert not six.callable("string") |
| 472 | |
| 473 | |
| 474 | def test_create_bound_method(): |
| 475 | class X(object): |
| 476 | pass |
| 477 | def f(self): |
| 478 | return self |
| 479 | x = X() |
| 480 | b = six.create_bound_method(f, x) |
| 481 | assert isinstance(b, types.MethodType) |
| 482 | assert b() is x |
| 483 | |
| 484 | |
| 485 | def test_create_unbound_method(): |
| 486 | class X(object): |
| 487 | pass |
| 488 | |
| 489 | def f(self): |
| 490 | return self |
| 491 | u = six.create_unbound_method(f, X) |
| 492 | py.test.raises(TypeError, u) |
| 493 | if six.PY2: |
| 494 | assert isinstance(u, types.MethodType) |
| 495 | x = X() |
| 496 | assert f(x) is x |
| 497 | |
| 498 | |
| 499 | if six.PY3: |
| 500 | |
| 501 | def test_b(): |
| 502 | data = six.b("\xff") |
| 503 | assert isinstance(data, bytes) |
| 504 | assert len(data) == 1 |
| 505 | assert data == bytes([255]) |
| 506 | |
| 507 | |
| 508 | def test_u(): |
| 509 | s = six.u("hi \u0439 \U00000439 \\ \\\\ \n") |
| 510 | assert isinstance(s, str) |
| 511 | assert s == "hi \u0439 \U00000439 \\ \\\\ \n" |
| 512 | |
| 513 | else: |
| 514 | |
| 515 | def test_b(): |
| 516 | data = six.b("\xff") |
| 517 | assert isinstance(data, str) |
| 518 | assert len(data) == 1 |
| 519 | assert data == "\xff" |
| 520 | |
| 521 | |
| 522 | def test_u(): |
| 523 | s = six.u("hi \u0439 \U00000439 \\ \\\\ \n") |
| 524 | assert isinstance(s, unicode) |
| 525 | assert s == "hi \xd0\xb9 \xd0\xb9 \\ \\\\ \n".decode("utf8") |
| 526 | |
| 527 | |
| 528 | def test_u_escapes(): |
| 529 | s = six.u("\u1234") |
| 530 | assert len(s) == 1 |
| 531 | |
| 532 | |
| 533 | def test_unichr(): |
| 534 | assert six.u("\u1234") == six.unichr(0x1234) |
| 535 | assert type(six.u("\u1234")) is type(six.unichr(0x1234)) |
| 536 | |
| 537 | |
| 538 | def test_int2byte(): |
| 539 | assert six.int2byte(3) == six.b("\x03") |
| 540 | py.test.raises(Exception, six.int2byte, 256) |
| 541 | |
| 542 | |
| 543 | def test_byte2int(): |
| 544 | assert six.byte2int(six.b("\x03")) == 3 |
| 545 | assert six.byte2int(six.b("\x03\x04")) == 3 |
| 546 | py.test.raises(IndexError, six.byte2int, six.b("")) |
| 547 | |
| 548 | |
| 549 | def test_bytesindex(): |
| 550 | assert six.indexbytes(six.b("hello"), 3) == ord("l") |
| 551 | |
| 552 | |
| 553 | def test_bytesiter(): |
| 554 | it = six.iterbytes(six.b("hi")) |
| 555 | assert six.next(it) == ord("h") |
| 556 | assert six.next(it) == ord("i") |
| 557 | py.test.raises(StopIteration, six.next, it) |
| 558 | |
| 559 | |
| 560 | def test_StringIO(): |
| 561 | fp = six.StringIO() |
| 562 | fp.write(six.u("hello")) |
| 563 | assert fp.getvalue() == six.u("hello") |
| 564 | |
| 565 | |
| 566 | def test_BytesIO(): |
| 567 | fp = six.BytesIO() |
| 568 | fp.write(six.b("hello")) |
| 569 | assert fp.getvalue() == six.b("hello") |
| 570 | |
| 571 | |
| 572 | def test_exec_(): |
| 573 | def f(): |
| 574 | l = [] |
| 575 | six.exec_("l.append(1)") |
| 576 | assert l == [1] |
| 577 | f() |
| 578 | ns = {} |
| 579 | six.exec_("x = 42", ns) |
| 580 | assert ns["x"] == 42 |
| 581 | glob = {} |
| 582 | loc = {} |
| 583 | six.exec_("global y; y = 42; x = 12", glob, loc) |
| 584 | assert glob["y"] == 42 |
| 585 | assert "x" not in glob |
| 586 | assert loc["x"] == 12 |
| 587 | assert "y" not in loc |
| 588 | |
| 589 | |
| 590 | def test_reraise(): |
| 591 | def get_next(tb): |
| 592 | if six.PY3: |
| 593 | return tb.tb_next.tb_next |
| 594 | else: |
| 595 | return tb.tb_next |
| 596 | e = Exception("blah") |
| 597 | try: |
| 598 | raise e |
| 599 | except Exception: |
| 600 | tp, val, tb = sys.exc_info() |
| 601 | try: |
| 602 | six.reraise(tp, val, tb) |
| 603 | except Exception: |
| 604 | tp2, value2, tb2 = sys.exc_info() |
| 605 | assert tp2 is Exception |
| 606 | assert value2 is e |
| 607 | assert tb is get_next(tb2) |
| 608 | try: |
| 609 | six.reraise(tp, val) |
| 610 | except Exception: |
| 611 | tp2, value2, tb2 = sys.exc_info() |
| 612 | assert tp2 is Exception |
| 613 | assert value2 is e |
| 614 | assert tb2 is not tb |
| 615 | try: |
| 616 | six.reraise(tp, val, tb2) |
| 617 | except Exception: |
| 618 | tp2, value2, tb3 = sys.exc_info() |
| 619 | assert tp2 is Exception |
| 620 | assert value2 is e |
| 621 | assert get_next(tb3) is tb2 |
| 622 | try: |
| 623 | six.reraise(tp, None, tb) |
| 624 | except Exception: |
| 625 | tp2, value2, tb2 = sys.exc_info() |
| 626 | assert tp2 is Exception |
| 627 | assert value2 is not val |
| 628 | assert isinstance(value2, Exception) |
| 629 | assert tb is get_next(tb2) |
| 630 | |
| 631 | |
| 632 | def test_raise_from(): |
| 633 | try: |
| 634 | try: |
| 635 | raise Exception("blah") |
| 636 | except Exception: |
| 637 | ctx = sys.exc_info()[1] |
| 638 | f = Exception("foo") |
| 639 | six.raise_from(f, None) |
| 640 | except Exception: |
| 641 | tp, val, tb = sys.exc_info() |
| 642 | if sys.version_info[:2] > (3, 0): |
| 643 | # We should have done a raise f from None equivalent. |
| 644 | assert val.__cause__ is None |
| 645 | assert val.__context__ is ctx |
| 646 | if sys.version_info[:2] >= (3, 3): |
| 647 | # And that should suppress the context on the exception. |
| 648 | assert val.__suppress_context__ |
| 649 | # For all versions the outer exception should have raised successfully. |
| 650 | assert str(val) == "foo" |
| 651 | |
| 652 | |
| 653 | def test_print_(): |
| 654 | save = sys.stdout |
| 655 | out = sys.stdout = six.moves.StringIO() |
| 656 | try: |
| 657 | six.print_("Hello,", "person!") |
| 658 | finally: |
| 659 | sys.stdout = save |
| 660 | assert out.getvalue() == "Hello, person!\n" |
| 661 | out = six.StringIO() |
| 662 | six.print_("Hello,", "person!", file=out) |
| 663 | assert out.getvalue() == "Hello, person!\n" |
| 664 | out = six.StringIO() |
| 665 | six.print_("Hello,", "person!", file=out, end="") |
| 666 | assert out.getvalue() == "Hello, person!" |
| 667 | out = six.StringIO() |
| 668 | six.print_("Hello,", "person!", file=out, sep="X") |
| 669 | assert out.getvalue() == "Hello,Xperson!\n" |
| 670 | out = six.StringIO() |
| 671 | six.print_(six.u("Hello,"), six.u("person!"), file=out) |
| 672 | result = out.getvalue() |
| 673 | assert isinstance(result, six.text_type) |
| 674 | assert result == six.u("Hello, person!\n") |
| 675 | six.print_("Hello", file=None) # This works. |
| 676 | out = six.StringIO() |
| 677 | six.print_(None, file=out) |
| 678 | assert out.getvalue() == "None\n" |
| 679 | class FlushableStringIO(six.StringIO): |
| 680 | def __init__(self): |
| 681 | six.StringIO.__init__(self) |
| 682 | self.flushed = False |
| 683 | def flush(self): |
| 684 | self.flushed = True |
| 685 | out = FlushableStringIO() |
| 686 | six.print_("Hello", file=out) |
| 687 | assert not out.flushed |
| 688 | six.print_("Hello", file=out, flush=True) |
| 689 | assert out.flushed |
| 690 | |
| 691 | |
| 692 | @py.test.mark.skipif("sys.version_info[:2] >= (2, 6)") |
| 693 | def test_print_encoding(monkeypatch): |
| 694 | # Fool the type checking in print_. |
| 695 | monkeypatch.setattr(six, "file", six.BytesIO, raising=False) |
| 696 | out = six.BytesIO() |
| 697 | out.encoding = "utf-8" |
| 698 | out.errors = None |
| 699 | six.print_(six.u("\u053c"), end="", file=out) |
| 700 | assert out.getvalue() == six.b("\xd4\xbc") |
| 701 | out = six.BytesIO() |
| 702 | out.encoding = "ascii" |
| 703 | out.errors = "strict" |
| 704 | py.test.raises(UnicodeEncodeError, six.print_, six.u("\u053c"), file=out) |
| 705 | out.errors = "backslashreplace" |
| 706 | six.print_(six.u("\u053c"), end="", file=out) |
| 707 | assert out.getvalue() == six.b("\\u053c") |
| 708 | |
| 709 | |
| 710 | def test_print_exceptions(): |
| 711 | py.test.raises(TypeError, six.print_, x=3) |
| 712 | py.test.raises(TypeError, six.print_, end=3) |
| 713 | py.test.raises(TypeError, six.print_, sep=42) |
| 714 | |
| 715 | |
| 716 | def test_with_metaclass(): |
| 717 | class Meta(type): |
| 718 | pass |
| 719 | class X(six.with_metaclass(Meta)): |
| 720 | pass |
| 721 | assert type(X) is Meta |
| 722 | assert issubclass(X, object) |
| 723 | class Base(object): |
| 724 | pass |
| 725 | class X(six.with_metaclass(Meta, Base)): |
| 726 | pass |
| 727 | assert type(X) is Meta |
| 728 | assert issubclass(X, Base) |
| 729 | class Base2(object): |
| 730 | pass |
| 731 | class X(six.with_metaclass(Meta, Base, Base2)): |
| 732 | pass |
| 733 | assert type(X) is Meta |
| 734 | assert issubclass(X, Base) |
| 735 | assert issubclass(X, Base2) |
| 736 | assert X.__mro__ == (X, Base, Base2, object) |
| 737 | class X(six.with_metaclass(Meta)): |
| 738 | pass |
| 739 | class MetaSub(Meta): |
| 740 | pass |
| 741 | class Y(six.with_metaclass(MetaSub, X)): |
| 742 | pass |
| 743 | assert type(Y) is MetaSub |
| 744 | assert Y.__mro__ == (Y, X, object) |
| 745 | |
| 746 | |
| 747 | @py.test.mark.skipif("sys.version_info[:2] < (3, 0)") |
| 748 | def test_with_metaclass_prepare(): |
| 749 | """Test that with_metaclass causes Meta.__prepare__ to be called with the correct arguments.""" |
| 750 | |
| 751 | class MyDict(dict): |
| 752 | pass |
| 753 | |
| 754 | class Meta(type): |
| 755 | |
| 756 | @classmethod |
| 757 | def __prepare__(cls, name, bases): |
| 758 | namespace = MyDict(super().__prepare__(name, bases), cls=cls, bases=bases) |
| 759 | namespace['namespace'] = namespace |
| 760 | return namespace |
| 761 | |
| 762 | class Base(object): |
| 763 | pass |
| 764 | |
| 765 | bases = (Base,) |
| 766 | |
| 767 | class X(six.with_metaclass(Meta, *bases)): |
| 768 | pass |
| 769 | |
| 770 | assert getattr(X, 'cls', type) is Meta |
| 771 | assert getattr(X, 'bases', ()) == bases |
| 772 | assert isinstance(getattr(X, 'namespace', {}), MyDict) |
| 773 | |
| 774 | |
| 775 | def test_wraps(): |
| 776 | def f(g): |
| 777 | @six.wraps(g) |
| 778 | def w(): |
| 779 | return 42 |
| 780 | return w |
| 781 | def k(): |
| 782 | pass |
| 783 | original_k = k |
| 784 | k = f(f(k)) |
| 785 | assert hasattr(k, '__wrapped__') |
| 786 | k = k.__wrapped__ |
| 787 | assert hasattr(k, '__wrapped__') |
| 788 | k = k.__wrapped__ |
| 789 | assert k is original_k |
| 790 | assert not hasattr(k, '__wrapped__') |
| 791 | |
| 792 | def f(g, assign, update): |
| 793 | def w(): |
| 794 | return 42 |
| 795 | w.glue = {"foo" : "bar"} |
| 796 | return six.wraps(g, assign, update)(w) |
| 797 | k.glue = {"melon" : "egg"} |
| 798 | k.turnip = 43 |
| 799 | k = f(k, ["turnip"], ["glue"]) |
| 800 | assert k.__name__ == "w" |
| 801 | assert k.turnip == 43 |
| 802 | assert k.glue == {"melon" : "egg", "foo" : "bar"} |
| 803 | |
| 804 | |
| 805 | def test_add_metaclass(): |
| 806 | class Meta(type): |
| 807 | pass |
| 808 | class X: |
| 809 | "success" |
| 810 | X = six.add_metaclass(Meta)(X) |
| 811 | assert type(X) is Meta |
| 812 | assert issubclass(X, object) |
| 813 | assert X.__module__ == __name__ |
| 814 | assert X.__doc__ == "success" |
| 815 | class Base(object): |
| 816 | pass |
| 817 | class X(Base): |
| 818 | pass |
| 819 | X = six.add_metaclass(Meta)(X) |
| 820 | assert type(X) is Meta |
| 821 | assert issubclass(X, Base) |
| 822 | class Base2(object): |
| 823 | pass |
| 824 | class X(Base, Base2): |
| 825 | pass |
| 826 | X = six.add_metaclass(Meta)(X) |
| 827 | assert type(X) is Meta |
| 828 | assert issubclass(X, Base) |
| 829 | assert issubclass(X, Base2) |
| 830 | |
| 831 | # Test a second-generation subclass of a type. |
| 832 | class Meta1(type): |
| 833 | m1 = "m1" |
| 834 | class Meta2(Meta1): |
| 835 | m2 = "m2" |
| 836 | class Base: |
| 837 | b = "b" |
| 838 | Base = six.add_metaclass(Meta1)(Base) |
| 839 | class X(Base): |
| 840 | x = "x" |
| 841 | X = six.add_metaclass(Meta2)(X) |
| 842 | assert type(X) is Meta2 |
| 843 | assert issubclass(X, Base) |
| 844 | assert type(Base) is Meta1 |
| 845 | assert "__dict__" not in vars(X) |
| 846 | instance = X() |
| 847 | instance.attr = "test" |
| 848 | assert vars(instance) == {"attr": "test"} |
| 849 | assert instance.b == Base.b |
| 850 | assert instance.x == X.x |
| 851 | |
| 852 | # Test a class with slots. |
| 853 | class MySlots(object): |
| 854 | __slots__ = ["a", "b"] |
| 855 | MySlots = six.add_metaclass(Meta1)(MySlots) |
| 856 | |
| 857 | assert MySlots.__slots__ == ["a", "b"] |
| 858 | instance = MySlots() |
| 859 | instance.a = "foo" |
| 860 | py.test.raises(AttributeError, setattr, instance, "c", "baz") |
| 861 | |
| 862 | # Test a class with string for slots. |
| 863 | class MyStringSlots(object): |
| 864 | __slots__ = "ab" |
| 865 | MyStringSlots = six.add_metaclass(Meta1)(MyStringSlots) |
| 866 | assert MyStringSlots.__slots__ == "ab" |
| 867 | instance = MyStringSlots() |
| 868 | instance.ab = "foo" |
| 869 | py.test.raises(AttributeError, setattr, instance, "a", "baz") |
| 870 | py.test.raises(AttributeError, setattr, instance, "b", "baz") |
| 871 | |
| 872 | class MySlotsWeakref(object): |
| 873 | __slots__ = "__weakref__", |
| 874 | MySlotsWeakref = six.add_metaclass(Meta)(MySlotsWeakref) |
| 875 | assert type(MySlotsWeakref) is Meta |
| 876 | |
| 877 | |
| 878 | @py.test.mark.skipif("sys.version_info[:2] < (2, 7) or sys.version_info[:2] in ((3, 0), (3, 1))") |
| 879 | def test_assertCountEqual(): |
| 880 | class TestAssertCountEqual(unittest.TestCase): |
| 881 | def test(self): |
| 882 | with self.assertRaises(AssertionError): |
| 883 | six.assertCountEqual(self, (1, 2), [3, 4, 5]) |
| 884 | |
| 885 | six.assertCountEqual(self, (1, 2), [2, 1]) |
| 886 | |
| 887 | TestAssertCountEqual('test').test() |
| 888 | |
| 889 | |
| 890 | @py.test.mark.skipif("sys.version_info[:2] < (2, 7)") |
| 891 | def test_assertRegex(): |
| 892 | class TestAssertRegex(unittest.TestCase): |
| 893 | def test(self): |
| 894 | with self.assertRaises(AssertionError): |
| 895 | six.assertRegex(self, 'test', r'^a') |
| 896 | |
| 897 | six.assertRegex(self, 'test', r'^t') |
| 898 | |
| 899 | TestAssertRegex('test').test() |
| 900 | |
| 901 | |
| 902 | @py.test.mark.skipif("sys.version_info[:2] < (2, 7)") |
| 903 | def test_assertRaisesRegex(): |
| 904 | class TestAssertRaisesRegex(unittest.TestCase): |
| 905 | def test(self): |
| 906 | with six.assertRaisesRegex(self, AssertionError, '^Foo'): |
| 907 | raise AssertionError('Foo') |
| 908 | |
| 909 | with self.assertRaises(AssertionError): |
| 910 | with six.assertRaisesRegex(self, AssertionError, r'^Foo'): |
| 911 | raise AssertionError('Bar') |
| 912 | |
| 913 | TestAssertRaisesRegex('test').test() |
| 914 | |
| 915 | |
| 916 | def test_python_2_unicode_compatible(): |
| 917 | @six.python_2_unicode_compatible |
| 918 | class MyTest(object): |
| 919 | def __str__(self): |
| 920 | return six.u('hello') |
| 921 | |
| 922 | def __bytes__(self): |
| 923 | return six.b('hello') |
| 924 | |
| 925 | my_test = MyTest() |
| 926 | |
| 927 | if six.PY2: |
| 928 | assert str(my_test) == six.b("hello") |
| 929 | assert unicode(my_test) == six.u("hello") |
| 930 | elif six.PY3: |
| 931 | assert bytes(my_test) == six.b("hello") |
| 932 | assert str(my_test) == six.u("hello") |
| 933 | |
| 934 | assert getattr(six.moves.builtins, 'bytes', str)(my_test) == six.b("hello") |