Coverage for src / python_commitlint / core / protocols.py: 100%

13 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-04-28 02:54 +0000

1"""Structural Protocols decoupling the linter from concrete adapters. 

2 

3These Protocols define the contracts the linter expects from its parser, 

4rule, and configuration-loading collaborators so alternative implementations 

5can be plugged in without inheritance. 

6""" 

7 

8from pathlib import Path 

9from typing import Protocol 

10 

11from python_commitlint.core.models import ( 

12 CommitMessage, 

13 Configuration, 

14 LintResult, 

15 RuleConfig, 

16 ValidationError, 

17) 

18 

19 

20class CommitParserProtocol(Protocol): 

21 """Parses a raw commit message into a :class:`CommitMessage`.""" 

22 

23 def parse(self, message: str) -> CommitMessage: 

24 """Parse ``message`` and return a structured commit. 

25 

26 Args: 

27 message: The raw commit message text, including newlines. 

28 

29 Returns: 

30 A :class:`CommitMessage` populated with whichever fields could 

31 be extracted; non-parseable messages return an empty-typed result. 

32 """ 

33 ... 

34 

35 

36class RuleProtocol(Protocol): 

37 """A single commitlint rule that validates a parsed commit.""" 

38 

39 @property 

40 def name(self) -> str: 

41 """The rule's stable identifier (e.g. ``type-case``).""" 

42 ... 

43 

44 def validate( 

45 self, commit: CommitMessage, config: RuleConfig 

46 ) -> ValidationError | None: 

47 """Apply the rule to ``commit`` under the given ``config``. 

48 

49 Args: 

50 commit: The parsed commit to validate. 

51 config: The rule's severity, condition, and optional value. 

52 

53 Returns: 

54 A :class:`ValidationError` when the rule is violated, otherwise 

55 ``None``. 

56 """ 

57 ... 

58 

59 

60class ConfigurationLoaderProtocol(Protocol): 

61 """Loads a :class:`Configuration` from a path or built-in default.""" 

62 

63 def load(self, config_path: Path | None = None) -> Configuration: 

64 """Load the configuration and return a fully-resolved value. 

65 

66 Args: 

67 config_path: Optional explicit path; when ``None`` the loader 

68 searches the working directory for a default config file. 

69 

70 Returns: 

71 The loaded :class:`Configuration`. 

72 """ 

73 ... 

74 

75 

76class CommitLinterProtocol(Protocol): 

77 """Validates a commit message against the configured rule set.""" 

78 

79 def lint(self, message: str) -> LintResult: 

80 """Validate ``message`` and return the lint outcome. 

81 

82 Args: 

83 message: The raw commit message text. 

84 

85 Returns: 

86 A :class:`LintResult` containing errors, warnings, and the 

87 overall ``valid`` flag. 

88 """ 

89 ...