[Doctests] Refactor doctests + add CI#22987
Conversation
|
The documentation is not available anymore as the PR was closed or merged. |
|
Local tests run, I now have this strange error: _____ ERROR collecting src/transformers/models/whisper/modeling_whisper.py _____
import file mismatch:
imported module 'transformers.models.whisper.modeling_whisper' has this __file__ attribute:
/home/circleci/.pyenv/versions/3.8.12/lib/python3.8/site-packages/transformers/models/whisper/modeling_whisper.py
which is not the same as the test file we want to collect:
/home/circleci/transformers/src/transformers/models/whisper/modeling_whisper.py
HINT: remove __pycache__ / .pyc files and/or use a unique basename for your test file modules |
|
@ArthurZucker Regarding the error you mentioned in the above comment, could you provide the command you used to launch? Also, for this PR to be merged, two thing we should check are:
|
|
Regarding
Actually the CI checks doc for all files in the diff that end in .py and .mdx. This is prone to changes! Fully open to recommandations. For slow test, I skip all codeblocks that includ "cuda" in it, we can refine the filter. |
|
CUDA tests are properly skipped! : (11 durations < 0.005s hidden. Use -vv to show these durations.)
=================================================================================================================================================================== short test summary info ====================================================================================================================================================================
PASSED docs/source/en/testing.mdx::testing.mdx
PASSED docs/source/en/testing.mdx::testing.mdx
PASSED src/transformers/models/whisper/modeling_whisper.py::transformers.models.whisper.modeling_whisper.WhisperForAudioClassification.forward
PASSED src/transformers/models/whisper/modeling_whisper.py::transformers.models.whisper.modeling_whisper.WhisperForAudioClassification.forward
PASSED src/transformers/models/whisper/modeling_whisper.py::transformers.models.whisper.modeling_whisper.WhisperForAudioClassification.forward
PASSED src/transformers/models/whisper/modeling_whisper.py::transformers.models.whisper.modeling_whisper.WhisperForConditionalGeneration.forward
PASSED src/transformers/models/whisper/modeling_whisper.py::transformers.models.whisper.modeling_whisper.WhisperForConditionalGeneration.forward
PASSED src/transformers/models/whisper/modeling_whisper.py::transformers.models.whisper.modeling_whisper.WhisperForConditionalGeneration.forward
PASSED src/transformers/models/whisper/modeling_whisper.py::transformers.models.whisper.modeling_whisper.WhisperModel.forward
PASSED src/transformers/models/whisper/modeling_whisper.py::transformers.models.whisper.modeling_whisper.WhisperModel.forward
PASSED src/transformers/models/whisper/modeling_whisper.py::transformers.models.whisper.modeling_whisper.WhisperModel.forward
PASSED docs/source/en/model_doc/wav2vec2.mdx::wav2vec2.mdx
PASSED docs/source/en/model_doc/wav2vec2.mdx::wav2vec2.mdx
SKIPPED [1] <doctest testing.mdx[0]>:1: Codeblock line xxx in xxxx has cuda involved. Skipping
SKIPPED [1] <doctest wav2vec2.mdx[0]>:1: Codeblock line xxx in xxxx has cuda involved. Skipping
Results (19.65s):
3 passed
2 skipped
(py39) arthur_huggingface_co@arthur-gpu-2:~/transformers$ |
|
Warning will be imporved |
sgugger
left a comment
There was a problem hiding this comment.
Thanks for working on this. I have a couple of comments.
| ``` | ||
|
|
||
| 2. Then, you can use the following line to automatically test every docstring example in the desired file: | ||
| Just run the following line to automatically test every docstring example in the desired file: |
|
Looked this PR and played a bit with it: so far so good 👍 One thing I found: The doctest is running while I assume it will be skipped as it has |
ydshieh
left a comment
There was a problem hiding this comment.
Thank you a lot for this awesome improvement! I have a few nit comments, especially for adding a bit more comments to explain things along the code.
It seems SKIP_CUDA_DOCTEST=1 is not working however.
| resource_class: Optional[str] = "xlarge" | ||
| tests_to_run: Optional[List[str]] = None | ||
| working_directory: str = "~/transformers" | ||
| timeout :int = None |
There was a problem hiding this comment.
could we add a comment to mention what it is for?
(i.e. not to confuse the readers with pytest timeout and this timeout)
There was a problem hiding this comment.
+1. Alternatively, another var name like ci_timeout so the code is self documenting
| }, | ||
| ], | ||
| tests_to_run="$(cat pr_documentation_tests.txt)", | ||
| pytest_options={"-doctest-modules":None, "doctest-glob":"*.mdx","dist":"loadfile", "rvsA":None}, |
There was a problem hiding this comment.
-doctest-modules seems incorrect and should be doctest-modules
There was a problem hiding this comment.
also, the format should be better: spaces after : or ,
There was a problem hiding this comment.
doctest-modules alone doesn’t work, since it’s only adding a single -
There was a problem hiding this comment.
doctest-modulesalone doesn’t work, since it’s only adding a single-
For such unusual situation, I would recommend to leave some comments in the code (and if not, in the PR page) to facilitate the review as well as for future HF developers.
There was a problem hiding this comment.
I'm not sure I follow, why is it adding only a single -? I agree with @ydshieh, this is non-obvious and to someone coming cold to the code I think confusing without further context.
There was a problem hiding this comment.
@amyeroberts I think it is because we use --doctest-modules without argument. But in create_circleci_config.py we have
pytest_flags = [f"--{key}={value}" if value is not None else f"-{key}" for key, value in all_options.items()]So we need put -doctest-modules and the above line will change it to --doctest-modules (that is what is required)
This is exceptional however, and we need to make it clear in some way :-)
There was a problem hiding this comment.
In this case, I'd say we should update this logic as it's not properly handling command line options :) e.g. something like this:
PYTEST_BOOL_FLAG = ['doctest-modules',]
...
pytest_flags = []
for key, value in all_options.items():
if key in PYTEST_BOOL_FLAG:
flag = f"--{key}"
elif value is not None:
flag = f"--{key}={value}"
else:
flag = f"-{key}
pytest_flags.append(flag)
| ``` | ||
|
|
||
| 2. Then, you can use the following line to automatically test every docstring example in the desired file: | ||
| Just run the following line to automatically test every docstring example in the desired file: |
|
|
||
|
|
||
| def preprocess_string(string, skip_cuda_tests): | ||
| codeblock_pattern = r"(```(?:python|py)\s*\n\s*>>> )((?:.*?\n)*?.*?```)" |
There was a problem hiding this comment.
probably a docstring to explain a bit what this does
| ] += f'from pytest import skip;skip("Codeblock line {line_num} uses `cuda`. Skipping" \ | ||
| ,allow_module_level=True);' | ||
| codeblocks = "".join(codeblocks) | ||
| return codeblocks |
There was a problem hiding this comment.
some comments along the code lines would be appreciated.
|
What should be detailed is that only the codeblocks (and not the entire file) should be skipped. This might be why longt5 is not skipped! |
amyeroberts
left a comment
There was a problem hiding this comment.
Thanks for working on this - resulting code looks really nice and makes things a lot simpler.
Just a few nits to clarify some part. Could you also add in the PR description what "the fix" is i.e. intention of the PR?
| resource_class: Optional[str] = "xlarge" | ||
| tests_to_run: Optional[List[str]] = None | ||
| working_directory: str = "~/transformers" | ||
| timeout :int = None |
There was a problem hiding this comment.
+1. Alternatively, another var name like ci_timeout so the code is self documenting
|
|
||
|
|
||
| def preprocess_string(string, skip_cuda_tests): | ||
| codeblock_pattern = r"(```(?:python|py)\s*\n\s*>>> )((?:.*?\n)*?.*?```)" |
| means that there are no extra lines at the end of our snippets. The `# doctest: +IGNORE_RESULT` marker is also | ||
| added anywhere a `load_dataset` call is made as a print would otherwise fail the corresonding line. |
There was a problem hiding this comment.
I'm not able to parse this final sentence. For:
"anywhere a load_dataset call is made as a print would otherwise fail the corresonding line"
It's read to me as a print call would fail after a load_dataset line - is this right?
There was a problem hiding this comment.
load_dataset itself will print something, so we need # doctest: +IGNORE_RESULT when load_dataset is called.
|
|
||
| doc_test_job = CircleCIJob( | ||
| "pr_documentation_tests", | ||
| additional_env={"TRANSFORMERS_VERBOSITY":"error", "DATASETS_VERBOSITY":"error", "SKIP_CUDA_DOCTEST": "1"}, |
There was a problem hiding this comment.
Just for my own understanding and doulbe checking - this means cuda docstests are skipped for the doc test job?
There was a problem hiding this comment.
On circleCI only, which does not have GPU runners.
| run: | | ||
| python3 utils/prepare_for_doc_test.py src docs | ||
|
|
||
| - name: Run doctests |
|
For info: I will take over this PR to try to merge it earlier. |
|
Convert to draft for now, as more changes to deal with |
| for i, codeblock in enumerate(codeblocks): | ||
| if "load_dataset(" in codeblock and "# doctest: +IGNORE_RESULT" not in codeblock: | ||
| codeblocks[i] = re.sub(r"(>>> .*load_dataset\(.*)", r"\1 # doctest: +IGNORE_RESULT", codeblock) | ||
| if (">>>" in codeblock or "..." in codeblock) and re.search(r"cuda|to\(0\)|device=0", codeblock) and skip_cuda_tests: |
There was a problem hiding this comment.
The previous regular expression with re.match is just wrong.
There was a problem hiding this comment.
and we also need to check ...
| modified_string = "" | ||
| if not is_cuda_found: | ||
| modified_string = "".join(codeblocks) | ||
| return modified_string |
There was a problem hiding this comment.
As discussed offline with @sgugger , for all doc example blocks in a single docstring, we should skip all the doc examples if one of them contains cuda stuff. Otherwise, we may have errors like NameError: name 'classifier' is not defined
| if "load_dataset(" in codeblock and "# doctest: +IGNORE_RESULT" not in codeblock: | ||
| codeblocks[i] = re.sub(r"(>>> .*load_dataset\(.*)", r"\1 # doctest: +IGNORE_RESULT", codeblock) | ||
| if (">>>" in codeblock or "..." in codeblock) and re.search(r"cuda|to\(0\)|device=0", codeblock) and skip_cuda_tests: | ||
| is_cuda_found = True |
Co-authored-by: Sylvain Gugger <[email protected]>
Co-authored-by: amyeroberts <[email protected]>
* intiial commit * new styling * update * just run doctest in CI * remove more test for fast dev * update * update refs * update path and fetch upstream * update documentatyion trests * typo * parse pwd * don't check for files that are in hidden folders * just give paths relative to transformers * update * update * update * major refactoring * make sure options is ok * lest test that mdx is tested * doctest glob * nits * update doctest nightly * some cleaning * run correct test on diff * debug * run on a single worker * skip_cuda_test tampkate * updates * add rA and continue on failure * test options * parse `py` codeblock? * we don't need to replace ignore results, don't remember whyu I put it * cleanup * more cleaning * fix arg * more cleaning * clean an todo * more pre-processing * doctest-module has none so extra `- ` is needed * remove logs * nits * doctest-modules .... * oups * let's use sugar * make dataset go quiet * add proper timeout * nites * spleling timeout * update * properly skip tests that have CUDSA * proper skipping * cleaning main and get tests to run * remove make report? * remove tee * some updates * tee was removed but is the full output still available? * [all-test] * only our tests * don't touch tee in this PR * no atee-sys * proper sub * monkey * only replace call * fix sub * nits * nits * fix invalid syntax * add skip cuda doctest env variable * make sure all packages are installed * move file * update check repo * revert changes * nit * finish cleanup * fix re * findall * update don't test init files * ignore pycache * `-ignore-pycache` when running pytests * try to fix the import missmatch error * install dec * pytest is required as doctest_utils imports things from it * the only log issues were dataset, ignore results should work * more cleaning * Update .circleci/create_circleci_config.py Co-authored-by: Sylvain Gugger <[email protected]> * Apply suggestions from code review Co-authored-by: amyeroberts <[email protected]> * [ydshieh] empty string if cuda is found * [ydshieh] fix condition * style * [ydshieh] fix * Add comment * style * style * show failure * trigger CI --------- Co-authored-by: Sylvain Gugger <[email protected]> Co-authored-by: Yih-Dar <[email protected]> Co-authored-by: amyeroberts <[email protected]> Co-authored-by: ydshieh <[email protected]>
Revert "[Doctests] Refactor doctests + add CI (huggingface#22987)" This reverts commit 627f447.
* intiial commit * new styling * update * just run doctest in CI * remove more test for fast dev * update * update refs * update path and fetch upstream * update documentatyion trests * typo * parse pwd * don't check for files that are in hidden folders * just give paths relative to transformers * update * update * update * major refactoring * make sure options is ok * lest test that mdx is tested * doctest glob * nits * update doctest nightly * some cleaning * run correct test on diff * debug * run on a single worker * skip_cuda_test tampkate * updates * add rA and continue on failure * test options * parse `py` codeblock? * we don't need to replace ignore results, don't remember whyu I put it * cleanup * more cleaning * fix arg * more cleaning * clean an todo * more pre-processing * doctest-module has none so extra `- ` is needed * remove logs * nits * doctest-modules .... * oups * let's use sugar * make dataset go quiet * add proper timeout * nites * spleling timeout * update * properly skip tests that have CUDSA * proper skipping * cleaning main and get tests to run * remove make report? * remove tee * some updates * tee was removed but is the full output still available? * [all-test] * only our tests * don't touch tee in this PR * no atee-sys * proper sub * monkey * only replace call * fix sub * nits * nits * fix invalid syntax * add skip cuda doctest env variable * make sure all packages are installed * move file * update check repo * revert changes * nit * finish cleanup * fix re * findall * update don't test init files * ignore pycache * `-ignore-pycache` when running pytests * try to fix the import missmatch error * install dec * pytest is required as doctest_utils imports things from it * the only log issues were dataset, ignore results should work * more cleaning * Update .circleci/create_circleci_config.py Co-authored-by: Sylvain Gugger <[email protected]> * Apply suggestions from code review Co-authored-by: amyeroberts <[email protected]> * [ydshieh] empty string if cuda is found * [ydshieh] fix condition * style * [ydshieh] fix * Add comment * style * style * show failure * trigger CI --------- Co-authored-by: Sylvain Gugger <[email protected]> Co-authored-by: Yih-Dar <[email protected]> Co-authored-by: amyeroberts <[email protected]> Co-authored-by: ydshieh <[email protected]>
Revert "[Doctests] Refactor doctests + add CI (huggingface#22987)" This reverts commit 627f447.
What does this PR do?
Wow! The fix is crazy simple but I broke my head finding the correct way to include this in the cleanest way.
We are keeping
pytest --doctest-module🥳 Basically it just came down to:doctest.DocTestParser()'s default regex compilation_pytest.doctestutilities that are private to use this parser!TODOS:
--doctest-globbut that's a small nit