def getSignInLink(self): return tags.span(tags.a(tags.span("Persona Sign-in", class_="persona-link-text"), href="#login", id="persona-login-link", class_="persona-button dark"), id="persona-login")
def test_sourceFragmentElement(self): """ L{_SourceFragmentElement} renders source lines at and around the line number indicated by a frame object. """ element = _SourceFragmentElement( TagLoader( tags.div(tags.span(render="lineNumber"), tags.span(render="sourceLine"), render="sourceLines")), self.frame) source = [ u' \N{NO-BREAK SPACE} \N{NO-BREAK SPACE}message = ' u'"This is a problem"', u' \N{NO-BREAK SPACE} \N{NO-BREAK SPACE}raise Exception(message)', u'# Figure out the line number from which the exception will be ' u'raised.', ] d = flattenString(None, element) d.addCallback( self.assertEqual, ''.join([ '<div class="snippet%sLine"><span>%d</span><span>%s</span>' '</div>' % (["", "Highlight"][lineNumber == 1], self.base + lineNumber, (u" \N{NO-BREAK SPACE}" * 4 + sourceLine).encode('utf-8')) for (lineNumber, sourceLine) in enumerate(source) ])) return d
def extras(self) -> List["Flattenable"]: r = super().extras() sourceHref = util.srclink(self.ob) source: "Flattenable" if sourceHref: source = (" ", tags.a("(source)", href=sourceHref, class_="sourceLink")) else: source = tags.transparent r.append( tags.p( tags.code(tags.span("class", class_='py-keyword'), " ", tags.span(self.ob.name, class_='py-defname'), self.classSignature(), ":", source))) scs = sorted(self.ob.subclasses, key=objects_order) if not scs: return r p = assembleList(self.ob.system, "Known subclasses: ", [o.fullName() for o in scs], "moreSubclasses", self.page_url) if p is not None: r.append(tags.p(p)) return r
def format_summary(obj): """Generate an shortened HTML representation of a docstring.""" doc, source = get_docstring(obj) if doc is None: # Attributes can be documented as fields in their parent's docstring. if isinstance(obj, model.Attribute): pdoc = getattr(obj, 'parsed_docstring', None) else: pdoc = None if pdoc is None: return format_undocumented(obj) source = obj.parent else: # Use up to three first non-empty lines of doc string as summary. lines = itertools.dropwhile(lambda line: not line.strip(), doc.split('\n')) lines = itertools.takewhile(lambda line: line.strip(), lines) lines = [line.strip() for line in lines] if len(lines) > 3: return tags.span(class_='undocumented')("No summary") pdoc = parse_docstring(obj, ' '.join(lines), source) try: stan = pdoc.to_stan(_EpydocLinker(source)) except Exception: # This problem will likely be reported by the full docstring as well, # so don't spam the log. return tags.span(class_='undocumented')("Broken description") content = [stan] if stan.tagName else stan.children if content and isinstance(content[0], Tag) and content[0].tagName == 'p': content = content[0].children return tags.span(*content)
def getSignInLink(self): return tags.span( tags.a( tags.span("Persona Sign-in", class_="persona-link-text"), href="#login", id="persona-login-link", class_="persona-button dark"), id="persona-login")
def test_sourceFragmentElement(self): """ L{_SourceFragmentElement} renders source lines at and around the line number indicated by a frame object. """ element = _SourceFragmentElement( TagLoader(tags.div( tags.span(render="lineNumber"), tags.span(render="sourceLine"), render="sourceLines")), self.frame) source = [ u' \N{NO-BREAK SPACE} \N{NO-BREAK SPACE}message = ' u'"This is a problem"', u' \N{NO-BREAK SPACE} \N{NO-BREAK SPACE}raise Exception(message)', u'# Figure out the line number from which the exception will be ' u'raised.', ] d = flattenString(None, element) d.addCallback( self.assertEqual, ''.join([ '<div class="snippet%sLine"><span>%d</span><span>%s</span>' '</div>' % ( ["", "Highlight"][lineNumber == 1], self.base + lineNumber, (u" \N{NO-BREAK SPACE}" * 4 + sourceLine).encode( 'utf-8')) for (lineNumber, sourceLine) in enumerate(source)])) return d
def test(missing): plating = Plating(tags=tags.span(slot(Plating.CONTENT))) @plating.routed(self.app.route("/"), tags.span(tags.span(render=missing))) def no(request): return {} self.get(b"/") [fe] = self.flushLoggedErrors(FlattenerError) self.assertIsInstance(fe.value.args[0], MissingRenderMethod)
def functionDef(self, request, tag): def_stmt = 'async def' if self.ob.is_async else 'def' name = self.ob.name if name.endswith('.setter') or name.endswith('.deleter'): name = name[:name.rindex('.')] return [ tags.span(def_stmt, class_='py-keyword'), ' ', tags.span(name, class_='py-defname'), signature(self.ob), ':' ]
def subfunc(match): text = match.group(1) if match.group('PROMPT1'): yield tags.span(text, class_='py-prompt') elif match.group('PROMPT2'): yield tags.span(text, class_='py-more') elif match.group('KEYWORD'): yield tags.span(text, class_='py-keyword') elif match.group('BUILTIN'): yield tags.span(text, class_='py-builtin') elif match.group('COMMENT'): yield tags.span(text, class_='py-comment') elif match.group('STRING'): idx = 0 while True: nxt = text.find('\n', idx) line = text[idx:] if nxt == -1 else text[idx:nxt] m = PROMPT2_RE.match(line) if m: prompt_end = m.end() yield tags.span(line[:prompt_end], class_='py-more') line = line[prompt_end:] if line: yield tags.span(line, class_='py-string') if nxt == -1: break yield '\n' idx = nxt + 1 elif match.group('DEFINE'): m = DEFINE_FUNC_RE.match(text) yield tags.span(m.group('def'), class_='py-keyword') yield m.group('space') yield tags.span(m.group('name'), class_='py-defname') elif match.group('EOS') is None: raise AssertionError('Unexpected match')
def getAuthedLink(self, account): return tags.span( tags.a( tags.span( account.getDisplayName(), class_="persona-link-text"), href="/members/account", class_="account-link"), " | ", tags.a( tags.span("Sign out", class_="persona-link-text"), href="#logout", id="persona-logout-link"), id="member-links")
def getAuthedLink(self, account): return tags.span(tags.a(tags.span(account.getDisplayName(), class_="persona-link-text"), href="/members/account", class_="account-link"), " | ", tags.a(tags.span("Sign out", class_="persona-link-text"), href="#logout", id="persona-logout-link"), id="member-links")
def test_presentation_only_json(self): """ Slots marked as "presentation only" will not be reflected in the output. """ plating = Plating(tags=tags.span(slot("title")), presentation_slots={"title"}) @plating.routed(self.app.route("/"), tags.span(slot("data"))) def justJson(request): return {"title": "uninteresting", "data": "interesting"} request, written = self.get(b"/?json=1") self.assertEqual(json.loads(written.decode("utf-8")), {"data": "interesting"})
def maybeShortenList(system, label, lst, idbase): lst2 = [] for name in lst: o = system.allobjects.get(name) if o is None or o.isVisible: lst2.append(name) lst = lst2 if not lst: return None def one(item): if item in system.allobjects: return taglink(system.allobjects[item]) else: return item def commasep(items): r = [] for item in items: r.append(one(item)) r.append(', ') del r[-1] return r p = [label] if len(lst) <= 5 or not system.options.htmlshortenlists: p.extend(commasep(lst)) else: p.extend(commasep(lst[:3])) q = [', '] q.extend(commasep(lst[3:])) q.append( tags.span(class_='showIfJS') [' ', tags.a(href="#", onclick="showAndHide('%s');" % idbase, class_="jslink")['(hide last %d again)' % len(lst[3:])]]) p.append(tags.span(id=idbase, class_='hideIfJS')[q]) p.append( tags.span( id=idbase + 'Link', class_='showIfJS')[' ', tags.a(href="#", onclick="hideAndShow('%s');" % idbase, class_="jslink")['... and %d more' % len(lst[3:])]]) return p
def test_template_numbers(self): """ Data returned from a plated method may include numeric types (integers, floats, and possibly longs), which although they are not normally serializable by twisted.web.template, will be converted by plating into their decimal representation. """ @page.routed( self.app.route("/"), tags.div( tags.span(slot("anInteger")), tags.i(slot("anFloat")), tags.b(slot("anLong")), ), ) def plateMe(result): return {"anInteger": 7, "anFloat": 3.2, "anLong": 0x10000000000000001} request, written = self.get(b"/") self.assertIn(b"<span>7</span>", written) self.assertIn(b"<i>3.2</i>", written) self.assertIn(b"<b>18446744073709551617</b>", written)
def test_sourceLineElement(self): """ L{_SourceLineElement} renders a source line and line number. """ element = _SourceLineElement( TagLoader(tags.div( tags.span(render="lineNumber"), tags.span(render="sourceLine"))), 50, " print 'hello'") d = flattenString(None, element) expected = ( u"<div><span>50</span><span>" u" \N{NO-BREAK SPACE} \N{NO-BREAK SPACE}print 'hello'</span></div>") d.addCallback( self.assertEqual, expected.encode('utf-8')) return d
def getCities(self): elements = [] for index, city in enumerate(sorted(config.officeCities)): if index >= 1: elements.append("·") elements.append(tags.span(city, class_="city")) return elements
def test_template_numbers(self): """ Data returned from a plated method may include numeric types (integers, floats, and possibly longs), which although they are not normally serializable by twisted.web.template, will be converted by plating into their decimal representation. """ @page.routed( self.app.route("/"), tags.div( tags.span(slot("anInteger")), tags.i(slot("anFloat")), tags.b(slot("anLong")), ), ) def plateMe(result): return { "anInteger": 7, "anFloat": 3.2, "anLong": 0x10000000000000001 } request, written = self.get(b"/") self.assertIn(b"<span>7</span>", written) self.assertIn(b"<i>3.2</i>", written) self.assertIn(b"<b>18446744073709551617</b>", written)
def format_undocumented(obj: model.Documentable) -> Tag: """Generate an HTML representation for an object lacking a docstring.""" sub_objects_with_docstring_count: DefaultDict[model.DocumentableKind, int] = defaultdict(int) sub_objects_total_count: DefaultDict[model.DocumentableKind, int] = defaultdict(int) for sub_ob in obj.contents.values(): k = sub_ob.kind sub_objects_total_count[k] += 1 if sub_ob.docstring is not None: sub_objects_with_docstring_count[k] += 1 if isinstance(obj, model.Package): sub_objects_total_count[model.DocumentableKind.MODULE] -= 1 tag: Tag = tags.span(class_='undocumented') if sub_objects_with_docstring_count: kind = obj.kind assert kind is not None # if kind is None, object is invisible tag( "No ", format_kind(kind).lower(), " docstring; ", ', '.join( f"{sub_objects_with_docstring_count[k]}/{sub_objects_total_count[k]} " f"{format_kind(k, plural=sub_objects_with_docstring_count[k]>=2).lower()}" for k in sorted(sub_objects_total_count, key=(lambda x: x.value))), " documented") else: tag("Undocumented") return tag
def format_undocumented(obj: model.Documentable) -> Tag: """Generate an HTML representation for an object lacking a docstring.""" subdocstrings: DefaultDict[str, int] = defaultdict(int) subcounts: DefaultDict[str, int] = defaultdict(int) for subob in obj.contents.values(): k = subob.kind.lower() subcounts[k] += 1 if subob.docstring is not None: subdocstrings[k] += 1 if isinstance(obj, model.Package): subcounts['module'] -= 1 tag: Tag = tags.span(class_='undocumented') if subdocstrings: plurals = {'class': 'classes'} kind = obj.kind assert kind is not None # if kind is None, object is invisible tag( "No ", kind.lower(), " docstring; ", ', '.join(f"{subdocstrings[k]}/{subcounts[k]} " f"{plurals.get(k, k + 's')}" for k in sorted(subcounts)), " documented") else: tag("Undocumented") return tag
def handle_raises(self, field: Field) -> None: name = field.arg if name is None: field.report('Exception type missing') typ_fmt = tags.span(class_='undocumented')("Unknown exception") else: typ_fmt = self._linker.link_to(name, name) self.raise_descs.append(RaisesDesc(type=typ_fmt, body=field.format()))
class AppObj(object): app = Klein() def __init__(self, x): self.x = x @page.routed(app.route("/"), tags.span(slot('yeah'))) def plateInstance(self, request): return {"yeah": "test-instance-data-" + self.x}
def format_summary(obj: model.Documentable) -> Tag: """Generate an shortened HTML representation of a docstring.""" doc, source = get_docstring(obj) if (doc is None or source is not obj) and isinstance(obj, model.Attribute): # Attributes can be documented as fields in their parent's docstring. pdoc = obj.parsed_docstring else: pdoc = None if pdoc is not None: # The docstring was split off from the Attribute's parent docstring. source = obj.parent assert source is not None elif doc is None: return format_undocumented(obj) else: # Tell mypy that if we found a docstring, we also have its source. assert source is not None # Use up to three first non-empty lines of doc string as summary. lines = [ line.strip() for line in itertools.takewhile( lambda line: line.strip(), itertools.dropwhile(lambda line: not line.strip(), doc.split('\n'))) ] if len(lines) > 3: return tags.span(class_='undocumented')( "No summary") # type: ignore[no-any-return] pdoc = parse_docstring(obj, ' '.join(lines), source) try: stan = pdoc.to_stan(_EpydocLinker(source)) except Exception: # This problem will likely be reported by the full docstring as well, # so don't spam the log. return tags.span(class_='undocumented')( "Broken description") # type: ignore[no-any-return] content = [stan] if stan.tagName else stan.children if content and isinstance(content[0], Tag) and content[0].tagName == 'p': content = content[0].children return tags.span(*content) # type: ignore[no-any-return]
def test_failureElementValue(self): """ The I{value} renderer of L{FailureElement} renders the value's exception value. """ element = FailureElement(self.failure, TagLoader(tags.span(render="value"))) d = flattenString(None, element) d.addCallback(self.assertEqual, b"<span>This is a problem</span>") return d
def test_failureElementType(self): """ The I{type} renderer of L{FailureElement} renders the failure's exception type. """ element = FailureElement(self.failure, TagLoader(tags.span(render="type"))) d = flattenString(None, element) d.addCallback(self.assertEqual, "<span>exceptions.Exception</span>") return d
def maybeShortenList(system, label, lst, idbase): lst2 = [] for name in lst: o = system.allobjects.get(name) if o is None or o.isVisible: lst2.append(name) lst = lst2 if not lst: return None def one(item): if item in system.allobjects: return taglink(system.allobjects[item]) else: return item def commasep(items): r = [] for item in items: r.append(one(item)) r.append(', ') del r[-1] return r p = [label] if len(lst) <= 5 or not system.options.htmlshortenlists: p.extend(commasep(lst)) else: p.extend(commasep(lst[:3])) q = [', '] q.extend(commasep(lst[3:])) q.append(tags.span(class_='showIfJS')[ ' ', tags.a(href="#", onclick="showAndHide('%s');"%idbase, class_="jslink") ['(hide last %d again)'%len(lst[3:])]]) p.append(tags.span(id=idbase, class_='hideIfJS')[q]) p.append(tags.span(id=idbase+'Link', class_='showIfJS')[ ' ', tags.a(href="#", onclick="hideAndShow('%s');"%idbase, class_="jslink") ['... and %d more'%len(lst[3:])]]) return p
def test_failureElementType(self): """ The I{type} renderer of L{FailureElement} renders the failure's exception type. """ element = FailureElement( self.failure, TagLoader(tags.span(render="type"))) d = flattenString(None, element) d.addCallback( self.assertEqual, "<span>exceptions.Exception</span>") return d
def test_frameElementLineNumber(self): """ The I{lineNumber} renderer of L{_FrameElement} renders the line number associated with the frame object used to initialize the L{_FrameElement}. """ element = _FrameElement(TagLoader(tags.span(render="lineNumber")), self.frame) d = flattenString(None, element) d.addCallback(self.assertEqual, b"<span>%d</span>" % (self.base + 1, )) return d
def test_failureElementValue(self): """ The I{value} renderer of L{FailureElement} renders the value's exception value. """ element = FailureElement( self.failure, TagLoader(tags.span(render="value"))) d = flattenString(None, element) d.addCallback( self.assertEqual, b'<span>This is a problem</span>') return d
def entry_rendered(entry): if entry.system_entry: attrs_entry = attrs_entry_system else: attrs_entry = attrs_entry_user return tags.div( tags.span( str(entry.created), u", ", entry.author, **attrs_timestamp ), ":", tags.br(), tags.span( entry.text, **attrs_entry_text ), **attrs_entry )
def test_template_html(self): """ Rendering a L{Plating.routed} decorated route results in templated HTML. """ @page.routed(self.app.route("/"), tags.span(slot("ok"))) def plateMe(request): return {"ok": "test-data-present"} request, written = self.get(b"/") self.assertIn(b'<span>test-data-present</span>', written) self.assertIn(b'<title>default title unchanged</title>', written)
def test_frameElementFunction(self): """ The I{function} renderer of L{_FrameElement} renders the line number associated with the frame object used to initialize the L{_FrameElement}. """ element = _FrameElement(TagLoader(tags.span(render="function")), self.frame) d = flattenString(None, element) d.addCallback(self.assertEqual, b"<span>lineNumberProbeAlsoBroken</span>") return d
def test_prime_directive_return(self): """ Nothing within these Articles Of Federation shall authorize the United Federation of Planets to alter the return value of a callable by applying a decorator to it... """ exact_result = {"ok": "some nonsense value"} @page.routed(self.app.route("/"), tags.span(slot("ok"))) def plateMe(request): return exact_result self.assertIdentical(plateMe(None), exact_result)
def render(self, request): setRequestCatalog(request) form = self.form(request) request.write('<!DOCTYPE html>\n') if request.method == "POST" and form.validate(): content = tags.span("Form Valid!") else: content = FormElement(form) done = flatten(request, Layout(content), request.write) done.addCallback(lambda r: request.finish()) return server.NOT_DONE_YET
def test_sourceFragmentElement(self): """ L{_SourceFragmentElement} renders source lines at and around the line number indicated by a frame object. """ element = _SourceFragmentElement( TagLoader( tags.div( tags.span(render="lineNumber"), tags.span(render="sourceLine"), render="sourceLines", )), self.frame, ) source = [ " \N{NO-BREAK SPACE} \N{NO-BREAK SPACE}message = " '"This is a problem"', " \N{NO-BREAK SPACE} \N{NO-BREAK SPACE}raise Exception(message)", "", ] d = flattenString(None, element) stringToCheckFor = "" for (lineNumber, sourceLine) in enumerate(source): template = '<div class="snippet{}Line"><span>{}</span><span>{}</span></div>' if lineNumber <= 1: stringToCheckFor += template.format( ["", "Highlight"][lineNumber == 1], self.base + lineNumber, (" \N{NO-BREAK SPACE}" * 4 + sourceLine), ) else: stringToCheckFor += template.format("", self.base + lineNumber, ("" + sourceLine)) bytesToCheckFor = stringToCheckFor.encode("utf8") d.addCallback(self.assertEqual, bytesToCheckFor) return d
def test_frameElementFunction(self): """ The I{function} renderer of L{_FrameElement} renders the line number associated with the frame object used to initialize the L{_FrameElement}. """ element = _FrameElement( TagLoader(tags.span(render="function")), self.frame) d = flattenString(None, element) d.addCallback( self.assertEqual, b"<span>lineNumberProbeAlsoBroken</span>") return d
def test_frameElementLineNumber(self): """ The I{lineNumber} renderer of L{_FrameElement} renders the line number associated with the frame object used to initialize the L{_FrameElement}. """ element = _FrameElement( TagLoader(tags.span(render="lineNumber")), self.frame) d = flattenString(None, element) d.addCallback( self.assertEqual, b"<span>" + intToBytes(self.base + 1) + b"</span>") return d
def test_failureElementType(self): """ The I{type} renderer of L{FailureElement} renders the failure's exception type. """ element = FailureElement(self.failure, TagLoader(tags.span(render="type"))) d = flattenString(None, element) if _PY3: exc = b"builtins.Exception" else: exc = b"exceptions.Exception" d.addCallback(self.assertEqual, b"<span>" + exc + b"</span>") return d
def mediumName(self, ob): r = [super(ClassPage, self).mediumName(ob)] zipped = zip(self.ob.rawbases, self.ob.bases, self.ob.baseobjects) if zipped: r.append('(') for i, (n, m, o) in enumerate(zipped): if o is None: r.append(tags.span(title=m)(n)) else: r.append(util.taglink(o, n)) if i != len(zipped) - 1: r.append(', ') r.append(')') return r
class FieldDesc: _UNDOCUMENTED: ClassVar[Tag] = tags.span( class_='undocumented')("Undocumented") kind: str name: Optional[str] = None type: Optional[Tag] = None body: Optional[Tag] = None def format(self) -> Tag: formatted = self.body or self._UNDOCUMENTED if self.type is not None: formatted = tags.transparent(formatted, ' (type: ', self.type, ')') return formatted
def mediumName(self, ob): r = [super(ClassPage, self).mediumName(ob)] zipped = zip(self.ob.rawbases, self.ob.bases, self.ob.baseobjects) if zipped: r.append('(') for i, (n, m, o) in enumerate(zipped): if o is None: r.append(tags.span(title=m)(n)) else: r.append(taglink(o, n)) if i != len(zipped)-1: r.append(', ') r.append(')') return r
def test_frameElementFilename(self): """ The I{filename} renderer of L{_FrameElement} renders the filename associated with the frame object used to initialize the L{_FrameElement}. """ element = _FrameElement( TagLoader(tags.span(render="filename")), self.frame) d = flattenString(None, element) d.addCallback( # __file__ differs depending on whether an up-to-date .pyc file # already existed. self.assertEqual, "<span>" + __file__.rstrip('c') + "</span>") return d
class SlowIncrementWebService(object): application = Klein() common_page = Plating(tags=tags.html( tags.head( tags.title(slot('title')), tags.style('#amount { font-weight: bold; }' '#message { font-style: italic; }')), tags.body(tags.div(slot(Plating.CONTENT))))) def __init__(self, reactor): self._reactor = reactor @common_page.routed(application.route('/<int:amount>'), tags.div( tags.span('Hello! Your new amount is: ', id='message'), tags.span(slot('new_amount'), id='amount'), )) def slow_increment(self, request, amount): slots = { 'title': 'Slow Increment', 'new_amount': amount + 1, } return task.deferLater(self._reactor, 1.0, lambda: slots)
def test_frameElementFilename(self): """ The I{filename} renderer of L{_FrameElement} renders the filename associated with the frame object used to initialize the L{_FrameElement}. """ element = _FrameElement(TagLoader(tags.span(render="filename")), self.frame) d = flattenString(None, element) d.addCallback( # __file__ differs depending on whether an up-to-date .pyc file # already existed. self.assertEqual, b"<span>" + networkString(__file__.rstrip('c')) + b"</span>") return d
def test_failureElementType(self): """ The I{type} renderer of L{FailureElement} renders the failure's exception type. """ element = FailureElement( self.failure, TagLoader(tags.span(render="type"))) d = flattenString(None, element) if _PY3: exc = b"builtins.Exception" else: exc = b"exceptions.Exception" d.addCallback( self.assertEqual, b"<span>" + exc + b"</span>") return d
def test_template_json(self): """ Rendering a L{Plating.routed} decorated route with a query parameter asking for JSON will yield JSON instead. """ @page.routed(self.app.route("/"), tags.span(slot("ok"))) def plateMe(request): return {"ok": "an-plating-test"} request, written = self.get(b"/?json=true") self.assertEqual( request.responseHeaders.getRawHeaders(b'content-type')[0], b'text/json; charset=utf-8' ) self.assertEquals({"ok": "an-plating-test", "title": "default title unchanged"}, json.loads(written.decode('utf-8')))
def stanForOb(self, ob, summary=False): current_docstring = self.currentDocstringForObject(ob) if summary: return epydoc2stan.doc2stan( ob.doctarget, summary=True, docstring=current_docstring)[0] r = [tags.div(epydoc2stan.doc2stan(ob.doctarget, docstring=current_docstring)[0]), tags.a(href="edit?ob="+ob.fullName())("Edit"), " "] if ob.doctarget in self.editsbyob: r.append(tags.a(href="history?ob="+ob.fullName())( "View docstring history (", str(len(self.editsbyob[ob.doctarget])), " versions)")) else: r.append(tags.span(class_='undocumented')("No edits yet.")) return r
def test_prime_directive_arguments(self): """ ... or shall require the function to modify its signature under these Articles Of Federation. """ @page.routed(self.app.route("/"), tags.span(slot("ok"))) def plateMe(request, one, two, three): return (one, two, three) exact_one = {"one": "and"} exact_two = {"two": "and"} exact_three = {"three": "and"} result_one, result_two, result_three = plateMe( None, exact_one, exact_two, three=exact_three ) self.assertIdentical(result_one, exact_one) self.assertIdentical(result_two, exact_two) self.assertIdentical(result_three, exact_three)
def make_html(components, instances): table = tags.table(class_='main') heading_row = tags.tr() for heading in 'component', 'tip revno', 'unreleased revisions', 'latest release': heading_row(tags.th(heading)) for instance_name in sorted(instances): heading_row(tags.th(instance_name, class_="instance-name")) table(tags.thead(heading_row)) tbody = tags.tbody() for name, component in sorted(components.items()): row = tags.tr(class_="component") revs_between_ids = {} extra_rows = [] def td(*args, **kwargs): row(tags.td(*args, **kwargs)) td(name) td(str(component.tip_revno), class_='version') unreleased_count = len(component.unreleased_revisions) if unreleased_count: id_ = get_id() td( tags.a(str(unreleased_count), href='#', class_='highlight'), class_='version clickable', id=id_) sub_name = 'revs between %s (r%s) and tip (r%s)' % ( component.last_release, component.released_revno, component.tip_revno) extra_rows.append( tags.tr( tags.td( format_revlist(component.unreleased_revisions, name=sub_name), colspan=str(4 + len(instances))), class_='hidden', id="show-" + id_)) elif not component.last_release: td(u'\N{EM DASH}', class_='version') else: td(str(unreleased_count), class_='version') if component.last_release: td(component.last_release, class_='version') else: td(u'???', class_='version') for instance_name, instance in sorted(instances.items()): ver, location = instance.get(name, (None, None)) if ver is None: td(u'\N{EM DASH}', class_='version') elif ver == component.last_release: td(ver, class_='version') elif ver in component.release2revno: revno_low = component.release2revno[ver] sub_name = 'revs between %s (r%s) and %s (r%s)' % ( ver, revno_low, component.last_release, component.released_revno) revlist = [] for rev, revno in component.mainline_revs: if revno_low < revno < component.released_revno: revlist.append((rev, revno)) if revlist: id_ = get_id() revs_between_ids[revno_low] = id_ extra_rows.append( tags.tr( tags.td( format_revlist(revlist, name=sub_name), colspan=str(4 + len(instances))), class_='hidden branch-diff', id="show-" + id_)) td( tags.a(ver, href='#', class_='highlight'), class_='version clickable', id=id_) else: td(tags.span(ver, class_='highlight'), class_='version') elif location: try: branch = bzrlib.branch.Branch.open(location) except bzrlib.errors.NoSuchBranch: td(tags.span(ver, class_='highlight'), class_='version') else: branch.lock_read() try: # This utterly half-assed version of bzr missing # doesn't take merges into account! revno, revid = branch.last_revision_info() ver = ver.split('dev')[0] + 'dev' + str(revno) mainline_revids = dict( (rev.revision_id, revno) for rev, revno in component.mainline_revs) in_branch_revs = [] while revid not in mainline_revids: rev = branch.repository.get_revision(revid) if rev.message != 'post release bump': in_branch_revs.append((rev, revno)) revno -= 1 if not rev.parent_ids: break revid = rev.parent_ids[0] tables = [] if in_branch_revs: tables.append( format_revlist( in_branch_revs, 'in branch (with nick %s) but not tip' % branch.nick)) in_trunk_revs = [] lca_revno = revno for rev, revno in component.mainline_revs: if revno > lca_revno: in_trunk_revs.append((rev, revno)) if in_trunk_revs: tables.append( format_revlist( in_trunk_revs, 'in tip but not branch')) if tables: id_ = get_id() td( tags.a(ver, href='#', class_='highlight'), class_='version clickable', id=id_) extra_rows.append( tags.tr( tags.td( tables, colspan=str(4 + len(instances))), class_='hidden branch-diff', id="show-" + id_)) else: if branch.last_revision() == component.tip_revno: td(ver, class_='highlight version') else: td(ver, class_='version') finally: branch.unlock() else: td(tags.span(ver, class_='highlight'), class_='version') tbody(row, *extra_rows) table(tbody) html = tags.html( tags.head( tags.title("Deployment report"), tags.script( src='https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js', type='text/javascript'), tags.script( src='https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/jquery-ui.min.js', type='text/javascript'), tags.script(CDATA(js), type='text/javascript'), tags.style(CDATA(css), type="text/css"), ), tags.body( tags.h1("Deployment report"), table, ), ) html(xmlns="http://www.w3.org/1999/xhtml") return DOCTYPE + flatten(html)
tags=tags.html( tags.head(tags.title(slot("title"))), tags.body( tags.h1(slot("title")), tags.div(slot(Plating.CONTENT), Class="content"), ), ), ) element = Plating( defaults={ "a": "NO VALUE FOR A", "b": "NO VALUE FOR B", }, tags=tags.div( tags.span("a: ", slot("a")), tags.span("b: ", slot("b")), ), ) @element.widgeted def enwidget(a, b): """ Provide some values for the L{element} template. """ return {"a": a, "b": b} @element.widgeted def deferredEnwidget(a, b): """
tags=tags.html( tags.head(tags.title(slot("title"))), tags.body( tags.h1(slot("title")), tags.div(slot(Plating.CONTENT), Class="content") ) ), ) element = Plating( defaults={ "a": "NO VALUE FOR A", "b": "NO VALUE FOR B", }, tags=tags.div(tags.span("a: ", slot("a")), tags.span("b: ", slot("b"))), ) @element.widgeted def enwidget(a, b): """ Provide some values for the L{widget} template. """ return {"a": a, "b": b} class PlatingTests(TestCase): """ Tests for L{Plating}. """
def tags(self, tag): author = tags.span(self.author, class_="author") timestamp = self.timestamp.asDatetime().strftime("%m/%d/%y(%a)%H:%M") number = "No. %d" % self.number comment = tags.p(self.comment) return tag(author, timestamp, number, comment)
crap = pdoc.to_html(_EpydocLinker(source)) except Exception, e: reportErrors(source, [e.__class__.__name__ +': ' + str(e)]) return (boringDocstring(doc, summary), [e.__class__.__name__ +': ' + str(e)]) else: crap = '' if isinstance(crap, unicode): crap = crap.encode('utf-8') if summary: if not crap: return (), [] stan = html2stan(crap) if len(stan) == 1 and isinstance(stan[0], Tag) and stan[0].tagName == 'p': stan = stan[0].children s = tags.span(stan) else: if not crap and not fields: return (), [] stan = html2stan(crap) s = tags.div(stan) fh = FieldHandler(obj) for field in fields: fh.handle(Field(field, obj)) fh.resolve_types() s(fh.format()) return s, [] field_name_to_human_name = { 'ivar': 'Instance Variable',
def doc2stan(obj, summary=False, docstring=None): """Generate an HTML representation of a docstring""" if getattr(obj, 'parsed_docstring', None) is not None: r = html2stan(obj.parsed_docstring.to_html(_EpydocLinker(obj))) if getattr(obj, 'parsed_type', None) is not None: r = [r, ' (type: ', html2stan(obj.parsed_type.to_html(_EpydocLinker(obj))), ')'] return r, [] origobj = obj if isinstance(obj, model.Package): obj = obj.contents['__init__'] if docstring is None: doc = None for source in obj.docsources(): if source.docstring is not None: doc = source.docstring break else: source = obj doc = docstring if doc is None or not doc.strip(): text = "Undocumented" subdocstrings = {} subcounts = {} for subob in origobj.contents.itervalues(): k = subob.kind.lower() subcounts[k] = subcounts.get(k, 0) + 1 if subob.docstring is not None: subdocstrings[k] = subdocstrings.get(k, 0) + 1 if isinstance(origobj, model.Package): subcounts["module"] -= 1 if subdocstrings: plurals = {'class':'classes'} text = "No %s docstring"%origobj.kind.lower() if summary: u = [] for k in sorted(subcounts): u.append("%s/%s %s"%(subdocstrings.get(k, 0), subcounts[k], plurals.get(k, k+'s'))) text += '; ' + ', '.join(u) + " documented" if summary: return tags.span(class_="undocumented")(text), [] else: return tags.div(class_="undocumented")(text), [] if summary: # Use up to three first non-empty lines of doc string as summary. lines = itertools.dropwhile(lambda line: not line.strip(), doc.split('\n')) lines = itertools.takewhile(lambda line: line.strip(), lines) lines = [ line.strip() for line in lines ] if len(lines) > 3: return tags.span(class_="undocumented")('No summary'), [] else: doc = ' '.join(lines) parse_docstring, e = get_parser(obj.system.options.docformat) if not parse_docstring: msg = 'Error trying to import %r parser:\n\n %s: %s\n\nUsing plain text formatting only.'%( obj.system.options.docformat, e.__class__.__name__, e) obj.system.msg('epydoc2stan', msg, thresh=-1, once=True) return boringDocstring(doc, summary), [] errs = [] def crappit(): pass crappit.__doc__ = doc doc = inspect.getdoc(crappit) try: pdoc = parse_docstring(doc, errs) except Exception, e: errs = [e.__class__.__name__ +': ' + str(e)]