In [1]:
from descr import boxy_notebook, descr, HTMLRuleBuilder as RB
from descr.util import Object
pr = boxy_notebook(always_setup = True)
class Person(object):
def __init__(self, name, age, occupation):
self.name, self.age, self.occupation = name, age, occupation
def __descr__(self, recurse):
return recurse(Object("Person", self.name, age = self.age, occupation = self.occupation))
peter = Person("Peter", 20, "baker")
pr(peter)
Now, let's investigate what exactly it is that we are dealing with. The function that calls __descr__
and will give itself as the recurse
argument is, by default, the descr
function (see import on top).
In [2]:
descr(peter)
Out[2]:
So it's really just a list of lists or tuples, with sets of classes. In a nutshell:
str
, int
and other basic types are leavesset
is a node with other nodes and leaves as childrenset
(or frozenset
), when it is a child of a node, is a set of classes for that
node. If more than one is encountered, the node's classes is their union.And about the classes you can make the following observations:
@foo
is the class given to objects of class Foo
+bar
is the class given to the label "bar"Now, you could pretty-print that:
In [3]:
pr(descr(peter))
However, that's confusing, because the differences between sets, lists and tuples only show up on hover even though the difference is properly crucial, and if there are generators, they will not be expanded (even though they would be if they were describing anything else than themselves).
Thankfully, you can use Description(descr(obj))
or Quote(obj)
to get something better:
In [4]:
from descr.util import Quote, Description
pr(Quote([1, 2.3, 4+5j]))
pr(Quote(dict(a = 1, b = 2)))
pr(Quote(peter)) # alternatively: pr(Description(descr(peter)))
Still, though, many processing rules that are applied to such descriptions add classes to nodes, and
some even rearrange the children. Quote
gives you the description prior to the application
of any rules, but you might want to see the result at various stages of the transformation.
For instance, @list
, @tuple
and other sequences get the sequence
class. @str
, @int
,
etc. get the scalar
class.
For instance, the CSS rules understandably apply to the final HTML that's generated. You can
get the raw string using pr.translate(descr(obj))
, which is certainly informative (it will
show you the CSS, for one). You can also use the inspect
rule:
In [5]:
pr(pr.translate(descr(peter)))
rules = RB().inspect("*")
pr(peter, rules = rules)
rules = RB().inspect(".{+age}")
pr(peter, rules = rules)
You can see how that is structured by inspecting descr.html.HTMLNode
objects.
In [6]:
from descr.html import HTMLNode
node = HTMLNode({"class1", "class2"}, ["child1", "child2"])
pr(node)
pr(Quote(node))
rules = RB().inspect("*")
pr(node, rules = rules)
This should suffice to tell you what kind of rules to make to manipulate that output (clearing out uninteresting classes, highlighting interesting ones, etc.) For instance:
In [7]:
hide = "scalar sequence stack vstack assoc_separator".split()
rules = RB().inspect("*").rearrange(".{@HTMLNode} > .{+classes}", lambda classes, children: [child for child in children if child not in hide] or ['---'])
pr(peter, rules = rules)
In [7]: