Skip to content

Commit 9b400a9

Browse files
committed
Reapply some patches
1 parent 19b6241 commit 9b400a9

File tree

3 files changed

+228
-1
lines changed

3 files changed

+228
-1
lines changed

Lib/_collections_abc.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,10 @@ def __getitem__(self, item):
512512
new_args = (t_args, t_result)
513513
return _CallableGenericAlias(Callable, tuple(new_args))
514514

515+
# TODO: RUSTPYTHON; patch for common call
516+
def __or__(self, other):
517+
super().__or__(other)
518+
515519
def _is_param_expr(obj):
516520
"""Checks if obj matches either a list of types, ``...``, ``ParamSpec`` or
517521
``_ConcatenateGenericAlias`` from typing.py

Lib/sysconfig/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@
107107
_INSTALL_SCHEMES['venv'] = _INSTALL_SCHEMES['posix_venv']
108108

109109
def _get_implementation():
110-
return 'Python'
110+
return 'RustPython' # XXX: For site-packages
111111

112112
# NOTE: site.py has copy of this function.
113113
# Sync it when modify this function.

Lib/test/support/__init__.py

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,7 @@ def requires_lzma(reason='requires lzma'):
511511
import lzma
512512
except ImportError:
513513
lzma = None
514+
lzma = None # XXX: RUSTPYTHON; xz is not supported yet
514515
return unittest.skipUnless(lzma, reason)
515516

516517
def has_no_debug_ranges():
@@ -841,13 +842,22 @@ def gc_collect():
841842
longer than expected. This function tries its best to force all garbage
842843
objects to disappear.
843844
"""
845+
return # TODO: RUSTPYTHON
846+
844847
import gc
845848
gc.collect()
846849
gc.collect()
847850
gc.collect()
848851

849852
@contextlib.contextmanager
850853
def disable_gc():
854+
# TODO: RUSTPYTHON; GC is not supported yet
855+
try:
856+
yield
857+
finally:
858+
pass
859+
return
860+
851861
import gc
852862
have_gc = gc.isenabled()
853863
gc.disable()
@@ -859,6 +869,13 @@ def disable_gc():
859869

860870
@contextlib.contextmanager
861871
def gc_threshold(*args):
872+
# TODO: RUSTPYTHON; GC is not supported yet
873+
try:
874+
yield
875+
finally:
876+
pass
877+
return
878+
862879
import gc
863880
old_threshold = gc.get_threshold()
864881
gc.set_threshold(*args)
@@ -1921,6 +1938,10 @@ def _check_tracemalloc():
19211938

19221939

