Пример #1
0
def write_create_function(model, stream):
    fields = [
        f for f in model._meta.get_fields() if f.concrete and f.model is model
    ]
    for f in fields:
        if getattr(f, 'auto_now_add', False):
            # raise Exception("%s.%s.auto_now_add is True : values will be lost!" % (
            #     full_model_name(model), f.name))
            logger.warning("%s.%s.auto_now_add is True : values will be lost!",
                           full_model_name(model), f.name)
            # f.auto_now_add = False
    stream.write('def create_%s(%s):\n' % (model._meta.db_table, ', '.join([
        f.attname for f in fields if not getattr(f, '_lino_babel_field', False)
    ])))
    for f in fields:
        if f.model is model:
            pre = '    '
        else:
            pre = '#   '
        if isinstance(f, models.DecimalField):
            stream.write(pre + 'if %s is not None: %s = Decimal(%s)\n' %
                         (f.attname, f.attname, f.attname))
        elif isinstance(f, ChoiceListField):
            lstname = 'settings.SITE.models.{0}.{1}'.format(
                f.choicelist.app_label, f.choicelist.__name__)
            ln = pre + 'if {0}: {0} = {1}.get_by_value({0})\n'
            ln = '#' + ln  # no longer needed but maybe useful as a comment
            stream.write(ln.format(f.attname, lstname))
        elif is_pointer_to_contenttype(f):
            stream.write(pre + '%s = new_content_type_id(%s)\n' %
                         (f.attname, f.attname))

    if model._meta.parents:
        if len(model._meta.parents) != 1:
            msg = "%s : model._meta.parents is %r" % (model,
                                                      model._meta.parents)
            raise Exception(msg)
        pm, pf = list(model._meta.parents.items())[0]
        fields = [f for f in fields if f != pf]

    stream.write("    kw = dict()\n")
    for f in fields:
        if f.model is model:
            pre = '    '
        else:
            pre = '#   '
        if getattr(f, '_lino_babel_field', False):
            continue
        elif isinstance(f, (BabelCharField, BabelTextField)):
            stream.write(pre + 'if %s is not None: kw.update(bv2kw(%r,%s))\n' %
                         (f.attname, f.attname, f.attname))
        else:
            stream.write(pre + 'kw.update(%s=%s)\n' % (f.attname, f.attname))

    if model._meta.parents:
        stream.write('    return create_mti_child(%s, %s, %s, **kw)\n\n' %
                     (full_model_name(
                         pm, '_'), pf.attname, full_model_name(model, '_')))
    else:
        stream.write('    return %s(**kw)\n\n' % full_model_name(model, '_'))
Пример #2
0
    def finalize(self):
        """
        """
        self.flush_deferred_objects()

        if len(self.AFTER_LOAD_HANDLERS):
            logger.info("Finalize %d after_load handlers",
                        len(self.AFTER_LOAD_HANDLERS))

        for h in self.AFTER_LOAD_HANDLERS:
            logger.info("Running after_load handler %s", h.__doc__)
            h(self)

        # logger.info("Loaded %d objects", self.count_objects)

        if self.save_later:
            count = 0
            s = ''
            for model, msg_objects in list(self.save_later.items()):
                for msg, objects in list(msg_objects.items()):
                    if False:  # detailed content of the first object
                        s += "\n- %s %s (%d object(s), e.g. %s)" % (
                            full_model_name(model), msg, len(objects),
                            obj2str(objects[0].object, force_detailed=True))
                    else:  # pk of all objects
                        s += "\n- %s %s (%d object(s) with primary key %s)" % (
                            full_model_name(model), msg, len(objects),
                            ', '.join([str(o.object.pk) for o in objects]))
                    count += len(objects)
            msg = "Abandoning with {} unsaved instances:{}"
            logger.warning(msg.format(count, s))
Пример #3
0
    def finalize(self):
        """
        """
        self.flush_deferred_objects()

        if len(self.AFTER_LOAD_HANDLERS):
            logger.info(
                "Finalize %d after_load handlers",
                len(self.AFTER_LOAD_HANDLERS))

        for h in self.AFTER_LOAD_HANDLERS:
            logger.info("Running after_load handler %s", h.__doc__)
            h(self)

        logger.info("Loaded %d objects", self.count_objects)
    
        if self.save_later:
            count = 0
            s = ''
            for model, msg_objects in list(self.save_later.items()):
                for msg, objects in list(msg_objects.items()):
                    if False:  # detailed content of the first object
                        s += "\n- %s %s (%d object(s), e.g. %s)" % (
                            full_model_name(model), msg, len(objects),
                            obj2str(objects[0].object, force_detailed=True))
                    else:  # pk of all objects
                        s += "\n- %s %s (%d object(s) with primary key %s)" % (
                            full_model_name(model), msg, len(objects),
                            ', '.join([str(o.object.pk) for o in objects]))
                    count += len(objects)

            msg = "Abandoning with %d unsaved instances:%s" % (count, s)
            logger.warning(msg)
Пример #4
0
    def sort_models(self, unsorted):
        sorted = []
        hope = True
        """
        20121120 if we convert the list to a set, we gain some performance
        for the ``in`` tests, but we obtain a random sorting order for all
        independent models, making the double dump test less evident.
        """
        #~ 20121120 unsorted = set(unsorted)
        while len(unsorted) and hope:
            hope = False
            guilty = dict()
            #~ puts("hope for", [m.__name__ for m in unsorted])
            for model in unsorted:
                deps = set([
                    f.rel.model for f in model._meta.fields
                    if f.rel is not None and f.rel.model is not model
                    and f.rel.model in unsorted
                ])
                #~ deps += [m for m in model._meta.parents.keys()]
                for m in sorted:
                    if m in deps:
                        deps.remove(m)
                if len(deps):
                    guilty[model] = deps
                else:
                    sorted.append(model)
                    unsorted.remove(model)
                    hope = True
                    break

                #~ ok = True
                #~ for d in deps:
                #~ if d in unsorted:
                #~ ok = False
                #~ if ok:
                #~ sorted.append(model)
                #~ unsorted.remove(model)
                #~ hope = True
                #~ break
                #~ else:
                #~ guilty[model] = deps
                #~ print model.__name__, "depends on", [m.__name__ for m in deps]
        if unsorted:
            assert len(unsorted) == len(guilty)
            msg = "There are %d models with circular dependencies :\n" % len(
                unsorted)
            msg += "- " + '\n- '.join([
                full_model_name(m) + ' (depends on %s)' %
                ", ".join([full_model_name(d) for d in deps])
                for m, deps in list(guilty.items())
            ])
            if False:
                # we don't write them to the .py file because they are
                # in random order which would cause false ddt to fail
                for ln in msg.splitlines():
                    self.stream.write('\n# %s' % ln)
            logger.info(msg)
            sorted.extend(unsorted)
        return sorted
Пример #5
0
    def sort_models(self, unsorted):
        sorted = []
        hope = True
        """
        20121120 if we convert the list to a set, we gain some performance
        for the ``in`` tests, but we obtain a random sorting order for all
        independent models, making the double dump test less evident.
        """
        #~ 20121120 unsorted = set(unsorted)
        while len(unsorted) and hope:
            hope = False
            guilty = dict()
            #~ puts("hope for", [m.__name__ for m in unsorted])
            for model in unsorted:
                deps = set([f.rel.model
                            for f in model._meta.fields
                            if f.rel is not None and f.rel.model is not model and f.rel.model in unsorted])
                #~ deps += [m for m in model._meta.parents.keys()]
                for m in sorted:
                    if m in deps:
                        deps.remove(m)
                if len(deps):
                    guilty[model] = deps
                else:
                    sorted.append(model)
                    unsorted.remove(model)
                    hope = True
                    break

                #~ ok = True
                #~ for d in deps:
                    #~ if d in unsorted:
                        #~ ok = False
                #~ if ok:
                    #~ sorted.append(model)
                    #~ unsorted.remove(model)
                    #~ hope = True
                    #~ break
                #~ else:
                    #~ guilty[model] = deps
                #~ print model.__name__, "depends on", [m.__name__ for m in deps]
        if unsorted:
            assert len(unsorted) == len(guilty)
            msg = "There are %d models with circular dependencies :\n" % len(
                unsorted)
            msg += "- " + '\n- '.join([
                full_model_name(m) + ' (depends on %s)' % ", ".join([
                    full_model_name(d) for d in deps])
                for m, deps in list(guilty.items())])
            if False:
                # we don't write them to the .py file because they are
                # in random order which would cause false ddt to fail
                for ln in msg.splitlines():
                    self.stream.write('\n# %s' % ln)
            logger.info(msg)
            sorted.extend(unsorted)
        return sorted
Пример #6
0
 def add(name):
     for f, qs in getattr(self, name):
         if qs.count() > 0:
             lst.append(
                 "- %d %s %s rows using %s : %s"
                 % (qs.count(), name, full_model_name(f.model), f.name, " ".join([str(o.pk) for o in qs]))
             )
Пример #7
0
 def value2string(self, obj, field):
     if isinstance(field, (BabelCharField, BabelTextField)):
         # ~ return repr([repr(x) for x in dbutils.field2args(obj,field.name)])
         return repr(settings.SITE.field2args(obj, field.name))
     value = field._get_val_from_obj(obj)
     # Protected types (i.e., primitives like None, numbers, dates,
     # and Decimals) are passed through as is. All other values are
     # converted to string first.
     if value is None:
         # ~ if value is None or value is NOT_PROVIDED:
         return "None"
     if isinstance(field, models.DateTimeField):
         d = value
         return "dt(%d,%d,%d,%d,%d,%d)" % (d.year, d.month, d.day, d.hour, d.minute, d.second)
     if isinstance(field, models.TimeField):
         d = value
         return "time(%d,%d,%d)" % (d.hour, d.minute, d.second)
     if is_pointer_to_contenttype(field):
         ContentType = settings.SITE.modules.contenttypes.ContentType
         ct = ContentType.objects.get(pk=value)
         return full_model_name(ct.model_class(), "_")
         # ~ return "'"+full_model_name(ct.model_class())+"'"
         # ~ return repr(tuple(value.app_label,value.model))
     if isinstance(field, models.DateField):
         d = value
         return "date(%d,%d,%d)" % (d.year, d.month, d.day)
         # ~ return 'i2d(%4d%02d%02d)' % (d.year,d.month,d.day)
     if isinstance(value, (float, Decimal)):
         return repr(str(value))
     if isinstance(value, int):
         return str(value)
     return repr(field.value_to_string(obj))
Пример #8
0
    def __init__(self, model, **kw):

        fields = dict(
            #~ merge_from=models.ForeignKey(model,verbose_name=_("Merge...")),
            merge_to=models.ForeignKey(model,
                                       verbose_name=_("into..."),
                                       blank=False,
                                       null=False),
            reason=models.CharField(_("Reason"), max_length=100)
            #~ notify=models.BooleanField(_("Send notifications"))
        )

        keep_volatiles = []

        # logger.info("20160621 MergeAction for %s", model)
        # logger.info("20160621 MergeAction for %s : _lino_ddh.fklist is %s",
        #             model, model._lino_ddh.fklist)
        for m, fk in traverse_ddh_fklist(model):
            if fk.name in m.allow_cascaded_delete:
                fieldname = full_model_name(m, '_')
                if fieldname not in keep_volatiles:
                    keep_volatiles.append(fieldname)
                    fields[fieldname] = models.BooleanField(
                        m._meta.verbose_name_plural, default=False)
                # logger.info(
                #     "20160621 %r in %r", fk.name, m.allow_cascaded_delete)

        layout = dict()
        if len(keep_volatiles) == 0:
            width = 50
            main = """
            merge_to
            reason
            """
        else:
            COLCOUNT = 2
            width = 70
            if len(keep_volatiles) > COLCOUNT:
                tpl = ''
                for i, name in enumerate(keep_volatiles):
                    if i % COLCOUNT == 0:
                        tpl += '\n'
                    else:
                        tpl += ' '
                    tpl += name
            else:
                tpl = ' '.join(keep_volatiles)
            main = """
            merge_to
            keep_volatiles
            reason
            """
            layout.update(keep_volatiles=layouts.Panel(
                tpl, label=_("Also reassign volatile related objects")))

        layout.update(window_size=(width, 'auto'))
        kw.update(parameters=fields,
                  params_layout=layouts.Panel(main, **layout))

        super(MergeAction, self).__init__(**kw)
Пример #9
0
 def value2string(self, obj, field):
     if isinstance(field, (BabelCharField, BabelTextField)):
         return repr(settings.SITE.field2args(obj, field.name))
     value = field._get_val_from_obj(obj)
     # Protected types (i.e., primitives like None, numbers, dates,
     # and Decimals) are passed through as is. All other values are
     # converted to string first.
     if value is None:
         #~ if value is None or value is NOT_PROVIDED:
         return 'None'
     if isinstance(field, models.DateTimeField):
         d = value
         return 'dt(%d,%d,%d,%d,%d,%d)' % (d.year, d.month, d.day, d.hour,
                                           d.minute, d.second)
     if isinstance(field, models.TimeField):
         d = value
         return 'time(%d,%d,%d)' % (d.hour, d.minute, d.second)
     if isinstance(field,
                   models.ForeignKey) and field.rel.to is ContentType:
         ct = ContentType.objects.get(pk=value)
         return full_model_name(ct.model_class(), '_')
         #~ return "'"+full_model_name(ct.model_class())+"'"
         #~ return repr(tuple(value.app_label,value.model))
     if isinstance(field, models.DateField):
         d = value
         return 'date(%d,%d,%d)' % (d.year, d.month, d.day)
         #~ return 'i2d(%4d%02d%02d)' % (d.year,d.month,d.day)
     if isinstance(value, (float, Decimal)):
         return repr(str(value))
     if isinstance(value, (int, long)):
         return str(value)
     return repr(field.value_to_string(obj))
