def show_memo_commands(self, doctestfmt=False): rst = "" mp = settings.SITE.plugins.memo.parser items = [] for cmd, func in sorted(mp.commands.items()): doc = unindent(func.__doc__ or '') if doc: # doc = doc.splitlines()[0] items.append("[{0} ...] : {1}".format(cmd, doc)) # rst += "\n**Commands**" # rst += rstgen.boldheader("Commands") rst += rstgen.ul(items) if False: items = [] for model, func in sorted(mp.renderers.items()): doc = unindent(func.__doc__ or '') if doc: items.append("[{0} ...] : {1}".format(model, doc)) if len(items): rst += "\n**Renderers**" rst += rstgen.ul(items) return rst
def get_rst(self): user_type = UserTypes.get_by_value('900') with translation.override(self.language): #~ set_language(lng) actor_names = ' '.join(self.content).split() items = [] for an in actor_names: cls = settings.SITE.models.resolve(an) if not isinstance(cls, type): raise Exception("%s is not an actor." % self.content[0]) desc = "**{0}** (:class:`{1} <{2}>`)".format( force_text(cls.label), cls.__name__, cls.__module__ + '.' + cls.__name__ ) mi = user_type.find_menu_item(cls.default_action) if mi is not None: desc += _(" (Menu %s)") % menuselection(mi) #~ print(str(mi.label).strip()) if cls.help_text: desc += " : " + force_text(cls.help_text).strip() # items.append("%s : %s" % (actor_ref(cls), cls.help_text or '')) items.append(desc) return rstgen.ul(items)
def fields_ul(fields): helpless = [] def field2li(fld): s = "**%s**" % str(f.verbose_name).strip() s += " (``%s``, %s)" % (f.name, fieldtype(f)) if f.help_text: s += " -- " + str(f.help_text) return s helpless.append(s) return None items = [] for f in fields: if not hasattr(f, '_lino_babel_field'): s = field2li(f) if s: items.append(s) #~ items = [ field2li(f) for f in fields if not hasattr(f,'_lino_babel_field')] if len(helpless): s = ', '.join(helpless) if len(items): s = _("... and %s") % s items.append(s) return rstgen.ul(items)
def doit(ar): if ar is None: user_type = None else: user_type = ar.user.user_type test_client.force_login(ar.user) mnu = settings.SITE.get_site_menu(user_type) items = [] for mi in mnu.walk_items(): if mi.bound_action: if isinstance(mi.bound_action.action, ShowTable): mt = mi.bound_action.actor url = 'api/{}/{}'.format(mt.app_label, mt.__name__) url = str(settings.SITE.buildurl(url, fmt='json')) item = menuselection_text(mi) + " : " try: response = test_client.get(url, REMOTE_USER=str(username)) result = check_json_result( response, None, "GET %s for user %s" % (url, username)) item += str(result['count']) except Exception as e: if severe: raise else: item += str(e) items.append(item) s = rstgen.ul(items) print(s)
def show_window_permissions(self): self.analyze() items = [] for ba in analyzer.window_actions: items.append("{0} : visible for {1}".format( ba.full_name(), visible_for(ba))) return rstgen.ul(items)
def commited_today(ctx, today=None): """Print all today's commits to stdout.""" from git import Repo list_options = dict() if True: today = get_current_date(today) ONEDAY = timedelta(days=1) yesterday = today - ONEDAY tomorrow = today + ONEDAY list_options.update(after=yesterday.strftime("%Y-%m-%d"), before=tomorrow.strftime("%Y-%m-%d")) if False: list_options.update(max_count=5) rows = [] def load(prj): # prj.load_info() # repo = Repo(cfg['root_dir']) repo = Repo(prj.root_dir) it = list(repo.iter_commits(**list_options)) if len(it) == 0: # print("20160816 no commits in {}".format(prj.nickname)) return def fmtcommit(c): url = repo.remotes.origin.url if url.startswith("*****@*****.**"): url = "https://github.com/" + url[15:-4] \ + "/commit/" + c.hexsha elif url.startswith("git+ssh://[email protected]"): url = "https://github.com/" + url[25:-4] \ + "/commit/" + c.hexsha s = "`{0} <{1}>`__".format(c.hexsha[-7:], url) # if c.message and not c.message.startswith("http://"): s += "\n({})".format(c.message.strip()) return s # url = prj.SETUP_INFO.get('url', "oops") # desc = "`%s <%s>`__" % (prj.name, url) desc = "*{}*".format(prj.nickname) for c in it: # ts = time.strftime("%H:%M", time.gmtime(c.committed_date)) ts = time.strftime("%Y-%m-%d %H:%M", time.localtime(c.committed_date)) rows.append([ts, desc, fmtcommit(c)]) for p in git_projects(): load(p) rows.sort(key=lambda a: a[0]) print(rstgen.ul(["{0} in {1}:\n{2}".format(*row) for row in rows]))
def show_window_fields(self): """List all window actions and the form fields they contain. """ self.analyze() items = [] for ba in analyzer.window_actions: items.append("{0} : {1}".format(ba.full_name(), layout_fields(ba))) return rstgen.ul(items)
def show_action_permissions(self, *classes): self.analyze() items = [] for ba in analyzer.custom_actions + analyzer.window_actions: if isinstance(ba.action, classes): items.append("{0} : visible for {1}".format( ba.full_name(), visible_for(ba))) return rstgen.ul(items)
def show_dialog_actions(self, doctestfmt=False): self.analyze() items = [] for ba in analyzer.custom_actions + analyzer.window_actions: # if ba.action.parameters and not ba.action.no_params_window: if ba.action.parameters: items.append("{0} : {1}".format(ba.full_name(), py2rst(ba.action, doctestfmt))) print(rstgen.ul(items))
def show_foreign_keys(self): """Return a list that shows how database objects are being referred to by some other database object. This information is important (1) before deleting objects and (2) when merging them. For every model we see a list of "delete handlers" and a list of fields from other models that point to this model using that delete handler. Delete handlers are: - PROTECT : refuse to delete when other objects refer to this object - CASCADE : delete objects refering to this object - set_on_delete : make other objects point to something else (or set their pointer to None) """ self.analyze() tdp = dict() # target model -> delete handler -> pointer list for target in get_models(): dp = tdp.setdefault(target, dict()) for m, fk in target._lino_ddh.fklist: k = fk.remote_field.on_delete p = dp.setdefault(k, []) p.append((m, fk)) def fk2str(mfk): return "{0}.{1}".format(fmn(mfk[0]), mfk[1].name) items1 = [] for target, dp in list(tdp.items()): items2 = [] for dh, pl in list(dp.items()): items2.append("{0} : {1}".format( dh.__name__, ', '.join([fk2str(mfk) for mfk in pl]))) if len(items2): items2 = sorted(items2) items1.append("{0} :\n{1}".format(fmn(target), rstgen.ul(items2))) items1 = sorted(items1) return rstgen.ul(items1)
def actions_ul(action_list): items = [] for ba in action_list: label = ba.action.label desc = "**%s** (" % str(label).strip() if ba.action.action_name: desc += "``%s``" % ba.action.action_name desc += ", %s)" % typeref(ba.action.__class__) if ba.action.help_text: desc += " -- " + str(ba.action.help_text) items.append(desc) return rstgen.ul(items)
def show_database_structure(self): """Show a bullet list of all models and their fields.""" self.analyze() items = [] for model in get_models(): names = [] # for f, m in model._meta.get_fields_with_model(): for f in model._meta.concrete_fields: names.append(f.name) items.append("{0} : {1}".format(fmn(model), ', '.join(names))) items = sorted(items) return rstgen.ul(items)
def show_fields(self, model, field_names=None, languages=None): model = dd.resolve_model(model) if field_names is not None: field_names = dd.fields_list(model, field_names) items = [] for f in model._meta.fields: if field_names is None or f.name in field_names: name = f.name ref = model.__module__ + '.' + model.__name__ + '.' + name verbose_name = force_text(f.verbose_name).strip() help_text = force_text(f.help_text).replace('\n', ' ') txt = "**{verbose_name}** (:attr:`{name} <{ref}>`) : " \ "{help_text}".format(**locals()) items.append(txt) return rstgen.ul(items)
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))
def actors_overview_ul(model_reports): user_type = UserTypes.get_by_value('900') # deprecated items = [] for tb in model_reports: desc = actor_ref(tb) #~ label = str(tb.title or tb.label) #~ desc += " (%s)" % str(tb) desc += " (%s)" % typeref(tb) # mi = find_menu_item(tb.default_action) mi = user_type.find_menu_item(tb.default_action) if mi is not None: desc += _(" (Menu %s)") % menuselection(mi) #~ print(unicode(mi.label).strip()) if tb.help_text: desc += " -- " + str(tb.help_text).strip() items.append(desc) return rstgen.ul(items)
def menu2rst(self, ar, mnu, level=1): """Used by :meth:`show_menu`.""" if not isinstance(mnu, Menu): return str(mnu.label) has_submenus = False for i in mnu.items: if isinstance(i, Menu): has_submenus = True items = [self.menu2rst(ar, mi, level + 1) for mi in mnu.items] if has_submenus: s = rstgen.ul(items).strip() + '\n' if mnu.label is not None: s = str(mnu.label) + ' :\n\n' + s else: s = ', '.join(items) if mnu.label is not None: s = str(mnu.label) + ' : ' + s return s
def show_excerpts(severe=True): ses = rt.login() # dd.logger.info("20141029 %s", settings.SITE) coll = {} def collect(obj): l = coll.setdefault(obj.excerpt_type, []) mf = obj.build_method.get_target(None, obj) tmppath = Path(mf.name) if tmppath.exists(): tail = tmppath.name tail = 'dl/excerpts/' + tail kw = dict(tail=tail) kw.update(type=obj.excerpt_type) kw.update(owner=obj.owner) try: # dd.logger.info("20141029 copy %s to %s", tmppath, tail) shutil.copyfile(tmppath, tail) except IOError as e: kw.update(error=str(e)) msg = "%(type)s %(owner)s %(tail)s Oops: %(error)s" % kw # raise Exception(msg) kw.update(owner=msg) l.append(kw) for o in rt.models.excerpts.Excerpt.objects.order_by('excerpt_type'): collect(o) def asli(et, items): s = str(et) s += " : " + ', '.join("`%(owner)s <../%(tail)s>`__" % kw % kw for kw in items) return s return rstgen.ul([asli(k, v) for k, v in coll.items()])
def py2rst(self, doctestfmt=False, fmt=None): """ Return a textual representation of the given Python object as a reStructuredText bullet list. The Python object can be a layout, a layout element, an action or a database object. If it is an action, it must have parameters, and py2rst will render the params_layout. If it is a database object, you will get a textual representation of a detail window on that object. If the optional argument `doctestfmt` is specified as `True`, then output contains less blank lines, which might be invalid reStructuredText but is more doctest-friendly. TODO: move this functionality to lino.api.doctests and rename it to something that reflects better what it does. """ from lino.core.store import get_atomizer if isinstance(self, models.Model) and fmt is None: ar = self.get_default_table().request() def fmt(e): s = elem_label(e) if isinstance(e, FieldElement): sf = get_atomizer(self.__class__, e.field, e.field.name) getter = sf.full_value_from_object value = getter(self, ar) # value = e.value_from_object(self, None) if value is not None: s += ": " + e.format_value(ar, value) return s dt = self.get_default_table() lh = dt.detail_layout.get_layout_handle() return py2rst(lh.main, doctestfmt, fmt) if isinstance(self, actions.Action): s = str(self) if self.params_layout: lh = self.params_layout.get_layout_handle( settings.SITE.kernel.default_ui) s += '\n' s += py2rst(lh.main, doctestfmt, fmt) return s if isinstance(self, BaseLayout): lh = self.get_layout_handle(settings.SITE.kernel.default_ui) return py2rst(lh.main, doctestfmt, fmt) if isinstance(self, Wrapper): self = self.wrapped if fmt is None: def fmt(e): s = elem_label(e) if visible_for(e) != visible_for(e.parent): s += " [visible for %s]" % visible_for(e) return s s = fmt(self) if isinstance(self, Container): use_ul = False for e in self.elements: if isinstance(e, Container): use_ul = True children = [py2rst(e, doctestfmt, fmt) for e in self.elements] if len(children): if use_ul: s += ':\n' if not doctestfmt: s += '\n' s += rstgen.ul(children) else: s += ": " + ', '.join(children) return s
def show_complexity_factors(self): return rstgen.ul(list(self.get_complexity_factors()))
def get_rst(self): # return str(self.state.document.refnames) env = self.state.document.settings.env target = ' '.join(self.content).strip() if not target: target = env.temp_data['docname'] # print("20140409 target is %r" % target) found = set() rows = set() # headers = 'children attributes \ # resolved referenced indirect_reference_name \ # tagname'.split() for docname in env.found_docs: if env.temp_data['docname'] == docname: # skip myself continue try: doc = env.get_doctree(docname) except Exception: # 20140117 i had the following after a fab clean: # File "/home/luc/pythonenvs/py27/local/lib/python2.7/site-packages/sphinx/environment.py", line 1077, in get_doctree # f = open(doctree_filename, 'rb') # IOError: [Errno 2] No such file or directory: u'/home/luc/hgwork/lino/docs/.build/.doctrees/topics/names.doctree' continue # print("20140115 traversing", docname) for ref in doc.traverse(addnodes.pending_xref): if ref['reftype'] == 'doc': other = docname_join(ref['refdoc'], ref['reftarget']) else: other = ref['reftarget'] if other == target: found.add(ref['refdoc']) # print("20140409 found", ref) else: # rows.add(ref['reftarget']) rows.add(other) # rows.add(repr(ref.attributes)) # row = [] # for h in headers: # row.append(py2rst(getattr(ref, h, 'N/A'))) # rows.append(unicode(row)) if len(found) == 0: s = """No documents found for target %r.""" % target # s += """\nPending xrefs were %r.""" % rows return s entries = [] for refdoc in found: mtime = path.getmtime(env.doc2path(refdoc)) entries.append((mtime, refdoc)) def f(a): return a[0] entries.sort(key=f) entries.reverse() import time # from time import strftime items = [':doc:`/%(doc)s` (%(time)s)' % dict( time=time.ctime(e[0]), doc=e[1]) for e in entries] if 'debug' in self.options: items.append("DEBUG: pending xrefs were %r." % rows) return rstgen.ul(items)