Skip to content

Commit 44f8f66

Browse files
committed
refactor: Expose public API from top-level module, sync API/docs
1 parent 6563112 commit 44f8f66

2 files changed

Lines changed: 112 additions & 29 deletions

File tree

src/mkdocstrings_handlers/c/__init__.py

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,60 @@
66
CInputOptions,
77
COptions,
88
)
9-
from mkdocstrings_handlers.c._internal.handler import CHandler, get_handler
9+
from mkdocstrings_handlers.c._internal.handler import (
10+
CHandler,
11+
CodeDoc,
12+
Comment,
13+
DocFunc,
14+
DocGlobalVar,
15+
DocMacro,
16+
Docstring,
17+
DocType,
18+
FuncParam,
19+
InOut,
20+
Macro,
21+
Param,
22+
SupportsQualsAndType,
23+
TypeDecl,
24+
TypeRef,
25+
ast_to_decl,
26+
desc,
27+
extract_comments,
28+
extract_macros,
29+
get_handler,
30+
lookup_type_html,
31+
parse_docstring,
32+
tp_ref_to_str,
33+
typedef_to_str,
34+
)
1035

1136
__all__ = [
1237
"CConfig",
1338
"CHandler",
1439
"CInputConfig",
1540
"CInputOptions",
1641
"COptions",
42+
"CodeDoc",
43+
"Comment",
44+
"DocFunc",
45+
"DocGlobalVar",
46+
"DocMacro",
47+
"DocType",
48+
"Docstring",
49+
"FuncParam",
50+
"InOut",
51+
"Macro",
52+
"Param",
53+
"SupportsQualsAndType",
54+
"TypeDecl",
55+
"TypeRef",
56+
"ast_to_decl",
57+
"desc",
58+
"extract_comments",
59+
"extract_macros",
1760
"get_handler",
61+
"lookup_type_html",
62+
"parse_docstring",
63+
"tp_ref_to_str",
64+
"typedef_to_str",
1865
]

src/mkdocstrings_handlers/c/_internal/handler.py

