Calls .listing.generate_all(), and post-processes the generated data, checking them and adding a header. Reads the input templates relative to input_dir. Writes them to output_dir according to mode. output_dir is a path or str. Returns ({generated}, {depends}), where genera
(mode: CodegenMode, input_dir: str, output_dir: str)
| 106 | |
| 107 | |
| 108 | def codegen(mode: CodegenMode, input_dir: str, output_dir: str) -> tuple[list[str], list[str]]: |
| 109 | """ |
| 110 | Calls .listing.generate_all(), and post-processes the generated |
| 111 | data, checking them and adding a header. |
| 112 | Reads the input templates relative to input_dir. |
| 113 | Writes them to output_dir according to mode. output_dir is a path or str. |
| 114 | |
| 115 | Returns ({generated}, {depends}), where |
| 116 | generated is a list of (absolute) filenames of generated files, and |
| 117 | depends is a list of (absolute) filenames of dependency files. |
| 118 | """ |
| 119 | input_dir = Directory(input_dir).root |
| 120 | output_dir = Directory(output_dir).root |
| 121 | |
| 122 | # this wrapper intercepts all writes and logs all reads. |
| 123 | wrapper = CodegenDirWrapper(input_dir) |
| 124 | generate_all(wrapper.root) |
| 125 | |
| 126 | # set of all generated filenames |
| 127 | generated = set() |
| 128 | |
| 129 | for parts, data in wrapper.get_writes(): |
| 130 | # TODO: this assumes output_dir is a fslike.Directory! |
| 131 | generated.add(output_dir.fsobj.resolve(parts)) |
| 132 | |
| 133 | # now, actually perform the generation. |
| 134 | # first, assemble the path for the current file |
| 135 | wpath = output_dir[parts] |
| 136 | |
| 137 | data = postprocess_write(parts, data) |
| 138 | |
| 139 | if mode == CodegenMode.CODEGEN: |
| 140 | # skip writing if the file already has that exact content |
| 141 | try: |
| 142 | with wpath.open('rb') as outfile: |
| 143 | if outfile.read() == data: |
| 144 | continue |
| 145 | except FileNotFoundError: |
| 146 | pass |
| 147 | |
| 148 | # write new content to file |
| 149 | wpath.parent.mkdirs() |
| 150 | with wpath.open('wb') as outfile: |
| 151 | print(f"\x1b[36mcodegen: {b'/'.join(parts).decode(errors='replace')}\x1b[0m") |
| 152 | outfile.write(data) |
| 153 | |
| 154 | elif mode == CodegenMode.DRYRUN: |
| 155 | # no-op |
| 156 | pass |
| 157 | |
| 158 | elif mode == CodegenMode.CLEAN: |
| 159 | if wpath.is_file(): |
| 160 | print(b'/'.join(parts).decode(errors='replace')) |
| 161 | wpath.unlink() |
| 162 | else: |
| 163 | err("unknown codegen mode: %s", mode) |
| 164 | sys.exit(1) |
| 165 |
no test coverage detected