@@ -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
516517def 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
850853def 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
861871def 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
19231940def 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