diff --git a/python/unittest_py/requirements.txt b/python/unittest_py/requirements.txt index dd353bb7f4827337791ea9d6a04fe3dc18e9f1db..e29dcf6c294462dbf27222190bfd0e26273031a7 100644 --- a/python/unittest_py/requirements.txt +++ b/python/unittest_py/requirements.txt @@ -18,3 +18,4 @@ parameterized wandb>=0.13 xlsxwriter==3.0.9 xdoctest +ubelt # just for xdoctest diff --git a/tools/sampcd_processor_utils.py b/tools/sampcd_processor_utils.py index 0d59da7cc1e1a2f45186c1c88048715f508fb8c9..f5983f8d5a346e63a7790293acc9fbcf37f11e30 100644 --- a/tools/sampcd_processor_utils.py +++ b/tools/sampcd_processor_utils.py @@ -13,7 +13,7 @@ # limitations under the License. import argparse -import collections +import dataclasses import inspect import logging import os @@ -42,20 +42,17 @@ API_DIFF_SPEC_FN = 'dev_pr_diff_api.spec' TEST_TIMEOUT = 10 -TestResult = collections.namedtuple( - "TestResult", - ( - "name", - "nocode", - "passed", - "skipped", - "failed", - "time", - "test_msg", - "extra_info", - ), - defaults=(None, False, False, False, False, -1, "", None), -) +@dataclasses.dataclass +class TestResult: + name: str + nocode: bool = False + passed: bool = False + skipped: bool = False + failed: bool = False + timeout: bool = False + time: float = float('inf') + test_msg: str = "" + extra_info: str = "" class DocTester: @@ -76,18 +73,20 @@ class DocTester: If the `style` is set to `google` and `target` is set to `codeblock`, we should implement/overwrite `ensemble_docstring` method, where ensemble the codeblock into a docstring with a `Examples:` and some indents as least. directives(list[str]): `DocTester` hold the default directives, we can/should replace them with method `convert_directive`. + For example: + ``` text + # doctest: +SKIP + # doctest: +REQUIRES(env:CPU) + # doctest: +REQUIRES(env:GPU) + # doctest: +REQUIRES(env:XPU) + # doctest: +REQUIRES(env:DISTRIBUTED) + # doctest: +REQUIRES(env:GPU, env:XPU) + ``` """ style = 'google' target = 'docstring' - directives = [ - "# doctest: +SKIP", - "# doctest: +REQUIRES(env:CPU)", - "# doctest: +REQUIRES(env:GPU)", - "# doctest: +REQUIRES(env:XPU)", - "# doctest: +REQUIRES(env:DISTRIBUTED)", - "# doctest: +REQUIRES(env:GPU, env:XPU)", - ] + directives = None def ensemble_docstring(self, codeblock: str) -> str: """Ensemble a cleaned codeblock into a docstring. diff --git a/tools/sampcd_processor_xdoctest.py b/tools/sampcd_processor_xdoctest.py index 62e84ab914a8303e63d5239493796ba0449db61b..10459dc99799e152a26ea67c536dceb18073b2d7 100644 --- a/tools/sampcd_processor_xdoctest.py +++ b/tools/sampcd_processor_xdoctest.py @@ -24,10 +24,13 @@ for example, you can run cpu version testing like this: import functools import logging +import multiprocessing import os import platform +import queue import re import sys +import threading import time import typing @@ -168,9 +171,62 @@ def _patch_float_precision(digits): checker.check_output = check_output +class Directive: + """Base class of global direvtives just for `xdoctest`.""" + + pattern: typing.Pattern + + def parse_directive(self, docstring: str) -> typing.Tuple[str, typing.Any]: + pass + + +class TimeoutDirective(Directive): + pattern = re.compile( + r""" + (?: + (?: + \s*\>{3}\s*\#\s*x?doctest\:\s* + ) + (?P[\+\-]) + (?: + TIMEOUT + ) + \( + (?P