This file is indexed.

/usr/lib/python2.7/dist-packages/ZODB/broken.py is in python-zodb 1:3.10.7-1.

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
##############################################################################
#
# Copyright (c) 2004 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Broken object support

$Id$
"""

import sys
import persistent

import zope.interface

import ZODB.interfaces

broken_cache = {}

class Broken(object):
    """Broken object base class

       Broken objects are placeholders for objects that can no longer be
       created because their class has gone away.

       Broken objects don't really do much of anything, except hold their
       state.   The Broken class is used as a base class for creating
       classes in leu of missing classes::

         >>> Atall = type('Atall', (Broken, ), {'__module__': 'not.there'})

       The only thing the class can be used for is to create new objects::

         >>> Atall()
         <broken not.there.Atall instance>
         >>> Atall().__Broken_newargs__
         ()
         >>> Atall().__Broken_initargs__
         ()

         >>> Atall(1, 2).__Broken_newargs__
         (1, 2)
         >>> Atall(1, 2).__Broken_initargs__
         (1, 2)

         >>> a = Atall.__new__(Atall, 1, 2)
         >>> a
         <broken not.there.Atall instance>
         >>> a.__Broken_newargs__
         (1, 2)
         >>> a.__Broken_initargs__

       You can't modify broken objects::

         >>> a.x = 1
         Traceback (most recent call last):
         ...
         BrokenModified: Can't change broken objects

       But you can set their state::

         >>> a.__setstate__({'x': 1, })

       You can pickle broken objects::

         >>> r = a.__reduce__()
         >>> len(r)
         3
         >>> r[0] is rebuild
         True
         >>> r[1]
         ('not.there', 'Atall', 1, 2)
         >>> r[2]
         {'x': 1}

         >>> import cPickle
         >>> a2 = cPickle.loads(cPickle.dumps(a, 1))
         >>> a2
         <broken not.there.Atall instance>
         >>> a2.__Broken_newargs__
         (1, 2)
         >>> a2.__Broken_initargs__
         >>> a2.__Broken_state__
         {'x': 1}

       Cleanup::

         >>> broken_cache.clear()
       """

    zope.interface.implements(ZODB.interfaces.IBroken)

    __Broken_state__ = __Broken_initargs__ = None

    __name__ = 'broken object'

    def __new__(class_, *args):
        result = object.__new__(class_)
        result.__dict__['__Broken_newargs__'] = args
        return result

    def __init__(self, *args):
        self.__dict__['__Broken_initargs__'] = args

    def __reduce__(self):
        """We pickle broken objects in hope of being able to fix them later
        """
        return (rebuild,
                ((self.__class__.__module__, self.__class__.__name__)
                 + self.__Broken_newargs__),
                self.__Broken_state__,
                )

    def __setstate__(self, state):
        self.__dict__['__Broken_state__'] = state

    def __repr__(self):
        return "<broken %s.%s instance>" % (
            self.__class__.__module__, self.__class__.__name__)

    def __setattr__(self, name, value):
        raise BrokenModified("Can't change broken objects")

def find_global(modulename, globalname,
                # These are *not* optimizations. Callers can override these.
                Broken=Broken, type=type,
                ):
    """Find a global object, returning a broken class if it can't be found.

       This function looks up global variable in modules::

         >>> import sys
         >>> find_global('sys', 'path') is sys.path
         True

       If an object can't be found, a broken class is returned::

         >>> broken = find_global('ZODB.not.there', 'atall')
         >>> issubclass(broken, Broken)
         True
         >>> broken.__module__
         'ZODB.not.there'
         >>> broken.__name__
         'atall'

       Broken classes are cached::

         >>> find_global('ZODB.not.there', 'atall') is broken
         True

       If we "repair" a missing global::

         >>> class ZODBnotthere:
         ...     atall = []

         >>> sys.modules['ZODB.not'] = ZODBnotthere
         >>> sys.modules['ZODB.not.there'] = ZODBnotthere

       we can then get the repaired value::

         >>> find_global('ZODB.not.there', 'atall') is ZODBnotthere.atall
         True

       Of course, if we beak it again::

         >>> del sys.modules['ZODB.not']
         >>> del sys.modules['ZODB.not.there']

       we get the broken value::

         >>> find_global('ZODB.not.there', 'atall') is broken
         True

       Cleanup::

         >>> broken_cache.clear()
       """

    # short circuit common case:
    try:
        return getattr(sys.modules[modulename], globalname)
    except (AttributeError, KeyError):
        pass

    try:
        __import__(modulename)
    except ImportError:
        pass
    else:
        module = sys.modules[modulename]
        try:
            return getattr(module, globalname)
        except AttributeError:
            pass

    try:
        return broken_cache[(modulename, globalname)]
    except KeyError:
        pass

    class_ = type(globalname, (Broken, ), {'__module__': modulename})
    broken_cache[(modulename, globalname)] = class_
    return class_

def rebuild(modulename, globalname, *args):
    """Recreate a broken object, possibly recreating the missing class

       This functions unpickles broken objects::

         >>> broken = rebuild('ZODB.notthere', 'atall', 1, 2)
         >>> broken
         <broken ZODB.notthere.atall instance>
         >>> broken.__Broken_newargs__
         (1, 2)

       If we "repair" the brokenness::

         >>> class notthere: # fake notthere module
         ...     class atall(object):
         ...         def __new__(self, *args):
         ...             ob = object.__new__(self)
         ...             ob.args = args
         ...             return ob
         ...         def __repr__(self):
         ...             return 'atall %s %s' % self.args

         >>> sys.modules['ZODB.notthere'] = notthere

         >>> rebuild('ZODB.notthere', 'atall', 1, 2)
         atall 1 2

         >>> del sys.modules['ZODB.notthere']

       Cleanup::

         >>> broken_cache.clear()

       """
    class_ = find_global(modulename, globalname)
    return class_.__new__(class_, *args)

class BrokenModified(TypeError):
    """Attempt to modify a broken object
    """

class PersistentBroken(Broken, persistent.Persistent):
    r"""Persistent broken objects

        Persistent broken objects are used for broken objects that are
        also persistent.  In addition to having to track the original
        object data, they need to handle persistent meta data.

        Persistent broken classes are created from existing broken classes
        using the persistentBroken, function::

          >>> Atall = type('Atall', (Broken, ), {'__module__': 'not.there'})
          >>> PAtall = persistentBroken(Atall)

        (Note that we always get the *same* persistent broken class
         for a given broken class::

          >>> persistentBroken(Atall) is PAtall
          True

         )

        Persistent broken classes work a lot like broken classes::

          >>> a = PAtall.__new__(PAtall, 1, 2)
          >>> a
          <persistent broken not.there.Atall instance None>
          >>> a.__Broken_newargs__
          (1, 2)
          >>> a.__Broken_initargs__
          >>> a.x = 1
          Traceback (most recent call last):
          ...
          BrokenModified: Can't change broken objects

        Unlike regular broken objects, persistent broken objects keep
        track of persistence meta data:

          >>> a._p_oid = '\0\0\0\0****'
          >>> a
          <persistent broken not.there.Atall instance '\x00\x00\x00\x00****'>

        and persistent broken objects aren't directly picklable:

          >>> a.__reduce__()    # doctest: +NORMALIZE_WHITESPACE
          Traceback (most recent call last):
          ...
          BrokenModified: 
          <persistent broken not.there.Atall instance '\x00\x00\x00\x00****'>

        but you can get their state:

          >>> a.__setstate__({'y': 2})
          >>> a.__getstate__()
          {'y': 2}

       Cleanup::

         >>> broken_cache.clear()

        """

    def __new__(class_, *args):
        result = persistent.Persistent.__new__(class_)
        result.__dict__['__Broken_newargs__'] = args
        return result

    def __reduce__(self, *args):
        raise BrokenModified(self)

    def __getstate__(self):
        return self.__Broken_state__

    def __setattr__(self, name, value):
        if name.startswith('_p_'):
            persistent.Persistent.__setattr__(self, name, value)
        else:
            raise BrokenModified("Can't change broken objects")

    def __repr__(self):
        return "<persistent broken %s.%s instance %r>" % (
            self.__class__.__module__, self.__class__.__name__,
            self._p_oid)

    def __getnewargs__(self):
        return self.__Broken_newargs__

def persistentBroken(class_):
    try:
        return class_.__dict__['__Broken_Persistent__']
    except KeyError:
        class_.__Broken_Persistent__ = (
            type(class_.__name__,
                 (PersistentBroken, class_),
                 {'__module__': class_.__module__},
                 )
            )
        return class_.__dict__['__Broken_Persistent__']