Пример #10
0
    def test_controllables(self):
        found = []
        for M in rt.models_by_base(Controllable):
            found.append(full_model_name(M))
        expected = """cal.Event cal.Task excerpts.Excerpt
        notes.Note notifier.Notification outbox.Attachment outbox.Mail
        plausibility.Problem uploads.Upload""".split()
        self.assertEqual(found, expected)

        Person = rt.modules.contacts.Person
        Note = rt.modules.notes.Note
        Excerpt = rt.modules.excerpts.Excerpt
        ExcerptType = rt.modules.excerpts.ExcerptType
        ContentType = rt.modules.contenttypes.ContentType
        self.assertEqual(len(Person.allow_cascaded_delete), 0)
        self.assertEqual(len(Note.allow_cascaded_delete), 0)
        self.assertEqual(len(Excerpt.allow_cascaded_delete), 1)

        doe = create(Person, first_name="John", last_name="Doe")
        note = create(Note, owner=doe, body="John Doe is a fink!")
        ct = ContentType.objects.get_for_model(Note)
        etype = create(ExcerptType, name="Note", content_type=ct)
        excerpt = create(Excerpt, owner=note,
                         excerpt_type=etype)

        self.assertEqual(Person.objects.count(), 1)
        self.assertEqual(Note.objects.count(), 1)
        self.assertEqual(Excerpt.objects.count(), 1)

        ar = rt.modules.notes.Notes.request()
        s = ar.to_rst(column_names="id owner")
        self.assertEqual(s, """\
==== ===============
 ID   Controlled by
---- ---------------
 1    *John Doe*
==== ===============

""")

        ar = rt.modules.excerpts.Excerpts.request()
        s = ar.to_rst(column_names="id owner")
        self.assertEqual(s, """\
==== ===============
 ID   Controlled by
---- ---------------
 1    *Note #1*
==== ===============

""")

        self.assertEqual(excerpt.disable_delete(), None)
        self.assertEqual(note.disable_delete(), None)
        self.assertEqual(doe.disable_delete(), None)
        # it is not "Cannot delete John Doe because 1 Notes refer to
        # it." because Note.owner is nullable.

        note.delete()
        self.assertEqual(Excerpt.objects.count(), 0)
        self.assertEqual(ExcerptType.objects.count(), 1)
Пример #11
0
 def value2string(self, obj, field):
     from django.contrib.contenttypes.models import ContentType
     if isinstance(field, (BabelCharField, BabelTextField)):
         return repr(settings.SITE.field2args(obj, field.name))
     value = field._get_val_from_obj(obj)
     # Protected types (i.e., primitives like None, numbers, dates,
     # and Decimals) are passed through as is. All other values are
     # converted to string first.
     if value is None:
     #~ if value is None or value is NOT_PROVIDED:
         return 'None'
     if isinstance(field, models.DateTimeField):
         d = value
         return 'dt(%d,%d,%d,%d,%d,%d)' % (
             d.year, d.month, d.day, d.hour, d.minute, d.second)
     if isinstance(field, models.TimeField):
         d = value
         return 'time(%d,%d,%d)' % (d.hour, d.minute, d.second)
     if isinstance(field, ForeignKey) and field.rel.model is ContentType:
         ct = ContentType.objects.get(pk=value)
         return full_model_name(ct.model_class(), '_')
         #~ return "'"+full_model_name(ct.model_class())+"'"
         #~ return repr(tuple(value.app_label,value.model))
     if isinstance(field, models.DateField):
         d = value
         return 'date(%d,%d,%d)' % (d.year, d.month, d.day)
         #~ return 'i2d(%4d%02d%02d)' % (d.year,d.month,d.day)
     if isinstance(value, (float, Decimal)):
         return repr(str(value))
     if isinstance(value, int):
         return str(value)
     return repr(field.value_to_string(obj))
Пример #12
0
    def __init__(self, model, **kw):

        fields = dict(
            #~ merge_from=models.ForeignKey(model,verbose_name=_("Merge...")),
            merge_to=models.ForeignKey(
                model, verbose_name=_("into..."), blank=False, null=False),
            reason=models.CharField(_("Reason"), max_length=100)
            #~ notify=models.BooleanField(_("Send notifications"))
        )

        keep_volatiles = []

        # logger.info("20160621 MergeAction for %s", model)
        # logger.info("20160621 MergeAction for %s : _lino_ddh.fklist is %s",
        #             model, model._lino_ddh.fklist)
        for m, fk in traverse_ddh_fklist(model):
            if fk.name in m.allow_cascaded_delete:
                fieldname = full_model_name(m, '_')
                if fieldname not in keep_volatiles:
                    keep_volatiles.append(fieldname)
                    fields[fieldname] = models.BooleanField(
                        m._meta.verbose_name_plural, default=False)
                # logger.info(
                #     "20160621 %r in %r", fk.name, m.allow_cascaded_delete)

        layout = dict()
        if len(keep_volatiles) == 0:
            width = 50
            main = """
            merge_to
            reason
            """
        else:
            COLCOUNT = 2
            width = 70
            if len(keep_volatiles) > COLCOUNT:
                tpl = ''
                for i, name in enumerate(keep_volatiles):
                    if i % COLCOUNT == 0:
                        tpl += '\n'
                    else:
                        tpl += ' '
                    tpl += name
            else:
                tpl = ' '.join(keep_volatiles)
            main = """
            merge_to
            keep_volatiles
            reason
            """
            layout.update(keep_volatiles=layouts.Panel(
                tpl, label=_("Also reassign volatile related objects")))

        layout.update(window_size=(width, 'auto'))
        kw.update(
            parameters=fields,
            params_layout=layouts.Panel(main, **layout))

        super(MergeAction, self).__init__(**kw)
Пример #13
0
 def fk_display(obj, value):
     ct = getattr(obj, self.ct_field)
     if ct:
         try:
             return unicode(ct.get_object_for_this_type(pk=value))
         except ct.model_class().DoesNotExist:
             return "%s with pk %r does not exist" % (
                 full_model_name(ct.model_class()), value)
Пример #14
0
 def fk_display(obj, value):
     ct = getattr(obj, self.ct_field)
     if ct:
         try:
             return unicode(ct.get_object_for_this_type(pk=value))
         except ct.model_class().DoesNotExist:
             return "%s with pk %r does not exist" % (
                 full_model_name(ct.model_class()), value)
Пример #15
0
 def add(name):
     for f, qs in getattr(self, name):
         if qs.count() > 0:
             lst.append('- %d %s %s rows using %s : %s' % (
                 qs.count(),
                 name,
                 full_model_name(f.model),
                 f.name,
                 ' '.join([str(o.pk) for o in qs])))
Пример #16
0
    def finalize(self):
        """
        """
        self.flush_deferred_objects()

        if len(self.AFTER_LOAD_HANDLERS):
            logger.info(
                "Finalize %d after_load handlers",
                len(self.AFTER_LOAD_HANDLERS))

        for h in self.AFTER_LOAD_HANDLERS:
            logger.info("Running after_load handler %s", h.__doc__)
            h(self)

        # logger.info("Loaded %d objects", self.count_objects)
    
        if self.save_later:
            count = 0
            s = ''
            for model, msg_objects in list(self.save_later.items()):
                for msg, objects in list(msg_objects.items()):
                    if False:  # detailed content of the first object
                        s += "\n- %s %s (%d object(s), e.g. %s)" % (
                            full_model_name(model), msg, len(objects),
                            obj2str(objects[0].object, force_detailed=True))
                    else:  # pk of all objects
                        s += "\n- %s %s (%d object(s) with primary key %s)" % (
                            full_model_name(model), msg, len(objects),
                            ', '.join([str(o.object.pk) for o in objects]))
                    count += len(objects)
            msg = "Abandoning with {} unsaved instances:{}"
            logger.warning(msg.format(count, s))

            # Don't raise an exception. The unsaved instances got lost and
            # the loaddata should be done again, but meanwhile the database
            # is not necessarily invalid and may be used for further testing.
            # And anyway, loaddata would catch it and still continue.
            # raise Exception(msg)

        settings.SITE.loading_from_dump = False
Пример #17
0
    def finalize(self):
        """
        """
        self.flush_deferred_objects()

        if len(self.AFTER_LOAD_HANDLERS):
            logger.info(
                "Finalize %d after_load handlers",
                len(self.AFTER_LOAD_HANDLERS))

        for h in self.AFTER_LOAD_HANDLERS:
            logger.info("Running after_load handler %s", h.__doc__)
            h(self)

        # logger.info("Loaded %d objects", self.count_objects)

        if self.save_later:
            count = 0
            s = ''
            for model, msg_objects in list(self.save_later.items()):
                for msg, objects in list(msg_objects.items()):
                    if False:  # detailed content of the first object
                        s += "\n- %s %s (%d object(s), e.g. %s)" % (
                            full_model_name(model), msg, len(objects),
                            obj2str(objects[0].object, force_detailed=True))
                    else:  # pk of all objects
                        s += "\n- %s %s (%d object(s) with primary key %s)" % (
                            full_model_name(model), msg, len(objects),
                            ', '.join([str(o.object.pk) for o in objects]))
                    count += len(objects)
            msg = "Abandoning with {} unsaved instances:{}"
            logger.warning(msg.format(count, s))

            # Don't raise an exception. The unsaved instances got lost and
            # the loaddata should be done again, but meanwhile the database
            # is not necessarily invalid and may be used for further testing.
            # And anyway, loaddata would catch it and still continue.
            # raise Exception(msg)

        settings.SITE.loading_from_dump = False
Пример #18
0
def get_by_id(model, pk, offset=0, warn=True):
    if not pk:
        return None
    pk = int(pk)
    if pk == 0:
        return None
    try:
        return model.objects.get(pk=pk + offset)
    except model.DoesNotExist:
        if warn:
            dblogger.warning("%s %r does not exist?!",
                             full_model_name(model), pk)
        return None
Пример #19
0
 def analyze(self):
     self.volatiles = []
     self.related = []
     for m, fk in self.obj._lino_ddh.fklist:
         qs = m.objects.filter(**{fk.name: self.obj})
         if fk.name in m.allow_cascaded_delete and not self.keep_volatiles.get(full_model_name(m, "_")):
             self.volatiles.append((fk, qs))
         else:
             self.related.append((fk, qs))
     self.generic_related = []
     for gfk, fk, qs in settings.SITE.kernel.get_generic_related(self.obj):
         if not getattr(gfk, "dont_merge", False):
             self.generic_related.append((gfk, qs))
Пример #20
0
 def analyze(self):
     self.volatiles = []
     self.related = []
     for m, fk in self.obj._lino_ddh.fklist:
         qs = m.objects.filter(**{fk.name: self.obj})
         if fk.name in m.allow_cascaded_delete and \
            not self.keep_volatiles.get(full_model_name(m, '_')):
             self.volatiles.append((fk, qs))
         else:
             self.related.append((fk, qs))
     self.generic_related = []
     for gfk, fk, qs in settings.SITE.kernel.get_generic_related(self.obj):
         if not getattr(gfk, 'dont_merge', False):
             self.generic_related.append((gfk, qs))
Пример #21
0
 def analyze(self):
     self.volatiles = []
     self.related = []
     self.generic_related = []
     # logger.info("20160621 ddh.fklist is %s", self.obj._lino_ddh.fklist)
     for m, fk in traverse_ddh_fklist(self.obj.__class__):
         qs = m.objects.filter(**{fk.name: self.obj})
         if fk.name in m.allow_cascaded_delete and \
            not self.keep_volatiles.get(full_model_name(m, '_')):
             self.volatiles.append((fk, qs))
         else:
             self.related.append((fk, qs))
     for gfk, fk, qs in settings.SITE.kernel.get_generic_related(self.obj):
         if not getattr(gfk, 'dont_merge', False):
             self.generic_related.append((gfk, qs))
Пример #22
0
 def analyze(self):
     self.volatiles = []
     self.related = []
     self.generic_related = []
     # logger.info("20160621 ddh.fklist is %s", self.obj._lino_ddh.fklist)
     for m, fk in traverse_ddh_fklist(self.obj.__class__):
         qs = m.objects.filter(**{fk.name: self.obj})
         if fk.name in m.allow_cascaded_delete and \
            not self.keep_volatiles.get(full_model_name(m, '_')):
             self.volatiles.append((fk, qs))
         else:
             self.related.append((fk, qs))
     for gfk, fk, qs in settings.SITE.kernel.get_generic_related(self.obj):
         if not getattr(gfk, 'dont_merge', False):
             self.generic_related.append((gfk, qs))
Пример #23
0
    def show_db_overview(self):
        """Return a reStructredText-formatted "database overview" report.
        Used by test cases in tested documents.

        """
        from lino.core.utils import (full_model_name, sorted_models_list)

        models_list = sorted_models_list()
        apps = [p.app_label for p in settings.SITE.installed_plugins]
        s = "%d apps: %s." % (len(apps), ", ".join(apps))
        s += "\n%d models:\n" % len(models_list)
        i = 0
        headers = [
            #~ "No.",
            "Name",
            "Default table",
            #~ "M",
            "#fields",
            "#rows",
            #~ ,"first","last"
        ]
        rows = []
        for model in models_list:
            if True:  # model._meta.managed:
                i += 1
                cells = []
                #~ cells.append(str(i))
                cells.append(full_model_name(model))
                cells.append(model.get_default_table())
                #~ cells.append(str(model))
                #~ if model._meta.managed:
                #~ cells.append('X')
                #~ else:
                #~ cells.append('')
                cells.append(str(len(model._meta.concrete_fields)))
                qs = model.objects.all()
                n = qs.count()
                cells.append(str(n))
                #~ if n:
                #~ cells.append(obj2str(qs[0]))
                #~ cells.append(obj2str(qs[n-1]))
                #~ else:
                #~ cells.append('')
                #~ cells.append('')

                rows.append(cells)
        s += rstgen.table(headers, rows)
        return s
