mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
Merge pull request #4073 from youknowone/unittests
Unittests update from CPython 3.10.6
This commit is contained in:
5
Lib/getpass.py
vendored
5
Lib/getpass.py
vendored
@@ -7,7 +7,6 @@ GetPassWarning - This UserWarning is issued when getpass() cannot prevent
|
||||
echoing of the password contents while reading.
|
||||
|
||||
On Windows, the msvcrt module will be used.
|
||||
On the Mac EasyDialogs.AskPassword is used, if available.
|
||||
|
||||
"""
|
||||
|
||||
@@ -53,7 +52,7 @@ def unix_getpass(prompt='Password: ', stream=None):
|
||||
stack.enter_context(input)
|
||||
if not stream:
|
||||
stream = input
|
||||
except OSError as e:
|
||||
except OSError:
|
||||
# If that fails, see if stdin can be controlled.
|
||||
stack.close()
|
||||
try:
|
||||
@@ -96,7 +95,7 @@ def unix_getpass(prompt='Password: ', stream=None):
|
||||
|
||||
|
||||
def win_getpass(prompt='Password: ', stream=None):
|
||||
"""Prompt for password with echo off, using Windows getch()."""
|
||||
"""Prompt for password with echo off, using Windows getwch()."""
|
||||
if sys.stdin is not sys.__stdin__:
|
||||
return fallback_getpass(prompt, stream)
|
||||
|
||||
|
||||
154
Lib/glob.py
vendored
154
Lib/glob.py
vendored
@@ -1,12 +1,16 @@
|
||||
"""Filename globbing utility."""
|
||||
|
||||
import contextlib
|
||||
import os
|
||||
import re
|
||||
import fnmatch
|
||||
import itertools
|
||||
import stat
|
||||
import sys
|
||||
|
||||
__all__ = ["glob", "iglob", "escape"]
|
||||
|
||||
def glob(pathname, *, recursive=False):
|
||||
def glob(pathname, *, root_dir=None, dir_fd=None, recursive=False):
|
||||
"""Return a list of paths matching a pathname pattern.
|
||||
|
||||
The pattern may contain simple shell-style wildcards a la
|
||||
@@ -17,9 +21,9 @@ def glob(pathname, *, recursive=False):
|
||||
If recursive is true, the pattern '**' will match any files and
|
||||
zero or more directories and subdirectories.
|
||||
"""
|
||||
return list(iglob(pathname, recursive=recursive))
|
||||
return list(iglob(pathname, root_dir=root_dir, dir_fd=dir_fd, recursive=recursive))
|
||||
|
||||
def iglob(pathname, *, recursive=False):
|
||||
def iglob(pathname, *, root_dir=None, dir_fd=None, recursive=False):
|
||||
"""Return an iterator which yields the paths matching a pathname pattern.
|
||||
|
||||
The pattern may contain simple shell-style wildcards a la
|
||||
@@ -30,35 +34,45 @@ def iglob(pathname, *, recursive=False):
|
||||
If recursive is true, the pattern '**' will match any files and
|
||||
zero or more directories and subdirectories.
|
||||
"""
|
||||
it = _iglob(pathname, recursive, False)
|
||||
if recursive and _isrecursive(pathname):
|
||||
s = next(it) # skip empty string
|
||||
assert not s
|
||||
sys.audit("glob.glob", pathname, recursive)
|
||||
sys.audit("glob.glob/2", pathname, recursive, root_dir, dir_fd)
|
||||
if root_dir is not None:
|
||||
root_dir = os.fspath(root_dir)
|
||||
else:
|
||||
root_dir = pathname[:0]
|
||||
it = _iglob(pathname, root_dir, dir_fd, recursive, False)
|
||||
if not pathname or recursive and _isrecursive(pathname[:2]):
|
||||
try:
|
||||
s = next(it) # skip empty string
|
||||
if s:
|
||||
it = itertools.chain((s,), it)
|
||||
except StopIteration:
|
||||
pass
|
||||
return it
|
||||
|
||||
def _iglob(pathname, recursive, dironly):
|
||||
def _iglob(pathname, root_dir, dir_fd, recursive, dironly):
|
||||
dirname, basename = os.path.split(pathname)
|
||||
if not has_magic(pathname):
|
||||
assert not dironly
|
||||
if basename:
|
||||
if os.path.lexists(pathname):
|
||||
if _lexists(_join(root_dir, pathname), dir_fd):
|
||||
yield pathname
|
||||
else:
|
||||
# Patterns ending with a slash should match only directories
|
||||
if os.path.isdir(dirname):
|
||||
if _isdir(_join(root_dir, dirname), dir_fd):
|
||||
yield pathname
|
||||
return
|
||||
if not dirname:
|
||||
if recursive and _isrecursive(basename):
|
||||
yield from _glob2(dirname, basename, dironly)
|
||||
yield from _glob2(root_dir, basename, dir_fd, dironly)
|
||||
else:
|
||||
yield from _glob1(dirname, basename, dironly)
|
||||
yield from _glob1(root_dir, basename, dir_fd, dironly)
|
||||
return
|
||||
# `os.path.split()` returns the argument itself as a dirname if it is a
|
||||
# drive or UNC path. Prevent an infinite recursion if a drive or UNC path
|
||||
# contains magic characters (i.e. r'\\?\C:').
|
||||
if dirname != pathname and has_magic(dirname):
|
||||
dirs = _iglob(dirname, recursive, True)
|
||||
dirs = _iglob(dirname, root_dir, dir_fd, recursive, True)
|
||||
else:
|
||||
dirs = [dirname]
|
||||
if has_magic(basename):
|
||||
@@ -69,76 +83,125 @@ def _iglob(pathname, recursive, dironly):
|
||||
else:
|
||||
glob_in_dir = _glob0
|
||||
for dirname in dirs:
|
||||
for name in glob_in_dir(dirname, basename, dironly):
|
||||
for name in glob_in_dir(_join(root_dir, dirname), basename, dir_fd, dironly):
|
||||
yield os.path.join(dirname, name)
|
||||
|
||||
# These 2 helper functions non-recursively glob inside a literal directory.
|
||||
# They return a list of basenames. _glob1 accepts a pattern while _glob0
|
||||
# takes a literal basename (so it only has to check for its existence).
|
||||
|
||||
def _glob1(dirname, pattern, dironly):
|
||||
names = list(_iterdir(dirname, dironly))
|
||||
def _glob1(dirname, pattern, dir_fd, dironly):
|
||||
names = _listdir(dirname, dir_fd, dironly)
|
||||
if not _ishidden(pattern):
|
||||
names = (x for x in names if not _ishidden(x))
|
||||
return fnmatch.filter(names, pattern)
|
||||
|
||||
def _glob0(dirname, basename, dironly):
|
||||
if not basename:
|
||||
# `os.path.split()` returns an empty basename for paths ending with a
|
||||
# directory separator. 'q*x/' should match only directories.
|
||||
if os.path.isdir(dirname):
|
||||
def _glob0(dirname, basename, dir_fd, dironly):
|
||||
if basename:
|
||||
if _lexists(_join(dirname, basename), dir_fd):
|
||||
return [basename]
|
||||
else:
|
||||
if os.path.lexists(os.path.join(dirname, basename)):
|
||||
# `os.path.split()` returns an empty basename for paths ending with a
|
||||
# directory separator. 'q*x/' should match only directories.
|
||||
if _isdir(dirname, dir_fd):
|
||||
return [basename]
|
||||
return []
|
||||
|
||||
# Following functions are not public but can be used by third-party code.
|
||||
|
||||
def glob0(dirname, pattern):
|
||||
return _glob0(dirname, pattern, False)
|
||||
return _glob0(dirname, pattern, None, False)
|
||||
|
||||
def glob1(dirname, pattern):
|
||||
return _glob1(dirname, pattern, False)
|
||||
return _glob1(dirname, pattern, None, False)
|
||||
|
||||
# This helper function recursively yields relative pathnames inside a literal
|
||||
# directory.
|
||||
|
||||
def _glob2(dirname, pattern, dironly):
|
||||
def _glob2(dirname, pattern, dir_fd, dironly):
|
||||
assert _isrecursive(pattern)
|
||||
yield pattern[:0]
|
||||
yield from _rlistdir(dirname, dironly)
|
||||
yield from _rlistdir(dirname, dir_fd, dironly)
|
||||
|
||||
# If dironly is false, yields all file names inside a directory.
|
||||
# If dironly is true, yields only directory names.
|
||||
def _iterdir(dirname, dironly):
|
||||
if not dirname:
|
||||
if isinstance(dirname, bytes):
|
||||
dirname = bytes(os.curdir, 'ASCII')
|
||||
else:
|
||||
dirname = os.curdir
|
||||
def _iterdir(dirname, dir_fd, dironly):
|
||||
try:
|
||||
with os.scandir(dirname) as it:
|
||||
for entry in it:
|
||||
try:
|
||||
if not dironly or entry.is_dir():
|
||||
yield entry.name
|
||||
except OSError:
|
||||
pass
|
||||
fd = None
|
||||
fsencode = None
|
||||
if dir_fd is not None:
|
||||
if dirname:
|
||||
fd = arg = os.open(dirname, _dir_open_flags, dir_fd=dir_fd)
|
||||
else:
|
||||
arg = dir_fd
|
||||
if isinstance(dirname, bytes):
|
||||
fsencode = os.fsencode
|
||||
elif dirname:
|
||||
arg = dirname
|
||||
elif isinstance(dirname, bytes):
|
||||
arg = bytes(os.curdir, 'ASCII')
|
||||
else:
|
||||
arg = os.curdir
|
||||
try:
|
||||
with os.scandir(arg) as it:
|
||||
for entry in it:
|
||||
try:
|
||||
if not dironly or entry.is_dir():
|
||||
if fsencode is not None:
|
||||
yield fsencode(entry.name)
|
||||
else:
|
||||
yield entry.name
|
||||
except OSError:
|
||||
pass
|
||||
finally:
|
||||
if fd is not None:
|
||||
os.close(fd)
|
||||
except OSError:
|
||||
return
|
||||
|
||||
def _listdir(dirname, dir_fd, dironly):
|
||||
with contextlib.closing(_iterdir(dirname, dir_fd, dironly)) as it:
|
||||
return list(it)
|
||||
|
||||
# Recursively yields relative pathnames inside a literal directory.
|
||||
def _rlistdir(dirname, dironly):
|
||||
names = list(_iterdir(dirname, dironly))
|
||||
def _rlistdir(dirname, dir_fd, dironly):
|
||||
names = _listdir(dirname, dir_fd, dironly)
|
||||
for x in names:
|
||||
if not _ishidden(x):
|
||||
yield x
|
||||
path = os.path.join(dirname, x) if dirname else x
|
||||
for y in _rlistdir(path, dironly):
|
||||
yield os.path.join(x, y)
|
||||
path = _join(dirname, x) if dirname else x
|
||||
for y in _rlistdir(path, dir_fd, dironly):
|
||||
yield _join(x, y)
|
||||
|
||||
|
||||
def _lexists(pathname, dir_fd):
|
||||
# Same as os.path.lexists(), but with dir_fd
|
||||
if dir_fd is None:
|
||||
return os.path.lexists(pathname)
|
||||
try:
|
||||
os.lstat(pathname, dir_fd=dir_fd)
|
||||
except (OSError, ValueError):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def _isdir(pathname, dir_fd):
|
||||
# Same as os.path.isdir(), but with dir_fd
|
||||
if dir_fd is None:
|
||||
return os.path.isdir(pathname)
|
||||
try:
|
||||
st = os.stat(pathname, dir_fd=dir_fd)
|
||||
except (OSError, ValueError):
|
||||
return False
|
||||
else:
|
||||
return stat.S_ISDIR(st.st_mode)
|
||||
|
||||
def _join(dirname, basename):
|
||||
# It is common if dirname or basename is empty
|
||||
if not dirname or not basename:
|
||||
return dirname or basename
|
||||
return os.path.join(dirname, basename)
|
||||
|
||||
magic_check = re.compile('([*?[])')
|
||||
magic_check_bytes = re.compile(b'([*?[])')
|
||||
|
||||
@@ -169,3 +232,6 @@ def escape(pathname):
|
||||
else:
|
||||
pathname = magic_check.sub(r'[\1]', pathname)
|
||||
return drive + pathname
|
||||
|
||||
|
||||
_dir_open_flags = os.O_RDONLY | getattr(os, 'O_DIRECTORY', 0)
|
||||
|
||||
4
Lib/heapq.py
vendored
4
Lib/heapq.py
vendored
@@ -597,5 +597,5 @@ except ImportError:
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
import doctest
|
||||
print(doctest.testmod())
|
||||
import doctest # pragma: no cover
|
||||
print(doctest.testmod()) # pragma: no cover
|
||||
|
||||
2151
Lib/mailbox.py
vendored
Normal file
2151
Lib/mailbox.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
688
Lib/test/test_genericalias.py
vendored
688
Lib/test/test_genericalias.py
vendored
@@ -1,342 +1,346 @@
|
||||
"""Tests for C-implemented GenericAlias."""
|
||||
|
||||
import unittest
|
||||
import pickle
|
||||
import copy
|
||||
from collections import (
|
||||
defaultdict, deque, OrderedDict, Counter, UserDict, UserList
|
||||
)
|
||||
from collections.abc import *
|
||||
from concurrent.futures import Future
|
||||
from concurrent.futures.thread import _WorkItem
|
||||
from contextlib import AbstractContextManager, AbstractAsyncContextManager
|
||||
# XXX RUSTPYTHON TODO: from contextvars import ContextVar, Token
|
||||
from dataclasses import Field
|
||||
from functools import partial, partialmethod, cached_property
|
||||
# XXX RUSTPYTHON TODO: from mailbox import Mailbox, _PartialFile
|
||||
try:
|
||||
import ctypes
|
||||
except ImportError:
|
||||
ctypes = None
|
||||
from difflib import SequenceMatcher
|
||||
from filecmp import dircmp
|
||||
# XXX RUSTPYTHON TODO: from fileinput import FileInput
|
||||
from itertools import chain
|
||||
from http.cookies import Morsel
|
||||
from multiprocessing.managers import ValueProxy
|
||||
from multiprocessing.pool import ApplyResult
|
||||
try:
|
||||
from multiprocessing.shared_memory import ShareableList
|
||||
except ImportError:
|
||||
# multiprocessing.shared_memory is not available on e.g. Android
|
||||
ShareableList = None
|
||||
from multiprocessing.queues import SimpleQueue as MPSimpleQueue
|
||||
from os import DirEntry
|
||||
from re import Pattern, Match
|
||||
from types import GenericAlias, MappingProxyType, AsyncGeneratorType
|
||||
from tempfile import TemporaryDirectory, SpooledTemporaryFile
|
||||
from urllib.parse import SplitResult, ParseResult
|
||||
from unittest.case import _AssertRaisesContext
|
||||
from queue import Queue, SimpleQueue
|
||||
from weakref import WeakSet, ReferenceType, ref
|
||||
import typing
|
||||
|
||||
from typing import TypeVar
|
||||
T = TypeVar('T')
|
||||
K = TypeVar('K')
|
||||
V = TypeVar('V')
|
||||
|
||||
class BaseTest(unittest.TestCase):
|
||||
"""Test basics."""
|
||||
generic_types = [type, tuple, list, dict, set, frozenset, enumerate,
|
||||
defaultdict, deque,
|
||||
SequenceMatcher,
|
||||
dircmp,
|
||||
# XXX RUSTPYTHON TODO: FileInput,
|
||||
OrderedDict, Counter, UserDict, UserList,
|
||||
Pattern, Match,
|
||||
partialmethod, cached_property, # XXX RUSTPYTHON TODO: partial
|
||||
# XXX RUSTPYTHON TODO: AbstractContextManager, AbstractAsyncContextManager,
|
||||
Awaitable, Coroutine,
|
||||
AsyncIterable, AsyncIterator,
|
||||
AsyncGenerator, Generator,
|
||||
Iterable, Iterator,
|
||||
Reversible,
|
||||
Container, Collection,
|
||||
# XXX RUSTPYTHON TODO: Mailbox, _PartialFile,
|
||||
# XXX RUSTPYTHON TODO: ContextVar, Token,
|
||||
Field,
|
||||
Set, MutableSet,
|
||||
Mapping, MutableMapping, MappingView,
|
||||
KeysView, ItemsView, ValuesView,
|
||||
Sequence, MutableSequence,
|
||||
MappingProxyType, AsyncGeneratorType,
|
||||
DirEntry,
|
||||
chain,
|
||||
TemporaryDirectory, SpooledTemporaryFile,
|
||||
Queue, SimpleQueue,
|
||||
_AssertRaisesContext,
|
||||
SplitResult, ParseResult,
|
||||
ValueProxy, ApplyResult,
|
||||
WeakSet, ReferenceType, ref,
|
||||
ShareableList, MPSimpleQueue,
|
||||
Future, _WorkItem,
|
||||
Morsel]
|
||||
if ctypes is not None:
|
||||
generic_types.extend((ctypes.Array, ctypes.LibraryLoader))
|
||||
|
||||
def test_subscriptable(self):
|
||||
for t in self.generic_types:
|
||||
if t is None:
|
||||
continue
|
||||
tname = t.__name__
|
||||
with self.subTest(f"Testing {tname}"):
|
||||
alias = t[int]
|
||||
self.assertIs(alias.__origin__, t)
|
||||
self.assertEqual(alias.__args__, (int,))
|
||||
self.assertEqual(alias.__parameters__, ())
|
||||
|
||||
def test_unsubscriptable(self):
|
||||
for t in int, str, float, Sized, Hashable:
|
||||
tname = t.__name__
|
||||
with self.subTest(f"Testing {tname}"):
|
||||
with self.assertRaises(TypeError):
|
||||
t[int]
|
||||
|
||||
def test_instantiate(self):
|
||||
for t in tuple, list, dict, set, frozenset, defaultdict, deque:
|
||||
tname = t.__name__
|
||||
with self.subTest(f"Testing {tname}"):
|
||||
alias = t[int]
|
||||
self.assertEqual(alias(), t())
|
||||
if t is dict:
|
||||
self.assertEqual(alias(iter([('a', 1), ('b', 2)])), dict(a=1, b=2))
|
||||
self.assertEqual(alias(a=1, b=2), dict(a=1, b=2))
|
||||
elif t is defaultdict:
|
||||
def default():
|
||||
return 'value'
|
||||
a = alias(default)
|
||||
d = defaultdict(default)
|
||||
self.assertEqual(a['test'], d['test'])
|
||||
else:
|
||||
self.assertEqual(alias(iter((1, 2, 3))), t((1, 2, 3)))
|
||||
|
||||
def test_unbound_methods(self):
|
||||
t = list[int]
|
||||
a = t()
|
||||
t.append(a, 'foo')
|
||||
self.assertEqual(a, ['foo'])
|
||||
x = t.__getitem__(a, 0)
|
||||
self.assertEqual(x, 'foo')
|
||||
self.assertEqual(t.__len__(a), 1)
|
||||
|
||||
def test_subclassing(self):
|
||||
class C(list[int]):
|
||||
pass
|
||||
self.assertEqual(C.__bases__, (list,))
|
||||
self.assertEqual(C.__class__, type)
|
||||
|
||||
def test_class_methods(self):
|
||||
t = dict[int, None]
|
||||
self.assertEqual(dict.fromkeys(range(2)), {0: None, 1: None}) # This works
|
||||
self.assertEqual(t.fromkeys(range(2)), {0: None, 1: None}) # Should be equivalent
|
||||
|
||||
def test_no_chaining(self):
|
||||
t = list[int]
|
||||
with self.assertRaises(TypeError):
|
||||
t[int]
|
||||
|
||||
def test_generic_subclass(self):
|
||||
class MyList(list):
|
||||
pass
|
||||
t = MyList[int]
|
||||
self.assertIs(t.__origin__, MyList)
|
||||
self.assertEqual(t.__args__, (int,))
|
||||
self.assertEqual(t.__parameters__, ())
|
||||
|
||||
def test_repr(self):
|
||||
class MyList(list):
|
||||
pass
|
||||
self.assertEqual(repr(list[str]), 'list[str]')
|
||||
self.assertEqual(repr(list[()]), 'list[()]')
|
||||
self.assertEqual(repr(tuple[int, ...]), 'tuple[int, ...]')
|
||||
self.assertTrue(repr(MyList[int]).endswith('.BaseTest.test_repr.<locals>.MyList[int]'))
|
||||
self.assertEqual(repr(list[str]()), '[]') # instances should keep their normal repr
|
||||
|
||||
def test_exposed_type(self):
|
||||
import types
|
||||
a = types.GenericAlias(list, int)
|
||||
self.assertEqual(str(a), 'list[int]')
|
||||
self.assertIs(a.__origin__, list)
|
||||
self.assertEqual(a.__args__, (int,))
|
||||
self.assertEqual(a.__parameters__, ())
|
||||
|
||||
def test_parameters(self):
|
||||
from typing import List, Dict, Callable
|
||||
D0 = dict[str, int]
|
||||
self.assertEqual(D0.__args__, (str, int))
|
||||
self.assertEqual(D0.__parameters__, ())
|
||||
D1a = dict[str, V]
|
||||
self.assertEqual(D1a.__args__, (str, V))
|
||||
self.assertEqual(D1a.__parameters__, (V,))
|
||||
D1b = dict[K, int]
|
||||
self.assertEqual(D1b.__args__, (K, int))
|
||||
self.assertEqual(D1b.__parameters__, (K,))
|
||||
D2a = dict[K, V]
|
||||
self.assertEqual(D2a.__args__, (K, V))
|
||||
self.assertEqual(D2a.__parameters__, (K, V))
|
||||
D2b = dict[T, T]
|
||||
self.assertEqual(D2b.__args__, (T, T))
|
||||
self.assertEqual(D2b.__parameters__, (T,))
|
||||
L0 = list[str]
|
||||
self.assertEqual(L0.__args__, (str,))
|
||||
self.assertEqual(L0.__parameters__, ())
|
||||
L1 = list[T]
|
||||
self.assertEqual(L1.__args__, (T,))
|
||||
self.assertEqual(L1.__parameters__, (T,))
|
||||
L2 = list[list[T]]
|
||||
self.assertEqual(L2.__args__, (list[T],))
|
||||
self.assertEqual(L2.__parameters__, (T,))
|
||||
L3 = list[List[T]]
|
||||
self.assertEqual(L3.__args__, (List[T],))
|
||||
self.assertEqual(L3.__parameters__, (T,))
|
||||
L4a = list[Dict[K, V]]
|
||||
self.assertEqual(L4a.__args__, (Dict[K, V],))
|
||||
self.assertEqual(L4a.__parameters__, (K, V))
|
||||
L4b = list[Dict[T, int]]
|
||||
self.assertEqual(L4b.__args__, (Dict[T, int],))
|
||||
self.assertEqual(L4b.__parameters__, (T,))
|
||||
L5 = list[Callable[[K, V], K]]
|
||||
self.assertEqual(L5.__args__, (Callable[[K, V], K],))
|
||||
self.assertEqual(L5.__parameters__, (K, V))
|
||||
|
||||
def test_parameter_chaining(self):
|
||||
from typing import List, Dict, Union, Callable
|
||||
self.assertEqual(list[T][int], list[int])
|
||||
self.assertEqual(dict[str, T][int], dict[str, int])
|
||||
self.assertEqual(dict[T, int][str], dict[str, int])
|
||||
self.assertEqual(dict[K, V][str, int], dict[str, int])
|
||||
self.assertEqual(dict[T, T][int], dict[int, int])
|
||||
|
||||
self.assertEqual(list[list[T]][int], list[list[int]])
|
||||
self.assertEqual(list[dict[T, int]][str], list[dict[str, int]])
|
||||
self.assertEqual(list[dict[str, T]][int], list[dict[str, int]])
|
||||
self.assertEqual(list[dict[K, V]][str, int], list[dict[str, int]])
|
||||
self.assertEqual(dict[T, list[int]][str], dict[str, list[int]])
|
||||
|
||||
self.assertEqual(list[List[T]][int], list[List[int]])
|
||||
self.assertEqual(list[Dict[K, V]][str, int], list[Dict[str, int]])
|
||||
self.assertEqual(list[Union[K, V]][str, int], list[Union[str, int]])
|
||||
self.assertEqual(list[Callable[[K, V], K]][str, int],
|
||||
list[Callable[[str, int], str]])
|
||||
self.assertEqual(dict[T, List[int]][str], dict[str, List[int]])
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
list[int][int]
|
||||
dict[T, int][str, int]
|
||||
dict[str, T][str, int]
|
||||
dict[T, T][str, int]
|
||||
|
||||
def test_equality(self):
|
||||
self.assertEqual(list[int], list[int])
|
||||
self.assertEqual(dict[str, int], dict[str, int])
|
||||
self.assertNotEqual(dict[str, int], dict[str, str])
|
||||
self.assertNotEqual(list, list[int])
|
||||
self.assertNotEqual(list[int], list)
|
||||
|
||||
def test_isinstance(self):
|
||||
self.assertTrue(isinstance([], list))
|
||||
with self.assertRaises(TypeError):
|
||||
isinstance([], list[str])
|
||||
|
||||
def test_issubclass(self):
|
||||
class L(list): ...
|
||||
self.assertTrue(issubclass(L, list))
|
||||
with self.assertRaises(TypeError):
|
||||
issubclass(L, list[str])
|
||||
|
||||
def test_type_generic(self):
|
||||
t = type[int]
|
||||
Test = t('Test', (), {})
|
||||
self.assertTrue(isinstance(Test, type))
|
||||
test = Test()
|
||||
self.assertEqual(t(test), Test)
|
||||
self.assertEqual(t(0), int)
|
||||
|
||||
def test_type_subclass_generic(self):
|
||||
class MyType(type):
|
||||
pass
|
||||
with self.assertRaises(TypeError):
|
||||
MyType[int]
|
||||
|
||||
def test_pickle(self):
|
||||
alias = GenericAlias(list, T)
|
||||
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
|
||||
s = pickle.dumps(alias, proto)
|
||||
loaded = pickle.loads(s)
|
||||
self.assertEqual(loaded.__origin__, alias.__origin__)
|
||||
self.assertEqual(loaded.__args__, alias.__args__)
|
||||
self.assertEqual(loaded.__parameters__, alias.__parameters__)
|
||||
|
||||
def test_copy(self):
|
||||
class X(list):
|
||||
def __copy__(self):
|
||||
return self
|
||||
def __deepcopy__(self, memo):
|
||||
return self
|
||||
|
||||
for origin in list, deque, X:
|
||||
alias = GenericAlias(origin, T)
|
||||
copied = copy.copy(alias)
|
||||
self.assertEqual(copied.__origin__, alias.__origin__)
|
||||
self.assertEqual(copied.__args__, alias.__args__)
|
||||
self.assertEqual(copied.__parameters__, alias.__parameters__)
|
||||
copied = copy.deepcopy(alias)
|
||||
self.assertEqual(copied.__origin__, alias.__origin__)
|
||||
self.assertEqual(copied.__args__, alias.__args__)
|
||||
self.assertEqual(copied.__parameters__, alias.__parameters__)
|
||||
|
||||
def test_union(self):
|
||||
a = typing.Union[list[int], list[str]]
|
||||
self.assertEqual(a.__args__, (list[int], list[str]))
|
||||
self.assertEqual(a.__parameters__, ())
|
||||
|
||||
def test_union_generic(self):
|
||||
a = typing.Union[list[T], tuple[T, ...]]
|
||||
self.assertEqual(a.__args__, (list[T], tuple[T, ...]))
|
||||
self.assertEqual(a.__parameters__, (T,))
|
||||
|
||||
def test_dir(self):
|
||||
dir_of_gen_alias = set(dir(list[int]))
|
||||
self.assertTrue(dir_of_gen_alias.issuperset(dir(list)))
|
||||
for generic_alias_property in ("__origin__", "__args__", "__parameters__"):
|
||||
self.assertIn(generic_alias_property, dir_of_gen_alias)
|
||||
|
||||
def test_weakref(self):
|
||||
for t in self.generic_types:
|
||||
if t is None:
|
||||
continue
|
||||
tname = t.__name__
|
||||
with self.subTest(f"Testing {tname}"):
|
||||
alias = t[int]
|
||||
self.assertEqual(ref(alias)(), alias)
|
||||
|
||||
def test_no_kwargs(self):
|
||||
# bpo-42576
|
||||
with self.assertRaises(TypeError):
|
||||
GenericAlias(bad=float)
|
||||
|
||||
def test_subclassing_types_genericalias(self):
|
||||
class SubClass(GenericAlias): ...
|
||||
alias = SubClass(list, int)
|
||||
class Bad(GenericAlias):
|
||||
def __new__(cls, *args, **kwargs):
|
||||
super().__new__(cls, *args, **kwargs)
|
||||
|
||||
self.assertEqual(alias, list[int])
|
||||
with self.assertRaises(TypeError):
|
||||
Bad(list, int, bad=int)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
"""Tests for C-implemented GenericAlias."""
|
||||
|
||||
import unittest
|
||||
import pickle
|
||||
import copy
|
||||
from collections import (
|
||||
defaultdict, deque, OrderedDict, Counter, UserDict, UserList
|
||||
)
|
||||
from collections.abc import *
|
||||
from concurrent.futures import Future
|
||||
from concurrent.futures.thread import _WorkItem
|
||||
from contextlib import AbstractContextManager, AbstractAsyncContextManager
|
||||
from contextvars import ContextVar, Token
|
||||
from dataclasses import Field
|
||||
from functools import partial, partialmethod, cached_property
|
||||
from mailbox import Mailbox, _PartialFile
|
||||
try:
|
||||
import ctypes
|
||||
except ImportError:
|
||||
ctypes = None
|
||||
from difflib import SequenceMatcher
|
||||
from filecmp import dircmp
|
||||
from fileinput import FileInput
|
||||
from itertools import chain
|
||||
from http.cookies import Morsel
|
||||
from multiprocessing.managers import ValueProxy
|
||||
from multiprocessing.pool import ApplyResult
|
||||
try:
|
||||
from multiprocessing.shared_memory import ShareableList
|
||||
except ImportError:
|
||||
# multiprocessing.shared_memory is not available on e.g. Android
|
||||
ShareableList = None
|
||||
from multiprocessing.queues import SimpleQueue as MPSimpleQueue
|
||||
from os import DirEntry
|
||||
from re import Pattern, Match
|
||||
from types import GenericAlias, MappingProxyType, AsyncGeneratorType
|
||||
from tempfile import TemporaryDirectory, SpooledTemporaryFile
|
||||
from urllib.parse import SplitResult, ParseResult
|
||||
from unittest.case import _AssertRaisesContext
|
||||
from queue import Queue, SimpleQueue
|
||||
from weakref import WeakSet, ReferenceType, ref
|
||||
import typing
|
||||
|
||||
from typing import TypeVar
|
||||
T = TypeVar('T')
|
||||
K = TypeVar('K')
|
||||
V = TypeVar('V')
|
||||
|
||||
class BaseTest(unittest.TestCase):
|
||||
"""Test basics."""
|
||||
generic_types = [type, tuple, list, dict, set, frozenset, enumerate,
|
||||
defaultdict, deque,
|
||||
SequenceMatcher,
|
||||
dircmp,
|
||||
FileInput,
|
||||
OrderedDict, Counter, UserDict, UserList,
|
||||
Pattern, Match,
|
||||
partial, partialmethod, cached_property,
|
||||
AbstractContextManager, AbstractAsyncContextManager,
|
||||
Awaitable, Coroutine,
|
||||
AsyncIterable, AsyncIterator,
|
||||
AsyncGenerator, Generator,
|
||||
Iterable, Iterator,
|
||||
Reversible,
|
||||
Container, Collection,
|
||||
Mailbox, _PartialFile,
|
||||
ContextVar, Token,
|
||||
Field,
|
||||
Set, MutableSet,
|
||||
Mapping, MutableMapping, MappingView,
|
||||
KeysView, ItemsView, ValuesView,
|
||||
Sequence, MutableSequence,
|
||||
MappingProxyType, AsyncGeneratorType,
|
||||
DirEntry,
|
||||
chain,
|
||||
TemporaryDirectory, SpooledTemporaryFile,
|
||||
Queue, SimpleQueue,
|
||||
_AssertRaisesContext,
|
||||
SplitResult, ParseResult,
|
||||
ValueProxy, ApplyResult,
|
||||
WeakSet, ReferenceType, ref,
|
||||
ShareableList, MPSimpleQueue,
|
||||
Future, _WorkItem,
|
||||
Morsel]
|
||||
if ctypes is not None:
|
||||
generic_types.extend((ctypes.Array, ctypes.LibraryLoader))
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_subscriptable(self):
|
||||
for t in self.generic_types:
|
||||
if t is None:
|
||||
continue
|
||||
tname = t.__name__
|
||||
with self.subTest(f"Testing {tname}"):
|
||||
alias = t[int]
|
||||
self.assertIs(alias.__origin__, t)
|
||||
self.assertEqual(alias.__args__, (int,))
|
||||
self.assertEqual(alias.__parameters__, ())
|
||||
|
||||
def test_unsubscriptable(self):
|
||||
for t in int, str, float, Sized, Hashable:
|
||||
tname = t.__name__
|
||||
with self.subTest(f"Testing {tname}"):
|
||||
with self.assertRaises(TypeError):
|
||||
t[int]
|
||||
|
||||
def test_instantiate(self):
|
||||
for t in tuple, list, dict, set, frozenset, defaultdict, deque:
|
||||
tname = t.__name__
|
||||
with self.subTest(f"Testing {tname}"):
|
||||
alias = t[int]
|
||||
self.assertEqual(alias(), t())
|
||||
if t is dict:
|
||||
self.assertEqual(alias(iter([('a', 1), ('b', 2)])), dict(a=1, b=2))
|
||||
self.assertEqual(alias(a=1, b=2), dict(a=1, b=2))
|
||||
elif t is defaultdict:
|
||||
def default():
|
||||
return 'value'
|
||||
a = alias(default)
|
||||
d = defaultdict(default)
|
||||
self.assertEqual(a['test'], d['test'])
|
||||
else:
|
||||
self.assertEqual(alias(iter((1, 2, 3))), t((1, 2, 3)))
|
||||
|
||||
def test_unbound_methods(self):
|
||||
t = list[int]
|
||||
a = t()
|
||||
t.append(a, 'foo')
|
||||
self.assertEqual(a, ['foo'])
|
||||
x = t.__getitem__(a, 0)
|
||||
self.assertEqual(x, 'foo')
|
||||
self.assertEqual(t.__len__(a), 1)
|
||||
|
||||
def test_subclassing(self):
|
||||
class C(list[int]):
|
||||
pass
|
||||
self.assertEqual(C.__bases__, (list,))
|
||||
self.assertEqual(C.__class__, type)
|
||||
|
||||
def test_class_methods(self):
|
||||
t = dict[int, None]
|
||||
self.assertEqual(dict.fromkeys(range(2)), {0: None, 1: None}) # This works
|
||||
self.assertEqual(t.fromkeys(range(2)), {0: None, 1: None}) # Should be equivalent
|
||||
|
||||
def test_no_chaining(self):
|
||||
t = list[int]
|
||||
with self.assertRaises(TypeError):
|
||||
t[int]
|
||||
|
||||
def test_generic_subclass(self):
|
||||
class MyList(list):
|
||||
pass
|
||||
t = MyList[int]
|
||||
self.assertIs(t.__origin__, MyList)
|
||||
self.assertEqual(t.__args__, (int,))
|
||||
self.assertEqual(t.__parameters__, ())
|
||||
|
||||
def test_repr(self):
|
||||
class MyList(list):
|
||||
pass
|
||||
self.assertEqual(repr(list[str]), 'list[str]')
|
||||
self.assertEqual(repr(list[()]), 'list[()]')
|
||||
self.assertEqual(repr(tuple[int, ...]), 'tuple[int, ...]')
|
||||
self.assertTrue(repr(MyList[int]).endswith('.BaseTest.test_repr.<locals>.MyList[int]'))
|
||||
self.assertEqual(repr(list[str]()), '[]') # instances should keep their normal repr
|
||||
|
||||
def test_exposed_type(self):
|
||||
import types
|
||||
a = types.GenericAlias(list, int)
|
||||
self.assertEqual(str(a), 'list[int]')
|
||||
self.assertIs(a.__origin__, list)
|
||||
self.assertEqual(a.__args__, (int,))
|
||||
self.assertEqual(a.__parameters__, ())
|
||||
|
||||
def test_parameters(self):
|
||||
from typing import List, Dict, Callable
|
||||
D0 = dict[str, int]
|
||||
self.assertEqual(D0.__args__, (str, int))
|
||||
self.assertEqual(D0.__parameters__, ())
|
||||
D1a = dict[str, V]
|
||||
self.assertEqual(D1a.__args__, (str, V))
|
||||
self.assertEqual(D1a.__parameters__, (V,))
|
||||
D1b = dict[K, int]
|
||||
self.assertEqual(D1b.__args__, (K, int))
|
||||
self.assertEqual(D1b.__parameters__, (K,))
|
||||
D2a = dict[K, V]
|
||||
self.assertEqual(D2a.__args__, (K, V))
|
||||
self.assertEqual(D2a.__parameters__, (K, V))
|
||||
D2b = dict[T, T]
|
||||
self.assertEqual(D2b.__args__, (T, T))
|
||||
self.assertEqual(D2b.__parameters__, (T,))
|
||||
L0 = list[str]
|
||||
self.assertEqual(L0.__args__, (str,))
|
||||
self.assertEqual(L0.__parameters__, ())
|
||||
L1 = list[T]
|
||||
self.assertEqual(L1.__args__, (T,))
|
||||
self.assertEqual(L1.__parameters__, (T,))
|
||||
L2 = list[list[T]]
|
||||
self.assertEqual(L2.__args__, (list[T],))
|
||||
self.assertEqual(L2.__parameters__, (T,))
|
||||
L3 = list[List[T]]
|
||||
self.assertEqual(L3.__args__, (List[T],))
|
||||
self.assertEqual(L3.__parameters__, (T,))
|
||||
L4a = list[Dict[K, V]]
|
||||
self.assertEqual(L4a.__args__, (Dict[K, V],))
|
||||
self.assertEqual(L4a.__parameters__, (K, V))
|
||||
L4b = list[Dict[T, int]]
|
||||
self.assertEqual(L4b.__args__, (Dict[T, int],))
|
||||
self.assertEqual(L4b.__parameters__, (T,))
|
||||
L5 = list[Callable[[K, V], K]]
|
||||
self.assertEqual(L5.__args__, (Callable[[K, V], K],))
|
||||
self.assertEqual(L5.__parameters__, (K, V))
|
||||
|
||||
def test_parameter_chaining(self):
|
||||
from typing import List, Dict, Union, Callable
|
||||
self.assertEqual(list[T][int], list[int])
|
||||
self.assertEqual(dict[str, T][int], dict[str, int])
|
||||
self.assertEqual(dict[T, int][str], dict[str, int])
|
||||
self.assertEqual(dict[K, V][str, int], dict[str, int])
|
||||
self.assertEqual(dict[T, T][int], dict[int, int])
|
||||
|
||||
self.assertEqual(list[list[T]][int], list[list[int]])
|
||||
self.assertEqual(list[dict[T, int]][str], list[dict[str, int]])
|
||||
self.assertEqual(list[dict[str, T]][int], list[dict[str, int]])
|
||||
self.assertEqual(list[dict[K, V]][str, int], list[dict[str, int]])
|
||||
self.assertEqual(dict[T, list[int]][str], dict[str, list[int]])
|
||||
|
||||
self.assertEqual(list[List[T]][int], list[List[int]])
|
||||
self.assertEqual(list[Dict[K, V]][str, int], list[Dict[str, int]])
|
||||
self.assertEqual(list[Union[K, V]][str, int], list[Union[str, int]])
|
||||
self.assertEqual(list[Callable[[K, V], K]][str, int],
|
||||
list[Callable[[str, int], str]])
|
||||
self.assertEqual(dict[T, List[int]][str], dict[str, List[int]])
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
list[int][int]
|
||||
dict[T, int][str, int]
|
||||
dict[str, T][str, int]
|
||||
dict[T, T][str, int]
|
||||
|
||||
def test_equality(self):
|
||||
self.assertEqual(list[int], list[int])
|
||||
self.assertEqual(dict[str, int], dict[str, int])
|
||||
self.assertNotEqual(dict[str, int], dict[str, str])
|
||||
self.assertNotEqual(list, list[int])
|
||||
self.assertNotEqual(list[int], list)
|
||||
|
||||
def test_isinstance(self):
|
||||
self.assertTrue(isinstance([], list))
|
||||
with self.assertRaises(TypeError):
|
||||
isinstance([], list[str])
|
||||
|
||||
def test_issubclass(self):
|
||||
class L(list): ...
|
||||
self.assertTrue(issubclass(L, list))
|
||||
with self.assertRaises(TypeError):
|
||||
issubclass(L, list[str])
|
||||
|
||||
def test_type_generic(self):
|
||||
t = type[int]
|
||||
Test = t('Test', (), {})
|
||||
self.assertTrue(isinstance(Test, type))
|
||||
test = Test()
|
||||
self.assertEqual(t(test), Test)
|
||||
self.assertEqual(t(0), int)
|
||||
|
||||
def test_type_subclass_generic(self):
|
||||
class MyType(type):
|
||||
pass
|
||||
with self.assertRaises(TypeError):
|
||||
MyType[int]
|
||||
|
||||
def test_pickle(self):
|
||||
alias = GenericAlias(list, T)
|
||||
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
|
||||
s = pickle.dumps(alias, proto)
|
||||
loaded = pickle.loads(s)
|
||||
self.assertEqual(loaded.__origin__, alias.__origin__)
|
||||
self.assertEqual(loaded.__args__, alias.__args__)
|
||||
self.assertEqual(loaded.__parameters__, alias.__parameters__)
|
||||
|
||||
def test_copy(self):
|
||||
class X(list):
|
||||
def __copy__(self):
|
||||
return self
|
||||
def __deepcopy__(self, memo):
|
||||
return self
|
||||
|
||||
for origin in list, deque, X:
|
||||
alias = GenericAlias(origin, T)
|
||||
copied = copy.copy(alias)
|
||||
self.assertEqual(copied.__origin__, alias.__origin__)
|
||||
self.assertEqual(copied.__args__, alias.__args__)
|
||||
self.assertEqual(copied.__parameters__, alias.__parameters__)
|
||||
copied = copy.deepcopy(alias)
|
||||
self.assertEqual(copied.__origin__, alias.__origin__)
|
||||
self.assertEqual(copied.__args__, alias.__args__)
|
||||
self.assertEqual(copied.__parameters__, alias.__parameters__)
|
||||
|
||||
def test_union(self):
|
||||
a = typing.Union[list[int], list[str]]
|
||||
self.assertEqual(a.__args__, (list[int], list[str]))
|
||||
self.assertEqual(a.__parameters__, ())
|
||||
|
||||
def test_union_generic(self):
|
||||
a = typing.Union[list[T], tuple[T, ...]]
|
||||
self.assertEqual(a.__args__, (list[T], tuple[T, ...]))
|
||||
self.assertEqual(a.__parameters__, (T,))
|
||||
|
||||
def test_dir(self):
|
||||
dir_of_gen_alias = set(dir(list[int]))
|
||||
self.assertTrue(dir_of_gen_alias.issuperset(dir(list)))
|
||||
for generic_alias_property in ("__origin__", "__args__", "__parameters__"):
|
||||
self.assertIn(generic_alias_property, dir_of_gen_alias)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_weakref(self):
|
||||
for t in self.generic_types:
|
||||
if t is None:
|
||||
continue
|
||||
tname = t.__name__
|
||||
with self.subTest(f"Testing {tname}"):
|
||||
alias = t[int]
|
||||
self.assertEqual(ref(alias)(), alias)
|
||||
|
||||
def test_no_kwargs(self):
|
||||
# bpo-42576
|
||||
with self.assertRaises(TypeError):
|
||||
GenericAlias(bad=float)
|
||||
|
||||
def test_subclassing_types_genericalias(self):
|
||||
class SubClass(GenericAlias): ...
|
||||
alias = SubClass(list, int)
|
||||
class Bad(GenericAlias):
|
||||
def __new__(cls, *args, **kwargs):
|
||||
super().__new__(cls, *args, **kwargs)
|
||||
|
||||
self.assertEqual(alias, list[int])
|
||||
with self.assertRaises(TypeError):
|
||||
Bad(list, int, bad=int)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
67
Lib/test/test_glob.py
vendored
67
Lib/test/test_glob.py
vendored
@@ -9,6 +9,7 @@ from test.support.os_helper import (TESTFN, skip_unless_symlink,
|
||||
|
||||
|
||||
class GlobTests(unittest.TestCase):
|
||||
dir_fd = None
|
||||
|
||||
def norm(self, *parts):
|
||||
return os.path.normpath(os.path.join(self.tempdir, *parts))
|
||||
@@ -38,8 +39,14 @@ class GlobTests(unittest.TestCase):
|
||||
os.symlink(self.norm('broken'), self.norm('sym1'))
|
||||
os.symlink('broken', self.norm('sym2'))
|
||||
os.symlink(os.path.join('a', 'bcd'), self.norm('sym3'))
|
||||
if {os.open, os.stat} <= os.supports_dir_fd and os.scandir in os.supports_fd:
|
||||
self.dir_fd = os.open(self.tempdir, os.O_RDONLY | os.O_DIRECTORY)
|
||||
else:
|
||||
self.dir_fd = None
|
||||
|
||||
def tearDown(self):
|
||||
if self.dir_fd is not None:
|
||||
os.close(self.dir_fd)
|
||||
shutil.rmtree(self.tempdir)
|
||||
|
||||
def glob(self, *parts, **kwargs):
|
||||
@@ -53,6 +60,41 @@ class GlobTests(unittest.TestCase):
|
||||
bres = [os.fsencode(x) for x in res]
|
||||
self.assertCountEqual(glob.glob(os.fsencode(p), **kwargs), bres)
|
||||
self.assertCountEqual(glob.iglob(os.fsencode(p), **kwargs), bres)
|
||||
|
||||
with change_cwd(self.tempdir):
|
||||
res2 = glob.glob(pattern, **kwargs)
|
||||
for x in res2:
|
||||
self.assertFalse(os.path.isabs(x), x)
|
||||
if pattern == '**' or pattern == '**' + os.sep:
|
||||
expected = res[1:]
|
||||
else:
|
||||
expected = res
|
||||
self.assertCountEqual([os.path.join(self.tempdir, x) for x in res2],
|
||||
expected)
|
||||
self.assertCountEqual(glob.iglob(pattern, **kwargs), res2)
|
||||
bpattern = os.fsencode(pattern)
|
||||
bres2 = [os.fsencode(x) for x in res2]
|
||||
self.assertCountEqual(glob.glob(bpattern, **kwargs), bres2)
|
||||
self.assertCountEqual(glob.iglob(bpattern, **kwargs), bres2)
|
||||
|
||||
self.assertCountEqual(glob.glob(pattern, root_dir=self.tempdir, **kwargs), res2)
|
||||
self.assertCountEqual(glob.iglob(pattern, root_dir=self.tempdir, **kwargs), res2)
|
||||
btempdir = os.fsencode(self.tempdir)
|
||||
self.assertCountEqual(
|
||||
glob.glob(bpattern, root_dir=btempdir, **kwargs), bres2)
|
||||
self.assertCountEqual(
|
||||
glob.iglob(bpattern, root_dir=btempdir, **kwargs), bres2)
|
||||
|
||||
if self.dir_fd is not None:
|
||||
self.assertCountEqual(
|
||||
glob.glob(pattern, dir_fd=self.dir_fd, **kwargs), res2)
|
||||
self.assertCountEqual(
|
||||
glob.iglob(pattern, dir_fd=self.dir_fd, **kwargs), res2)
|
||||
self.assertCountEqual(
|
||||
glob.glob(bpattern, dir_fd=self.dir_fd, **kwargs), bres2)
|
||||
self.assertCountEqual(
|
||||
glob.iglob(bpattern, dir_fd=self.dir_fd, **kwargs), bres2)
|
||||
|
||||
return res
|
||||
|
||||
def assertSequencesEqual_noorder(self, l1, l2):
|
||||
@@ -78,6 +120,14 @@ class GlobTests(unittest.TestCase):
|
||||
res = glob.glob(os.path.join(os.fsencode(os.curdir), b'*'))
|
||||
self.assertEqual({type(r) for r in res}, {bytes})
|
||||
|
||||
def test_glob_empty_pattern(self):
|
||||
self.assertEqual(glob.glob(''), [])
|
||||
self.assertEqual(glob.glob(b''), [])
|
||||
self.assertEqual(glob.glob('', root_dir=self.tempdir), [])
|
||||
self.assertEqual(glob.glob(b'', root_dir=os.fsencode(self.tempdir)), [])
|
||||
self.assertEqual(glob.glob('', dir_fd=self.dir_fd), [])
|
||||
self.assertEqual(glob.glob(b'', dir_fd=self.dir_fd), [])
|
||||
|
||||
def test_glob_one_directory(self):
|
||||
eq = self.assertSequencesEqual_noorder
|
||||
eq(self.glob('a*'), map(self.norm, ['a', 'aab', 'aaa']))
|
||||
@@ -264,6 +314,23 @@ class GlobTests(unittest.TestCase):
|
||||
expect += [join('sym3', 'EF')]
|
||||
eq(glob.glob(join('**', 'EF'), recursive=True), expect)
|
||||
|
||||
def test_glob_many_open_files(self):
|
||||
depth = 30
|
||||
base = os.path.join(self.tempdir, 'deep')
|
||||
p = os.path.join(base, *(['d']*depth))
|
||||
os.makedirs(p)
|
||||
pattern = os.path.join(base, *(['*']*depth))
|
||||
iters = [glob.iglob(pattern, recursive=True) for j in range(100)]
|
||||
for it in iters:
|
||||
self.assertEqual(next(it), p)
|
||||
pattern = os.path.join(base, '**', 'd')
|
||||
iters = [glob.iglob(pattern, recursive=True) for j in range(100)]
|
||||
p = base
|
||||
for i in range(depth):
|
||||
p = os.path.join(p, 'd')
|
||||
for it in iters:
|
||||
self.assertEqual(next(it), p)
|
||||
|
||||
|
||||
@skip_unless_symlink
|
||||
class SymlinkLoopGlobTests(unittest.TestCase):
|
||||
|
||||
14
Lib/test/test_global.py
vendored
14
Lib/test/test_global.py
vendored
@@ -1,6 +1,6 @@
|
||||
"""Verify that warnings are issued for global statements following use."""
|
||||
|
||||
from test.support import run_unittest, check_syntax_error
|
||||
from test.support import check_syntax_error
|
||||
from test.support.warnings_helper import check_warnings
|
||||
import unittest
|
||||
import warnings
|
||||
@@ -53,10 +53,12 @@ x = 2
|
||||
compile(prog_text_4, "<test string>", "exec")
|
||||
|
||||
|
||||
def test_main():
|
||||
with warnings.catch_warnings():
|
||||
warnings.filterwarnings("error", module="<test string>")
|
||||
run_unittest(GlobalTests)
|
||||
def setUpModule():
|
||||
cm = warnings.catch_warnings()
|
||||
cm.__enter__()
|
||||
unittest.addModuleCleanup(cm.__exit__, None, None, None)
|
||||
warnings.filterwarnings("error", module="<test string>")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_main()
|
||||
unittest.main()
|
||||
|
||||
358
Lib/test/test_hash.py
vendored
Normal file
358
Lib/test/test_hash.py
vendored
Normal file
@@ -0,0 +1,358 @@
|
||||
# test the invariant that
|
||||
# iff a==b then hash(a)==hash(b)
|
||||
#
|
||||
# Also test that hash implementations are inherited as expected
|
||||
|
||||
import datetime
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
from test.support.script_helper import assert_python_ok
|
||||
from collections.abc import Hashable
|
||||
|
||||
IS_64BIT = sys.maxsize > 2**32
|
||||
|
||||
def lcg(x, length=16):
|
||||
"""Linear congruential generator"""
|
||||
if x == 0:
|
||||
return bytes(length)
|
||||
out = bytearray(length)
|
||||
for i in range(length):
|
||||
x = (214013 * x + 2531011) & 0x7fffffff
|
||||
out[i] = (x >> 16) & 0xff
|
||||
return bytes(out)
|
||||
|
||||
def pysiphash(uint64):
|
||||
"""Convert SipHash24 output to Py_hash_t
|
||||
"""
|
||||
assert 0 <= uint64 < (1 << 64)
|
||||
# simple unsigned to signed int64
|
||||
if uint64 > (1 << 63) - 1:
|
||||
int64 = uint64 - (1 << 64)
|
||||
else:
|
||||
int64 = uint64
|
||||
# mangle uint64 to uint32
|
||||
uint32 = (uint64 ^ uint64 >> 32) & 0xffffffff
|
||||
# simple unsigned to signed int32
|
||||
if uint32 > (1 << 31) - 1:
|
||||
int32 = uint32 - (1 << 32)
|
||||
else:
|
||||
int32 = uint32
|
||||
return int32, int64
|
||||
|
||||
def skip_unless_internalhash(test):
|
||||
"""Skip decorator for tests that depend on SipHash24 or FNV"""
|
||||
ok = sys.hash_info.algorithm in {"fnv", "siphash24"}
|
||||
msg = "Requires SipHash24 or FNV"
|
||||
return test if ok else unittest.skip(msg)(test)
|
||||
|
||||
|
||||
class HashEqualityTestCase(unittest.TestCase):
|
||||
|
||||
def same_hash(self, *objlist):
|
||||
# Hash each object given and fail if
|
||||
# the hash values are not all the same.
|
||||
hashed = list(map(hash, objlist))
|
||||
for h in hashed[1:]:
|
||||
if h != hashed[0]:
|
||||
self.fail("hashed values differ: %r" % (objlist,))
|
||||
|
||||
def test_numeric_literals(self):
|
||||
self.same_hash(1, 1, 1.0, 1.0+0.0j)
|
||||
self.same_hash(0, 0.0, 0.0+0.0j)
|
||||
self.same_hash(-1, -1.0, -1.0+0.0j)
|
||||
self.same_hash(-2, -2.0, -2.0+0.0j)
|
||||
|
||||
def test_coerced_integers(self):
|
||||
self.same_hash(int(1), int(1), float(1), complex(1),
|
||||
int('1'), float('1.0'))
|
||||
self.same_hash(int(-2**31), float(-2**31))
|
||||
self.same_hash(int(1-2**31), float(1-2**31))
|
||||
self.same_hash(int(2**31-1), float(2**31-1))
|
||||
# for 64-bit platforms
|
||||
self.same_hash(int(2**31), float(2**31))
|
||||
self.same_hash(int(-2**63), float(-2**63))
|
||||
self.same_hash(int(2**63), float(2**63))
|
||||
|
||||
def test_coerced_floats(self):
|
||||
self.same_hash(int(1.23e300), float(1.23e300))
|
||||
self.same_hash(float(0.5), complex(0.5, 0.0))
|
||||
|
||||
def test_unaligned_buffers(self):
|
||||
# The hash function for bytes-like objects shouldn't have
|
||||
# alignment-dependent results (example in issue #16427).
|
||||
b = b"123456789abcdefghijklmnopqrstuvwxyz" * 128
|
||||
for i in range(16):
|
||||
for j in range(16):
|
||||
aligned = b[i:128+j]
|
||||
unaligned = memoryview(b)[i:128+j]
|
||||
self.assertEqual(hash(aligned), hash(unaligned))
|
||||
|
||||
|
||||
_default_hash = object.__hash__
|
||||
class DefaultHash(object): pass
|
||||
|
||||
_FIXED_HASH_VALUE = 42
|
||||
class FixedHash(object):
|
||||
def __hash__(self):
|
||||
return _FIXED_HASH_VALUE
|
||||
|
||||
class OnlyEquality(object):
|
||||
def __eq__(self, other):
|
||||
return self is other
|
||||
|
||||
class OnlyInequality(object):
|
||||
def __ne__(self, other):
|
||||
return self is not other
|
||||
|
||||
class InheritedHashWithEquality(FixedHash, OnlyEquality): pass
|
||||
class InheritedHashWithInequality(FixedHash, OnlyInequality): pass
|
||||
|
||||
class NoHash(object):
|
||||
__hash__ = None
|
||||
|
||||
class HashInheritanceTestCase(unittest.TestCase):
|
||||
default_expected = [object(),
|
||||
DefaultHash(),
|
||||
OnlyInequality(),
|
||||
]
|
||||
fixed_expected = [FixedHash(),
|
||||
InheritedHashWithEquality(),
|
||||
InheritedHashWithInequality(),
|
||||
]
|
||||
error_expected = [NoHash(),
|
||||
OnlyEquality(),
|
||||
]
|
||||
|
||||
def test_default_hash(self):
|
||||
for obj in self.default_expected:
|
||||
self.assertEqual(hash(obj), _default_hash(obj))
|
||||
|
||||
def test_fixed_hash(self):
|
||||
for obj in self.fixed_expected:
|
||||
self.assertEqual(hash(obj), _FIXED_HASH_VALUE)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_error_hash(self):
|
||||
for obj in self.error_expected:
|
||||
self.assertRaises(TypeError, hash, obj)
|
||||
|
||||
def test_hashable(self):
|
||||
objects = (self.default_expected +
|
||||
self.fixed_expected)
|
||||
for obj in objects:
|
||||
self.assertIsInstance(obj, Hashable)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_not_hashable(self):
|
||||
for obj in self.error_expected:
|
||||
self.assertNotIsInstance(obj, Hashable)
|
||||
|
||||
|
||||
# Issue #4701: Check that some builtin types are correctly hashable
|
||||
class DefaultIterSeq(object):
|
||||
seq = range(10)
|
||||
def __len__(self):
|
||||
return len(self.seq)
|
||||
def __getitem__(self, index):
|
||||
return self.seq[index]
|
||||
|
||||
class HashBuiltinsTestCase(unittest.TestCase):
|
||||
hashes_to_check = [enumerate(range(10)),
|
||||
iter(DefaultIterSeq()),
|
||||
iter(lambda: 0, 0),
|
||||
]
|
||||
|
||||
def test_hashes(self):
|
||||
_default_hash = object.__hash__
|
||||
for obj in self.hashes_to_check:
|
||||
self.assertEqual(hash(obj), _default_hash(obj))
|
||||
|
||||
class HashRandomizationTests:
|
||||
|
||||
# Each subclass should define a field "repr_", containing the repr() of
|
||||
# an object to be tested
|
||||
|
||||
def get_hash_command(self, repr_):
|
||||
return 'print(hash(eval(%a)))' % repr_
|
||||
|
||||
def get_hash(self, repr_, seed=None):
|
||||
env = os.environ.copy()
|
||||
env['__cleanenv'] = True # signal to assert_python not to do a copy
|
||||
# of os.environ on its own
|
||||
if seed is not None:
|
||||
env['PYTHONHASHSEED'] = str(seed)
|
||||
else:
|
||||
env.pop('PYTHONHASHSEED', None)
|
||||
out = assert_python_ok(
|
||||
'-c', self.get_hash_command(repr_),
|
||||
**env)
|
||||
stdout = out[1].strip()
|
||||
return int(stdout)
|
||||
|
||||
def test_randomized_hash(self):
|
||||
# two runs should return different hashes
|
||||
run1 = self.get_hash(self.repr_, seed='random')
|
||||
run2 = self.get_hash(self.repr_, seed='random')
|
||||
self.assertNotEqual(run1, run2)
|
||||
|
||||
class StringlikeHashRandomizationTests(HashRandomizationTests):
|
||||
repr_ = None
|
||||
repr_long = None
|
||||
|
||||
# 32bit little, 64bit little, 32bit big, 64bit big
|
||||
known_hashes = {
|
||||
'djba33x': [ # only used for small strings
|
||||
# seed 0, 'abc'
|
||||
[193485960, 193485960, 193485960, 193485960],
|
||||
# seed 42, 'abc'
|
||||
[-678966196, 573763426263223372, -820489388, -4282905804826039665],
|
||||
],
|
||||
'siphash24': [
|
||||
# NOTE: PyUCS2 layout depends on endianness
|
||||
# seed 0, 'abc'
|
||||
[1198583518, 4596069200710135518, 1198583518, 4596069200710135518],
|
||||
# seed 42, 'abc'
|
||||
[273876886, -4501618152524544106, 273876886, -4501618152524544106],
|
||||
# seed 42, 'abcdefghijk'
|
||||
[-1745215313, 4436719588892876975, -1745215313, 4436719588892876975],
|
||||
# seed 0, 'äú∑ℇ'
|
||||
[493570806, 5749986484189612790, -1006381564, -5915111450199468540],
|
||||
# seed 42, 'äú∑ℇ'
|
||||
[-1677110816, -2947981342227738144, -1860207793, -4296699217652516017],
|
||||
],
|
||||
'fnv': [
|
||||
# seed 0, 'abc'
|
||||
[-1600925533, 1453079729188098211, -1600925533,
|
||||
1453079729188098211],
|
||||
# seed 42, 'abc'
|
||||
[-206076799, -4410911502303878509, -1024014457,
|
||||
-3570150969479994130],
|
||||
# seed 42, 'abcdefghijk'
|
||||
[811136751, -5046230049376118746, -77208053 ,
|
||||
-4779029615281019666],
|
||||
# seed 0, 'äú∑ℇ'
|
||||
[44402817, 8998297579845987431, -1956240331,
|
||||
-782697888614047887],
|
||||
# seed 42, 'äú∑ℇ'
|
||||
[-283066365, -4576729883824601543, -271871407,
|
||||
-3927695501187247084],
|
||||
]
|
||||
}
|
||||
|
||||
def get_expected_hash(self, position, length):
|
||||
if length < sys.hash_info.cutoff:
|
||||
algorithm = "djba33x"
|
||||
else:
|
||||
algorithm = sys.hash_info.algorithm
|
||||
if sys.byteorder == 'little':
|
||||
platform = 1 if IS_64BIT else 0
|
||||
else:
|
||||
assert(sys.byteorder == 'big')
|
||||
platform = 3 if IS_64BIT else 2
|
||||
return self.known_hashes[algorithm][position][platform]
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_null_hash(self):
|
||||
# PYTHONHASHSEED=0 disables the randomized hash
|
||||
known_hash_of_obj = self.get_expected_hash(0, 3)
|
||||
|
||||
# Randomization is enabled by default:
|
||||
self.assertNotEqual(self.get_hash(self.repr_), known_hash_of_obj)
|
||||
|
||||
# It can also be disabled by setting the seed to 0:
|
||||
self.assertEqual(self.get_hash(self.repr_, seed=0), known_hash_of_obj)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@skip_unless_internalhash
|
||||
def test_fixed_hash(self):
|
||||
# test a fixed seed for the randomized hash
|
||||
# Note that all types share the same values:
|
||||
h = self.get_expected_hash(1, 3)
|
||||
self.assertEqual(self.get_hash(self.repr_, seed=42), h)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@skip_unless_internalhash
|
||||
def test_long_fixed_hash(self):
|
||||
if self.repr_long is None:
|
||||
return
|
||||
h = self.get_expected_hash(2, 11)
|
||||
self.assertEqual(self.get_hash(self.repr_long, seed=42), h)
|
||||
|
||||
|
||||
class StrHashRandomizationTests(StringlikeHashRandomizationTests,
|
||||
unittest.TestCase):
|
||||
repr_ = repr('abc')
|
||||
repr_long = repr('abcdefghijk')
|
||||
repr_ucs2 = repr('äú∑ℇ')
|
||||
|
||||
@skip_unless_internalhash
|
||||
def test_empty_string(self):
|
||||
self.assertEqual(hash(""), 0)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@skip_unless_internalhash
|
||||
def test_ucs2_string(self):
|
||||
h = self.get_expected_hash(3, 6)
|
||||
self.assertEqual(self.get_hash(self.repr_ucs2, seed=0), h)
|
||||
h = self.get_expected_hash(4, 6)
|
||||
self.assertEqual(self.get_hash(self.repr_ucs2, seed=42), h)
|
||||
|
||||
class BytesHashRandomizationTests(StringlikeHashRandomizationTests,
|
||||
unittest.TestCase):
|
||||
repr_ = repr(b'abc')
|
||||
repr_long = repr(b'abcdefghijk')
|
||||
|
||||
@skip_unless_internalhash
|
||||
def test_empty_string(self):
|
||||
self.assertEqual(hash(b""), 0)
|
||||
|
||||
class MemoryviewHashRandomizationTests(StringlikeHashRandomizationTests,
|
||||
unittest.TestCase):
|
||||
repr_ = "memoryview(b'abc')"
|
||||
repr_long = "memoryview(b'abcdefghijk')"
|
||||
|
||||
@skip_unless_internalhash
|
||||
def test_empty_string(self):
|
||||
self.assertEqual(hash(memoryview(b"")), 0)
|
||||
|
||||
class DatetimeTests(HashRandomizationTests):
|
||||
def get_hash_command(self, repr_):
|
||||
return 'import datetime; print(hash(%s))' % repr_
|
||||
|
||||
class DatetimeDateTests(DatetimeTests, unittest.TestCase):
|
||||
repr_ = repr(datetime.date(1066, 10, 14))
|
||||
|
||||
class DatetimeDatetimeTests(DatetimeTests, unittest.TestCase):
|
||||
repr_ = repr(datetime.datetime(1, 2, 3, 4, 5, 6, 7))
|
||||
|
||||
class DatetimeTimeTests(DatetimeTests, unittest.TestCase):
|
||||
repr_ = repr(datetime.time(0))
|
||||
|
||||
|
||||
class HashDistributionTestCase(unittest.TestCase):
|
||||
|
||||
def test_hash_distribution(self):
|
||||
# check for hash collision
|
||||
base = "abcdefghabcdefg"
|
||||
for i in range(1, len(base)):
|
||||
prefix = base[:i]
|
||||
with self.subTest(prefix=prefix):
|
||||
s15 = set()
|
||||
s255 = set()
|
||||
for c in range(256):
|
||||
h = hash(prefix + chr(c))
|
||||
s15.add(h & 0xf)
|
||||
s255.add(h & 0xff)
|
||||
# SipHash24 distribution depends on key, usually > 60%
|
||||
self.assertGreater(len(s15), 8, prefix)
|
||||
self.assertGreater(len(s255), 128, prefix)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
319
Lib/test/test_hashlib.py
vendored
319
Lib/test/test_hashlib.py
vendored
@@ -21,6 +21,7 @@ from test import support
|
||||
from test.support import _4G, bigmemtest
|
||||
from test.support.import_helper import import_fresh_module
|
||||
from test.support import threading_helper
|
||||
from test.support import warnings_helper
|
||||
from http.client import HTTPException
|
||||
|
||||
# Were we compiled --with-pydebug or with #define Py_DEBUG?
|
||||
@@ -47,12 +48,15 @@ else:
|
||||
builtin_hashlib = None
|
||||
|
||||
try:
|
||||
from _hashlib import HASH, HASHXOF, openssl_md_meth_names
|
||||
from _hashlib import HASH, HASHXOF, openssl_md_meth_names, get_fips_mode
|
||||
except ImportError:
|
||||
HASH = None
|
||||
HASHXOF = None
|
||||
openssl_md_meth_names = frozenset()
|
||||
|
||||
def get_fips_mode():
|
||||
return 0
|
||||
|
||||
try:
|
||||
import _blake2
|
||||
except ImportError:
|
||||
@@ -60,12 +64,9 @@ except ImportError:
|
||||
|
||||
requires_blake2 = unittest.skipUnless(_blake2, 'requires _blake2')
|
||||
|
||||
try:
|
||||
import _sha3
|
||||
except ImportError:
|
||||
_sha3 = None
|
||||
|
||||
requires_sha3 = unittest.skipUnless(_sha3, 'requires _sha3')
|
||||
# bpo-46913: Don't test the _sha3 extension on a Python UBSAN build
|
||||
SKIP_SHA3 = support.check_sanitizer(ub=True)
|
||||
requires_sha3 = unittest.skipUnless(not SKIP_SHA3, 'requires _sha3')
|
||||
|
||||
|
||||
def hexstr(s):
|
||||
@@ -79,11 +80,10 @@ def hexstr(s):
|
||||
|
||||
URL = "http://www.pythontest.net/hashlib/{}.txt"
|
||||
|
||||
|
||||
def read_vectors(hash_name):
|
||||
url = URL.format(hash_name)
|
||||
try:
|
||||
testdata = support.open_urlresource(url)
|
||||
testdata = support.open_urlresource(url, encoding="utf-8")
|
||||
except (OSError, HTTPException):
|
||||
raise unittest.SkipTest("Could not retrieve {}".format(url))
|
||||
with testdata:
|
||||
@@ -97,13 +97,13 @@ def read_vectors(hash_name):
|
||||
|
||||
|
||||
class HashLibTestCase(unittest.TestCase):
|
||||
supported_hash_names = ('md5', 'MD5', 'sha1', 'SHA1',
|
||||
'sha224', 'SHA224', 'sha256', 'SHA256',
|
||||
'sha384', 'SHA384', 'sha512', 'SHA512',
|
||||
'blake2b', 'blake2s',
|
||||
'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512',
|
||||
# TODO: RUSTPYTHON
|
||||
# 'shake_128', 'shake_256'
|
||||
supported_hash_names = ( 'md5', 'MD5', 'sha1', 'SHA1',
|
||||
'sha224', 'SHA224', 'sha256', 'SHA256',
|
||||
'sha384', 'SHA384', 'sha512', 'SHA512',
|
||||
'blake2b', 'blake2s',
|
||||
'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512',
|
||||
# TODO: RUSTPYTHON
|
||||
# 'shake_128', 'shake_256'
|
||||
)
|
||||
|
||||
shakes = {'shake_128', 'shake_256'}
|
||||
@@ -131,13 +131,14 @@ class HashLibTestCase(unittest.TestCase):
|
||||
|
||||
self.constructors_to_test = {}
|
||||
for algorithm in algorithms:
|
||||
if SKIP_SHA3 and algorithm.startswith('sha3_'):
|
||||
continue
|
||||
self.constructors_to_test[algorithm] = set()
|
||||
|
||||
# For each algorithm, test the direct constructor and the use
|
||||
# of hashlib.new given the algorithm name.
|
||||
for algorithm, constructors in self.constructors_to_test.items():
|
||||
constructors.add(getattr(hashlib, algorithm))
|
||||
|
||||
def _test_algorithm_via_hashlib_new(data=None, _alg=algorithm, **kwargs):
|
||||
if data is None:
|
||||
return hashlib.new(_alg, **kwargs)
|
||||
@@ -184,14 +185,15 @@ class HashLibTestCase(unittest.TestCase):
|
||||
add_builtin_constructor('blake2s')
|
||||
add_builtin_constructor('blake2b')
|
||||
|
||||
_sha3 = self._conditional_import_module('_sha3')
|
||||
if _sha3:
|
||||
add_builtin_constructor('sha3_224')
|
||||
add_builtin_constructor('sha3_256')
|
||||
add_builtin_constructor('sha3_384')
|
||||
add_builtin_constructor('sha3_512')
|
||||
add_builtin_constructor('shake_128')
|
||||
add_builtin_constructor('shake_256')
|
||||
if not SKIP_SHA3:
|
||||
_sha3 = self._conditional_import_module('_sha3')
|
||||
if _sha3:
|
||||
add_builtin_constructor('sha3_224')
|
||||
add_builtin_constructor('sha3_256')
|
||||
add_builtin_constructor('sha3_384')
|
||||
add_builtin_constructor('sha3_512')
|
||||
add_builtin_constructor('shake_128')
|
||||
add_builtin_constructor('shake_256')
|
||||
|
||||
super(HashLibTestCase, self).__init__(*args, **kwargs)
|
||||
|
||||
@@ -202,10 +204,7 @@ class HashLibTestCase(unittest.TestCase):
|
||||
|
||||
@property
|
||||
def is_fips_mode(self):
|
||||
if hasattr(self._hashlib, "get_fips_mode"):
|
||||
return self._hashlib.get_fips_mode()
|
||||
else:
|
||||
return None
|
||||
return get_fips_mode()
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@@ -222,14 +221,18 @@ class HashLibTestCase(unittest.TestCase):
|
||||
@unittest.expectedFailure
|
||||
def test_algorithms_guaranteed(self):
|
||||
self.assertEqual(hashlib.algorithms_guaranteed,
|
||||
set(_algo for _algo in self.supported_hash_names
|
||||
if _algo.islower()))
|
||||
set(_algo for _algo in self.supported_hash_names
|
||||
if _algo.islower()))
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_algorithms_available(self):
|
||||
self.assertTrue(set(hashlib.algorithms_guaranteed).
|
||||
issubset(hashlib.algorithms_available))
|
||||
issubset(hashlib.algorithms_available))
|
||||
# all available algorithms must be loadable, bpo-47101
|
||||
self.assertNotIn("undefined", hashlib.algorithms_available)
|
||||
for name in hashlib.algorithms_available:
|
||||
digest = hashlib.new(name, usedforsecurity=False)
|
||||
|
||||
def test_usedforsecurity_true(self):
|
||||
hashlib.new("sha256", usedforsecurity=True)
|
||||
@@ -337,7 +340,7 @@ class HashLibTestCase(unittest.TestCase):
|
||||
aas = b'a' * 128
|
||||
bees = b'b' * 127
|
||||
cees = b'c' * 126
|
||||
dees = b'd' * 2048 # HASHLIB_GIL_MINSIZE
|
||||
dees = b'd' * 2048 # HASHLIB_GIL_MINSIZE
|
||||
|
||||
for cons in self.hash_constructors:
|
||||
m1 = cons(usedforsecurity=False)
|
||||
@@ -375,11 +378,11 @@ class HashLibTestCase(unittest.TestCase):
|
||||
m = hash_object_constructor(data, **kwargs)
|
||||
computed = m.hexdigest() if not shake else m.hexdigest(length)
|
||||
self.assertEqual(
|
||||
computed, hexdigest,
|
||||
"Hash algorithm %s constructed using %s returned hexdigest"
|
||||
" %r for %d byte input data that should have hashed to %r."
|
||||
% (name, hash_object_constructor,
|
||||
computed, len(data), hexdigest))
|
||||
computed, hexdigest,
|
||||
"Hash algorithm %s constructed using %s returned hexdigest"
|
||||
" %r for %d byte input data that should have hashed to %r."
|
||||
% (name, hash_object_constructor,
|
||||
computed, len(data), hexdigest))
|
||||
computed = m.digest() if not shake else m.digest(length)
|
||||
digest = bytes.fromhex(hexdigest)
|
||||
self.assertEqual(computed, digest)
|
||||
@@ -405,6 +408,8 @@ class HashLibTestCase(unittest.TestCase):
|
||||
self.check_no_unicode('blake2b')
|
||||
self.check_no_unicode('blake2s')
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@requires_sha3
|
||||
def test_no_unicode_sha3(self):
|
||||
self.check_no_unicode('sha3_224')
|
||||
@@ -466,6 +471,8 @@ class HashLibTestCase(unittest.TestCase):
|
||||
self.assertEqual(m._rate_bits, rate)
|
||||
self.assertEqual(m._suffix, suffix)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@requires_sha3
|
||||
def test_extra_sha3(self):
|
||||
self.check_sha3('sha3_224', 448, 1152, b'\x06')
|
||||
@@ -531,87 +538,91 @@ class HashLibTestCase(unittest.TestCase):
|
||||
self.check('sha1', b"a" * 1000000,
|
||||
"34aa973cd4c4daa4f61eeb2bdbad27316534016f")
|
||||
|
||||
|
||||
# use the examples from Federal Information Processing Standards
|
||||
# Publication 180-2, Secure Hash Standard, 2002 August 1
|
||||
# http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
|
||||
|
||||
def test_case_sha224_0(self):
|
||||
self.check('sha224', b"",
|
||||
"d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f")
|
||||
"d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f")
|
||||
|
||||
def test_case_sha224_1(self):
|
||||
self.check('sha224', b"abc",
|
||||
"23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7")
|
||||
"23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7")
|
||||
|
||||
def test_case_sha224_2(self):
|
||||
self.check('sha224',
|
||||
b"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
||||
"75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525")
|
||||
b"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
||||
"75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525")
|
||||
|
||||
def test_case_sha224_3(self):
|
||||
self.check('sha224', b"a" * 1000000,
|
||||
"20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67")
|
||||
"20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67")
|
||||
|
||||
|
||||
def test_case_sha256_0(self):
|
||||
self.check('sha256', b"",
|
||||
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
|
||||
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
|
||||
|
||||
def test_case_sha256_1(self):
|
||||
self.check('sha256', b"abc",
|
||||
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad")
|
||||
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad")
|
||||
|
||||
def test_case_sha256_2(self):
|
||||
self.check('sha256',
|
||||
b"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
||||
"248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1")
|
||||
b"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
||||
"248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1")
|
||||
|
||||
def test_case_sha256_3(self):
|
||||
self.check('sha256', b"a" * 1000000,
|
||||
"cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0")
|
||||
"cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0")
|
||||
|
||||
|
||||
def test_case_sha384_0(self):
|
||||
self.check('sha384', b"",
|
||||
"38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da" +
|
||||
"274edebfe76f65fbd51ad2f14898b95b")
|
||||
"38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da"+
|
||||
"274edebfe76f65fbd51ad2f14898b95b")
|
||||
|
||||
def test_case_sha384_1(self):
|
||||
self.check('sha384', b"abc",
|
||||
"cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed" +
|
||||
"8086072ba1e7cc2358baeca134c825a7")
|
||||
"cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed"+
|
||||
"8086072ba1e7cc2358baeca134c825a7")
|
||||
|
||||
def test_case_sha384_2(self):
|
||||
self.check('sha384',
|
||||
b"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" +
|
||||
b"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"+
|
||||
b"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
|
||||
"09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712" +
|
||||
"fcc7c71a557e2db966c3e9fa91746039")
|
||||
"09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712"+
|
||||
"fcc7c71a557e2db966c3e9fa91746039")
|
||||
|
||||
def test_case_sha384_3(self):
|
||||
self.check('sha384', b"a" * 1000000,
|
||||
"9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b" +
|
||||
"07b8b3dc38ecc4ebae97ddd87f3d8985")
|
||||
"9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b"+
|
||||
"07b8b3dc38ecc4ebae97ddd87f3d8985")
|
||||
|
||||
|
||||
def test_case_sha512_0(self):
|
||||
self.check('sha512', b"",
|
||||
"cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce" +
|
||||
"47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e")
|
||||
"cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce"+
|
||||
"47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e")
|
||||
|
||||
def test_case_sha512_1(self):
|
||||
self.check('sha512', b"abc",
|
||||
"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a" +
|
||||
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f")
|
||||
"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"+
|
||||
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f")
|
||||
|
||||
def test_case_sha512_2(self):
|
||||
self.check('sha512',
|
||||
b"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" +
|
||||
b"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"+
|
||||
b"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
|
||||
"8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018" +
|
||||
"501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909")
|
||||
"8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"+
|
||||
"501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909")
|
||||
|
||||
def test_case_sha512_3(self):
|
||||
self.check('sha512', b"a" * 1000000,
|
||||
"e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb" +
|
||||
"de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b")
|
||||
"e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb"+
|
||||
"de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b")
|
||||
|
||||
def check_blake2(self, constructor, salt_size, person_size, key_size,
|
||||
digest_size, max_offset):
|
||||
@@ -664,9 +675,9 @@ class HashLibTestCase(unittest.TestCase):
|
||||
self.assertRaises(ValueError, constructor, inner_size=digest_size+1)
|
||||
|
||||
constructor(leaf_size=0)
|
||||
constructor(leaf_size=(1 << 32)-1)
|
||||
constructor(leaf_size=(1<<32)-1)
|
||||
self.assertRaises(ValueError, constructor, leaf_size=-1)
|
||||
self.assertRaises(OverflowError, constructor, leaf_size=1 << 32)
|
||||
self.assertRaises(OverflowError, constructor, leaf_size=1<<32)
|
||||
|
||||
constructor(node_offset=0)
|
||||
constructor(node_offset=max_offset)
|
||||
@@ -694,7 +705,7 @@ class HashLibTestCase(unittest.TestCase):
|
||||
|
||||
def blake2_rfc7693(self, constructor, md_len, in_len):
|
||||
def selftest_seq(length, seed):
|
||||
mask = (1 << 32)-1
|
||||
mask = (1<<32)-1
|
||||
a = (0xDEAD4BAD * seed) & mask
|
||||
b = 1
|
||||
out = bytearray(length)
|
||||
@@ -716,7 +727,7 @@ class HashLibTestCase(unittest.TestCase):
|
||||
|
||||
@requires_blake2
|
||||
def test_blake2b(self):
|
||||
self.check_blake2(hashlib.blake2b, 16, 16, 64, 64, (1 << 64)-1)
|
||||
self.check_blake2(hashlib.blake2b, 16, 16, 64, 64, (1<<64)-1)
|
||||
b2b_md_len = [20, 32, 48, 64]
|
||||
b2b_in_len = [0, 3, 128, 129, 255, 1024]
|
||||
self.assertEqual(
|
||||
@@ -726,32 +737,32 @@ class HashLibTestCase(unittest.TestCase):
|
||||
@requires_blake2
|
||||
def test_case_blake2b_0(self):
|
||||
self.check('blake2b', b"",
|
||||
"786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419" +
|
||||
"d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce")
|
||||
"786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419"+
|
||||
"d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce")
|
||||
|
||||
@requires_blake2
|
||||
def test_case_blake2b_1(self):
|
||||
self.check('blake2b', b"abc",
|
||||
"ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1" +
|
||||
"7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923")
|
||||
"ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d1"+
|
||||
"7d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923")
|
||||
|
||||
@requires_blake2
|
||||
def test_case_blake2b_all_parameters(self):
|
||||
# This checks that all the parameters work in general, and also that
|
||||
# parameter byte order doesn't get confused on big endian platforms.
|
||||
self.check('blake2b', b"foo",
|
||||
"920568b0c5873b2f0ab67bedb6cf1b2b",
|
||||
digest_size=16,
|
||||
key=b"bar",
|
||||
salt=b"baz",
|
||||
person=b"bing",
|
||||
fanout=2,
|
||||
depth=3,
|
||||
leaf_size=4,
|
||||
node_offset=5,
|
||||
node_depth=6,
|
||||
inner_size=7,
|
||||
last_node=True)
|
||||
"920568b0c5873b2f0ab67bedb6cf1b2b",
|
||||
digest_size=16,
|
||||
key=b"bar",
|
||||
salt=b"baz",
|
||||
person=b"bing",
|
||||
fanout=2,
|
||||
depth=3,
|
||||
leaf_size=4,
|
||||
node_offset=5,
|
||||
node_depth=6,
|
||||
inner_size=7,
|
||||
last_node=True)
|
||||
|
||||
@requires_blake2
|
||||
def test_blake2b_vectors(self):
|
||||
@@ -761,7 +772,7 @@ class HashLibTestCase(unittest.TestCase):
|
||||
|
||||
@requires_blake2
|
||||
def test_blake2s(self):
|
||||
self.check_blake2(hashlib.blake2s, 8, 8, 32, 32, (1 << 48)-1)
|
||||
self.check_blake2(hashlib.blake2s, 8, 8, 32, 32, (1<<48)-1)
|
||||
b2s_md_len = [16, 20, 28, 32]
|
||||
b2s_in_len = [0, 3, 64, 65, 255, 1024]
|
||||
self.assertEqual(
|
||||
@@ -771,30 +782,30 @@ class HashLibTestCase(unittest.TestCase):
|
||||
@requires_blake2
|
||||
def test_case_blake2s_0(self):
|
||||
self.check('blake2s', b"",
|
||||
"69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9")
|
||||
"69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9")
|
||||
|
||||
@requires_blake2
|
||||
def test_case_blake2s_1(self):
|
||||
self.check('blake2s', b"abc",
|
||||
"508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982")
|
||||
"508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982")
|
||||
|
||||
@requires_blake2
|
||||
def test_case_blake2s_all_parameters(self):
|
||||
# This checks that all the parameters work in general, and also that
|
||||
# parameter byte order doesn't get confused on big endian platforms.
|
||||
self.check('blake2s', b"foo",
|
||||
"bf2a8f7fe3c555012a6f8046e646bc75",
|
||||
digest_size=16,
|
||||
key=b"bar",
|
||||
salt=b"baz",
|
||||
person=b"bing",
|
||||
fanout=2,
|
||||
depth=3,
|
||||
leaf_size=4,
|
||||
node_offset=5,
|
||||
node_depth=6,
|
||||
inner_size=7,
|
||||
last_node=True)
|
||||
"bf2a8f7fe3c555012a6f8046e646bc75",
|
||||
digest_size=16,
|
||||
key=b"bar",
|
||||
salt=b"baz",
|
||||
person=b"bing",
|
||||
fanout=2,
|
||||
depth=3,
|
||||
leaf_size=4,
|
||||
node_offset=5,
|
||||
node_depth=6,
|
||||
inner_size=7,
|
||||
last_node=True)
|
||||
|
||||
@requires_blake2
|
||||
def test_blake2s_vectors(self):
|
||||
@@ -805,7 +816,7 @@ class HashLibTestCase(unittest.TestCase):
|
||||
@requires_sha3
|
||||
def test_case_sha3_224_0(self):
|
||||
self.check('sha3_224', b"",
|
||||
"6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7")
|
||||
"6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7")
|
||||
|
||||
@requires_sha3
|
||||
def test_case_sha3_224_vector(self):
|
||||
@@ -815,7 +826,7 @@ class HashLibTestCase(unittest.TestCase):
|
||||
@requires_sha3
|
||||
def test_case_sha3_256_0(self):
|
||||
self.check('sha3_256', b"",
|
||||
"a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a")
|
||||
"a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a")
|
||||
|
||||
@requires_sha3
|
||||
def test_case_sha3_256_vector(self):
|
||||
@@ -825,8 +836,8 @@ class HashLibTestCase(unittest.TestCase):
|
||||
@requires_sha3
|
||||
def test_case_sha3_384_0(self):
|
||||
self.check('sha3_384', b"",
|
||||
"0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2a" +
|
||||
"c3713831264adb47fb6bd1e058d5f004")
|
||||
"0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2a"+
|
||||
"c3713831264adb47fb6bd1e058d5f004")
|
||||
|
||||
@requires_sha3
|
||||
def test_case_sha3_384_vector(self):
|
||||
@@ -836,36 +847,38 @@ class HashLibTestCase(unittest.TestCase):
|
||||
@requires_sha3
|
||||
def test_case_sha3_512_0(self):
|
||||
self.check('sha3_512', b"",
|
||||
"a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a6" +
|
||||
"15b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26")
|
||||
"a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a6"+
|
||||
"15b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26")
|
||||
|
||||
@requires_sha3
|
||||
def test_case_sha3_512_vector(self):
|
||||
for msg, md in read_vectors('sha3_512'):
|
||||
self.check('sha3_512', msg, md)
|
||||
|
||||
@requires_sha3
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_case_shake_128_0(self):
|
||||
self.check('shake_128', b"",
|
||||
"7f9c2ba4e88f827d616045507605853ed73b8093f6efbc88eb1a6eacfa66ef26",
|
||||
True)
|
||||
"7f9c2ba4e88f827d616045507605853ed73b8093f6efbc88eb1a6eacfa66ef26",
|
||||
True)
|
||||
self.check('shake_128', b"", "7f9c", True)
|
||||
|
||||
@requires_sha3
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_case_shake128_vector(self):
|
||||
for msg, md in read_vectors('shake_128'):
|
||||
self.check('shake_128', msg, md, True)
|
||||
|
||||
@requires_sha3
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_case_shake_256_0(self):
|
||||
self.check('shake_256', b"",
|
||||
"46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762f",
|
||||
True)
|
||||
"46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762f",
|
||||
True)
|
||||
self.check('shake_256', b"", "46b9", True)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@requires_sha3
|
||||
def test_case_shake256_vector(self):
|
||||
for msg, md in read_vectors('shake_256'):
|
||||
self.check('shake_256', msg, md, True)
|
||||
@@ -940,17 +953,42 @@ class HashLibTestCase(unittest.TestCase):
|
||||
if fips_mode is not None:
|
||||
self.assertIsInstance(fips_mode, int)
|
||||
|
||||
@support.cpython_only
|
||||
def test_disallow_instantiation(self):
|
||||
for algorithm, constructors in self.constructors_to_test.items():
|
||||
if algorithm.startswith(("sha3_", "shake", "blake")):
|
||||
# _sha3 and _blake types can be instantiated
|
||||
continue
|
||||
# all other types have DISALLOW_INSTANTIATION
|
||||
for constructor in constructors:
|
||||
# In FIPS mode some algorithms are not available raising ValueError
|
||||
try:
|
||||
h = constructor()
|
||||
except ValueError:
|
||||
continue
|
||||
with self.subTest(constructor=constructor):
|
||||
support.check_disallow_instantiation(self, type(h))
|
||||
|
||||
@unittest.skipUnless(HASH is not None, 'need _hashlib')
|
||||
def test_internal_types(self):
|
||||
def test_hash_disallow_instantiation(self):
|
||||
# internal types like _hashlib.HASH are not constructable
|
||||
with self.assertRaisesRegex(
|
||||
TypeError, "cannot create 'HASH' instance"
|
||||
):
|
||||
HASH()
|
||||
with self.assertRaisesRegex(
|
||||
TypeError, "cannot create 'HASHXOF' instance"
|
||||
):
|
||||
HASHXOF()
|
||||
support.check_disallow_instantiation(self, HASH)
|
||||
support.check_disallow_instantiation(self, HASHXOF)
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
def test_readonly_types(self):
|
||||
for algorithm, constructors in self.constructors_to_test.items():
|
||||
# all other types have DISALLOW_INSTANTIATION
|
||||
for constructor in constructors:
|
||||
# In FIPS mode some algorithms are not available raising ValueError
|
||||
try:
|
||||
hash_type = type(constructor())
|
||||
except ValueError:
|
||||
continue
|
||||
with self.subTest(hash_type=hash_type):
|
||||
with self.assertRaisesRegex(TypeError, "immutable type"):
|
||||
hash_type.value = False
|
||||
|
||||
|
||||
class KDFTests(unittest.TestCase):
|
||||
@@ -967,13 +1005,10 @@ class KDFTests(unittest.TestCase):
|
||||
]
|
||||
|
||||
scrypt_test_vectors = [
|
||||
(b'', b'', 16, 1, 1, unhexlify(
|
||||
'77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906')),
|
||||
(b'password', b'NaCl', 1024, 8, 16, unhexlify(
|
||||
'fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640')),
|
||||
(b'pleaseletmein', b'SodiumChloride', 16384, 8, 1, unhexlify(
|
||||
'7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887')),
|
||||
]
|
||||
(b'', b'', 16, 1, 1, unhexlify('77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906')),
|
||||
(b'password', b'NaCl', 1024, 8, 16, unhexlify('fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640')),
|
||||
(b'pleaseletmein', b'SodiumChloride', 16384, 8, 1, unhexlify('7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887')),
|
||||
]
|
||||
|
||||
pbkdf2_results = {
|
||||
"sha1": [
|
||||
@@ -984,7 +1019,7 @@ class KDFTests(unittest.TestCase):
|
||||
#(bytes.fromhex('eefe3d61cd4da4e4e9945b3d6ba2158c2634e984'), None),
|
||||
(bytes.fromhex('3d2eec4fe41c849b80c8d83662c0e44a8b291a964c'
|
||||
'f2f07038'), 25),
|
||||
(bytes.fromhex('56fa6aa75548099dcc37d7f03425e0c3'), None), ],
|
||||
(bytes.fromhex('56fa6aa75548099dcc37d7f03425e0c3'), None),],
|
||||
"sha256": [
|
||||
(bytes.fromhex('120fb6cffcf8b32c43e7225256c4f837'
|
||||
'a86548c92ccc35480805987cb70be17b'), None),
|
||||
@@ -992,11 +1027,11 @@ class KDFTests(unittest.TestCase):
|
||||
'2a303f8ef3c251dfd6e2d85a95474c43'), None),
|
||||
(bytes.fromhex('c5e478d59288c841aa530db6845c4c8d'
|
||||
'962893a001ce4e11a4963873aa98134a'), None),
|
||||
# (bytes.fromhex('cf81c66fe8cfc04d1f31ecb65dab4089'
|
||||
#(bytes.fromhex('cf81c66fe8cfc04d1f31ecb65dab4089'
|
||||
# 'f7f179e89b3b0bcb17ad10e3ac6eba46'), None),
|
||||
(bytes.fromhex('348c89dbcbd32b2f32d814b8116e84cf2b17'
|
||||
'347ebc1800181c4e2a1fb8dd53e1c635518c7dac47e9'), 40),
|
||||
(bytes.fromhex('89b69d0516f829893c696226650a8687'), None), ],
|
||||
(bytes.fromhex('89b69d0516f829893c696226650a8687'), None),],
|
||||
"sha512": [
|
||||
(bytes.fromhex('867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5'
|
||||
'd513554e1c8cf252c02d470a285a0501bad999bfe943c08f'
|
||||
@@ -1010,7 +1045,7 @@ class KDFTests(unittest.TestCase):
|
||||
(bytes.fromhex('8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b8'
|
||||
'68c005174dc4ee71115b59f9e60cd9532fa33e0f75aefe30'
|
||||
'225c583a186cd82bd4daea9724a3d3b8'), 64),
|
||||
(bytes.fromhex('9d9e9c4cd21fe4be24d5b8244c759665'), None), ],
|
||||
(bytes.fromhex('9d9e9c4cd21fe4be24d5b8244c759665'), None),],
|
||||
}
|
||||
|
||||
def _test_pbkdf2_hmac(self, pbkdf2, supported):
|
||||
@@ -1036,7 +1071,7 @@ class KDFTests(unittest.TestCase):
|
||||
self.assertEqual(out, expected,
|
||||
(digest_name, password, salt, rounds))
|
||||
|
||||
with self.assertRaisesRegex(ValueError, 'unsupported hash type'):
|
||||
with self.assertRaisesRegex(ValueError, '.*unsupported.*'):
|
||||
pbkdf2('unknown', b'pass', b'salt', 1)
|
||||
|
||||
if 'sha1' in supported:
|
||||
@@ -1059,22 +1094,26 @@ class KDFTests(unittest.TestCase):
|
||||
ValueError, pbkdf2, 'sha1', b'pass', b'salt', 1, -1
|
||||
)
|
||||
out = pbkdf2(hash_name='sha1', password=b'password', salt=b'salt',
|
||||
iterations=1, dklen=None)
|
||||
iterations=1, dklen=None)
|
||||
self.assertEqual(out, self.pbkdf2_results['sha1'][0][0])
|
||||
|
||||
# TODO: RUSTPYTHON
|
||||
@unittest.expectedFailure
|
||||
@unittest.skipIf(builtin_hashlib is None, "test requires builtin_hashlib")
|
||||
def test_pbkdf2_hmac_py(self):
|
||||
self._test_pbkdf2_hmac(builtin_hashlib.pbkdf2_hmac, builtin_hashes)
|
||||
with warnings_helper.check_warnings():
|
||||
self._test_pbkdf2_hmac(
|
||||
builtin_hashlib.pbkdf2_hmac, builtin_hashes
|
||||
)
|
||||
|
||||
@unittest.skipUnless(hasattr(openssl_hashlib, 'pbkdf2_hmac'),
|
||||
' test requires OpenSSL > 1.0')
|
||||
' test requires OpenSSL > 1.0')
|
||||
def test_pbkdf2_hmac_c(self):
|
||||
self._test_pbkdf2_hmac(openssl_hashlib.pbkdf2_hmac, openssl_md_meth_names)
|
||||
|
||||
@unittest.skipUnless(hasattr(hashlib, 'scrypt'),
|
||||
' test requires OpenSSL > 1.1')
|
||||
' test requires OpenSSL > 1.1')
|
||||
@unittest.skipIf(get_fips_mode(), reason="scrypt is blocked in FIPS mode")
|
||||
def test_scrypt(self):
|
||||
for password, salt, n, r, p, expected in self.scrypt_test_vectors:
|
||||
result = hashlib.scrypt(password, salt=salt, n=n, r=r, p=p)
|
||||
|
||||
35
Lib/test/test_heapq.py
vendored
35
Lib/test/test_heapq.py
vendored
@@ -146,11 +146,11 @@ class TestHeap:
|
||||
self.assertEqual(type(h[0]), int)
|
||||
self.assertEqual(type(x), float)
|
||||
|
||||
h = [10];
|
||||
h = [10]
|
||||
x = self.module.heappushpop(h, 9)
|
||||
self.assertEqual((h, x), ([10], 9))
|
||||
|
||||
h = [10];
|
||||
h = [10]
|
||||
x = self.module.heappushpop(h, 11)
|
||||
self.assertEqual((h, x), ([11], 10))
|
||||
|
||||
@@ -433,6 +433,37 @@ class TestErrorHandling:
|
||||
with self.assertRaises((IndexError, RuntimeError)):
|
||||
self.module.heappop(heap)
|
||||
|
||||
def test_comparison_operator_modifiying_heap(self):
|
||||
# See bpo-39421: Strong references need to be taken
|
||||
# when comparing objects as they can alter the heap
|
||||
class EvilClass(int):
|
||||
def __lt__(self, o):
|
||||
heap.clear()
|
||||
return NotImplemented
|
||||
|
||||
heap = []
|
||||
self.module.heappush(heap, EvilClass(0))
|
||||
self.assertRaises(IndexError, self.module.heappushpop, heap, 1)
|
||||
|
||||
def test_comparison_operator_modifiying_heap_two_heaps(self):
|
||||
|
||||
class h(int):
|
||||
def __lt__(self, o):
|
||||
list2.clear()
|
||||
return NotImplemented
|
||||
|
||||
class g(int):
|
||||
def __lt__(self, o):
|
||||
list1.clear()
|
||||
return NotImplemented
|
||||
|
||||
list1, list2 = [], []
|
||||
|
||||
self.module.heappush(list1, h(0))
|
||||
self.module.heappush(list2, g(0))
|
||||
|
||||
self.assertRaises((IndexError, RuntimeError), self.module.heappush, list1, g(1))
|
||||
self.assertRaises((IndexError, RuntimeError), self.module.heappush, list2, h(1))
|
||||
|
||||
class TestErrorHandlingPython(TestErrorHandling, TestCase):
|
||||
module = py_heapq
|
||||
|
||||
659
Lib/test/test_isinstance.py
vendored
659
Lib/test/test_isinstance.py
vendored
@@ -1,295 +1,364 @@
|
||||
# Tests some corner cases with isinstance() and issubclass(). While these
|
||||
# tests use new style classes and properties, they actually do whitebox
|
||||
# testing of error conditions uncovered when using extension types.
|
||||
|
||||
import unittest
|
||||
import sys
|
||||
|
||||
|
||||
|
||||
class TestIsInstanceExceptions(unittest.TestCase):
|
||||
# Test to make sure that an AttributeError when accessing the instance's
|
||||
# class's bases is masked. This was actually a bug in Python 2.2 and
|
||||
# 2.2.1 where the exception wasn't caught but it also wasn't being cleared
|
||||
# (leading to an "undetected error" in the debug build). Set up is,
|
||||
# isinstance(inst, cls) where:
|
||||
#
|
||||
# - cls isn't a type, or a tuple
|
||||
# - cls has a __bases__ attribute
|
||||
# - inst has a __class__ attribute
|
||||
# - inst.__class__ as no __bases__ attribute
|
||||
#
|
||||
# Sounds complicated, I know, but this mimics a situation where an
|
||||
# extension type raises an AttributeError when its __bases__ attribute is
|
||||
# gotten. In that case, isinstance() should return False.
|
||||
def test_class_has_no_bases(self):
|
||||
class I(object):
|
||||
def getclass(self):
|
||||
# This must return an object that has no __bases__ attribute
|
||||
return None
|
||||
__class__ = property(getclass)
|
||||
|
||||
class C(object):
|
||||
def getbases(self):
|
||||
return ()
|
||||
__bases__ = property(getbases)
|
||||
|
||||
self.assertEqual(False, isinstance(I(), C()))
|
||||
|
||||
# Like above except that inst.__class__.__bases__ raises an exception
|
||||
# other than AttributeError
|
||||
def test_bases_raises_other_than_attribute_error(self):
|
||||
class E(object):
|
||||
def getbases(self):
|
||||
raise RuntimeError
|
||||
__bases__ = property(getbases)
|
||||
|
||||
class I(object):
|
||||
def getclass(self):
|
||||
return E()
|
||||
__class__ = property(getclass)
|
||||
|
||||
class C(object):
|
||||
def getbases(self):
|
||||
return ()
|
||||
__bases__ = property(getbases)
|
||||
|
||||
self.assertRaises(RuntimeError, isinstance, I(), C())
|
||||
|
||||
# Here's a situation where getattr(cls, '__bases__') raises an exception.
|
||||
# If that exception is not AttributeError, it should not get masked
|
||||
def test_dont_mask_non_attribute_error(self):
|
||||
class I: pass
|
||||
|
||||
class C(object):
|
||||
def getbases(self):
|
||||
raise RuntimeError
|
||||
__bases__ = property(getbases)
|
||||
|
||||
self.assertRaises(RuntimeError, isinstance, I(), C())
|
||||
|
||||
# Like above, except that getattr(cls, '__bases__') raises an
|
||||
# AttributeError, which /should/ get masked as a TypeError
|
||||
def test_mask_attribute_error(self):
|
||||
class I: pass
|
||||
|
||||
class C(object):
|
||||
def getbases(self):
|
||||
raise AttributeError
|
||||
__bases__ = property(getbases)
|
||||
|
||||
self.assertRaises(TypeError, isinstance, I(), C())
|
||||
|
||||
# check that we don't mask non AttributeErrors
|
||||
# see: http://bugs.python.org/issue1574217
|
||||
def test_isinstance_dont_mask_non_attribute_error(self):
|
||||
class C(object):
|
||||
def getclass(self):
|
||||
raise RuntimeError
|
||||
__class__ = property(getclass)
|
||||
|
||||
c = C()
|
||||
self.assertRaises(RuntimeError, isinstance, c, bool)
|
||||
|
||||
# test another code path
|
||||
class D: pass
|
||||
self.assertRaises(RuntimeError, isinstance, c, D)
|
||||
|
||||
|
||||
# These tests are similar to above, but tickle certain code paths in
|
||||
# issubclass() instead of isinstance() -- really PyObject_IsSubclass()
|
||||
# vs. PyObject_IsInstance().
|
||||
class TestIsSubclassExceptions(unittest.TestCase):
|
||||
def test_dont_mask_non_attribute_error(self):
|
||||
class C(object):
|
||||
def getbases(self):
|
||||
raise RuntimeError
|
||||
__bases__ = property(getbases)
|
||||
|
||||
class S(C): pass
|
||||
|
||||
self.assertRaises(RuntimeError, issubclass, C(), S())
|
||||
|
||||
def test_mask_attribute_error(self):
|
||||
class C(object):
|
||||
def getbases(self):
|
||||
raise AttributeError
|
||||
__bases__ = property(getbases)
|
||||
|
||||
class S(C): pass
|
||||
|
||||
self.assertRaises(TypeError, issubclass, C(), S())
|
||||
|
||||
# Like above, but test the second branch, where the __bases__ of the
|
||||
# second arg (the cls arg) is tested. This means the first arg must
|
||||
# return a valid __bases__, and it's okay for it to be a normal --
|
||||
# unrelated by inheritance -- class.
|
||||
def test_dont_mask_non_attribute_error_in_cls_arg(self):
|
||||
class B: pass
|
||||
|
||||
class C(object):
|
||||
def getbases(self):
|
||||
raise RuntimeError
|
||||
__bases__ = property(getbases)
|
||||
|
||||
self.assertRaises(RuntimeError, issubclass, B, C())
|
||||
|
||||
def test_mask_attribute_error_in_cls_arg(self):
|
||||
class B: pass
|
||||
|
||||
class C(object):
|
||||
def getbases(self):
|
||||
raise AttributeError
|
||||
__bases__ = property(getbases)
|
||||
|
||||
self.assertRaises(TypeError, issubclass, B, C())
|
||||
|
||||
|
||||
|
||||
# meta classes for creating abstract classes and instances
|
||||
class AbstractClass(object):
|
||||
def __init__(self, bases):
|
||||
self.bases = bases
|
||||
|
||||
def getbases(self):
|
||||
return self.bases
|
||||
__bases__ = property(getbases)
|
||||
|
||||
def __call__(self):
|
||||
return AbstractInstance(self)
|
||||
|
||||
class AbstractInstance(object):
|
||||
def __init__(self, klass):
|
||||
self.klass = klass
|
||||
|
||||
def getclass(self):
|
||||
return self.klass
|
||||
__class__ = property(getclass)
|
||||
|
||||
# abstract classes
|
||||
AbstractSuper = AbstractClass(bases=())
|
||||
|
||||
AbstractChild = AbstractClass(bases=(AbstractSuper,))
|
||||
|
||||
# normal classes
|
||||
class Super:
|
||||
pass
|
||||
|
||||
class Child(Super):
|
||||
pass
|
||||
|
||||
class TestIsInstanceIsSubclass(unittest.TestCase):
|
||||
# Tests to ensure that isinstance and issubclass work on abstract
|
||||
# classes and instances. Before the 2.2 release, TypeErrors were
|
||||
# raised when boolean values should have been returned. The bug was
|
||||
# triggered by mixing 'normal' classes and instances were with
|
||||
# 'abstract' classes and instances. This case tries to test all
|
||||
# combinations.
|
||||
|
||||
def test_isinstance_normal(self):
|
||||
# normal instances
|
||||
self.assertEqual(True, isinstance(Super(), Super))
|
||||
self.assertEqual(False, isinstance(Super(), Child))
|
||||
self.assertEqual(False, isinstance(Super(), AbstractSuper))
|
||||
self.assertEqual(False, isinstance(Super(), AbstractChild))
|
||||
|
||||
self.assertEqual(True, isinstance(Child(), Super))
|
||||
self.assertEqual(False, isinstance(Child(), AbstractSuper))
|
||||
|
||||
def test_isinstance_abstract(self):
|
||||
# abstract instances
|
||||
self.assertEqual(True, isinstance(AbstractSuper(), AbstractSuper))
|
||||
self.assertEqual(False, isinstance(AbstractSuper(), AbstractChild))
|
||||
self.assertEqual(False, isinstance(AbstractSuper(), Super))
|
||||
self.assertEqual(False, isinstance(AbstractSuper(), Child))
|
||||
|
||||
self.assertEqual(True, isinstance(AbstractChild(), AbstractChild))
|
||||
self.assertEqual(True, isinstance(AbstractChild(), AbstractSuper))
|
||||
self.assertEqual(False, isinstance(AbstractChild(), Super))
|
||||
self.assertEqual(False, isinstance(AbstractChild(), Child))
|
||||
|
||||
def test_subclass_normal(self):
|
||||
# normal classes
|
||||
self.assertEqual(True, issubclass(Super, Super))
|
||||
self.assertEqual(False, issubclass(Super, AbstractSuper))
|
||||
self.assertEqual(False, issubclass(Super, Child))
|
||||
|
||||
self.assertEqual(True, issubclass(Child, Child))
|
||||
self.assertEqual(True, issubclass(Child, Super))
|
||||
self.assertEqual(False, issubclass(Child, AbstractSuper))
|
||||
|
||||
def test_subclass_abstract(self):
|
||||
# abstract classes
|
||||
self.assertEqual(True, issubclass(AbstractSuper, AbstractSuper))
|
||||
self.assertEqual(False, issubclass(AbstractSuper, AbstractChild))
|
||||
self.assertEqual(False, issubclass(AbstractSuper, Child))
|
||||
|
||||
self.assertEqual(True, issubclass(AbstractChild, AbstractChild))
|
||||
self.assertEqual(True, issubclass(AbstractChild, AbstractSuper))
|
||||
self.assertEqual(False, issubclass(AbstractChild, Super))
|
||||
self.assertEqual(False, issubclass(AbstractChild, Child))
|
||||
|
||||
def test_subclass_tuple(self):
|
||||
# test with a tuple as the second argument classes
|
||||
self.assertEqual(True, issubclass(Child, (Child,)))
|
||||
self.assertEqual(True, issubclass(Child, (Super,)))
|
||||
self.assertEqual(False, issubclass(Super, (Child,)))
|
||||
self.assertEqual(True, issubclass(Super, (Child, Super)))
|
||||
self.assertEqual(False, issubclass(Child, ()))
|
||||
self.assertEqual(True, issubclass(Super, (Child, (Super,))))
|
||||
|
||||
self.assertEqual(True, issubclass(int, (int, (float, int))))
|
||||
self.assertEqual(True, issubclass(str, (str, (Child, str))))
|
||||
|
||||
def test_subclass_recursion_limit(self):
|
||||
# make sure that issubclass raises RecursionError before the C stack is
|
||||
# blown
|
||||
self.assertRaises(RecursionError, blowstack, issubclass, str, str)
|
||||
|
||||
def test_isinstance_recursion_limit(self):
|
||||
# make sure that issubclass raises RecursionError before the C stack is
|
||||
# blown
|
||||
self.assertRaises(RecursionError, blowstack, isinstance, '', str)
|
||||
|
||||
def test_issubclass_refcount_handling(self):
|
||||
# bpo-39382: abstract_issubclass() didn't hold item reference while
|
||||
# peeking in the bases tuple, in the single inheritance case.
|
||||
class A:
|
||||
@property
|
||||
def __bases__(self):
|
||||
return (int, )
|
||||
|
||||
class B:
|
||||
def __init__(self):
|
||||
# setting this here increases the chances of exhibiting the bug,
|
||||
# probably due to memory layout changes.
|
||||
self.x = 1
|
||||
|
||||
@property
|
||||
def __bases__(self):
|
||||
return (A(), )
|
||||
|
||||
self.assertEqual(True, issubclass(B(), int))
|
||||
|
||||
def test_infinite_recursion_in_bases(self):
|
||||
class X:
|
||||
@property
|
||||
def __bases__(self):
|
||||
return self.__bases__
|
||||
|
||||
self.assertRaises(RecursionError, issubclass, X(), int)
|
||||
self.assertRaises(RecursionError, issubclass, int, X())
|
||||
self.assertRaises(RecursionError, isinstance, 1, X())
|
||||
|
||||
|
||||
def blowstack(fxn, arg, compare_to):
|
||||
# Make sure that calling isinstance with a deeply nested tuple for its
|
||||
# argument will raise RecursionError eventually.
|
||||
tuple_arg = (compare_to,)
|
||||
for cnt in range(sys.getrecursionlimit()+5):
|
||||
tuple_arg = (tuple_arg,)
|
||||
fxn(arg, tuple_arg)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
# Tests some corner cases with isinstance() and issubclass(). While these
|
||||
# tests use new style classes and properties, they actually do whitebox
|
||||
# testing of error conditions uncovered when using extension types.
|
||||
|
||||
import unittest
|
||||
import sys
|
||||
import typing
|
||||
from test import support
|
||||
|
||||
|
||||
|
||||
class TestIsInstanceExceptions(unittest.TestCase):
|
||||
# Test to make sure that an AttributeError when accessing the instance's
|
||||
# class's bases is masked. This was actually a bug in Python 2.2 and
|
||||
# 2.2.1 where the exception wasn't caught but it also wasn't being cleared
|
||||
# (leading to an "undetected error" in the debug build). Set up is,
|
||||
# isinstance(inst, cls) where:
|
||||
#
|
||||
# - cls isn't a type, or a tuple
|
||||
# - cls has a __bases__ attribute
|
||||
# - inst has a __class__ attribute
|
||||
# - inst.__class__ as no __bases__ attribute
|
||||
#
|
||||
# Sounds complicated, I know, but this mimics a situation where an
|
||||
# extension type raises an AttributeError when its __bases__ attribute is
|
||||
# gotten. In that case, isinstance() should return False.
|
||||
def test_class_has_no_bases(self):
|
||||
class I(object):
|
||||
def getclass(self):
|
||||
# This must return an object that has no __bases__ attribute
|
||||
return None
|
||||
__class__ = property(getclass)
|
||||
|
||||
class C(object):
|
||||
def getbases(self):
|
||||
return ()
|
||||
__bases__ = property(getbases)
|
||||
|
||||
self.assertEqual(False, isinstance(I(), C()))
|
||||
|
||||
# Like above except that inst.__class__.__bases__ raises an exception
|
||||
# other than AttributeError
|
||||
def test_bases_raises_other_than_attribute_error(self):
|
||||
class E(object):
|
||||
def getbases(self):
|
||||
raise RuntimeError
|
||||
__bases__ = property(getbases)
|
||||
|
||||
class I(object):
|
||||
def getclass(self):
|
||||
return E()
|
||||
__class__ = property(getclass)
|
||||
|
||||
class C(object):
|
||||
def getbases(self):
|
||||
return ()
|
||||
__bases__ = property(getbases)
|
||||
|
||||
self.assertRaises(RuntimeError, isinstance, I(), C())
|
||||
|
||||
# Here's a situation where getattr(cls, '__bases__') raises an exception.
|
||||
# If that exception is not AttributeError, it should not get masked
|
||||
def test_dont_mask_non_attribute_error(self):
|
||||
class I: pass
|
||||
|
||||
class C(object):
|
||||
def getbases(self):
|
||||
raise RuntimeError
|
||||
__bases__ = property(getbases)
|
||||
|
||||
self.assertRaises(RuntimeError, isinstance, I(), C())
|
||||
|
||||
# Like above, except that getattr(cls, '__bases__') raises an
|
||||
# AttributeError, which /should/ get masked as a TypeError
|
||||
def test_mask_attribute_error(self):
|
||||
class I: pass
|
||||
|
||||
class C(object):
|
||||
def getbases(self):
|
||||
raise AttributeError
|
||||
__bases__ = property(getbases)
|
||||
|
||||
self.assertRaises(TypeError, isinstance, I(), C())
|
||||
|
||||
# check that we don't mask non AttributeErrors
|
||||
# see: http://bugs.python.org/issue1574217
|
||||
def test_isinstance_dont_mask_non_attribute_error(self):
|
||||
class C(object):
|
||||
def getclass(self):
|
||||
raise RuntimeError
|
||||
__class__ = property(getclass)
|
||||
|
||||
c = C()
|
||||
self.assertRaises(RuntimeError, isinstance, c, bool)
|
||||
|
||||
# test another code path
|
||||
class D: pass
|
||||
self.assertRaises(RuntimeError, isinstance, c, D)
|
||||
|
||||
|
||||
# These tests are similar to above, but tickle certain code paths in
|
||||
# issubclass() instead of isinstance() -- really PyObject_IsSubclass()
|
||||
# vs. PyObject_IsInstance().
|
||||
class TestIsSubclassExceptions(unittest.TestCase):
|
||||
def test_dont_mask_non_attribute_error(self):
|
||||
class C(object):
|
||||
def getbases(self):
|
||||
raise RuntimeError
|
||||
__bases__ = property(getbases)
|
||||
|
||||
class S(C): pass
|
||||
|
||||
self.assertRaises(RuntimeError, issubclass, C(), S())
|
||||
|
||||
def test_mask_attribute_error(self):
|
||||
class C(object):
|
||||
def getbases(self):
|
||||
raise AttributeError
|
||||
__bases__ = property(getbases)
|
||||
|
||||
class S(C): pass
|
||||
|
||||
self.assertRaises(TypeError, issubclass, C(), S())
|
||||
|
||||
# Like above, but test the second branch, where the __bases__ of the
|
||||
# second arg (the cls arg) is tested. This means the first arg must
|
||||
# return a valid __bases__, and it's okay for it to be a normal --
|
||||
# unrelated by inheritance -- class.
|
||||
def test_dont_mask_non_attribute_error_in_cls_arg(self):
|
||||
class B: pass
|
||||
|
||||
class C(object):
|
||||
def getbases(self):
|
||||
raise RuntimeError
|
||||
__bases__ = property(getbases)
|
||||
|
||||
self.assertRaises(RuntimeError, issubclass, B, C())
|
||||
|
||||
def test_mask_attribute_error_in_cls_arg(self):
|
||||
class B: pass
|
||||
|
||||
class C(object):
|
||||
def getbases(self):
|
||||
raise AttributeError
|
||||
__bases__ = property(getbases)
|
||||
|
||||
self.assertRaises(TypeError, issubclass, B, C())
|
||||
|
||||
|
||||
|
||||
# meta classes for creating abstract classes and instances
|
||||
class AbstractClass(object):
|
||||
def __init__(self, bases):
|
||||
self.bases = bases
|
||||
|
||||
def getbases(self):
|
||||
return self.bases
|
||||
__bases__ = property(getbases)
|
||||
|
||||
def __call__(self):
|
||||
return AbstractInstance(self)
|
||||
|
||||
class AbstractInstance(object):
|
||||
def __init__(self, klass):
|
||||
self.klass = klass
|
||||
|
||||
def getclass(self):
|
||||
return self.klass
|
||||
__class__ = property(getclass)
|
||||
|
||||
# abstract classes
|
||||
AbstractSuper = AbstractClass(bases=())
|
||||
|
||||
AbstractChild = AbstractClass(bases=(AbstractSuper,))
|
||||
|
||||
# normal classes
|
||||
class Super:
|
||||
pass
|
||||
|
||||
class Child(Super):
|
||||
pass
|
||||
|
||||
class TestIsInstanceIsSubclass(unittest.TestCase):
|
||||
# Tests to ensure that isinstance and issubclass work on abstract
|
||||
# classes and instances. Before the 2.2 release, TypeErrors were
|
||||
# raised when boolean values should have been returned. The bug was
|
||||
# triggered by mixing 'normal' classes and instances were with
|
||||
# 'abstract' classes and instances. This case tries to test all
|
||||
# combinations.
|
||||
|
||||
def test_isinstance_normal(self):
|
||||
# normal instances
|
||||
self.assertEqual(True, isinstance(Super(), Super))
|
||||
self.assertEqual(False, isinstance(Super(), Child))
|
||||
self.assertEqual(False, isinstance(Super(), AbstractSuper))
|
||||
self.assertEqual(False, isinstance(Super(), AbstractChild))
|
||||
|
||||
self.assertEqual(True, isinstance(Child(), Super))
|
||||
self.assertEqual(False, isinstance(Child(), AbstractSuper))
|
||||
|
||||
def test_isinstance_abstract(self):
|
||||
# abstract instances
|
||||
self.assertEqual(True, isinstance(AbstractSuper(), AbstractSuper))
|
||||
self.assertEqual(False, isinstance(AbstractSuper(), AbstractChild))
|
||||
self.assertEqual(False, isinstance(AbstractSuper(), Super))
|
||||
self.assertEqual(False, isinstance(AbstractSuper(), Child))
|
||||
|
||||
self.assertEqual(True, isinstance(AbstractChild(), AbstractChild))
|
||||
self.assertEqual(True, isinstance(AbstractChild(), AbstractSuper))
|
||||
self.assertEqual(False, isinstance(AbstractChild(), Super))
|
||||
self.assertEqual(False, isinstance(AbstractChild(), Child))
|
||||
|
||||
def test_isinstance_with_or_union(self):
|
||||
self.assertTrue(isinstance(Super(), Super | int))
|
||||
self.assertFalse(isinstance(None, str | int))
|
||||
self.assertTrue(isinstance(3, str | int))
|
||||
self.assertTrue(isinstance("", str | int))
|
||||
self.assertTrue(isinstance([], typing.List | typing.Tuple))
|
||||
self.assertTrue(isinstance(2, typing.List | int))
|
||||
self.assertFalse(isinstance(2, typing.List | typing.Tuple))
|
||||
self.assertTrue(isinstance(None, int | None))
|
||||
self.assertFalse(isinstance(3.14, int | str))
|
||||
with self.assertRaises(TypeError):
|
||||
isinstance(2, list[int])
|
||||
with self.assertRaises(TypeError):
|
||||
isinstance(2, list[int] | int)
|
||||
with self.assertRaises(TypeError):
|
||||
isinstance(2, int | str | list[int] | float)
|
||||
|
||||
|
||||
|
||||
def test_subclass_normal(self):
|
||||
# normal classes
|
||||
self.assertEqual(True, issubclass(Super, Super))
|
||||
self.assertEqual(False, issubclass(Super, AbstractSuper))
|
||||
self.assertEqual(False, issubclass(Super, Child))
|
||||
|
||||
self.assertEqual(True, issubclass(Child, Child))
|
||||
self.assertEqual(True, issubclass(Child, Super))
|
||||
self.assertEqual(False, issubclass(Child, AbstractSuper))
|
||||
self.assertTrue(issubclass(typing.List, typing.List|typing.Tuple))
|
||||
self.assertFalse(issubclass(int, typing.List|typing.Tuple))
|
||||
|
||||
def test_subclass_abstract(self):
|
||||
# abstract classes
|
||||
self.assertEqual(True, issubclass(AbstractSuper, AbstractSuper))
|
||||
self.assertEqual(False, issubclass(AbstractSuper, AbstractChild))
|
||||
self.assertEqual(False, issubclass(AbstractSuper, Child))
|
||||
|
||||
self.assertEqual(True, issubclass(AbstractChild, AbstractChild))
|
||||
self.assertEqual(True, issubclass(AbstractChild, AbstractSuper))
|
||||
self.assertEqual(False, issubclass(AbstractChild, Super))
|
||||
self.assertEqual(False, issubclass(AbstractChild, Child))
|
||||
|
||||
def test_subclass_tuple(self):
|
||||
# test with a tuple as the second argument classes
|
||||
self.assertEqual(True, issubclass(Child, (Child,)))
|
||||
self.assertEqual(True, issubclass(Child, (Super,)))
|
||||
self.assertEqual(False, issubclass(Super, (Child,)))
|
||||
self.assertEqual(True, issubclass(Super, (Child, Super)))
|
||||
self.assertEqual(False, issubclass(Child, ()))
|
||||
self.assertEqual(True, issubclass(Super, (Child, (Super,))))
|
||||
|
||||
self.assertEqual(True, issubclass(int, (int, (float, int))))
|
||||
self.assertEqual(True, issubclass(str, (str, (Child, str))))
|
||||
|
||||
def test_subclass_recursion_limit(self):
|
||||
# make sure that issubclass raises RecursionError before the C stack is
|
||||
# blown
|
||||
with support.infinite_recursion():
|
||||
self.assertRaises(RecursionError, blowstack, issubclass, str, str)
|
||||
|
||||
def test_isinstance_recursion_limit(self):
|
||||
# make sure that issubclass raises RecursionError before the C stack is
|
||||
# blown
|
||||
with support.infinite_recursion():
|
||||
self.assertRaises(RecursionError, blowstack, isinstance, '', str)
|
||||
|
||||
def test_subclass_with_union(self):
|
||||
self.assertTrue(issubclass(int, int | float | int))
|
||||
self.assertTrue(issubclass(str, str | Child | str))
|
||||
self.assertFalse(issubclass(dict, float|str))
|
||||
self.assertFalse(issubclass(object, float|str))
|
||||
with self.assertRaises(TypeError):
|
||||
issubclass(2, Child | Super)
|
||||
with self.assertRaises(TypeError):
|
||||
issubclass(int, list[int] | Child)
|
||||
|
||||
def test_issubclass_refcount_handling(self):
|
||||
# bpo-39382: abstract_issubclass() didn't hold item reference while
|
||||
# peeking in the bases tuple, in the single inheritance case.
|
||||
class A:
|
||||
@property
|
||||
def __bases__(self):
|
||||
return (int, )
|
||||
|
||||
class B:
|
||||
def __init__(self):
|
||||
# setting this here increases the chances of exhibiting the bug,
|
||||
# probably due to memory layout changes.
|
||||
self.x = 1
|
||||
|
||||
@property
|
||||
def __bases__(self):
|
||||
return (A(), )
|
||||
|
||||
self.assertEqual(True, issubclass(B(), int))
|
||||
|
||||
def test_infinite_recursion_in_bases(self):
|
||||
class X:
|
||||
@property
|
||||
def __bases__(self):
|
||||
return self.__bases__
|
||||
with support.infinite_recursion():
|
||||
self.assertRaises(RecursionError, issubclass, X(), int)
|
||||
self.assertRaises(RecursionError, issubclass, int, X())
|
||||
self.assertRaises(RecursionError, isinstance, 1, X())
|
||||
|
||||
@unittest.skip("TODO: RUSTPYTHON")
|
||||
def test_infinite_recursion_via_bases_tuple(self):
|
||||
"""Regression test for bpo-30570."""
|
||||
class Failure(object):
|
||||
def __getattr__(self, attr):
|
||||
return (self, None)
|
||||
with support.infinite_recursion():
|
||||
with self.assertRaises(RecursionError):
|
||||
issubclass(Failure(), int)
|
||||
|
||||
@unittest.skip("TODO: RUSTPYTHON")
|
||||
def test_infinite_cycle_in_bases(self):
|
||||
"""Regression test for bpo-30570."""
|
||||
class X:
|
||||
@property
|
||||
def __bases__(self):
|
||||
return (self, self, self)
|
||||
with support.infinite_recursion():
|
||||
self.assertRaises(RecursionError, issubclass, X(), int)
|
||||
|
||||
def test_infinitely_many_bases(self):
|
||||
"""Regression test for bpo-30570."""
|
||||
class X:
|
||||
def __getattr__(self, attr):
|
||||
self.assertEqual(attr, "__bases__")
|
||||
class A:
|
||||
pass
|
||||
class B:
|
||||
pass
|
||||
A.__getattr__ = B.__getattr__ = X.__getattr__
|
||||
return (A(), B())
|
||||
with support.infinite_recursion():
|
||||
self.assertRaises(RecursionError, issubclass, X(), int)
|
||||
|
||||
|
||||
def blowstack(fxn, arg, compare_to):
|
||||
# Make sure that calling isinstance with a deeply nested tuple for its
|
||||
# argument will raise RecursionError eventually.
|
||||
tuple_arg = (compare_to,)
|
||||
for cnt in range(sys.getrecursionlimit()+5):
|
||||
tuple_arg = (tuple_arg,)
|
||||
fxn(arg, tuple_arg)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user