Compare commits

..

15 commits

279 changed files with 454 additions and 158 deletions

View file

@ -1 +0,0 @@
USE_BAZEL_VERSION=6.2.0

View file

@ -1,4 +1,9 @@
common --curses=auto
common --show_timestamps=true
test --keep_going
test --test_output=errors test --test_output=errors
test --test_tag_filters=-known-to-fail
# To enable flake8 on all build steps, uncomment this - # To enable flake8 on all build steps, uncomment this -
# test --aspects="//tools/flake8:flake8.bzl%flake8_aspect" --output_groups=flake8_checks # test --aspects="//tools/flake8:flake8.bzl%flake8_aspect" --output_groups=flake8_checks

1
.bazelversion Normal file
View file

@ -0,0 +1 @@
7.0.0

2
.envrc Normal file
View file

@ -0,0 +1,2 @@
export SOURCE=$(dirname $(realpath $0))
export PATH="${SOURCE}/bin:$PATH"

1
.gitignore vendored
View file

@ -24,3 +24,4 @@ tmp/
/**/*.sqlite* /**/*.sqlite*
/**/config*.toml /**/config*.toml
/**/config*.yml /**/config*.yml
MODULE.bazel.lock

View file

6
MODULE.bazel Normal file
View file

@ -0,0 +1,6 @@
###############################################################################
# Bazel now uses Bzlmod by default to manage external dependencies.
# Please consider migrating your external dependencies from WORKSPACE to MODULE.bazel.
#
# For more details, please check https://github.com/bazelbuild/bazel/issues/18958
###############################################################################

View file

@ -62,76 +62,14 @@ load("@arrdem_source_pypi//:requirements.bzl", "install_deps")
# Call it to define repos for your requirements. # Call it to define repos for your requirements.
install_deps() install_deps()
git_repository( # git_repository(
name = "rules_zapp", # name = "rules_zapp",
remote = "https://git.arrdem.com/arrdem/rules_zapp.git", # remote = "https://git.arrdem.com/arrdem/rules_zapp.git",
commit = "961be891e5cff539e14f2050d5cd9e82845ce0f2", # commit = "961be891e5cff539e14f2050d5cd9e82845ce0f2",
# tag = "0.1.2", # # tag = "0.1.2",
)
# local_repository(
# name = "rules_zapp",
# path = "/home/arrdem/Documents/hobby/programming/lang/python/rules_zapp",
# ) # )
#################################################################################################### local_repository(
# Docker support name = "rules_zapp",
#################################################################################################### path = "/home/arrdem/Documents/hobby/programming/lang/python/rules_zapp",
http_archive(
name = "io_bazel_rules_docker",
sha256 = "b1e80761a8a8243d03ebca8845e9cc1ba6c82ce7c5179ce2b295cd36f7e394bf",
urls = ["https://github.com/bazelbuild/rules_docker/releases/download/v0.25.0/rules_docker-v0.25.0.tar.gz"],
)
load("@io_bazel_rules_docker//toolchains/docker:toolchain.bzl",
docker_toolchain_configure="toolchain_configure"
)
docker_toolchain_configure(
name = "docker_config",
docker_flags = [
],
)
load(
"@io_bazel_rules_docker//repositories:repositories.bzl",
container_repositories = "repositories",
)
container_repositories()
load(
"@io_bazel_rules_docker//repositories:deps.bzl",
container_deps = "deps"
)
container_deps()
load(
"@io_bazel_rules_docker//container:container.bzl",
"container_pull",
)
# container_pull(
# name = "python_base",
# registry = "index.docker.io",
# repository = "library/python",
# tag = "3.10.8-alpine"
# # sha256 = "digest:d78a749034380426dd6cec6a0db139459ca701630533ffce112adbcdd996fddd",
# )
# container_pull(
# name = "python_base",
# registry = "gcr.io",
# repository = "distroless/python3-debian11",
# tag = "latest"
# # sha256 = "digest:d78a749034380426dd6cec6a0db139459ca701630533ffce112adbcdd996fddd",
# )
container_pull(
name = "python_base",
registry = "index.docker.io",
repository = "library/python",
tag = "3.11-buster"
# sha256 = "digest:d78a749034380426dd6cec6a0db139459ca701630533ffce112adbcdd996fddd",
) )

2
bin/bazel Executable file
View file

@ -0,0 +1,2 @@
#!/bin/sh
exec "${SOURCE}/projects/bazelshim/src/bazelshim/__main__.py" --bazelshim_exclude="$(realpath "${SOURCE}")/bin" "$@"

2
bin/bazelisk Executable file
View file

@ -0,0 +1,2 @@
#!/bin/sh
exec "${SOURCE}/projects/bazelshim/src/bazelshim/__main__.py" --bazelshim_exclude="$(realpath "${SOURCE}")/bin" "$@"

View file

