1
0

imports.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. """Import operations."""
  2. from __future__ import annotations
  3. from collections import defaultdict
  4. from typing import Dict, List, Optional, Tuple, Union
  5. from reflex.base import Base
  6. def merge_imports(
  7. *imports: ImportDict | ParsedImportDict | ImmutableParsedImportDict,
  8. ) -> ParsedImportDict:
  9. """Merge multiple import dicts together.
  10. Args:
  11. *imports: The list of import dicts to merge.
  12. Returns:
  13. The merged import dicts.
  14. """
  15. all_imports = defaultdict(list)
  16. for import_dict in imports:
  17. for lib, fields in (
  18. import_dict if isinstance(import_dict, tuple) else import_dict.items()
  19. ):
  20. all_imports[lib].extend(fields)
  21. return all_imports
  22. def parse_imports(imports: ImportDict | ParsedImportDict) -> ParsedImportDict:
  23. """Parse the import dict into a standard format.
  24. Args:
  25. imports: The import dict to parse.
  26. Returns:
  27. The parsed import dict.
  28. """
  29. def _make_list(value: ImportTypes) -> list[str | ImportVar] | list[ImportVar]:
  30. if isinstance(value, (str, ImportVar)):
  31. return [value]
  32. return value
  33. return {
  34. package: [
  35. ImportVar(tag=tag) if isinstance(tag, str) else tag
  36. for tag in _make_list(maybe_tags)
  37. ]
  38. for package, maybe_tags in imports.items()
  39. }
  40. def collapse_imports(
  41. imports: ParsedImportDict | ImmutableParsedImportDict,
  42. ) -> ParsedImportDict:
  43. """Remove all duplicate ImportVar within an ImportDict.
  44. Args:
  45. imports: The import dict to collapse.
  46. Returns:
  47. The collapsed import dict.
  48. """
  49. return {
  50. lib: (
  51. list(set(import_vars))
  52. if isinstance(import_vars, list)
  53. else list(import_vars)
  54. )
  55. for lib, import_vars in (
  56. imports if isinstance(imports, tuple) else imports.items()
  57. )
  58. }
  59. class ImportVar(Base):
  60. """An import var."""
  61. # The name of the import tag.
  62. tag: Optional[str]
  63. # whether the import is default or named.
  64. is_default: Optional[bool] = False
  65. # The tag alias.
  66. alias: Optional[str] = None
  67. # Whether this import need to install the associated lib
  68. install: Optional[bool] = True
  69. # whether this import should be rendered or not
  70. render: Optional[bool] = True
  71. # whether this import package should be added to transpilePackages in next.config.js
  72. # https://nextjs.org/docs/app/api-reference/next-config-js/transpilePackages
  73. transpile: Optional[bool] = False
  74. @property
  75. def name(self) -> str:
  76. """The name of the import.
  77. Returns:
  78. The name(tag name with alias) of tag.
  79. """
  80. if self.alias:
  81. return (
  82. self.alias if self.is_default else " as ".join([self.tag, self.alias]) # type: ignore
  83. )
  84. else:
  85. return self.tag or ""
  86. def __lt__(self, other: ImportVar) -> bool:
  87. """Compare two ImportVar objects.
  88. Args:
  89. other: The other ImportVar object to compare.
  90. Returns:
  91. Whether this ImportVar object is less than the other.
  92. """
  93. return (
  94. self.tag,
  95. self.is_default,
  96. self.alias,
  97. self.install,
  98. self.render,
  99. self.transpile,
  100. ) < (
  101. other.tag,
  102. other.is_default,
  103. other.alias,
  104. other.install,
  105. other.render,
  106. other.transpile,
  107. )
  108. def __eq__(self, other: ImportVar) -> bool:
  109. """Check if two ImportVar objects are equal.
  110. Args:
  111. other: The other ImportVar object to compare.
  112. Returns:
  113. Whether the two ImportVar objects are equal.
  114. """
  115. return (
  116. self.tag,
  117. self.is_default,
  118. self.alias,
  119. self.install,
  120. self.render,
  121. self.transpile,
  122. ) == (
  123. other.tag,
  124. other.is_default,
  125. other.alias,
  126. other.install,
  127. other.render,
  128. other.transpile,
  129. )
  130. def __hash__(self) -> int:
  131. """Hash the ImportVar object.
  132. Returns:
  133. The hash of the ImportVar object.
  134. """
  135. return hash(
  136. (
  137. self.tag,
  138. self.is_default,
  139. self.alias,
  140. self.install,
  141. self.render,
  142. self.transpile,
  143. )
  144. )
  145. ImportTypes = Union[str, ImportVar, List[Union[str, ImportVar]], List[ImportVar]]
  146. ImportDict = Dict[str, ImportTypes]
  147. ParsedImportDict = Dict[str, List[ImportVar]]
  148. ImmutableParsedImportDict = Tuple[Tuple[str, Tuple[ImportVar, ...]], ...]