Coverage for /usr/lib/python3/dist-packages/sympy/printing/python.py: 21%

58 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-14 15:55 +0200

1import keyword as kw 

2import sympy 

3from .repr import ReprPrinter 

4from .str import StrPrinter 

5 

6# A list of classes that should be printed using StrPrinter 

7STRPRINT = ("Add", "Infinity", "Integer", "Mul", "NegativeInfinity", 

8 "Pow", "Zero") 

9 

10 

11class PythonPrinter(ReprPrinter, StrPrinter): 

12 """A printer which converts an expression into its Python interpretation.""" 

13 

14 def __init__(self, settings=None): 

15 super().__init__(settings) 

16 self.symbols = [] 

17 self.functions = [] 

18 

19 # Create print methods for classes that should use StrPrinter instead 

20 # of ReprPrinter. 

21 for name in STRPRINT: 

22 f_name = "_print_%s" % name 

23 f = getattr(StrPrinter, f_name) 

24 setattr(PythonPrinter, f_name, f) 

25 

26 def _print_Function(self, expr): 

27 func = expr.func.__name__ 

28 if not hasattr(sympy, func) and func not in self.functions: 

29 self.functions.append(func) 

30 return StrPrinter._print_Function(self, expr) 

31 

32 # procedure (!) for defining symbols which have be defined in print_python() 

33 def _print_Symbol(self, expr): 

34 symbol = self._str(expr) 

35 if symbol not in self.symbols: 

36 self.symbols.append(symbol) 

37 return StrPrinter._print_Symbol(self, expr) 

38 

39 def _print_module(self, expr): 

40 raise ValueError('Modules in the expression are unacceptable') 

41 

42 

43def python(expr, **settings): 

44 """Return Python interpretation of passed expression 

45 (can be passed to the exec() function without any modifications)""" 

46 

47 printer = PythonPrinter(settings) 

48 exprp = printer.doprint(expr) 

49 

50 result = '' 

51 # Returning found symbols and functions 

52 renamings = {} 

53 for symbolname in printer.symbols: 

54 # Remove curly braces from subscripted variables 

55 if '{' in symbolname: 

56 newsymbolname = symbolname.replace('{', '').replace('}', '') 

57 renamings[sympy.Symbol(symbolname)] = newsymbolname 

58 else: 

59 newsymbolname = symbolname 

60 

61 # Escape symbol names that are reserved Python keywords 

62 if kw.iskeyword(newsymbolname): 

63 while True: 

64 newsymbolname += "_" 

65 if (newsymbolname not in printer.symbols and 

66 newsymbolname not in printer.functions): 

67 renamings[sympy.Symbol( 

68 symbolname)] = sympy.Symbol(newsymbolname) 

69 break 

70 result += newsymbolname + ' = Symbol(\'' + symbolname + '\')\n' 

71 

72 for functionname in printer.functions: 

73 newfunctionname = functionname 

74 # Escape function names that are reserved Python keywords 

75 if kw.iskeyword(newfunctionname): 

76 while True: 

77 newfunctionname += "_" 

78 if (newfunctionname not in printer.symbols and 

79 newfunctionname not in printer.functions): 

80 renamings[sympy.Function( 

81 functionname)] = sympy.Function(newfunctionname) 

82 break 

83 result += newfunctionname + ' = Function(\'' + functionname + '\')\n' 

84 

85 if renamings: 

86 exprp = expr.subs(renamings) 

87 result += 'e = ' + printer._str(exprp) 

88 return result 

89 

90 

91def print_python(expr, **settings): 

92 """Print output of python() function""" 

93 print(python(expr, **settings))