├── .github
├── dependabot.yml
└── workflows
│ └── test-and-lint.yml
├── .gitignore
├── LICENSE
├── NEWS.md
├── README.md
├── elements.rst
├── htmlgen
├── __init__.py
├── __init__.pyi
├── attribute.py
├── attribute.pyi
├── block.py
├── block.pyi
├── document.py
├── document.pyi
├── element.py
├── element.pyi
├── form.py
├── form.pyi
├── generator.py
├── generator.pyi
├── image.py
├── image.pyi
├── inline.py
├── inline.pyi
├── link.py
├── link.pyi
├── list.py
├── list.pyi
├── py.typed
├── structure.py
├── structure.pyi
├── table.py
├── table.pyi
├── time.py
├── time.pyi
├── timeutil.py
├── timeutil.pyi
├── video.py
└── video.pyi
├── mypy.ini
├── poetry.lock
├── pyproject.toml
└── test_htmlgen
├── __init__.py
├── attribute.py
├── block.py
├── document.py
├── element.py
├── form.py
├── generator.py
├── image.py
├── inline.py
├── link.py
├── list.py
├── structure.py
├── table.py
├── time.py
├── util.py
└── video.py
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: pip
4 | directory: "/"
5 | schedule:
6 | interval: daily
7 | time: '04:00'
8 | open-pull-requests-limit: 10
9 |
--------------------------------------------------------------------------------
/.github/workflows/test-and-lint.yml:
--------------------------------------------------------------------------------
1 | name: Test and lint
2 |
3 | on: [push]
4 |
5 | jobs:
6 | build:
7 |
8 | runs-on: ubuntu-latest
9 | strategy:
10 | matrix:
11 | python-version: ["3.7", "3.8", "3.9", "3.10"]
12 | fail-fast: false
13 |
14 | steps:
15 | - uses: actions/checkout@v3
16 | - name: Set up Python ${{ matrix.python-version }}
17 | uses: actions/setup-python@v4
18 | with:
19 | python-version: ${{ matrix.python-version }}
20 | cache: pip
21 | cache-dependency-path: "**/poetry.lock"
22 | - name: Install poetry
23 | run: pip --disable-pip-version-check install -U poetry
24 | - name: Install Python dependencies
25 | run: poetry install
26 | - name: Type checking with mypy
27 | run: |
28 | poetry run mypy --version
29 | poetry run mypy htmlgen test_htmlgen
30 | - name: Test with unittest
31 | run: poetry run python -Wall -m unittest discover -t . -s test_htmlgen -p "*.py"
32 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.py[cod]
2 |
3 | # C extensions
4 | *.so
5 |
6 | # Packages
7 | *.egg
8 | *.egg-info
9 | dist
10 | build
11 | eggs
12 | parts
13 | bin
14 | var
15 | sdist
16 | develop-eggs
17 | .installed.cfg
18 | lib
19 | lib64
20 | __pycache__
21 |
22 | # virtual environments
23 | .venv*
24 |
25 | # mypy
26 | .mypy_cache
27 |
28 | # Installer logs
29 | pip-log.txt
30 |
31 | # Unit test / coverage reports
32 | .coverage
33 | .tox
34 | nosetests.xml
35 |
36 | # Translations
37 | *.mo
38 |
39 | # Mr Developer
40 | .mr.developer.cfg
41 | .project
42 | .pydevproject
43 |
44 | # PyCharm
45 | .idea
46 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Sebastian Rittau
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/NEWS.md:
--------------------------------------------------------------------------------
1 | # News in version 3.0.1
2 |
3 | ## Bug Fixes
4 |
5 | * Fix import from `collections` instead of `collections.abc` in stubs.
6 |
7 | # News in version 3.0.0
8 |
9 | ## Incompatible Changes
10 |
11 | * Drop support for Python 3.5 and 3.6.
12 |
13 | # News in version 2.0.0
14 |
15 | ## Incompatible Changes
16 |
17 | * Drop support for Python 2.7 and 3.4.
18 |
19 | ## API Additions
20 |
21 | * Add `Video` element.
22 | * Add `Button.disabled`.
23 | * Add `autocomplete` attribute to `Input`, `TextArea`, `Select`, and `Form`.
24 | * Add `enum_attribute`.
25 |
26 | # News in version 1.2.2
27 |
28 | ## API Additions
29 |
30 | * Add `GenValue` and `GenValueGenerator` to `htmlgen`.
31 |
32 | # News in version 1.2.1
33 |
34 | ## API Additions
35 |
36 | * `from htmlgen import ElementBase` now works.
37 |
38 | ## Bug Fixes
39 |
40 | * Add missing `ElementBase` to type stubs.
41 |
42 | # News in version 1.2.0
43 |
44 | ## API Additions
45 |
46 | * Make `ElementBase` public.
47 | * Add `GenValue` and `GenValueGenerator` type aliases.
48 | * Fix annotation of `Heading`.
49 |
50 | # News in version 1.1.0
51 |
52 | ## Improvements
53 |
54 | * PEP 561 support.
55 | * Improve type hints.
56 |
57 | # News in version 1.0.0
58 |
59 | No changes.
60 |
61 | # News in version 0.99.3
62 |
63 | ## API-Incompatible Changes
64 |
65 | * Revert deriving from ABC classes.
66 |
67 | # News in version 0.99.2
68 |
69 | ## API Additions
70 |
71 | * `Element.data` does now derive from MutableMapping and implements all its
72 | methods.
73 |
74 | ## Improvements
75 |
76 | * Derive `ChildGenerator`, `HTMLChildGenerator`, and `Element` from
77 | Sized.
78 |
79 | ## Bug Fixes
80 |
81 | * Fix a few stubs.
82 | * Fix incorrect usage of `AnyStr`.
83 |
84 | # News in version 0.99.1
85 |
86 | ## API-Incompatible Changes
87 |
88 | * `html_attribute()` at al. are now directly implemented using the descriptor
89 | protocol, and not derived from property.
90 |
91 | ## Improvements
92 |
93 | * Add stub files.
94 |
95 | # News in version 0.99.0
96 |
97 | First Beta Release
98 |
99 | ## API Additions
100 |
101 | * Add generate_html_string().
102 | * Add css_class_attribute().
103 | * Add Checkbox (<input type="checkbox">), RadioButton (<input type="radio">),
104 | and Label (<label>).
105 |
106 | ## API-Incompatible Changes
107 |
108 | * Remove html_attribute() from htmlgen.element.
109 |
110 | ## Improvements
111 |
112 | * Render CSS classes alphabetically for easier unit testing.
113 |
114 | ## Bug Fixes
115 |
116 | * Fix PendingDeprecationWarnings.
117 |
118 | # News in version 0.9
119 |
120 | ## API Additions
121 |
122 | * Add IteratorGenerator.
123 | * Add HiddenInput (<input type="hidden">), FileInput (<input type="file">),
124 | SearchInput (<input type="search">), and TimeInput (<input type="time">).
125 | * Add LineBreak (<br>).
126 | * Table now has two overridable generator methods generate_header_rows() and
127 | generate_rows().
128 | * Add TextArea.placeholder property.
129 | * Add NumberInput.number property.
130 | * Add Form.target property and Form.set_blank_target().
131 | * Add data_attribute(), list_html_attribute() and time_html_attribute().
132 |
133 | ## API-Incompatible Changes
134 |
135 | * Improve Element.id handling and raise ValueError on invalid ids.
136 | * The default name of all input elements has been changed from None to the
137 | empty string to match Input.name.
138 | * NumberInput constructor: Replace value argument by number.
139 |
140 | # News in version 0.8
141 |
142 | ## API Additions
143 |
144 | * Add form elements TextArea (<textarea>), Select (<select>), OptionGroup
145 | (<optgroup>), and Option (<option>).
146 | * Add is_element() to check whether an object is an element generator of
147 | a certain type.
148 | * Forms now support multipart submissions using the Form.encryption_type and
149 | Form.multipart attributes.
150 |
151 | ## API-Incompatible Changes
152 |
153 | * Fix the default HTTP method to be "GET" for forms as per HTML spec. This
154 | avoids unexpected behaviour and the need for problematic workarounds
155 | with "POST" forms.
156 |
157 | # News in version 0.7
158 |
159 | ## API Additions
160 |
161 | * Add input elements Button (<button>), NumberInput (<input type="number">),
162 | PasswordInput (<input type="password">), and DateInput (<input
163 | type="date">).
164 |
165 | ## API-Incompatible Changes
166 |
167 | * Move attribute functions from htmlgen.elements to htmlgen.attribute.
168 | (But you should import them directly from htmlgen anyway.)
169 |
170 | ## Improvements
171 |
172 | * Improved error handling and reporting.
173 |
174 | ## Documentation
175 |
176 | * Add element list document elements.rst.
177 |
178 | ## Bug Fixes
179 |
180 | * Add float_html_attribute to htmlgen.
181 |
182 | # News in version 0.6.1
183 |
184 | ## Bug Fixes
185 |
186 | * Fixed error when passing elements to TableCell's and TableHeaderCell's
187 | constructor.
188 |
189 | # News in version 0.6
190 |
191 | ## API Additions
192 |
193 | * Add TableHeaderCell to htmlgen (missing from 0.5).
194 | * Division constructor now accepts initial content arguments.
195 |
196 | ## API-Incompatible Changes
197 |
198 | * All element constructors that took an initial content argument now take
199 | any number of content arguments, i.e. the following is now possible:
200 | >>> Paragraph("This is ", Emphasis("initial"), " content.")
201 |
202 | # News in version 0.5
203 |
204 | ## API Additions
205 |
206 | * Add table elements Table (<table>), TableHead (<thead>),
207 | TableBody (<tbody>), TableRow (<tr>), TableHeaderCell (<th>),
208 | TableCell (<td>), ColumnGroup (<colgroup>), and Column (<col>).
209 |
210 | # News in version 0.4
211 |
212 | ## API Additions
213 |
214 | * Add data property to element classes. This provides an API to
215 | easily set and query data-* attributes.
216 | * Add structural element Article (<article>).
217 | * Add inline elements Link (<a>) and Time (<time>).
218 | * Add description list elements DescriptionList (<dl>),
219 | DescriptionTerm (<dt>), and DescriptionDefinition (<dd>).
220 |
221 | # News in version 0.3
222 |
223 | ## API Additions
224 |
225 | * Add child-management methods and properties to ChildGenerator and
226 | HTMLChildGenerator:
227 | * remove()
228 | * remove_raw() (HTMLChildGenerator only)
229 | * children
230 | * Add new base class NonVoidElement, derive Element from this class.
231 | This base class can be used for elements with content that do not
232 | support the usual container interface.
233 | * Add document-level elements Document, HTMLRoot (<html>), Head (<head>),
234 | Body (<body>), Title (<title>), Meta (<meta>), Script (<script>),
235 | HeadLink (<link>), and Main (<main>).
236 | * Add structural elements Section (<section>), Navigation (<nav>),
237 | Aside (<aside>), Header (<header>), Footer (<footer>), and Heading
238 | (<h1> to <h6>).
239 | * Add list elements OrderedList (<ol>), UnorderedList (<ul>), and
240 | ListItem (<li>).
241 | * Add has_css_class() method to elements.
242 |
243 | ## Improvements
244 |
245 | * Element attributes are now always rendered in alphabetical order. This
246 | makes testing elements easier.
247 |
248 | # News in version 0.2
249 |
250 | ## API Additions
251 |
252 | * Add elements Paragraph (<p>), Preformatted (<pre>), Image (<img>),
253 | Highlight (<b>), Strong (<strong>), Alternate (<i>), Emphasis (<em>),
254 | and Small (<small>).
255 | * Add float_html_attribute().
256 | * Add remove_css_classes() method to elements.
257 |
258 | ## API-Incompatible Changes
259 |
260 | * Rename ShortElement to VoidElement to conform to the HTML 5 standard.
261 |
262 | # News in version 0.1.1
263 |
264 | ## API Additions
265 |
266 | * Add ShortElement to htmlgen.
267 |
268 | ## Bug Fixes
269 |
270 | * Elements are now always truthy.
271 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Python HTML 5 Generator
2 |
3 | [](https://pypi.python.org/pypi/htmlgen/)
4 | [](https://pypi.python.org/pypi/htmlgen/)
5 | [](https://github.com/srittau/python-htmlgen/releases/)
6 | [](https://pypi.python.org/pypi/htmlgen/)
7 | [](https://travis-ci.org/srittau/python-htmlgen)
8 |
9 | Library to generate HTML from classes.
10 |
11 | Basic usage:
12 |
13 | >>> from htmlgen import Division, Span
14 | >>> Division("This is ", Span("important!"), "!")
15 |
16 | A more verbose example:
17 |
18 | >>> span = Span("important")
19 | >>> span.add_css_classes("important")
20 | >>> div = Division()
21 | >>> div.id = "my-block"
22 | >>> div.append("This is ")
23 | >>> div.append(span)
24 | >>> div.append("!")
25 |
26 | A tree constructed like this can be converted to a string:
27 |
28 | >>> str(div)
29 | '
This is important!
'
30 | >>> "
This is {}!
".format(span)
31 | '
This is important!
'
32 |
33 | Alternatively, all elements can be used as iterators, for example to return
34 | them from a WSGI callback:
35 |
36 | >>> def application(env, start_response):
37 | ... start_response("200 OK", [("Content-Type", "text/html")])
38 | ... return div
39 |
40 | There are two different ways to render children of HTML elements. The tree
41 | construction approach shown above is mainly suitable for elements with few
42 | children. The disadvantage of this approach is that the whole tree must be
43 | constructed in memory. An alternative way, best suited for custom sub-classes
44 | of elements, is to override the generate_children method of the Element class:
45 |
46 | >>> class MyBlock(Division):
47 | ... def __init__(self):
48 | ... super(MyBlock, self).__init__()
49 | ... self.id = "my-block"
50 | ... def generate_children(self):
51 | ... yield "This is "
52 | ... span = Span("important")
53 | ... span.add_css_classes("important")
54 | ... yield span
55 | ... yield "!"
56 | >>> str(MyBlock())
57 | '
This is important!
'
58 |
--------------------------------------------------------------------------------
/elements.rst:
--------------------------------------------------------------------------------
1 | htmlgen currently supports the following HTML elements:
2 |
3 | * - Link
4 | * - Article
5 | *