def loop(self): pyv = sys.version_info self.session.queue_result( H.div( "Starting interpreter in ", self.format_modname(), H.br(), f"Snektalk {version} using Python {pyv.major}.{pyv.minor}.{pyv.micro}", ), type="info", ) try: while True: try: prompt = H.span["snek-input-mode-python"](self.prompt) with self.session.prompt(prompt) as cmd: if cmd["command"] == "expr": expr = cmd["expr"] if expr.strip(): try: self.dispatch(expr) except SnektalkInterrupt as exc: print(exc) elif cmd["command"] == "noop": pass except SnektalkInterrupt: continue except StopEvaluator: return
def __hrepr__(self, H, hrepr): params = sktk_hjson(self.parameters) self.active = True tmpid = f"$$tmp{next(_count)}" return H.div( H.div(id=tmpid), H.script(f""" (() => {{ let elem = document.getElementById('{tmpid}'); let existing = document.getElementById('{self.jsid}'); if (existing && existing.handler) {{ // Move the existing div elem.parentElement.replaceChild( existing, elem ); }} else {{ elem.id = '{self.jsid}'; requirejs.undef('{self.jsid}'); define( '{self.jsid}', ['{self.js_constructor}'], ctor => {{ let obj = new ctor(elem, {params}); elem.handler = obj; return new WeakRef(obj); }} ); require(['{self.jsid}'], _ => null); }} }})(); """), )
def _run(self, xs: exactly(tuple), *, depth): if depth == self.max_depth: return self.ref(xs) elems = [self.run(x, depth=depth + 1) for x in xs] if len(xs) == 1: elems.append(H.atom("")) return H.bracketed(elems, start="(", end=")", delimiter=", ")
def command_quit(self, expr, glb, lcl): self.session.queue_result(H.div("/quit"), type="echo") self.session.queue_result( H.div("Quitting interpreter in ", self.format_modname()), type="info", ) # Small delay so that the messages get flushed time.sleep(0.01) raise StopEvaluator()
def test_javascript_tag_req_list(): assert sht( H.javascript("xxx='hello';", require=["abc", "d/ef"], export="xxx") ) == H.script( "define('xxx', ['abc', 'd/ef'], (abc, ef) => {", "xxx='hello';", "\nreturn xxx;});", "require(['xxx'], _ => {});", ).fill( resources=_reqjs )
def test_javascript_tag_lazy(): assert sht( H.javascript("xxx='hello';", require="abc", export="xxx", lazy=True) ) == H.script( "define('xxx', ['abc'], (abc) => {", "xxx='hello';", "\nreturn xxx;});", "", ).fill( resources=_reqjs )
def hrepr(self, prop: property): # noqa: F811 if self.state.depth == 0: title = "property" return self.H.instance( H.pair("fget", self(edit(prop.fget)), delimiter="="), H.pair("fset", self(edit(prop.fset)), delimiter="="), H.pair("fdel", self(edit(prop.fdel)), delimiter="="), type=title, vertical=True, ) else: return NotImplemented
def test_nesting(): assert matches(H.div(H.div(H.b("inner"))), "<div><div><b>inner</b></div></div>") assert matches(H.div(H.b("hello"), H.i("there")), "<div><b>hello</b><i>there</i></div>") assert matches( H.div([[[H.b("hello"), [H.i("there")]]]]), "<div><b>hello</b><i>there</i></div>", )
def test_javascript_tag_req_dict(): assert sht( H.javascript( "xxx='hello';", require={"abc": "A", "d/ef": "B"}, export="xxx" ) ) == H.script( "define('xxx', ['abc', 'd/ef'], (A, B) => {", "xxx='hello';", "\nreturn xxx;});", "require(['xxx'], _ => {});", ).fill( resources=_reqjs )
def _run(self, xs: exactly(set), *, depth): if depth == self.max_depth: return self.ref(xs) if not xs: return H.atom("set()") else: return H.bracketed( [self.run(x, depth=depth + 1) for x in xs], start="{", end="}", delimiter=",", )
def test_constructed_element(): assert sht( H.div["chapeau"](id="melon", constructor="fou", options={"x": 1},) ) == H.inline( H.div["chapeau"](id="melon"), sht( H.javascript( "new fou(document.getElementById('melon'), {\"x\": 1});", require="fou", lazy=False, ) ), )
def test_multiref(): li = [1, 2] lili = [li, li] assert hrepr(lili) == H.div["hreprt-list", "hrepr-bracketed"]( H.div["hrepr-open"]("["), H.div["hreprl-h", "hrepr-body"]( H.div( H.div["hrepr-refbox"]( H.span["hrepr-ref"]("#", 1, "="), H.div["hreprt-list", "hrepr-bracketed"]( H.div["hrepr-open"]("["), H.div["hreprl-h", "hrepr-body"]( H.div(H.span["hreprt-int"]("1")), H.div(H.span["hreprt-int"]("2")), ), H.div["hrepr-close"]("]"), ), ) ), H.div( H.div["hrepr-refbox"]( H.span["hrepr-ref"]("#", 1, "="), H.div["hreprt-list", "hrepr-bracketed"]( H.div["hrepr-open"]("["), H.div["hreprl-s", "hrepr-body"](H.div("..."),), H.div["hrepr-close"]("]"), ), ) ), ), H.div["hrepr-close"]("]"), ) assert hrepr(lili, shortrefs=True) == H.div[ "hreprt-list", "hrepr-bracketed" ]( H.div["hrepr-open"]("["), H.div["hreprl-h", "hrepr-body"]( H.div( H.div["hrepr-refbox"]( H.span["hrepr-ref"]("#", 1, "="), H.div["hreprt-list", "hrepr-bracketed"]( H.div["hrepr-open"]("["), H.div["hreprl-h", "hrepr-body"]( H.div(H.span["hreprt-int"]("1")), H.div(H.span["hreprt-int"]("2")), ), H.div["hrepr-close"]("]"), ), ) ), H.div(H.span["hrepr-ref"]("#", 1)), ), H.div["hrepr-close"]("]"), )
def test_as_page_with_resources(): sty = H.style("b { color: red; }") scr = H.script("x = 1234;") resources = (sty, scr) inner = H.b("resources").fill(resources=scr) tag = H.div("with ", inner).fill(resources=sty) utf8 = H.meta({"http-equiv": "Content-type"}, content="text/html", charset="UTF-8") page = H.inline( H.raw("<!DOCTYPE html>"), H.html(H.head(utf8, *resources), H.body(tag)), ) assert tag.as_page() == page
def __hrepr__(self, H, hrepr): # H.instance is a special kind of tag to format data like an instance. # Notice how we call the hrepr parameter on self.age and self.job to # format them. return H.instance["person"]( H.pair("age", hrepr(self.age), delimiter=" ↦ "), H.pair("job", hrepr(self.job), delimiter=" ↦ "), # The "type" represents the header for the "instance" type=self.name, # "vertical=True" means we'll display the pairs as a table with # the delimiters aligned, instead of sticking them horizontally # next to each other vertical=True, )
def command_debug(self, expr, glb, lcl): from .debug import SnekTalkDb expr = expr.lstrip() glb = glb or self.glb lcl = lcl or self.lcl if expr: self.session.queue(command="echo", value=f"/debug {expr}", process=False) result = SnekTalkDb().runeval_step(expr, glb, lcl) typ = "statement" if result is None else "expression" self.session.queue_result(result, type=typ) else: exc = self.session.blt.get("$$exc_info", None) if exc: self.session.queue( command="echo", value=f"Debugging {exc[0].__qualname__}: {exc[1]}", language="text", process=False, ) tb = exc[2] SnekTalkDb().interaction(tb.tb_frame, tb) else: self.session.queue_result( H.div("Last expression was not an exception"), type="exception", )
def __hrepr_resources__(cls, H): return [ H.javascript( export="plotly", src="https://cdn.plot.ly/plotly-latest.min.js", ), H.javascript( """ function make_plot(element, data) { return plotly.newPlot(element, data); } """, require="plotly", export="make_plot", ), ]
def _run(self, obj: object, *, depth): d = getattr(obj, "__dict__", None) if depth == self.max_depth or not isinstance(d, dict): return self.ref(obj) call = f"sktk.mod({self.ref(type(obj), wrap=str)})" return H.bracketed( [ H.pair(k, self.run(v, depth=depth + 1), delimiter="=") for k, v in d.items() ], start=f"{call}(", end=")", delimiter=", ", ) return self.ref(obj)
def test_trepr(): assert pstr([1, 2, "hello"]) == "[1, 2, 'hello']" assert pstr({"a": 1, "b": 2}) == "{'a': 1, 'b': 2}" assert pstr(Point(1, 2)) == "Point(x=1, y=2)" assert ( pstr(H.span["kls"](H.b("great"), "canyon")) == '<span class="kls"><b>great</b>canyon</span>' )
def __hrepr__(self, H, hrepr): return H.div( constructor="make_plot", options=[{ "x": list(range(len(self.data))), "y": list(self.data) }], )
def _run(self, d: exactly(dict), *, depth): if depth == self.max_depth: return self.ref(d) items = list(d.items()) return H.bracketed( [ H.pair( self.run(k, depth=depth + 1), self.run(v, depth=depth + 1), delimiter=": ", ) for k, v in items ], start="{", end="}", delimiter=", ", )
def test_dataclass(): pt = Point(1, 2) assert hrepr(pt) == H.div["hreprt-Point", "hrepr-instance", "hreprl-v"]( H.div["hrepr-title"]("Point"), H.table["hrepr-body"]( H.tr( H.td(H.span["hreprt-symbol"]("x")), H.td["hrepr-delim"]("="), H.td(H.span["hreprt-int"]("1")), ), H.tr( H.td(H.span["hreprt-symbol"]("y")), H.td["hrepr-delim"]("="), H.td(H.span["hreprt-int"]("2")), ), ), ) assert hrepr(pt, max_depth=0) == H.div[ "hreprt-Point", "hrepr-instance", "hreprl-s" ]( H.div["hrepr-title"]("Point"), H.div["hreprl-s", "hrepr-body"](H.div("...")), )
def join(elems, sep=", ", lastsep=None): """Create a list using the given separators. If lastsep is None, lastsep = sep. Returns: [elem0, (sep, elem1), (sep, elem2), ... (lastsep, elemn)] """ if lastsep is None: lastsep = sep elems = list(elems) if len(elems) <= 1: return elems results = [elems[0]] for elem in elems[1:-1]: results.extend((H.raw(sep), elem)) results.extend((H.raw(lastsep), elems[-1])) return results
def test_structures(): for typ, o, c in ( (tuple, "(", ")"), (list, "[", "]"), (set, "{", "}"), (frozenset, "{", "}"), ): clsname = typ.__name__ assert hrepr(typ((1, 2))) == H.div[ f"hreprt-{clsname}", "hrepr-bracketed" ]( H.div["hrepr-open"](o), H.div["hreprl-h", "hrepr-body"]( H.div(H.span["hreprt-int"]("1")), H.div(H.span["hreprt-int"]("2")), ), H.div["hrepr-close"](c), )
def sktk_html(self, node: HType.include): _, children, data = _extract_as(self, node, "include", path=None, type=None) if data.type is None or data.path is None: raise TypeError("H.include must have a type and a path") path = os.path.expanduser(data.path) path = os.path.abspath(path) if data.type == "text/css": return H.link(rel="stylesheet", href=f"/fs{path}") elif data.type == "text/javascript": return H.script(type="text/javascript", src=f"/fs{path}") else: raise TypeError(f"Cannot include type '{data.type}'")
def prompt(self, prompt="", nav=H.span()): self.set_prompt(prompt) self.set_nav(nav) self._clean_owners() self._current_prompt() expr = self.next() with self.set_context(): with new_evalid(): yield expr
def hrepr(self, fn: types.BuiltinFunctionType): # noqa: F811 if self.state.depth == 0: return H.instance( H.pre["snek-docstring"](fn.__doc__), type=fn.__name__, vertical=True, ) else: return NotImplemented
def __hrepr__(self, H, hrepr): size = hrepr.config.swatch_size or 25 style = f""" background: rgb({self.r}, {self.g}, {self.b}); width: {size}px; height: {size}px; margin: 3px; """ return H.div(style=style)
def test_dunder(): assert hrepr(Banana("starchy")) == H.span["banana"]( H.span["hreprt-str"]("starchy")) assert hrepr(Banana("starchy"), max_depth=0) == H.span["banana"]("B A N A N A") assert hrepr(Plantain("starchy")) == H.span["banana"]( H.span["hreprt-str"]("starchy")).fill( resources=H.style(".banana { color: yellow; }")) assert chrepr(Banana(10)) == H.span["banana"](H.span["myint"]("-10"))
def test_as_page(): utf8 = H.meta( {"http-equiv": "Content-type"}, content="text/html", charset="UTF-8" ) assert real_hrepr.page(1) == H.inline( H.raw("<!DOCTYPE html>"), H.html(H.head(utf8, H.style(css_hrepr)), H.body(real_hrepr(1)),), )
def prompt(self, prompt="", nav=H.span(), evaluator=None): self.set_prompt(prompt) self.set_nav(nav) self.evaluators[NamedThreads.current()] = evaluator self._clean_owners() self._current_prompt() expr = self.next() with self.set_context(): with new_evalid(): yield expr