Пример #24
0
    def show_db_overview(self):
        """Return a reStructredText-formatted "database overview" report.
        Used by test cases in tested documents.

        """
        from lino.core.utils import (full_model_name, sorted_models_list)

        models_list = sorted_models_list()
        apps = [p.app_label for p in settings.SITE.installed_plugins]
        s = "%d apps: %s." % (len(apps), ", ".join(apps))
        s += "\n%d models:\n" % len(models_list)
        i = 0
        headers = [
            #~ "No.",
            "Name",
            "Default table",
            #~ "M",
            "#fields",
            "#rows",
            #~ ,"first","last"
        ]
        rows = []
        for model in models_list:
            if True:  # model._meta.managed:
                i += 1
                cells = []
                #~ cells.append(str(i))
                cells.append(full_model_name(model))
                cells.append(model.get_default_table())
                #~ cells.append(str(model))
                #~ if model._meta.managed:
                #~ cells.append('X')
                #~ else:
                #~ cells.append('')
                cells.append(str(len(model._meta.concrete_fields)))
                qs = model.objects.all()
                n = qs.count()
                cells.append(str(n))
                #~ if n:
                #~ cells.append(obj2str(qs[0]))
                #~ cells.append(obj2str(qs[n-1]))
                #~ else:
                #~ cells.append('')
                #~ cells.append('')

                rows.append(cells)
        s += rstgen.table(headers, rows)
        return s
Пример #25
0
def show_fields_by_type(fldtype):
    """Print a list of all fields (in all models) that have the specified type.
    """
    from lino.core.utils import (sorted_models_list)
    items = []
    for model in sorted_models_list():
        flds = []
        for f in model._meta.fields:
            if isinstance(f, fldtype):
                name = f.name
                verbose_name = force_text(f.verbose_name).strip()
                txt = "{verbose_name} ({name})".format(**locals())
                flds.append(txt)
        if len(flds):
            txt = "{model} : {fields}".format(model=full_model_name(model),
                                              fields=", ".join(flds))
            items.append(txt)
    print(rstgen.ul(items))
Пример #26
0
 def value2string(self, obj, field):
     if isinstance(field, (BabelCharField, BabelTextField)):
         #~ return repr([repr(x) for x in dbutils.field2args(obj,field.name)])
         return repr(settings.SITE.field2args(obj, field.name))
     # value = field._get_val_from_obj(obj)
     value = field.value_from_object(obj)
     # Protected types (i.e., primitives like None, numbers, dates,
     # and Decimals) are passed through as is. All other values are
     # converted to string first.
     if value is None:
         #~ if value is None or value is NOT_PROVIDED:
         return 'None'
     if isinstance(field, models.DateTimeField):
         if is_aware(value):
             d = make_naive(value, timezone=utc)
         else:
             d = value
         return 'dt(%d,%d,%d,%d,%d,%d)' % (d.year, d.month, d.day, d.hour,
                                           d.minute, d.second)
     if isinstance(field, models.TimeField):
         d = value
         return 'time(%d,%d,%d)' % (d.hour, d.minute, d.second)
     if is_pointer_to_contenttype(field):
         ContentType = settings.SITE.models.contenttypes.ContentType
         ct = ContentType.objects.get(pk=value)
         return full_model_name(ct.model_class(), '_')
         #~ return "'"+full_model_name(ct.model_class())+"'"
         #~ return repr(tuple(value.app_label,value.model))
     if isinstance(field, models.DateField):
         d = value
         return 'date(%d,%d,%d)' % (d.year, d.month, d.day)
         #~ return 'i2d(%4d%02d%02d)' % (d.year,d.month,d.day)
     if isinstance(value, (float, Decimal)):
         return repr(str(value))
     if isinstance(value, int):
         return str(value)
     return repr(field.value_to_string(obj))
Пример #27
0
def model_name(m):
    return settings.SITE.userdocs_prefix + full_model_name(m).lower()
Пример #28
0
    def get_rst(self):
        #~ from actordoc import get_actor_description
        #~ from django.conf import settings
        #~ from djangosite.dbutils import set_language
        with translation.override(self.language):
            level, cls = resolve_name(self.content[0])
            if isinstance(cls, models.Field):
                fld = cls
                s = ''
                name = str(fld.model) + '.' + fld.name
                title = force_text(fld.verbose_name).strip()
                
                s += "\n.. index::\n   single: "
                s += str(_('%(field)s (field in %(model)s)') % dict(
                    field=title, model=model_ref(fld.model)))
                s += '\n\n'
                s += rstgen.header(level, _("%s (field)") % title)
                if len(self.content) > 1:
                    s += '\n'.join(self.content[1:])
                    s += '\n\n'
                return s

            if isinstance(cls, Plugin):
                s = ''
                title = str(cls.verbose_name)
                s += "\n.. index::\n   single: "
                s += str(_('%s (app)') % title)
                s += '\n\n.. _' + name + ':\n'
                s += '\n'
                s += rstgen.header(level, _("%s (app)") % title)
                return s

            if not isinstance(cls, type):
                raise Exception("%s is not an actor." % self.content[0])

            if issubclass(cls, models.Model):
                model = cls

                s = ''
                name = model_name(model).lower()
                title = force_text(model._meta.verbose_name)
                s += "\n.. index::\n   single: "
                s += str(_('%(model)s (model in %(app)s)') % dict(
                    model=title, app=model._meta.app_label))

                s += '\n\n'

                s += '\n\n.. _' + name + ':\n'

                s += '\n'
                s += rstgen.header(level, _("%s (model)") % title)

                s += '\n'
                s += '\n:Internal name: ``%s``\n' % full_model_name(cls)
                s += '\n:Implemented by: %s\n' % typeref(cls)
                s += '\n'

                if len(self.content) > 1:
                    s += '\n'.join(self.content[1:])
                    s += '\n\n'

                model_reports = [
                    r for r in kernel.master_tables if r.model is cls]
                model_reports += [r for r in kernel.slave_tables
                                  if r.model is cls]
                s += rstgen.boldheader(_("Views on %s") %
                                       cls._meta.verbose_name)
                s += actors_overview_ul(model_reports)

                s += rstgen.boldheader(_("Fields in %s") %
                                       cls._meta.verbose_name)
                s += fields_ul(cls._meta.fields)

                action_list = cls.get_default_table().get_actions()
                action_list = [
                    ba for ba in action_list
                    if not isinstance(ba.action, IGNORED_ACTIONS)]
                if action_list:
                    s += '\n'
                    s += rstgen.boldheader(_("Actions on %s") %
                                           cls._meta.verbose_name)
                    s += actions_ul(action_list)

                slave_tables = getattr(cls, '_lino_slaves', {}).values()
                if slave_tables:
                    s += rstgen.boldheader(_("Tables referring to %s") %
                                           cls._meta.verbose_name)
                    s += actors_overview_ul(slave_tables)

                return s

            if issubclass(cls, actors.Actor):

                title = force_text(cls.label or cls.title)
                indextext = _('%(actor)s (view in %(app)s)') % dict(
                    actor=title, app=cls.app_label)
                name = actor_name(cls)
                #~ if name == 'welfare.reception.waitingvisitors':
                    #~ self.debug = True
                #~ print(20130907, name)
                self.index_entries.append(('single', indextext, name, ''))
                #~ self.add_ref_target(name,name)

                s = ''
                s += '\n\n.. _%s:\n\n' % name
                s += rstgen.header(level, _("%s (view)") % title)
                s += '\n:Internal name: ``%s`` (%s)\n' % (cls, typeref(cls))

                if len(self.content) > 1:
                    s += '\n'.join(self.content[1:])
                    s += '\n\n'

                s += '\n\n'
                s += get_actor_description(cls)
                s += '\n\n'
                return s
            raise Exception("Cannot handle actor %r." % cls)
Пример #29
0
    def write_files(self):
        puts("Writing {0}...".format(self.main_file))
        self.stream = open(self.main_file, 'wt')
        current_version = settings.SITE.version

        self.stream.write('''\
#!/usr/bin/env python
# -*- coding: UTF-8 -*-

# This is a Python dump created using dump2py.
# DJANGO_SETTINGS_MODULE was %r, TIME_ZONE was %r.

''' % (settings.SETTINGS_MODULE, settings.TIME_ZONE))

        self.stream.write('''
from __future__ import unicode_literals

import logging
logger = logging.getLogger('%s')
import os

''' % __name__)

        self.stream.write('SOURCE_VERSION = %r\n' % str(current_version))
        self.stream.write('''
from decimal import Decimal
from datetime import datetime
from datetime import time, date
from django.conf import settings
from django.utils.timezone import make_aware
# from django.contrib.contenttypes.models import ContentType
from lino.utils.dpy import create_mti_child
from lino.utils.dpy import DpyLoader
from lino.core.utils import resolve_model

if settings.USE_TZ:
    def dt(*args):
        return make_aware(datetime(*args))
else:
    def dt(*args):
        return datetime(*args)
        
def new_content_type_id(m):
    if m is None: return m
    ct = settings.SITE.models.contenttypes.ContentType.objects.get_for_model(m)
    if ct is None: return None
    return ct.pk
    
''')
        s = ','.join([
            '%s=values[%d]' % (lng.name, lng.index)
            for lng in settings.SITE.languages])
        self.stream.write('''
def bv2kw(fieldname, values):
    """
    Needed if `Site.languages` changed between dumpdata and loaddata
    """
    return settings.SITE.babelkw(fieldname, %s)
    
''' % s)
        self.models = sorted_models_list()
        
        if settings.SITE.is_installed('contenttypes'):
            from django.contrib.contenttypes.models import ContentType
            self.models = [m for m in self.models
                           if not issubclass(m, ContentType)]
        
        if settings.SITE.is_installed('sessions'):
            from django.contrib.sessions.models import Session
            self.models = [m for m in self.models
                           if not issubclass(m, Session)]

        for model in self.models:
            self.stream.write('%s = resolve_model("%s")\n' % (
                full_model_name(model, '_'), full_model_name(model)))
        self.stream.write('\n')
        self.models = self.sort_models(self.models)
        self.stream.write('\n')
        for model in self.models:
            fields = [f for f in model._meta.get_fields()
                      if f.concrete and f.model is model]
            for f in fields:
                if getattr(f, 'auto_now_add', False):
                    raise Exception("%s.%s.auto_now_add is True : values will be lost!" % (
                        full_model_name(model), f.name))
            #~ fields = model._meta.local_fields
            #~ fields = [f for f in model._meta.fields if f.serialize]
            #~ fields = [f for f in model._meta.local_fields if f.serialize]
            self.stream.write('def create_%s(%s):\n' % (
                model._meta.db_table, ', '.join([
                    f.attname for f in fields
                    if not getattr(f, '_lino_babel_field', False)])))
            for f in fields:
                if isinstance(f, models.DecimalField):
                    self.stream.write(
                        '    if %s is not None: %s = Decimal(%s)\n' % (
                            f.attname, f.attname, f.attname))
                elif isinstance(f, ChoiceListField):
                    lstname = 'settings.SITE.modules.{0}.{1}'.format(
                        f.choicelist.app_label, f.choicelist.__name__)
                    ln = '    if {0}: {0} = {1}.get_by_value({0})\n'
                    self.stream.write(ln.format(f.attname, lstname))
                elif is_pointer_to_contenttype(f):
                    self.stream.write(
                        '    %s = new_content_type_id(%s)\n' % (
                            f.attname, f.attname))

            if model._meta.parents:
                if len(model._meta.parents) != 1:
                    msg = "%s : model._meta.parents is %r" % (
                        model, model._meta.parents)
                    raise Exception(msg)
                pm, pf = list(model._meta.parents.items())[0]
                child_fields = [f for f in fields if f != pf]
                if child_fields:
                    attrs = ',' + ','.join([
                        '%s=%s' % (f.attname, f.attname)
                        for f in child_fields])
                else:
                    attrs = ''
                self.stream.write(
                    '    return create_mti_child(%s, %s, %s%s)\n' % (
                        full_model_name(pm, '_'), pf.attname,
                        full_model_name(model, '_'), attrs))
            else:
                self.stream.write("    kw = dict()\n")
                for f in fields:
                    if getattr(f, '_lino_babel_field', False):
                        continue
                    elif isinstance(f, (BabelCharField, BabelTextField)):
                        self.stream.write(
                            '    if %s is not None: kw.update(bv2kw(%r,%s))\n' % (
                                f.attname, f.attname, f.attname))
                    else:
                        self.stream.write(
                            '    kw.update(%s=%s)\n' % (f.attname, f.attname))

                self.stream.write('    return %s(**kw)\n\n' %
                                  full_model_name(model, '_'))
        self.stream.write('\n')
        #~ used_models = set()

        self.stream.write("""

def main(args):
    loader = DpyLoader(globals())
    from django.core.management import call_command
    call_command('initdb', interactive=args.interactive)
    os.chdir(os.path.dirname(__file__))
    loader.initialize()

""")

        for model in progress.bar(self.models):
            filename = '%s.py' % model._meta.db_table
            filename = os.path.join(self.output_dir, filename)
            # puts("Writing {0}...".format(filename))
            # stream = file(filename, 'wt')
            stream = open(filename, 'wt')
            stream.write('# -*- coding: UTF-8 -*-\n')
            qs = model.objects.all()
            try:
                stream.write(
                    'logger.info("Loading %d objects to table %s...")\n' % (
                        qs.count(), model._meta.db_table))

                fields = [f for f in model._meta.get_fields()
                          if f.concrete and f.model is model]
                fields = [
                    f for f in fields
                    if not getattr(f, '_lino_babel_field', False)]
                stream.write(
                    "# fields: %s\n" % ', '.join(
                        [f.name for f in fields]))
                for obj in qs:
                    self.count_objects += 1
                    #~ used_models.add(model)
                    stream.write('loader.save(create_%s(%s))\n' % (
                        obj._meta.db_table,
                        ','.join([self.value2string(obj, f) for f in fields])))
                stream.write('\n')
                stream.write('loader.flush_deferred_objects()\n')
            except DatabaseError as e:
                self.database_errors += 1
                if not self.options['tolerate']:
                    raise
                stream.write('\n')
                logger.warning("Tolerating database error %s in %s",
                               e, model._meta.db_table)
                msg = ("The data of this table has not been dumped"
                       "because an error {0} occured.").format(e)
                stream.write('raise Exception("{0}")\n'.format(msg))
                
            stream.close()

            #~ self.stream.write('\nfilename = os.path.join(os.path.dirname(__file__),"%s.py")\n' % )
            self.stream.write('    execfile("%s.py")\n' % model._meta.db_table)

        self.stream.write(
            '    loader.finalize()\n')
        # self.stream.write(
        #     '    logger.info("Loaded %d objects",loader.count_objects)\n')
        self.stream.write("""
if __name__ == '__main__':
    import argparse
    parser = argparse.ArgumentParser(description='Restore the data.')
    parser.add_argument('--noinput', dest='interactive',
        action='store_false', default=True,
        help="Don't ask for confirmation before flushing the database.")

    args = parser.parse_args()
    main(args)
""")
        #~ self.stream.write('\nsettings.SITE.load_from_file(globals())\n')
        self.stream.close()
Пример #30
0
    def write_files(self):
        puts("Writing {0}...".format(self.main_file))
        self.stream = open(self.main_file, 'wt')
        current_version = settings.SITE.version

        self.stream.write("""\
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
""")

        self.stream.write('''\
"""
This is a Python dump created using %s.
''' % settings.SITE.using_text())

        #~ self.stream.write(settings.SITE.welcome_text())
        self.stream.write('''
"""
from __future__ import unicode_literals

import logging
logger = logging.getLogger('%s')
import os

''' % __name__)
        if False:
            self.stream.write("""
os.environ['DJANGO_SETTINGS_MODULE'] = '%s'
""" % settings.SETTINGS_MODULE)

        self.stream.write('SOURCE_VERSION = %r\n' % str(current_version))
        self.stream.write('''
from decimal import Decimal
from datetime import datetime as dt
from datetime import time,date
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from lino.utils.dpy import create_mti_child
from lino.utils.dpy import DpyLoader
from lino.core.utils import resolve_model
        
def new_content_type_id(m):
    if m is None: return m
    ct = ContentType.objects.get_for_model(m)
    if ct is None: return None
    return ct.pk
    
''')
        s = ','.join([
            '%s=values[%d]' % (lng.name, lng.index)
            for lng in settings.SITE.languages
        ])
        self.stream.write('''
def bv2kw(fieldname, values):
    """
    Needed if `Site.languages` changed between dumpdata and loaddata
    """
    return settings.SITE.babelkw(fieldname, %s)
    
''' % s)
        self.models = [
            m for m in sorted_models_list()
            if not issubclass(m, (ContentType, Session))
        ]
        for model in self.models:
            self.stream.write(
                '%s = resolve_model("%s")\n' %
                (full_model_name(model, '_'), full_model_name(model)))
        self.stream.write('\n')
        self.models = self.sort_models(self.models)
        self.stream.write('\n')
        for model in self.models:
            fields = [
                f for f, m in model._meta.get_fields_with_model() if m is None
            ]
            if AFTER17:
                fields = [f for f in fields if f.concrete]
            for f in fields:
                if getattr(f, 'auto_now_add', False):
                    raise Exception(
                        "%s.%s.auto_now_add is True : values will be lost!" %
                        (full_model_name(model), f.name))
            #~ fields = model._meta.local_fields
            #~ fields = [f for f in model._meta.fields if f.serialize]
            #~ fields = [f for f in model._meta.local_fields if f.serialize]
            self.stream.write('def create_%s(%s):\n' %
                              (model._meta.db_table, ', '.join([
                                  f.attname for f in fields
                                  if not getattr(f, '_lino_babel_field', False)
                              ])))
            if model._meta.parents:
                if len(model._meta.parents) != 1:
                    msg = "%s : model._meta.parents is %r" % (
                        model, model._meta.parents)
                    raise Exception(msg)
                pm, pf = model._meta.parents.items()[0]
                child_fields = [f for f in fields if f != pf]
                if child_fields:
                    attrs = ',' + ','.join([
                        '%s=%s' % (f.attname, f.attname) for f in child_fields
                    ])
                else:
                    attrs = ''
                #~ self.stream.write('    return insert_child(%s.objects.get(pk=%s),%s%s)\n' % (
                #~ full_model_name(pm,'_'),pf.attname,full_model_name(model,'_'),attrs))
                self.stream.write('    return create_mti_child(%s,%s,%s%s)\n' %
                                  (full_model_name(pm, '_'), pf.attname,
                                   full_model_name(model, '_'), attrs))
            else:
                self.stream.write("    kw = dict()\n")
                for f in fields:
                    if getattr(f, '_lino_babel_field', False):
                        continue
                    elif isinstance(f, (BabelCharField, BabelTextField)):
                        self.stream.write(
                            '    if %s is not None: kw.update(bv2kw(%r,%s))\n'
                            % (f.attname, f.attname, f.attname))
                    else:
                        if isinstance(f, models.DecimalField):
                            self.stream.write(
                                '    if %s is not None: %s = Decimal(%s)\n' %
                                (f.attname, f.attname, f.attname))
                        elif isinstance(
                                f,
                                models.ForeignKey) and f.rel.to is ContentType:
                            #~ self.stream.write(
                            #~ '    %s = ContentType.objects.get_for_model(%s).pk\n' % (
                            #~ f.attname,f.attname))
                            self.stream.write(
                                '    %s = new_content_type_id(%s)\n' %
                                (f.attname, f.attname))
                        self.stream.write('    kw.update(%s=%s)\n' %
                                          (f.attname, f.attname))

                self.stream.write('    return %s(**kw)\n\n' %
                                  full_model_name(model, '_'))
        self.stream.write('\n')
        #~ used_models = set()

        self.stream.write("""

def main():
    loader = DpyLoader(globals())
    from django.core.management import call_command
    # call_command('initdb', interactive=False)
    call_command('initdb')
    os.chdir(os.path.dirname(__file__))
    loader.initialize()

""")

        for model in progress.bar(self.models):
            filename = '%s.py' % model._meta.db_table
            filename = os.path.join(self.output_dir, filename)
            # puts("Writing {0}...".format(filename))
            stream = file(filename, 'wt')
            stream.write('# -*- coding: UTF-8 -*-\n')
            qs = model.objects.all()
            try:
                stream.write(
                    'logger.info("Loading %d objects to table %s...")\n' %
                    (qs.count(), model._meta.db_table))
                fields = [
                    f for f, m in model._meta.get_fields_with_model()
                    if m is None
                ]
                fields = [
                    f for f in fields
                    if not getattr(f, '_lino_babel_field', False)
                ]
                if AFTER17:
                    fields = [f for f in fields if f.concrete]
                stream.write("# fields: %s\n" %
                             ', '.join([f.name for f in fields]))
                for obj in qs:
                    self.count_objects += 1
                    #~ used_models.add(model)
                    stream.write(
                        'loader.save(create_%s(%s))\n' %
                        (obj._meta.db_table, ','.join(
                            [self.value2string(obj, f) for f in fields])))
                stream.write('\n')
                stream.write('loader.flush_deferred_objects()\n')
            except ProgrammingError as e:
                if not self.options['tolerate']:
                    raise
                stream.write('\n')
                logger.warning("Tolerating database error %s in %s", e,
                               model._meta.db_table)
                msg = ("The data of this table has not been dumped"
                       "because an error {0} occured.").format(e)
                stream.write('raise Exception("{0}")\n'.format(msg))

            stream.close()

            #~ self.stream.write('\nfilename = os.path.join(os.path.dirname(__file__),"%s.py")\n' % )
            self.stream.write('    execfile("%s.py")\n' % model._meta.db_table)

        self.stream.write('    loader.finalize()\n')
        # self.stream.write(
        #     '    logger.info("Loaded %d objects",loader.count_objects)\n')
        self.stream.write("""
if __name__ == '__main__':
    main()
""")
        #~ self.stream.write('\nsettings.SITE.load_from_file(globals())\n')
        self.stream.close()
Пример #31
0
    def get_data_elem(cls, name):
        """Return the named data element. This can be a database field, a
        :class:`lino.core.fields.RemoteField`, a
        :class:`lino.core.fields.VirtualField` or a Django-style
        virtual field (GenericForeignKey).

        """
        #~ logger.info("20120202 get_data_elem %r,%r",model,name)
        if not name.startswith('__'):
            parts = name.split('__')
            if len(parts) > 1:
                # It's going to be a RemoteField
                # logger.warning("20151203 RemoteField %s in %s", name, cls)

                from lino.core import store

                model = cls
                field_chain = []
                for n in parts:
                    if model is None:
                        raise Exception(
                            "Invalid remote field {0} for {1}".format(name, cls))

                    if isinstance(model, basestring):
                        model = resolve_model(model)
                        # logger.warning("20151203 %s", model)
                        # Django 1.9 no longer resolves the
                        # rel.model of ForeignKeys on abstract
                        # models.

                    # ~ 20130508 model.get_default_table().get_handle() # make sure that all atomizers of those fields get created.
                    fld = model.get_data_elem(n)
                    if fld is None:
                        # raise Exception("Part %s of %s got None" % (n,model))
                        raise Exception(
                            "Invalid RemoteField %s.%s (no field %s in %s)" %
                            (full_model_name(model), name, n, full_model_name(model)))
                    # make sure that the atomizer gets created.
                    store.get_atomizer(model, fld, fld.name)
                    field_chain.append(fld)
                    if getattr(fld, 'rel', None):
                        if AFTER18:
                            model = fld.rel.model
                        else:
                            model = fld.rel.to
                    else:
                        model = None

                def func(obj, ar=None):
                    try:
                        for fld in field_chain:
                            if obj is None:
                                return obj
                            obj = fld._lino_atomizer.full_value_from_object(
                                obj, ar)
                        return obj
                    except Exception as e:
                        raise Exception(
                            "Error while computing %s: %s" % (name, e))
                        # ~ if False: # only for debugging
                        if True:  # see 20130802
                            logger.exception(e)
                            return str(e)
                        return None
                return fields.RemoteField(func, name, fld)

        try:
            return cls._meta.get_field(name)
        except models.FieldDoesNotExist:
            pass

        v = get_class_attr(cls, name)
        if v is not None:
            return v

        for vf in cls._meta.virtual_fields:
            if vf.name == name:
                return vf
