This file is indexed.

/usr/share/pyshared/translationstring/__init__.py is in python-translationstring 1.1-4.

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
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
import re
from gettext import NullTranslations
from translationstring.compat import text_type
from translationstring.compat import string_types
from translationstring.compat import PY3

NAME_RE = r"[a-zA-Z][-a-zA-Z0-9_]*"

_interp_regex = re.compile(r'(?<!\$)(\$(?:(%(n)s)|{(%(n)s)}))'
    % ({'n': NAME_RE}))

class TranslationString(text_type):
    """
    The constructor for a :term:`translation string`.  A translation
    string is a Unicode-like object that has some extra metadata.

    This constructor accepts one required argument named ``msgid``.
    ``msgid`` must be the :term:`message identifier` for the
    translation string.  It must be a ``unicode`` object or a ``str``
    object encoded in the default system encoding.

    Optional keyword arguments to this object's constructor include
    ``domain``, ``default``, and ``mapping``.

    ``domain`` represents the :term:`translation domain`.  By default,
    the translation domain is ``None``, indicating that this
    translation string is associated with the default translation
    domain (usually ``messages``).

    ``default`` represents an explicit *default text* for this
    translation string.  Default text appears when the translation
    string cannot be translated.  Usually, the ``msgid`` of a
    translation string serves double duty as as its default text.
    However, using this option you can provide a different default
    text for this translation string.  This feature is useful when the
    default of a translation string is too complicated or too long to
    be used as a message identifier. If ``default`` is provided, it
    must be a ``unicode`` object or a ``str`` object encoded in the
    default system encoding (usually means ASCII).  If ``default`` is
    ``None`` (its default value), the ``msgid`` value used by this
    translation string will be assumed to be the value of ``default``.

    ``mapping``, if supplied, must be a dictionary-like object which
    represents the replacement values for any :term:`translation
    string` *replacement marker* instances found within the ``msgid``
    (or ``default``) value of this translation string.

    After a translation string is constructed, it behaves like most
    other ``unicode`` objects; its ``msgid`` value will be displayed
    when it is treated like a ``unicode`` object.  Only when its
    ``ugettext`` method is called will it be translated.

    Its default value is available as the ``default`` attribute of the
    object, its :term:`translation domain` is available as the
    ``domain`` attribute, and the ``mapping`` is available as the
    ``mapping`` attribute.  The object otherwise behaves much like a
    Unicode string.
    """
    __slots__ = ('domain', 'default', 'mapping')

    def __new__(self, msgid, domain=None, default=None, mapping=None):

        # NB: this function should never never lose the *original
        # identity* of a non-``None`` but empty ``default`` value
        # provided to it.  See the comment in ChameleonTranslate.

        self = text_type.__new__(self, msgid)
        if isinstance(msgid, self.__class__):
            domain = domain or msgid.domain and msgid.domain[:]
            default = default or msgid.default and msgid.default[:]
            mapping = mapping or msgid.mapping and msgid.mapping.copy()
            msgid = text_type(msgid)
        self.domain = domain
        if default is None:
            default = text_type(msgid)
        self.default = default
        self.mapping = mapping
        return self

    def __mod__(self, options):
        """Create a new TranslationString instance with an updated mapping.
        This makes it possible to use the standard python %-style string
        formatting with translatable strings. Only dictionary
        arguments are supported.
        """
        if not isinstance(options, dict):
            raise ValueError(
                    'Can only interpolate translationstring '
                    'with dictionaries.')
        if self.mapping:
            mapping = self.mapping.copy()
            mapping.update(options)
        else:
            mapping = options.copy()
        return TranslationString(self, mapping=mapping)

    def interpolate(self, translated=None):
        """ Interpolate the value ``translated`` which is assumed to
        be a Unicode object containing zero or more *replacement
        markers* (``${foo}`` or ``${bar}``) using the ``mapping``
        dictionary attached to this instance.  If the ``mapping``
        dictionary is empty or ``None``, no interpolation is
        performed.

        If ``translated`` is ``None``, interpolation will be performed
        against the ``default`` value.
        """
        if translated is None:
            translated = self.default

        # NB: this function should never never lose the *original
        # identity* of a non-``None`` but empty ``default`` value it
        # is provided.  If (translated == default) , it should return the
        # *orignal* default, not a derivation.  See the comment below in
        # ChameleonTranslate.

        if self.mapping and translated:
            def replace(match):
                whole, param1, param2 = match.groups()
                return text_type(self.mapping.get(param1 or param2, whole))
            translated = _interp_regex.sub(replace, translated)

        return translated

    def __reduce__(self):
        return self.__class__, self.__getstate__()

    def __getstate__(self):
        return text_type(self), self.domain, self.default, self.mapping

