Skip to content

[Doctests] Refactor doctests + add CI#22987

Merged
ydshieh merged 95 commits into
mainfrom
doct-tests
May 9, 2023
Merged

[Doctests] Refactor doctests + add CI#22987
ydshieh merged 95 commits into
mainfrom
doct-tests

Conversation

@ArthurZucker

@ArthurZucker ArthurZucker commented Apr 25, 2023

Copy link
Copy Markdown
Collaborator

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:

  • change the doctest.DocTestParser()'s default regex compilation
  • rewrite _pytest.doctest utilities that are private to use this parser!

TODOS:

  • change parser
  • add CI Job
  • Filter jobs that can't run on CUDA! This is pretty important
  • update doc
  • fiind a way to default --doctest-glob but that's a small nit
  • add test, to test the parser mostly
  • add check file is doctested if it has some doctring

@HuggingFaceDocBuilderDev

HuggingFaceDocBuilderDev commented Apr 25, 2023

Copy link
Copy Markdown

The documentation is not available anymore as the PR was closed or merged.

@ArthurZucker ArthurZucker changed the title [Doctests] Refactor doctests, don't merge experimental [Doctests] Refactor doctests + add CI + add check Apr 26, 2023
@ArthurZucker
ArthurZucker marked this pull request as ready for review April 26, 2023 06:45
@ArthurZucker

Copy link
Copy Markdown
Collaborator Author

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

@ydshieh

ydshieh commented Apr 26, 2023

Copy link
Copy Markdown
Collaborator

@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:

  • for a single modeling file, how long it will take to run the doctest against it on CircleCI, and if it will fit in the available memory.
    • (we should probably run the doctest against a few existing models)
  • There should NOT have multiple modeling files being included in test_to_run for doctest.
    • This PR currently checks if a file is in utils/documentation_tests.txt, but that file doesn't contain all existing modeling files if I remember correctly.

@ArthurZucker

Copy link
Copy Markdown
Collaborator Author

Regarding

There should NOT have multiple modeling files being included in test_to_run for doctest.
This PR currently checks if a file is in utils/documentation_tests.txt, but that file doesn't contain all existing modeling files if I remember correctly.

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.

@ArthurZucker

Copy link
Copy Markdown
Collaborator Author

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$ 

@ArthurZucker

Copy link
Copy Markdown
Collaborator Author

Warning will be imporved

Comment thread docs/source/en/testing.mdx Outdated
Comment thread docs/source/en/testing.mdx Outdated
Comment thread src/transformers/models/whisper/modeling_whisper.py Outdated
Comment thread utils/check_repo.py Outdated
@ArthurZucker ArthurZucker changed the title [Doctests] Refactor doctests + add CI + add check [Doctests] Refactor doctests + add CI Apr 28, 2023

@sgugger sgugger left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this. I have a couple of comments.

Comment thread .circleci/create_circleci_config.py Outdated
```

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:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Much simpler, nice!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💘

Comment thread docs/source/en/testing.mdx
Comment thread src/transformers/utils/doctest_utils.py Outdated
Comment thread src/transformers/utils/doctest_utils.py Outdated
Comment thread src/transformers/utils/doctest_utils.py
Comment thread src/transformers/utils/doctest_utils.py
Comment thread .circleci/config.yml
@ydshieh

ydshieh commented Apr 29, 2023

Copy link
Copy Markdown
Collaborator

Looked this PR and played a bit with it: so far so good 👍

One thing I found:

SKIP_CUDA_DOCTEST=1 pytest -v --doctest-modules --doctest-glob="*.mdx" docs/source/en/model_doc/longt5.mdx

The doctest is running while I assume it will be skipped as it has cuda thing.

@ydshieh ydshieh left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread .circleci/create_circleci_config.py Outdated
resource_class: Optional[str] = "xlarge"
tests_to_run: Optional[List[str]] = None
working_directory: str = "~/transformers"
timeout :int = None

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we add a comment to mention what it is for?
(i.e. not to confuse the readers with pytest timeout and this timeout)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1. Alternatively, another var name like ci_timeout so the code is self documenting

Comment thread .circleci/create_circleci_config.py Outdated
},
],
tests_to_run="$(cat pr_documentation_tests.txt)",
pytest_options={"-doctest-modules":None, "doctest-glob":"*.mdx","dist":"loadfile", "rvsA":None},

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-doctest-modules seems incorrect and should be doctest-modules

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, the format should be better: spaces after : or ,

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doctest-modules alone doesn’t work, since it’s only adding a single -

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doctest-modules alone 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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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 :-)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do agree :-)

```

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:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💘



