diff --git a/packages/reflex-base/news/+pyi_hashes_post_ruff.bugfix.md b/packages/reflex-base/news/+pyi_hashes_post_ruff.bugfix.md new file mode 100644 index 00000000000..804c0453e38 --- /dev/null +++ b/packages/reflex-base/news/+pyi_hashes_post_ruff.bugfix.md @@ -0,0 +1 @@ +`pyi_hashes.json` entries are now computed from the final `.pyi` content after `ruff format` / `ruff check --fix` post-processing, instead of the intermediate generator output. A pyi_generator change that only affects pre-format output no longer flags hash changes for stubs whose final content is identical. diff --git a/packages/reflex-base/src/reflex_base/utils/pyi_generator.py b/packages/reflex-base/src/reflex_base/utils/pyi_generator.py index 3e35b583151..507515a8af3 100644 --- a/packages/reflex-base/src/reflex_base/utils/pyi_generator.py +++ b/packages/reflex-base/src/reflex_base/utils/pyi_generator.py @@ -1413,7 +1413,13 @@ def _path_to_module_name(path: Path) -> str: return _relative_to_pwd(path).with_suffix("").as_posix().replace("/", ".") -def _write_pyi_file(module_path: Path, source: str) -> str: +def _write_pyi_file(module_path: Path, source: str) -> None: + """Write the .pyi stub next to its source module. + + Args: + module_path: The path of the source .py module. + source: The generated stub source, without the header. + """ relpath = str(_relative_to_pwd(module_path)).replace("\\", "/") pyi_content = ( "\n".join([ @@ -1429,7 +1435,6 @@ def _write_pyi_file(module_path: Path, source: str) -> str: pyi_path = module_path.with_suffix(".pyi") pyi_path.write_text(pyi_content) logger.info(f"Wrote {relpath}") - return md5(pyi_content.encode()).hexdigest() # Mapping from component subpackage name to its target Python package. @@ -1561,14 +1566,14 @@ def _get_init_lazy_imports(mod: ModuleType, new_tree: ast.AST): return text -def _scan_file(module_path: Path) -> tuple[str, str] | None: +def _scan_file(module_path: Path) -> str | None: """Process a single Python file and generate its .pyi stub. Args: module_path: Path to the Python source file. Returns: - Tuple of (pyi_path, content_hash) or None if no stub needed. + The path of the written .pyi file, or None if no stub is needed. """ module_import = _path_to_module_name(module_path) module = importlib.import_module(module_import) @@ -1598,11 +1603,11 @@ def _scan_file(module_path: Path) -> tuple[str, str] | None: init_imports = _get_init_lazy_imports(module, new_tree) if not init_imports: return None - content_hash = _write_pyi_file(module_path, init_imports) + _write_pyi_file(module_path, init_imports) else: new_tree = StubGenerator(module, class_names).visit(ast.parse(source)) - content_hash = _write_pyi_file(module_path, ast.unparse(new_tree)) - return str(module_path.with_suffix(".pyi").resolve()), content_hash + _write_pyi_file(module_path, ast.unparse(new_tree)) + return str(module_path.with_suffix(".pyi").resolve()) class PyiGenerator: @@ -1610,10 +1615,9 @@ class PyiGenerator: generate the appropriate stub. """ - modules: list = [] - root: str = "" - current_module: Any = {} - written_files: list[tuple[str, str]] = [] + def __init__(self) -> None: + """Initialize the generator with no written .pyi files.""" + self.written_files: list[str] = [] def _scan_files(self, files: list[Path]): max_workers = min(multiprocessing.cpu_count() or 1, len(files), 8) @@ -1715,19 +1719,22 @@ def scan_all( self._scan_files(file_targets) - file_paths, hashes = ( - [f[0] for f in self.written_files], - [f[1] for f in self.written_files], - ) + file_paths = self.written_files # Fix generated pyi files with ruff. if file_paths: subprocess.run(["ruff", "format", *file_paths]) subprocess.run(["ruff", "check", "--fix", *file_paths]) - if use_json: - if file_paths and prune_stale: - file_paths = list(map(Path, file_paths)) + if use_json and file_paths: + file_paths = list(map(Path, file_paths)) + # Hash only after ruff post-processing, so the registry reflects the + # final on-disk content rather than the intermediate generator output. + hashes = [ + md5(file_path.read_text().encode()).hexdigest() + for file_path in file_paths + ] + if prune_stale: top_dir = file_paths[0].parent for file_path in file_paths: file_parent = file_path.parent @@ -1765,8 +1772,7 @@ def scan_all( ) + "\n", ) - elif file_paths: - file_paths = list(map(Path, file_paths)) + else: pyi_hashes_parent = file_paths[0].parent while ( not pyi_hashes_parent.samefile(pyi_hashes_parent.parent) @@ -1778,7 +1784,7 @@ def scan_all( if pyi_hashes_file.exists(): pyi_hashes = json.loads(pyi_hashes_file.read_text()) for file_path, hashed_content in zip( - file_paths, hashes, strict=False + file_paths, hashes, strict=True ): formatted_path = file_path.relative_to( pyi_hashes_parent diff --git a/pyi_hashes.json b/pyi_hashes.json index d0d09e0a996..dc601e746f3 100644 --- a/pyi_hashes.json +++ b/pyi_hashes.json @@ -1,124 +1,124 @@ { - "packages/reflex-components-code/src/reflex_components_code/code.pyi": "ee1377bb8779bcd9a1069246cc41f957", - "packages/reflex-components-code/src/reflex_components_code/shiki_code_block.pyi": "60d916b71e20b2c37ee85c2f77cb1a94", - "packages/reflex-components-core/src/reflex_components_core/__init__.pyi": "82b29d23f2490161d42fd21021bd39c3", - "packages/reflex-components-core/src/reflex_components_core/base/__init__.pyi": "7009187aaaf191814d031e5462c48318", - "packages/reflex-components-core/src/reflex_components_core/base/app_wrap.pyi": "7e6d47b5103645de33309dc4ac1a4317", - "packages/reflex-components-core/src/reflex_components_core/base/body.pyi": "401472c41e11c629598e5b6200434a18", - "packages/reflex-components-core/src/reflex_components_core/base/document.pyi": "1852d2a5b49961a6e164b65bcf153b4a", - "packages/reflex-components-core/src/reflex_components_core/base/error_boundary.pyi": "49fb5ade8b957091a5a5a7c98e6feafb", - "packages/reflex-components-core/src/reflex_components_core/base/fragment.pyi": "ed61f55dd75ae4df5cc14ee01a6540fa", - "packages/reflex-components-core/src/reflex_components_core/base/link.pyi": "581499d67df1d53b4ff57fd660067d9c", - "packages/reflex-components-core/src/reflex_components_core/base/meta.pyi": "762e78d2b1e1c5632afcc0652ca467af", - "packages/reflex-components-core/src/reflex_components_core/base/script.pyi": "cdc59d7bdde7b9b3b10845aa52853299", - "packages/reflex-components-core/src/reflex_components_core/base/strict_mode.pyi": "bb692191ce0f1fbfce859a9eba10cbad", - "packages/reflex-components-core/src/reflex_components_core/core/__init__.pyi": "dd5142b3c9087bf2bf22651adf6f2724", - "packages/reflex-components-core/src/reflex_components_core/core/auto_scroll.pyi": "d63f077b0c4cd1924c59a6562d558e39", - "packages/reflex-components-core/src/reflex_components_core/core/banner.pyi": "2f81188abc7a1c8fc2e7573e4335ba63", - "packages/reflex-components-core/src/reflex_components_core/core/clipboard.pyi": "289f617c1646449bddef17f8f124999e", - "packages/reflex-components-core/src/reflex_components_core/core/debounce.pyi": "64cd028071ead4892bf5ff4c8d0af34e", - "packages/reflex-components-core/src/reflex_components_core/core/helmet.pyi": "5d542049d242432da93bdb37f064232c", - "packages/reflex-components-core/src/reflex_components_core/core/html.pyi": "90f372ef93b742ed445a6afa8b671e5c", - "packages/reflex-components-core/src/reflex_components_core/core/sticky.pyi": "fe237bf5b5c0030cb85c7b72b2eabdfe", - "packages/reflex-components-core/src/reflex_components_core/core/upload.pyi": "b8e4b197e7678faa653d9a2f7da10591", - "packages/reflex-components-core/src/reflex_components_core/core/window_events.pyi": "c51889b4e63f6b3132ae195da959ea1e", - "packages/reflex-components-core/src/reflex_components_core/datadisplay/__init__.pyi": "c96fed4da42a13576d64f84e3c7cb25c", - "packages/reflex-components-core/src/reflex_components_core/el/__init__.pyi": "f09129ddefb57ab4c7769c86dc9a3153", - "packages/reflex-components-core/src/reflex_components_core/el/element.pyi": "19bd843c1294785ec42b3e0f6ae5e46f", - "packages/reflex-components-core/src/reflex_components_core/el/elements/__init__.pyi": "e6c845f2f29eb079697a2e31b0c2f23a", - "packages/reflex-components-core/src/reflex_components_core/el/elements/base.pyi": "d89d4cf5fa68f7607cc613ba862dbc33", - "packages/reflex-components-core/src/reflex_components_core/el/elements/forms.pyi": "0929908170b04328b23e2343493dbd14", - "packages/reflex-components-core/src/reflex_components_core/el/elements/inline.pyi": "106c40b2f1732dc8ab5ac3a55c9ade0a", - "packages/reflex-components-core/src/reflex_components_core/el/elements/media.pyi": "3ee07d06e7ef9b72129d4315e32aa017", - "packages/reflex-components-core/src/reflex_components_core/el/elements/metadata.pyi": "9bffa93d5d9753fa1123bdf327ef224b", - "packages/reflex-components-core/src/reflex_components_core/el/elements/other.pyi": "9824faa7115bba66a3b0e827022c8cf1", - "packages/reflex-components-core/src/reflex_components_core/el/elements/scripts.pyi": "5cf24239b88c1d2847c92a025d05f31d", - "packages/reflex-components-core/src/reflex_components_core/el/elements/sectioning.pyi": "55eeee66bb8a07af0e73885d61ce819c", - "packages/reflex-components-core/src/reflex_components_core/el/elements/tables.pyi": "5c544e26f79477713d9426dfa6003220", - "packages/reflex-components-core/src/reflex_components_core/el/elements/typography.pyi": "f746255251faf92aa54d5cf28e202758", - "packages/reflex-components-core/src/reflex_components_core/react_router/dom.pyi": "b5f6d8ce3fcdfc1d5efd5dfac2b95e3b", - "packages/reflex-components-dataeditor/src/reflex_components_dataeditor/dataeditor.pyi": "69b644aa2d116ea3532155ada09be70a", - "packages/reflex-components-gridjs/src/reflex_components_gridjs/datatable.pyi": "74ce1f8a302aa9b9b317e6e63e5dac41", - "packages/reflex-components-lucide/src/reflex_components_lucide/icon.pyi": "cbac4e023ad9b9923736908600d416f6", - "packages/reflex-components-markdown/src/reflex_components_markdown/markdown.pyi": "62a1b311ed239ff1dc943478ae2b7c7d", - "packages/reflex-components-moment/src/reflex_components_moment/moment.pyi": "2623f3930c838f52a13018fb5ded01c0", - "packages/reflex-components-plotly/src/reflex_components_plotly/plotly.pyi": "700dac836a2610094c4e85e068d2c8f7", - "packages/reflex-components-radix/src/reflex_components_radix/__init__.pyi": "19216eb3618f68c8a76e5e43801cf4af", - "packages/reflex-components-radix/src/reflex_components_radix/primitives/__init__.pyi": "5404a8da97e8b5129133d7f300e3f642", - "packages/reflex-components-radix/src/reflex_components_radix/primitives/accordion.pyi": "e48ed5a3fbe79eb73e63ad07aa490241", - "packages/reflex-components-radix/src/reflex_components_radix/primitives/base.pyi": "44ae9d7d31f4c0237d9b8ce213454218", - "packages/reflex-components-radix/src/reflex_components_radix/primitives/dialog.pyi": "170dc8766164a4021770ac0447e7978e", - "packages/reflex-components-radix/src/reflex_components_radix/primitives/drawer.pyi": "5bd53bb47323cc26a4e0c4b64f93cbaf", - "packages/reflex-components-radix/src/reflex_components_radix/primitives/form.pyi": "041125ac50c493621e58758412ea5c02", - "packages/reflex-components-radix/src/reflex_components_radix/primitives/progress.pyi": "47e86a27f49fbc9c5f2f8f4832f27d30", - "packages/reflex-components-radix/src/reflex_components_radix/primitives/slider.pyi": "381491180881ae1890396ae1276748f9", - "packages/reflex-components-radix/src/reflex_components_radix/themes/__init__.pyi": "b433b9a099dc5b0ab008d02c85d38059", - "packages/reflex-components-radix/src/reflex_components_radix/themes/base.pyi": "6210c4383081524f9e521441247fdc3a", - "packages/reflex-components-radix/src/reflex_components_radix/themes/color_mode.pyi": "56ed24c55adcfcc1665e3c2b1f5bca4f", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/__init__.pyi": "f10f0169f81c78290333da831915762f", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/alert_dialog.pyi": "cf4ee8d5881ae637d3921ce47d77288c", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/aspect_ratio.pyi": "fc59489d19ced57d25b79ed3faea1452", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/avatar.pyi": "44c8f858b0dd5a0b2cf3a123819800ca", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/badge.pyi": "4aaf303dda33666f843497f739372f31", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/button.pyi": "9513c578fd0937af79e844b862247e07", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/callout.pyi": "30f9b953cd5f67a3bee5b862758630c3", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/card.pyi": "7fc1a0118435b5326e87218486ba0467", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/checkbox.pyi": "c1a14bc5ef590547fceb75b0b7ba8133", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/checkbox_cards.pyi": "386b07f457781c167e70d57cfee33264", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/checkbox_group.pyi": "d888952bbd5e8df885e7ba7b9c7c6894", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/context_menu.pyi": "d82544e85d3c47ebddb6b1fee6216f78", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/data_list.pyi": "48e0d7e25cc418e10e3d6f270a1cbcb2", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/dialog.pyi": "325f54a610ddca5679ec555220207caa", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/dropdown_menu.pyi": "794d02c236c887de7572d7b1fa730d64", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/hover_card.pyi": "30867282512dd968e6570e5aad7b52aa", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/icon_button.pyi": "19d3d20ea46171346a1c3e488ebd1a3a", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/inset.pyi": "75991b362962882f18c69e081e68c284", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/popover.pyi": "430834b6a91bca074447f9c4b046d7d2", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/progress.pyi": "81e92f87d352f75e1e09f8f44cc782f5", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/radio.pyi": "f452755354bec757ebf01817de731bda", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/radio_cards.pyi": "4e296a069c395154825e51abc8b37abb", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/radio_group.pyi": "ba6f983a6dbee4fd9665bb63544152d4", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/scroll_area.pyi": "3b746f28fb7f9518697edb2dfc0a2c90", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/segmented_control.pyi": "0b5e8273d1d3044772c710f32475f2b4", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/select.pyi": "75f5da11fe90491751d8ebcb3d1332a1", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/separator.pyi": "0885e5b47e0f158511b26c111ccea9ba", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/skeleton.pyi": "b4abd9619577a34783f7b41e4041170c", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/slider.pyi": "e714426507967f2d0d1feebb8ca8c005", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/spinner.pyi": "07e7d6a75c5bb5673d2fc6992ac05b6a", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/switch.pyi": "5d97af6f1bacf7b29ff709922f6835d5", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/table.pyi": "5ca834b3dae21884223fd76f485c7c04", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/tabs.pyi": "445695ca79d8efebadf60201c17c9d98", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/text_area.pyi": "609fff762d18b6326b87a4f1dfbddc25", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/text_field.pyi": "e7215f6ebde268e6ff27c7f3f65b91e2", - "packages/reflex-components-radix/src/reflex_components_radix/themes/components/tooltip.pyi": "e6f6007a6e5ba3ace5f8d761992107c7", - "packages/reflex-components-radix/src/reflex_components_radix/themes/layout/__init__.pyi": "9e452af27229b676ad0146e40f75bed5", - "packages/reflex-components-radix/src/reflex_components_radix/themes/layout/base.pyi": "0a60d38f462928eccd5f2e1522f8d9e5", - "packages/reflex-components-radix/src/reflex_components_radix/themes/layout/box.pyi": "99a43eb5e4f64a9670587f7c4c33e1ab", - "packages/reflex-components-radix/src/reflex_components_radix/themes/layout/center.pyi": "f7995de1ca82dca1fb0a52baa6221e06", - "packages/reflex-components-radix/src/reflex_components_radix/themes/layout/container.pyi": "ac557baa161dd9f4fd5ba4239dc6f3e7", - "packages/reflex-components-radix/src/reflex_components_radix/themes/layout/flex.pyi": "045892084d19790ec5dce0aca23f8ab6", - "packages/reflex-components-radix/src/reflex_components_radix/themes/layout/grid.pyi": "e09b30f3045fffe6415df56c2ef6b801", - "packages/reflex-components-radix/src/reflex_components_radix/themes/layout/list.pyi": "081c2dc6b6bdd9ac58865b605f51d73a", - "packages/reflex-components-radix/src/reflex_components_radix/themes/layout/section.pyi": "7ee955218a908d3ff4724d6f870536f9", - "packages/reflex-components-radix/src/reflex_components_radix/themes/layout/spacer.pyi": "1f3a21cbcc69131135c069d200ddd432", - "packages/reflex-components-radix/src/reflex_components_radix/themes/layout/stack.pyi": "71540d9403ebbdac97fa21096b5c01e9", - "packages/reflex-components-radix/src/reflex_components_radix/themes/typography/__init__.pyi": "de7ee994f66a4c1d1a6ac2ad3370c30e", - "packages/reflex-components-radix/src/reflex_components_radix/themes/typography/blockquote.pyi": "ef67ff3ea9805bd95322834f044437cb", - "packages/reflex-components-radix/src/reflex_components_radix/themes/typography/code.pyi": "636acf47e8aac0cda0ab2b5beb4119de", - "packages/reflex-components-radix/src/reflex_components_radix/themes/typography/heading.pyi": "bc56e9eb91ae9899560c613d55089375", - "packages/reflex-components-radix/src/reflex_components_radix/themes/typography/link.pyi": "f4dad92290f4bb8cb65e7702d41d23de", - "packages/reflex-components-radix/src/reflex_components_radix/themes/typography/text.pyi": "179be574a5127a877780d2839fcae7ee", - "packages/reflex-components-react-player/src/reflex_components_react_player/audio.pyi": "5bbf08502695fededb3ca4d23245d3df", - "packages/reflex-components-react-player/src/reflex_components_react_player/react_player.pyi": "41e57798ed7df7eb405d0ac532289c1b", - "packages/reflex-components-react-player/src/reflex_components_react_player/video.pyi": "ae525af69173fab76a89924d10e07209", - "packages/reflex-components-recharts/src/reflex_components_recharts/__init__.pyi": "7b8b69840a3637c1f1cac45ba815cccf", - "packages/reflex-components-recharts/src/reflex_components_recharts/cartesian.pyi": "1d4ecc60531f713c9ff5948370ec5657", - "packages/reflex-components-recharts/src/reflex_components_recharts/charts.pyi": "45e7fbe250684e338a6ac5c74a6c6b74", - "packages/reflex-components-recharts/src/reflex_components_recharts/general.pyi": "64f5e189d4bda0e7d946c302297070c9", - "packages/reflex-components-recharts/src/reflex_components_recharts/polar.pyi": "1ad9783b38fda94d9c64ac808a7f2535", - "packages/reflex-components-recharts/src/reflex_components_recharts/recharts.pyi": "193ab7e39b83b8898feeeed98f21d542", - "packages/reflex-components-sonner/src/reflex_components_sonner/toast.pyi": "13e2466062abe801d0741b55a39ae978", - "reflex/__init__.pyi": "674cc55e646deb97c0e414e1d0e850ef", - "reflex/components/__init__.pyi": "f39a2af77f438fa243c58c965f19d42e", - "reflex/experimental/memo.pyi": "665e37631a7b38dfac5497098d6c0a04" + "packages/reflex-components-code/src/reflex_components_code/code.pyi": "3b89c09ccc89eeeafe3e38ca539607a0", + "packages/reflex-components-code/src/reflex_components_code/shiki_code_block.pyi": "53c8f35514ebcf40ac5cf70c2342ac1c", + "packages/reflex-components-core/src/reflex_components_core/__init__.pyi": "d89c7cfa0920f664bc41d292ef882a64", + "packages/reflex-components-core/src/reflex_components_core/base/__init__.pyi": "d46e910c03263a8d3456d473de9e76c7", + "packages/reflex-components-core/src/reflex_components_core/base/app_wrap.pyi": "4a701f7eaf84ec041c8fd5c8af4e48ff", + "packages/reflex-components-core/src/reflex_components_core/base/body.pyi": "8550ac0cdb7f57b35dc639b605294b98", + "packages/reflex-components-core/src/reflex_components_core/base/document.pyi": "92be3177fff806cd44281cb912b21463", + "packages/reflex-components-core/src/reflex_components_core/base/error_boundary.pyi": "2bec3beeafea96787d10838d73e47bdc", + "packages/reflex-components-core/src/reflex_components_core/base/fragment.pyi": "04de5816bc98f33bbf14370af7f787b3", + "packages/reflex-components-core/src/reflex_components_core/base/link.pyi": "d39ded31424a9af8532b9d4eb0ce8abf", + "packages/reflex-components-core/src/reflex_components_core/base/meta.pyi": "c0e97a357ac2521c9b1c48b9368513e7", + "packages/reflex-components-core/src/reflex_components_core/base/script.pyi": "14cd6b846459f469168e78c305ee696a", + "packages/reflex-components-core/src/reflex_components_core/base/strict_mode.pyi": "135dd395a27f01be303b3879ece179c1", + "packages/reflex-components-core/src/reflex_components_core/core/__init__.pyi": "931b222daf3755f67281b6c4d7155f85", + "packages/reflex-components-core/src/reflex_components_core/core/auto_scroll.pyi": "2d83dc211884423496c31d372d3f3734", + "packages/reflex-components-core/src/reflex_components_core/core/banner.pyi": "473666c89f74a1fcd82f12cc2cd34f43", + "packages/reflex-components-core/src/reflex_components_core/core/clipboard.pyi": "21d51b69ab11279e864f7aca9307462f", + "packages/reflex-components-core/src/reflex_components_core/core/debounce.pyi": "86b2bea0aeec5334dbb64b3addae91df", + "packages/reflex-components-core/src/reflex_components_core/core/helmet.pyi": "cbbfc51195fb5cef671ff9ce65586d29", + "packages/reflex-components-core/src/reflex_components_core/core/html.pyi": "bedb5c94e690d50721ddc7bfdfbe8a25", + "packages/reflex-components-core/src/reflex_components_core/core/sticky.pyi": "a910d65f42f620531c959677d22977cb", + "packages/reflex-components-core/src/reflex_components_core/core/upload.pyi": "d903297d188fe6fe56a824127e0db925", + "packages/reflex-components-core/src/reflex_components_core/core/window_events.pyi": "3e39f7b3282570da5d2d3ac503d1f278", + "packages/reflex-components-core/src/reflex_components_core/datadisplay/__init__.pyi": "f46edcf2c5bd4b80894b4d0f623e059b", + "packages/reflex-components-core/src/reflex_components_core/el/__init__.pyi": "ca9bfe7ba432aa47d982a144ef374126", + "packages/reflex-components-core/src/reflex_components_core/el/element.pyi": "930b020d7c933ab0e29ba7971ba1abd2", + "packages/reflex-components-core/src/reflex_components_core/el/elements/__init__.pyi": "ded6fc0acc37c9260da5cfd5f4309079", + "packages/reflex-components-core/src/reflex_components_core/el/elements/base.pyi": "d075a1420b5a08cccd45aa58599ab3dc", + "packages/reflex-components-core/src/reflex_components_core/el/elements/forms.pyi": "42b0e8e04b79d7aa78d16b4f9ad39cef", + "packages/reflex-components-core/src/reflex_components_core/el/elements/inline.pyi": "c4085b9ee43847b6765cbf775341bc0b", + "packages/reflex-components-core/src/reflex_components_core/el/elements/media.pyi": "c2515454828415b78799f0ee0fb7a6af", + "packages/reflex-components-core/src/reflex_components_core/el/elements/metadata.pyi": "2d8d722c68f5a3082c0d3fa4883bb5c0", + "packages/reflex-components-core/src/reflex_components_core/el/elements/other.pyi": "da35b7e4a4496c7a84e79bc447b69ba1", + "packages/reflex-components-core/src/reflex_components_core/el/elements/scripts.pyi": "ddb26aa7e3f437579ac48dbe1da3bcfc", + "packages/reflex-components-core/src/reflex_components_core/el/elements/sectioning.pyi": "1f91a452bceebd410056e4fbdad0dfe9", + "packages/reflex-components-core/src/reflex_components_core/el/elements/tables.pyi": "7b4c2eaff78f6a412f804457570014c4", + "packages/reflex-components-core/src/reflex_components_core/el/elements/typography.pyi": "a3d0d5b0ad9d896261091603df6d2c03", + "packages/reflex-components-core/src/reflex_components_core/react_router/dom.pyi": "7617635157b816f70354e2db98b38642", + "packages/reflex-components-dataeditor/src/reflex_components_dataeditor/dataeditor.pyi": "5d12a0b0e9b4d76a9e4ba1d486094c1c", + "packages/reflex-components-gridjs/src/reflex_components_gridjs/datatable.pyi": "2ce1c076ecf5c2fa4945b4abdbf2f91d", + "packages/reflex-components-lucide/src/reflex_components_lucide/icon.pyi": "2e1da186a37e2bb8a1d90e16ee9a63b5", + "packages/reflex-components-markdown/src/reflex_components_markdown/markdown.pyi": "79d0a59b1ba12a2f2c4a09fa6b5c776f", + "packages/reflex-components-moment/src/reflex_components_moment/moment.pyi": "eabf233471bc5b94084914f6f35ecd66", + "packages/reflex-components-plotly/src/reflex_components_plotly/plotly.pyi": "6b84ff7659294b20d21b0ef7781531fa", + "packages/reflex-components-radix/src/reflex_components_radix/__init__.pyi": "a77352f60fb6f4135b5d08a6e56efa6d", + "packages/reflex-components-radix/src/reflex_components_radix/primitives/__init__.pyi": "bbd4d1a4fa73275a882c33ba485d0165", + "packages/reflex-components-radix/src/reflex_components_radix/primitives/accordion.pyi": "2639b56ce9ccb8b404c6dc12eaace19d", + "packages/reflex-components-radix/src/reflex_components_radix/primitives/base.pyi": "c6500b29e90ca0c04e6bac65ad19936e", + "packages/reflex-components-radix/src/reflex_components_radix/primitives/dialog.pyi": "e67999e6a7433d0eb8c18f4dd185761b", + "packages/reflex-components-radix/src/reflex_components_radix/primitives/drawer.pyi": "172048f74ea5cb7b0e68829d5de3a1fa", + "packages/reflex-components-radix/src/reflex_components_radix/primitives/form.pyi": "2a0611c1ffa91b4c2061ef3697b7ec75", + "packages/reflex-components-radix/src/reflex_components_radix/primitives/progress.pyi": "849b07e27c3916bd24bb576b57e9e2c4", + "packages/reflex-components-radix/src/reflex_components_radix/primitives/slider.pyi": "2846f40bff377ee688d46055c4f7390a", + "packages/reflex-components-radix/src/reflex_components_radix/themes/__init__.pyi": "6c7e1b9a0a7ca00f029bf6ba0c514fdb", + "packages/reflex-components-radix/src/reflex_components_radix/themes/base.pyi": "bf24641c7b44efcacaf67e2e49947c2c", + "packages/reflex-components-radix/src/reflex_components_radix/themes/color_mode.pyi": "efcec0a98ceb064556bcbcd8718ac9cc", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/__init__.pyi": "758646fcd894b0acb09bfb6b97f2d475", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/alert_dialog.pyi": "c4fc4b724c07f7cce647e8c72046d01a", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/aspect_ratio.pyi": "376e58873fa3431e178420d6c5806967", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/avatar.pyi": "ca8e7b05994c4bfb0e7f6ca611d48275", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/badge.pyi": "73ebf22c8fbb2d1388a3f1cd55eb1919", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/button.pyi": "3cd7cc1df19d44e14da3b291e4689ba2", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/callout.pyi": "030a61bddc63006470b856fa2d29fe47", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/card.pyi": "88cb5e549b3a4e099fe4a0795a2d4977", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/checkbox.pyi": "cd5187687dc614b908bf6ac5216c56fa", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/checkbox_cards.pyi": "f1632234039d89dc08a06e1fae7952d9", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/checkbox_group.pyi": "2c6b06167afb6a3fad615ae689fc706c", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/context_menu.pyi": "61f55df2ce771eb3d3d50b0441a6db76", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/data_list.pyi": "5891cd0930bcdbd55b37a6d945e99cd3", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/dialog.pyi": "6533a2e38a2cdfe8e0c798d975a566fe", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/dropdown_menu.pyi": "1368f79dd2a9d3e5d628ffb18d0f15fa", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/hover_card.pyi": "4566d59581a7bd7d870994a1a6267349", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/icon_button.pyi": "d16568436493dce1a35dd9b706dbb6ba", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/inset.pyi": "eaeb2399578e423ce7887d92fc276012", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/popover.pyi": "f0e2ce71c899e7029e0dffa9a88df1d2", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/progress.pyi": "e90d1f64301e17ca54a1edf2878bea9f", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/radio.pyi": "e14c994517828f84d9fc9f85501eee7a", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/radio_cards.pyi": "45470676b80c15d722b142c27521a64f", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/radio_group.pyi": "e933b49dab8027e1829cdd90ba99cc5d", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/scroll_area.pyi": "b83dd81a37aaad75dcb6341e94e6d41f", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/segmented_control.pyi": "dfdde032961bda7905ef4256eb19152d", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/select.pyi": "98818bc17dd54d4a0bfb48f7d971875a", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/separator.pyi": "b97507dd3c8ee6464b733fb61558c0ba", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/skeleton.pyi": "77e709d2f460b19617c9fc2e45537e18", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/slider.pyi": "27ae71e52b3a6abce5d94e83c354afb9", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/spinner.pyi": "a44624cea06503e76fbc1d90132faa72", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/switch.pyi": "ced70bf91fa0b598db0d1d976f2caeb7", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/table.pyi": "20b17107bb0ce5289a89b13fcef023e4", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/tabs.pyi": "4bb81b1bbb020add0bff1a5cbd541442", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/text_area.pyi": "4eba432001b75e809105dde744cc987c", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/text_field.pyi": "1adb24a4b4d8dde64c1d6bb19807675b", + "packages/reflex-components-radix/src/reflex_components_radix/themes/components/tooltip.pyi": "7159fb41c6e8e5375d70e01b3db5878d", + "packages/reflex-components-radix/src/reflex_components_radix/themes/layout/__init__.pyi": "dcb8926703a1015583fc12daadb0ee21", + "packages/reflex-components-radix/src/reflex_components_radix/themes/layout/base.pyi": "3722a5c6ed8cdd5f483b112b673a460d", + "packages/reflex-components-radix/src/reflex_components_radix/themes/layout/box.pyi": "91c0636f8347bb3861b98679129054fe", + "packages/reflex-components-radix/src/reflex_components_radix/themes/layout/center.pyi": "97a48bf51881c96c48230e97495ef526", + "packages/reflex-components-radix/src/reflex_components_radix/themes/layout/container.pyi": "c1b4dd2f75d37b95ccce31d95bce339c", + "packages/reflex-components-radix/src/reflex_components_radix/themes/layout/flex.pyi": "ff5f0a7671b3b52253d1e9c01091e383", + "packages/reflex-components-radix/src/reflex_components_radix/themes/layout/grid.pyi": "4623cb3f6cacd49d9ace0f582eec6821", + "packages/reflex-components-radix/src/reflex_components_radix/themes/layout/list.pyi": "8b7a051ef85c0e0c14a61ee3f50ca260", + "packages/reflex-components-radix/src/reflex_components_radix/themes/layout/section.pyi": "9eedd4b6a85daee106ee4a4ca2e8b1a5", + "packages/reflex-components-radix/src/reflex_components_radix/themes/layout/spacer.pyi": "02655879b13b3edf07bc18f21cec2d39", + "packages/reflex-components-radix/src/reflex_components_radix/themes/layout/stack.pyi": "94d5d4aef75d03be26d07ee0bf20fac1", + "packages/reflex-components-radix/src/reflex_components_radix/themes/typography/__init__.pyi": "a904755b3ecbd65b826328431342b8b5", + "packages/reflex-components-radix/src/reflex_components_radix/themes/typography/blockquote.pyi": "377d220f6ecb0e734cfe4a8b7cc834da", + "packages/reflex-components-radix/src/reflex_components_radix/themes/typography/code.pyi": "2bd706e29877dfdeda6ca46900f7414b", + "packages/reflex-components-radix/src/reflex_components_radix/themes/typography/heading.pyi": "6691a55131a893676a68960cf64116e3", + "packages/reflex-components-radix/src/reflex_components_radix/themes/typography/link.pyi": "e4d9e52ce7f2e97a4d2136eade8bf7cd", + "packages/reflex-components-radix/src/reflex_components_radix/themes/typography/text.pyi": "2f94a562aa24860cf6754c86128ffba1", + "packages/reflex-components-react-player/src/reflex_components_react_player/audio.pyi": "39e4144cef066bbff8c27b36a205a54b", + "packages/reflex-components-react-player/src/reflex_components_react_player/react_player.pyi": "86fc106181638c6a0a2a199332be817f", + "packages/reflex-components-react-player/src/reflex_components_react_player/video.pyi": "2682dc6e825d25307d8390d01e2bd653", + "packages/reflex-components-recharts/src/reflex_components_recharts/__init__.pyi": "359e123d9a046557ce05a96ce10313f5", + "packages/reflex-components-recharts/src/reflex_components_recharts/cartesian.pyi": "3485aaabbfd3ca89908ae19425c7297e", + "packages/reflex-components-recharts/src/reflex_components_recharts/charts.pyi": "280a7cd51298ee676f3d076104133f44", + "packages/reflex-components-recharts/src/reflex_components_recharts/general.pyi": "f5e3491c4e1f69ba89085682888888a9", + "packages/reflex-components-recharts/src/reflex_components_recharts/polar.pyi": "99ebcfc07868061bdc3c2010d85a153f", + "packages/reflex-components-recharts/src/reflex_components_recharts/recharts.pyi": "4f6c26f8c76543cc41e2b9dc400ece8a", + "packages/reflex-components-sonner/src/reflex_components_sonner/toast.pyi": "58521fcd1b514804f534d97624e82c9a", + "reflex/__init__.pyi": "56385a4f0d9431eb0056dbc5553a58f9", + "reflex/components/__init__.pyi": "9facd05a776d0641432696bbf8e34388", + "reflex/experimental/memo.pyi": "58d97de180cc34a8aa605cd76d97ee57" } diff --git a/tests/units/reflex_base/utils/pyi_generator/test_hashes.py b/tests/units/reflex_base/utils/pyi_generator/test_hashes.py new file mode 100644 index 00000000000..f94376b5aff --- /dev/null +++ b/tests/units/reflex_base/utils/pyi_generator/test_hashes.py @@ -0,0 +1,71 @@ +"""Regression test: pyi_hashes.json must hash the final post-processed content. + +``PyiGenerator.scan_all`` writes the raw ``ast.unparse`` output to disk and then +runs ``ruff format`` / ``ruff check --fix`` over the generated stubs. The hash +registry must be computed from the post-processed file contents: hashing the +intermediate pre-ruff output flags a change whenever the generator's raw output +shifts (quoting, line wrapping, ...), even when the ``.pyi`` file the user sees +is byte-for-byte identical. +""" + +from __future__ import annotations + +import json +import subprocess +import sys +import textwrap +from hashlib import md5 +from pathlib import Path + +_WIDGET_SOURCE = textwrap.dedent( + '''\ + """A fake component module.""" + + from reflex_base.components.component import Component + from reflex_base.vars.base import Var + + + class Widget(Component): + """A widget.""" + + value: Var[str] + ''' +) + +_SCAN_SCRIPT = ( + "from reflex_base.utils.pyi_generator import PyiGenerator; " + "PyiGenerator().scan_all(['fake_pkg'], None, use_json=True)" +) + + +def test_pyi_hashes_reflect_post_ruff_content(tmp_path: Path): + """The recorded hash matches the .pyi content after ruff post-processing. + + Args: + tmp_path: A pytest-provided temporary directory (outside the repo). + """ + root = tmp_path / "fake-root" + pkg = root / "fake_pkg" + pkg.mkdir(parents=True) + (pkg / "__init__.py").write_text("") + (pkg / "widget.py").write_text(_WIDGET_SOURCE) + + # An empty registry that scan_all discovers by walking up from the stub. + hashes_file = root / "pyi_hashes.json" + hashes_file.write_text("{}\n") + + # Run from root so _path_to_module_name produces a valid import name. + subprocess.run( + [sys.executable, "-c", _SCAN_SCRIPT], + cwd=root, + check=True, + ) + + pyi_path = pkg / "widget.pyi" + assert pyi_path.exists() + + hashes = json.loads(hashes_file.read_text()) + assert list(hashes) == ["fake_pkg/widget.pyi"] + assert hashes["fake_pkg/widget.pyi"] == ( + md5(pyi_path.read_text().encode()).hexdigest() + ) diff --git a/tests/units/reflex_base/utils/pyi_generator/test_regression.py b/tests/units/reflex_base/utils/pyi_generator/test_regression.py index f52ca4ec07d..c918162c234 100644 --- a/tests/units/reflex_base/utils/pyi_generator/test_regression.py +++ b/tests/units/reflex_base/utils/pyi_generator/test_regression.py @@ -72,7 +72,7 @@ def _run_generator() -> dict[Path, str]: gen = PyiGenerator() gen.scan_all([str(DATASET_DIR)]) - pyi_paths = [Path(pyi_str) for pyi_str, _hash in gen.written_files] + pyi_paths = [Path(pyi_str) for pyi_str in gen.written_files] try: results: dict[Path, str] = {} for pyi_path in pyi_paths: