11"""Sphinx extension."""
22
3- import copy
43import shlex
54from pathlib import Path
6- from typing import Any
5+ from typing import TYPE_CHECKING , Any
76
87from docutils .nodes import Body , Node , paragraph
8+ from docutils .parsers .rst .states import RSTState
99from docutils .statemachine import StringList
1010from jinja2 import Environment
1111from sphinx .application import Sphinx
1212from sphinx .config import Config
13+ from sphinx .environment import BuildEnvironment
1314from sphinx .errors import ConfigError , ExtensionError , SphinxError
1415from sphinx .util .docutils import SphinxDirective
1516from sphinx .util .typing import ExtensionMetadata
2223
2324LAST_PART = "__end__"
2425
26+ if TYPE_CHECKING :
27+ from sphinx .environment import _CurrentDocument
28+
2529
2630class CurrentDocumentMixin :
31+ """Mixin adding the current document property and context."""
32+
33+ if TYPE_CHECKING :
34+ env : BuildEnvironment
35+
2736 # NOTE: sphinx 8.2.0 introduced "current_document", temp_data is deprecated and kept only for
2837 # backwards compatability: https://github.com/sphinx-doc/sphinx/pull/13151
2938 @property
30- def current_document (self ):
39+ def current_document (self ) -> "_CurrentDocument" :
3140 if hasattr (self .env , "current_document" ):
3241 return self .env .current_document
3342 else :
3443 return self .env .temp_data
3544
3645 @property
37- def context (self ):
38- return self .current_document ["tutorial-context" ]
46+ def context (self ) -> dict [ str , Any ] :
47+ return self .current_document ["tutorial-context" ] # type: ignore[no-any-return]
3948
4049 @property
4150 def jinja (self ) -> Environment :
42- return self .current_document ["tutorial-env" ]
51+ return self .current_document ["tutorial-env" ] # type: ignore[no-any-return]
4352
4453
4554class TutorialDirective (CurrentDocumentMixin , SphinxDirective ):
@@ -49,7 +58,7 @@ class TutorialDirective(CurrentDocumentMixin, SphinxDirective):
4958 required_arguments = 1
5059 optional_arguments = 0
5160
52- def get_tutorial_path (self , tutorial : str ) -> str :
61+ def get_tutorial_path (self , tutorial : str ) -> Path :
5362 root : Path = self .config .tutorial_root
5463 tutorial_path = Path (tutorial )
5564 if tutorial_path .is_absolute ():
@@ -60,9 +69,9 @@ def get_tutorial_path(self, tutorial: str) -> str:
6069 return absolute_path
6170
6271 def run (self ) -> list [Node ]:
63- tutorial = self .arguments [0 ].strip ()
72+ tutorial_arg = self .arguments [0 ].strip ()
6473
65- tutorial_path = self .get_tutorial_path (tutorial )
74+ tutorial_path = self .get_tutorial_path (tutorial_arg )
6675 tutorial = load_tutorial (tutorial_path )
6776
6877 self .current_document ["tutorial" ] = tutorial
@@ -84,10 +93,10 @@ class PartDirective(CurrentDocumentMixin, SphinxDirective):
8493 required_arguments = 0
8594 optional_arguments = 1 # Next part to display
8695
87- def render (self , template : str , ** extra_context : dict [ str , Any ] ) -> str :
96+ def render (self , template : str , ** extra_context : Any ) -> str :
8897 return self .jinja .from_string (template ).render ({** self .context , ** extra_context })
8998
90- def get_command (self , command : Command ) -> dict :
99+ def get_command (self , command : Command ) -> dict [ str , Any ] :
91100 if isinstance (command .command , str ):
92101 args = self .jinja .from_string (command .command ).render (self .context )
93102 else :
@@ -128,13 +137,6 @@ def render_file(self, file: File) -> str:
128137 { file }
129138"""
130139
131- @property
132- def current_document (self ):
133- if hasattr (self .env , "current_document" ):
134- return self .env .current_document
135- else :
136- return self .env .temp_data
137-
138140 def run (self ) -> list [paragraph ]:
139141 node = paragraph ()
140142
@@ -166,7 +168,7 @@ def run(self) -> list[paragraph]:
166168 raise ExtensionError (f"{ next_part_id } : Part not found." )
167169
168170 lines = StringList (text .splitlines ())
169- state : Body = self .state
171+ state : RSTState = self .state
170172 state .nested_parse (lines , 0 , node )
171173 return [node ]
172174
0 commit comments