From af8e90ae207604b4e704e069b78de6484f031bfe Mon Sep 17 00:00:00 2001 From: Gavin Uberti Date: Wed, 28 Dec 2022 11:42:50 -0800 Subject: [PATCH] Add sphinx_gallery flag for requiring CUDA Flag tutorials that require cuda Clarify docstring slightly Change position of requires_cuda config Allow other sphinx_gallery flags inside request hook Fix comments and admonition directives Fix microTVM install scripts --- apps/microtvm/requirements.txt | 53 ------------------- docs/conf.py | 50 +++++++++++++---- gallery/how_to/compile_models/from_keras.py | 1 + gallery/how_to/compile_models/from_mxnet.py | 1 + gallery/how_to/compile_models/from_oneflow.py | 1 + .../deploy_models/deploy_model_on_nano.py | 1 + .../extend_tvm/bring_your_own_datatypes.py | 2 +- .../optimize_operators/opt_conv_cuda.py | 1 + .../optimize_operators/opt_conv_tensorcore.py | 1 + .../tune_conv2d_layer_cuda.py | 1 + .../tune_with_autotvm/tune_conv2d_cuda.py | 1 + .../tune_with_autotvm/tune_relay_cuda.py | 1 + .../work_with_microtvm/install_cmsis.rst | 4 +- .../install_dependencies.rst | 11 ++-- .../work_with_microtvm/install_zephyr.rst | 6 +-- .../using_optimized_torch.py | 1 + .../how_to/work_with_relay/using_relay_viz.py | 7 +++ .../how_to/work_with_schedules/reduction.py | 1 + gallery/how_to/work_with_schedules/scan.py | 1 + gallery/tutorial/intro_topi.py | 1 + gallery/tutorial/relay_quick_start.py | 1 + gallery/tutorial/tensor_ir_blitz_course.py | 1 + tests/lint/check_request_hook.py | 35 ++++++++---- 23 files changed, 99 insertions(+), 84 deletions(-) delete mode 100644 apps/microtvm/requirements.txt diff --git a/apps/microtvm/requirements.txt b/apps/microtvm/requirements.txt deleted file mode 100644 index fa83c1ac9060..000000000000 --- a/apps/microtvm/requirements.txt +++ /dev/null @@ -1,53 +0,0 @@ -absl-py==1.3.0; python_version >= "3.7" -astunparse==1.6.3 -attrs==19.3.0; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.4.0") -cachetools==5.2.0; python_version >= "3.7" and python_version < "4.0" and (python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.7") -certifi==2022.12.7; python_version >= "3.7" and python_version < "4" -charset-normalizer==2.1.1; python_version >= "3.7" and python_version < "4" and python_full_version >= "3.6.0" -cloudpickle==1.6.0; python_version >= "3.5" -decorator==4.4.2; (python_version >= "2.6" and python_full_version < "3.0.0") or (python_full_version >= "3.2.0") -flatbuffers==2.0.7; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" and python_version < "4" -gast==0.4.0; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" -google-auth-oauthlib==0.4.6; python_version >= "3.7" -google-auth==2.15.0; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.7" -google-pasta==0.2.0 -grpcio==1.51.1; python_version >= "3.7" -h5py==3.7.0; python_version >= "3.7" -idna==3.4; python_version >= "3.7" and python_version < "4" -importlib-metadata==5.1.0; python_version < "3.10" and python_version >= "3.7" -keras-preprocessing==1.1.2 -keras==2.7.0 -libclang==14.0.6 -markdown==3.4.1; python_version >= "3.7" -markupsafe==2.1.1; python_version >= "3.7" -numpy==1.19.5; python_version >= "3.6" -oauthlib==3.2.2; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.7" -opt-einsum==3.3.0; python_version >= "3.5" -pillow==6.2.2; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0") -protobuf==3.19.6; python_version >= "3.7" -psutil==5.9.4; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.4.0") -pyasn1-modules==0.2.8; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.7" -pyasn1==0.4.8; python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4" and (python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.7") or python_full_version >= "3.6.0" and python_version >= "3.7" and python_version < "4" and (python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.7") -pyserial==3.5 -pyusb==1.2.1; python_full_version >= "3.6.0" -pyyaml==6.0; python_version >= "3.6" -requests-oauthlib==1.3.1; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.7" -requests==2.28.1; python_version >= "3.7" and python_version < "4" and (python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.7") -rsa==4.9; python_version >= "3.6" and python_version < "4" and (python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.7") -scipy==1.7.3; python_version >= "3.7" and python_version < "3.11" -six==1.16.0; python_version >= "3.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.7" -tensorboard-data-server==0.6.1; python_version >= "3.7" -tensorboard-plugin-wit==1.8.1; python_version >= "3.7" -tensorboard==2.11.0; python_version >= "3.7" -tensorflow-estimator==2.7.0 -tensorflow-io-gcs-filesystem==0.28.0; python_version >= "3.7" and python_version < "3.11" -tensorflow==2.7.4 -termcolor==2.1.1; python_version >= "3.7" -tflite==2.1.0; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.5.0" and python_version < "4") -tornado==6.2; python_version >= "3.7" -typed-ast==1.5.4; python_version >= "3.6" -typing-extensions==4.4.0; python_version < "3.8" and python_version >= "3.7" -urllib3==1.26.13; python_version >= "3.7" and python_full_version < "3.0.0" and python_version < "4" or python_version >= "3.7" and python_version < "4" and python_full_version >= "3.6.0" -werkzeug==2.2.2; python_version >= "3.7" -wrapt==1.14.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0" -zipp==3.11.0; python_version < "3.10" and python_version >= "3.7" diff --git a/docs/conf.py b/docs/conf.py index d517360fe34e..357df8cef12c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -38,8 +38,8 @@ from pathlib import Path import re import sys +from textwrap import dedent, indent from unittest.mock import patch -import textwrap # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -105,6 +105,21 @@ def decorator(function): return decorator +CURRENT_FILE_CONF = None + + +@monkey_patch("sphinx_gallery.py_source_parser", "split_code_and_text_blocks") +def split_code_and_text_blocks(source_file, return_node, real_func): + """Monkey-patch split_code_and_text_blocks to expose sphinx-gallery's file-level config. + + It's kinda gross, but we need access to file_conf to detect the requires_cuda flag. + """ + global CURRENT_FILE_CONF + file_conf, blocks, node = real_func(source_file, return_node) + CURRENT_FILE_CONF = file_conf + return (file_conf, blocks, node) + + # This header replaces the default sphinx-gallery one in sphinx_gallery/gen_rst.py. COLAB_HTML_HEADER = """ .. DO NOT EDIT. THIS FILE WAS AUTOMATICALLY GENERATED BY @@ -165,7 +180,9 @@ def save_rst_example(example_rst, example_file, time_elapsed, memory_used, galle INCLUDE_DIRECTIVE_RE = re.compile(r"^([ \t]*)\.\. include::\s*(.+)\n", flags=re.M) -COMMENT_DIRECTIVE_RE = re.compile(r"^\.\.(?: .*)?\n(?: .*\n)*", flags=re.M) +COMMENT_DIRECTIVE_RE = re.compile(r"^\.\.(?: .*)?\n(?:(?: .*)?\n)*", flags=re.M) +ADMONITION_DIRECTIVE_RE = re.compile(rf"^\.\. admonition:: *(.*)\n((?:(?: .*)?\n)*)\n", flags=re.M) + @monkey_patch("sphinx_gallery.notebook", "rst2md") def rst2md(text, gallery_conf, target_dir, heading_levels, real_func): @@ -174,20 +191,34 @@ def rst2md(text, gallery_conf, target_dir, heading_levels, real_func): Currently, only include directives without any parameters are supported. Also, note that in reStructuredText any unrecognized explicit markup block is treated as a comment (see https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html#comments). + + For callouts, we only replace generic "admonition" directives. All others should be replaced by + sphinx-gallery's rst2md. Note that the "alert" and "alert-info" tags are support in most IPython + notebooks, but they render kinda funky on Colab. """ def load_include(match): full_path = os.path.join(target_dir, match.group(2)) with open(full_path) as f: lines = f.read() - indented = textwrap.indent(lines, match.group(1)) + "\n" + indented = indent(lines, match.group(1)) + "\n" return indented text = re.sub(INCLUDE_DIRECTIVE_RE, load_include, text) - mostly_converted = real_func(text, gallery_conf, target_dir, heading_levels) - # All unrecognized directives are treated as comments and removed. - return re.sub(COMMENT_DIRECTIVE_RE, "", text) + # Replace generic, titled admonitions with indented text. Other admonitions (e.g. .. note::) + # will be handled by sphinx-gallery's + def rewrite_generic_admonition(match): + title, text = match.groups() + stripped_text = dedent(text).strip() + return f'

{title}

{stripped_text}

' + + text = re.sub(ADMONITION_DIRECTIVE_RE, rewrite_generic_admonition, text) + + # Call the real function, and then strip any remaining directives (i.e. comments) + text = real_func(text, gallery_conf, target_dir, heading_levels) + text = re.sub(COMMENT_DIRECTIVE_RE, "", text) + return text INSTALL_TVM_DEV = f"""\ @@ -218,7 +249,6 @@ def load_include(match): # source, see see https://tvm.apache.org/docs/install/from_source.html pip install apache-tvm-cu113=={version} -f https://tlcpack.ai/wheels""" -CUDA_FUNC_CALL_RE = re.compile(r"cuda\([0-9]*\)", re.IGNORECASE) @monkey_patch("sphinx_gallery.gen_rst", "jupyter_notebook") def jupyter_notebook(script_blocks, gallery_conf, target_dir, real_func): @@ -228,11 +258,11 @@ def jupyter_notebook(script_blocks, gallery_conf, target_dir, real_func): However, how we import TVM depends on if we are using a fixed or dev version, and whether we will use the GPU. - We install a CUDA version of TVM if and only if the tutorial calls "cuda" as a function. It - would be cleaner specify this with a config flag, but sphinx-gallery does not support this. + Tutorials requiring a CUDA-enabled build of TVM should use the flag: + # sphinx_gallery_requires_cuda = True """ - requires_cuda = any(CUDA_FUNC_CALL_RE.search(block[1]) for block in script_blocks) + requires_cuda = CURRENT_FILE_CONF.get("requires_cuda", False) fixed_version = not "dev" in version if fixed_version and requires_cuda: diff --git a/gallery/how_to/compile_models/from_keras.py b/gallery/how_to/compile_models/from_keras.py index 41929d3d5b86..ac961ca16ad0 100644 --- a/gallery/how_to/compile_models/from_keras.py +++ b/gallery/how_to/compile_models/from_keras.py @@ -36,6 +36,7 @@ """ # sphinx_gallery_start_ignore +# sphinx_gallery_requires_cuda = True from tvm import testing testing.utils.install_request_hook(depth=3) diff --git a/gallery/how_to/compile_models/from_mxnet.py b/gallery/how_to/compile_models/from_mxnet.py index e216b8e4b9c7..cfd66ecdb74c 100644 --- a/gallery/how_to/compile_models/from_mxnet.py +++ b/gallery/how_to/compile_models/from_mxnet.py @@ -34,6 +34,7 @@ """ # sphinx_gallery_start_ignore +# sphinx_gallery_requires_cuda = True from tvm import testing testing.utils.install_request_hook(depth=3) diff --git a/gallery/how_to/compile_models/from_oneflow.py b/gallery/how_to/compile_models/from_oneflow.py index 4ba65e755c5d..0925c9fe81ce 100644 --- a/gallery/how_to/compile_models/from_oneflow.py +++ b/gallery/how_to/compile_models/from_oneflow.py @@ -38,6 +38,7 @@ """ # sphinx_gallery_start_ignore +# sphinx_gallery_requires_cuda = True from tvm import testing testing.utils.install_request_hook(depth=3) diff --git a/gallery/how_to/deploy_models/deploy_model_on_nano.py b/gallery/how_to/deploy_models/deploy_model_on_nano.py index 5e59dccf205d..3d8a4a796f8c 100644 --- a/gallery/how_to/deploy_models/deploy_model_on_nano.py +++ b/gallery/how_to/deploy_models/deploy_model_on_nano.py @@ -26,6 +26,7 @@ """ # sphinx_gallery_start_ignore +# sphinx_gallery_requires_cuda = True from tvm import testing testing.utils.install_request_hook(depth=3) diff --git a/gallery/how_to/extend_tvm/bring_your_own_datatypes.py b/gallery/how_to/extend_tvm/bring_your_own_datatypes.py index 479269a224a3..bbd207dbac8b 100644 --- a/gallery/how_to/extend_tvm/bring_your_own_datatypes.py +++ b/gallery/how_to/extend_tvm/bring_your_own_datatypes.py @@ -47,7 +47,7 @@ If you would like to try this with your own datatype library, first bring the library's functions into the process space with ``CDLL``: -.. code-block :: python +.. code-block:: python ctypes.CDLL('my-datatype-lib.so', ctypes.RTLD_GLOBAL) """ diff --git a/gallery/how_to/optimize_operators/opt_conv_cuda.py b/gallery/how_to/optimize_operators/opt_conv_cuda.py index e5b452af66a9..33e5d9855361 100644 --- a/gallery/how_to/optimize_operators/opt_conv_cuda.py +++ b/gallery/how_to/optimize_operators/opt_conv_cuda.py @@ -31,6 +31,7 @@ """ # sphinx_gallery_start_ignore +# sphinx_gallery_requires_cuda = True from tvm import testing testing.utils.install_request_hook(depth=3) diff --git a/gallery/how_to/optimize_operators/opt_conv_tensorcore.py b/gallery/how_to/optimize_operators/opt_conv_tensorcore.py index 8db20b9b9bf8..5734f064f0dc 100644 --- a/gallery/how_to/optimize_operators/opt_conv_tensorcore.py +++ b/gallery/how_to/optimize_operators/opt_conv_tensorcore.py @@ -52,6 +52,7 @@ # NHWCnc memory layout.The following code defines the convolution algorithm in TVM. # sphinx_gallery_start_ignore +# sphinx_gallery_requires_cuda = True from tvm import testing testing.utils.install_request_hook(depth=3) diff --git a/gallery/how_to/tune_with_autoscheduler/tune_conv2d_layer_cuda.py b/gallery/how_to/tune_with_autoscheduler/tune_conv2d_layer_cuda.py index 5d173e38128e..7964694e68c0 100644 --- a/gallery/how_to/tune_with_autoscheduler/tune_conv2d_layer_cuda.py +++ b/gallery/how_to/tune_with_autoscheduler/tune_conv2d_layer_cuda.py @@ -38,6 +38,7 @@ """ # sphinx_gallery_start_ignore +# sphinx_gallery_requires_cuda = True from tvm import testing testing.utils.install_request_hook(depth=3) diff --git a/gallery/how_to/tune_with_autotvm/tune_conv2d_cuda.py b/gallery/how_to/tune_with_autotvm/tune_conv2d_cuda.py index 4560cf881ed8..a73b97525f12 100644 --- a/gallery/how_to/tune_with_autotvm/tune_conv2d_cuda.py +++ b/gallery/how_to/tune_with_autotvm/tune_conv2d_cuda.py @@ -49,6 +49,7 @@ # Now return to python code. Import packages. # sphinx_gallery_start_ignore +# sphinx_gallery_requires_cuda = True from tvm import testing testing.utils.install_request_hook(depth=3) diff --git a/gallery/how_to/tune_with_autotvm/tune_relay_cuda.py b/gallery/how_to/tune_with_autotvm/tune_relay_cuda.py index 4cf397e2567e..7cb6cb8dd3f9 100644 --- a/gallery/how_to/tune_with_autotvm/tune_relay_cuda.py +++ b/gallery/how_to/tune_with_autotvm/tune_relay_cuda.py @@ -60,6 +60,7 @@ # Now return to python code. Import packages. # sphinx_gallery_start_ignore +# sphinx_gallery_requires_cuda = True from tvm import testing testing.utils.install_request_hook(depth=3) diff --git a/gallery/how_to/work_with_microtvm/install_cmsis.rst b/gallery/how_to/work_with_microtvm/install_cmsis.rst index f1c0cd1b39ab..2f1d2fb1189a 100644 --- a/gallery/how_to/work_with_microtvm/install_cmsis.rst +++ b/gallery/how_to/work_with_microtvm/install_cmsis.rst @@ -6,9 +6,9 @@ "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at -.. http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 -.. Unless required by applicable law or agreed to in writing, + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the diff --git a/gallery/how_to/work_with_microtvm/install_dependencies.rst b/gallery/how_to/work_with_microtvm/install_dependencies.rst index 880b5ae625fb..d1bee4176d94 100644 --- a/gallery/how_to/work_with_microtvm/install_dependencies.rst +++ b/gallery/how_to/work_with_microtvm/install_dependencies.rst @@ -6,9 +6,9 @@ "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at -.. http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 -.. Unless required by applicable law or agreed to in writing, + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the @@ -23,8 +23,11 @@ Install microTVM Python dependencies ------------------------------------ +TVM does not include a package for Python serial communication, so +we must install one before using microTVM. We will also need TFLite +to load models. + .. code-block:: bash %%shell - wget https://github.com/guberti/tvm/raw/hackathon/tutorials/apps/microtvm/requirements.txt - pip install -r requirements.txt + pip install pyserial==3.5 tflite==2.1 diff --git a/gallery/how_to/work_with_microtvm/install_zephyr.rst b/gallery/how_to/work_with_microtvm/install_zephyr.rst index 489ece974544..a4c412f0f746 100644 --- a/gallery/how_to/work_with_microtvm/install_zephyr.rst +++ b/gallery/how_to/work_with_microtvm/install_zephyr.rst @@ -6,9 +6,9 @@ "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at -.. http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 -.. Unless required by applicable law or agreed to in writing, + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the @@ -46,7 +46,7 @@ Install Zephyr wget --no-verbose -O $ZEPHYR_SDK_FILE \ https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v${ZEPHYR_SDK_VERSION}/zephyr-sdk-${ZEPHYR_SDK_VERSION}-linux-x86_64-setup.run chmod +x $ZEPHYR_SDK_FILE - "$ZEPHYR_SDK_FILE" -- -d /content/zephyr-sdk + "$ZEPHYR_SDK_FILE" -- -d /content/zephyr-sdk --quiet # Install python dependencies python3 -m pip install -r "${ZEPHYR_BASE}/scripts/requirements.txt" diff --git a/gallery/how_to/work_with_pytorch/using_optimized_torch.py b/gallery/how_to/work_with_pytorch/using_optimized_torch.py index bc449d84137c..baf80541b964 100644 --- a/gallery/how_to/work_with_pytorch/using_optimized_torch.py +++ b/gallery/how_to/work_with_pytorch/using_optimized_torch.py @@ -32,6 +32,7 @@ """ # sphinx_gallery_start_ignore +# sphinx_gallery_requires_cuda = True from tvm import testing testing.utils.install_request_hook(depth=3) diff --git a/gallery/how_to/work_with_relay/using_relay_viz.py b/gallery/how_to/work_with_relay/using_relay_viz.py index 2e68ce902899..ae22fe20e1f2 100644 --- a/gallery/how_to/work_with_relay/using_relay_viz.py +++ b/gallery/how_to/work_with_relay/using_relay_viz.py @@ -32,6 +32,13 @@ Here we use a renderer rendering graph in the text-form. It is a lightweight, AST-like visualizer, inspired by `clang ast-dump `_. We will introduce how to implement customized parsers and renderers through interface classes. +To install dependencies, run: + +.. code-block:: bash + + %%shell + pip install graphviz + For more details, please refer to :py:mod:`tvm.contrib.relay_viz`. """ diff --git a/gallery/how_to/work_with_schedules/reduction.py b/gallery/how_to/work_with_schedules/reduction.py index 432e9cd143b1..c084c45d3839 100644 --- a/gallery/how_to/work_with_schedules/reduction.py +++ b/gallery/how_to/work_with_schedules/reduction.py @@ -29,6 +29,7 @@ # sphinx_gallery_start_ignore +# sphinx_gallery_requires_cuda = True from tvm import testing testing.utils.install_request_hook(depth=3) diff --git a/gallery/how_to/work_with_schedules/scan.py b/gallery/how_to/work_with_schedules/scan.py index d21673acd9e4..d523d5b9959d 100644 --- a/gallery/how_to/work_with_schedules/scan.py +++ b/gallery/how_to/work_with_schedules/scan.py @@ -26,6 +26,7 @@ # sphinx_gallery_start_ignore +# sphinx_gallery_requires_cuda = True from tvm import testing testing.utils.install_request_hook(depth=3) diff --git a/gallery/tutorial/intro_topi.py b/gallery/tutorial/intro_topi.py index e10a74c849c0..f2a4db608646 100644 --- a/gallery/tutorial/intro_topi.py +++ b/gallery/tutorial/intro_topi.py @@ -27,6 +27,7 @@ """ # sphinx_gallery_start_ignore +# sphinx_gallery_requires_cuda = True from tvm import testing testing.utils.install_request_hook(depth=3) diff --git a/gallery/tutorial/relay_quick_start.py b/gallery/tutorial/relay_quick_start.py index 8910817c2117..e59f0107f943 100644 --- a/gallery/tutorial/relay_quick_start.py +++ b/gallery/tutorial/relay_quick_start.py @@ -27,6 +27,7 @@ """ # sphinx_gallery_start_ignore +# sphinx_gallery_requires_cuda = True from tvm import testing testing.utils.install_request_hook(depth=3) diff --git a/gallery/tutorial/tensor_ir_blitz_course.py b/gallery/tutorial/tensor_ir_blitz_course.py index a62fa3979393..dc75a3fb9452 100644 --- a/gallery/tutorial/tensor_ir_blitz_course.py +++ b/gallery/tutorial/tensor_ir_blitz_course.py @@ -30,6 +30,7 @@ """ # sphinx_gallery_start_ignore +# sphinx_gallery_requires_cuda = True from tvm import testing testing.utils.install_request_hook(depth=3) diff --git a/tests/lint/check_request_hook.py b/tests/lint/check_request_hook.py index 35b1a85c3a43..925af5597c12 100644 --- a/tests/lint/check_request_hook.py +++ b/tests/lint/check_request_hook.py @@ -23,13 +23,27 @@ REPO_ROOT = Path(__file__).resolve().parent.parent.parent -EXPECTED = """ + +EXPECTED_HOOK = """ # sphinx_gallery_start_ignore from tvm import testing -testing.utils.install_request_hook(depth=3) +testing.utils.install_request_hook(depth=3)\ # sphinx_gallery_end_ignore -""".rstrip() +""" + +# Extra sphinx-gallery config options may be passed inside the ignore block before the hook. This +# is a workaround that can be removed once sphinx-gallery #1059 merges and the version is updated. +EXPECTED_REGEX = re.compile( + r""" +\# sphinx_gallery_start_ignore +(?:.*\n)*from tvm import testing + +testing\.utils\.install_request_hook\(depth=3\)\ +\# sphinx_gallery_end_ignore +""".rstrip(), + re.MULTILINE, +) IGNORE_PATTERNS = ["*/micro_tvmc.py", "*/micro_train.py"] APACHE_HEADER_LINES = 16 @@ -84,14 +98,13 @@ def find_code_block_line(lines: List[str]) -> Optional[int]: with open(file) as f: content = f.read() - if EXPECTED not in content: + regex_match = EXPECTED_REGEX.search(content) + if not regex_match: errors.append((file, None)) continue - index = content.index(EXPECTED) - line = content.count("\n", 0, index) + EXPECTED.count("\n") + 2 + line = content.count("\n", 0, regex_match.end()) + 2 expected = find_code_block_line(content.split("\n")) - if expected is not None and line < expected: errors.append((file, (line, expected))) @@ -106,19 +119,19 @@ def find_code_block_line(lines: List[str]) -> Optional[int]: if "from __future__" in content: # Place after the last __future__ import new_content = re.sub( - r"((?:from __future__.*?\n)+)", r"\1\n" + EXPECTED, content, flags=re.MULTILINE + r"((?:from __future__.*?\n)+)", r"\1\n" + EXPECTED_HOOK, content, flags=re.M ) else: # Place in the first codeblock lines = content.split("\n") position = find_code_block_line(lines) if position is None: - new_content = "\n".join(lines) + EXPECTED + "\n" + new_content = "\n".join(lines) + EXPECTED_HOOK + "\n" else: print(position) new_content = ( "\n".join(lines[:position]) - + EXPECTED + + EXPECTED_HOOK + "\n\n" + "\n".join(lines[position:]) ) @@ -134,7 +147,7 @@ def find_code_block_line(lines: List[str]) -> Optional[int]: "the whitespace is incorrect.\n" "You can run 'python3 tests/lint/check_request_hook.py --fix' to " "automatically fix these errors:\n" - f"{EXPECTED}\n\nFiles:" + f"{EXPECTED_HOOK}\n\nFiles:" ) for file, line_info in errors: if line_info is None: