Skip to content

Commit fde2019

Browse files
committed
refactor: Prepare public filtering method feature
Issue-78: #78
1 parent 9f43ed9 commit fde2019

File tree

29 files changed

+3475
-18
lines changed

29 files changed

+3475
-18
lines changed

docs/insiders/changelog.md

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## mkdocstrings-python Insiders
44

5+
### 1.11.0 <small>March 20, 2025</small> { id="1.11.0" }
6+
7+
- [Filtering method: `public`][option-filters-public]
8+
59
### 1.10.0 <small>March 10, 2025</small> { id="1.10.0" }
610

711
- [Backlinks][backlinks]

docs/insiders/goals.yml

+3
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,6 @@ goals:
4545
- name: Backlinks
4646
ref: /usage/configuration/general/#backlinks
4747
since: 2025/03/10
48+
- name: "Filtering method: `public`"
49+
ref: /usage/configuration/members/#option-filters-public
50+
since: 2025/03/20

docs/usage/configuration/members.md

+15-4
Original file line numberDiff line numberDiff line change
@@ -335,10 +335,21 @@ def function_c():
335335
[](){#option-filters}
336336
## `filters`
337337

338-
- **:octicons-package-24: Type <code><autoref identifier="list" optional>list</autoref>[<autoref identifier="str" optional>str</autoref>] | None</code> :material-equal: `["!^_[^_]"]`{ title="default value" }**
338+
- **:octicons-package-24: Type <code><autoref identifier="list" optional>list</autoref>[<autoref identifier="str" optional>str</autoref>] | <autoref identifier="typing.Literal" optional>Literal</autoref>["public"] | None</code> :material-equal: `["!^_[^_]"]`{ title="default value" }**
339339
<!-- - **:octicons-project-template-24: Template :material-null:** (N/A) -->
340340

341-
A list of filters applied to filter objects based on their name.
341+
A list of filters, or `"public"`.
342+
343+
**Filtering methods**
344+
345+
[](){#option-filters-public}
346+
347+
[:octicons-heart-fill-24:{ .pulse } Sponsors only](../../insiders/index.md){ .insiders } &mdash;
348+
[:octicons-tag-24: Insiders 1.11.0](../../insiders/changelog.md#1.11.0)
349+
350+
The `public` filtering method will include only public objects: those added to the `__all__` attribute of modules, or not starting with a single underscore. Special methods and attributes ("dunder" methods/attributes, starting and ending with two underscores), like `__init__`, `__call__`, `__mult__`, etc., are always considered public.
351+
352+
**List of filters**
342353

343354
Filters are regular expressions. These regular expressions are evaluated by Python
344355
and so must match the syntax supported by the [`re`][] module.
@@ -379,13 +390,13 @@ plugins:
379390
python:
380391
options:
381392
filters:
382-
- "!^_"
393+
- "!^_[^_]"
383394
```
384395

385396
```md title="or in docs/some_page.md (local configuration)"
386397
::: package.module
387398
options:
388-
filters: []
399+
filters: public
389400
```
390401

391402
```python title="package/module.py"

mkdocs.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ plugins:
160160
ignore_init_summary: true
161161
docstring_section_style: list
162162
extensions: [scripts/griffe_extensions.py]
163-
filters: ["!^_"]
163+
filters: public
164164
heading_level: 1
165165
inherited_members: true
166166
line_length: 88

src/mkdocstrings_handlers/python/_internal/config.py

+19-4
Original file line numberDiff line numberDiff line change
@@ -432,14 +432,24 @@ class PythonInputOptions:
432432
] = field(default_factory=list)
433433

434434
filters: Annotated[
435-
list[str],
435+
list[str] | Literal["public"],
436436
_Field(
437437
group="members",
438-
description="""A list of filters applied to filter objects based on their name.
438+
description="""A list of filters, or `"public"`.
439+
440+
**List of filters**
439441
440442
A filter starting with `!` will exclude matching objects instead of including them.
441443
The `members` option takes precedence over `filters` (filters will still be applied recursively
442444
to lower members in the hierarchy).
445+
446+
**Filtering methods**
447+
448+
[:octicons-heart-fill-24:{ .pulse } Sponsors only](../insiders/index.md){ .insiders } &mdash;
449+
[:octicons-tag-24: Insiders 1.11.0](../insiders/changelog.md#1.11.0)
450+
451+
The `public` method will include only public objects:
452+
those added to `__all__` or not starting with an underscore (except for special methods/attributes).
443453
""",
444454
),
445455
] = field(default_factory=lambda: _DEFAULT_FILTERS.copy())
@@ -916,12 +926,12 @@ def from_data(cls, **data: Any) -> Self:
916926
class PythonOptions(PythonInputOptions): # type: ignore[override,unused-ignore]
917927
"""Final options passed as template context."""
918928

919-
filters: list[tuple[re.Pattern, bool]] = field( # type: ignore[assignment]
929+
filters: list[tuple[re.Pattern, bool]] | Literal["public"] = field( # type: ignore[assignment]
920930
default_factory=lambda: [
921931
(re.compile(filtr.removeprefix("!")), filtr.startswith("!")) for filtr in _DEFAULT_FILTERS
922932
],
923933
)
924-
"""A list of filters applied to filter objects based on their name."""
934+
"""A list of filters, or `"public"`."""
925935

926936
summary: SummaryOption = field(default_factory=SummaryOption)
927937
"""Whether to render summaries of modules, classes, functions (methods) and attributes."""
@@ -930,6 +940,11 @@ class PythonOptions(PythonInputOptions): # type: ignore[override,unused-ignore]
930940
def coerce(cls, **data: Any) -> MutableMapping[str, Any]:
931941
"""Create an instance from a dictionary."""
932942
if "filters" in data:
943+
# Non-insiders: transform back to default filters.
944+
# Next: `if "filters" in data and not isinstance(data["filters"], str):`.
945+
if data["filters"] == "public":
946+
data["filters"] = _DEFAULT_FILTERS
947+
# Filters are `None` or a sequence of strings (tests use tuples).
933948
data["filters"] = [
934949
(re.compile(filtr.removeprefix("!")), filtr.startswith("!")) for filtr in data["filters"] or ()
935950
]

src/mkdocstrings_handlers/python/_internal/rendering.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ def _keep_object(name: str, filters: Sequence[tuple[Pattern, bool]]) -> bool:
399399
def do_filter_objects(
400400
objects_dictionary: dict[str, Object | Alias],
401401
*,
402-
filters: Sequence[tuple[Pattern, bool]] | None = None,
402+
filters: Sequence[tuple[Pattern, bool]] | Literal["public"] | None = None,
403403
members_list: bool | list[str] | None = None,
404404
inherited_members: bool | list[str] = False,
405405
keep_no_docstrings: bool = True,
@@ -408,7 +408,7 @@ def do_filter_objects(
408408
409409
Parameters:
410410
objects_dictionary: The dictionary of objects.
411-
filters: Filters to apply, based on members' names.
411+
filters: Filters to apply, based on members' names, or `"public"`.
412412
Each element is a tuple: a pattern, and a boolean indicating whether
413413
to reject the object if the pattern matches.
414414
members_list: An optional, explicit list of members to keep.
@@ -449,7 +449,9 @@ def do_filter_objects(
449449
]
450450

451451
# Use filters and docstrings.
452-
if filters:
452+
if filters == "public":
453+
objects = [obj for obj in objects if obj.is_public]
454+
elif filters:
453455
objects = [
454456
obj for obj in objects if _keep_object(obj.name, filters) or (inherited_members_specified and obj.inherited)
455457
]

src/mkdocstrings_handlers/python/templates/material/_base/children.html.jinja

+5-5
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ Context:
4949
{% endif %}
5050
{% with heading_level = heading_level + extra_level %}
5151
{% for attribute in attributes|order_members(config.members_order, members_list) %}
52-
{% if members_list is not none or (not attribute.is_imported or attribute.is_public) %}
52+
{% if config.filters == "public" or members_list is not none or (not attribute.is_imported or attribute.is_public) %}
5353
{% include attribute|get_template with context %}
5454
{% endif %}
5555
{% endfor %}
@@ -69,7 +69,7 @@ Context:
6969
{% endif %}
7070
{% with heading_level = heading_level + extra_level %}
7171
{% for class in classes|order_members(config.members_order, members_list) %}
72-
{% if members_list is not none or (not class.is_imported or class.is_public) %}
72+
{% if config.filters == "public" or members_list is not none or (not class.is_imported or class.is_public) %}
7373
{% include class|get_template with context %}
7474
{% endif %}
7575
{% endfor %}
@@ -90,7 +90,7 @@ Context:
9090
{% with heading_level = heading_level + extra_level %}
9191
{% for function in functions|order_members(config.members_order, members_list) %}
9292
{% if not (obj.kind.value == "class" and function.name == "__init__" and config.merge_init_into_class) %}
93-
{% if members_list is not none or (not function.is_imported or function.is_public) %}
93+
{% if config.filters == "public" or members_list is not none or (not function.is_imported or function.is_public) %}
9494
{% include function|get_template with context %}
9595
{% endif %}
9696
{% endif %}
@@ -112,7 +112,7 @@ Context:
112112
{% endif %}
113113
{% with heading_level = heading_level + extra_level %}
114114
{% for module in modules|order_members("alphabetical", members_list) %}
115-
{% if members_list is not none or (not module.is_alias or module.is_public) %}
115+
{% if config.filters == "public" or members_list is not none or (not module.is_alias or module.is_public) %}
116116
{% include module|get_template with context %}
117117
{% endif %}
118118
{% endfor %}
@@ -137,7 +137,7 @@ Context:
137137

138138
{% if not (obj.is_class and child.name == "__init__" and config.merge_init_into_class) %}
139139

140-
{% if members_list is not none or child.is_public %}
140+
{% if config.filters == "public" or members_list is not none or child.is_public %}
141141
{% if child.is_attribute %}
142142
{% with attribute = child %}
143143
{% include attribute|get_template with context %}

tests/snapshots/__init__.py

+30
Original file line numberDiff line numberDiff line change
@@ -353,5 +353,35 @@
353353
("inherited_members", ()),
354354
("members", ()),
355355
): external("a185e216dc7b*.html"),
356+
(("filters", "public"), ("inherited_members", ("method1",)), ("members", None)): external("6af55596d9c4*.html"),
357+
(("filters", "public"), ("inherited_members", ("method1",)), ("members", False)): external(
358+
"6abf5ddd819b*.html",
359+
),
360+
(("filters", "public"), ("inherited_members", ()), ("members", None)): external("6d72c524b827*.html"),
361+
(("filters", "public"), ("inherited_members", False), ("members", False)): external("9dab67183389*.html"),
362+
(("filters", "public"), ("inherited_members", ("method1",)), ("members", True)): external("6c0b7207df03*.html"),
363+
(("filters", "public"), ("inherited_members", True), ("members", ())): external("f48d651b3f1a*.html"),
364+
(("filters", "public"), ("inherited_members", ("method1",)), ("members", ("module_attribute",))): external(
365+
"408244423577*.html",
366+
),
367+
(("filters", "public"), ("inherited_members", True), ("members", None)): external("16295fa51a2c*.html"),
368+
(("filters", "public"), ("inherited_members", True), ("members", True)): external("37232379c426*.html"),
369+
(("filters", "public"), ("inherited_members", ()), ("members", ())): external("2e866eca9a45*.html"),
370+
(("filters", "public"), ("inherited_members", True), ("members", False)): external("ed5d07bcdbaa*.html"),
371+
(("filters", "public"), ("inherited_members", False), ("members", ())): external("135f57223e00*.html"),
372+
(("filters", "public"), ("inherited_members", False), ("members", None)): external("b4e20d5cd52e*.html"),
373+
(("filters", "public"), ("inherited_members", ()), ("members", False)): external("46daa7e60b98*.html"),
374+
(("filters", "public"), ("inherited_members", False), ("members", True)): external("a255ee80bf7a*.html"),
375+
(("filters", "public"), ("inherited_members", ()), ("members", True)): external("74e2496015e1*.html"),
376+
(("filters", "public"), ("inherited_members", True), ("members", ("module_attribute",))): external(
377+
"e254ae60f9af*.html",
378+
),
379+
(("filters", "public"), ("inherited_members", ("method1",)), ("members", ())): external("51d73351dc55*.html"),
380+
(("filters", "public"), ("inherited_members", ()), ("members", ("module_attribute",))): external(
381+
"d56d3aeae22b*.html",
382+
),
383+
(("filters", "public"), ("inherited_members", False), ("members", ("module_attribute",))): external(
384+
"80399c502938*.html",
385+
),
356386
},
357387
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<!--
2+
{
3+
"filters": "public",
4+
"inherited_members": false,
5+
"members": []
6+
}
7+
-->
8+
9+
<div class="doc doc-object doc-module">
10+
<h1 class="doc doc-heading" id="members_package">
11+
<code>
12+
members_package
13+
</code>
14+
</h1>
15+
<div class="doc doc-contents first">
16+
<p>
17+
Docstring for the package.
18+
</p>
19+
<div class="doc doc-children">
20+
</div>
21+
</div>
22+
</div>

0 commit comments

Comments
 (0)