This file is indexed.

/usr/share/pyshared/django_evolution/diff.py is in python-django-evolution 0.6.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
from django.db import models
from django.db.models.fields.related import *

from django_evolution import EvolutionException
from django_evolution.mutations import DeleteField, AddField, DeleteModel, ChangeField
from django_evolution.signature import ATTRIBUTE_DEFAULTS

try:
    set
except ImportError:
    from sets import Set as set #Python 2.3 Fallback


class NullFieldInitialCallback(object):
    def __init__(self, app, model, field):
        self.app = app
        self.model = model
        self.field = field

    def __repr__(self):
        return '<<USER VALUE REQUIRED>>'

    def __call__(self):
        raise EvolutionException(
            "Cannot use hinted evolution: AddField or ChangeField mutation "
            "for '%s.%s' in '%s' requires user-specified initial value."
            % (self.model, self.field, self.app))


def get_initial_value(app_label, model_name, field_name):
    """Derive an initial value for a field.

    If a default has been provided on the field definition or the field allows
    for an empty string, that value will be used. Otherwise, a placeholder
    callable will be used. This callable cannot actually be used in an
    evolution, but will indicate that user input is required.
    """
    model = models.get_model(app_label, model_name)
    field = model._meta.get_field(field_name)

    if field and (field.has_default() or
                  (field.empty_strings_allowed and field.blank)):
        return field.get_default()

    return NullFieldInitialCallback(app_label, model_name, field_name)


