From b2d0006f427d66b2fb60b7da269c73c145630537 Mon Sep 17 00:00:00 2001 From: Austin Appleby Date: Wed, 13 Mar 2024 15:19:33 -0700 Subject: [PATCH] add task_creates_task test, add app-wide list of all tasks created --- .vscode/launch.json | 2 +- hancho.py | 19 ++++++++++++++----- tests/task_creates_task.hancho | 15 +++++++++++++++ tests/test.py | 3 +++ 4 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 tests/task_creates_task.hancho diff --git a/.vscode/launch.json b/.vscode/launch.json index 117b9e4..cac3f82 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,7 +10,7 @@ "request": "launch", "program": "${workspaceFolder}/hancho.py", "cwd": "${workspaceFolder}/tests", - "args": ["--force", "-j1", "multiple_commands.hancho"], + "args": ["--force", "-j1", "task_creates_task.hancho"], "console": "integratedTerminal", "justMyCode": false, }, diff --git a/hancho.py b/hancho.py index 534201f..a7b7e0a 100755 --- a/hancho.py +++ b/hancho.py @@ -290,6 +290,8 @@ class Encoder(json.JSONEncoder): """Types the encoder doesn't understand just get stringified.""" def default(self, o): + if isinstance(o, Path): + return f"Path {o}" return str(o) return json.dumps(self, indent=2, cls=Encoder) @@ -330,10 +332,17 @@ def __call__(self, files_in, files_out=None, **kwargs): Path(inspect.stack(context=0)[1].filename).parent, self.root_dir ) task.work_dir = relpath(Path.cwd(), self.root_dir) - task.load_dir = relpath(Path(app.mod_stack[-1].__file__).parent, self.root_dir) + + # A task that's created during task execution instead of module loading will have no mod + # stack entry to pull load_dir from, so it runs from '.' (root_dir) instead. + if app.mod_stack: + task.load_dir = relpath(Path(app.mod_stack[-1].__file__).parent, self.root_dir) + else: + task.load_dir = Path(".") coroutine = task.run_async() task.promise = asyncio.create_task(coroutine) + app.all_tasks.append(task) return task @@ -429,9 +438,9 @@ async def task_main(self): # Check for duplicate task outputs for file in self.abs_files_out: - if file in app.hancho_outs: + if file in app.all_files_out: raise NameError(f"Multiple rules build {file}!") - app.hancho_outs.add(file) + app.all_files_out.add(file) # Check if we need a rebuild self.reason = self.needs_rerun(self.force) @@ -511,7 +520,6 @@ async def run_command(self, command): # Create the subprocess via asyncio and then await the result. with Chdir(self.task_dir): - log(f"Running {command}") proc = await asyncio.create_subprocess_shell( command, stdout=asyncio.subprocess.PIPE, @@ -617,7 +625,8 @@ class App: def __init__(self): self.hancho_mods = {} self.mod_stack = [] - self.hancho_outs = set() + self.all_tasks = [] + self.all_files_out = set() self.tasks_total = 0 self.tasks_pass = 0 self.tasks_fail = 0 diff --git a/tests/task_creates_task.hancho b/tests/task_creates_task.hancho new file mode 100644 index 0000000..c74d370 --- /dev/null +++ b/tests/task_creates_task.hancho @@ -0,0 +1,15 @@ +from hancho import * + +rule1 = Rule( + command = "touch {files_out}" +) + +def callback(task): + rule1([], "dummy.txt") + return [] + +rule2 = Rule( + command = callback +) + +rule2([], []) diff --git a/tests/test.py b/tests/test.py index b424c91..83bc136 100755 --- a/tests/test.py +++ b/tests/test.py @@ -206,6 +206,9 @@ def test_cancellation(self): self.assertFalse(Path("build/fail_result.txt").exists()) self.assertFalse(Path("build/should_not_be_created.txt").exists()) + def test_task_creates_task(self): + self.assertEqual(0, run_hancho("task_creates_task")) + self.assertTrue(Path("build/dummy.txt").exists()) ################################################################################