def TranslationStringFactory(domain):
    """ Create a factory which will generate translation strings
    without requiring that each call to the factory be passed a
    ``domain`` value.  A single argument is passed to this class'
    constructor: ``domain``.  This value will be used as the
    ``domain`` values of :class:`translationstring.TranslationString`
    objects generated by the ``__call__`` of this class.  The
    ``msgid``, ``mapping``, and ``default`` values provided to the
    ``__call__`` method of an instance of this class have the meaning
    as described by the constructor of the
    :class:`translationstring.TranslationString`"""
    def create(msgid, mapping=None, default=None):
        """ Provided a msgid (Unicode object or :term:`translation
        string`) and optionally a mapping object, and a *default
        value*, return a :term:`translation string` object."""
        return TranslationString(msgid, domain=domain, default=default,
                                 mapping=mapping)
    return create

def ChameleonTranslate(translator):
    """
    When necessary, use the result of calling this function as a
    Chameleon template 'translate' function (e.g. the ``translate``
    argument to the ``chameleon.zpt.template.PageTemplate``
    constructor) to allow our translation machinery to drive template
    translation.  A single required argument ``translator`` is
    passsed.  The ``translator`` provided should be a callable which
    accepts a single argument ``translation_string`` ( a
    :class:`translationstring.TranslationString` instance) which
    returns a ``unicode`` object as a translation.  ``translator`` may
    also optionally be ``None``, in which case no translation is
    performed (the ``msgid`` or ``default`` value is returned
    untranslated).
    """
    def translate(msgid, domain=None, mapping=None, context=None,
                 target_language=None, default=None):

        # NB: note that both TranslationString._init__ and
        # TranslationString.interpolate are careful to never lose the
        # *identity* of an empty but non-``None`` ``default`` value we
        # provide to them.  For example, neither of those functions
        # are permitted to run an empty but non-``None`` ``default``
        # through ``unicode`` and throw the original default value
        # away afterwards.

        # This has a dubious cause: for Chameleon API reasons we must
        # ensure that, after translation, if ( (translated == msgid)
        # and (not default) and (default is not None) ) that we return
        # the ``default`` value provided to us *unmodified*, because
        # Chameleon uses it as a sentinel (it compares the return
        # value of this function by identity to what it passed in as
        # ``default``; this marker is a
        # chameleon.core.i18n.StringMarker instance, a subclass of str
        # that == '').  This is, of course, totally absurd, because
        # Chameleon *also* wants us to use ``default`` as the input to
        # a translation string in some cases, and maintaining the
        # identity of this object through translation operations isn't
        # a contract it spells out in its docs.

        # Chameleon's use of ``default`` to represent both a sentinel
        # and input to a translation string is a Chameleon i18n
        # extensibility design bug.  Until we overhaul its hook point
        # for translation extensibility, we need to appease it by
        # preserving ``default`` in the aforementioned case.  So we
        # spray these indignant comments all over this module. ;-)

        if not isinstance(msgid, string_types):
            if msgid is not None:
                msgid = text_type(msgid)
            return msgid

        tstring = msgid

        if not hasattr(tstring, 'interpolate'):
            tstring = TranslationString(msgid, domain, default, mapping)

        if translator is None:
            result = tstring.interpolate()
        else:
            result = translator(tstring)

        return result

    return translate

def ugettext_policy(translations, tstring, domain):
    """ A translator policy function which unconditionally uses the
    ``ugettext`` API on the translations object."""

    if PY3: # pragma: no cover
        _gettext = translations.gettext
    else: # pragma: no cover
        _gettext = translations.ugettext

    return _gettext(tstring)

def dugettext_policy(translations, tstring, domain):
    """ A translator policy function which assumes the use of a
    :class:`babel.support.Translations` translations object, which
    supports the dugettext API; fall back to ugettext."""
    if domain is None:
        default_domain = getattr(translations, 'domain', None) or 'messages'
        domain = getattr(tstring, 'domain', None) or default_domain
    if getattr(translations, 'dugettext', None) is not None:
        return translations.dugettext(domain, tstring)

    if PY3: # pragma: no cover
        _gettext = translations.gettext
    else: # pragma: no cover
        _gettext = translations.ugettext

    return _gettext(tstring)