def preprocess_string(string, skip_cuda_tests):
codeblock_pattern = r"(```(?:python|py)\s*\n\s*>>> )((?:.*?\n)*?.*?```)"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably a docstring to explain a bit what this does

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1!

Comment thread src/transformers/utils/doctest_utils.py Outdated
] += f'from pytest import skip;skip("Codeblock line {line_num} uses `cuda`. Skipping" \
,allow_module_level=True);'
codeblocks = "".join(codeblocks)
return codeblocks

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some comments along the code lines would be appreciated.

@ArthurZucker

Copy link
Copy Markdown
Collaborator Author

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!
I’ll be off for a while, I leave this in your hands! 🤗🤗

@amyeroberts amyeroberts left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Comment thread .circleci/create_circleci_config.py Outdated
Comment thread .circleci/create_circleci_config.py Outdated
Comment thread .circleci/create_circleci_config.py Outdated
Comment thread .circleci/create_circleci_config.py Outdated
resource_class: Optional[str] = "xlarge"
tests_to_run: Optional[List[str]] = None
working_directory: str = "~/transformers"
timeout :int = None

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1. Alternatively, another var name like ci_timeout so the code is self documenting

Comment thread conftest.py Outdated


def preprocess_string(string, skip_cuda_tests):
codeblock_pattern = r"(```(?:python|py)\s*\n\s*>>> )((?:.*?\n)*?.*?```)"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1!

Comment thread src/transformers/utils/doctest_utils.py Outdated
Comment on lines +65 to +66
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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

load_dataset itself will print something, so we need # doctest: +IGNORE_RESULT when load_dataset is called.

Comment thread src/transformers/utils/doctest_utils.py Outdated
Comment thread .circleci/create_circleci_config.py Outdated

doc_test_job = CircleCIJob(
"pr_documentation_tests",
additional_env={"TRANSFORMERS_VERBOSITY":"error", "DATASETS_VERBOSITY":"error", "SKIP_CUDA_DOCTEST": "1"},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for my own understanding and doulbe checking - this means cuda docstests are skipped for the doc test job?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On circleCI only, which does not have GPU runners.

run: |
python3 utils/prepare_for_doc_test.py src docs

- name: Run doctests

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✨ so much cleaner ✨

@ydshieh

ydshieh commented May 3, 2023

Copy link
Copy Markdown
Collaborator

For info: I will take over this PR to try to merge it earlier.

@ydshieh
ydshieh marked this pull request as draft May 3, 2023 16:08
@ydshieh

ydshieh commented May 3, 2023

Copy link
Copy Markdown
Collaborator

Convert to draft for now, as more changes to deal with cuda is required.

Comment thread src/transformers/utils/doctest_utils.py Outdated
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:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous regular expression with re.match is just wrong.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and we also need to check ...

Comment on lines +53 to +67
modified_string = ""
if not is_cuda_found:
modified_string = "".join(codeblocks)
return modified_string

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see below

@ydshieh
ydshieh merged commit 627f447 into main May 9, 2023
@ydshieh
ydshieh deleted the doct-tests branch May 9, 2023 18:34
@ydshieh ydshieh mentioned this pull request May 9, 2023
sgugger added a commit that referenced this pull request May 9, 2023
sgugger added a commit that referenced this pull request May 9, 2023
Revert "[Doctests] Refactor doctests + add CI (#22987)"

This reverts commit 627f447.
sgugger added a commit that referenced this pull request May 9, 2023
Revert "[Doctests] Refactor doctests + add CI (#22987)"

This reverts commit 627f447.
gojiteji pushed a commit to gojiteji/transformers that referenced this pull request Jun 5, 2023
* 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]>
gojiteji pushed a commit to gojiteji/transformers that referenced this pull request Jun 5, 2023
Revert "[Doctests] Refactor doctests + add CI (huggingface#22987)"

This reverts commit 627f447.
novice03 pushed a commit to novice03/transformers that referenced this pull request Jun 23, 2023
* 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]>
novice03 pushed a commit to novice03/transformers that referenced this pull request Jun 23, 2023
Revert "[Doctests] Refactor doctests + add CI (huggingface#22987)"

This reverts commit 627f447.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants