diff --git a/devtools/__main__.py b/devtools/__main__.py index 95955c2e..b53b9fb8 100644 --- a/devtools/__main__.py +++ b/devtools/__main__.py @@ -1,15 +1,74 @@ -import click +import subprocess +import sys +import os +from pathlib import Path + +try: + import click + import rich + from .ctx import Context + from . import ci + from . import update_pyproject + from .subproject import Subproject + from .progress import progress +except (ImportError, ModuleNotFoundError): + print("Installing robotpy dev requirements...") + subprocess.check_call( + [ + sys.executable, + "-m", + "pip", + "install", + "--disable-pip-version-check", + "-r", + (Path(__file__).parent.parent / "rdev_requirements.txt").resolve().as_posix(), + ] + ) + + print("Try running the command again.") + exit(0) -from .ctx import Context -from . import ci -from . import update_pyproject @click.group() +@click.option("--only", required=False, default=None, help="Only run for the specified project") +@click.option("--till", required=False, default=None, help="Only run until the specified project") @click.pass_context -def main(ctx: click.Context): +def main(ctx: click.Context, only: str, till: str): """RobotPy development tool""" - ctx.obj = Context() + obj = ctx.obj = Context() + + if obj.cfg.params.parallel is not None: + os.environ.setdefault("RPYBUILD_PARALLEL", str(int(obj.cfg.params.parallel))) + if obj.cfg.params.cc_launcher is not None: + os.environ.setdefault("RPYBUILD_CC_LAUNCHER", obj.cfg.params.cc_launcher) + if obj.cfg.params.strip_libpython is not None: + os.environ.setdefault("RPYBUILD_STRIP_LIBPYTHON", str(int(obj.cfg.params.strip_libpython))) + if obj.cfg.params.macosx_deployment_target is not None: + os.environ.setdefault("MACOSX_DEPLOYMENT_TARGET", obj.cfg.params.macosx_deployment_target) + + subprocess.check_call( + [ + sys.executable, + "-m", + "pip", + "install", + "--disable-pip-version-check", + "robotpy-build"+obj.cfg.params.robotpy_build_req, + ], + stdout=subprocess.DEVNULL, + ) + + if only is not None: + obj.subprojects = {only: obj.subprojects[only]} + elif till is not None: + subprojects = {} + for name, project in obj.subprojects.items(): + subprojects[name] = project + if name == till: + subprojects[name] = project + break + obj.subprojects = subprojects main.add_command(ci.ci) @@ -20,25 +79,37 @@ def main(ctx: click.Context): @click.pass_obj def info(ctx: Context): """Display information""" - for project in ctx.subprojects.values(): - print(project.name, project.requires) + for project in progress(ctx.subprojects.values()): + rich.print(project.name, ":", project.requires) @main.command() @click.pass_obj def develop(ctx: Context): """Install all robotpy packages in editable mode""" - for project in ctx.subprojects.values(): + for project in progress(ctx.subprojects.values()): project.develop() +@main.command() +@click.pass_obj +def build(ctx: Context): + """Build all robotpy packages""" + for project in progress(ctx.subprojects.values()): + project.bdist_wheel(wheel_path=ctx.wheel_path, install=True) @main.command() @click.pass_obj def test(ctx: Context): """Run all test scripts""" - for project in ctx.subprojects.values(): + for project in progress(ctx.subprojects.values()): project.test() +@main.command() +@click.pass_obj +def clean(ctx: Context): + """Clean all projects""" + for project in progress(ctx.subprojects.values()): + project.clean() if __name__ == "__main__": - main() + main() \ No newline at end of file diff --git a/devtools/config.py b/devtools/config.py index 10150b50..36b165ad 100644 --- a/devtools/config.py +++ b/devtools/config.py @@ -25,6 +25,11 @@ class Parameters(Model): exclude_artifacts: typing.Set[str] + parallel: typing.Optional[bool] + cc_launcher: typing.Optional[str] + strip_libpython: typing.Optional[bool] + macosx_deployment_target: typing.Optional[str] + class UpdateConfig(Model): params: Parameters diff --git a/devtools/progress.py b/devtools/progress.py new file mode 100644 index 00000000..5e7a2f53 --- /dev/null +++ b/devtools/progress.py @@ -0,0 +1,43 @@ +from typing import Iterable, ValuesView +import rich.progress +from datetime import datetime +import inspect + +import rich.text + +from .subproject import Subproject + +def progress( + sequence: ValuesView[Subproject], +) -> Iterable[Subproject]: + + taskname = inspect.stack()[1].function + + class NumTaskColumn(rich.progress.ProgressColumn): + def render(self, task: rich.progress.Task) -> rich.text.Text: + return rich.text.Text(f"{task.completed}/{task.total}", style="purple") + + current_hour = datetime.now().hour + if 7 <= current_hour < (12 + 9): + spinner_name = "earth" + else: + spinner_name = "moon" + + progress = rich.progress.Progress( + rich.progress.SpinnerColumn(spinner_name=spinner_name), + rich.progress.TextColumn("[progress.description]{task.description}"), + rich.progress.BarColumn(), + NumTaskColumn(), + rich.progress.TimeElapsedColumn(), + redirect_stdout=True, + redirect_stderr=True, + # refresh_per_second=50 + ) + + with progress: + for item in progress.track( + sequence, total=len(sequence) + ): + progress.update(progress.task_ids[0], description=f"{taskname} {item.name}") + yield item + diff --git a/devtools/subproject.py b/devtools/subproject.py index 526fecad..0374ce14 100644 --- a/devtools/subproject.py +++ b/devtools/subproject.py @@ -80,6 +80,16 @@ def test(self, *, install_requirements=False): cwd=tests_path, ) + def clean(self): + self._cmd( + sys.executable, + "setup.py", + "clean", + "--all", + cwd=self.path, + ) + shutil.rmtree(self.path / "build", ignore_errors=True) + def bdist_wheel(self, *, wheel_path: pathlib.Path, install: bool): wheel_path.mkdir(parents=True, exist_ok=True) diff --git a/rdev.toml b/rdev.toml index e221add4..fdca11c7 100644 --- a/rdev.toml +++ b/rdev.toml @@ -4,6 +4,12 @@ [params] +parallel = true +cc_launcher = "ccache" +# strip_libpython = true +# macosx_deployment_target = "12" + + wpilib_bin_url = "https://frcmaven.wpi.edu/artifactory/release" wpilib_bin_version = "2024.1.1-beta-3" # wpilib_bin_url = "https://frcmaven.wpi.edu/artifactory/development" diff --git a/rdev_requirements.txt b/rdev_requirements.txt index 5524355d..11243bb6 100644 --- a/rdev_requirements.txt +++ b/rdev_requirements.txt @@ -3,6 +3,7 @@ click packaging pydantic<2 requests +rich setuptools tomlkit tomli diff --git a/subprojects/robotpy-halsim-ds-socket/halsim_ds_socket/version.py b/subprojects/robotpy-halsim-ds-socket/halsim_ds_socket/version.py new file mode 100644 index 00000000..40c02cc5 --- /dev/null +++ b/subprojects/robotpy-halsim-ds-socket/halsim_ds_socket/version.py @@ -0,0 +1,4 @@ +# file generated by setuptools_scm +# don't change, don't track in version control +__version__ = version = '2024.0.0b3.post2.dev3+g375e0468.d20231113' +__version_tuple__ = version_tuple = (2024, 0, 0, 'dev3', 'g375e0468.d20231113')