@ -10,6 +10,6 @@ py_project(
py_requirement("pyyaml"), py_requirement("pyyaml"),
py_requirement("retry"), py_requirement("retry"),
], ],
main = "src/python/relay/__main__.py", main = "src/relay/__main__.py",
shebang = "/usr/bin/env python3" shebang = "/usr/bin/env python3"
) )

View file

@ -4,7 +4,7 @@ py_project(
zapp_binary( zapp_binary(
name = "aloe", name = "aloe",
main = "src/python/aloe/__main__.py", main = "src/aloe/__main__.py",
deps = [ deps = [
":lib", ":lib",
py_requirement("icmplib"), py_requirement("icmplib"),

View file

@ -15,5 +15,6 @@ zapp_binary(
deps = [ deps = [
py_requirement("ExifRead"), py_requirement("ExifRead"),
py_requirement("yaspin"), py_requirement("yaspin"),
] ],
shebang = "/usr/bin/env python3"
) )

View file

@ -0,0 +1,4 @@
py_project(
name = "bazelshim",
main = "src/bazelshim/__main__.py",
)

View file

@ -0,0 +1,217 @@
#!/usr/bin/env python3
# Since this can't run under Bazel, we have to set up the sys.path ourselves
import os
import sys
from pathlib import Path
if (p := str(Path(sys.argv[0]).absolute().parent.parent)) not in sys.path:
sys.path.pop(0) # Remove '.' / ''
sys.path.insert(0, p) # Insert the bazelshim root
# Now that's out of the way...
from dataclasses import dataclass
from shlex import quote, split as shlex
import sys
import tomllib
from pathlib import Path
from typing import List, Optional
from itertools import chain
# FIXME: Allow user-defined extensions here
VERBS = [
"aquery",
"build",
"clean",
"coverage",
"cquery",
"dump",
"fetch",
"help",
"info",
"mod",
"query",
"run",
"sync",
"test",
"watch",
]
def path():
for it in os.getenv("PATH").split(":"):
yield Path(it)
def which(cmd):
for it in path():
f: Path = (it / cmd).absolute()
if f.exists() and f.stat().st_mode & 0x700:
yield f
def normalize_opts(args: List[str]) -> List[str]:
acc = []
if args[0].endswith("bazel") or args[0].endswith("bazelis"):
acc.append(args.pop(0))
while len(args) >= 2:
if args[0] == "--":
# Break
acc.extend(args)
break
elif "=" in args[0]:
# If it's a k/v form pass it through
acc.append(args.pop(0))
elif args[0].startswith("--no"):
# Convert --no<foo> args to --<foo>=no
acc.append("--" + args.pop(0).lstrip("--no") + "=false")
elif args[0] == "--isatty=0":
acc.append("--isatty=false")
args.pop(0)
elif (
args[0].startswith("--")
and not args[1].startswith("--")
and args[1] not in VERBS
):
# If the next thing isn't an opt, assume it's a '--a b' form
acc.append(args[0] + "=" + args[1])
args.pop(0)
args.pop(0)
elif args[0].startswith("--"):
# Assume it's a boolean true flag
acc.append(args.pop(0) + "=true")
else:
acc.append(args.pop(0))
else:
if args:
acc.extend(args)
return acc
@dataclass
class BazelCli:
binary: str
startup_opts: List[str]
command: Optional[str]
command_opts: List[str]
subprocess_opts: List[str]
@classmethod
def parse_cli(cls, args: List[str]) -> "BazelCli":
args = normalize_opts(args)
binary = args.pop(0)
startup_opts = []
while args and args[0].startswith("--"):
startup_opts.append(args.pop(0))
command = None
if args and args[0] in VERBS:
command = args.pop(0)
command_opts = []
while args and args[0] != "--":
command_opts.append(args.pop(0))
subprocess_opts = []
if args:
if args[0] == "--":
args.pop(0)
subprocess_opts.extend(args)
return cls(
binary=binary,
startup_opts=startup_opts,
command=command,
command_opts=command_opts,
subprocess_opts=subprocess_opts,
)
def render_cli(self):
acc = [
self.binary,
*self.startup_opts,
]
if self.command:
if self.command == "watch":
acc.extend(self.command_opts)
else:
acc.append(self.command)
acc.extend(self.command_opts)
if self.command == "test":
acc.extend(["--test_arg=" + it for it in self.subprocess_opts])
elif self.command == "run":
acc.append("--")
acc.extend(self.subprocess_opts)
elif self.command and not self.subprocess_opts:
pass
else:
print(
f"Warning: {self.command} does not support -- args! {self.subprocess_opts!r}",
file=sys.stderr,
)
return acc
def executable(self, exclude: List[Path]):
"""Try to resolve as via which() an executable to delegate to."""
if self.command == "watch":
for p in chain(which("ibazel")):
if p.parent not in exclude:
return str(p)
else:
for p in chain(which("bazelisk"), which("bazel")):
if p.parent not in exclude:
return str(p)
def render_text(self, next):
lines = []
lines.append(" " + next)
base_prefix = " "
for arg in self.render_cli()[1:]:
prefix = base_prefix
if arg in VERBS or arg == self.command:
prefix = " "
elif arg == "--":
base_prefix += " "
lines.append(prefix + arg)
return "\\\n".join(lines)
# FIXME: Use some sort of plugin model here to implement interceptors
def middleware(cli):
return cli
if __name__ == "__main__":
# This script has a magical flag to help with resolving bazel
exclude = []
while len(sys.argv) > 1 and sys.argv[1].startswith("--bazelshim_exclude"):
exclude.append(Path(sys.argv.pop(1).split("=")[1]).absolute())
us = Path(sys.argv[0]).absolute()
exclude.append(us.parent)
cli = BazelCli.parse_cli(["bazel"] + sys.argv[1:])
cli = middleware(cli)
next = cli.executable(exclude=exclude)
if sys.stderr.isatty() and not "--isatty=false" in cli.command_opts:
print(
"\u001b[33mInfo\u001b[0m: Executing\n" + cli.render_text(next),
file=sys.stderr,
)
os.execv(next, cli.render_cli())

View file

@ -0,0 +1,74 @@
#!/usr/bin/env python3
from shlex import split as shlex
from bazelshim.__main__ import normalize_opts
import pytest
@pytest.mark.parametrize(
"a, b",
[
(
"bazel clean",
[
"bazel",
"clean",
],
),
(
"bazel --client_debug clean",
[
"bazel",
"--client_debug=true",
"clean",
],
),
(
"bazel build //foo:bar //baz:*",
[
"bazel",
"build",
"//foo:bar",
"//baz:*",
],
),
(
"bazel test //foo:bar //baz:* -- -vvv",
[
"bazel",
"test",
"//foo:bar",
"//baz:*",
"--",
"-vvv",
],
),
(
"bazel test --shell_executable /bin/bish //foo:bar //baz:* -- -vvv",
[
"bazel",
"test",
"--shell_executable=/bin/bish",
"//foo:bar",
"//baz:*",
"--",
"-vvv",
],
),
(
"bazel run //foo:bar -- --foo=bar --baz=qux",
[
"bazel",
"run",
"//foo:bar",
"--",
"--foo=bar",
"--baz=qux",
],
),
],
)
def test_normalize_opts(a, b):
assert normalize_opts(shlex(a)) == b

View file

@ -0,0 +1,52 @@
#!/usr/bin/env python3
from shlex import split as shlex
from bazelshim.__main__ import BazelCli
import pytest
@pytest.mark.parametrize(
"a, b",
[
(
"bazel clean",
BazelCli("bazel", [], "clean", [], []),
),
(
"bazel --client_debug clean",
BazelCli("bazel", ["--client_debug=true"], "clean", [], []),
),
(
"bazel build //foo:bar //baz:*",
BazelCli("bazel", [], "build", ["//foo:bar", "//baz:*"], []),
),
(
"bazel test //foo:bar //baz:* -- -vvv",
BazelCli("bazel", [], "test", ["//foo:bar", "//baz:*"], ["-vvv"]),
),
(
"bazel test --shell_executable /bin/bish //foo:bar //baz:* -- -vvv",
BazelCli(
"bazel",
[],
"test",
["--shell_executable=/bin/bish", "//foo:bar", "//baz:*"],
["-vvv"],
),
),
(
"bazel run //foo:bar -- --foo=bar --baz=qux",
BazelCli(
"bazel",
[],
"run",
["//foo:bar"],
["--foo=bar", "--baz=qux"],
),
),
],
)
def test_normalize_opts(a, b):
assert BazelCli.parse_cli(shlex(a)) == b

View file

@ -2,7 +2,7 @@ package(default_visibility = ["//visibility:public"])
py_library( py_library(
name = "lib", name = "lib",
srcs = glob(["src/python/**/*.py"]), srcs = glob(["src/**/*.py"]),
imports = ["src/python"], imports = ["src/python"],
deps = [ deps = [
py_requirement("pyrsistent"), py_requirement("pyrsistent"),

View file

@ -7,7 +7,7 @@ py_project(
zapp_binary( zapp_binary(
name = "clusterctrl", name = "clusterctrl",
main = "src/python/clusterctrl/__main__.py", main = "src/clusterctrl/__main__.py",
imports = [ imports = [
"src/python", "src/python",
], ],

View file

@ -1,6 +1,6 @@
zapp_binary( zapp_binary(
name = "datalog-shell", name = "datalog-shell",
main = "src/python/datalog/shell/__main__.py", main = "src/datalog/shell/__main__.py",
imports = [ imports = [
"src/python" "src/python"
], ],

Some files were not shown because too many files have changed in this diff Show more