Skip to content

Commit d80aeb9

Browse files
committed
update
1 parent dcf07bf commit d80aeb9

6 files changed

Lines changed: 131 additions & 42 deletions

File tree

docs/api.rst

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Value, Data, Field and Schema
66
=============================
77

88
.. autotype:: sphinxnotes.render.PlainValue
9+
910
.. autotype:: sphinxnotes.render.Value
1011

1112
.. autoclass:: sphinxnotes.render.RawData
@@ -31,20 +32,40 @@ Value, Data, Field and Schema
3132
The Render Pipeline
3233
===================
3334

35+
Node
36+
-----
37+
38+
.. autoclass:: sphinxnotes.render.pending_node
39+
3440
Context
3541
-------
3642

37-
.. autoclass:: sphinxnotes.render.PendingContext
43+
Context refers dynamic content of Jinja template. It can be:
44+
45+
:py:class:`~sphinxnotes.render.ResolvedContext`:
46+
The data we defined earlier, or any Python dict.
47+
48+
:py:class:`~sphinxnotes.render.PendingContext`:
49+
Any class that can generate this :py:class:`~sphinxnotes.render.ResolvedContext`.
50+
3851
.. autotype:: sphinxnotes.render.ResolvedContext
39-
.. autoclass:: sphinxnotes.render.UnparsedData
4052

41-
.. autoclass:: sphinxnotes.render.pending_node
53+
.. autoclass:: sphinxnotes.render.PendingContext
54+
:members: resolve
55+
56+
PendingContext Implementions
57+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
58+
59+
.. autoclass:: sphinxnotes.render.UnparsedData
60+
:show-inheritance:
4261

4362
Extra Context
4463
-------------
4564

4665
.. autoclass:: sphinxnotes.render.GlobalExtraContxt
66+
4767
.. autoclass:: sphinxnotes.render.ParsePhaseExtraContext
68+
4869
.. autoclass:: sphinxnotes.render.ResolvePhaseExtraContext
4970

5071
.. autoclass:: sphinxnotes.render.ExtraContextRegistry
@@ -62,11 +83,40 @@ Template
6283
Pipeline
6384
--------
6485

86+
Base Role Classes
87+
~~~~~~~~~~~~~~~~~
88+
6589
.. autoclass:: sphinxnotes.render.BaseContextRole
66-
.. autoclass:: sphinxnotes.render.BaseContextDirective
90+
:show-inheritance:
91+
6792
.. autoclass:: sphinxnotes.render.BaseDataDefineRole
93+
:show-inheritance:
94+
95+
Base Directive Classes
96+
~~~~~~~~~~~~~~~~~~~~~~
97+
98+
.. autoclass:: sphinxnotes.render.BaseContextDirective
99+
:show-inheritance:
100+
68101
.. autoclass:: sphinxnotes.render.BaseDataDefineDirective
102+
:show-inheritance:
103+
69104
.. autoclass:: sphinxnotes.render.StrictDataDefineDirective
105+
:show-inheritance:
106+
:members: derive
107+
108+
Internal Used Classes
109+
~~~~~~~~~~~~~~~~~~~~~
110+
111+
.. autoclass:: sphinxnotes.render.pipeline.Pipeline
112+
:members: process_pending_node, queue_pending_node, queue_context
113+
114+
.. autoclass:: sphinxnotes.render.pipeline.BaseContextSource
115+
:show-inheritance:
116+
:members: current_context, current_template
117+
118+
.. autoclass:: sphinxnotes.render.sources.BaseRawDataSource
119+
:members: current_raw_data, current_schema
70120

71121
Registry
72122
========

docs/conf.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,8 @@
130130
'member-order': 'bysource',
131131
}
132132

133-
134133
intersphinx_mapping['python'] = ('https://docs.python.org/3', None)
135134
intersphinx_mapping['sphinx'] = ('https://www.sphinx-doc.org/en/master', None)
136135

137136
def setup(app):
138-
139137
app.add_object_type('event', 'event') # for intersphinx

src/sphinxnotes/render/ctx.py

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
"""
2-
sphinxnotes.render.ctx
3-
~~~~~~~~~~~~~~~~~~~~~~
4-
5-
:copyright: Copyright 2026 by the Shengyu Zhang.
6-
:license: BSD, see LICENSE for details.
7-
8-
This module wraps the :mod:`data` into context for rendering the template.
2+
This module wraps the :py:mod:`sphinxnote.render.data` module into context
3+
suitable for use with Jinja templates.
94
"""
105

116
from typing import Any
@@ -17,6 +12,7 @@
1712
from .utils import Unpicklable
1813

1914
type ResolvedContext = ParsedData | dict[str, Any]
15+
"""The context is """
2016

2117

2218
@dataclass
@@ -31,18 +27,17 @@ def __hash__(self) -> int:
3127

3228

3329
class PendingContext(ABC, Unpicklable, Hashable):
34-
"""A abstract representation of context that is not currently available.
35-
36-
Call :py:meth:`resolve` at the right time (depends on the implment) to get
37-
context available.
38-
"""
30+
"""A abstract representation of context that is not currently available."""
3931

