Skip to content

Commit 1252510

Browse files
committed
update documentation
1 parent e592ff0 commit 1252510

File tree

8 files changed

+668
-64
lines changed

8 files changed

+668
-64
lines changed

README.rst

Lines changed: 70 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -10,33 +10,53 @@
1010
.. image:: https://codecov.io/gh/fabiommendes/hyperpython/branch/master/graph/badge.svg
1111
:target: https://codecov.io/gh/fabiommendes/hyperpython
1212
:alt: Code coverage
13+
.. module:: hyperpython
1314

1415

15-
HyperPython
16+
Hyperpython
1617
===========
1718

18-
HyperPython is a Python interpretion of
19-
`Hyperscript <http://https://github.com/hyperhype/hyperscript>`_. If you are not
20-
familiar with Hyperscript, think of it as React, but using pure Javascript
21-
instead of JSX. Hyperpython allow us to generate, manipulate and query
22-
HTML documents using a small DSL embedded in Python. And just like in Hyperscript,
23-
the default entry point of Hyperpython the `h` function:
19+
Hyperpython is a Python interpretation of Hyperscript_. If you are not
20+
familiar with Hyperscript, think of it as a pure Javascript alternative to JSX.
21+
Hyperpython allow us to generate, manipulate and query HTML documents using a
22+
small DSL embedded in Python. Just like Hyperscript, the default entry point is
23+
the :func:`hyperpython.h` function:
2424

2525
>>> from hyperpython import h
26-
>>> elem = h('p', {'class': 'hello'}, 'Hello World!')
26+
>>> elem = h('p', {'class': 'hello'}, ['Hello World!'])
27+
28+
.. _Hyperscript: https://github.com/hyperhype/hyperscript
2729

2830
This can be converted to HTML by calling ``str()`` on the element:
2931

3032
>>> print(elem)
3133
<p class="hello">Hello World!</p>
3234

33-
The p tag can also be created by the standalone p function (and we have a
34-
corresponding function to each valid HTML5 tag).
35+
It accepts Hyperscript's ``h(tag, attributes, list_of_children)`` signature,
36+
but we encourage to use more idiomatic Python version that uses keyword arguments to
37+
represent attributes instead of a dictionary. If the list of children contains a
38+
single element, we can also omit the brackets:
39+
40+
>>> h('p', 'Hello World!', class_='hello') == elem
41+
True
42+
43+
Notice in the snippet above that we had to escape the "class" attribute because
44+
it is a reserved word in Python. Hyperpython maps Python keyword arguments by replacing
45+
underscores with dashes and by escaping Python reserved words such as "class", "for"
46+
"from", etc with a trailing underscore.
3547

36-
>>> print(p({'class': 'hello'}, 'Hello World!'))
48+
Elements can be be more conveniently created with standalone functions representing
49+
specific tags:
50+
51+
>>> print(p('Hello World!', class_='hello'))
3752
<p class="hello">Hello World!</p>
3853

39-
There is also no problem with nested structures:
54+
In Python, keyword arguments cannot appear after positional arguments. This means
55+
that attributes are placed *after* the list of children, which isn't natural to
56+
represent HTML. For simple elements like the ones above, it does not hinders
57+
legibility, but for larger structures it can be a real issue. Hyperpython
58+
provides two alternatives. The first uses the index notation:
59+
4060

4161
>>> from hyperpython import div, p, h1
4262
>>> fragment = \
@@ -45,10 +65,24 @@ There is also no problem with nested structures:
4565
... p('Now you can write HTML in Python!'),
4666
... ]
4767

48-
HyperPython returns a DOM-like structure which we can introspect, query and
49-
modify later. The main usage, of course, is to generate strings of HTML source
50-
code. We can apply the str() function for a compact representation of the output
51-
code or call ``.pretty()`` method to to get a more human-friendly output.
68+
The second alternative is to use the "children" pseudo-attribute. This is the
69+
approach taken by some Javascript libraries such as React:
70+
71+
>>> fragment = \
72+
... div(class_="alert-box",
73+
... children = [
74+
... h1('Hello Python'),
75+
... p('Now you can write HTML in Python!'),
76+
... ])
77+
78+
79+
Hyperpython returns a DOM-like structure which we can introspect, query and
80+
modify later. The main usage, of course, is to render strings of HTML source
81+
code. We expect that the main use of Hyperpython will be to complement (or even replace)
82+
the templating language in a Python web application. That said, Hyperpython generates a
83+
very compact HTML that is efficient to generate and transmit over the wire. To
84+
get a more human-friendly output (and keep your sanity while debugging), use
85+
the .pretty() method:
5286