19231940
def check_free_after_iterating(test, iter, cls, args=()):
1941+
# TODO: RUSTPYTHON; GC is not supported yet
1942+
test.assertTrue(False)
1943+
return
1944+
19241945
done = False
19251946
def wrapper():
19261947
class A(cls):
@@ -2845,3 +2866,205 @@ def linked_to_musl():
28452866
except (OSError, subprocess.CalledProcessError):
28462867
return False
28472868
return ('musl' in stdout)
2869+
2870+
2871+
# TODO: RUSTPYTHON
2872+
# Every line of code below allowed us to update `Lib/test/support/__init__.py` without
2873+
# needing to update `libregtest` and its dependencies.
2874+
# Ideally we want to remove all code below and update `libregtest`.
2875+
#
2876+
# Code below was copied from: https://github.com/RustPython/RustPython/blob/9499d39f55b73535e2405bf208d5380241f79ada/Lib/test/support/__init__.py
2877+
2878+
from .testresult import get_test_runner
2879+
2880+
def _filter_suite(suite, pred):
2881+
"""Recursively filter test cases in a suite based on a predicate."""
2882+
newtests = []
2883+
for test in suite._tests:
2884+
if isinstance(test, unittest.TestSuite):
2885+
_filter_suite(test, pred)
2886+
newtests.append(test)
2887+
else:
2888+
if pred(test):
2889+
newtests.append(test)
2890+
suite._tests = newtests
2891+
2892+
# By default, don't filter tests
2893+
_match_test_func = None
2894+
2895+
_accept_test_patterns = None
2896+
_ignore_test_patterns = None
2897+
2898+
def match_test(test):
2899+
# Function used by support.run_unittest() and regrtest --list-cases
2900+
if _match_test_func is None:
2901+
return True
2902+
else:
2903+
return _match_test_func(test.id())
2904+
2905+
def _is_full_match_test(pattern):
2906+
# If a pattern contains at least one dot, it's considered
2907+
# as a full test identifier.
2908+
# Example: 'test.test_os.FileTests.test_access'.
2909+
#
2910+
# ignore patterns which contain fnmatch patterns: '*', '?', '[...]'
2911+
# or '[!...]'. For example, ignore 'test_access*'.
2912+
return ('.' in pattern) and (not re.search(r'[?*\[\]]', pattern))
2913+
2914+
def set_match_tests(accept_patterns=None, ignore_patterns=None):
2915+
global _match_test_func, _accept_test_patterns, _ignore_test_patterns
2916+
2917+
if accept_patterns is None:
2918+
accept_patterns = ()
2919+
if ignore_patterns is None:
2920+
ignore_patterns = ()
2921+
2922+
accept_func = ignore_func = None
2923+
2924+
if accept_patterns != _accept_test_patterns:
2925+
accept_patterns, accept_func = _compile_match_function(accept_patterns)
2926+
if ignore_patterns != _ignore_test_patterns:
2927+
ignore_patterns, ignore_func = _compile_match_function(ignore_patterns)
2928+
2929+
# Create a copy since patterns can be mutable and so modified later
2930+
_accept_test_patterns = tuple(accept_patterns)
2931+
_ignore_test_patterns = tuple(ignore_patterns)
2932+
2933+
if accept_func is not None or ignore_func is not None:
2934+
def match_function(test_id):
2935+
accept = True
2936+
ignore = False
2937+
if accept_func:
2938+
accept = accept_func(test_id)
2939+
if ignore_func:
2940+
ignore = ignore_func(test_id)
2941+
return accept and not ignore
2942+
2943+
_match_test_func = match_function
2944+
2945+
def _compile_match_function(patterns):
2946+
if not patterns:
2947+
func = None
2948+
# set_match_tests(None) behaves as set_match_tests(())
2949+
patterns = ()
2950+
elif all(map(_is_full_match_test, patterns)):
2951+
# Simple case: all patterns are full test identifier.
2952+
# The test.bisect_cmd utility only uses such full test identifiers.
2953+
func = set(patterns).__contains__
2954+
else:
2955+
import fnmatch
2956+
regex = '|'.join(map(fnmatch.translate, patterns))
2957+
# The search *is* case sensitive on purpose:
2958+
# don't use flags=re.IGNORECASE
2959+
regex_match = re.compile(regex).match
2960+
2961+
def match_test_regex(test_id):
2962+
if regex_match(test_id):
2963+
# The regex matches the whole identifier, for example
2964+
# 'test.test_os.FileTests.test_access'.
2965+
return True
2966+
else:
2967+
# Try to match parts of the test identifier.
2968+
# For example, split 'test.test_os.FileTests.test_access'
2969+
# into: 'test', 'test_os', 'FileTests' and 'test_access'.
2970+
return any(map(regex_match, test_id.split(".")))
2971+
2972+
func = match_test_regex
2973+
2974+
return patterns, func
2975+
2976+
def run_unittest(*classes):
2977+
"""Run tests from unittest.TestCase-derived classes."""
2978+
valid_types = (unittest.TestSuite, unittest.TestCase)
2979+
loader = unittest.TestLoader()
2980+
suite = unittest.TestSuite()
2981+
for cls in classes:
2982+
if isinstance(cls, str):
2983+
if cls in sys.modules:
2984+
suite.addTest(loader.loadTestsFromModule(sys.modules[cls]))
2985+
else:
2986+
raise ValueError("str arguments must be keys in sys.modules")
2987+
elif isinstance(cls, valid_types):
2988+
suite.addTest(cls)
2989+
else:
2990+
suite.addTest(loader.loadTestsFromTestCase(cls))
2991+
_filter_suite(suite, match_test)
2992+
return _run_suite(suite)
2993+
2994+
def _run_suite(suite):
2995+
"""Run tests from a unittest.TestSuite-derived class."""
2996+
runner = get_test_runner(sys.stdout,
2997+
verbosity=verbose,
2998+
capture_output=(junit_xml_list is not None))
2999+
3000+
result = runner.run(suite)
3001+
3002+
if junit_xml_list is not None:
3003+
junit_xml_list.append(result.get_xml_element())
3004+
3005+
if not result.testsRun and not result.skipped and not result.errors:
3006+
raise TestDidNotRun
3007+
if not result.wasSuccessful():
3008+
stats = TestStats.from_unittest(result)
3009+
if len(result.errors) == 1 and not result.failures:
3010+
err = result.errors[0][1]
3011+
elif len(result.failures) == 1 and not result.errors:
3012+
err = result.failures[0][1]
3013+
else:
3014+
err = "multiple errors occurred"
3015+
if not verbose: err += "; run in verbose mode for details"
3016+
errors = [(str(tc), exc_str) for tc, exc_str in result.errors]
3017+
failures = [(str(tc), exc_str) for tc, exc_str in result.failures]
3018+
raise TestFailedWithDetails(err, errors, failures, stats=stats)
3019+
return result
3020+
3021+
@dataclasses.dataclass(slots=True)
3022+
class TestStats:
3023+
tests_run: int = 0
3024+
failures: int = 0
3025+
skipped: int = 0
3026+
3027+
@staticmethod
3028+
def from_unittest(result):
3029+
return TestStats(result.testsRun,
3030+
len(result.failures),
3031+
len(result.skipped))
3032+
3033+
@staticmethod
3034+
def from_doctest(results):
3035+
return TestStats(results.attempted,
3036+
results.failed)
3037+
3038+
def accumulate(self, stats):
3039+
self.tests_run += stats.tests_run
3040+
self.failures += stats.failures
3041+
self.skipped += stats.skipped
3042+
3043+
3044+
def run_doctest(module, verbosity=None, optionflags=0):
3045+
"""Run doctest on the given module. Return (#failures, #tests).
3046+
3047+
If optional argument verbosity is not specified (or is None), pass
3048+
support's belief about verbosity on to doctest. Else doctest's
3049+
usual behavior is used (it searches sys.argv for -v).
3050+
"""
3051+
3052+
import doctest
3053+
3054+
if verbosity is None:
3055+
verbosity = verbose
3056+
else:
3057+
verbosity = None
3058+
3059+
results = doctest.testmod(module,
3060+
verbose=verbosity,
3061+
optionflags=optionflags)
3062+
if results.failed:
3063+
stats = TestStats.from_doctest(results)
3064+
raise TestFailed(f"{results.failed} of {results.attempted} "
3065+
f"doctests failed",
3066+
stats=stats)
3067+
if verbose:
3068+
print('doctest (%s) ... %d tests with zero failures' %
3069+
(module.__name__, results.attempted))
3070+
return results

0 commit comments

Comments
 (0)