Lines changed: 64 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""This module implements a handler for the C language."""
1+
# This module implements a handler for the C language.
22

33
from __future__ import annotations
44

@@ -10,33 +10,40 @@
1010
from pathlib import Path
1111
from typing import TYPE_CHECKING, Any, ClassVar, Protocol
1212

13+
from mkdocs.exceptions import PluginError
1314
from mkdocstrings import BaseHandler, CollectionError, CollectorItem, get_logger
1415
from pycparser import CParser, c_ast
1516

17+
from mkdocstrings_handlers.c._internal.config import COptions
18+
1619
if TYPE_CHECKING:
1720
from collections.abc import Mapping, MutableMapping
1821

1922
from mkdocs.config.defaults import MkDocsConfig
2023
from pycparser.c_ast import FileAST
2124

2225

23-
logger = get_logger(__name__)
26+
_logger = get_logger(__name__)
2427

2528

2629
@dataclass
2730
class Comment:
2831
"""A comment extracted from the source code."""
2932

3033
text: str
34+
"""The text of the comment."""
3135
last_line_number: int
36+
"""The last line number of the comment in the source code."""
3237

3338

3439
@dataclass
3540
class Macro:
3641
"""A macro extracted from the source code."""
3742

3843
text: str
44+
"""The text of the macro."""
3945
line_number: int
46+
"""The line number of the macro in the source code."""
4047

4148

4249
_C_PARSER = CParser()
@@ -167,26 +174,35 @@ class InOut(str, Enum):
167174
"""Enumeration for parameter direction."""
168175

169176
UNSPECIFIED = "unspecified"
177+
"""The direction is unspecified."""
170178
IN = "in"
179+
"""The parameter is an input."""
171180
OUT = "out"
181+
"""The parameter is an output."""
172182

173183

174184
@dataclass
175185
class Param:
176186
"""A parameter in a function signature."""
177187

178188
name: str
189+
"""The name of the parameter."""
179190
desc: str
191+
"""The description of the parameter."""
180192
in_out: InOut
193+
"""The direction of the parameter (input, output, or unspecified)."""
181194

182195

183196
@dataclass
184197
class Docstring:
185198
"""A parsed docstring."""
186199

187200
desc: str
201+
"""The description of the docstring."""
188202
params: list[Param] | None = None
203+
"""The parameters of the docstring."""
189204
ret: str | None = None
205+
"""The return value of the docstring."""
190206

191207

192208
def parse_docstring(content: str) -> Docstring:
@@ -270,82 +286,113 @@ class DocMacro:
270286
"""A parsed macro."""
271287

272288
name: str
289+
"""The name of the macro."""
273290
content: str | None
291+
"""The content of the macro."""
274292
doc: Docstring | None
293+
"""The docstring of the macro."""
275294

276295

277296
@dataclass
278297
class DocType:
279298
"""A parsed typedef."""
280299

281300
name: str
301+
"""The name of the typedef."""
282302
tp: TypeRef
303+
"""The type reference of the typedef."""
283304
doc: Docstring | None
305+
"""The docstring of the typedef."""
284306
quals: list[str]
307+
"""The qualifiers of the typedef."""
285308

286309

287310
@dataclass
288311
class DocGlobalVar:
289312
"""A parsed global variable."""
290313

291314
name: str
315+
"""The name of the global variable."""
292316
tp: TypeRef
317+
"""The type reference of the global variable."""
293318
doc: Docstring | None
319+
"""The docstring of the global variable."""
294320
quals: list[str]
321+
"""The qualifiers of the global variable."""
295322

296323

297324
@dataclass
298325
class FuncParam:
299326
"""A parameter in a function signature."""
300327

301328
name: str
329+
"""The name of the parameter."""
302330
tp: TypeRef
331+
"""The type reference of the parameter."""
303332

304333

305334
@dataclass
306335
class DocFunc:
307336
"""A parsed function."""
308337

309338
name: str
339+
"""The name of the function."""
310340
args: list[FuncParam]
341+
"""The arguments of the function."""
311342
ret: TypeRef
343+
"""The return type of the function."""
312344
doc: Docstring | None
345+
"""The docstring of the function."""
313346

314347

315348
@dataclass
316349
class CodeDoc:
317350
"""A parsed C source file."""
318351

319352
macros: list[DocMacro]
353+
"""List of macros in the source file."""
320354
functions: list[DocFunc]
355+
""""List of functions in the source file."""
321356
global_vars: list[DocGlobalVar]
357+
"""List of global variables in the source file."""
322358
typedefs: dict[str, DocType]
359+
"""List of typedefs in the source file."""
323360

324361

325362
class TypeDecl(str, Enum):
326363
"""Enumeration for type declarations."""
327364

328365
NORMAL = "normal"
366+
"""A normal type declaration."""
329367
POINTER = "pointer"
368+
"""A pointer type declaration."""
330369
ARRAY = "array"
370+
"""An array type declaration."""
331371
FUNCTION = "function"
372+
"""A function type declaration."""
332373

333374

334375
@dataclass
335376
class TypeRef:
336377
"""A reference to a type in C."""
337378

338379
name: TypeRef | str
380+
"""The name of the type reference."""
339381
decl: TypeDecl
382+
"""The type declaration of the type reference."""
340383
quals: list[str]
384+
"""The qualifiers of the type reference."""
341385
params: list[TypeRef] | None = None # only in functions
386+
"""The parameters of the type reference."""
342387

343388

344389
class SupportsQualsAndType(Protocol):
345390
"""A protocol for types that can have qualifiers and a type."""
346391

347392
quals: list[str]
393+
"""The qualifiers of the type."""
348394
type: SupportsQualsAndType | c_ast.TypeDecl | c_ast.IdentifierType
395+
"""The type of the node."""
349396

350397

