Coverage for pysource_minimize/_minimize.py: 94%

38 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2024-03-25 08:14 +0100

1import ast 

2import warnings 

3 

4from ._minimize_base import equal_ast 

5from ._minimize_structure import MinimizeStructure 

6from ._minimize_value import MinimizeValue 

7from ._utils import parse 

8from ._utils import unparse 

9 

10 

11def minimize_ast( 11 ↛ exitline 11 didn't jump to the function exit

12 original_ast: ast.AST, 

13 checker, 

14 *, 

15 progress_callback=lambda current, total: None, 

16 retries=1, 

17) -> ast.AST: 

18 """ 

19 minimzes the AST 

20 

21 Args: 

22 ast: the ast to minimize 

23 checker: a function which gets the ast and returns `True` when the criteria is fullfilled. 

24 progress_callback: function which is called everytime the ast gets a bit smaller. 

25 retries: the number of retries which sould be performed when the ast could be minimized (useful for non deterministic issues) 

26 

27 returns the minimized ast 

28 """ 

29 

30 last_success = 0 

31 

32 current_ast = original_ast 

33 while last_success <= retries: 

34 new_ast = current_ast 

35 

36 for Minimizer in (MinimizeStructure, MinimizeValue): 

37 minimizer = Minimizer(new_ast, checker, progress_callback) 

38 new_ast = minimizer.get_current_tree({}) 

39 if minimizer.stop: 

40 break 

41 

42 minimized_something = not equal_ast(new_ast, current_ast) 

43 

44 current_ast = new_ast 

45 

46 if minimized_something: 

47 last_success = 0 

48 else: 

49 last_success += 1 

50 

51 return current_ast 

52 

53 

54def minimize( 

55 source: str, checker, *, progress_callback=lambda current, total: None, retries=1 

56) -> str: 

57 """ 

58 minimzes the source code 

59 

60 Args: 

61 source: the source code to minimize 

62 checker: a function which gets the source and returns `True` when the criteria is fullfilled. 

63 progress_callback: function which is called everytime the source gets a bit smaller. 

64 retries: the number of retries which sould be performed when the ast could be minimized (useful for non deterministic issues) 

65 

66 returns the minimized source 

67 """ 

68 

69 original_ast = parse(source) 

70 

71 def source_checker(new_ast): 

72 try: 

73 with warnings.catch_warnings(): 

74 source = unparse(new_ast) 

75 warnings.simplefilter("ignore", SyntaxWarning) 

76 compile(source, "<string>", "exec") 

77 except: 

78 return False 

79 

80 return checker(source) 

81 

82 if not source_checker(original_ast): 82 ↛ 83line 82 didn't jump to line 83, because the condition on line 82 was never true

83 raise ValueError("ast.unparse removes the error minimize can not help here") 

84 

85 minimized_ast = minimize_ast( 

86 original_ast, 

87 source_checker, 

88 progress_callback=progress_callback, 

89 retries=retries, 

90 ) 

91 

92 return unparse(minimized_ast)