5387
>>> print(fragment.pretty())
5488
<div class="alert-box">
@@ -58,41 +92,40 @@ code or call ``.pretty()`` method to to get a more human-friendly output.
5892
<BLANKLINE>
5993

6094

61-
Secret goal: replace templating
62-
===============================
95+
Replacing templates
96+
===================
6397

6498
The goal of ``hyperpython`` is to replace a lot of work that would be traditionally
6599
done with a template engine such as Jinja2 by Python code that generates HTML
66-
fragments. Templating languages are obviously more efficient than pure Python for
67-
string interpolation, and should work fine for simple documents. For large systems,
68-
however, templating can be tedious to create and very hard to maintain.
69-
Templating is usually not a good answer to handle growing complexity.
70-
71-
Many recent Javascript libraries had played with direct manipulation of DOM or
72-
virtual DOM nodes sidestepping the whole business of creating intermediate
73-
HTML strings. React was probably the library that popularized this idea. As they
100+
fragments. Templating languages are obviously more expressive than pure Python for
101+
string interpolation, and are a perfect match for ad hoc documents. For large systems,
102+
they offer little in terms of architecture, organization and code reuse.
103+
104+
A recent trend in Javascript is to promote direct creation of DOM or
105+
virtual DOM nodes sidestepping the whole business of rendering intermediate
106+
HTML strings. React was probably the library that better popularized this idea. As they
74107
nicely put, "Templates separate technologies, not concerns". There is no point
75-
on choosing a deliberately underpowered templating language that has poorly
76-
communicates with your data sources and outputs your document in a flat string
77-
representation since it does not improve architecture or organization.
108+
on choosing a deliberately underpowered programming language that integrates
109+
poorly with your data sources just to output structured documents in a flat string
110+
representation.
78111

79112
The same lesson can be applied to Python on the server side. With Hyperpython,
80-
we generate HTML directly in Python, instead of passing through an intermediate
81-
templating step.
113+
we can generate HTML directly in Python. Hyperpython plays nicely with
114+
existing templating systems, but it makes easy to migrate parts of your rendering
115+
sub-system to Python.
82116

83117
For those afraid of putting too much logic on templates, we recognize that
84118
Hyperpython doesn't prevent anyone from shooting themselves on the foot, but neither
85-
do any minimally powerful templating language. The discipline we must exercise
86-
is to keep business logic separated from view logic (i.e., separate concerns).
87-
Our advice is to break your code in small pieces and compose those pieces in
88-
simple and predictable ways. Incidentally, this is a good advice for any piece
89-
of code ;).
119+
do any minimally powerful templating engine. It always requires some discipline to
120+
keep business logic separated from view logic. Our advice is to break code in
121+
small pieces and compose those pieces in simple and predictable ways.
122+
Incidentally, this is a good advice for any piece of code ;).
90123

91124

92125
Can it be used on Django? Flask? Etc?
93126
=====================================
94127

95-
Yes! Hyperpython is completely framework agnostic. We have a few optional
128+
Of course! Hyperpython is completely framework agnostic. We have a few optional
96129
integrations with Django, but it does not prevent Hyperpython of being used
97130
in other frameworks or without any framework at all. It implements the __html__
98131
interface which is recognized by most templating engines in Python. That way, it

docs/apidoc.rst

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,24 @@ same names of all HTML tags.
2929
.. autofunction:: h
3030

3131

32-
Communication with external Python objects
33-
------------------------------------------
32+
Creation of HTML elements for Python objects
33+
--------------------------------------------
3434

35-
.. module:: hyperpython.components
35+
.. autofunction:: html
3636
.. autofunction:: render
37-
.. autofunction:: render_html
37+
.. autofunction:: fragment
38+
39+
40+
Hyperpython components
41+
----------------------
42+
43+
.. module:: hyperpython.components
44+
45+
All functions bellow belongs to the :mod:`hyperpython.components` module.
3846

3947

4048
Hyperlinks
41-
----------
49+
~~~~~~~~~~
4250

4351
.. autofunction:: hyperlink
4452
.. autofunction:: url
@@ -48,7 +56,7 @@ Hyperlinks
4856

4957

5058
HTML data structures
51-
....................
59+
~~~~~~~~~~~~~~~~~~~~
5260

5361
Those functions convert Python data structures to their natural HTML
5462
representations.
@@ -59,7 +67,7 @@ representations.
5967

6068

6169
Icons
62-
.....
70+
~~~~~
6371

6472
Generic icon support using the <i> tag and helper functions for Font Awesome
6573
icons.
@@ -70,6 +78,6 @@ icons.
7078

7179

7280
Text
73-
....
81+
~~~~
7482

7583
.. autofunction:: markdown

0 commit comments

Comments
 (0)