|
1 |
| -from typing import Union |
| 1 | +import re |
| 2 | +from typing import Union, Optional |
| 3 | +from pathlib import Path |
2 | 4 |
|
3 | 5 | import pytest
|
| 6 | +from bs4 import BeautifulSoup, ResultSet, Tag |
| 7 | +from cmarkgfm import github_flavored_markdown_to_html as gfm_to_html |
4 | 8 |
|
5 | 9 |
|
6 | 10 | def requires_gpu_count(num_required_gpus: int) -> pytest.MarkDecorator:
|
@@ -37,3 +41,50 @@ def requires_gpu_mem(required_amount: Union[int, float]) -> pytest.MarkDecorator
|
37 | 41 | f"{actual_vram:.1f} GiB GPU memory found"
|
38 | 42 | )
|
39 | 43 | return pytest.mark.skipif(required_amount > actual_vram, reason=reason)
|
| 44 | + |
| 45 | + |
| 46 | +class ReadMe: |
| 47 | + """ |
| 48 | + Class representing a README (Markdown) file with methods to expedite common usage. |
| 49 | + """ |
| 50 | + |
| 51 | + def __init__(self, path: Path) -> None: |
| 52 | + self.path = path |
| 53 | + self.content = self.path.expanduser().read_text(encoding="utf-8") |
| 54 | + self.__normalize_code_fence_lang() |
| 55 | + self.html = gfm_to_html(self.content) |
| 56 | + self.soup = BeautifulSoup(self.html, "html.parser") |
| 57 | + |
| 58 | + def __normalize_code_fence_lang(self): |
| 59 | + """ |
| 60 | + Perform limited normalization on the code language of code blocks to maintain |
| 61 | + consistency and simplicity with locating them. |
| 62 | + """ |
| 63 | + self.content = re.sub(r"```(shell|bash|sh)\b", "```shell", self.content) |
| 64 | + |
| 65 | + def get_code_blocks(self, *, lang: Optional[str] = None) -> ResultSet[Tag]: |
| 66 | + """ |
| 67 | + Get all code blocks with language `lang`, or all code blocks if `lang` is None |
| 68 | + (default). |
| 69 | + :param lang: language of code block to filter by |
| 70 | + :return: code block `Tag`s found in README |
| 71 | + """ |
| 72 | + lang = "shell" if lang == "bash" else lang |
| 73 | + selector = f'pre[lang="{lang}"] > code' if lang else "pre > code" |
| 74 | + tags = self.soup.select(selector) |
| 75 | + return tags |
| 76 | + |
| 77 | + def get_code_block_content( |
| 78 | + self, *, position: int, lang: Optional[str] = None |
| 79 | + ) -> str: |
| 80 | + """ |
| 81 | + Get contents of code block at specified position (starting with 0). Optionally |
| 82 | + pass a language specifier, `lang`, to only look at code blocks highlighted for |
| 83 | + that language (happens prior to indexing). |
| 84 | + :param position: position of code block to get (starting at 0) |
| 85 | + :param lang: language of code block to filter by |
| 86 | + :return: content of the code block |
| 87 | + """ |
| 88 | + code_blocks = self.get_code_blocks(lang=lang) |
| 89 | + code = code_blocks[position].text.strip() |
| 90 | + return code |
0 commit comments