htmy 0.3.3__py3-none-any.whl → 0.3.5__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.

Potentially problematic release.


This version of htmy might be problematic. Click here for more details.

htmy/core.py CHANGED
@@ -7,6 +7,7 @@ from collections.abc import Callable, Container
7
7
  from pathlib import Path
8
8
  from typing import TYPE_CHECKING, Any, ClassVar, Generic, TypedDict, cast, overload
9
9
  from xml.sax.saxutils import escape as xml_escape
10
+ from xml.sax.saxutils import quoteattr as xml_quoteattr
10
11
 
11
12
  from .io import open_file
12
13
  from .typing import (
@@ -429,7 +430,7 @@ class Formatter(ContextAware):
429
430
  See `SkipProperty` for more information.
430
431
  """
431
432
  try:
432
- return f'{self.format_name(name)}="{self.format_value(value)}"'
433
+ return f"{self.format_name(name)}={xml_quoteattr(self.format_value(value))}"
433
434
  except SkipProperty:
434
435
  return ""
435
436
 
htmy/renderer.py CHANGED
@@ -5,7 +5,7 @@ from collections import ChainMap
5
5
  from collections.abc import Awaitable, Callable, Iterable
6
6
 
7
7
  from .core import ErrorBoundary, xml_format_string
8
- from .typing import Component, ComponentType, Context, ContextProvider, HTMYComponentType
8
+ from .typing import Component, ComponentType, Context
9
9
 
10
10
 
11
11
  class HTMY:
@@ -82,15 +82,19 @@ class HTMY:
82
82
  Returns:
83
83
  The rendered string.
84
84
  """
85
- child_context = context
86
- if isinstance(component, ContextProvider):
87
- extra_context = component.htmy_context()
88
- if isinstance(extra_context, Awaitable):
89
- extra_context = await extra_context
85
+ if isinstance(component, str):
86
+ return self._string_formatter(component)
87
+ else:
88
+ child_context: Context = context
89
+ if hasattr(component, "htmy_context"): # isinstance() is too expensive.
90
+ extra_context: Context | Awaitable[Context] = component.htmy_context()
91
+ if isinstance(extra_context, Awaitable):
92
+ extra_context = await extra_context
90
93
 
91
- child_context = ChainMap(extra_context, context)
94
+ if len(extra_context):
95
+ # Context must not be mutated, so we can ignore that ChainMap expext mutable mappings.
96
+ child_context = ChainMap(extra_context, context) # type: ignore[arg-type]
92
97
 
93
- if isinstance(component, HTMYComponentType):
94
98
  try:
95
99
  children = component.htmy(child_context)
96
100
  if isinstance(children, Awaitable):
@@ -102,7 +106,3 @@ class HTMY:
102
106
  return await self._render_one(component.fallback_component(e), context)
103
107
 
104
108
  raise e
105
- elif isinstance(component, str):
106
- return self._string_formatter(component)
107
- else:
108
- raise TypeError("Unknown component type.")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: htmy
3
- Version: 0.3.3
3
+ Version: 0.3.5
4
4
  Summary: Async, pure-Python rendering engine.
5
5
  License: MIT
6
6
  Author: Peter Volf
@@ -295,6 +295,12 @@ If a component executes a potentially "long-running" synchronous call, it is str
295
295
 
296
296
  In all other cases, it's best to use sync components.
297
297
 
298
+ ## Framework integrations
299
+
300
+ FastAPI:
301
+
302
+ - [FastHX](https://github.com/volfpeter/fasthx)
303
+
298
304
  ## Why
299
305
 
300
306
  At one end of the spectrum, there are the complete application frameworks that combine the server (Python) and client (JavaScript) applications with the entire state management and synchronization into a single Python (an in some cases an additional JavaScript) package. Some of the most popular examples are: [Reflex](https://github.com/reflex-dev/reflex), [NiceGUI](https://github.com/zauberzeug/nicegui/), [ReactPy](https://github.com/reactive-python/reactpy), and [FastUI](https://github.com/pydantic/FastUI).
@@ -1,5 +1,5 @@
1
1
  htmy/__init__.py,sha256=My_Dmh9JNQpQekTO6CEbdbV7Ux7MD9Pz-L2M3KMZjGQ,1835
2
- htmy/core.py,sha256=6_mFrJ1GdMQv3lrIgUWa0-41NhSKGtgwrXrxYr7BHQY,18666
2
+ htmy/core.py,sha256=JZNryJU1VCAVBf1wzkaa9bD3LiepT-Eu28XydfbWpOw,18735
3
3
  htmy/etree.py,sha256=zZkKY82t5fX85unS9oHuG6KEBsJY_iz6E7SJto8lSVQ,3097
4
4
  htmy/html.py,sha256=pxmE-KU5OgwNp6MyxOfdS0Ohpzu2RNYCeGGFlHLDGUM,20940
5
5
  htmy/i18n.py,sha256=brNazQjObBFfbnViZCpcnxa0qgxQbJfX7xJAH-MqTW8,5124
@@ -8,10 +8,10 @@ htmy/md/__init__.py,sha256=lxBJnYplkDuxYuiese6My9KYp1DeGdzo70iUdYTvMnE,334
8
8
  htmy/md/core.py,sha256=-EKucDFKMUtGgs9k_q9134oXY2GXtdKX1KOJXG4YmKc,3342
9
9
  htmy/md/typing.py,sha256=LF-AEvo7FCW2KumyR5l55rsXizV2E4AHVLKFf6lApgM,762
10
10
  htmy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- htmy/renderer.py,sha256=vIY-_IFonctEHgl6kOL3586Peve2Lz7Ly8jpf9WOlqQ,3706
11
+ htmy/renderer.py,sha256=vCYqq83RaEtlXKDGWB6LgKjoE1TSfMfB5TW1lJWHE5c,3829
12
12
  htmy/typing.py,sha256=iUZQjMU-DHMV1Mv-ugW26eSPlrFO-KVhWfkLod7dig4,2937
13
13
  htmy/utils.py,sha256=7_CyA39l2m6jzDqparPKkKgRB2wiGuBZXbiPgiZOXKA,1093
14
- htmy-0.3.3.dist-info/LICENSE,sha256=rFtoGU_3c_rlacXgOZapTHfMErN-JFPT5Bq_col4bqI,1067
15
- htmy-0.3.3.dist-info/METADATA,sha256=MPbERjyHqKdhtcWZyM2rUeHHwTL3uzfY-O5zUB1IjBY,16261
16
- htmy-0.3.3.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
17
- htmy-0.3.3.dist-info/RECORD,,
14
+ htmy-0.3.5.dist-info/LICENSE,sha256=rFtoGU_3c_rlacXgOZapTHfMErN-JFPT5Bq_col4bqI,1067
15
+ htmy-0.3.5.dist-info/METADATA,sha256=emcRbV2rYZ_RP4LqKGjzv3WBdadUpyQREdujGyycXt0,16347
16
+ htmy-0.3.5.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
17
+ htmy-0.3.5.dist-info/RECORD,,
File without changes
File without changes