Coverage for src/footman/tasks/new.py: 87%

13 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-09-06 02:59 +0000

1"""Scaffold a tasks file — `fm new`, the first thing in an empty directory. 

2 

3Brand-aware through the configured world: a branded CLI writes its own 

4tasks filename and teaches its own command, so one implementation serves 

5every runner. Stock footman declares it in `builtin=`, which is what makes 

6`fm new` answer in a directory with no tasks at all — and inside a project 

7the ordinary remedy applies: mount `footman.new` from the root tasks file 

8to offer it there too. 

9""" 

10 

11from __future__ import annotations 

12 

13from footman import _paths, context 

14from footman.context import fail 

15from footman.registry import task 

16 

17# Pure ASCII on purpose: this docstring is the first help text the new 

18# tasks file renders, and a console encoding narrower than UTF-8 cannot 

19# print a glyph outside its codec. A starter file plants nothing a legacy 

20# terminal has to degrade. 

21_SCAFFOLD = '''\ 

22from footman import task 

23 

24 

25@task 

26def hello(name: str = "world") -> None: 

27 """Say hello. Replace me with your first real task.""" 

28 print(f"hello {name}") 

29''' 

30 

31 

32# The built-in set defaults to needing a project; this is the one task that 

33# does not — writing the first tasks file is precisely what you do where 

34# there is no project yet. 

35@task(expose="global_only") 

36def new() -> None: 

37 """Write a starter tasks file in this directory.""" 

38 prog = context.current().prog 

39 target = context.cwd() / _paths._tasks_file 

40 if target.exists(): 40 ↛ 41line 40 didn't jump to line 41 because the condition on line 40 was never true

41 fail( 

42 f"{target.name} already exists here — edit it instead, or run " 

43 f"{prog} new somewhere empty" 

44 ) 

45 target.write_text(_SCAFFOLD, encoding="utf-8") 

46 print(f"wrote {target.name} — try: {prog} hello")