Nymbo commited on
Commit
55ab3a6
·
verified ·
1 Parent(s): 07e140c

Update Modules/_docstrings.py

Browse files
Files changed (1) hide show
  1. Modules/_docstrings.py +37 -0
Modules/_docstrings.py CHANGED
@@ -1,6 +1,7 @@
1
  from __future__ import annotations
2
 
3
  import inspect
 
4
  from typing import Any, Annotated, get_args, get_origin, get_type_hints
5
 
6
 
@@ -16,9 +17,45 @@ def _typename(tp: Any) -> str:
16
  return str(tp)
17
 
18
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  def _extract_base_and_meta(annotation: Any) -> tuple[Any, str | None]:
20
  """Given an annotation, return (base_type, first string metadata) if Annotated, else (annotation, None)."""
21
  try:
 
 
 
 
 
 
 
22
  if get_origin(annotation) is Annotated:
23
  args = get_args(annotation)
24
  base = args[0] if args else annotation
 
1
  from __future__ import annotations
2
 
3
  import inspect
4
+ import re
5
  from typing import Any, Annotated, get_args, get_origin, get_type_hints
6
 
7
 
 
17
  return str(tp)
18
 
19
 
20
+ def _parse_string_annotation(annot_str: str) -> tuple[str | None, str | None]:
21
+ """
22
+ Parse a string annotation like "Annotated[Optional[str], 'description']"
23
+ and extract the base type name and the description metadata.
24
+
25
+ Returns (base_type_name, description) or (None, None) if parsing fails.
26
+ """
27
+ if not isinstance(annot_str, str):
28
+ return None, None
29
+
30
+ # Match Annotated[..., 'description'] or Annotated[..., "description"]
31
+ # Pattern: Annotated[<base_type>, '<description>'] or with double quotes
32
+ match = re.match(
33
+ r"^Annotated\[(.+?),\s*['\"](.+?)['\"]\s*\]$",
34
+ annot_str.strip(),
35
+ re.DOTALL,
36
+ )
37
+ if match:
38
+ base_type_str = match.group(1).strip()
39
+ description = match.group(2)
40
+ # Simplify Optional[X] -> just the base type for display
41
+ opt_match = re.match(r"^Optional\[(.+)\]$", base_type_str)
42
+ if opt_match:
43
+ base_type_str = opt_match.group(1).strip()
44
+ return base_type_str, description
45
+
46
+ return None, None
47
+
48
+
49
  def _extract_base_and_meta(annotation: Any) -> tuple[Any, str | None]:
50
  """Given an annotation, return (base_type, first string metadata) if Annotated, else (annotation, None)."""
51
  try:
52
+ # Handle string annotations from PEP 563 (__future__.annotations)
53
+ if isinstance(annotation, str):
54
+ base_str, meta = _parse_string_annotation(annotation)
55
+ if meta:
56
+ return base_str or annotation, meta
57
+ return annotation, None
58
+
59
  if get_origin(annotation) is Annotated:
60
  args = get_args(annotation)
61
  base = args[0] if args else annotation