Compute a hash of all example file metadata (path + mtime + size). This provides a fast way to detect if any example files have been added, deleted, or modified without re-parsing all example files. Args: examples_dir: Root directory containing example files Returns:
(examples_dir: Path)
| 27 | |
| 28 | |
| 29 | def compute_example_files_hash(examples_dir: Path) -> str: |
| 30 | """ |
| 31 | Compute a hash of all example file metadata (path + mtime + size). |
| 32 | |
| 33 | This provides a fast way to detect if any example files have been added, |
| 34 | deleted, or modified without re-parsing all example files. |
| 35 | |
| 36 | Args: |
| 37 | examples_dir: Root directory containing example files |
| 38 | |
| 39 | Returns: |
| 40 | SHA256 hash of all example file metadata |
| 41 | """ |
| 42 | # Find all .ino files and additional .cpp files |
| 43 | example_files: list[Path] = [] |
| 44 | |
| 45 | # Find all .ino files recursively |
| 46 | for f in sorted(examples_dir.rglob("*.ino")): |
| 47 | example_files.append(f) |
| 48 | |
| 49 | # Find all .cpp files in example subdirectories |
| 50 | for f in sorted(examples_dir.rglob("*.cpp")): |
| 51 | example_files.append(f) |
| 52 | |
| 53 | # Find all .h files in example subdirectories (for dependencies) |
| 54 | for f in sorted(examples_dir.rglob("*.h")): |
| 55 | example_files.append(f) |
| 56 | |
| 57 | # Also include the discovery script itself so changes to it invalidate the cache |
| 58 | this_script = Path(__file__).parent / "discover_examples_all.py" |
| 59 | if this_script.is_file(): |
| 60 | example_files.append(this_script) |
| 61 | |
| 62 | # Deduplicate while preserving order |
| 63 | seen: set[Path] = set() |
| 64 | unique_files: list[Path] = [] |
| 65 | for f in example_files: |
| 66 | if f not in seen: |
| 67 | seen.add(f) |
| 68 | unique_files.append(f) |
| 69 | |
| 70 | # Create hash input from file metadata |
| 71 | hash_input: list[str] = [] |
| 72 | for f in unique_files: |
| 73 | if f.is_file(): |
| 74 | from os import stat_result |
| 75 | |
| 76 | stat: stat_result = f.stat() |
| 77 | # Use absolute path for scripts outside examples_dir |
| 78 | try: |
| 79 | rel_path: str = f.relative_to(examples_dir).as_posix() |
| 80 | except ValueError: |
| 81 | rel_path = f.as_posix() |
| 82 | # Include path, mtime, and size in hash |
| 83 | hash_input.append(f"{rel_path}:{stat.st_mtime:.6f}:{stat.st_size}") |
| 84 | |
| 85 | # Compute SHA256 hash |
| 86 | hash_str = "\n".join(hash_input) |
no test coverage detected