Пример #32
0
    def write_files(self):
        puts("Writing {0}...".format(self.main_file))
        self.stream = open(self.main_file, "wt")
        current_version = settings.SITE.version

        self.stream.write(
            """\
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
        )

        self.stream.write(
            '''\
"""
This is a Python dump created using %s.
'''
            % settings.SITE.using_text()
        )

        # ~ self.stream.write(settings.SITE.welcome_text())
        self.stream.write(
            '''
"""
from __future__ import unicode_literals

import logging
logger = logging.getLogger('%s')
import os

'''
            % __name__
        )
        if False:
            self.stream.write(
                """
os.environ['DJANGO_SETTINGS_MODULE'] = '%s'
"""
                % settings.SETTINGS_MODULE
            )

        self.stream.write("SOURCE_VERSION = %r\n" % str(current_version))
        self.stream.write(
            """
from decimal import Decimal
from datetime import datetime as dt
from datetime import time, date
from django.conf import settings
# from django.contrib.contenttypes.models import ContentType
from lino.utils.dpy import create_mti_child
from lino.utils.dpy import DpyLoader
from lino.core.utils import resolve_model
        
def new_content_type_id(m):
    if m is None: return m
    ct = settings.SITE.modules.contenttypes.ContentType.objects.get_for_model(m)
    if ct is None: return None
    return ct.pk
    
"""
        )
        s = ",".join(["%s=values[%d]" % (lng.name, lng.index) for lng in settings.SITE.languages])
        self.stream.write(
            '''
def bv2kw(fieldname, values):
    """
    Needed if `Site.languages` changed between dumpdata and loaddata
    """
    return settings.SITE.babelkw(fieldname, %s)
    
'''
            % s
        )
        self.models = sorted_models_list()

        if settings.SITE.is_installed("contenttypes"):
            from django.contrib.contenttypes.models import ContentType

            self.models = [m for m in self.models if not issubclass(m, ContentType)]

        if settings.SITE.is_installed("sessions"):
            from django.contrib.sessions.models import Session

            self.models = [m for m in self.models if not issubclass(m, Session)]

        for model in self.models:
            self.stream.write('%s = resolve_model("%s")\n' % (full_model_name(model, "_"), full_model_name(model)))
        self.stream.write("\n")
        self.models = self.sort_models(self.models)
        self.stream.write("\n")
        for model in self.models:
            if AFTER17:
                fields = [f for f in model._meta.get_fields() if f.concrete and f.model is model]
            else:
                fields = [f for f, m in model._meta.get_fields_with_model() if m is None]
            for f in fields:
                if getattr(f, "auto_now_add", False):
                    raise Exception(
                        "%s.%s.auto_now_add is True : values will be lost!" % (full_model_name(model), f.name)
                    )
            # ~ fields = model._meta.local_fields
            # ~ fields = [f for f in model._meta.fields if f.serialize]
            # ~ fields = [f for f in model._meta.local_fields if f.serialize]
            self.stream.write(
                "def create_%s(%s):\n"
                % (
                    model._meta.db_table,
                    ", ".join([f.attname for f in fields if not getattr(f, "_lino_babel_field", False)]),
                )
            )
            for f in fields:
                if isinstance(f, models.DecimalField):
                    self.stream.write("    if %s is not None: %s = Decimal(%s)\n" % (f.attname, f.attname, f.attname))
                elif isinstance(f, ChoiceListField):
                    lstname = "settings.SITE.modules.{0}.{1}".format(f.choicelist.app_label, f.choicelist.__name__)
                    ln = "    if {0}: {0} = {1}.get_by_value({0})\n"
                    self.stream.write(ln.format(f.attname, lstname))
                elif is_pointer_to_contenttype(f):
                    self.stream.write("    %s = new_content_type_id(%s)\n" % (f.attname, f.attname))

            if model._meta.parents:
                if len(model._meta.parents) != 1:
                    msg = "%s : model._meta.parents is %r" % (model, model._meta.parents)
                    raise Exception(msg)
                pm, pf = list(model._meta.parents.items())[0]
                child_fields = [f for f in fields if f != pf]
                if child_fields:
                    attrs = "," + ",".join(["%s=%s" % (f.attname, f.attname) for f in child_fields])
                else:
                    attrs = ""
                self.stream.write(
                    "    return create_mti_child(%s, %s, %s%s)\n"
                    % (full_model_name(pm, "_"), pf.attname, full_model_name(model, "_"), attrs)
                )
            else:
                self.stream.write("    kw = dict()\n")
                for f in fields:
                    if getattr(f, "_lino_babel_field", False):
                        continue
                    elif isinstance(f, (BabelCharField, BabelTextField)):
                        self.stream.write(
                            "    if %s is not None: kw.update(bv2kw(%r,%s))\n" % (f.attname, f.attname, f.attname)
                        )
                    else:
                        self.stream.write("    kw.update(%s=%s)\n" % (f.attname, f.attname))

                self.stream.write("    return %s(**kw)\n\n" % full_model_name(model, "_"))
        self.stream.write("\n")
        # ~ used_models = set()

        self.stream.write(
            """

def main():
    loader = DpyLoader(globals())
    from django.core.management import call_command
    # call_command('initdb', interactive=False)
    call_command('initdb')
    os.chdir(os.path.dirname(__file__))
    loader.initialize()

"""
        )

        for model in progress.bar(self.models):
            filename = "%s.py" % model._meta.db_table
            filename = os.path.join(self.output_dir, filename)
            # puts("Writing {0}...".format(filename))
            stream = file(filename, "wt")
            stream.write("# -*- coding: UTF-8 -*-\n")
            qs = model.objects.all()
            try:
                stream.write('logger.info("Loading %d objects to table %s...")\n' % (qs.count(), model._meta.db_table))

                if AFTER17:
                    fields = [f for f in model._meta.get_fields() if f.concrete and f.model is model]
                else:
                    fields = [f for f, m in model._meta.get_fields_with_model() if m is None]
                fields = [f for f in fields if not getattr(f, "_lino_babel_field", False)]
                stream.write("# fields: %s\n" % ", ".join([f.name for f in fields]))
                for obj in qs:
                    self.count_objects += 1
                    # ~ used_models.add(model)
                    stream.write(
                        "loader.save(create_%s(%s))\n"
                        % (obj._meta.db_table, ",".join([self.value2string(obj, f) for f in fields]))
                    )
                stream.write("\n")
                stream.write("loader.flush_deferred_objects()\n")
            except ProgrammingError as e:
                if not self.options["tolerate"]:
                    raise
                stream.write("\n")
                logger.warning("Tolerating database error %s in %s", e, model._meta.db_table)
                msg = ("The data of this table has not been dumped" "because an error {0} occured.").format(e)
                stream.write('raise Exception("{0}")\n'.format(msg))

            stream.close()

            # ~ self.stream.write('\nfilename = os.path.join(os.path.dirname(__file__),"%s.py")\n' % )
            self.stream.write('    execfile("%s.py")\n' % model._meta.db_table)

        self.stream.write("    loader.finalize()\n")
        # self.stream.write(
        #     '    logger.info("Loaded %d objects",loader.count_objects)\n')
        self.stream.write(
            """
if __name__ == '__main__':
    main()
"""
        )
        # ~ self.stream.write('\nsettings.SITE.load_from_file(globals())\n')
        self.stream.close()
Пример #33
0
def make_remote_field(model, name):
    parts = name.split('__')
    if len(parts) == 1:
        return
    # It's going to be a RemoteField
    # logger.warning("20151203 RemoteField %s in %s", name, cls)

    from lino.core import store
    cls = model
    field_chain = []
    editable = False
    for n in parts:
        if model is None:
            raise Exception(
                "Invalid remote field {0} for {1}".format(name, cls))

        if isinstance(model, six.string_types):
            # Django 1.9 no longer resolves the
            # rel.model of ForeignKeys on abstract
            # models, so we do it here.
            model = resolve_model(model)
            # logger.warning("20151203 %s", model)

        fld = model.get_data_elem(n)
        if fld is None:
            raise Exception(
                "Invalid RemoteField %s.%s (no field %s in %s)" %
                (full_model_name(model), name, n, full_model_name(model)))
        # make sure that the atomizer gets created.
        store.get_atomizer(model, fld, fld.name)
        field_chain.append(fld)
        if isinstance(fld, models.OneToOneRel):
            editable = True
        if getattr(fld, 'remote_field', None):
            model = fld.remote_field.model
        elif getattr(fld, 'rel', None):
            raise Exception("20180712")
            model = fld.rel.model
        else:
            model = None

    def getter(obj, ar=None):
        try:
            for fld in field_chain:
                if obj is None:
                    return None
                obj = fld._lino_atomizer.full_value_from_object(
                    obj, ar)
            return obj
        except Exception as e:
            # raise
            msg = "Error while computing {}: {} ({} in {})"
            raise Exception(msg.format(
                name, e, fld, field_chain))
            # ~ if False: # only for debugging
            if True:  # see 20130802
                logger.exception(e)
                return str(e)
            return None

    if not editable:
        return RemoteField(getter, name, fld)

    def setter(obj, value):
        # logger.info("20180712 %s setter() %s", name, value)
        # all intermediate fields are OneToOneRel
        target = obj
        try:
            for fld in field_chain:
                # print("20180712a %s" % fld)
                if isinstance(fld, models.OneToOneRel):
                    reltarget = getattr(target, fld.name, None)
                    if reltarget is None:
                        rkw = { fld.field.name: target}
                        # print(
                        #     "20180712 create {}({})".format(
                        #         fld.related_model, rkw))
                        reltarget = fld.related_model(**rkw)
                        reltarget.full_clean()
                        reltarget.save()

                    setattr(target, fld.name, reltarget)
                    target.full_clean()
                    target.save()
                    # print("20180712b {}.{} = {}".format(
                    #     target, fld.name, reltarget))
                    target = reltarget
                else:
                    setattr(target, fld.name, value)
                    target.full_clean()
                    target.save()
                    # print(
                    #     "20180712c setattr({},{},{}".format(
                    #         target, fld.name, value))
                    return True
        except Exception as e:
            raise e.__class__(
                "Error while setting %s: %s" % (name, e))
            # ~ if False: # only for debugging
            if True:  # see 20130802
                logger.exception(e)
                return str(e)
            return False

    return RemoteField(getter, name, fld, setter)
Пример #34
0
    def write_files(self):
        puts("Writing {0}...".format(self.main_file))
        self.stream = open(self.main_file, 'wt')
        current_version = settings.SITE.version

        self.stream.write('''\
#!/usr/bin/env python
# -*- coding: UTF-8 -*-

# This is a Python dump created using dump2py.
# DJANGO_SETTINGS_MODULE was %r, TIME_ZONE was %r.

''' % (settings.SETTINGS_MODULE, settings.TIME_ZONE))

        self.stream.write('''
from __future__ import unicode_literals

import logging
logger = logging.getLogger('%s')

''' % __name__)

        self.stream.write('SOURCE_VERSION = %r\n' % str(current_version))
        self.stream.write('''
import os
import six
from decimal import Decimal
from datetime import datetime
from datetime import time, date
from django.conf import settings
from django.utils.timezone import make_aware, utc
from django.core.management import call_command
# from django.contrib.contenttypes.models import ContentType
from lino.utils.dpy import create_mti_child
from lino.utils.dpy import DpyLoader
from lino.core.utils import resolve_model

if settings.USE_TZ:
    def dt(*args):
        return make_aware(datetime(*args), timezone=utc)
else:
    def dt(*args):
        return datetime(*args)

def new_content_type_id(m):
    if m is None: return m
    ct = settings.SITE.models.contenttypes.ContentType.objects.get_for_model(m)
    if ct is None: return None
    return ct.pk

def pmem():
    # Thanks to https://stackoverflow.com/questions/938733/total-memory-used-by-python-process
    process = psutil.Process(os.getpid())
    print(process.memory_info().rss)

def execfile(fn, *args):
    logger.info("Execute file %s ...", fn)
    six.exec_(compile(open(fn, "rb").read(), fn, 'exec'), *args)
    # pmem()  # requires pip install psutil

''')
        s = ','.join([
            '%s=values[%d]' % (lng.name, lng.index)
            for lng in settings.SITE.languages
        ])
        self.stream.write('''
def bv2kw(fieldname, values):
    """
    Needed if `Site.languages` changed between dumpdata and loaddata
    """
    return settings.SITE.babelkw(fieldname, %s)

''' % s)
        self.models = sorted_models_list()

        if settings.SITE.is_installed('contenttypes'):
            from django.contrib.contenttypes.models import ContentType
            self.models = [
                m for m in self.models if not issubclass(m, ContentType)
            ]

        if settings.SITE.is_installed('sessions'):
            from django.contrib.sessions.models import Session
            self.models = [
                m for m in self.models if not issubclass(m, Session)
            ]

        for model in self.models:
            self.stream.write(
                '%s = resolve_model("%s")\n' %
                (full_model_name(model, '_'), full_model_name(model)))
        self.stream.write('\n')
        self.models = self.sort_models(self.models)
        self.stream.write('\n')
        for model in self.models:
            write_create_function(model, self.stream)
        self.stream.write('\n')
        #~ used_models = set()

        self.stream.write("""

def main(args):
    loader = DpyLoader(globals(), quick=args.quick)
    from django.core.management import call_command
    call_command('initdb', interactive=args.interactive)
    os.chdir(os.path.dirname(__file__))
    loader.initialize()
    args = (globals(), locals())

""")

        max_row_count = self.options['max_row_count']
        for model in progress.bar(self.models):
            try:
                qs = model.objects.all()
                total_count = qs.count()
            except DatabaseError as e:
                self.database_errors += 1
                if not self.options['tolerate']:
                    raise
                self.stream.write('\n')
                logger.warning("Tolerating database error %s in %s", e,
                               model._meta.db_table)
                msg = ("The data of table {0} has not been dumped"
                       "because an error {1} occured.").format(
                           model._meta.db_table, e)
                self.stream.write('raise Exception("{0}")\n'.format(msg))
                continue

            fields = [
                f for f in model._meta.get_fields()
                if f.concrete and f.model is model
            ]
            fields = [
                f for f in fields if not getattr(f, '_lino_babel_field', False)
            ]

            chunks = []  # list of tuples (i, filename, queryset)
            if total_count > max_row_count:
                num_files = (total_count // max_row_count) + 1
                for i in range(num_files):
                    o1 = max_row_count * i
                    o2 = max_row_count * (i + 1)
                    t = (i + 1, '%s_%d.py' % (model._meta.db_table, i + 1),
                         qs[o1:o2])
                    chunks.append(t)
            else:
                chunks.append((1, '%s.py' % model._meta.db_table, qs))
            for i, filename, qs in chunks:
                self.stream.write('    execfile("%s", *args)\n' % filename)
                filename = os.path.join(self.output_dir, filename)
                # puts("Writing {0}...".format(filename))
                # stream = file(filename, 'wt')
                stream = open(filename, 'wt')
                stream.write('# -*- coding: UTF-8 -*-\n')
                txt = "%d objects" % total_count
                if len(chunks) > 1:
                    txt += " (part %d of %d)" % (i, len(chunks))
                stream.write('logger.info("Loading %s to table %s...")\n' %
                             (txt, model._meta.db_table))

                stream.write("# fields: %s\n" %
                             ', '.join([f.name for f in fields]))
                for obj in qs:
                    self.count_objects += 1
                    #~ used_models.add(model)
                    stream.write(
                        'loader.save(create_%s(%s))\n' %
                        (obj._meta.db_table, ','.join(
                            [self.value2string(obj, f) for f in fields])))
                stream.write('\n')
                if i == len(chunks):
                    stream.write('loader.flush_deferred_objects()\n')

                stream.close()

            #~ self.stream.write('\nfilename = os.path.join(os.path.dirname(__file__),"%s.py")\n' % )

        self.stream.write('    loader.finalize()\n')
        # 20180416 why was the following message commented out?
        # reactivated it because otherwise we have no log entry when
        # the process has finished.
        self.stream.write(
            '    logger.info("Loaded %d objects", loader.count_objects)\n')
        self.stream.write("    call_command('resetsequences')\n")

        self.stream.write("""
if __name__ == '__main__':
    import argparse
    parser = argparse.ArgumentParser(description='Restore the data.')
    parser.add_argument('--noinput', dest='interactive',
        action='store_false', default=True,
        help="Don't ask for confirmation before flushing the database.")
    parser.add_argument('--quick', dest='quick',
        action='store_true',default=False,
        help='Do not call full_clean() on restored instances.')

    args = parser.parse_args()
    main(args)
""")
        #~ self.stream.write('\nsettings.SITE.load_from_file(globals())\n')
        self.stream.close()
Пример #35
0
    def write_files(self):
        puts("Writing {0}...".format(self.main_file))
        self.stream = open(self.main_file, 'wt')
        current_version = settings.SITE.version

        self.stream.write('''\
#!/usr/bin/env python
# -*- coding: UTF-8 -*-

# This is a Python dump created using dump2py.
# DJANGO_SETTINGS_MODULE was %r, TIME_ZONE was %r.

''' % (settings.SETTINGS_MODULE, settings.TIME_ZONE))

        self.stream.write('''
from __future__ import unicode_literals

import logging
logger = logging.getLogger('%s')
import os

''' % __name__)

        self.stream.write('SOURCE_VERSION = %r\n' % str(current_version))
        self.stream.write('''
from decimal import Decimal
from datetime import datetime
from datetime import time, date
from django.conf import settings
from django.utils.timezone import make_aware
# from django.contrib.contenttypes.models import ContentType
from lino.utils.dpy import create_mti_child
from lino.utils.dpy import DpyLoader
from lino.core.utils import resolve_model

if settings.USE_TZ:
    def dt(*args):
        return make_aware(datetime(*args))
else:
    def dt(*args):
        return datetime(*args)
        
def new_content_type_id(m):
    if m is None: return m
    ct = settings.SITE.models.contenttypes.ContentType.objects.get_for_model(m)
    if ct is None: return None
    return ct.pk
    
''')
        s = ','.join([
            '%s=values[%d]' % (lng.name, lng.index)
            for lng in settings.SITE.languages
        ])
        self.stream.write('''
def bv2kw(fieldname, values):
    """
    Needed if `Site.languages` changed between dumpdata and loaddata
    """
    return settings.SITE.babelkw(fieldname, %s)
    
''' % s)
        self.models = sorted_models_list()

        if settings.SITE.is_installed('contenttypes'):
            from django.contrib.contenttypes.models import ContentType
            self.models = [
                m for m in self.models if not issubclass(m, ContentType)
            ]

        if settings.SITE.is_installed('sessions'):
            from django.contrib.sessions.models import Session
            self.models = [
                m for m in self.models if not issubclass(m, Session)
            ]

        for model in self.models:
            self.stream.write(
                '%s = resolve_model("%s")\n' %
                (full_model_name(model, '_'), full_model_name(model)))
        self.stream.write('\n')
        self.models = self.sort_models(self.models)
        self.stream.write('\n')
        for model in self.models:
            fields = [
                f for f in model._meta.get_fields()
                if f.concrete and f.model is model
            ]
            for f in fields:
                if getattr(f, 'auto_now_add', False):
                    raise Exception(
                        "%s.%s.auto_now_add is True : values will be lost!" %
                        (full_model_name(model), f.name))
            #~ fields = model._meta.local_fields
            #~ fields = [f for f in model._meta.fields if f.serialize]
            #~ fields = [f for f in model._meta.local_fields if f.serialize]
            self.stream.write('def create_%s(%s):\n' %
                              (model._meta.db_table, ', '.join([
                                  f.attname for f in fields
                                  if not getattr(f, '_lino_babel_field', False)
                              ])))
            for f in fields:
                if isinstance(f, models.DecimalField):
                    self.stream.write(
                        '    if %s is not None: %s = Decimal(%s)\n' %
                        (f.attname, f.attname, f.attname))
                elif isinstance(f, ChoiceListField):
                    lstname = 'settings.SITE.modules.{0}.{1}'.format(
                        f.choicelist.app_label, f.choicelist.__name__)
                    ln = '    if {0}: {0} = {1}.get_by_value({0})\n'
                    self.stream.write(ln.format(f.attname, lstname))
                elif is_pointer_to_contenttype(f):
                    self.stream.write('    %s = new_content_type_id(%s)\n' %
                                      (f.attname, f.attname))

            if model._meta.parents:
                if len(model._meta.parents) != 1:
                    msg = "%s : model._meta.parents is %r" % (
                        model, model._meta.parents)
                    raise Exception(msg)
                pm, pf = list(model._meta.parents.items())[0]
                child_fields = [f for f in fields if f != pf]
                if child_fields:
                    attrs = ',' + ','.join([
                        '%s=%s' % (f.attname, f.attname) for f in child_fields
                    ])
                else:
                    attrs = ''
                self.stream.write(
                    '    return create_mti_child(%s, %s, %s%s)\n' %
                    (full_model_name(pm, '_'), pf.attname,
                     full_model_name(model, '_'), attrs))
            else:
                self.stream.write("    kw = dict()\n")
                for f in fields:
                    if getattr(f, '_lino_babel_field', False):
                        continue
                    elif isinstance(f, (BabelCharField, BabelTextField)):
                        self.stream.write(
                            '    if %s is not None: kw.update(bv2kw(%r,%s))\n'
                            % (f.attname, f.attname, f.attname))
                    else:
                        self.stream.write('    kw.update(%s=%s)\n' %
                                          (f.attname, f.attname))

                self.stream.write('    return %s(**kw)\n\n' %
                                  full_model_name(model, '_'))
        self.stream.write('\n')
        #~ used_models = set()

        self.stream.write("""

def main(args):
    loader = DpyLoader(globals())
    from django.core.management import call_command
    call_command('initdb', interactive=args.interactive)
    os.chdir(os.path.dirname(__file__))
    loader.initialize()

""")

        for model in progress.bar(self.models):
            filename = '%s.py' % model._meta.db_table
            filename = os.path.join(self.output_dir, filename)
            # puts("Writing {0}...".format(filename))
            # stream = file(filename, 'wt')
            stream = open(filename, 'wt')
            stream.write('# -*- coding: UTF-8 -*-\n')
            qs = model.objects.all()
            try:
                stream.write(
                    'logger.info("Loading %d objects to table %s...")\n' %
                    (qs.count(), model._meta.db_table))

                fields = [
                    f for f in model._meta.get_fields()
                    if f.concrete and f.model is model
                ]
                fields = [
                    f for f in fields
                    if not getattr(f, '_lino_babel_field', False)
                ]
                stream.write("# fields: %s\n" %
                             ', '.join([f.name for f in fields]))
                for obj in qs:
                    self.count_objects += 1
                    #~ used_models.add(model)
                    stream.write(
                        'loader.save(create_%s(%s))\n' %
                        (obj._meta.db_table, ','.join(
                            [self.value2string(obj, f) for f in fields])))
                stream.write('\n')
                stream.write('loader.flush_deferred_objects()\n')
            except DatabaseError as e:
                self.database_errors += 1
                if not self.options['tolerate']:
                    raise
                stream.write('\n')
                logger.warning("Tolerating database error %s in %s", e,
                               model._meta.db_table)
                msg = ("The data of this table has not been dumped"
                       "because an error {0} occured.").format(e)
                stream.write('raise Exception("{0}")\n'.format(msg))

            stream.close()

            #~ self.stream.write('\nfilename = os.path.join(os.path.dirname(__file__),"%s.py")\n' % )
            self.stream.write('    execfile("%s.py")\n' % model._meta.db_table)

        self.stream.write('    loader.finalize()\n')
        # self.stream.write(
        #     '    logger.info("Loaded %d objects",loader.count_objects)\n')
        self.stream.write("""
if __name__ == '__main__':
    import argparse
    parser = argparse.ArgumentParser(description='Restore the data.')
    parser.add_argument('--noinput', dest='interactive',
        action='store_false', default=True,
        help="Don't ask for confirmation before flushing the database.")

    args = parser.parse_args()
    main(args)
""")
        #~ self.stream.write('\nsettings.SITE.load_from_file(globals())\n')
        self.stream.close()
Пример #36
0
def model_name(m):
    return settings.SITE.userdocs_prefix + full_model_name(m).lower()
Пример #37
0
    def get_rst(self):
        #~ from actordoc import get_actor_description
        #~ from django.conf import settings
        #~ from djangosite.dbutils import set_language
        with translation.override(self.language):
            level, cls = resolve_name(self.content[0])
            if isinstance(cls, models.Field):
                fld = cls
                s = ''
                name = str(fld.model) + '.' + fld.name
                title = force_unicode(fld.verbose_name).strip()

                s += "\n.. index::\n   single: "
                s += unicode(
                    _('%(field)s (field in %(model)s)') %
                    dict(field=title, model=model_ref(fld.model)))
                s += '\n\n'
                s += rstgen.header(level, _("%s (field)") % title)
                if len(self.content) > 1:
                    s += '\n'.join(self.content[1:])
                    s += '\n\n'
                return s

            if isinstance(cls, Plugin):
                s = ''
                title = unicode(cls.verbose_name)
                s += "\n.. index::\n   single: "
                s += unicode(_('%s (app)') % title)
                s += '\n\n.. _' + name + ':\n'
                s += '\n'
                s += rstgen.header(level, _("%s (app)") % title)
                return s

            if not isinstance(cls, type):
                raise Exception("%s is not an actor." % self.content[0])

            if issubclass(cls, models.Model):
                model = cls

                s = ''
                name = model_name(model).lower()
                title = force_unicode(model._meta.verbose_name)
                s += "\n.. index::\n   single: "
                s += unicode(
                    _('%(model)s (model in %(app)s)') %
                    dict(model=title, app=model._meta.app_label))

                s += '\n\n'

                s += '\n\n.. _' + name + ':\n'

                s += '\n'
                s += rstgen.header(level, _("%s (model)") % title)

                s += '\n'
                s += '\n:Internal name: ``%s``\n' % full_model_name(cls)
                s += '\n:Implemented by: %s\n' % typeref(cls)
                s += '\n'

                if len(self.content) > 1:
                    s += '\n'.join(self.content[1:])
                    s += '\n\n'

                model_reports = [
                    r for r in dbtables.master_reports if r.model is cls
                ]
                model_reports += [
                    r for r in dbtables.slave_reports if r.model is cls
                ]
                s += rstgen.boldheader(
                    _("Views on %s") % cls._meta.verbose_name)
                s += actors_overview_ul(model_reports)

                s += rstgen.boldheader(
                    _("Fields in %s") % cls._meta.verbose_name)
                s += fields_ul(cls._meta.fields)

                action_list = cls.get_default_table().get_actions()
                action_list = [
                    ba for ba in action_list
                    if not isinstance(ba.action, IGNORED_ACTIONS)
                ]
                if action_list:
                    s += '\n'
                    s += rstgen.boldheader(
                        _("Actions on %s") % cls._meta.verbose_name)
                    s += actions_ul(action_list)

                slave_tables = getattr(cls, '_lino_slaves', {}).values()
                if slave_tables:
                    s += rstgen.boldheader(
                        _("Tables referring to %s") % cls._meta.verbose_name)
                    s += actors_overview_ul(slave_tables)

                return s

            if issubclass(cls, actors.Actor):

                title = force_unicode(cls.label or cls.title)
                indextext = _('%(actor)s (view in %(app)s)') % dict(
                    actor=title, app=cls.app_label)
                name = actor_name(cls)
                #~ if name == 'welfare.reception.waitingvisitors':
                #~ self.debug = True
                #~ print(20130907, name)
                self.index_entries.append(('single', indextext, name, ''))
                #~ self.add_ref_target(name,name)

                s = ''
                s += '\n\n.. _%s:\n\n' % name
                s += rstgen.header(level, _("%s (view)") % title)
                s += '\n:Internal name: ``%s`` (%s)\n' % (cls, typeref(cls))

                if len(self.content) > 1:
                    s += '\n'.join(self.content[1:])
                    s += '\n\n'

                s += '\n\n'
                s += get_actor_description(cls)
                s += '\n\n'
                return s
            raise Exception("Cannot handle actor %r." % cls)
Пример #38
0
    def get_data_elem(cls, name):
        """Return the named data element. This can be a database field, a
        :class:`lino.core.fields.RemoteField`, a
        :class:`lino.core.fields.VirtualField` or a Django-style
        virtual field (GenericForeignKey).

        """
        #~ logger.info("20120202 get_data_elem %r,%r",model,name)
        if not name.startswith('__'):
            parts = name.split('__')
            if len(parts) > 1:
                # It's going to be a RemoteField
                # logger.warning("20151203 RemoteField %s in %s", name, cls)

                from lino.core import store

                model = cls
                field_chain = []
                editable = False
                for n in parts:
                    if model is None:
                        raise Exception(
                            "Invalid remote field {0} for {1}".format(
                                name, cls))

                    if isinstance(model, six.string_types):
                        # Django 1.9 no longer resolves the
                        # rel.model of ForeignKeys on abstract
                        # models, so we do it here.
                        model = resolve_model(model)
                        # logger.warning("20151203 %s", model)

                    fld = model.get_data_elem(n)
                    if fld is None:
                        raise Exception(
                            "Invalid RemoteField %s.%s (no field %s in %s)" %
                            (full_model_name(model), name, n,
                             full_model_name(model)))
                    # make sure that the atomizer gets created.
                    store.get_atomizer(model, fld, fld.name)
                    field_chain.append(fld)
                    if isinstance(fld, models.OneToOneRel):
                        editable = True
                    if getattr(fld, 'remote_field', None):
                        model = fld.remote_field.model
                    elif getattr(fld, 'rel', None):
                        raise Exception("20180712")
                        model = fld.rel.model
                    else:
                        model = None

                def getter(obj, ar=None):
                    try:
                        for fld in field_chain:
                            if obj is None:
                                return None
                            obj = fld._lino_atomizer.full_value_from_object(
                                obj, ar)
                        return obj
                    except Exception as e:
                        # raise
                        msg = "Error while computing {}: {} ({} in {})"
                        raise Exception(msg.format(name, e, fld, field_chain))
                        # ~ if False: # only for debugging
                        if True:  # see 20130802
                            logger.exception(e)
                            return str(e)
                        return None

                if not editable:
                    return fields.RemoteField(getter, name, fld)

                def setter(obj, value):
                    # logger.info("20180712 %s setter() %s", name, value)
                    # all intermediate fields are OneToOneRel
                    target = obj
                    try:
                        for fld in field_chain:
                            # print("20180712a %s" % fld)
                            if isinstance(fld, models.OneToOneRel):
                                reltarget = getattr(target, fld.name, None)
                                if reltarget is None:
                                    rkw = {fld.field.name: target}
                                    # print(
                                    #     "20180712 create {}({})".format(
                                    #         fld.related_model, rkw))
                                    reltarget = fld.related_model(**rkw)
                                    reltarget.full_clean()
                                    reltarget.save()

                                setattr(target, fld.name, reltarget)
                                target.full_clean()
                                target.save()
                                # print("20180712b {}.{} = {}".format(
                                #     target, fld.name, reltarget))
                                target = reltarget
                            else:
                                setattr(target, fld.name, value)
                                target.full_clean()
                                target.save()
                                # print(
                                #     "20180712c setattr({},{},{}".format(
                                #         target, fld.name, value))
                                return True
                    except Exception as e:
                        raise Exception("Error while setting %s: %s" %
                                        (name, e))
                        # ~ if False: # only for debugging
                        if True:  # see 20130802
                            logger.exception(e)
                            return str(e)
                        return False

                return fields.RemoteField(getter, name, fld, setter)

        try:
            return cls._meta.get_field(name)
        except models.FieldDoesNotExist:
            pass

        v = get_class_attr(cls, name)
        if v is not None:
            return v

        for vf in cls._meta.private_fields:
            if vf.name == name:
                return vf
Пример #39
0
 def __init__(self, model, *args, **kwargs):
     self.model = model
     self.template_name = "noi/{0}.html".format(full_model_name(model))
     super(TemplateView, self).__init__(*args, **kwargs)
Пример #40
0
 def __init__(self, model, *args, **kwargs):
     self.model = model
     self.template_name = "noi/{0}.html".format(full_model_name(model))
     super(TemplateView, self).__init__(*args, **kwargs)
Пример #41
0
    def get_data_elem(cls, name):
        """Return the named data element. This can be a database field, a
        :class:`lino.core.fields.RemoteField`, a
        :class:`lino.core.fields.VirtualField` or a Django-style
        virtual field (GenericForeignKey).

        """
        #~ logger.info("20120202 get_data_elem %r,%r",model,name)
        if not name.startswith('__'):
            parts = name.split('__')
            if len(parts) > 1:
                # It's going to be a RemoteField
                # logger.warning("20151203 RemoteField %s in %s", name, cls)

                from lino.core import store

                model = cls
                field_chain = []
                for n in parts:
                    if model is None:
                        raise Exception(
                            "Invalid remote field {0} for {1}".format(name, cls))

                    if isinstance(model, six.string_types):
                        model = resolve_model(model)
                        # logger.warning("20151203 %s", model)
                        # Django 1.9 no longer resolves the
                        # rel.model of ForeignKeys on abstract
                        # models.

                    # ~ 20130508 model.get_default_table().get_handle() # make sure that all atomizers of those fields get created.
                    fld = model.get_data_elem(n)
                    if fld is None:
                        # raise Exception("Part %s of %s got None" % (n,model))
                        raise Exception(
                            "Invalid RemoteField %s.%s (no field %s in %s)" %
                            (full_model_name(model), name, n, full_model_name(model)))
                    # make sure that the atomizer gets created.
                    store.get_atomizer(model, fld, fld.name)
                    field_chain.append(fld)
                    if getattr(fld, 'rel', None):
                        if AFTER18:
                            model = fld.rel.model
                        else:
                            model = fld.rel.to
                    else:
                        model = None

                def func(obj, ar=None):
                    try:
                        for fld in field_chain:
                            if obj is None:
                                return obj
                            obj = fld._lino_atomizer.full_value_from_object(
                                obj, ar)
                        return obj
                    except Exception as e:
                        raise Exception(
                            "Error while computing %s: %s" % (name, e))
                        # ~ if False: # only for debugging
                        if True:  # see 20130802
                            logger.exception(e)
                            return str(e)
                        return None
                return fields.RemoteField(func, name, fld)

        try:
            return cls._meta.get_field(name)
        except models.FieldDoesNotExist:
            pass

        v = get_class_attr(cls, name)
        if v is not None:
            return v

        for vf in cls._meta.virtual_fields:
            if vf.name == name:
                return vf
Пример #42
0
    def serialize(self, queryset, **options):
        from django.contrib.sessions.models import Session
        from django.contrib.contenttypes.models import ContentType
        self.options = options

        self.stream = options.get("stream", StringIO())
        self.selected_fields = options.get("fields")
        self.use_natural_keys = options.get("use_natural_keys", False)
        if self.write_preamble:
            current_version = settings.SITE.version
            if '+' in current_version:
                logger.warning(
                    "Dumpdata from intermediate version %s" % current_version)

            self.stream.write('# -*- coding: UTF-8 -*-\n')
            self.stream.write('''\
"""
This is a `Python dump created using %s.
''' % settings.SITE.using_text())
            #~ self.stream.write(settings.SITE.welcome_text())
            self.stream.write('''
"""
from __future__ import unicode_literals
''')
            self.stream.write('SOURCE_VERSION = %r\n' % str(current_version))
            self.stream.write('from decimal import Decimal\n')
            self.stream.write('from datetime import datetime as dt\n')
            self.stream.write('from datetime import time,date\n')
            self.stream.write('from lino.utils.dpy import create_mti_child\n')
            self.stream.write('from lino.utils.dbutils import resolve_model\n')
            self.stream.write(
                'from lino.modlib.gfks.models import ContentType\n')
            self.stream.write('from django.conf import settings\n')
            self.stream.write('''
            
def new_content_type_id(m):
    if m is None: return m
    # if not fmn: return None
    # m = resolve_model(fmn)
    ct = ContentType.objects.get_for_model(m)
    if ct is None: return None
    return ct.pk
    
''')
            #~ s = ','.join([
              #~ '%s=values[%d]' % (k,i)
                #~ for i,k in enumerate(settings.SITE.AVAILABLE_LANGUAGES)])
            s = ','.join([
                '%s=values[%d]' % (lng.name, lng.index)
                for lng in settings.SITE.languages])
            self.stream.write('''
def bv2kw(fieldname,values):
    """
    Needed if `Site.languages` changed between dumpdata and loaddata
    """
    return settings.SITE.babelkw(fieldname,%s)
    
''' % s)
        #~ model = queryset.model
        if self.models is None:
            self.models = sorted_models_list()  # models.get_models()
        if self.write_preamble:
            for model in self.models:
                self.stream.write('%s = resolve_model("%s")\n' % (
                    full_model_name(model, '_'), full_model_name(model)))
        self.stream.write('\n')
        for model in self.models:
            fields = [f for f,
                      m in model._meta.get_fields_with_model() if m is None]
            for f in fields:
                if getattr(f, 'auto_now_add', False):
                    raise Exception("%s.%s.auto_now_add is True : values will be lost!" % (
                        full_model_name(model), f.name))
            field_names = [f.attname for f in fields
                           if not getattr(f, '_lino_babel_field', False)]
            self.stream.write('def create_%s(%s):\n' % (
                model._meta.db_table, ', '.join(field_names)))
            if model._meta.parents:
                if len(model._meta.parents) != 1:
                    msg = "%s : model._meta.parents is %r" % (
                        model, model._meta.parents)
                    raise Exception(msg)
                pm, pf = list(model._meta.parents.items())[0]
                child_fields = [f for f in fields if f != pf]
                if child_fields:
                    attrs = ', ' + ', '.join([
                        '%s=%s' % (f.attname, f.attname)
                        for f in child_fields])
                else:
                    attrs = ''
                tpl = '    return create_mti_child(%s, %s, %s%s)\n'
                self.stream.write(tpl % (
                    full_model_name(pm, '_'),
                    pf.attname, full_model_name(model, '_'), attrs))
            else:
                self.stream.write("    kw = dict()\n")
                for f in fields:
                    if getattr(f, '_lino_babel_field', False):
                        continue
                    elif isinstance(f, (BabelCharField, BabelTextField)):
                        tpl = '    if %s is not None:'
                        tpl += ' kw.update(bv2kw(%r, %s))\n'
                        self.stream.write(
                            tpl % (f.attname, f.attname, f.attname))
                    else:
                        if isinstance(f, models.DecimalField):
                            self.stream.write(
                                '    if %s is not None: %s = Decimal(%s)\n' % (
                                    f.attname, f.attname, f.attname))
                        elif isinstance(f, ChoiceListField):
                            lstname = 'settings.SITE.modules.{0}.{1}'.format(
                                f.choicelist.app_label, f.choicelist.__name__)
                            ln = '    if {0}: {0} = {1}.get_by_value({0})\n'
                            self.stream.write(ln.format(f.attname, lstname))
                        elif isinstance(f, ForeignKey):
                            if f.rel.model is ContentType:
                                self.stream.write(
                                    '    %s = new_content_type_id(%s)\n' % (
                                        f.attname, f.attname))
                        self.stream.write(
                            '    kw.update(%s=%s)\n' % (f.attname, f.attname))

                self.stream.write('    return %s(**kw)\n\n' %
                                  full_model_name(model, '_'))
        #~ self.start_serialization()
        self.stream.write('\n')
        model = None
        all_models = []
        for obj in queryset:
            if isinstance(obj, ContentType):
                continue
            if isinstance(obj, Session):
                continue
            if obj.__class__ != model:
                model = obj.__class__
                if model in all_models:
                    raise Exception("%s instances weren't grouped!" % model)
                all_models.append(model)
                self.stream.write('\ndef %s_objects():\n' %
                                  model._meta.db_table)
            fields = [f for f,
                      m in model._meta.get_fields_with_model() if m is None]
            fields = [
                f for f in fields if not getattr(f, '_lino_babel_field', False)]
            self.stream.write('    yield create_%s(%s)\n' % (
                obj._meta.db_table,
                ','.join([self.value2string(obj, f) for f in fields])))
        self.stream.write('\n\ndef objects():\n')
        all_models = self.sort_models(all_models)
        for model in all_models:
            #~ self.stream.write('    for o in %s_objects(): yield o\n' % model._meta.db_table)
            self.stream.write('    yield %s_objects()\n' %
                              model._meta.db_table)
Пример #43
0
    def test_controllables(self):
        found = []
        for M in rt.models_by_base(Controllable):
            found.append(full_model_name(M))
        expected = """cal.Event cal.Task
        checkdata.Problem
        comments.Comment
        comments.Mention
        excerpts.Excerpt
        notes.Note
        notify.Message
        uploads.Upload
        """.split()
        self.assertEqual(found, expected)

        Person = rt.models.contacts.Person
        Note = rt.models.notes.Note
        Excerpt = rt.models.excerpts.Excerpt
        ExcerptType = rt.models.excerpts.ExcerptType
        ContentType = rt.models.contenttypes.ContentType
        self.assertEqual(len(Person.allow_cascaded_delete), 0)
        self.assertEqual(len(Note.allow_cascaded_delete), 0)
        self.assertEqual(len(Excerpt.allow_cascaded_delete), 1)

        doe = create(Person, first_name="John", last_name="Doe")
        note = create(Note, owner=doe, body="John Doe is a fink!")
        ct = ContentType.objects.get_for_model(Note)
        etype = create(ExcerptType, name="Note", content_type=ct)
        excerpt = create(Excerpt, owner=note, excerpt_type=etype)

        self.assertEqual(Person.objects.count(), 1)
        self.assertEqual(Note.objects.count(), 1)
        self.assertEqual(Excerpt.objects.count(), 1)

        ar = rt.models.notes.Notes.request()
        s = ar.to_rst(column_names="id owner")
        self.assertEqual(
            s, """\
==== ===============
 ID   Controlled by
---- ---------------
 1    *John Doe*
==== ===============

""")

        ar = rt.models.excerpts.Excerpts.request()
        s = ar.to_rst(column_names="id owner")
        self.assertEqual(
            s, """\
==== ===============
 ID   Controlled by
---- ---------------
 1    *Note #1*
==== ===============

""")

        self.assertEqual(excerpt.disable_delete(), None)
        self.assertEqual(note.disable_delete(), None)
        self.assertEqual(doe.disable_delete(), None)
        # it is not "Cannot delete John Doe because 1 Notes refer to
        # it." because Note.owner is nullable.

        note.delete()
        self.assertEqual(Excerpt.objects.count(), 0)
        self.assertEqual(ExcerptType.objects.count(), 5)
Пример #44
0
    def write_files(self):
        puts("Writing {0}...".format(self.main_file))
        self.stream = open(self.main_file, 'wt')
        current_version = settings.SITE.version

        self.stream.write('''\
#!/usr/bin/env python
# -*- coding: UTF-8 -*-

# This is a Python dump created using dump2py.
# DJANGO_SETTINGS_MODULE was %r, TIME_ZONE was %r.

''' % (settings.SETTINGS_MODULE, settings.TIME_ZONE))

        self.stream.write('''
from __future__ import unicode_literals

import logging
logger = logging.getLogger('%s')

''' % __name__)

        self.stream.write('SOURCE_VERSION = %r\n' % str(current_version))
        self.stream.write('''
import os
import six
from decimal import Decimal
from datetime import datetime
from datetime import time, date
from django.conf import settings
from django.utils.timezone import make_aware, utc
from django.core.management import call_command
# from django.contrib.contenttypes.models import ContentType
from lino.utils.dpy import create_mti_child
from lino.utils.dpy import DpyLoader
from lino.core.utils import resolve_model

if settings.USE_TZ:
    def dt(*args):
        return make_aware(datetime(*args), timezone=utc)
else:
    def dt(*args):
        return datetime(*args)
        
def new_content_type_id(m):
    if m is None: return m
    ct = settings.SITE.models.contenttypes.ContentType.objects.get_for_model(m)
    if ct is None: return None
    return ct.pk

def pmem():
    # Thanks to https://stackoverflow.com/questions/938733/total-memory-used-by-python-process    
    process = psutil.Process(os.getpid())
    print(process.memory_info().rss)
    
def execfile(fn, *args):
    logger.info("Execute file %s ...", fn)
    six.exec_(compile(open(fn, "rb").read(), fn, 'exec'), *args)
    # pmem()  # requires pip install psutil

''')
        s = ','.join([
            '%s=values[%d]' % (lng.name, lng.index)
            for lng in settings.SITE.languages])
        self.stream.write('''
def bv2kw(fieldname, values):
    """
    Needed if `Site.languages` changed between dumpdata and loaddata
    """
    return settings.SITE.babelkw(fieldname, %s)
    
''' % s)
        self.models = sorted_models_list()
        
        if settings.SITE.is_installed('contenttypes'):
            from django.contrib.contenttypes.models import ContentType
            self.models = [m for m in self.models
                           if not issubclass(m, ContentType)]
        
        if settings.SITE.is_installed('sessions'):
            from django.contrib.sessions.models import Session
            self.models = [m for m in self.models
                           if not issubclass(m, Session)]

        for model in self.models:
            self.stream.write('%s = resolve_model("%s")\n' % (
                full_model_name(model, '_'), full_model_name(model)))
        self.stream.write('\n')
        self.models = self.sort_models(self.models)
        self.stream.write('\n')
        for model in self.models:
            write_create_function(model, self.stream)
        self.stream.write('\n')
        #~ used_models = set()

        self.stream.write("""

def main(args):
    loader = DpyLoader(globals(), quick=args.quick)
    from django.core.management import call_command
    call_command('initdb', interactive=args.interactive)
    os.chdir(os.path.dirname(__file__))
    loader.initialize()
    args = (globals(), locals())

""")

        max_row_count = self.options['max_row_count']
        for model in progress.bar(self.models):
            try:
                qs = model.objects.all()
                total_count = qs.count()
            except DatabaseError as e:
                self.database_errors += 1
                if not self.options['tolerate']:
                    raise
                self.stream.write('\n')
                logger.warning("Tolerating database error %s in %s",
                               e, model._meta.db_table)
                msg = ("The data of table {0} has not been dumped"
                       "because an error {1} occured.").format(
                           model._meta.db_table, e)
                self.stream.write('raise Exception("{0}")\n'.format(msg))
                continue

            fields = [f for f in model._meta.get_fields()
                      if f.concrete and f.model is model]
            fields = [
                f for f in fields
                if not getattr(f, '_lino_babel_field', False)]

            chunks = []  # list of tuples (i, filename, queryset)
            if total_count > max_row_count:
                num_files = (total_count // max_row_count) + 1
                for i in range(num_files):
                    o1 = max_row_count * i
                    o2 = max_row_count * (i+1)
                    t = (i+1,
                         '%s_%d.py' % (model._meta.db_table, i+1),
                         qs[o1:o2])
                    chunks.append(t)
            else:
                chunks.append((1, '%s.py' % model._meta.db_table, qs))
            for i, filename, qs in chunks:
                self.stream.write('    execfile("%s", *args)\n' % filename)
                filename = os.path.join(self.output_dir, filename)
                # puts("Writing {0}...".format(filename))
                # stream = file(filename, 'wt')
                stream = open(filename, 'wt')
                stream.write('# -*- coding: UTF-8 -*-\n')
                txt = "%d objects" % total_count
                if len(chunks) > 1:
                    txt += " (part %d of %d)" % (i, len(chunks))
                stream.write(
                    'logger.info("Loading %s to table %s...")\n' % (
                        txt, model._meta.db_table))

                stream.write(
                    "# fields: %s\n" % ', '.join(
                        [f.name for f in fields]))
                for obj in qs:
                    self.count_objects += 1
                    #~ used_models.add(model)
                    stream.write('loader.save(create_%s(%s))\n' % (
                        obj._meta.db_table,
                        ','.join([self.value2string(obj, f) for f in fields])))
                stream.write('\n')
                if i == len(chunks):
                    stream.write('loader.flush_deferred_objects()\n')

                stream.close()

            #~ self.stream.write('\nfilename = os.path.join(os.path.dirname(__file__),"%s.py")\n' % )

        self.stream.write(
            '    loader.finalize()\n')
        # 20180416 why was the following message commented out?
        # reactivated it because otherwise we have no log entry when
        # the process has finished.
        self.stream.write(
            '    logger.info("Loaded %d objects", loader.count_objects)\n')
        self.stream.write(
            "    call_command('resetsequences')\n")
        
        self.stream.write("""
if __name__ == '__main__':
    import argparse
    parser = argparse.ArgumentParser(description='Restore the data.')
    parser.add_argument('--noinput', dest='interactive',
        action='store_false', default=True,
        help="Don't ask for confirmation before flushing the database.")
    parser.add_argument('--quick', dest='quick', 
        action='store_true',default=False,
        help='Do not call full_clean() on restored instances.')

    args = parser.parse_args()
    main(args)
""")
        #~ self.stream.write('\nsettings.SITE.load_from_file(globals())\n')
        self.stream.close()
Пример #45
0
    def serialize(self, queryset, **options):
        self.options = options

        self.stream = options.get("stream", StringIO())
        self.selected_fields = options.get("fields")
        self.use_natural_keys = options.get("use_natural_keys", False)
        if self.write_preamble:
            current_version = settings.SITE.version
            if '+' in current_version:
                logger.warning("Dumpdata from intermediate version %s" %
                               current_version)

            self.stream.write('# -*- coding: UTF-8 -*-\n')
            self.stream.write('''\
"""
This is a `Python dump created using %s.
''' % settings.SITE.using_text())
            #~ self.stream.write(settings.SITE.welcome_text())
            self.stream.write('''
"""
from __future__ import unicode_literals
''')
            self.stream.write('SOURCE_VERSION = %r\n' % str(current_version))
            self.stream.write('from decimal import Decimal\n')
            self.stream.write('from datetime import datetime as dt\n')
            self.stream.write('from datetime import time,date\n')
            self.stream.write('from lino.utils.dpy import create_mti_child\n')
            self.stream.write('from lino.utils.dbutils import resolve_model\n')
            self.stream.write(
                'from lino.modlib.gfks.models import ContentType\n')
            self.stream.write('from django.conf import settings\n')
            self.stream.write('''
            
def new_content_type_id(m):
    if m is None: return m
    # if not fmn: return None
    # m = resolve_model(fmn)
    ct = ContentType.objects.get_for_model(m)
    if ct is None: return None
    return ct.pk
    
''')
            #~ s = ','.join([
            #~ '%s=values[%d]' % (k,i)
            #~ for i,k in enumerate(settings.SITE.AVAILABLE_LANGUAGES)])
            s = ','.join([
                '%s=values[%d]' % (lng.name, lng.index)
                for lng in settings.SITE.languages
            ])
            self.stream.write('''
def bv2kw(fieldname,values):
    """
    Needed if `Site.languages` changed between dumpdata and loaddata
    """
    return settings.SITE.babelkw(fieldname,%s)
    
''' % s)
        #~ model = queryset.model
        if self.models is None:
            self.models = sorted_models_list()  # models.get_models()
        if self.write_preamble:
            for model in self.models:
                self.stream.write(
                    '%s = resolve_model("%s")\n' %
                    (full_model_name(model, '_'), full_model_name(model)))
        self.stream.write('\n')
        for model in self.models:
            fields = [
                f for f, m in model._meta.get_fields_with_model() if m is None
            ]
            for f in fields:
                if getattr(f, 'auto_now_add', False):
                    raise Exception(
                        "%s.%s.auto_now_add is True : values will be lost!" %
                        (full_model_name(model), f.name))
            field_names = [
                f.attname for f in fields
                if not getattr(f, '_lino_babel_field', False)
            ]
            self.stream.write('def create_%s(%s):\n' %
                              (model._meta.db_table, ', '.join(field_names)))
            if model._meta.parents:
                if len(model._meta.parents) != 1:
                    msg = "%s : model._meta.parents is %r" % (
                        model, model._meta.parents)
                    raise Exception(msg)
                pm, pf = model._meta.parents.items()[0]
                child_fields = [f for f in fields if f != pf]
                if child_fields:
                    attrs = ',' + ','.join([
                        '%s=%s' % (f.attname, f.attname) for f in child_fields
                    ])
                else:
                    attrs = ''
                tpl = '    return create_mti_child(%s, %s, %s%s)\n'
                self.stream.write(tpl % (full_model_name(
                    pm, '_'), pf.attname, full_model_name(model, '_'), attrs))
            else:
                self.stream.write("    kw = dict()\n")
                for f in fields:
                    if getattr(f, '_lino_babel_field', False):
                        continue
                    elif isinstance(f, (BabelCharField, BabelTextField)):
                        tpl = '    if %s is not None:'
                        tpl += ' kw.update(bv2kw(%r, %s))\n'
                        self.stream.write(tpl %
                                          (f.attname, f.attname, f.attname))
                    else:
                        if isinstance(f, models.DecimalField):
                            self.stream.write(
                                '    if %s is not None: %s = Decimal(%s)\n' %
                                (f.attname, f.attname, f.attname))
                        elif isinstance(
                                f,
                                models.ForeignKey) and f.rel.to is ContentType:
                            #~ self.stream.write(
                            #~ '    %s = ContentType.objects.get_for_model(%s).pk\n' % (
                            #~ f.attname,f.attname))
                            self.stream.write(
                                '    %s = new_content_type_id(%s)\n' %
                                (f.attname, f.attname))
                        self.stream.write('    kw.update(%s=%s)\n' %
                                          (f.attname, f.attname))

                self.stream.write('    return %s(**kw)\n\n' %
                                  full_model_name(model, '_'))
        #~ self.start_serialization()
        self.stream.write('\n')
        model = None
        all_models = []
        for obj in queryset:
            if isinstance(obj, ContentType):
                continue
            if isinstance(obj, Session):
                continue
            #~ if isinstance(obj,Permission): continue
            if obj.__class__ != model:
                model = obj.__class__
                if model in all_models:
                    raise Exception("%s instances weren't grouped!" % model)
                all_models.append(model)
                self.stream.write('\ndef %s_objects():\n' %
                                  model._meta.db_table)
            fields = [
                f for f, m in model._meta.get_fields_with_model() if m is None
            ]
            fields = [
                f for f in fields if not getattr(f, '_lino_babel_field', False)
            ]
            self.stream.write(
                '    yield create_%s(%s)\n' % (obj._meta.db_table, ','.join(
                    [self.value2string(obj, f) for f in fields])))
        self.stream.write('\n\ndef objects():\n')
        all_models = self.sort_models(all_models)
        for model in all_models:
            #~ self.stream.write('    for o in %s_objects(): yield o\n' % model._meta.db_table)
            self.stream.write('    yield %s_objects()\n' %
                              model._meta.db_table)
Пример #46
0
    def handle(self, *args, **options):
        if args:
            raise CommandError("This command doesn't accept any arguments.")

        self.options = options

        #~ settings.SITE.startup()

        state = dict()
        state.update(timestamp=datetime.datetime.now())
        state.update(lino_version=lino.__version__)

        states_file = os.path.join(settings.SITE.project_dir, 'states.pck')

        if os.path.exists(states_file):
            fd = open(states_file)
            states_list = pickle.load(fd)
            fd.close()
            logger.info("Loaded %d states from %s",
                        len(states_list), states_file)
        else:
            states_list = []

        models_list = sorted_models_list()

        apps = [p.app_label for p in settings.SITE.installed_plugins]
        state.update(applications=" ".join(apps))
        for model in models_list:
            if model._meta.managed:
                model_state = dict()
                #~ cells.append(str(i))
                #~ cells.append(full_model_name(model))
                #~ cells.append(str(model))
                #~ if model._meta.managed:
                    #~ cells.append('X')
                #~ else:
                    #~ cells.append('')
                model_state.update(fields=[f.name for f in model._meta.fields])
                #~ qs = model.objects.all()
                qs = model.objects.order_by('pk')
                n = qs.count()
                model_state.update(rows=n)

                connection = connections[DEFAULT_DB_ALIAS]

                #~ if isinstance(connection,sqlite):
                    #~ cells.append("-")
                if mysql and isinstance(connection, mysql):

                    cursor = connection.cursor()
                    dbname = connection.settings_dict['NAME']
                    sql = """\
                    SELECT (data_length+index_length) tablesize
                    FROM information_schema.tables
                    WHERE table_schema='%s' and table_name='%s';
                    """ % (dbname, model._meta.db_table)
                    #~ print sql
                    cursor.execute(sql)
                    row = cursor.fetchone()
                    if row is not None:
                        model_state.update(bytes=row[0])
                else:
                    pass

                state[full_model_name(model)] = model_state

        if len(states_list):
            msg = compare(state, states_list[-1])
            if msg:
                logger.info(msg)
                #~ sendmail_admins()

        states_list.append(state)

        #~ print state
        if self.options['write']:
            f = open(states_file, 'w')
            pickle.dump(states_list, f)
            logger.info("Saved %d states to %s", len(states_list), states_file)
Пример #47
0
def write_create_function(model, stream):
    fields = [f for f in model._meta.get_fields()
              if f.concrete and f.model is model]
    for f in fields:
        if getattr(f, 'auto_now_add', False):
            # raise Exception("%s.%s.auto_now_add is True : values will be lost!" % (
            #     full_model_name(model), f.name))
            logger.warning(
                "%s.%s.auto_now_add is True : values will be lost!",
                full_model_name(model), f.name)
            # f.auto_now_add = False
    stream.write('def create_%s(%s):\n' % (
        model._meta.db_table, ', '.join([
            f.attname for f in fields
            if not getattr(f, '_lino_babel_field', False)])))
    for f in fields:
        if f.model is model:
            pre = '    '
        else:
            pre = '#   '
        if isinstance(f, models.DecimalField):
            stream.write(
                pre+'if %s is not None: %s = Decimal(%s)\n' % (
                    f.attname, f.attname, f.attname))
        elif isinstance(f, ChoiceListField):
            lstname = 'settings.SITE.models.{0}.{1}'.format(
                f.choicelist.app_label, f.choicelist.__name__)
            ln = pre+'if {0}: {0} = {1}.get_by_value({0})\n'
            ln = '#' + ln # no longer needed but maybe useful as a comment
            stream.write(ln.format(f.attname, lstname))
        elif is_pointer_to_contenttype(f):
            stream.write(
                pre+'%s = new_content_type_id(%s)\n' % (
                    f.attname, f.attname))

    if model._meta.parents:
        if len(model._meta.parents) != 1:
            msg = "%s : model._meta.parents is %r" % (
                model, model._meta.parents)
            raise Exception(msg)
        pm, pf = list(model._meta.parents.items())[0]
        fields = [f for f in fields if f != pf]
        
    stream.write("    kw = dict()\n")
    for f in fields:
        if f.model is model:
            pre = '    '
        else:
            pre = '#   '
        if getattr(f, '_lino_babel_field', False):
            continue
        elif isinstance(f, (BabelCharField, BabelTextField)):
            stream.write(
                pre + 'if %s is not None: kw.update(bv2kw(%r,%s))\n' % (
                    f.attname, f.attname, f.attname))
        else:
            stream.write(
                pre + 'kw.update(%s=%s)\n' % (f.attname, f.attname))

    if model._meta.parents:
        stream.write(
            '    return create_mti_child(%s, %s, %s, **kw)\n\n' % (
                full_model_name(pm, '_'), pf.attname,
                full_model_name(model, '_')))
    else:
        stream.write('    return %s(**kw)\n\n' %
                          full_model_name(model, '_'))