-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdoctest.bzl
74 lines (63 loc) · 1.79 KB
/
doctest.bzl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# Adapted from https://github.com/1e100/bazel_doctest/tree/master
"""Implements Python doctest support for Bazel."""
load("@rules_python//python:defs.bzl", "py_test")
DOCTEST_TPL = r"""
import doctest, unittest
def load_tests(loader, tests, ignore):
{}
return tests
if __name__ == "__main__":
unittest.main()
"""
# TODO: Make `ELLIPSIS` optional?
ADD_TESTS_TPL = r" tests.addTests(doctest.DocTestSuite('{}', optionflags=doctest.ELLIPSIS))"
def _file_to_module(file):
if file.basename == "__init__.py":
path = file.dirname
else:
path = file.path[:-len(file.extension) - 1]
return path.replace("/", ".")
def _impl(ctx):
modules = []
for src in ctx.attr.srcs:
modules.extend([
ADD_TESTS_TPL.format(_file_to_module(file))
for file in src.files.to_list()
])
runner = ctx.actions.declare_file(ctx.attr.name)
content = DOCTEST_TPL.format("\n".join(modules))
ctx.actions.write(
runner,
content = content,
)
return [
DefaultInfo(files = depset([runner])),
]
_runner = rule(
implementation = _impl,
attrs = {
"srcs": attr.label_list(
mandatory = True,
providers = [DefaultInfo],
doc = "List of Python targets potentially containing doctests.",
),
},
)
# Deliberately using the required _test convention
# so that this is easy to search for.
def py_doc_test(name, srcs, deps = [], **kwargs):
runner_py = name + "-doctest-runner.py"
_runner(
name = runner_py,
srcs = srcs,
testonly = True,
)
py_test(
name = name,
srcs = [runner_py],
deps = srcs + deps,
main = runner_py,
legacy_create_init = False,
python_version = "PY3",
**kwargs
)