Coverage for src/workstack/core/context.py: 100%

25 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-10-19 09:31 -0400

1"""Application context with dependency injection.""" 

2 

3from dataclasses import dataclass 

4 

5from workstack.core.github_ops import DryRunGitHubOps, GitHubOps, RealGitHubOps 

6from workstack.core.gitops import DryRunGitOps, GitOps, RealGitOps 

7from workstack.core.global_config_ops import ( 

8 DryRunGlobalConfigOps, 

9 GlobalConfigOps, 

10 RealGlobalConfigOps, 

11) 

12from workstack.core.graphite_ops import DryRunGraphiteOps, GraphiteOps, RealGraphiteOps 

13from workstack.core.shell_ops import RealShellOps, ShellOps 

14 

15 

16@dataclass(frozen=True) 

17class WorkstackContext: 

18 """Immutable context holding all dependencies for workstack operations. 

19 

20 Created at CLI entry point and threaded through the application. 

21 Frozen to prevent accidental modification at runtime. 

22 """ 

23 

24 git_ops: GitOps 

25 global_config_ops: GlobalConfigOps 

26 github_ops: GitHubOps 

27 graphite_ops: GraphiteOps 

28 shell_ops: ShellOps 

29 dry_run: bool 

30 

31 

32def create_context(*, dry_run: bool) -> WorkstackContext: 

33 """Create production context with real implementations. 

34 

35 Called at CLI entry point to create the context for the entire 

36 command execution. 

37 

38 Args: 

39 dry_run: If True, wrap all dependencies with dry-run wrappers that 

40 print intended actions without executing them 

41 

42 Returns: 

43 WorkstackContext with real implementations, wrapped in dry-run 

44 wrappers if dry_run=True 

45 

46 Example: 

47 >>> ctx = create_context(dry_run=False) 

48 >>> worktrees = ctx.git_ops.list_worktrees(Path("/repo")) 

49 >>> workstacks_root = ctx.global_config_ops.get_workstacks_root() 

50 """ 

51 git_ops: GitOps = RealGitOps() 

52 graphite_ops: GraphiteOps = RealGraphiteOps() 

53 github_ops: GitHubOps = RealGitHubOps() 

54 global_config_ops: GlobalConfigOps = RealGlobalConfigOps() 

55 

56 if dry_run: 

57 git_ops = DryRunGitOps(git_ops) 

58 graphite_ops = DryRunGraphiteOps(graphite_ops) 

59 github_ops = DryRunGitHubOps(github_ops) 

60 global_config_ops = DryRunGlobalConfigOps(global_config_ops) 

61 

62 return WorkstackContext( 

63 git_ops=git_ops, 

64 global_config_ops=global_config_ops, 

65 github_ops=github_ops, 

66 graphite_ops=graphite_ops, 

67 shell_ops=RealShellOps(), 

68 dry_run=dry_run, 

69 )