class Diff(object):
    """
    A diff between two model signatures.

    The resulting diff is contained in two attributes:

    self.changed = {
        app_label: {
            'changed': {
                model_name : {
                    'added': [ list of added field names ]
                    'deleted': [ list of deleted field names ]
                    'changed': {
                        field: [ list of modified property names ]
                    }
                }
            'deleted': [ list of deleted model names ]
        }
    }
    self.deleted = {
        app_label: [ list of models in deleted app ]
    }
    """
    def __init__(self, original, current):
        self.original_sig = original
        self.current_sig = current

        self.changed = {}
        self.deleted = {}

        if self.original_sig.get('__version__', 1) != 1:
            raise EvolutionException(
                "Unknown version identifier in original signature: %s",
                self.original_sig['__version__'])

        if self.current_sig.get('__version__', 1) != 1:
            raise EvolutionException(
                "Unknown version identifier in target signature: %s",
                self.current_sig['__version__'])

        for app_name, old_app_sig in original.items():
            if app_name == '__version__':
                # Ignore the __version__ tag
                continue

            new_app_sig = self.current_sig.get(app_name, None)

            if new_app_sig is None:
                # App has been deleted
                self.deleted[app_name] = old_app_sig.keys()
                continue

            for model_name, old_model_sig in old_app_sig.items():
                new_model_sig = new_app_sig.get(model_name, None)

                if new_model_sig is None:
                    # Model has been deleted
                    self.changed.setdefault(app_name,
                        {}).setdefault('deleted',
                        []).append(model_name)
                    continue

                old_fields = old_model_sig['fields']
                new_fields = new_model_sig['fields']

                # Look for deleted or modified fields
                for field_name, old_field_data in old_fields.items():
                    new_field_data = new_fields.get(field_name, None)

                    if new_field_data is None:
                        # Field has been deleted
                        self.changed.setdefault(app_name,
                            {}).setdefault('changed',
                            {}).setdefault(model_name,
                            {}).setdefault('deleted',
                            []).append(field_name)
                        continue

                    properties = set(old_field_data.keys())
                    properties.update(new_field_data.keys())

                    for prop in properties:
                        old_value = old_field_data.get(prop,
                            ATTRIBUTE_DEFAULTS.get(prop, None))
                        new_value = new_field_data.get(prop,
                            ATTRIBUTE_DEFAULTS.get(prop, None))

                        if old_value != new_value:
                            try:
                                if (prop == 'field_type' and
                                    (old_value().get_internal_type() ==
                                     new_value().get_internal_type())):
                                    continue
                            except TypeError:
                                pass

                            # Field has been changed
                            self.changed.setdefault(app_name,
                                {}).setdefault('changed',
                                {}).setdefault(model_name,
                                {}).setdefault('changed',
                                {}).setdefault(field_name,[]).append(prop)

                # Look for added fields
                new_fields = new_model_sig['fields']

                for field_name, new_field_data in new_fields.items():
                    old_field_data = old_fields.get(field_name, None)

                    if old_field_data is None:
                        self.changed.setdefault(app_name,
                            {}).setdefault('changed',
                            {}).setdefault(model_name,
                            {}).setdefault('added',
                            []).append(field_name)

    def is_empty(self, ignore_apps=True):
        """Is this an empty diff? i.e., is the source and target the same?

        Set 'ignore_apps=False' if you wish to ignore changes caused by
        deleted applications. This is used when you don't purge deleted
        applications during an evolve.
        """
        if ignore_apps:
            return not self.changed
        else:
            return not self.deleted and not self.changed

    def __str__(self):
        "Output an application signature diff in a human-readable format"
        lines = []

        for app_label in self.deleted:
            lines.append('The application %s has been deleted' % app_label)

        for app_label, app_changes in self.changed.items():
            for model_name in app_changes.get('deleted', {}):
                lines.append('The model %s.%s has been deleted'
                             % (app_label, model_name))

            for model_name, change in app_changes.get('changed', {}).items():
                lines.append('In model %s.%s:' % (app_label, model_name))

                for field_name in change.get('added',[]):
                    lines.append("    Field '%s' has been added" % field_name)

                for field_name in change.get('deleted',[]):
                    lines.append("    Field '%s' has been deleted" % field_name)

                for field_name,field_change in change.get('changed',{}).items():
                    lines.append("    In field '%s':" % field_name)

                    for prop in field_change:
                        lines.append("        Property '%s' has changed" % prop)

        return '\n'.join(lines)

    def evolution(self):
        "Generate an evolution that would neutralize the diff"
        mutations = {}

        for app_label, app_changes in self.changed.items():
            for model_name, change in app_changes.get('changed', {}).items():
                for field_name in change.get('added',{}):
                    field_sig = self.current_sig[app_label][model_name]['fields'][field_name]
                    add_params = [(key,field_sig[key])
                                    for key in field_sig.keys()
                                    if key in ATTRIBUTE_DEFAULTS.keys()]
                    add_params.append(('field_type', field_sig['field_type']))

                    if (field_sig['field_type'] != models.ManyToManyField and
                        not field_sig.get('null', ATTRIBUTE_DEFAULTS['null'])):
                        add_params.append(
                            ('initial',
                             get_initial_value(app_label, model_name,
                                               field_name)))

                    if 'related_model' in field_sig:
                        add_params.append(('related_model',
                                           '%s' % field_sig['related_model']))

                    mutations.setdefault(app_label,[]).append(
                        AddField(model_name, field_name, **dict(add_params)))

                for field_name in change.get('deleted',[]):
                    mutations.setdefault(app_label,[]).append(
                        DeleteField(model_name, field_name))

                for field_name,field_change in change.get('changed',{}).items():
                    changed_attrs = {}
                    current_field_sig = self.current_sig[app_label][model_name]['fields'][field_name]

                    for prop in field_change:
                        if prop == 'related_model':
                            changed_attrs[prop] = current_field_sig[prop]
                        else:
                            changed_attrs[prop] = \
                                current_field_sig.get(prop,
                                                      ATTRIBUTE_DEFAULTS[prop])

                    if (changed_attrs.has_key('null') and
                        current_field_sig['field_type'] !=
                            models.ManyToManyField and
                        not current_field_sig.get('null',
                                                  ATTRIBUTE_DEFAULTS['null'])):
                        changed_attrs['initial'] = \
                            get_initial_value(app_label, model_name, field_name)

                    mutations.setdefault(app_label,[]).append(
                        ChangeField(model_name, field_name, **changed_attrs))

            for model_name in app_changes.get('deleted',{}):
                mutations.setdefault(app_label,[]).append(
                    DeleteModel(model_name))

        return mutations