351398
def ast_to_decl(node: SupportsQualsAndType, types: dict[str, DocType]) -> TypeRef:
@@ -477,25 +524,6 @@ class CHandler(BaseHandler):
477524
fallback_theme: ClassVar[str] = "material"
478525
"""The theme to fallback to."""
479526

480-
fallback_config: ClassVar[dict] = {"fallback": True}
481-
"""The configuration used to collect item during autorefs fallback."""
482-
483-
default_config: ClassVar[dict] = {
484-
"show_root_heading": False,
485-
"show_root_toc_entry": True,
486-
"show_symbol_type_heading": True,
487-
"show_symbol_type_toc_entry": True,
488-
"heading_level": 2,
489-
}
490-
"""The default configuration options.
491-
492-
Option | Type | Description | Default
493-
------ | ---- | ----------- | -------
494-
**`show_root_heading`** | `bool` | Show the heading of the object at the root of the documentation tree. | `False`
495-
**`show_root_toc_entry`** | `bool` | If the root heading is not shown, at least add a ToC entry for it. | `True`
496-
**`heading_level`** | `int` | The initial heading level to use. | `2`
497-
"""
498-
499527
def __init__(self, config: Mapping[str, Any], base_dir: Path, **kwargs: Any) -> None:
500528
"""Initialize the handler.
501529
@@ -507,14 +535,22 @@ def __init__(self, config: Mapping[str, Any], base_dir: Path, **kwargs: Any) ->
507535
super().__init__(**kwargs)
508536

509537
self.config = config
538+
"""The handler configuration."""
510539
self.base_dir = base_dir
540+
"""The base directory of the project."""
511541
self.global_options = config.get("options", {})
542+
"""The global options for the handler."""
512543

513-
def get_options(self, local_options: Mapping[str, Any]) -> Mapping[str, Any]:
544+
def get_options(self, local_options: Mapping[str, Any]) -> COptions:
514545
"""Combine configuration options."""
515-
return {**self.default_config, **self.global_options, **local_options}
516-
517-
def collect(self, identifier: str, options: MutableMapping[str, Any]) -> CollectorItem:
546+
extra = {**self.global_options.get("extra", {}), **local_options.get("extra", {})}
547+
options = {**self.global_options, **local_options, "extra": extra}
548+
try:
549+
return COptions.from_data(**options)
550+
except Exception as error:
551+
raise PluginError(f"Invalid options: {error}") from error
552+
553+
def collect(self, identifier: str, options: COptions) -> CollectorItem:
518554
"""Collect data given an identifier and selection configuration.
519555
520556
In the implementation, you typically call a subprocess that returns JSON, and load that JSON again into
@@ -530,7 +566,7 @@ def collect(self, identifier: str, options: MutableMapping[str, Any]) -> Collect
530566
Returns:
531567
Anything you want, as long as you can feed it to the `render` method.
532568
"""
533-
if options.get("fallback", False):
569+
if options == {}:
534570
raise CollectionError("Not loading additional headers during fallback")
535571

536572
source = Path(identifier).read_text(encoding="utf-8")
@@ -607,7 +643,7 @@ def collect(self, identifier: str, options: MutableMapping[str, Any]) -> Collect
607643

608644
return CodeDoc(macros, funcs, global_vars, types)
609645

610-
def render(self, data: CodeDoc, options: MutableMapping[str, Any]) -> str:
646+
def render(self, data: CodeDoc, options: COptions) -> str:
611647
"""Render a template using provided data and configuration options.
612648
613649
Parameters:
@@ -618,7 +654,7 @@ def render(self, data: CodeDoc, options: MutableMapping[str, Any]) -> str:
618654
Returns:
619655
The rendered template as HTML.
620656
"""
621-
heading_level = options["heading_level"]
657+
heading_level = options.heading_level
622658
template = self.env.get_template("header.html.jinja")
623659
return template.render(
624660
config=options,

0 commit comments

Comments
 (0)