Viewing PyGX Objects in HTML¶
pg.views provides a versatile, highly extensible view system that is universal across all PyGX objects. With the new pg.view API (together with pg.Content, pg.View concepts), users can generate the views of objects in various formats, such as HTML. Additionally, developers can easily add new views or extend existing ones by subclassing the pg.View class. The system also makes it simple to integrate user-defined types into each view for customized behavior.
In [ ]:
Copied!
!pip install pygx --pre
!pip install pygx --pre
In [24]:
Copied!
import pygx as pg
import pygx as pg
Viewing any object in HTML tree view¶
In [25]:
Copied!
class Foo:
pass
class Bar(pg.Object):
x: str
y: int = 1
value = pg.Dict(
x=1,
y=[
1,
dict(a=[2, 3, 4]),
'short string',
],
z='This is a very long strong\n' * 10,
w=[],
a=1.2,
b=2,
c=None,
d=True,
e=Foo(),
f=Bar('abc'),
g=int,
)
# Try hovering the mouse over the title bar and keys of each item.
value
class Foo:
pass
class Bar(pg.Object):
x: str
y: int = 1
value = pg.Dict(
x=1,
y=[
1,
dict(a=[2, 3, 4]),
'short string',
],
z='This is a very long strong\n' * 10,
w=[],
a=1.2,
b=2,
c=None,
d=True,
e=Foo(),
f=Bar('abc'),
g=int,
)
# Try hovering the mouse over the title bar and keys of each item.
value
Out[25]:
Dict(...){
'x': 1,
'y': [
1,
{
'a': [
2,
3,
4
]
},
'short string'
],
'z': 'This is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a ver...',
'w': [],
'a': 1.2,
'b': 2,
'c': None,
'd': True,
'e': <__main__.Foo object at 0x32e992b95110>,
'f': Bar(
x='abc',
y=1
),
'g': <class 'int'>
}
xxint1
1yyList(...)[
1,
{
'a': [
2,
3,
4
]
},
'short string'
]
| 0y[0] | 1 | ||||||
| 1y[1] |
|
| 0y[1].a[0] | 2 |
| 1y[1].a[1] | 3 |
| 2y[1].a[2] | 4 |
zzstr'This is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a ver...'
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
wwList(...)[]
aafloat1.2
1.2bbint2
2ccNoneType(...)None
NoneddboolTrue
TrueeeFoo(...)<__main__.Foo object at 0x32e992b95110>
<__main__.Foo object at 0x32e992b95110>ggtype<class 'int'>
<class 'int'>Customizing the view¶
Use different key styles¶
In [26]:
Copied!
pg.view(value, key_style='label')
pg.view(value, key_style='label')
Out[26]:
Dict(...){
'x': 1,
'y': [
1,
{
'a': [
2,
3,
4
]
},
'short string'
],
'z': 'This is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a ver...',
'w': [],
'a': 1.2,
'b': 2,
'c': None,
'd': True,
'e': <__main__.Foo object at 0x32e992b95110>,
'f': Bar(
x='abc',
y=1
),
'g': <class 'int'>
}
| xx | 1 | ||||||||||||||
| yy |
|
| 0y[0] | 1 | ||||||||
| 1y[1] |
|
| ay[1].a |
|
| 0y[1].a[0] | 2 |
| 1y[1].a[1] | 3 |
| 2y[1].a[2] | 4 |
str'This is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a ver...'
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
List(...)[]
Foo(...)<__main__.Foo object at 0x32e992b95110>
<__main__.Foo object at 0x32e992b95110>type<class 'int'>
<class 'int'>Use extra_flags to specify component-specfic flags¶
In [27]:
Copied!
# Hide default values.
pg.view(Bar('abc', 1), extra_flags=dict(exclude_defaults=True))
# Hide default values.
pg.view(Bar('abc', 1), extra_flags=dict(exclude_defaults=True))
Out[27]:
Highlight/lowlight values¶
In [28]:
Copied!
pg.view(
value,
# Highlight all int and list or key is 'e'
highlight=lambda k, v, p: isinstance(v, (int, list)) or k.key == 'e',
# Lowlight keys named 'a', 'b' and 'c'.
lowlight=lambda k, v, p: k.key in ['a', 'b', 'c']
)
pg.view(
value,
# Highlight all int and list or key is 'e'
highlight=lambda k, v, p: isinstance(v, (int, list)) or k.key == 'e',
# Lowlight keys named 'a', 'b' and 'c'.
lowlight=lambda k, v, p: k.key in ['a', 'b', 'c']
)
Out[28]:
Dict(...){
'x': 1,
'y': [
1,
{
'a': [
2,
3,
4
]
},
'short string'
],
'z': 'This is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a ver...',
'w': [],
'a': 1.2,
'b': 2,
'c': None,
'd': True,
'e': <__main__.Foo object at 0x32e992b95110>,
'f': Bar(
x='abc',
y=1
),
'g': <class 'int'>
}
xxint1
1yyList(...)[
1,
{
'a': [
2,
3,
4
]
},
'short string'
]
| 0y[0] | 1 | ||||||
| 1y[1] |
|
| 0y[1].a[0] | 2 |
| 1y[1].a[1] | 3 |
| 2y[1].a[2] | 4 |
zzstr'This is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a ver...'
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
wwList(...)[]
aafloat1.2
1.2bbint2
2ccNoneType(...)None
NoneddboolTrue
TrueeeFoo(...)<__main__.Foo object at 0x32e992b95110>
<__main__.Foo object at 0x32e992b95110>ggtype<class 'int'>
<class 'int'>Collapsing nodes¶
In [29]:
Copied!
# Collapse at root.
pg.view(value, collapse_level=0)
# Collapse at root.
pg.view(value, collapse_level=0)
Out[29]:
Dict(...){
'x': 1,
'y': [
1,
{
'a': [
2,
3,
4
]
},
'short string'
],
'z': 'This is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a ver...',
'w': [],
'a': 1.2,
'b': 2,
'c': None,
'd': True,
'e': <__main__.Foo object at 0x32e992b95110>,
'f': Bar(
x='abc',
y=1
),
'g': <class 'int'>
}
xxint1
1yyList(...)[
1,
{
'a': [
2,
3,
4
]
},
'short string'
]
| 0y[0] | 1 | ||||||
| 1y[1] |
|
| 0y[1].a[0] | 2 |
| 1y[1].a[1] | 3 |
| 2y[1].a[2] | 4 |
zzstr'This is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a ver...'
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
wwList(...)[]
aafloat1.2
1.2bbint2
2ccNoneType(...)None
NoneddboolTrue
TrueeeFoo(...)<__main__.Foo object at 0x32e992b95110>
<__main__.Foo object at 0x32e992b95110>ggtype<class 'int'>
<class 'int'>In [30]:
Copied!
# Uncollapse everything.
pg.view(value, collapse_level=None)
# Uncollapse everything.
pg.view(value, collapse_level=None)
Out[30]:
Dict(...){
'x': 1,
'y': [
1,
{
'a': [
2,
3,
4
]
},
'short string'
],
'z': 'This is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a ver...',
'w': [],
'a': 1.2,
'b': 2,
'c': None,
'd': True,
'e': <__main__.Foo object at 0x32e992b95110>,
'f': Bar(
x='abc',
y=1
),
'g': <class 'int'>
}
xxint1
1yyList(...)[
1,
{
'a': [
2,
3,
4
]
},
'short string'
]
| 0y[0] | 1 | ||||||
| 1y[1] |
|
| 0y[1].a[0] | 2 |
| 1y[1].a[1] | 3 |
| 2y[1].a[2] | 4 |
zzstr'This is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a ver...'
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
wwList(...)[]
aafloat1.2
1.2bbint2
2ccNoneType(...)None
NoneddboolTrue
TrueeeFoo(...)<__main__.Foo object at 0x32e992b95110>
<__main__.Foo object at 0x32e992b95110>ggtype<class 'int'>
<class 'int'>In [31]:
Copied!
# Uncollapse the first level + selected nodes.
pg.view(
value,
collapse_level=1,
uncollapse=['y[1].a']
)
# Uncollapse the first level + selected nodes.
pg.view(
value,
collapse_level=1,
uncollapse=['y[1].a']
)
Out[31]:
Dict(...){
'x': 1,
'y': [
1,
{
'a': [
2,
3,
4
]
},
'short string'
],
'z': 'This is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a ver...',
'w': [],
'a': 1.2,
'b': 2,
'c': None,
'd': True,
'e': <__main__.Foo object at 0x32e992b95110>,
'f': Bar(
x='abc',
y=1
),
'g': <class 'int'>
}
xxint1
1yyList(...)[
1,
{
'a': [
2,
3,
4
]
},
'short string'
]
| 0y[0] | 1 | ||||||
| 1y[1] |
|
| 0y[1].a[0] | 2 |
| 1y[1].a[1] | 3 |
| 2y[1].a[2] | 4 |
zzstr'This is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a very long strong\nThis is a ver...'
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
wwList(...)[]
aafloat1.2
1.2bbint2
2ccNoneType(...)None
NoneddboolTrue
TrueeeFoo(...)<__main__.Foo object at 0x32e992b95110>
<__main__.Foo object at 0x32e992b95110>ggtype<class 'int'>
<class 'int'>Show/hide tooltips¶
In [32]:
Copied!
pg.view(value, enable_summary_tooltip=False, enable_key_tooltip=True)
pg.view(value, enable_summary_tooltip=False, enable_key_tooltip=True)
Out[32]:
Dict(...)
xxint
1yyList(...)
| 0y[0] | 1 | ||||||
| 1y[1] |
|
| 0y[1].a[0] | 2 |
| 1y[1].a[1] | 3 |
| 2y[1].a[2] | 4 |
zzstr
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
This is a very long strong
wwList(...)
aafloat
1.2bbint
2ccNoneType(...)
Noneddbool
TrueeeFoo(...)
<__main__.Foo object at 0x32e992b95110>ggtype
<class 'int'>Use pg.diff to compare values.¶
In [33]:
Copied!
#pg.dev.reload(workspace='lf_html')
pg.diff(1, 1)
#pg.dev.reload(workspace='lf_html')
pg.diff(1, 1)
Out[33]:
DiffNo diff
In [34]:
Copied!
class Foo(pg.Object):
x: int
y: str = 'abc'
class Bar(Foo):
pass
pg.diff(
[0, Foo(x=1), Foo(x=2), 3],
[0, Foo(x=1, y='def'), Bar(x=2)],
mode='both'
)
class Foo(pg.Object):
x: int
y: str = 'abc'
class Bar(Foo):
pass
pg.diff(
[0, Foo(x=1), Foo(x=2), 3],
[0, Foo(x=1, y='def'), Bar(x=2)],
mode='both'
)
Out[34]:
List[
'0': 0,
'1': Foo(
'x': 1,
'y': Diff(
left='abc',
right='def'
)
),
'2': Diff(
left=Foo(
x=2,
y='abc'
),
right=Bar(
x=2,
y='abc'
)
),
'3': Diff(
left=3,
right=MISSING
)
]
| 0[0] | 0 | ||||
| 1[1] |
|
| x[1].x | 1 |
| y[1].y | 'abc''def' |
Foo(...)Foo(
x=2,
y='abc'
)
x[2].left.xint2
2y[2].left.ystr'abc'
'abc'3
Customize HTML views for your objects¶
In [35]:
Copied!
# By implementing pg.views.HtmlTreeView.Extension, rendering methods are
# routed to the object's members. Check out
# https://github.com/google/pygx/blob/fcb53ebafd539e412ae0e6c730b8cf754e65108f/pygx/core/views/html/tree_view.py#L38-L191
class MyImage(pg.Object, pg.views.HtmlTreeView.Extension):
url: str
def _html_tree_view_content(self, *, view: pg.views.HtmlTreeView, **kwargs):
kwargs.pop('parent', None)
return pg.Html.element(
'div',
[
pg.Html.element(
'img',
src=self.url
),
view.complex_value(
self.sym_init_args,
parent=self,
**kwargs
)
]
).add_style(
# Add or override CSS styles
"""
.my-image .object_key{
color: white;
border: 1px solid white;
background-color: red;
}
"""
)
pg.view(
pg.Dict(
x=1,
y=MyImage(
url='https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcRb8BMw3RWhIF-wAiHpwibf7h0SNZUZRa0qA0IQ-d5p3EuNL0zR'
)
),
collapse_level=None
)
# By implementing pg.views.HtmlTreeView.Extension, rendering methods are
# routed to the object's members. Check out
# https://github.com/google/pygx/blob/fcb53ebafd539e412ae0e6c730b8cf754e65108f/pygx/core/views/html/tree_view.py#L38-L191
class MyImage(pg.Object, pg.views.HtmlTreeView.Extension):
url: str
def _html_tree_view_content(self, *, view: pg.views.HtmlTreeView, **kwargs):
kwargs.pop('parent', None)
return pg.Html.element(
'div',
[
pg.Html.element(
'img',
src=self.url
),
view.complex_value(
self.sym_init_args,
parent=self,
**kwargs
)
]
).add_style(
# Add or override CSS styles
"""
.my-image .object_key{
color: white;
border: 1px solid white;
background-color: red;
}
"""
)
pg.view(
pg.Dict(
x=1,
y=MyImage(
url='https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcRb8BMw3RWhIF-wAiHpwibf7h0SNZUZRa0qA0IQ-d5p3EuNL0zR'
)
),
collapse_level=None
)
Out[35]: