| 366 | return source.decode(self.encoding), p, up_to_date |
| 367 | |
| 368 | def list_templates(self) -> t.List[str]: |
| 369 | results: t.List[str] = [] |
| 370 | |
| 371 | if self._archive is None: |
| 372 | # Package is a directory. |
| 373 | offset = len(self._template_root) |
| 374 | |
| 375 | for dirpath, _, filenames in os.walk(self._template_root): |
| 376 | dirpath = dirpath[offset:].lstrip(os.path.sep) |
| 377 | results.extend( |
| 378 | os.path.join(dirpath, name).replace(os.path.sep, "/") |
| 379 | for name in filenames |
| 380 | ) |
| 381 | else: |
| 382 | if not hasattr(self._loader, "_files"): |
| 383 | raise TypeError( |
| 384 | "This zip import does not have the required" |
| 385 | " metadata to list templates." |
| 386 | ) |
| 387 | |
| 388 | # Package is a zip file. |
| 389 | prefix = ( |
| 390 | self._template_root[len(self._archive) :].lstrip(os.path.sep) |
| 391 | + os.path.sep |
| 392 | ) |
| 393 | offset = len(prefix) |
| 394 | |
| 395 | for name in self._loader._files.keys(): # type: ignore |
| 396 | # Find names under the templates directory that aren't directories. |
| 397 | if name.startswith(prefix) and name[-1] != os.path.sep: |
| 398 | results.append(name[offset:].replace(os.path.sep, "/")) |
| 399 | |
| 400 | results.sort() |
| 401 | return results |
| 402 | |
| 403 | |
| 404 | class DictLoader(BaseLoader): |