This file is indexed.

/usr/share/pyshared/sympy/printing/printer.py is in python-sympy 0.7.1.rc1-3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
"""Printing subsystem driver

SymPy's printing system works the following way: Any expression can be passed to
a designated Printer who then is responsible to return a adequate representation
of that expression.

The basic concept is the following:
  1. Let the object print itself if it knows how.
  2. Take the best fitting method defined in the printer.
  3. As fall-back use the emptyPrinter method for the printer.

Some more information how the single concepts work and who should use which:

1. The object prints itself

    This was the original way of doing printing in sympy. Every class had its
    own latex, mathml, str and repr methods, but it turned out that it is hard
    to produce a high quality printer, if all the methods are spread out that
    far. Therefor all printing code was combined into the different printers,
    which works great for built-in sympy objects, but not that good for user
    defined classes where it is inconvenient to patch the printers.
    To get nevertheless a fitting representation, the printers look for a
    specific method in every object, that will be called if it's available and
    is then responsible for the representation. The name of that method depends
    on the specific printer and is defined under Printer.printmethodname.


2. Take the best fitting method defined in the printer.

    The printer loops through expr classes (class + its bases), and tries to dispatch the
    work to _print_<EXPR_CLASS>

    e.g., suppose we have the following class hierarchy::

            Basic
            |
            Atom
            |
            Number
            |
        Rational

    then, for expr=Rational(...), in order to dispatch, we will try calling printer methods
    as shown in the figure below::

        p._print(expr)
        |
        |-- p._print_Rational(expr)
        |
        |-- p._print_Number(expr)
        |
        |-- p._print_Atom(expr)
        |
        `-- p._print_Basic(expr)

    if ._print_Rational method exists in the printer, then it is called,
    and the result is returned back.

    otherwise, we proceed with trying Rational bases in the inheritance
    order.

3. As fall-back use the emptyPrinter method for the printer.

    As fall-back self.emptyPrinter will be called with the expression. If
    not defined in the Printer subclass this will be the same as str(expr)
"""

from sympy import S, Basic, Mul, Add

from sympy.core.exprtools import decompose_power
from sympy.polys.monomialtools import monomial_key
from sympy.core.basic import BasicMeta

from sympy.core.compatibility import cmp_to_key

class Printer(object):
    """Generic printer

    Its job is to provide infrastructure for implementing new printers easily.

    Basically, if you want to implement a printer, all you have to do is:

    1. Subclass Printer.

    2. Define Printer.printmethod in your subclass.
       If a object has a method with that name, this method will be used
       for printing.

    3. In your subclass, define _print_<CLASS> methods

       For each class you want to provide printing to, define an appropriate
       method how to do it. For example if you want a class FOO to be printed in
       its own way, define _print_FOO:

       def _print_FOO(self, e):
           ...

       this should return how FOO instance e is printed

       Also, if BAR is a subclass of FOO, _print_FOO(bar) will be called for
       instance of BAR, if no _print_BAR is provided.  Thus, usually, we don't
       need to provide printing routines for every class we want to support --
       only generic routine has to be provided for a set of classes.

       A good example for this are functions - for example PrettyPrinter only
       defines _print_Function, and there is no _print_sin, _print_tan, etc...

       On the other hand, a good printer will probably have to define separate
       routines for Symbol, Atom, Number, Integral, Limit, etc...

    4. If convenient, override self.emptyPrinter

       This callable will be called to obtain printing result as a last resort,
       that is when no appropriate print method was found for an expression.

    Example of overloading StrPrinter::

        from sympy import Basic, Function, Symbol
        from sympy.printing.str import StrPrinter

        class CustomStrPrinter(StrPrinter):
            \"\"\"
            Example of how to customize the StrPrinter for both a Sympy class and a
            user defined class subclassed from the Sympy Basic class.
            \"\"\"

            def _print_Derivative(self, expr):
                \"\"\"
                Custom printing of the Sympy Derivative class.

                Instead of:

                D(x(t), t) or D(x(t), t, t)

                We will print:

                x'     or     x''

                In this example, expr.args == (x(t), t), and expr.args[0] == x(t), and
                expr.args[0].func == x
                \"\"\"
                return str(expr.args[0].func) + "'"*len(expr.args[1:])

            def _print_MyClass(self, expr):
                \"\"\"
                Print the characters of MyClass.s alternatively lower case and upper
                case
                \"\"\"
                s = ""
                i = 0
                for char in expr.s:
                    if i % 2 == 0:
                        s += char.lower()
                    else:
                        s += char.upper()
                    i += 1
                return s

        # Override the __str__ method of to use CustromStrPrinter
        Basic.__str__ = lambda self: CustomStrPrinter().doprint(self)
        # Demonstration of CustomStrPrinter:
        t = Symbol('t')
        x = Function('x')(t)
        dxdt = x.diff(t)            # dxdt is a Derivative instance
        d2xdt2 = dxdt.diff(t)       # dxdt2 is a Derivative instance
        ex = MyClass('I like both lowercase and upper case')

        print dxdt
        print d2xdt2
        print ex

    The output of the above code is::

        x'
        x''
        i lIkE BoTh lOwErCaSe aNd uPpEr cAsE

    By overriding Basic.__str__, we can customize the printing of anything that
    is subclassed from Basic.

    """

    _global_settings = {}

    _default_settings = {}

    emptyPrinter = str
    printmethod = None

    def __init__(self, settings=None):
        self._str = str

        self._settings = self._default_settings.copy()

        for key, val in self._global_settings.iteritems():
            if key in self._default_settings:
                self._settings[key] = val

        if settings is not None:
            self._settings.update(settings)

            if len(self._settings) > len(self._default_settings):
                for key in self._settings:
                    if key not in self._default_settings:
                        raise TypeError("Unknown setting '%s'." % key)

        # _print_level is the number of times self._print() was recursively
        # called. See StrPrinter._print_Float() for an example of usage
        self._print_level = 0

    @classmethod
    def set_global_settings(cls, **settings):
        """Set system-wide printing settings. """
        for key, val in settings.iteritems():
            if val is not None:
                cls._global_settings[key] = val

    @property
    def order(self):
        return self._settings['order']

    def doprint(self, expr):
        """Returns printer's representation for expr (as a string)"""
        return self._str(self._print(expr))

    def _print(self, expr, *args):
        """Internal dispatcher

        Tries the following concepts to print an expression:
            1. Let the object print itself if it knows how.
            2. Take the best fitting method defined in the printer.
            3. As fall-back use the emptyPrinter method for the printer.
        """
        self._print_level += 1
        try:
            # If the printer defines a name for a printing method
            # (Printer.printmethod) and the object knows for itself how it
            # should be printed, use that method.
            if (self.printmethod and hasattr(expr, self.printmethod)
                    and not isinstance(expr, BasicMeta)):
                return getattr(expr, self.printmethod)(self, *args)

            # See if the class of expr is known, or if one of its super
            # classes is known, and use that print function
            for cls in type(expr).__mro__:
                printmethod = '_print_' + cls.__name__
                if hasattr(self, printmethod):
                    return getattr(self, printmethod)(expr, *args)

            # Unknown object, fall back to the emptyPrinter.
            return self.emptyPrinter(expr)
        finally:
            self._print_level -= 1

    def _as_ordered_terms(self, expr, order=None):
        """A compatibility function for ordering terms in Add. """
        order = order or self.order

        if order == 'old':
            return sorted(Add.make_args(expr), key=cmp_to_key(Basic._compare_pretty))
        else:
            return expr.as_ordered_terms(order=order)