Skip to content

Commit 64d5224

Browse files
committed
update
1 parent 4518322 commit 64d5224

6 files changed

Lines changed: 93 additions & 57 deletions

File tree

src/sphinxnotes/data/__init__.py

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,27 @@
1717

1818
from . import meta
1919
from .data import Field, Schema
20-
from . import template
21-
from . import render
20+
from .template import Template, Phase
21+
from .render import BaseDataDirective, BaseDataRole, pending_node
2222
from .utils.freestyle import FreeStyleDirective, FreeStyleOptionSpec
2323

2424
logger = logging.getLogger(__name__)
2525

2626
TEMPLATE_KEY = 'sphinxnotes:template'
2727
SCHEMA_KEY = 'sphinxnotes:data'
2828

29+
2930
class TemplateDirective(SphinxDirective):
3031
option_spec = {
31-
'on': template.Phase.option_spec,
32+
'on': Phase.option_spec,
3233
'debug': directives.flag,
3334
}
3435
has_content = True
3536

3637
def run(self) -> list[nodes.Node]:
37-
self.env.current_document[TEMPLATE_KEY] = template.Template(
38+
self.env.current_document[TEMPLATE_KEY] = Template(
3839
text='\n'.join(self.content),
39-
phase=self.options.get('on', template.Phase.default()),
40+
phase=self.options.get('on', Phase.default()),
4041
debug='debug' in self.options,
4142
)
4243

@@ -59,46 +60,63 @@ def run(self) -> list[nodes.Node]:
5960

6061
return []
6162

62-
class ContextfulDataRole(render.BaseDataRole):
63+
64+
class ContextfulDataRole(BaseDataRole):
6365
@override
64-
def current_template(self) -> template.Template:
65-
tmpl = self.env.current_document.get(TEMPLATE_KEY, template.Template.preset_role())
66-
return cast(template.Template, tmpl)
66+
def current_template(self) -> Template:
67+
tmpl = self.env.current_document.get(TEMPLATE_KEY, Template.preset_role())
68+
return cast(Template, tmpl)
6769

6870
@override
6971
def current_schema(self) -> Schema:
7072
schema = self.env.current_document.get(SCHEMA_KEY, Schema.role_default())
7173
return cast(Schema, schema)
7274

7375

74-
class ContextfulDataDirective(render.BaseDataDirective, FreeStyleDirective):
76+
class FreeDataDirective(BaseDataDirective, FreeStyleDirective):
7577
optional_arguments = 1
7678
has_content = True
7779

7880
@override
79-
def current_template(self) -> template.Template:
80-
tmpl = self.env.current_document.get(TEMPLATE_KEY, template.Template.preset_directive())
81-
return cast(template.Template, tmpl)
81+
def current_template(self) -> Template:
82+
tmpl = self.env.current_document.get(TEMPLATE_KEY, Template.preset_directive())
83+
return cast(Template, tmpl)
8284

8385
@override
8486
def current_schema(self) -> Schema:
8587
schema = self.env.current_document.get(SCHEMA_KEY, Schema.directive_default())
8688
return cast(Schema, schema)
8789

8890

91+
class AutoFreeDataDirective(FreeDataDirective):
92+
@override
93+
def process_pending_node(self, n: pending_node) -> None:
94+
n.name_external = n.content_external = True
95+
96+
@override
97+
def current_template(self) -> Template:
98+
tmpl = super().current_template()
99+
tmpl.phase = Phase.Parsed
100+
return tmpl
101+
89102

90103
def setup(app: Sphinx):
91104
meta.pre_setup(app)
92105

106+
from . import template
107+
from . import render
108+
93109
template.setup(app)
94110
render.setup(app)
95111

96112
app.add_config_value('data_template_debug', True, types=bool, rebuild='')
97113

114+
app.add_directive('data', FreeDataDirective)
115+
app.add_directive('data.auto', AutoFreeDataDirective)
116+
98117
app.add_directive('data.tmpl', TemplateDirective)
118+
app.add_directive('data.template', TemplateDirective)
99119
app.add_directive('data.schema', SchemaDirective)
100-
app.add_directive('data', ContextfulDataDirective)
101-
#app.add_directive('data.auto', AutoDataDirective)
102120

103121
app.add_role('data', ContextfulDataRole())
104122

src/sphinxnotes/data/data.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,6 @@ def parse(self, rawval: str | None) -> Value:
212212
raise ValueError(f"failed to parse '{rawval}' as {self.etype}: {e}")
213213

214214

215-
216215
@dataclasses.dataclass(frozen=True)
217216
class Schema(object):
218217
name: Field | None

src/sphinxnotes/data/render.py

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
logger = logging.getLogger(__name__)
2626

27+
2728
class BaseNode(nodes.Node):
2829
data: Data
2930
template: Template
@@ -57,11 +58,15 @@ def render(self, caller: Caller, replace: bool = False) -> rendered_node:
5758

5859
renderer = self._get_caller_markup_parser(caller)
5960
rendered = rendered_node()
60-
rendered += self.template.render(renderer, parsed, {
61-
**extra_contexts.sphinx(caller),
62-
**extra_contexts.doctree(self),
63-
**extra_contexts.markup(self),
64-
})
61+
rendered += self.template.render(
62+
renderer,
63+
parsed,
64+
{
65+
**extra_contexts.sphinx(caller),
66+
**extra_contexts.doctree(self),
67+
**extra_contexts.markup(self),
68+
},
69+
)
6570
rendered.update_all_atts(self)
6671

6772
if replace:
@@ -78,40 +83,42 @@ def _resolve_external_name(self, caller_parent: nodes.Element | None) -> str | N
7883

7984
def _resolve_external_content(self) -> str | None:
8085
if not self.parent:
81-
return None # TODO
86+
return None # TODO
8287
contnodes = []
8388
for i, child in enumerate(self.parent):
8489
if child == self:
8590
contnodes = self.parent[i:]
8691
break
8792
return '\n\n'.join([n.astext() for n in contnodes])
8893

89-
90-
def _get_caller_markup_parser(self, caller: Caller) -> MarkupParser:
94+
def _get_caller_markup_parser(self, caller: Caller) -> MarkupParser:
9195
if isinstance(caller, SphinxDirective):
9296
return caller.parse_text_to_nodes
9397
if isinstance(caller, SphinxRole):
98+
9499
def wrapper(text: str) -> list[nodes.Node]:
95100
return utils.role_parse_text_to_nodes(caller, text)
101+
96102
return wrapper
97103
else:
98104
return utils.parse_text_to_nodes
99105

100-
def _get_caller_parent(self, caller: Caller) -> nodes.Element | None:
106+
def _get_caller_parent(self, caller: Caller) -> nodes.Element | None:
101107
if isinstance(caller, SphinxDirective):
102108
return caller.state.parent
103109
if isinstance(caller, SphinxRole):
104110
return caller.inliner.parent
105111
else:
106112
return None
107113

108-
def _get_caller_reporter(self, caller: Caller, e: ValueError) -> Exception:
114+
def _get_caller_reporter(self, caller: Caller, e: ValueError) -> Exception:
109115
if isinstance(caller, SphinxDirective):
110116
raise caller.error(str(e))
111117
if isinstance(caller, SphinxRole):
112-
... # TODO
118+
... # TODO
113119
else:
114-
... # TODO
120+
... # TODO
121+
115122

116123
class rendered_node(BaseNode, nodes.container):
117124
anchor: nodes.Element | None
@@ -134,7 +141,6 @@ def process_rendered_node(self, n: rendered_node) -> None: ...
134141

135142

136143
class BaseDataDirective(BaseDataMarkup, SphinxDirective):
137-
138144
"""Methods overridden from parent."""
139145

140146
@override
@@ -165,13 +171,12 @@ def build_pending_node(self) -> pending_node:
165171
return n
166172

167173
def render_pending_node(self, pending: pending_node) -> rendered_node:
168-
rendered = pending.render(self)
169-
self.process_rendered_node(rendered)
170-
return rendered
174+
rendered = pending.render(self)
175+
self.process_rendered_node(rendered)
176+
return rendered
171177

172178

173179
class BaseDataRole(BaseDataMarkup, SphinxRole):
174-
175180
"""Methods overridden from parent."""
176181

177182
@override
@@ -199,9 +204,9 @@ def build_pending_node(self) -> pending_node:
199204
return n
200205

201206
def render_pending_node(self, pending: pending_node) -> rendered_node:
202-
rendered = pending.render(self)
203-
self.process_rendered_node(rendered)
204-
return rendered
207+
rendered = pending.render(self)
208+
self.process_rendered_node(rendered)
209+
return rendered
205210

206211

207212
class AutoDataDirective(BaseDataDirective):
@@ -217,7 +222,9 @@ class FixedDataDirective(BaseDataDirective):
217222
template: Template
218223

219224
@classmethod
220-
def derive(cls, name: str, tmpl: Template, schema: Schema) -> type[FixedDataDirective]:
225+
def derive(
226+
cls, name: str, tmpl: Template, schema: Schema
227+
) -> type[FixedDataDirective]:
221228
"""Generate an AnyDirective child class for describing object."""
222229
if not schema.name:
223230
required_arguments = 0
@@ -242,7 +249,7 @@ def derive(cls, name: str, tmpl: Template, schema: Schema) -> type[FixedDataDire
242249
# Generate directive class
243250
return type(
244251
'%sFixedDataDirective' % name.title(),
245-
(FixedDataDirective, ),
252+
(FixedDataDirective,),
246253
{
247254
'schema': schema,
248255
'template': tmpl,
@@ -262,7 +269,6 @@ def current_schema(self) -> Schema:
262269
return self.schema
263270

264271

265-
266272
class _ParsedHook(SphinxDirective):
267273
def run(self) -> list[nodes.Node]:
268274
# Save origin system_message method.

src/sphinxnotes/data/template.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
type MarkupParser = Callable[[str], list[nodes.Node]]
2121

22+
2223
class Phase(Enum):
2324
Parsing = 'parsing'
2425
Parsed = 'parsed'
@@ -34,13 +35,14 @@ def option_spec(cls, arg):
3435
return cls[choice.title()]
3536

3637

37-
@dataclasses.dataclass(frozen=True)
38+
@dataclasses.dataclass()
3839
class Template(object):
3940
text: str
4041
phase: Phase
4142
debug: bool
4243

43-
def render(self, parser: MarkupParser, data: Parsed, extractx: dict[str, Any]
44+
def render(
45+
self, parser: MarkupParser, data: Parsed, extractx: dict[str, Any]
4446
) -> list[nodes.Node]:
4547
ctx = data.ascontext()
4648
ctx.update(**extractx)
@@ -52,7 +54,9 @@ def render(self, parser: MarkupParser, data: Parsed, extractx: dict[str, Any]
5254
reporter = Reporter('Template debug report')
5355
reporter.append_text('Data:')
5456
reporter.append_code(pformat(data), lang='python')
55-
reporter.append_text(f'Template (phase: {self.phase}, debug: {self.debug}):')
57+
reporter.append_text(
58+
f'Template (phase: {self.phase}, debug: {self.debug}):'
59+
)
5660
reporter.append_code(self.text, lang='jinja')
5761
reporter.append_text('Rendered ndoes:')
5862
reporter.append_code('\n'.join(n.pformat() for n in ns), lang='xml')
@@ -61,14 +65,15 @@ def render(self, parser: MarkupParser, data: Parsed, extractx: dict[str, Any]
6165

6266
return ns
6367

64-
6568
def _render(self, ctx: dict[str, Any]) -> str:
6669
return _JinjaEnv().from_string(self.text).render(ctx)
6770

68-
6971
@classmethod
7072
def preset_directive(cls) -> Template:
71-
return Template(debug=True, phase=Phase.Parsing, text="""
73+
return Template(
74+
debug=True,
75+
phase=Phase.Parsing,
76+
text="""
7277
.. note::
7378
7479
This is a default template for rendering the data your deinfed.
@@ -82,19 +87,22 @@ def preset_directive(cls) -> Template:
8287
::
8388
8489
{{ content or 'None' }}""",
85-
)
90+
)
8691

8792
@classmethod
8893
def preset_role(cls) -> Template:
89-
return Template(debug=True,phase=Phase.Parsing, text="""
94+
return Template(
95+
debug=True,
96+
phase=Phase.Parsing,
97+
text="""
9098
``{{ content or 'None' }}``
9199
:abbr:`ⁱⁿᶠᵒ (This is a default template for rendering the data your deinfed
92100
Please create your own template using the data.tmpl directive.)`""",
93-
)
101+
)
94102

95103
@classmethod
96104
def preset_nope(cls) -> Template:
97-
return Template(debug=False,phase=Phase.Parsing, text='')
105+
return Template(debug=False, phase=Phase.Parsing, text='')
98106

99107

100108
class _JinjaEnv(SandboxedEnvironment):
@@ -141,5 +149,6 @@ def __init__(self):
141149
for name, factory in self._filter_factories.items():
142150
self.filters[name] = factory(self._builder.env)
143151

152+
144153
def setup(app: Sphinx):
145154
_JinjaEnv.setup(app)

src/sphinxnotes/data/utils/__init__.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@ def role_parse_text_to_nodes(self: SphinxRole, text: str) -> list[nodes.Node]:
2727
Utility for parsing reStructuredText (without Sphinx stuffs) to nodes in
2828
SphinxRole Context.
2929
"""
30-
memo = Struct(document=self.inliner.document,
31-
reporter=self.inliner.reporter,
32-
language=self.inliner.language)
30+
memo = Struct(
31+
document=self.inliner.document,
32+
reporter=self.inliner.reporter,
33+
language=self.inliner.language,
34+
)
3335
ns, msgs = self.inliner.parse(text, self.lineno, memo, self.inliner.parent)
3436
return ns + msgs
3537

@@ -74,16 +76,18 @@ def find_titular_node_upward(node: nodes.Element | None) -> nodes.Element | None
7476
return para
7577
return find_titular_node_upward(node.parent)
7678

77-
class Reporter(nodes.system_message):
7879

79-
def __init__(self, title: str, level: Lit['DEBUG'] | Lit['INFO']| Lit['WARNING'] | Lit['ERROR'] = 'DEBUG') -> None:
80+
class Reporter(nodes.system_message):
81+
def __init__(
82+
self,
83+
title: str,
84+
level: Lit['DEBUG'] | Lit['INFO'] | Lit['WARNING'] | Lit['ERROR'] = 'DEBUG',
85+
) -> None:
8086
super().__init__(title + ':', type=level, level=2, source='')
8187

82-
8388
def append_text(self, text: str) -> None:
8489
self += nodes.paragraph(text, text)
8590

86-
8791
def append_code(self, code: str, lang: str | None = None) -> None:
8892
blk = nodes.literal_block(code, code)
8993
if lang:

src/sphinxnotes/data/utils/context_proxy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ def __str__(self) -> str:
100100
class NodeWithTitle(Node):
101101
@proxy_property
102102
def title(self) -> Node | None:
103-
return find_first_child(self._obj, nodes.Titular) # type: ignore
103+
return find_first_child(self._obj, nodes.Titular) # type: ignore
104104

105105

106106
@dataclass(frozen=True)

0 commit comments

Comments
 (0)