Python对象的可扩展HTML表示。
项目描述
hrepr
hrepr
为Python对象输出HTML/美观表示。
✅ 列表、字典、数据类、布尔值等的漂亮、多彩的表示
✅ 无与伦比的扩展性和可配置性
✅ 处理递归数据结构
✅ 与Jupyter笔记本兼容
我建议研究示例文件来学习 hrepr
python examples/exhibit.py > exhibit.html
(然后查看HTML文件)
还可以查看位于 examples/Basics.ipynb
的Jupyter笔记本,但请注意,GitHub由于注入的样式/脚本无法正确显示它。
安装
pip install hrepr
用法
from hrepr import hrepr
obj = {'potatoes': [1, 2, 3], 'bananas': {'cantaloups': 8}}
# Print the HTML representation of obj
print(hrepr(obj))
# Wrap the representation in <html><body> tags and embed the default
# css style files in a standalone page, which is saved to obj.html
hrepr.page(obj, file="obj.html")
在Jupyter笔记本中,您可以从任何单元格返回 hrepr(obj)
,它将显示其表示。您还可以编写 display_html(hrepr(obj))
。
自定义表示
可以使用以下三种方法定义对象的自定义表示(不需要定义所有这些,只需与您的案例相关的那些即可)
__hrepr__(self, H, hrepr)
返回常规HTML表示。- 使用
H.span["some-class"](some-content, some_attr=some_value)
生成HTML。 - 使用
hrepr(self.x)
生成子字段x
的表示。 hrepr.config
包含在顶级调用hrepr
中提供的任何关键字参数。例如,如果您调用hrepr(obj, blah=3)
,则hrepr.config.blah == 3
在所有后续调用__hrepr__
中(所有键的默认值是None
)。
- 使用
__hrepr_short__(self, H, hrepr)
返回一个 短 表示,理想情况下为固定大小。- 当达到最大深度或出现重复引用时,该方法输出的结果被使用。
- 仅包含必要的信息。简短意味着简洁。
__hrepr_resources__(cls, H)
是一个 类方法,它返回该类所有实例共有的资源(通常是一个样式表或脚本)。- 生成页面时,资源将放入
<head>
中。 - 你可以返回一个资源列表。
- 生成页面时,资源将放入
不需要依赖 hrepr
。
例如
class Person:
def __init__(self, name, age, job):
self.name = name
self.age = age
self.job = job
@classmethod
def __hrepr_resources__(cls, H):
# Note: you might need to add "!important" next to some rules if
# they conflict with defaults from hrepr's own CSS.
return H.style("""
.person {
background: magenta !important;
border-color: magenta !important;
}
.person-short { font-weight: bold; color: green; }
""")
def __hrepr__(self, H, hrepr):
# hrepr.make.instance is a helper to show a table with a header that
# describes some kind of object
return hrepr.make.instance(
title=self.name,
fields=[["age", self.age], ["job", self.job]],
delimiter=" ↦ ",
type="person",
)
def __hrepr_short__(self, H, hrepr):
return H.span["person-short"](self.name)
引用
hrepr
可以处理循环引用。此外,如果结构中找到多个相同对象,则只打印第一个出现的完整表示,其余的将是一个数字引用,映射到对象的简短表示。它看起来像这样
配置键 shortrefs
和 norefs
控制引用的表示
当存在循环引用时,忽略 norefs
。
HTML生成
使用 __hrepr__
方法的 H
参数生成HTML,或者导入它并直接使用。
from hrepr import H
html = H.span["bear"](
"Only ", H.b("YOU"), " can prevent forest fires!",
style="color: brown;"
)
print(html)
# <span class="bear" style="color: brown;">Only <b>YOU</b> can prevent forest fires!</span>
H
可以逐步构建:如果您有一个元素,您可以调用它以添加子元素,索引它以添加类,等等。例如
from hrepr import H
html = H.span()
html = html("Only ")
html = html(style="color: brown;")["bear"]
html = html(H.b("YOU"), " can prevent forest fires!")
print(html)
# <span class="bear" style="color: brown;">Only <b>YOU</b> can prevent forest fires!</span>
这可以很方便地稍微调整生成的HTML。例如,hrepr(obj)["fox"]
将将类 fox
添加到对象的表示中。
辅助工具
hrepr.make.instance(title, fields, delimiter=None, type=None)
:将字段格式化为类似于数据类的形式,标题在最上方。hrepr.make.bracketed(body, start, end, type=None)
:使用指定的起始/结束括号格式化正文。
使用JavaScript库
函数 J
允许您创建JavaScript表达式。如果表达式以HTML元素作为参数,您可以创建一个并使用 returns()
语句传递它,该语句告诉hrepr将其插入到 J()
表达式所在的位置。
例如,您可以加载Plotly并创建一个像这样的图表
from hrepr import H, J, returns
def plot(data):
Plotly = J(src="https://cdn.plot.ly/plotly-latest.min.js").Plotly
return Plotly.newPlot(
returns(H.div()),
[{"x": list(range(len(data))), "y": list(data)}],
)
print(plot([math.sin(x / 10) for x in range(100)]).as_page())
上面的代码将
- 将指定的脚本放入页面的
<head>
元素中(这就是为什么需要as_page()
调用来使其工作)。 - 插入一些hrepr库代码。
- 在
J()
调用处插入一个<div>
,如returns(H.div())
所指定,并带有自动生成的ID。 - 在全局命名空间中获取
Plotly.newPlot
函数。 - 用第一个参数(作为
div
元素)和任何其他给定的参数调用它(只要它们可以序列化为JSON)。
它看起来像这样
您当然可以在 J
和 H
内嵌套 J
,例如 H.body(H.h1(...), H.div(J(...)))
,只要您喜欢,这样您可以轻松地组合多个库。请注意,如果没有 returns()
参数的JavaScript,它可能需要返回一个HTML元素以插入其代替(将自动创建占位符)。
小心处理 J
对象:由于它们覆盖了 __getattr__
和 __call__
,它们几乎永远不会引发异常,并且很容易意外生成不正确的表达式。
模块
另一个例子,这次使用ESM(模块)
cystyle = [{"selector": "node","style": {"background-color": "#800", "label": "data(id)"},},{"selector": "edge","style": {"width": 3,"line-color": "#ccc","target-arrow-color": "#ccc","target-arrow-shape": "triangle","curve-style": "bezier"}}]
cytoscape = J(module="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.23.0/cytoscape.esm.min.js")
j = cytoscape(
container=returns(H.div(style="width:500px;height:500px;border:1px solid black;")),
elements=[
{"data": {"id": "A"}},
{"data": {"id": "B"}},
{"data": {"id": "C"}},
{"data": {"source": "A", "target": "B"}},
{"data": {"source": "B", "target": "C"}},
{"data": {"source": "C", "target": "A"}},
],
style=cystyle,
layout={"name": "cose"},
)
print(j.as_page())
上面的代码将像前面的例子一样工作,但有以下区别
- 导入指定的模块。
- 所有关键字参数都打包成一个对象,该对象将作为最后一个(在这种情况下,唯一的)参数传递给模块的默认导出。
如果您想使用非默认导出,请使用 namespace=
而不是 module=
。例如,如果您想使用JavaScript导入 import {fn} from "xxx"
,请使用 J(namespace="xxx").fn(...)
。
自定义hrepr
混合
如果您想真正自定义 hrepr,可以使用混入(mixins)。它们看起来像一点黑魔法,但它们足够简单。
# ovld is one of the dependencies of hrepr
from ovld import ovld, extend_super, has_attribute, OvldMC
from hrepr import hrepr
class MyMixin(metaclass=OvldMC):
# Change the representation of integers
@extend_super
def hrepr_resources(self, cls: int):
# Note: in hrepr_resources, cls is the int type, not an integer
return self.H.style(".my-integer { color: fuchsia; }")
@extend_super
def hrepr(self, n: int):
return self.H.span["my-integer"]("The number ", str(n))
# Specially handle any object with a "quack" method
def hrepr(self, duck: has_attribute("quack")):
return self.H.span("🦆")
规则的注释可以是类型、ovld.has_attribute
,或者任何用 ovld.meta
装饰器包装的函数,只要该函数在类上操作。有关更多信息,请参阅 ovld 的文档。
是的,您可以在类内部多次定义 hrepr
,只要它们具有不同的注释并且您继承自 Hrepr
。您也可以以相同的方式定义 hrepr_short
或 hrepr_resources
。
后处理器
hrepr
可以提供一个后处理器,该后处理器在任意对象的表示上被调用。您可以使用它来执行诸如突出特定对象之类的操作。
from hrepr import H
style = H.style(".highlight { border: 3px solid red !important; }")
def highlight(x):
def postprocess(element, obj, hrepr):
if obj == x:
# Adds the "highlight" class and attaches a style
return element["highlight"].fill(resources=style)
else:
return element
return postprocess
hrepr([1, 2, [3, 4, 2]], postprocess=highlight(2))
hrepr 变体
将所有这些放在一起,您可以为 hrepr
创建一个 变体。
hrepr2 = hrepr.variant(mixins=MyMixin, postprocess=highlight(2))
hrepr2([1, 2, 3]) # Will use the mixins and postprocessor
配置 hrepr 函数本身
或者,您也可以配置主要的 hrepr
。
hrepr.configure(mixins=MyMixin, postprocess=highlight(2))
但请注意,与变体不同,上述操作将修改 hrepr
用于其他所有内容。
项目详情
下载文件
下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。