diff --git a/tools/build_rules/prelude_bazel b/tools/build_rules/prelude_bazel index c6037e7..4d8b204 100644 --- a/tools/build_rules/prelude_bazel +++ b/tools/build_rules/prelude_bazel @@ -6,6 +6,7 @@ load("//tools/python:defs.bzl", "py_unittest", "py_pytest", "py_resources", + "py_project", ) load("@arrdem_source_pypi//:requirements.bzl", diff --git a/tools/python/defs.bzl b/tools/python/defs.bzl index 6239f23..929daf8 100644 --- a/tools/python/defs.bzl +++ b/tools/python/defs.bzl @@ -10,102 +10,102 @@ load("@rules_python//python:defs.bzl", def py_requirement(*args, **kwargs): - """A re-export of requirement()""" - return _py_requirement(*args, **kwargs) + """A re-export of requirement()""" + return _py_requirement(*args, **kwargs) def py_test(python_version=None, **kwargs): - """A re-export of py_test()""" + """A re-export of py_test()""" - if python_version and python_version != "PY3": - fail("py3k only!") + if python_version and python_version != "PY3": + fail("py3k only!") - return _py_test( - python_version="PY3", - **kwargs, - ) + return _py_test( + python_version="PY3", + **kwargs, + ) def py_pytest(name, srcs, deps, main=None, python_version=None, args=None, **kwargs): - """A py_test target which uses pytest.""" + """A py_test target which uses pytest.""" - if python_version and python_version != "PY3": - fail("py3k only!") + if python_version and python_version != "PY3": + fail("py3k only!") - f = "//tools/python:bzl_pytest_shim.py" + f = "//tools/python:bzl_pytest_shim.py" - deps = [ - py_requirement("pytest"), - py_requirement("jedi"), - py_requirement("pytest-pudb"), - ] + deps + deps = [ + py_requirement("pytest"), + py_requirement("jedi"), + py_requirement("pytest-pudb"), + ] + deps - srcs = [f] + srcs + srcs = [f] + srcs - t = py_test( - name = name, - srcs = srcs, - main = f, - args = args, - python_version="PY3", - deps = deps, - **kwargs, - ) + t = py_test( + name = name, + srcs = srcs, + main = f, + args = args, + python_version="PY3", + deps = deps, + **kwargs, + ) - # FIXME (arrdem 2020-09-27): - # This really needs to be a py_image_test. - # Not clear how to achieve that. - # py_image( - # name = name + ".containerized", - # main = f, - # args = args, - # srcs = srcs, - # deps = deps, - # **kwargs, - # ) + # FIXME (arrdem 2020-09-27): + # This really needs to be a py_image_test. + # Not clear how to achieve that. + # py_image( + # name = name + ".containerized", + # main = f, + # args = args, + # srcs = srcs, + # deps = deps, + # **kwargs, + # ) - return t + return t def py_unittest(srcs=[], **kwargs): - """A helper for running unittest tests""" + """A helper for running unittest tests""" - f = "//tools/python:bzl_unittest_shim.py" - return py_test( - main = f, - srcs = [f] + srcs, - **kwargs - ) + f = "//tools/python:bzl_unittest_shim.py" + return py_test( + main = f, + srcs = [f] + srcs, + **kwargs + ) def py_binary(python_version=None, main=None, srcs=None, **kwargs): - """A re-export of py_binary()""" + """A re-export of py_binary()""" - if python_version and python_version != "PY3": - fail("py3k only!") + if python_version and python_version != "PY3": + fail("py3k only!") - srcs = srcs or [] - if main not in srcs: - srcs = [main] + srcs + srcs = srcs or [] + if main not in srcs: + srcs = [main] + srcs - return _py_binary( - python_version = "PY3", - main = main, - srcs = srcs, - **kwargs, - ) + return _py_binary( + python_version = "PY3", + main = main, + srcs = srcs, + **kwargs, + ) def py_library(srcs_version=None, **kwargs): - """A re-export of py_library()""" + """A re-export of py_library()""" - if srcs_version and srcs_version != "PY3": - fail("py3k only!") + if srcs_version and srcs_version != "PY3": + fail("py3k only!") - return _py_library( - srcs_version="PY3", - **kwargs - ) + return _py_library( + srcs_version="PY3", + **kwargs + ) ResourceGroupInfo = provider( @@ -144,3 +144,37 @@ py_resources = rule( ), }, ) + +def py_project(name=None, + lib_srcs=None, + lib_deps=None, + test_srcs=None, + test_deps=None): + """ + A helper for defining conventionally-formatted python project. + + Assumes that there's a src/python tree, and a src/test tree. + + Each test_*.py source generates its own implicit test target. This allows + for automatic test parallelism. + + """ + + lib_srcs = lib_srcs or native.glob(["src/python/**/*.py"]) + test_srcs = test_srcs or native.glob(["test/python/**/*.py"]) + + py_library( + name=name, + srcs=lib_srcs, + deps=lib_deps, + imports=["src/python"], + ) + + for src in test_srcs: + if "test_" in src: + py_pytest( + name=name + ".test." + str(hash(src)).replace("-", "") + "." + src.split("/")[-1], + srcs=test_srcs, + deps=[name] + test_deps, + imports=["test/python"], + )