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)
def objects(): Comment = rt.models.comments.Comment User = rt.models.users.User Comment.auto_touch = False TXT = Cycler([ styled, table, lorem, short_lorem, breaking, cond_comment, plain1, plain2 ]) for model in rt.models_by_base(Commentable): OWNERS = Cycler(model.objects.all()) if len(OWNERS) == 0: return now = datetime.datetime.combine(dd.today(-30), i2t(822)) if settings.USE_TZ: now = make_aware(now) DELTA = datetime.timedelta(minutes=34) owner = OWNERS.pop() for i in range(12): for u in User.objects.all(): ses = BaseRequest(user=u) # if owner.private: # txt = "<p>Confidential comment</p>" # else: # txt = TXT.pop() # txt = "Hackerish comment" obj = Comment(user=u, owner=owner, body=TXT.pop()) obj.on_create(ses) obj.after_ui_create(ses) obj.before_ui_save(ses) obj.modified = now yield obj now += DELTA if i % 3: owner = OWNERS.pop()
def objects(): from lino_xl.lib.phones.mixins import ContactDetailsOwner for m in rt.models_by_base(ContactDetailsOwner): for p in m.objects.all(): p.propagate_contact_details() yield p
def update_reminders_for_user(user, ar): n = 0 for model in rt.models_by_base(EventGenerator): for obj in model.objects.filter(user=user): obj.update_reminders(ar) # logger.info("--> %s",unicode(obj)) n += 1 return n
def objects(): ExcerptType = rt.models.excerpts.ExcerptType for cls in rt.models_by_base(Certifiable): kw = dd.str2kw('name', cls._meta.verbose_name) kw.update(primary=True, certifying=True) yield ExcerptType( content_type=ContentType.objects.get_for_model(cls), **kw)
def get_checkable_models(self): """Return a list of the models to check. The default implementation uses the :attr:`model`. """ if self.model is None: return [None] return rt.models_by_base(self.model, toplevel_only=True)
def objects(): ExcerptType = rt.models.excerpts.ExcerptType ContentType = rt.models.contenttypes.ContentType for cls in rt.models_by_base(Certifiable): ct = ContentType.objects.get_for_model(cls) kw = dict(content_type=ct, primary=True, certifying=True) if ExcerptType.objects.filter(**kw).count() == 0: kw.update(dd.str2kw('name', cls._meta.verbose_name)) yield ExcerptType(**kw)
def __init__(self, client): self.client = client self.actives = [] for model in rt.models_by_base(ContractBase): for con1 in model.objects.filter(client=client): ap = con1.active_period() if ap[0] is None and ap[1] is None: continue self.actives.append((ap, con1))
def run_from_ui(self, ar, fix=None): for sm in rt.models_by_base(Summary, toplevel_only=True): sm.objects.all().delete() for mm, summary_models in get_summary_models().items(): for sm in summary_models: dd.logger.info("Updating %s ...", sm._meta.verbose_name_plural) for master in sm.get_summary_masters(): sm.update_for_master(master) ar.set_response(refresh=True)
def get_summary_models(): summary_masters = dict() for sm in rt.models_by_base(Summary, toplevel_only=True): if sm.summary_period not in SUMMARY_PERIODS: raise Exception("Invalid summary_period {!r} for {}".format( sm.summary_period, sm)) mm = sm.get_summary_master_model() lst = summary_masters.setdefault(mm, []) lst.append(sm) return summary_masters
def get_summary_models(): """Return a `dict` mapping each model which has at least one summary to a list of these summaries. """ summary_masters = dict() for sm in rt.models_by_base(Summary, toplevel_only=True): mm = sm.get_summary_master_model() lst = summary_masters.setdefault(mm, []) lst.append(sm) return summary_masters
def get_data_rows(self, ar): obj = ar.master_instance rows = [] if obj is not None: for M in rt.models_by_base(VatDocument): rows += list(M.objects.filter(partner=obj)) def by_date(a, b): return cmp(b.voucher_date, a.voucher_date) rows.sort(by_date) return rows
def objects(): ExcerptType = rt.modules.excerpts.ExcerptType for cls in rt.models_by_base(Certifiable): kw = dd.str2kw('name', cls._meta.verbose_name) if False: kw.update(backward_compat=True) yield ExcerptType( #template='Default.odt', primary=True, certifying=True, content_type=ContentType.objects.get_for_model(cls), **kw)
def masters_with_summaries(): """ Return a dict mapping each model that is a summary master to the list of its slave summaries. """ summary_masters = dict() for sm in rt.models_by_base(SlaveSummarized, toplevel_only=True): mm = sm.get_summary_master_model() lst = summary_masters.setdefault(mm, []) lst.append(sm) return summary_masters
def collect(m): for c in rt.models_by_base(m): #~ if c is not m and (m in c.__bases__): #~ if c is not m: if c is not m and m in c.__bases__: ok = True #~ for cb in c.__bases__: #~ if cb in m.mro(): #~ ok = False if ok: pairs.append( (m._meta.verbose_name, c._meta.verbose_name)) collect(c)
def get_data_rows(self, ar): obj = ar.master_instance rows = [] if obj is not None: flt = {self._master_field_name: obj} for M in rt.models_by_base(AccountInvoice): rows += list(M.objects.filter(**flt)) def by_date(a, b): return cmp(b.voucher_date, a.voucher_date) rows.sort(by_date) return rows
def get_data_rows(self, ar): obj = ar.master_instance rows = [] if obj is not None: flt = {self._master_field_name: obj} for M in rt.models_by_base(self._voucher_base): rows += list(M.objects.filter(**flt)) # def by_date(a, b): # return cmp(b.entry_date, a.entry_date) rows.sort(key= lambda i: i.entry_date) return rows
def collect(p): for c in rt.models_by_base(p): # if c is not p and (p in c.__bases__): # if c is not m and p in c.__bases__: if c is not p: # ok = True # for cb in c.__bases__: # if cb in p.mro(): # ok = False # if ok: if c not in collected: pairs.append((p, c)) collected.add(c) collect(c)
def get_checkable_models(*args): """Return a `dict` mapping each model which has at least one checker to a list of these checkers. """ if len(args): selection = [getattr(Checkers, arg) for arg in args] else: selection = Checkers.objects() checkable_models = dict() for chk in selection: for m in rt.models_by_base(chk.model, toplevel_only=True): lst = checkable_models.setdefault(m, []) lst.append(chk) return checkable_models
def get_user_queryset(cls, user): qs = super(Comment, cls).get_user_queryset(user) if not user.user_type.has_required_roles([CommentsReader]): return qs.none() filters = [] for m in rt.models_by_base(Commentable): flt = m.get_comments_filter(user) if flt is not None: ct = rt.models.contenttypes.ContentType.objects.get_for_model( m) filters.append(flt | ~Q(owner_type=ct)) if len(filters): qs = qs.filter(*filters) return qs.distinct() # add distinct because filter might be on a join
def run_from_ui(self, ar, fix=None): for sm in rt.models_by_base(Summarized, toplevel_only=True): dd.logger.info("Updating summary data for %s ...", sm._meta.verbose_name_plural) sm.check_all_summaries() ar.set_response(refresh=True)
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)
def get_checkable_models(self): if self.model is None: return [None] return rt.models_by_base(self.model, toplevel_only=True)
def invoiceable_type_choices(cls): return ContentType.objects.get_for_models( *rt.models_by_base(InvoiceGenerator)).values()
def set_excerpts_actions(sender, **kw): # logger.info("20180114 %s.set_excerpts_actions()", __name__) # in case ExcerptType is overridden ExcerptType = sender.modules.excerpts.ExcerptType Excerpt = sender.modules.excerpts.Excerpt try: etypes = [(obj, obj.content_type) for obj in ExcerptType.objects.all().order_by('id')] except (OperationalError, ProgrammingError, UnresolvedChoice) as e: dd.logger.debug("Failed to set excerpts actions : %s", e) # Happens e.g. when the database has not yet been migrated etypes = [] for atype, ct in etypes: if ct is not None: bm = ct.model_class() if bm is None: # e.g. database contains types for models that existed # before but have been removed continue for m in rt.models_by_base(bm): an = atype.get_action_name() if not hasattr(m, an): m.define_action(**{an: CreateExcerpt( atype, six.text_type(atype))}) # dd.logger.info("Added print action to %s", m) # if atype.certifying and not issubclass(m, Certifiable): # m.define_action( # clear_printed=ClearCache()) # An attestable model must also inherit # :class:`lino.mixins.printable.BasePrintable` or some subclass # thereof. for i in Shortcuts.items(): def f(obj, ar): if ar is None: return '' if obj is None: return E.div() try: et = ExcerptType.objects.get(shortcut=i) except ExcerptType.DoesNotExist: return E.div() items = [] if True: sar = ar.spawn( ExcerptsByOwner, master_instance=obj, param_values=dict(excerpt_type=et)) n = sar.get_total_count() if n > 0: ex = sar.sliced_data_iterator[0] items.append(ar.obj2html(ex, _("Last"))) ba = sar.bound_action btn = sar.renderer.action_button( obj, sar, ba, "%s (%d)" % (_("All"), n), icon_name=None) items.append(btn) ia = getattr(obj, et.get_action_name()) btn = ar.instance_action_button( ia, _("Create"), icon_name=None) items.append(btn) else: ot = ContentType.objects.get_for_model(obj.__class__) qs = Excerpt.objects.filter( owner_id=obj.pk, owner_type=ot, excerpt_type=et) if qs.count() > 0: ex = qs[0] txt = ExcerptsByOwner.format_excerpt(ex) items.append(ar.obj2html(ex, txt)) return E.div(*join_elems(items, ', ')) vf = dd.VirtualField(dd.DisplayField(i.text), f) dd.inject_field(i.model_spec, i.name, vf)
def holder_model(): cmc = list(rt.models_by_base(BeIdCardHolder)) if len(cmc) != 1: raise Exception( "There must be exactly one BeIdCardHolder model in your Site!") return cmc[0]
def customize_contacts1(sender, **kw): from lino.utils.addressable import Addressable for m in rt.models_by_base(Addressable): m.define_action(print_labels=PrintLabelsAction())
def get_checkable_models(self): for m in rt.models_by_base(Voucher): if m is not Voucher: yield m
def get_generators_for_plan(self, partner=None): for m in rt.models_by_base(InvoiceGenerator): for obj in m.get_generators_for_plan(self, partner): # if obj.get_invoiceable_product(self) is not None: yield obj
def get_checkable_models(self): """Return a list of the models to check. The default implementation expects :attr:`model` to be set. """ return rt.models_by_base(self.model, toplevel_only=True)
def on_post_analyze(sender, **kw): for m in rt.models_by_base(VatDocument): dd.post_init.connect(set_default_item_vat, sender=m)
def set_excerpts_actions(sender, **kw): # logger.info("20180114 %s.set_excerpts_actions()", __name__) # in case ExcerptType is overridden ExcerptType = sender.modules.excerpts.ExcerptType Excerpt = sender.modules.excerpts.Excerpt try: etypes = [(obj, obj.content_type) for obj in ExcerptType.objects.order_by('id')] except (OperationalError, ProgrammingError, UnresolvedChoice) as e: dd.logger.debug("Failed to set excerpts actions : %s", e) # Happens e.g. when the database has not yet been migrated etypes = [] for atype, ct in etypes: if ct is not None: bm = ct.model_class() if bm is None: # e.g. database contains types for models that existed # before but have been removed continue for m in rt.models_by_base(bm): an = atype.get_action_name() if not hasattr(m, an): m.define_action(**{an: CreateExcerpt(atype, str(atype))}) # dd.logger.info("Added print action to %s", m) # if atype.certifying and not issubclass(m, Certifiable): # m.define_action( # clear_printed=DeleteExcerpt()) # An attestable model must also inherit # :class:`lino.mixins.printable.BasePrintable` or some subclass # thereof. for i in Shortcuts.get_list_items(): def f(obj, ar): if ar is None: return '' if obj is None: return E.div() try: et = ExcerptType.objects.get(shortcut=i) except ExcerptType.DoesNotExist: return E.div() items = [] if True: sar = ar.spawn(ExcerptsByOwner, master_instance=obj, param_values=dict(excerpt_type=et)) n = sar.get_total_count() if n > 0: ex = sar.sliced_data_iterator[0] items.append(ar.obj2html(ex, _("Last"))) ba = sar.bound_action btn = sar.renderer.action_button(obj, sar, ba, "%s (%d)" % (_("All"), n), icon_name=None) items.append(btn) ia = getattr(obj, et.get_action_name()) btn = ar.instance_action_button(ia, _("Create"), icon_name=None) items.append(btn) else: ot = ContentType.objects.get_for_model(obj.__class__) qs = Excerpt.objects.filter(owner_id=obj.pk, owner_type=ot, excerpt_type=et) if qs.count() > 0: ex = qs[0] txt = ExcerptsByOwner.format_excerpt(ex) items.append(ar.obj2html(ex, txt)) return E.div(*join_elems(items, ', ')) vf = dd.VirtualField(dd.DisplayField(i.text), f) dd.inject_field(i.model_spec, i.name, vf)