def Translator(translations=None, policy=None):
    """
    Return a translator object based on the ``translations`` and
    ``policy`` provided.  ``translations`` should be an object
    supporting *at least* the Python :class:`gettext.NullTranslations`
    API but ideally the :class:`babel.support.Translations` API, which
    has support for domain lookups like dugettext.

    ``policy`` should be a callable which accepts three arguments:
    ``translations``, ``tstring`` and ``domain``.  It must perform the
    actual translation lookup.  If ``policy`` is ``None``, the
    :func:`translationstring.dugettext_policy` policy will be used.

    The callable returned accepts three arguments: ``tstring``
    (required), ``domain`` (optional) and ``mapping`` (optional).
    When called, it will translate the ``tstring`` translation string
    to a ``unicode`` object using the ``translations`` provided.  If
    ``translations`` is ``None``, the result of interpolation of the
    default value is returned.  The optional ``domain`` argument can
    be used to specify or override the domain of the ``tstring``
    (useful when ``tstring`` is a normal string rather than a
    translation string).  The optional ``mapping`` argument can
    specify or override the ``tstring`` interpolation mapping, useful
    when the ``tstring`` argument is a simple string instead of a
    translation string.
    """
    if policy is None:
        policy = dugettext_policy
    def translator(tstring, domain=None, mapping=None):
        if not hasattr(tstring, 'interpolate'):
            tstring = TranslationString(tstring, domain=domain, mapping=mapping)
        elif mapping:
            if tstring.mapping:
                new_mapping = tstring.mapping.copy()
                new_mapping.update(mapping)
            else:
                new_mapping = mapping
            tstring = TranslationString(tstring, domain=domain, mapping=new_mapping)
        translated = tstring
        if translations is not None:
            translated = policy(translations, tstring, domain)
        if translated == tstring:
            translated = tstring.default
        if translated and '$' in translated and tstring.mapping:
            translated = tstring.interpolate(translated)
        return translated
    return translator

def ungettext_policy(translations, singular, plural, n, domain):
    """ A pluralizer policy function which unconditionally uses the
    ``ungettext`` API on the translations object."""

    if PY3: # pragma: no cover
        _gettext = translations.ngettext
    else: # pragma: no cover
        _gettext = translations.ungettext

    return _gettext(singular, plural, n)

def dungettext_policy(translations, singular, plural, n, domain):
    """ A pluralizer policy function which assumes the use of the
    :class:`babel.support.Translations` class, which supports the
    dungettext API; falls back to ungettext."""

    default_domain = getattr(translations, 'domain', None) or 'messages'
    domain = domain or default_domain

    if getattr(translations, 'dungettext', None) is not None:
        return translations.dungettext(domain, singular, plural, n)

    if PY3: # pragma: no cover
        _gettext = translations.ngettext
    else: # pragma: no cover
        _gettext = translations.ungettext

    return _gettext(singular, plural, n)

def Pluralizer(translations=None, policy=None):
    """
    Return a pluralizer object based on the ``translations`` and
    ``policy`` provided.  ``translations`` should be an object
    supporting *at least* the Python :class:`gettext.NullTranslations`
    API but ideally the :class:`babel.support.Translations` API, which
    has support for domain lookups like dugettext.

    ``policy`` should be a callable which accepts five arguments:
    ``translations``, ``singular`` and ``plural``, ``n`` and
    ``domain``.  It must perform the actual pluralization lookup.  If
    ``policy`` is ``None``, the
    :func:`translationstring.dungettext_policy` policy will be used.

    The object returned will be a callable which has the following
    signature::

        def pluralizer(singular, plural, n, domain=None, mapping=None):
            ...

    The ``singular`` and ``plural`` objects passed may be translation
    strings or unicode strings.  ``n`` represents the number of
    elements.  ``domain`` is the translation domain to use to do the
    pluralization, and ``mapping`` is the interpolation mapping that
    should be used on the result.  Note that if the objects passed are
    translation strings, their domains and mappings are ignored.  The
    domain and mapping arguments must be used instead.  If the ``domain`` is
    not supplied, a default domain is used (usually ``messages``).
    """

    if policy is None:
        policy = dungettext_policy
    if translations is None:
        translations = NullTranslations()
    def pluralizer(singular, plural, n, domain=None, mapping=None):
        """ Pluralize this object """
        translated = text_type(
            policy(translations, singular, plural, n, domain))
        if translated and '$' in translated and mapping:
            return TranslationString(translated, mapping=mapping).interpolate()
        return translated
    return pluralizer