Coverage for /usr/lib/python3/dist-packages/sympy/printing/repr.py: 30%
216 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
1"""
2A Printer for generating executable code.
4The most important function here is srepr that returns a string so that the
5relation eval(srepr(expr))=expr holds in an appropriate environment.
6"""
8from __future__ import annotations
9from typing import Any
11from sympy.core.function import AppliedUndef
12from sympy.core.mul import Mul
13from mpmath.libmp import repr_dps, to_str as mlib_to_str
15from .printer import Printer, print_function
18class ReprPrinter(Printer):
19 printmethod = "_sympyrepr"
21 _default_settings: dict[str, Any] = {
22 "order": None,
23 "perm_cyclic" : True,
24 }
26 def reprify(self, args, sep):
27 """
28 Prints each item in `args` and joins them with `sep`.
29 """
30 return sep.join([self.doprint(item) for item in args])
32 def emptyPrinter(self, expr):
33 """
34 The fallback printer.
35 """
36 if isinstance(expr, str):
37 return expr
38 elif hasattr(expr, "__srepr__"):
39 return expr.__srepr__()
40 elif hasattr(expr, "args") and hasattr(expr.args, "__iter__"):
41 l = []
42 for o in expr.args:
43 l.append(self._print(o))
44 return expr.__class__.__name__ + '(%s)' % ', '.join(l)
45 elif hasattr(expr, "__module__") and hasattr(expr, "__name__"):
46 return "<'%s.%s'>" % (expr.__module__, expr.__name__)
47 else:
48 return str(expr)
50 def _print_Add(self, expr, order=None):
51 args = self._as_ordered_terms(expr, order=order)
52 args = map(self._print, args)
53 clsname = type(expr).__name__
54 return clsname + "(%s)" % ", ".join(args)
56 def _print_Cycle(self, expr):
57 return expr.__repr__()
59 def _print_Permutation(self, expr):
60 from sympy.combinatorics.permutations import Permutation, Cycle
61 from sympy.utilities.exceptions import sympy_deprecation_warning
63 perm_cyclic = Permutation.print_cyclic
64 if perm_cyclic is not None:
65 sympy_deprecation_warning(
66 f"""
67 Setting Permutation.print_cyclic is deprecated. Instead use
68 init_printing(perm_cyclic={perm_cyclic}).
69 """,
70 deprecated_since_version="1.6",
71 active_deprecations_target="deprecated-permutation-print_cyclic",
72 stacklevel=7,
73 )
74 else:
75 perm_cyclic = self._settings.get("perm_cyclic", True)
77 if perm_cyclic:
78 if not expr.size:
79 return 'Permutation()'
80 # before taking Cycle notation, see if the last element is
81 # a singleton and move it to the head of the string
82 s = Cycle(expr)(expr.size - 1).__repr__()[len('Cycle'):]
83 last = s.rfind('(')
84 if not last == 0 and ',' not in s[last:]:
85 s = s[last:] + s[:last]
86 return 'Permutation%s' %s
87 else:
88 s = expr.support()
89 if not s:
90 if expr.size < 5:
91 return 'Permutation(%s)' % str(expr.array_form)
92 return 'Permutation([], size=%s)' % expr.size
93 trim = str(expr.array_form[:s[-1] + 1]) + ', size=%s' % expr.size
94 use = full = str(expr.array_form)
95 if len(trim) < len(full):
96 use = trim
97 return 'Permutation(%s)' % use
99 def _print_Function(self, expr):
100 r = self._print(expr.func)
101 r += '(%s)' % ', '.join([self._print(a) for a in expr.args])
102 return r
104 def _print_Heaviside(self, expr):
105 # Same as _print_Function but uses pargs to suppress default value for
106 # 2nd arg.
107 r = self._print(expr.func)
108 r += '(%s)' % ', '.join([self._print(a) for a in expr.pargs])
109 return r
111 def _print_FunctionClass(self, expr):
112 if issubclass(expr, AppliedUndef):
113 return 'Function(%r)' % (expr.__name__)
114 else:
115 return expr.__name__
117 def _print_Half(self, expr):
118 return 'Rational(1, 2)'
120 def _print_RationalConstant(self, expr):
121 return str(expr)
123 def _print_AtomicExpr(self, expr):
124 return str(expr)
126 def _print_NumberSymbol(self, expr):
127 return str(expr)
129 def _print_Integer(self, expr):
130 return 'Integer(%i)' % expr.p
132 def _print_Complexes(self, expr):
133 return 'Complexes'
135 def _print_Integers(self, expr):
136 return 'Integers'
138 def _print_Naturals(self, expr):
139 return 'Naturals'
141 def _print_Naturals0(self, expr):
142 return 'Naturals0'
144 def _print_Rationals(self, expr):
145 return 'Rationals'
147 def _print_Reals(self, expr):
148 return 'Reals'
150 def _print_EmptySet(self, expr):
151 return 'EmptySet'
153 def _print_UniversalSet(self, expr):
154 return 'UniversalSet'
156 def _print_EmptySequence(self, expr):
157 return 'EmptySequence'
159 def _print_list(self, expr):
160 return "[%s]" % self.reprify(expr, ", ")
162 def _print_dict(self, expr):
163 sep = ", "
164 dict_kvs = ["%s: %s" % (self.doprint(key), self.doprint(value)) for key, value in expr.items()]
165 return "{%s}" % sep.join(dict_kvs)
167 def _print_set(self, expr):
168 if not expr:
169 return "set()"
170 return "{%s}" % self.reprify(expr, ", ")
172 def _print_MatrixBase(self, expr):
173 # special case for some empty matrices
174 if (expr.rows == 0) ^ (expr.cols == 0):
175 return '%s(%s, %s, %s)' % (expr.__class__.__name__,
176 self._print(expr.rows),
177 self._print(expr.cols),
178 self._print([]))
179 l = []
180 for i in range(expr.rows):
181 l.append([])
182 for j in range(expr.cols):
183 l[-1].append(expr[i, j])
184 return '%s(%s)' % (expr.__class__.__name__, self._print(l))
186 def _print_BooleanTrue(self, expr):
187 return "true"
189 def _print_BooleanFalse(self, expr):
190 return "false"
192 def _print_NaN(self, expr):
193 return "nan"
195 def _print_Mul(self, expr, order=None):
196 if self.order not in ('old', 'none'):
197 args = expr.as_ordered_factors()
198 else:
199 # use make_args in case expr was something like -x -> x
200 args = Mul.make_args(expr)
202 args = map(self._print, args)
203 clsname = type(expr).__name__
204 return clsname + "(%s)" % ", ".join(args)
206 def _print_Rational(self, expr):
207 return 'Rational(%s, %s)' % (self._print(expr.p), self._print(expr.q))
209 def _print_PythonRational(self, expr):
210 return "%s(%d, %d)" % (expr.__class__.__name__, expr.p, expr.q)
212 def _print_Fraction(self, expr):
213 return 'Fraction(%s, %s)' % (self._print(expr.numerator), self._print(expr.denominator))
215 def _print_Float(self, expr):
216 r = mlib_to_str(expr._mpf_, repr_dps(expr._prec))
217 return "%s('%s', precision=%i)" % (expr.__class__.__name__, r, expr._prec)
219 def _print_Sum2(self, expr):
220 return "Sum2(%s, (%s, %s, %s))" % (self._print(expr.f), self._print(expr.i),
221 self._print(expr.a), self._print(expr.b))
223 def _print_Str(self, s):
224 return "%s(%s)" % (s.__class__.__name__, self._print(s.name))
226 def _print_Symbol(self, expr):
227 d = expr._assumptions_orig
228 # print the dummy_index like it was an assumption
229 if expr.is_Dummy:
230 d['dummy_index'] = expr.dummy_index
232 if d == {}:
233 return "%s(%s)" % (expr.__class__.__name__, self._print(expr.name))
234 else:
235 attr = ['%s=%s' % (k, v) for k, v in d.items()]
236 return "%s(%s, %s)" % (expr.__class__.__name__,
237 self._print(expr.name), ', '.join(attr))
239 def _print_CoordinateSymbol(self, expr):
240 d = expr._assumptions.generator
242 if d == {}:
243 return "%s(%s, %s)" % (
244 expr.__class__.__name__,
245 self._print(expr.coord_sys),
246 self._print(expr.index)
247 )
248 else:
249 attr = ['%s=%s' % (k, v) for k, v in d.items()]
250 return "%s(%s, %s, %s)" % (
251 expr.__class__.__name__,
252 self._print(expr.coord_sys),
253 self._print(expr.index),
254 ', '.join(attr)
255 )
257 def _print_Predicate(self, expr):
258 return "Q.%s" % expr.name
260 def _print_AppliedPredicate(self, expr):
261 # will be changed to just expr.args when args overriding is removed
262 args = expr._args
263 return "%s(%s)" % (expr.__class__.__name__, self.reprify(args, ", "))
265 def _print_str(self, expr):
266 return repr(expr)
268 def _print_tuple(self, expr):
269 if len(expr) == 1:
270 return "(%s,)" % self._print(expr[0])
271 else:
272 return "(%s)" % self.reprify(expr, ", ")
274 def _print_WildFunction(self, expr):
275 return "%s('%s')" % (expr.__class__.__name__, expr.name)
277 def _print_AlgebraicNumber(self, expr):
278 return "%s(%s, %s)" % (expr.__class__.__name__,
279 self._print(expr.root), self._print(expr.coeffs()))
281 def _print_PolyRing(self, ring):
282 return "%s(%s, %s, %s)" % (ring.__class__.__name__,
283 self._print(ring.symbols), self._print(ring.domain), self._print(ring.order))
285 def _print_FracField(self, field):
286 return "%s(%s, %s, %s)" % (field.__class__.__name__,
287 self._print(field.symbols), self._print(field.domain), self._print(field.order))
289 def _print_PolyElement(self, poly):
290 terms = list(poly.terms())
291 terms.sort(key=poly.ring.order, reverse=True)
292 return "%s(%s, %s)" % (poly.__class__.__name__, self._print(poly.ring), self._print(terms))
294 def _print_FracElement(self, frac):
295 numer_terms = list(frac.numer.terms())
296 numer_terms.sort(key=frac.field.order, reverse=True)
297 denom_terms = list(frac.denom.terms())
298 denom_terms.sort(key=frac.field.order, reverse=True)
299 numer = self._print(numer_terms)
300 denom = self._print(denom_terms)
301 return "%s(%s, %s, %s)" % (frac.__class__.__name__, self._print(frac.field), numer, denom)
303 def _print_FractionField(self, domain):
304 cls = domain.__class__.__name__
305 field = self._print(domain.field)
306 return "%s(%s)" % (cls, field)
308 def _print_PolynomialRingBase(self, ring):
309 cls = ring.__class__.__name__
310 dom = self._print(ring.domain)
311 gens = ', '.join(map(self._print, ring.gens))
312 order = str(ring.order)
313 if order != ring.default_order:
314 orderstr = ", order=" + order
315 else:
316 orderstr = ""
317 return "%s(%s, %s%s)" % (cls, dom, gens, orderstr)
319 def _print_DMP(self, p):
320 cls = p.__class__.__name__
321 rep = self._print(p.rep)
322 dom = self._print(p.dom)
323 if p.ring is not None:
324 ringstr = ", ring=" + self._print(p.ring)
325 else:
326 ringstr = ""
327 return "%s(%s, %s%s)" % (cls, rep, dom, ringstr)
329 def _print_MonogenicFiniteExtension(self, ext):
330 # The expanded tree shown by srepr(ext.modulus)
331 # is not practical.
332 return "FiniteExtension(%s)" % str(ext.modulus)
334 def _print_ExtensionElement(self, f):
335 rep = self._print(f.rep)
336 ext = self._print(f.ext)
337 return "ExtElem(%s, %s)" % (rep, ext)
339@print_function(ReprPrinter)
340def srepr(expr, **settings):
341 """return expr in repr form"""
342 return ReprPrinter(settings).doprint(expr)