Coverage for sources/librovore/structures/sphinx/detection.py: 25%
43 statements
« prev ^ index » next coverage.py v7.10.5, created at 2025-08-29 01:14 +0000
« prev ^ index » next coverage.py v7.10.5, created at 2025-08-29 01:14 +0000
1# vim: set filetype=python fileencoding=utf-8:
2# -*- coding: utf-8 -*-
4#============================================================================#
5# #
6# Licensed under the Apache License, Version 2.0 (the "License"); #
7# you may not use this file except in compliance with the License. #
8# You may obtain a copy of the License at #
9# #
10# http://www.apache.org/licenses/LICENSE-2.0 #
11# #
12# Unless required by applicable law or agreed to in writing, software #
13# distributed under the License is distributed on an "AS IS" BASIS, #
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15# See the License for the specific language governing permissions and #
16# limitations under the License. #
17# #
18#============================================================================#
21''' Sphinx detection and metadata extraction. '''
24from urllib.parse import ParseResult as _Url
26from . import __
27from . import extraction as _extraction
28from . import urls as _urls
31_scribe = __.acquire_scribe( __name__ )
34class SphinxDetection( __.StructureDetection ):
35 ''' Detection result for Sphinx documentation sources. '''
37 source: str
38 has_searchindex: bool = False
39 normalized_source: str = ''
40 theme: __.typx.Optional[ str ] = None
42 @classmethod
43 async def from_source(
44 selfclass,
45 auxdata: __.ApplicationGlobals,
46 processor: __.Processor,
47 source: str,
48 ) -> __.typx.Self:
49 ''' Constructs detection from source location. '''
50 detection = await processor.detect( auxdata, source )
51 return __.typx.cast( __.typx.Self, detection )
53 async def extract_contents(
54 self,
55 auxdata: __.ApplicationGlobals,
56 source: str,
57 objects: __.cabc.Sequence[ __.InventoryObject ], /, *,
58 include_snippets: bool = True,
59 ) -> tuple[ __.ContentDocument, ... ]:
60 ''' Extracts documentation content for specified objects. '''
61 theme = self.theme if self.theme is not None else __.absent
62 documents = await _extraction.extract_contents(
63 auxdata, source, objects,
64 theme = theme, include_snippets = include_snippets )
65 return tuple( documents )
69async def check_searchindex(
70 auxdata: __.ApplicationGlobals, source: _Url
71) -> bool:
72 ''' Checks if searchindex.js exists (indicates full Sphinx site). '''
73 url = _urls.derive_searchindex_url( source )
74 return await __.probe_url( auxdata.probe_cache, url )
77async def detect_theme(
78 auxdata: __.ApplicationGlobals, source: _Url
79) -> dict[ str, __.typx.Any ]:
80 ''' Detects Sphinx theme and other metadata. '''
81 theme_metadata: dict[ str, __.typx.Any ] = { }
82 html_url = _urls.derive_html_url( source )
83 try:
84 # TODO: Use probe_url instead of `try`.
85 html_content = await __.retrieve_url_as_text(
86 auxdata.content_cache,
87 html_url, duration_max = 10.0 )
88 except __.DocumentationInaccessibility: pass
89 else:
90 html_content_lower = html_content.lower( )
91 if ( 'furo' in html_content_lower
92 or 'css/furo.css' in html_content_lower
93 ): theme_metadata[ 'theme' ] = 'furo'
94 elif ( 'sphinx_rtd_theme' in html_content_lower
95 or 'css/theme.css' in html_content_lower
96 ): theme_metadata[ 'theme' ] = 'sphinx_rtd_theme'
97 elif ( 'alabaster' in html_content_lower
98 or 'css/alabaster.css' in html_content_lower
99 ): theme_metadata[ 'theme' ] = 'alabaster'
100 elif ( 'pydoctheme.css' in html_content_lower
101 or 'classic.css' in html_content_lower
102 ): theme_metadata[ 'theme' ] = 'pydoctheme'
103 elif 'flask.css' in html_content_lower:
104 theme_metadata[ 'theme' ] = 'flask'
105 elif 'css/nature.css' in html_content_lower:
106 theme_metadata[ 'theme' ] = 'nature'
107 elif 'css/default.css' in html_content_lower:
108 theme_metadata[ 'theme' ] = 'classic'
109 elif 'sphinx_book_theme' in html_content_lower:
110 theme_metadata[ 'theme' ] = 'sphinx_book_theme'
111 elif 'pydata_sphinx_theme' in html_content_lower:
112 theme_metadata[ 'theme' ] = 'pydata_sphinx_theme'
113 # If no theme detected, don't set theme key (returns None)
114 return theme_metadata