hypie 0.1.1.dev2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,135 @@
1
+ from dataclasses import dataclass, is_dataclass
2
+ from typing import dataclass_transform
3
+ from textwrap import indent
4
+
5
+ import htpy
6
+ from markupsafe import Markup
7
+
8
+ from hypie.hs_ast.helpers import kebab_case_name, htpy_to_tree, tree_to_htpy
9
+
10
+
11
+ def transform_root(el: dict, component_name: str):
12
+ if not isinstance(el, dict):
13
+ return el
14
+ k, v = next(iter(el.items()))
15
+ if k == "_fragment":
16
+ return {
17
+ k: {
18
+ "children": [transform_root(c, component_name) for c in v["children"]],
19
+ "attrs": v["attrs"],
20
+ }
21
+ }
22
+ if "data-hypie-component" in v["attrs"]:
23
+ return el
24
+ return {
25
+ k: {
26
+ "children": v["children"],
27
+ "attrs": v["attrs"] + f' data-hypie-component="{component_name}"',
28
+ }
29
+ }
30
+
31
+
32
+ SPACES = " " * 2
33
+
34
+
35
+ def parse_css_dict(k, v: dict):
36
+ parts = [f"{k} {{"]
37
+ for sub_k, sub_v in v.items():
38
+ if sub_k.strip() == "@apply":
39
+ if isinstance(sub_v, list):
40
+ parts.append(
41
+ indent(
42
+ f"@apply {' '.join(sub_v)};",
43
+ prefix=SPACES,
44
+ predicate=lambda _: True,
45
+ )
46
+ )
47
+ else:
48
+ parts.append(
49
+ indent(f"@apply {sub_v};", prefix=SPACES, predicate=lambda _: True)
50
+ )
51
+ elif isinstance(sub_v, str):
52
+ parts.append(
53
+ indent(f"{sub_k}: {sub_v};", prefix=SPACES, predicate=lambda _: True)
54
+ )
55
+ elif isinstance(sub_v, dict):
56
+ parts.append(
57
+ indent(
58
+ parse_css_dict(sub_k, sub_v),
59
+ prefix=SPACES,
60
+ predicate=lambda _: True,
61
+ )
62
+ )
63
+ parts.append("}")
64
+ return "\n".join(parts)
65
+
66
+
67
+ def generate_scoped_css(component_name, css_dict):
68
+ css_parts = [f"@scope ({component_name}) {{"]
69
+ for k, v in css_dict.items():
70
+ css_parts.append(
71
+ indent(parse_css_dict(k, v), prefix=SPACES, predicate=lambda _: True)
72
+ )
73
+ css_parts.append("}")
74
+ return "\n\n".join(css_parts)
75
+
76
+
77
+ class ComponentMeta(type):
78
+ def __getitem__(cls, children):
79
+ instance = Component.__new__(cls)
80
+ instance.children = children
81
+ return instance
82
+
83
+
84
+ @dataclass_transform()
85
+ class Component(metaclass=ComponentMeta):
86
+ children = None
87
+
88
+ def __new__(cls, *args, **kwargs):
89
+ dataclass_cls = cls
90
+ if not is_dataclass(cls):
91
+ dataclass_cls = dataclass(cls)
92
+ instance = object.__new__(dataclass_cls)
93
+ return instance
94
+
95
+ def __init_subclass__(cls, as_fragment=False, hidden=False, contents=False):
96
+ cls._hs_dsl_component = True
97
+ cls.as_fragment = as_fragment
98
+ cls.hidden = hidden
99
+ cls.contents = contents
100
+ cls.component_name = kebab_case_name(cls.__name__)
101
+ cls.tag = f"div[data-hypie-component='{cls.component_name}']"
102
+
103
+ def __html__(self):
104
+ el = self.template()
105
+ new_el = tree_to_htpy(transform_root(htpy_to_tree(el), self.component_name))
106
+ # print(new_el)
107
+ return new_el
108
+
109
+ def __getitem__(self, children):
110
+ if hasattr(self, "children") and self.children:
111
+ raise Exception("Can not reassign children twice")
112
+ self.children = children
113
+ return self
114
+
115
+ def template(self):
116
+ return htpy.fragment[self.children]
117
+
118
+ @staticmethod
119
+ def style() -> dict:
120
+ pass
121
+
122
+ @classmethod
123
+ def generate_style(cls, with_style_tags=True):
124
+ output_style = cls.style()
125
+ if output_style:
126
+ css = generate_scoped_css(cls.tag, cls.style())
127
+ if with_style_tags:
128
+ return htpy.style[Markup(css)]
129
+ return Markup(css)
130
+
131
+ def encode(self, encoding: str = "utf-8", errors: str = "strict") -> bytes:
132
+ return str(self).encode(encoding, errors)
133
+
134
+ def __str__(self):
135
+ return str(self.__html__())
@@ -0,0 +1,35 @@
1
+ import dataclasses
2
+
3
+ from hypie.literals import var
4
+ from hypie.commands import set_
5
+ from hypie import hs
6
+
7
+
8
+ class HyperScript:
9
+ def __new__(cls, *args, **kwargs):
10
+ raise Exception("HyperScript class is not meant to be instantiated.")
11
+
12
+ def __init_subclass__(cls):
13
+ if not dataclasses.is_dataclass(cls):
14
+ dataclasses.dataclass(cls, init=False)
15
+ cls._hs_dsl_hyperscript = True
16
+ cls._vars_script = hs()
17
+ for f in dataclasses.fields(cls):
18
+ setattr(cls, f.name, var(f"${cls.__name__}__{f.name}"))
19
+ cls._vars_script.add_features(
20
+ set_(
21
+ var(f"${cls.__name__}__{f.name}"),
22
+ to=f.default if f.default != dataclasses.MISSING else None,
23
+ )
24
+ )
25
+
26
+ @classmethod
27
+ def script(cls):
28
+ return hs()
29
+
30
+ @classmethod
31
+ def register_hyperscript(cls):
32
+ _hs = hs()
33
+ _hs.add_features(cls._vars_script)
34
+ _hs.add_features(cls.script())
35
+ return _hs
@@ -0,0 +1,50 @@
1
+ import dataclasses
2
+ import htpy
3
+
4
+ # from hypie.literals import var
5
+ from hypie.hs_ast.expressions import TemplatedVariableLiteral
6
+ from hypie.hs_ast.helpers import (
7
+ kebab_case_name,
8
+ htpy_to_tree,
9
+ tranform_tree,
10
+ tree_to_htpy,
11
+ )
12
+ from hypie.hs_ast.expressions import VarTemplateString
13
+ from typing import dataclass_transform
14
+
15
+
16
+ @dataclass_transform()
17
+ class Template:
18
+ field_names = None
19
+
20
+ def __init_subclass__(cls):
21
+ dataclasses.dataclass(cls)
22
+ cls._hs_dsl_template = True
23
+ for f in dataclasses.fields(cls):
24
+ setattr(cls, f.name, TemplatedVariableLiteral(f.name))
25
+ setattr(cls, "field_names", [f.name for f in dataclasses.fields(cls)])
26
+ cls.id = kebab_case_name(cls.__name__)
27
+
28
+ # @classmethod
29
+ def template(cls):
30
+ pass
31
+
32
+ @classmethod
33
+ def register_template(cls):
34
+ template = cls(
35
+ **{f: TemplatedVariableLiteral(f) for f in cls.field_names}
36
+ ).template()
37
+ tree = htpy_to_tree(template)
38
+ transformed_tree = tranform_tree(tree, rules={"text": cls.handle_text_nodes})
39
+ transformed_htpy = tree_to_htpy(transformed_tree)
40
+ return htpy.script(type="text/hyperscript-template", id=cls.id)[
41
+ transformed_htpy
42
+ ]
43
+
44
+ @staticmethod
45
+ def handle_text_nodes(text):
46
+ # print(text)
47
+ exp_template = VarTemplateString(text)
48
+ if not exp_template.interpolations:
49
+ return text
50
+ return exp_template.transform(interp_func=lambda x: "${" + x + "}")
hypie/features.py ADDED
@@ -0,0 +1,46 @@
1
+ from hypie.hs_ast.features import *
2
+ from hypie.commands import set_
3
+ from hypie.events import Event
4
+
5
+
6
+ # so you can call it as init() or init[] both work
7
+ Init = InitF()
8
+
9
+
10
+ def On(*event_specs: EventSpecLiteral | str, queue: ON_QUEUE = None):
11
+ _event_specs = []
12
+ for event in event_specs:
13
+ if isinstance(event, type) and issubclass(event, Event):
14
+ _event_specs.append(
15
+ EventSpecLiteral(
16
+ event_name=event.event_name,
17
+ args=event.event_args,
18
+ filter=event.event_spec and event.event_spec.filter,
19
+ count=event.event_spec and event.event_spec.count,
20
+ from_=event.event_spec and event.event_spec.from_,
21
+ in_=event.event_spec and event.event_spec.in_,
22
+ debounce=event.event_spec and event.event_spec.debounce,
23
+ throttle=event.event_spec and event.event_spec.throttle,
24
+ )
25
+ )
26
+ else:
27
+ _event_specs.append(event)
28
+ return OnF(event_specs=_event_specs, queue=queue)
29
+
30
+
31
+ Live = LiveF()
32
+
33
+
34
+ def Bind(exprA: Expr, exprB: Expr, /):
35
+ return BindF(exprA=exprA, exprB=exprB)
36
+
37
+
38
+ Set = set_
39
+
40
+
41
+ def WhenChange(*exprs):
42
+ return WhenF(exprs=exprs)
43
+
44
+
45
+ def Js(javascript: str, /):
46
+ return JsF(javascript)