Fix @{} references in all files under `src_dir` matching `file_pattern`. A matching directory structure, with the modified files is written to `output_dir`. `{"__init__.py","OWNERS","README.txt"}` are skipped. Files not matching `file_pattern` (using `fnmatch`) are copied with no change.
(src_dir,
output_dir,
reference_resolver,
file_pattern='*.md',
api_docs_relpath='api_docs')
| 455 | |
| 456 | |
| 457 | def replace_refs(src_dir, |
| 458 | output_dir, |
| 459 | reference_resolver, |
| 460 | file_pattern='*.md', |
| 461 | api_docs_relpath='api_docs'): |
| 462 | """Fix @{} references in all files under `src_dir` matching `file_pattern`. |
| 463 | |
| 464 | A matching directory structure, with the modified files is |
| 465 | written to `output_dir`. |
| 466 | |
| 467 | `{"__init__.py","OWNERS","README.txt"}` are skipped. |
| 468 | |
| 469 | Files not matching `file_pattern` (using `fnmatch`) are copied with no change. |
| 470 | |
| 471 | Also, files in the `api_guides/python` directory get explicit ids set on all |
| 472 | heading-2s to ensure back-links work. |
| 473 | |
| 474 | Args: |
| 475 | src_dir: The directory to convert files from. |
| 476 | output_dir: The root directory to write the resulting files to. |
| 477 | reference_resolver: A `parser.ReferenceResolver` to make the replacements. |
| 478 | file_pattern: Only replace references in files matching file_patters, |
| 479 | using fnmatch. Non-matching files are copied unchanged. |
| 480 | api_docs_relpath: Relative-path string to the api_docs, from the src_dir. |
| 481 | """ |
| 482 | # Iterate through all the source files and process them. |
| 483 | for dirpath, _, filenames in os.walk(src_dir): |
| 484 | depth = os.path.relpath(src_dir, start=dirpath) |
| 485 | # How to get from `dirpath` to api_docs/python/ |
| 486 | relative_path_to_root = os.path.join(depth, api_docs_relpath, 'python') |
| 487 | |
| 488 | # Make the directory under output_dir. |
| 489 | new_dir = os.path.join(output_dir, |
| 490 | os.path.relpath(path=dirpath, start=src_dir)) |
| 491 | if not os.path.exists(new_dir): |
| 492 | os.makedirs(new_dir) |
| 493 | |
| 494 | for base_name in filenames: |
| 495 | if base_name in EXCLUDED: |
| 496 | continue |
| 497 | full_in_path = os.path.join(dirpath, base_name) |
| 498 | |
| 499 | # Set the `current_doc_full_name` so bad files can be reported on errors. |
| 500 | reference_resolver.current_doc_full_name = full_in_path |
| 501 | |
| 502 | suffix = os.path.relpath(path=full_in_path, start=src_dir) |
| 503 | full_out_path = os.path.join(output_dir, suffix) |
| 504 | # Copy files that do not match the file_pattern, unmodified. |
| 505 | if not fnmatch.fnmatch(base_name, file_pattern): |
| 506 | if full_in_path != full_out_path: |
| 507 | shutil.copyfile(full_in_path, full_out_path) |
| 508 | continue |
| 509 | |
| 510 | with open(full_in_path, 'rb') as f: |
| 511 | content = f.read().decode('utf-8') |
| 512 | |
| 513 | content = reference_resolver.replace_references(content, |
| 514 | relative_path_to_root) |