precompile.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. """Dynamically compile classes for all HTML elements and output them to the
  2. elements directory.
  3. This script generates the element classes in the pynecone.el.elements module.
  4. Run as follows:
  5. python -m pynecone.el.precompile
  6. Make sure to delete the __init__.py file in the elements directory before
  7. running this script.
  8. """
  9. import os
  10. from pynecone.compiler.templates import join
  11. from .constants import ELEMENT_TO_PROPS, ELEMENTS
  12. FILE_DIR = os.path.dirname(os.path.realpath(__file__))
  13. ELEMENTS_DIR = os.path.join(FILE_DIR, "elements")
  14. INIT_PY_PATH = os.path.join(ELEMENTS_DIR, "__init__.py")
  15. def element_path(element: str) -> str:
  16. """Get the name of the Python file for the given element.
  17. Args:
  18. element: The name of the element. For example, `a` or `div`.
  19. Returns:
  20. The name of the Python file for the given element.
  21. """
  22. return os.path.join(ELEMENTS_DIR, f"{element}.py")
  23. PROP = " {prop}: PCVar[Union[str, int, bool]]".format
  24. def compile_pyclass_props(element: str) -> str:
  25. """Compile props for an element.
  26. Args:
  27. element: The name of the element. For example, `a` or `div`.
  28. Returns:
  29. A string containing compiled props for the element.
  30. """
  31. return join(PROP(prop=prop) for prop in ELEMENT_TO_PROPS[element])
  32. PYCLASS = join(
  33. [
  34. "",
  35. "class {name}(Element): # noqa: E742",
  36. ' """Display the {element} element."""',
  37. "",
  38. ' tag = "{element}"',
  39. "",
  40. "{props}",
  41. "",
  42. "",
  43. "{call_name} = {name}.create",
  44. "",
  45. ]
  46. ).format
  47. def compile_pyclass(element: str) -> str:
  48. """Compile a Python class for an element.
  49. Args:
  50. element: The name of the element. For example, `a` or `div`.
  51. Returns:
  52. A string containing a Python class for the element.
  53. """
  54. name = element.capitalize()
  55. props = compile_pyclass_props(element)
  56. # Handle the `del` element, which is a Python keyword. Note that the class
  57. # name is still `Del`.
  58. call_name = "del_" if element == "del" else element
  59. return PYCLASS(
  60. name=name,
  61. element=element,
  62. props=props,
  63. call_name=call_name,
  64. )
  65. INIT_PY = [
  66. '"""Element classes. This is an auto-generated file. Do not edit. See ../generate.py."""',
  67. "from typing import Union",
  68. "",
  69. "from pynecone.el.element import Element",
  70. "from pynecone.var import Var as PCVar",
  71. "",
  72. ]
  73. for element in sorted(ELEMENTS):
  74. INIT_PY.append(compile_pyclass(element))
  75. os.makedirs(ELEMENTS_DIR, exist_ok=True)
  76. with open(INIT_PY_PATH, "w+") as f:
  77. f.write(join(INIT_PY))