1
0

utils.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. """Common utility functions used in the compiler."""
  2. from __future__ import annotations
  3. import json
  4. from typing import TYPE_CHECKING, Dict, Set, Type
  5. from pynecone import constants, utils
  6. from pynecone.compiler import templates
  7. from pynecone.components.base import (
  8. Body,
  9. Description,
  10. DocumentHead,
  11. Head,
  12. Html,
  13. Image,
  14. Link,
  15. Main,
  16. Script,
  17. Title,
  18. )
  19. from pynecone.components.component import ImportDict
  20. from pynecone.state import State
  21. from pynecone.style import Style
  22. if TYPE_CHECKING:
  23. from pynecone.components.component import Component
  24. # To re-export this function.
  25. merge_imports = utils.merge_imports
  26. def compile_import_statement(lib: str, fields: Set[str]) -> str:
  27. """Compile an import statement.
  28. Args:
  29. lib: The library to import from.
  30. fields: The set of fields to import from the library.
  31. Returns:
  32. The compiled import statement.
  33. """
  34. # Check for default imports.
  35. defaults = {
  36. field
  37. for field in fields
  38. if field.lower() == lib.lower().replace("-", "").replace("/", "")
  39. }
  40. assert len(defaults) < 2
  41. # Get the default import, and the specific imports.
  42. default = next(iter(defaults), "")
  43. rest = fields - defaults
  44. return templates.format_import(lib=lib, default=default, rest=rest)
  45. def compile_imports(imports: ImportDict) -> str:
  46. """Compile an import dict.
  47. Args:
  48. imports: The import dict to compile.
  49. Returns:
  50. The compiled import dict.
  51. """
  52. return templates.join(
  53. [compile_import_statement(lib, fields) for lib, fields in imports.items()]
  54. )
  55. def compile_constant_declaration(name: str, value: str) -> str:
  56. """Compile a constant declaration.
  57. Args:
  58. name: The name of the constant.
  59. value: The value of the constant.
  60. Returns:
  61. The compiled constant declaration.
  62. """
  63. return templates.CONST(name=name, value=json.dumps(value))
  64. def compile_constants() -> str:
  65. """Compile all the necessary constants.
  66. Returns:
  67. A string of all the compiled constants.
  68. """
  69. endpoint = constants.Endpoint.EVENT
  70. return templates.join(
  71. [compile_constant_declaration(name=endpoint.name, value=endpoint.get_url())]
  72. )
  73. import plotly.graph_objects as go
  74. def compile_state(state: Type[State]) -> str:
  75. """Compile the state of the app.
  76. Args:
  77. state: The app state object.
  78. Returns:
  79. A string of the compiled state.
  80. """
  81. initial_state = state().dict()
  82. initial_state.update(
  83. {
  84. "events": [{"name": utils.get_hydrate_event(state)}],
  85. }
  86. )
  87. initial_state = utils.format_state(initial_state)
  88. synced_state = templates.format_state(
  89. state=state.get_name(), initial_state=json.dumps(initial_state)
  90. )
  91. initial_result = {
  92. constants.STATE: None,
  93. constants.EVENTS: [],
  94. constants.PROCESSING: False,
  95. }
  96. result = templates.format_state(
  97. state="result",
  98. initial_state=json.dumps(initial_result),
  99. )
  100. router = templates.ROUTER
  101. return templates.join([synced_state, result, router])
  102. def compile_events(state: Type[State]) -> str:
  103. """Compile all the events for a given component.
  104. Args:
  105. state: The state class for the component.
  106. Returns:
  107. A string of the compiled events for the component.
  108. """
  109. state_name = state.get_name()
  110. state_setter = templates.format_state_setter(state_name)
  111. return templates.EVENT_FN(state=state_name, set_state=state_setter)
  112. def compile_effects(state: Type[State]) -> str:
  113. """Compile all the effects for a given component.
  114. Args:
  115. state: The state class for the component.
  116. Returns:
  117. A string of the compiled effects for the component.
  118. """
  119. state_name = state.get_name()
  120. set_state = templates.format_state_setter(state_name)
  121. return templates.USE_EFFECT(state=state_name, set_state=set_state)
  122. def compile_render(component: Component) -> str:
  123. """Compile the component's render method.
  124. Args:
  125. component: The component to compile the render method for.
  126. Returns:
  127. A string of the compiled render method.
  128. """
  129. return component.render()
  130. def create_document_root(stylesheets) -> Component:
  131. """Create the document root.
  132. Args:
  133. stylesheets: The stylesheets to include in the document root.
  134. Returns:
  135. The document root.
  136. """
  137. sheets = [Link.create(rel="stylesheet", href=href) for href in stylesheets]
  138. return Html.create(
  139. DocumentHead.create(*sheets),
  140. Body.create(
  141. Main.create(),
  142. Script.create(),
  143. ),
  144. )
  145. def create_theme(style: Style) -> Dict:
  146. """Create the base style for the app.
  147. Args:
  148. style: The style dict for the app.
  149. Returns:
  150. The base style for the app.
  151. """
  152. return {
  153. "styles": {
  154. "global": Style({k: v for k, v in style.items() if not isinstance(k, type)})
  155. },
  156. }
  157. def add_meta(page: Component, title, image, description) -> Component:
  158. """Add metadata to a page.
  159. Args:
  160. page: The component for the page.
  161. title: The title of the page.
  162. image: The image for the page.
  163. description: The description of the page.
  164. Returns:
  165. The component with the metadata added.
  166. """
  167. page.children.append(
  168. Head.create(
  169. Title.create(title),
  170. Description.create(content=description),
  171. Image.create(content=image),
  172. )
  173. )
  174. return page