@@ -66,24 +66,26 @@ def get_tests(
6666 files : Optional [List [os .PathLike ] | os .PathLike ] = None ,
6767 base : Optional [os .PathLike ] = None ,
6868 environ : Environment = None ,
69+ python = "python3" ,
6970 k : str = None ,
7071 ) -> List [str ]:
7172 return []
7273
7374 def run_test (
74- self , directory : Path , test : str , environ : Environment = None
75+ self , directory : Path , test : str , environ : Environment = None , python = "python3"
7576 ) -> TestResult :
7677 return TestResult .UNDEFINED
7778
7879 def filter_tests (self , tests : List [str ]) -> List [str ]:
80+ # noinspection PyTypeChecker
7981 return list (filter (self .re_filter .search , tests ))
8082
8183 @staticmethod
8284 def safe (s : str ):
83- s = s .encode ("ascii" , "ignore" )
85+ s : bytes = s .encode ("ascii" , "ignore" )
8486 if len (s ) > 255 :
8587 return hashlib .md5 (s ).hexdigest ()
86- s = s .decode ("ascii" )
88+ s : str = s .decode ("ascii" )
8789 for c in string .punctuation :
8890 if c in s :
8991 s = s .replace (c , "_" )
@@ -95,6 +97,7 @@ def run_tests(
9597 output : Path ,
9698 tests : List [str ],
9799 environ : Environment = None ,
100+ python = "python3" ,
98101 ):
99102 output .mkdir (parents = True , exist_ok = True )
100103 for test_result in TestResult :
@@ -119,6 +122,7 @@ def run(
119122 files : Optional [List [os .PathLike ] | os .PathLike ] = None ,
120123 base : Optional [os .PathLike ] = None ,
121124 environ : Environment = None ,
125+ python = "python3" ,
122126 k : str = None ,
123127 ):
124128 self .passing_tests .clear ()
@@ -134,12 +138,13 @@ def run(
134138 self .get_tests (directory , files = files , base = base , environ = environ , k = k )
135139 ),
136140 environ = environ ,
141+ python = python ,
137142 )
138143
139144
140145class VoidRunner (Runner ):
141146 @staticmethod
142- def use_parallel () -> Runner :
147+ def use_parallel () -> type [ Runner ] :
143148 return VoidRunner
144149
145150
@@ -290,11 +295,11 @@ def __init__(
290295 self .set_python_path = set_python_path
291296
292297 @staticmethod
293- def use_parallel () -> Runner :
298+ def use_parallel () -> type [ Runner ] :
294299 return ParallelPytestRunner
295300
296301 @staticmethod
297- def common_base (directory : Path , tests : List [str ]) -> Path :
302+ def common_base (directory : Path , tests : List [str ]) -> Path | None :
298303 parts = directory .parts
299304 common_bases = {Path (* parts [:i ]) for i in range (1 , len (parts ) + 1 )}
300305 leaves_paths = {Path (r .split ("::" , 1 )[0 ] if "::" in r else r ) for r in tests }
@@ -323,7 +328,7 @@ def common_path(files: List[str]) -> Optional[Path]:
323328 return None
324329
325330 @staticmethod
326- def get_files (files : List [os .PathLike ]) -> Set [str ]:
331+ def get_files (files : List [str | os .PathLike [ str ] ]) -> Set [str ]:
327332 paths = set ()
328333 for f in files :
329334 f = str (f )
@@ -393,6 +398,7 @@ def get_tests(
393398 files : Optional [List [os .PathLike ] | os .PathLike ] = None ,
394399 base : Optional [os .PathLike ] = None ,
395400 environ : Environment = None ,
401+ python = "python3" ,
396402 k : str = None ,
397403 ) -> List [str ]:
398404 c = []
@@ -416,7 +422,7 @@ def get_tests(
416422 c += str_files
417423 process = subprocess .run (
418424 [
419- "python3" ,
425+ python ,
420426 "-m" ,
421427 "pytest" ,
422428 "--collect-only" ,
@@ -451,11 +457,11 @@ def __get_pytest_result__(
451457 return False , None , None
452458
453459 def run_test (
454- self , directory : Path , test : str , environ : Environment = None
460+ self , directory : Path , test : str , environ : Environment = None , python = "python3"
455461 ) -> TestResult :
456462 try :
457463 output = subprocess .run (
458- ["python3" , "-m" , "pytest" , test ],
464+ [python , "-m" , "pytest" , test ],
459465 stdout = subprocess .PIPE ,
460466 env = environ ,
461467 cwd = directory ,
@@ -464,7 +470,7 @@ def run_test(
464470 except subprocess .TimeoutExpired :
465471 return TestResult .UNDEFINED
466472 successful , passing , failing = self .__get_pytest_result__ (output )
467- if successful :
473+ if successful and passing is not None and failing is not None :
468474 if passing > 0 and failing == 0 :
469475 return TestResult .PASSING
470476 elif failing > 0 and passing == 0 :
@@ -496,7 +502,7 @@ def __init__(
496502 self .failing : Dict [str , List [str ]] = self ._prepare_tests (failing , "failing" )
497503
498504 @staticmethod
499- def use_parallel () -> Runner :
505+ def use_parallel () -> type [ Runner ] :
500506 return ParallelInputRunner
501507
502508 @staticmethod
@@ -529,22 +535,27 @@ def get_tests(
529535 files : Optional [List [os .PathLike ] | os .PathLike ] = None ,
530536 base : Optional [os .PathLike ] = None ,
531537 environ : Environment = None ,
538+ python = "python3" ,
532539 k : str = None ,
533540 ) -> List [str ]:
534541 return list (self .passing .keys ()) + list (self .failing .keys ())
535542
536543 def run_test (
537- self , directory : Path , test_name : str , environ : Environment = None
544+ self ,
545+ directory : Path | None ,
546+ test : str ,
547+ environ : Environment = None ,
548+ python = "python3" ,
538549 ) -> TestResult :
539- if "passing" in test_name :
540- test = self .passing [test_name ]
550+ if "passing" in test :
551+ test_args = self .passing [test ]
541552 result = TestResult .PASSING
542553 else :
543- test = self .failing [test_name ]
554+ test_args = self .failing [test ]
544555 result = TestResult .FAILING
545556 try :
546557 subprocess .run (
547- ["python3" , self .access ] + test ,
558+ [python , self .access ] + test_args ,
548559 stdout = subprocess .PIPE ,
549560 stderr = subprocess .PIPE ,
550561 env = environ ,
@@ -568,21 +579,27 @@ def __init__(
568579 super ().__init__ (
569580 re_filter , timeout , set_python_path , thread_support = thread_support
570581 )
571- self .workers = max (min (workers , os .cpu_count () or float ( "inf" ) ), 1 )
582+ self .workers = max (min (workers , os .cpu_count () or 512 ), 1 )
572583 self .is_parallel = True
573584 self .environ = None
585+ self .python = None
574586 self .directory = None
575587 self .output = None
576588
577589 @staticmethod
578- def use_parallel () -> Runner :
590+ def use_parallel () -> type [ Runner ] :
579591 return ParallelPytestRunner
580592
581- def process_test (self , test : str ):
593+ def process_test (
594+ self ,
595+ test : str ,
596+ ):
582597 local_environ = self .environ .copy ()
583598 events_path_name = f"EVENTS_PATH_{ os .getpid ()} "
584599 local_environ ["EVENTS_PATH" ] = events_path_name
585- tr = self .run_test (self .directory , test , environ = local_environ )
600+ tr = self .run_test (
601+ self .directory , test , environ = local_environ , python = self .python
602+ )
586603 self .tests [tr ].add (test )
587604 if os .path .exists (self .directory / events_path_name ):
588605 shutil .move (
@@ -598,14 +615,17 @@ def run_tests(
598615 output : Path ,
599616 tests : List [str ],
600617 environ : Environment = None ,
618+ python = "python3" ,
601619 ):
602620 output .mkdir (parents = True , exist_ok = True )
603621 for test_result in TestResult :
604622 (output / test_result .get_dir ()).mkdir (parents = True , exist_ok = True )
605623
606624 self .directory = directory
607625 self .output = output
626+ # noinspection PyUnresolvedReferences
608627 self .environ = environ or os .environ .copy ()
628+ self .python = python
609629
610630 with ProcessPoolExecutor (max_workers = self .workers ) as executor :
611631 # Consume the iterator to ensure all tasks complete
@@ -625,23 +645,28 @@ def __init__(
625645 thread_support : bool = False ,
626646 ):
627647 super ().__init__ (access , passing , failing , thread_support = thread_support )
628- self .workers = max (min (workers , os .cpu_count () or float ( "inf" ) ), 1 )
648+ self .workers = max (min (workers , os .cpu_count () or 512 ), 1 )
629649 self .is_parallel = True
630650 self .environ = None
631- self .directory : Path = None
632- self .output : Path = None
651+ self .python = None
652+ self .directory : Path | None = None
653+ self .output : Path | None = None
633654
634655 @staticmethod
635- def use_parallel () -> Runner :
656+ def use_parallel () -> type [ Runner ] :
636657 return ParallelInputRunner
637658
638659 def process_test (self , test_name : str ):
639660 local_environ = self .environ .copy ()
640661 events_path_name = f"EVENTS_PATH_{ os .getpid ()} "
641662 local_environ ["EVENTS_PATH" ] = events_path_name
642- tr = self .run_test (self .directory , test_name , environ = local_environ )
663+ tr = self .run_test (
664+ self .directory , test_name , environ = local_environ , python = self .python
665+ )
643666 self .tests [tr ].add (test_name )
667+ # noinspection PyUnresolvedReferences
644668 if os .path .exists (self .directory / events_path_name ):
669+ # noinspection PyUnresolvedReferences
645670 shutil .move (
646671 self .directory / events_path_name ,
647672 self .output / tr .get_dir () / self .safe (test_name ),
@@ -655,14 +680,17 @@ def run_tests(
655680 output : Path ,
656681 tests : List [str ],
657682 environ : Environment = None ,
683+ python = "python3" ,
658684 ):
659685 output .mkdir (parents = True , exist_ok = True )
660686 for test_result in TestResult :
661687 (output / test_result .get_dir ()).mkdir (parents = True , exist_ok = True )
662688
663689 self .directory = directory
664690 self .output = output
691+ # noinspection PyUnresolvedReferences
665692 self .environ = environ or os .environ .copy ()
693+ self .python = python
666694
667695 with ProcessPoolExecutor (max_workers = self .workers ) as executor :
668696 # Consume the iterator to ensure all tasks complete
0 commit comments