4032
@abstractmethod
41-
def resolve(self) -> ResolvedContext: ...
33+
def resolve(self) -> ResolvedContext:
34+
"""This method will be called when rendering to get the available
35+
:py:type:`ResolvedContext`."""
36+
...
4237

4338

4439
class PendingContextStorage:
45-
"""Area for temporarily storing PendingContext.
40+
"""Area for temporarily storing :py:class:`PendingContext`.
4641
4742
This class is indented to resolve the problem that:
4843

src/sphinxnotes/render/ctxnodes.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121

2222
class pending_node(nodes.Element):
23+
"""A docutils node to be rendered."""
24+
2325
# The context to be rendered by Jinja template.
2426
ctx: PendingContextRef | ResolvedContext
2527
# The extra context as supplement to ctx.
@@ -64,7 +66,7 @@ def __init__(
6466

6567
def render(self, host: Host) -> None:
6668
"""
67-
The core function for rendering context to docutils nodes.
69+
The core function for rendering context and template to docutils nodes.
6870
6971
1. PendingContextRef -> PendingContext -> ResolvedContext
7072
2. TemplateRenderer.render(ResolvedContext) -> Markup Text (``str``)

src/sphinxnotes/render/pipeline.py

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""
1+
"""pip
22
sphinxnotes.render.pipeline
33
~~~~~~~~~~~~~~~~~~~~~~~~~~~
44
@@ -10,13 +10,13 @@
1010
The Pipline
1111
===========
1212
13-
1. Define context: BaseDataSource generates a :class:`pending_node`, which contains:
13+
1. Define context: BaseContextSource generates a :class:`pending_node`, which contains:
1414
1515
- Context
1616
- Template for rendering data to markup text
1717
- Possible extra contexts
1818
19-
See also :class:`BaseDataSource`.
19+
See also :class:`BaseContextSource`.
2020
2121
2. Render data: the ``pending_node`` nodes will be rendered
2222
(by calling :meth:`pending_node.render`) at some point, depending on
@@ -29,7 +29,7 @@
2929
Phases:
3030
3131
:``Phase.Parsing``:
32-
Called by BaseDataSource ('s subclasses)
32+
Called by BaseContextSource ('s subclasses)
3333
3434
:``Phase.Parsed``:
3535
Called by :class:`ParsedHookTransform`.
@@ -67,22 +67,23 @@
6767

6868
class Pipeline(ABC):
6969
"""
70-
The core class defines the pipleing of rendering :class:`pending_node`s.
70+
The core class defines the pipleing of rendering
71+
:py:class:`~sphinxnotes.render.pending_node`\ (s).
7172
7273
Subclass is responsible to:
7374
7475
- call ``queue_xxx`` to add pendin nodes into queue.
75-
- override :meth:`process_pending_node` to control when a pending node gets
76+
- override :py:meth:`~Pipeline.process_pending_node` to control when a pending node gets
7677
rendered. In this method subclass can also call ``queue_xxx`` to add more
7778
pending nodes.
78-
- call :meth:`render_queue` to process all queued nodes and
79+
- call :py:meth:`render_queue` to process all queued nodes and
7980
returns any that couldn't be rendered in the current phase.
8081
8182
See Also:
8283
83-
- :class:`BaseDataSource`: Context source implementation and hook for Phase.Parsing
84-
- :class:`ParsedHookTransform`: Built-in hook for Phase.Parsed
85-
- :class:`ResolvingHookTransform`: Built-in hook for Phase.Resolving
84+
- :py:class:`BaseContextSource`: Context source implementation and hook for Phase.Parsing
85+
- :py:class:`ParsedHookTransform`: Built-in hook for Phase.Parsed
86+
- :py:class:`ResolvingHookTransform`: Built-in hook for Phase.Resolving
8687
"""
8788

8889
#: Queue of pending node to be rendered.
@@ -92,18 +93,28 @@ class Pipeline(ABC):
9293

9394
def process_pending_node(self, n: pending_node) -> bool:
9495
"""
95-
You can add hooks to pending node here.
96+
This method is called when it is the pending node's turn to be rendered.
9697
9798
Return ``true`` if you want to render the pending node *now*,
98-
otherwise it will be inserted to doctree directly andwaiting to later
99-
rendering
99+
otherwise it will be inserted to doctree directly and waiting to later
100+
rendering (and this method will be called again.).
101+
102+
You can add hooks to pending node here. or call :py:meth:`~Pipeline.queue_pending_node`
103+
to. You are responsible for inserting it into the doctree themselves if
104+
the node is created by the yourself.
105+
106+
.. note::
107+
108+
Please always call ``super().process_pending_node(n)`` to ensure the
109+
extension functions properly.
100110
"""
101111
...
102112

103113
"""Helper method for subclasses."""
104114

105115
@final
106116
def queue_pending_node(self, n: pending_node) -> None:
117+
"""Push a new pending_node to the render queue."""
107118
if not self._q:
108119
self._q = []
109120
self._q.append(n)
@@ -112,6 +123,7 @@ def queue_pending_node(self, n: pending_node) -> None:
112123
def queue_context(
113124
self, ctx: PendingContext | ResolvedContext, tmpl: Template
114125
) -> pending_node:
126+
"""A helper method of :py:meth:`Pipeline.queue_pending_node`."""
115127
pending = pending_node(ctx, tmpl)
116128
self.queue_pending_node(pending)
117129
return pending
@@ -121,8 +133,9 @@ def render_queue(self) -> list[pending_node]:
121133
"""
122134
Try rendering all pending nodes in queue.
123135
124-
If the timing(Phase) is ok, :class:`pending_node` will be rendered
125-
(pending.rendered = True); otherwise, the pending node is unchanged.
136+
If the timing(Phase) is ok, :py:class:`sphinxnotes.render.pending_node`
137+
will be rendered (pending.rendered = True); otherwise, the pending node
138+
is unchanged.
126139
127140
If the pending node is already inserted to document, it will not be return.
128141
And the corrsponding rendered node will replace it too.
@@ -176,9 +189,9 @@ class BaseContextSource(Pipeline):
176189
pipeline.
177190
178191
This class also responsible to render context in Phase.Parsing. So the final
179-
implementations MUST be subclass of :class:`SphinxDirective` or
180-
:class:`SphinxRole`, which provide the execution context and interface for
181-
processing reStructuredText markup.
192+
implementations MUST be subclass of :py:class:`~sphinx.util.docutils.SphinxDirective`
193+
or :py:class:`~sphinx.util.docutils.SphinxRole`, which provide the execution
194+
context and interface forrprocessing reStructuredText markup.
182195
"""
183196

184197
"""Methods to be implemented."""
@@ -217,6 +230,13 @@ def process_pending_node(self, n: pending_node) -> bool:
217230

218231

219232
class BaseContextDirective(BaseContextSource, SphinxDirective):
233+
"""This class generates :py:meth:`sphinxnotes.render.pending_node` in
234+
``SphinxDirective.run`` method and make sure it can be correctly rendered.
235+
236+
User should implement ``current_context`` and ``current_template`` methods
237+
for providing the construct parameters of pending_node.
238+
"""
239+
220240
@override
221241
def run(self) -> list[nodes.Node]:
222242
self.queue_context(self.current_context(), self.current_template())
@@ -232,6 +252,13 @@ def run(self) -> list[nodes.Node]:
232252

233253

234254
class BaseContextRole(BaseContextSource, SphinxRole):
255+
"""This class extends generates :py:meth:`sphinxnotes.render.pending_node` in
256+
``SphinxRole.run`` method and make sure it can be correctly rendered.
257+
258+
User should implement ``current_context`` and ``current_template`` methods
259+
for providing the construct parameters of pending_node.
260+
"""
261+
235262
@override
236263
def process_pending_node(self, n: pending_node) -> bool:
237264
n.inline = True

src/sphinxnotes/render/sources.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@
2222

2323
@dataclass
2424
class UnparsedData(PendingContext):
25-
"""A implementation of PendingContext, contains raw data and its schema."""
25+
"""A pending context which contains raw data and its schema.
26+
27+
Raw data will be parsed when calling ``resolve``.
28+
"""
2629

2730
raw: RawData
2831
schema: Schema
@@ -44,10 +47,15 @@ class BaseRawDataSource(BaseContextSource):
4447
"""Methods to be implemented."""
4548

4649
@abstractmethod
47-
def current_raw_data(self) -> RawData: ...
50+
def current_raw_data(self) -> RawData:
51+
"""Return the raw data to be rendered.
52+
User **must not** override ``current_context`` method of this class."""
53+
...
4854

4955
@abstractmethod
50-
def current_schema(self) -> Schema: ...
56+
def current_schema(self) -> Schema:
57+
"""Return the schema of raw data.
58+
User **must not** override ``current_context`` method of this class."""
5159

5260
"""Methods to be overrided."""
5361

@@ -57,6 +65,8 @@ def current_context(self) -> PendingContext | ResolvedContext:
5765

5866

5967
class BaseDataDefineDirective(BaseRawDataSource, BaseContextDirective):
68+
"""User is responsible to implemente ``current_schema`` method."""
69+
6070
@override
6171
def current_raw_data(self) -> RawData:
6272
return RawData(
@@ -90,6 +100,13 @@ def current_schema(self) -> Schema:
90100
def derive(
91101
cls, name: str, schema: Schema, tmpl: Template
92102
) -> type['StrictDataDefineDirective']:
103+
"""Dynamically derive a new directive class from schema and template.
104+
105+
This method generates a new ``StrictDataDefineDirective`` subclass with
106+
the given schema and template. It automatically sets the appropriate
107+
argument counts, option specifications, and content handling based on
108+
the schema definition.
109+
"""
93110
if not schema.name:
94111
required_arguments = 0
95112
optional_arguments = 0

0 commit comments

Comments
 (0)