def show_memo_commands(self, doctestfmt=False): rst = "" mp = settings.SITE.kernel.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 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 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 walk_menu_items(username, severe=False): """Walk through all menu items which run a :class:`GridEdit <lino.core.actions.GridEdit>` action, showing how many data rows the grid contains. """ ar = settings.SITE.login(username) with translation.override(ar.user.language): mnu = settings.SITE.get_site_menu(None, ar.user.profile) items = [] for mi in mnu.walk_items(): if mi.bound_action: if isinstance(mi.bound_action.action, GridEdit): mt = mi.bound_action.actor url = 'api/{}/{}'.format(mt.app_label, mt.__name__) url = six.text_type(settings.SITE.buildurl(url, fmt='json')) item = menuselection_text(mi) + " : " try: response = test_client.get(url, REMOTE_USER=six.text_type(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_fields(self): 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_excerpts(severe=True): ses = rt.login() # dd.logger.info("20141029 %s", settings.SITE) coll = {} def collect(obj): l = coll.setdefault(obj.excerpt_type, []) if len(l) > 2: return try: rv = ses.run(obj.do_print) except Warning as e: return if rv['success']: pass # print("\n\n%s\n\n" % rv['open_url']) else: if severe: raise Exception("Oops: %s" % rv['message']) else: return if not 'open_url' in rv: if severe: raise Exception("Oops: %s" % rv['message']) else: return # tmppath = settings.SITE.project_dir + rv['open_url'] tmppath = settings.SITE.cache_dir if not 'media' in rv['open_url']: # if not tmppath.endswith('media'): tmppath = tmppath.child('media') tmppath += rv['open_url'] head, tail = os.path.split(tmppath) # tail = 'tested/' + tail 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 show_excerpts(severe=True): ses = rt.login() # dd.logger.info("20141029 %s", settings.SITE) coll = {} def collect(obj): l = coll.setdefault(obj.excerpt_type, []) if len(l) > 2: return try: rv = ses.run(obj.do_print) except Warning as e: return if rv['success']: pass # print("\n\n%s\n\n" % rv['open_url']) else: if severe: raise Exception("Oops: %s" % rv['message']) else: return if not 'open_url' in rv: if severe: raise Exception("Oops: %s" % rv['message']) else: return # tmppath = settings.SITE.project_dir + rv['open_url'] tmppath = settings.SITE.cache_dir if not 'media' in rv['open_url']: # if not tmppath.endswith('media'): tmppath = tmppath.child('media') tmppath += rv['open_url'] head, tail = os.path.split(tmppath) # tail = 'tested/' + tail 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 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 = six.text_type(settings.SITE.buildurl(url, fmt='json')) item = menuselection_text(mi) + " : " try: response = test_client.get(url, REMOTE_USER=six.text_type(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 fields_ul(fields): helpless = [] def field2li(fld): s = "**%s**" % unicode(f.verbose_name).strip() s += " (``%s``, %s)" % (f.name, fieldtype(f)) if f.help_text: s += " -- " + unicode(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 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_dialog_actions(self, doctestfmt=False): self.analyze() items = [] for ba in analyzer.custom_actions + analyzer.window_actions: if ba.action.parameters: items.append("{0} : {1}".format(ba.full_name(), py2rst(ba.action, doctestfmt))) print(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_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 show_window_fields(self): 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_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 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_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.rel.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 show_dialog_actions(self, doctestfmt=False): self.analyze() items = [] for ba in analyzer.custom_actions + analyzer.window_actions: if ba.action.parameters: items.append( "{0} : {1}".format( ba.full_name(), py2rst(ba.action, doctestfmt))) print(rstgen.ul(items))
def get_rst(self): with translation.override(self.language): #~ set_language(lng) actor_names = ' '.join(self.content).split() items = [] for an in actor_names: cls = settings.SITE.modules.resolve(an) if not isinstance(cls, type): raise Exception("%s is not an actor." % self.content[0]) items.append("%s : %s" % (actor_ref(cls), cls.help_text or '')) return rstgen.ul(items)
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 commited_today(today=None): """Print all today's commits to stdout.""" from atelier.projects import load_projects from git import Repo today = get_current_date(today) rows = [] def load(self): self.load_fabfile() if env.revision_control_system != 'git': return repo = Repo(env.root_dir) kw = dict() ONEDAY = timedelta(days=1) yesterday = today - ONEDAY tomorrow = today + ONEDAY kw.update(after=yesterday.strftime("%Y-%m-%d"), before=tomorrow.strftime("%Y-%m-%d")) it = list(repo.iter_commits(**kw)) if len(it) == 0: return def fmtcommit(c): url = repo.remotes.origin.url if url.startswith("*****@*****.**"): url = "https://github.com/" + url[15:-4] \ + "/commit/" + c.hexsha s = "`{0} <{1}>`__".format(c.hexsha[-7:], url) if c.message and not c.message.startswith("http://"): s += " " + c.message return s url = self.SETUP_INFO.get('url', "oops") desc = "`%s <%s>`__" % (self.name, url) for c in it: ts = time.strftime("%H:%M", time.gmtime(c.committed_date)) rows.append([ts, desc, fmtcommit(c)]) for p in load_projects(): load(p) def mycmp(a, b): return cmp(a[0], b[0]) rows.sort(mycmp) print(rstgen.ul(["{0} : {1}\n{2}".format(*row) for row in rows]))
def py2rst(self, doctestfmt=False): """Render any Python object as reStructuredText. Where "any" currently means a layout or a layout element. :class:`lino.core.layouts.BaseLayout` :mod:`lino.modlib.extjs.elems` 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. """ 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) return s if isinstance(self, BaseLayout): lh = self.get_layout_handle(settings.SITE.kernel.default_ui) return py2rst(lh.main, doctestfmt) if isinstance(self, Wrapper): self = self.wrapped if isinstance(self, FieldElement): s = "**%s** (%s)" % (str(self.field.verbose_name), self.field.name) elif self.label is None: s = "(%s)" % self.name else: s = "**%s** (%s)" % (str(self.label), self.name) if visible_for(self) != visible_for(self.parent): s += " [visible for %s]" % visible_for(self) if isinstance(self, Container): use_ul = False for e in self.elements: if isinstance(e, Container): use_ul = True children = [py2rst(e, doctestfmt) 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 actions_ul(action_list): items = [] for ba in action_list: label = ba.action.label desc = "**%s** (" % unicode(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 += " -- " + unicode(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 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_complexity_factors(self): self.analyze() items = [] items.append("{0} plugins".format(len(dd.plugins))) items.append("{0} models".format(len(get_models()))) items.append("{0} views".format(len(actors.actors_list))) items.append("{0} user types".format(len(UserTypes.objects()))) dialog_actions = [ ba for ba in analyzer.custom_actions + analyzer.window_actions if ba.action.parameters ] items.append("{0} dialog actions".format(len(dialog_actions))) 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 actors_overview_ul(model_reports): items = [] for tb in model_reports: desc = actor_ref(tb) #~ label = unicode(tb.title or tb.label) #~ desc += " (%s)" % str(tb) desc += " (%s)" % typeref(tb) mi = 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 += " -- " + unicode(tb.help_text).strip() items.append(desc) 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 as_rst(self,ar,level=1): """ Render this menu as an rst string. Currently used only for writing test cases. """ has_submenus = False for i in self.items: if isinstance(i,Menu): has_submenus = True items = [mi.as_rst(ar,level+1) for mi in self.items] if has_submenus: s = rstgen.ul(items).strip() + '\n' if self.label is not None: s = unicode(self.label) + ' :\n\n' + s else: s = ', '.join(items) if self.label is not None: s = unicode(self.label) + ' : ' + s return s
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 unicode(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 = unicode(mnu.label) + ' :\n\n' + s else: s = ', '.join(items) if mnu.label is not None: s = unicode(mnu.label) + ' : ' + s return s
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 get_rst(self): with translation.override(self.language): #~ set_language(lng) actor_names = ' '.join(self.content).split() items = [] for an in actor_names: cls = settings.SITE.modules.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 = find_menu_item(cls.default_action) if mi is not None: desc += _(" (Menu %s)") % menuselection(mi) #~ print(unicode(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 commited_today(ctx, today=None): """Print all today's commits to stdout.""" from atelier.projects import load_projects from git import Repo today = get_current_date(today) rows = [] def load(prj): # prj.load_fabfile() prj.load_tasks() # tsk, cfg = prj.ns.task_with_config('ci') cfg = prj.ns.configuration() if cfg['revision_control_system'] != 'git': # if cfg.revision_control_system != 'git': # print("20160816 {}".format(cfg)) return repo = Repo(cfg['root_dir']) kw = dict() ONEDAY = timedelta(days=1) yesterday = today - ONEDAY tomorrow = today + ONEDAY kw.update(after=yesterday.strftime("%Y-%m-%d"), before=tomorrow.strftime("%Y-%m-%d")) it = list(repo.iter_commits(**kw)) 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 += " " + c.message return s url = prj.SETUP_INFO.get('url', "oops") desc = "`%s <%s>`__" % (prj.name, url) 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 load_projects(): load(p) def mycmp(a, b): return cmp(a[0], b[0]) rows.sort(mycmp) print(rstgen.ul(["{0} : {1}\n{2}".format(*row) for row in rows]))
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)