docwrap 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- docwrap/__init__.py +59 -0
- docwrap/__main__.py +8 -0
- docwrap/_canonical.py +66 -0
- docwrap/_classify.py +56 -0
- docwrap/_cli.py +1284 -0
- docwrap/_color.py +135 -0
- docwrap/_config.py +615 -0
- docwrap/_convert.py +1324 -0
- docwrap/_core/__init__.py +27 -0
- docwrap/_core/_codeblock.py +214 -0
- docwrap/_core/_discover.py +466 -0
- docwrap/_core/_escape.py +204 -0
- docwrap/_core/_incremental.py +402 -0
- docwrap/_core/_normalize.py +306 -0
- docwrap/_core/_parse.py +594 -0
- docwrap/_core/_process.py +826 -0
- docwrap/_core/_wrap.py +1714 -0
- docwrap/_detect.py +98 -0
- docwrap/_detector.py +166 -0
- docwrap/_display/__init__.py +17 -0
- docwrap/_display/_diff.py +62 -0
- docwrap/_display/_json.py +168 -0
- docwrap/_display/_print.py +93 -0
- docwrap/_display/_recommend.py +165 -0
- docwrap/_display/_skips.py +17 -0
- docwrap/_display/_stats.py +1075 -0
- docwrap/_display/_summary.py +213 -0
- docwrap/_display/_text.py +17 -0
- docwrap/_downstream.py +181 -0
- docwrap/_exceptions.py +52 -0
- docwrap/_files.py +304 -0
- docwrap/_git.py +764 -0
- docwrap/_git_utils.py +76 -0
- docwrap/_grammar.py +800 -0
- docwrap/_hook.py +1001 -0
- docwrap/_hosts/__init__.py +50 -0
- docwrap/_shell.py +73 -0
- docwrap/_shellparse.py +643 -0
- docwrap/_stats.py +529 -0
- docwrap/_styles/__init__.py +335 -0
- docwrap/_styles/_google.py +423 -0
- docwrap/_styles/_numpy.py +292 -0
- docwrap/_styles/_sphinx.py +324 -0
- docwrap/_types.py +423 -0
- docwrap/_validate.py +62 -0
- docwrap/hooks/__init__.py +245 -0
- docwrap/py.typed +0 -0
- docwrap-0.1.0.dist-info/METADATA +126 -0
- docwrap-0.1.0.dist-info/RECORD +58 -0
- docwrap-0.1.0.dist-info/WHEEL +4 -0
- docwrap-0.1.0.dist-info/entry_points.txt +7 -0
- docwrap-0.1.0.dist-info/licenses/LICENSE +21 -0
- plugins/agy/_docwrap/__init__.py +1 -0
- plugins/agy/_docwrap/_adapter.py +122 -0
- plugins/claude/_docwrap/__init__.py +1 -0
- plugins/claude/_docwrap/_adapter.py +106 -0
- plugins/codex/_docwrap/__init__.py +1 -0
- plugins/codex/_docwrap/_adapter.py +117 -0
docwrap/__init__.py
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""Public facade for docwrap's supported library API.
|
|
2
|
+
|
|
3
|
+
Example:
|
|
4
|
+
>>> import docwrap
|
|
5
|
+
>>> docwrap.wrap_source('def f(): pass')
|
|
6
|
+
'def f(): pass'
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from docwrap._config import clear_config_cache, resolve_config
|
|
10
|
+
from docwrap._core import check, wrap_file_report, wrap_source, wrap_source_report
|
|
11
|
+
from docwrap._exceptions import (
|
|
12
|
+
DocwrapConfigWarning,
|
|
13
|
+
DocwrapSkipWarning,
|
|
14
|
+
InvalidLineLengthError,
|
|
15
|
+
UnknownStyleError,
|
|
16
|
+
)
|
|
17
|
+
from docwrap._styles import get_styles
|
|
18
|
+
from docwrap._types import (
|
|
19
|
+
DEFAULT_LINE_LENGTH,
|
|
20
|
+
DetailLevel,
|
|
21
|
+
DocstringChange,
|
|
22
|
+
DocstringSkip,
|
|
23
|
+
DocwrapConfig,
|
|
24
|
+
FillStyle,
|
|
25
|
+
ReflowMode,
|
|
26
|
+
SkipCode,
|
|
27
|
+
StyleName,
|
|
28
|
+
SummaryStart,
|
|
29
|
+
WrapCheckResult,
|
|
30
|
+
WrapReport,
|
|
31
|
+
WrapStatus,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
__all__ = [
|
|
35
|
+
'DEFAULT_LINE_LENGTH',
|
|
36
|
+
'DetailLevel',
|
|
37
|
+
'DocstringChange',
|
|
38
|
+
'DocstringSkip',
|
|
39
|
+
'DocwrapConfig',
|
|
40
|
+
'DocwrapConfigWarning',
|
|
41
|
+
'DocwrapSkipWarning',
|
|
42
|
+
'FillStyle',
|
|
43
|
+
'InvalidLineLengthError',
|
|
44
|
+
'ReflowMode',
|
|
45
|
+
'SkipCode',
|
|
46
|
+
'StyleName',
|
|
47
|
+
'SummaryStart',
|
|
48
|
+
'UnknownStyleError',
|
|
49
|
+
'WrapCheckResult',
|
|
50
|
+
'WrapReport',
|
|
51
|
+
'WrapStatus',
|
|
52
|
+
'check',
|
|
53
|
+
'clear_config_cache',
|
|
54
|
+
'get_styles',
|
|
55
|
+
'resolve_config',
|
|
56
|
+
'wrap_file_report',
|
|
57
|
+
'wrap_source',
|
|
58
|
+
'wrap_source_report',
|
|
59
|
+
]
|
docwrap/__main__.py
ADDED
docwrap/_canonical.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Canonical section registry for docstring roles."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
|
|
5
|
+
from docwrap._types import CanonicalRole
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass(frozen=True, slots=True)
|
|
9
|
+
class CanonicalSection:
|
|
10
|
+
"""Registry entry whose tuple position determines canonical section order.
|
|
11
|
+
|
|
12
|
+
The entry's position in `CANONICAL_SECTIONS` is the ordering authority.
|
|
13
|
+
Sphinx field mappings and target support belong to the Sphinx style.
|
|
14
|
+
|
|
15
|
+
Attributes:
|
|
16
|
+
role: Canonical docstring role represented by this entry.
|
|
17
|
+
google_header: Google header label, or `None` when unavailable.
|
|
18
|
+
numpy_header: NumPy header label, or `None` when unavailable.
|
|
19
|
+
return_like: Whether the role uses return-like entry handling.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
role: CanonicalRole
|
|
23
|
+
google_header: str | None = None
|
|
24
|
+
numpy_header: str | None = None
|
|
25
|
+
return_like: bool = False
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
CANONICAL_SECTIONS: tuple[CanonicalSection, ...] = (
|
|
29
|
+
CanonicalSection('param', google_header='Args', numpy_header='Parameters'),
|
|
30
|
+
CanonicalSection('keyword_param', google_header='Keyword Args'),
|
|
31
|
+
CanonicalSection('other_param', numpy_header='Other Parameters'),
|
|
32
|
+
CanonicalSection(
|
|
33
|
+
'returns',
|
|
34
|
+
google_header='Returns',
|
|
35
|
+
numpy_header='Returns',
|
|
36
|
+
return_like=True,
|
|
37
|
+
),
|
|
38
|
+
CanonicalSection(
|
|
39
|
+
'yields',
|
|
40
|
+
google_header='Yields',
|
|
41
|
+
numpy_header='Yields',
|
|
42
|
+
return_like=True,
|
|
43
|
+
),
|
|
44
|
+
CanonicalSection('raises', google_header='Raises', numpy_header='Raises'),
|
|
45
|
+
CanonicalSection('warns', google_header='Warns', numpy_header='Warns'),
|
|
46
|
+
CanonicalSection(
|
|
47
|
+
'attributes',
|
|
48
|
+
google_header='Attributes',
|
|
49
|
+
numpy_header='Attributes',
|
|
50
|
+
),
|
|
51
|
+
CanonicalSection('methods', google_header='Methods', numpy_header='Methods'),
|
|
52
|
+
CanonicalSection('see_also', google_header='See Also', numpy_header='See Also'),
|
|
53
|
+
CanonicalSection('notes', google_header='Notes', numpy_header='Notes'),
|
|
54
|
+
CanonicalSection('references', google_header='References', numpy_header='References'),
|
|
55
|
+
CanonicalSection('examples', google_header='Examples', numpy_header='Examples'),
|
|
56
|
+
CanonicalSection('todo', google_header='Todo', numpy_header='Todo'),
|
|
57
|
+
CanonicalSection('warnings', google_header='Warnings', numpy_header='Warnings'),
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
CANONICAL_ORDER: tuple[CanonicalRole, ...] = tuple(section.role for section in CANONICAL_SECTIONS)
|
|
61
|
+
|
|
62
|
+
CANONICAL_ORDER_SET: frozenset[CanonicalRole] = frozenset(CANONICAL_ORDER)
|
|
63
|
+
|
|
64
|
+
RETURN_LIKE_ROLES: frozenset[CanonicalRole] = frozenset(
|
|
65
|
+
s.role for s in CANONICAL_SECTIONS if s.return_like
|
|
66
|
+
)
|
docwrap/_classify.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""Classify a pre-tool shell command into one of three outcomes."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Literal
|
|
5
|
+
|
|
6
|
+
from docwrap._color import visible_controls
|
|
7
|
+
from docwrap._detector import detect_commit
|
|
8
|
+
from docwrap._grammar import CommitPlan, NoCommit, Rejection, classify_grammar
|
|
9
|
+
from docwrap._shellparse import parse_command
|
|
10
|
+
|
|
11
|
+
type _OUTCOME = Literal['unrelated', 'supported', 'unsupported']
|
|
12
|
+
|
|
13
|
+
_REASON_PREFIX = 'docwrap: unsupported commit command'
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass(frozen=True, slots=True)
|
|
17
|
+
class Classification:
|
|
18
|
+
"""Outcome of classifying one command.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
outcome: `unrelated`, `supported`, or `unsupported`.
|
|
22
|
+
plan: Resolved commit plan, or `NoCommit`, for a supported command.
|
|
23
|
+
reason: Deny reason for an unsupported command.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
outcome: _OUTCOME
|
|
27
|
+
plan: CommitPlan | NoCommit | None = None
|
|
28
|
+
reason: str | None = None
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _deny_reason(rejection: Rejection) -> str:
|
|
32
|
+
"""Render a sanitized deny reason for a rejected command."""
|
|
33
|
+
return visible_controls(f'{_REASON_PREFIX}: {rejection.element}; {rejection.hint}')
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def classify_command(text: str, command_cwd: str | None) -> Classification:
|
|
37
|
+
"""Classify a shell command as unrelated, supported, or unsupported.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
text: Shell command text from the hook payload.
|
|
41
|
+
command_cwd: Absolute directory the command executes in, or `None` when
|
|
42
|
+
unknown.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
The classification. The grammar decides first; a rejected command is
|
|
46
|
+
unsupported when the detector finds a commit and unrelated otherwise.
|
|
47
|
+
A committing command with an unknown directory and no absolute route is
|
|
48
|
+
unsupported.
|
|
49
|
+
"""
|
|
50
|
+
command = parse_command(text)
|
|
51
|
+
result = classify_grammar(command, command_cwd)
|
|
52
|
+
if isinstance(result, Rejection):
|
|
53
|
+
if detect_commit(command):
|
|
54
|
+
return Classification('unsupported', reason=_deny_reason(result))
|
|
55
|
+
return Classification('unrelated')
|
|
56
|
+
return Classification('supported', plan=result)
|