load("//tools/lint:lint.bzl", "add_lint_tests")
load(
    "//tools/lint:python_lint.bzl",
    "PYTHON_LINT_IGNORE_DEFAULT",
    "python_lint",
)
load(
    "//tools/skylark:drake_py.bzl",
    "drake_py_binary",
    "drake_py_library",
    "drake_py_unittest",
)

package(default_visibility = ["//visibility:public"])

drake_py_library(
    name = "module_py",
    srcs = ["__init__.py"],
    deps = ["//tools:module_py"],
)

# TODO(jwnimmer-tri) This probably deserves to live in drake/common, since it
# should probably be widely used, but we'll wait until we have more evidence
# before promoting it.
drake_py_library(
    name = "find_data",
    srcs = ["find_data.py"],
    deps = [
        ":module_py",
    ],
)

drake_py_library(
    name = "util",
    srcs = ["util.py"],
    data = ["//:.bazelproject"],
    visibility = ["//visibility:private"],
    deps = [
        ":module_py",
    ],
)

drake_py_binary(
    name = "buildifier",
    srcs = ["buildifier.py"],
    data = [
        ":buildifier-tables.json",
        "@buildifier",
    ],
    deps = [
        ":find_data",
        ":module_py",
        ":util",
    ],
)

drake_py_library(
    name = "clang_format",
    testonly = 1,
    srcs = ["clang_format.py"],
    data = ["//:.clang-format"],
    deps = [
        ":module_py",
    ],
)

drake_py_binary(
    name = "clang_format_lint",
    testonly = 1,
    srcs = ["clang_format_lint.py"],
    deps = [
        ":clang_format",
        ":module_py",
    ],
)

drake_py_binary(
    name = "drakelint",
    testonly = 1,
    srcs = ["drakelint.py"],
    deps = [
        ":formatter",
        ":module_py",
    ],
)

drake_py_binary(
    name = "bzlcodestyle",
    srcs = ["bzlcodestyle.py"],
    main = "bzlcodestyle.py",
    deps = [
        ":module_py",
        "@pycodestyle",
    ],
)

drake_py_library(
    name = "formatter",
    testonly = 1,
    srcs = ["formatter.py"],
    deps = [":clang_format"],
)

drake_py_binary(
    name = "clang-format-includes",
    testonly = 1,
    srcs = ["clang_format_includes.py"],
    main = "clang_format_includes.py",
    deps = [
        ":formatter",
        ":module_py",
        ":util",
    ],
)

drake_py_binary(
    name = "install_lint_reporter",
    testonly = 1,
    srcs = ["install_lint_reporter.py"],
    deps = [
        ":module_py",
    ],
)

drake_py_binary(
    name = "library_lint_reporter",
    testonly = 1,
    srcs = ["library_lint_reporter.py"],
    deps = [
        ":module_py",
    ],
)

# === test ===

drake_py_unittest(
    name = "buildifier_test",
    data = [":buildifier"],
)

drake_py_unittest(
    name = "find_data_test",
    data = ["test/find_data_test.txt"],
    deps = [":find_data"],
)

drake_py_unittest(
    name = "util_test",
    tags = [
        # This test's pass/fail result depends on the presence of files in the
        # source tree beyond what is declared in its `deps`; thus, we need to
        # re-run the test anytime the source tree might have changed, for which
        # "external" is the closest semantic match.
        "external",
        # This test looks outside the sandbox.
        "no-sandbox",
    ],
    deps = [":util"],
)

drake_py_unittest(
    name = "formatter_test",
    deps = [":formatter"],
)

sh_test(
    name = "clang_format_includes_test",
    size = "small",
    srcs = ["test/clang_format_includes_test.sh"],
    data = [
        ":clang-format-includes",
    ],
    # Valgrind Memcheck reports numerous leaks in the python executable.
    tags = ["no_memcheck"],
)

# Exercise `ignore` for `python_lint`.
python_lint(
    existing_rules = [],
    extra_srcs = ["test/python_lint_ignore_example.py"],
    ignore = ["E402"],
)

add_lint_tests()
