Skip to content

Commit d815b10

Browse files
Create Options class
1 parent 97a0b3c commit d815b10

File tree

1 file changed

+72
-0
lines changed

1 file changed

+72
-0
lines changed

pyhtml/__render_options.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
"""
2+
# PyHTML / Render Options
3+
4+
Definition for the `Options` object, used to control rendering.
5+
"""
6+
7+
from dataclasses import asdict, dataclass
8+
from typing import Optional
9+
10+
# While it could be cleaner (and far less-repetitive) to use a TypedDict and
11+
# declare the partial options class as per
12+
# https://discuss.python.org/t/introduce-partial-for-typeddict/45176/4
13+
# I elected not to do this, as by using a dataclass, the type is much more
14+
# explicit, meaning that users won't encounter very confusing type-checker
15+
# errors if they inadvertently pass a non-Options-shaped `dict` to a tag
16+
# constructor.
17+
# By using a `dataclass`, it is also much easier to perform `isinstance`
18+
# checking on the object, which simplifies the implementation significantly.
19+
# The only down-side is the duplicated definitions and copy-pasted
20+
# documentation.
21+
22+
23+
@dataclass(kw_only=True, frozen=True)
24+
class FullOptions:
25+
indent: str
26+
"""String to add to indentation for non-inline child elements"""
27+
spacing: str
28+
"""String to use for spacing between child elements"""
29+
30+
def union(self, other: "Options | FullOptions") -> "FullOptions":
31+
"""
32+
Union this set of options with the other options, returning a new
33+
`Options` object as the result.
34+
35+
Any non-`None` options in `other` will overwrite the original values.
36+
"""
37+
values = asdict(self)
38+
for field in values:
39+
if (other_value := getattr(other, field)) is not None:
40+
values[field] = other_value
41+
42+
return FullOptions(**values)
43+
44+
45+
@dataclass(kw_only=True, frozen=True)
46+
class Options:
47+
"""
48+
PyHTML rendering options.
49+
50+
* `indent` (`str`): string to add to indentation for non-inline child
51+
elements. For example, to indent using a tab, you could use `'\\t'`.
52+
Defaults to 2 spaces `' '`.
53+
* `spacing` (`str`): string to use for spacing between child elements. When
54+
this is set to `'\\n'`, each child element will be placed on its own
55+
line, and indentation will be applied. Otherwise, each child element will
56+
be separated using the given value.
57+
"""
58+
59+
indent: Optional[str] = None
60+
"""String to add to indentation for non-inline child elements"""
61+
spacing: Optional[str] = None
62+
"""String to use for spacing between child elements"""
63+
64+
@staticmethod
65+
def default() -> FullOptions:
66+
"""
67+
Returns PyHTML's default rendering options.
68+
"""
69+
return FullOptions(
70+
indent=" ",
71+
spacing="\n",
72+
)

0 commit comments

Comments
 (0)