Skip to content

Commit 33c37f4

Browse files
committed
ext: Add increasement build support for SnippetBuilder
1 parent 23f5f35 commit 33c37f4

File tree

2 files changed

+48
-21
lines changed

2 files changed

+48
-21
lines changed

src/sphinxnotes/snippet/builder.py

Lines changed: 0 additions & 17 deletions
This file was deleted.

src/sphinxnotes/snippet/ext.py

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,31 @@
1111
from __future__ import annotations
1212
from typing import List, Set, TYPE_CHECKING, Dict
1313
import re
14+
from os import path
15+
import time
1416

1517
from docutils import nodes
18+
from sphinx.locale import __
19+
from sphinx.util import logging
20+
from sphinx.builders import Builder
1621

1722
if TYPE_CHECKING:
1823
from sphinx.application import Sphinx
1924
from sphinx.environment import BuildEnvironment
2025
from sphinx.config import Config as SphinxConfig
21-
from sphinx.util import logging
26+
from collections.abc import Iterator
2227

2328
from .config import Config
2429
from . import Snippet, WithTitle, Document, Section
2530
from .picker import pick
2631
from .cache import Cache, Item
2732
from .keyword import Extractor
2833
from .utils import titlepath
29-
from .builder import Builder
3034

3135

3236
logger = logging.getLogger(__name__)
3337

34-
cache:Cache = None
38+
cache:Cache|None = None
3539
extractor:Extractor = Extractor()
3640

3741

@@ -146,8 +150,48 @@ def on_builder_finished(app:Sphinx, exception) -> None:
146150
cache.dump()
147151

148152

153+
class SnippetBuilder(Builder):
154+
name = 'snippet'
155+
epilog = __('The snippet builder produces snippets (not to OUTPUTDIR) for use by snippet CLI tool')
156+
157+
def get_outdated_docs(self) -> Iterator[str]:
158+
""" Modified from :py:meth:`sphinx.builders.html.StandaloneHTMLBuilder.get_outdated_docs`."""
159+
for docname in self.env.found_docs:
160+
if docname not in self.env.all_docs:
161+
logger.debug('[build target] did not in env: %r', docname)
162+
yield docname
163+
continue
164+
165+
assert cache is not None
166+
targetname = cache.itemfile((self.app.config.project, docname))
167+
try:
168+
targetmtime = path.getmtime(targetname)
169+
except Exception:
170+
targetmtime = 0
171+
try:
172+
srcmtime = path.getmtime(self.env.doc2path(docname))
173+
if srcmtime > targetmtime:
174+
logger.debug(
175+
'[build target] targetname %r(%s), docname %r(%s)',
176+
targetname,
177+
_format_modified_time(targetmtime),
178+
docname,
179+
_format_modified_time(path.getmtime(self.env.doc2path(docname))),
180+
)
181+
yield docname
182+
except OSError:
183+
# source doesn't exist anymore
184+
pass
185+
186+
187+
def _format_modified_time(timestamp: float) -> str:
188+
"""Return an RFC 3339 formatted string representing the given timestamp."""
189+
seconds, fraction = divmod(timestamp, 1)
190+
return time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(seconds)) + f'.{fraction:.3f}'
191+
192+
149193
def setup(app:Sphinx):
150-
app.add_builder(Builder)
194+
app.add_builder(SnippetBuilder)
151195

152196
app.add_config_value('snippet_config', {}, '')
153197
app.add_config_value('snippet_patterns', {'*':['.*']}, '')

0 commit comments

Comments
 (0)