Spaces:
Configuration error
Configuration error
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | |
| # SPDX-License-Identifier: Apache-2.0 | |
| # | |
| # Licensed under the Apache License, Version 2.0 (the "License"); | |
| # you may not use this file except in compliance with the License. | |
| # You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, software | |
| # distributed under the License is distributed on an "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| # See the License for the specific language governing permissions and | |
| # limitations under the License. | |
| """Utility functions for JSON output.""" | |
| import fnmatch | |
| from typing import Any | |
| from sphinx.application import Sphinx | |
| from sphinx.config import Config | |
| from sphinx.util import logging | |
| logger = logging.getLogger(__name__) | |
| def validate_content_gating_integration(app: Sphinx) -> None: | |
| """Validate that content gating integration is working properly.""" | |
| # Check if content_gating extension is loaded | |
| if "content_gating" in app.extensions: | |
| logger.info("Content gating extension detected - JSON output will respect content gating rules") | |
| else: | |
| logger.debug("Content gating extension not detected - JSON output will process all documents") | |
| # Log current exclude patterns for debugging | |
| exclude_patterns = getattr(app.config, "exclude_patterns", []) | |
| if exclude_patterns: | |
| logger.debug(f"Current exclude patterns: {exclude_patterns}") | |
| # Check current build tags for debugging | |
| if hasattr(app, "tags"): | |
| try: | |
| current_tags = set(app.tags) | |
| if current_tags: | |
| logger.info(f"Active build tags: {current_tags}") | |
| else: | |
| logger.info("No build tags active") | |
| except (TypeError, AttributeError): | |
| logger.debug("Could not determine active build tags") | |
| def get_setting(config: Config, key: str, default: Any = None) -> Any: # noqa: ANN401 | |
| """Get a setting from json_output_settings with fallback to old config names.""" | |
| settings = getattr(config, "json_output_settings", {}) | |
| # Try new settings format first | |
| if key in settings: | |
| return settings[key] | |
| # Fallback to old config names for backward compatibility | |
| old_config_map = { | |
| "enabled": "json_output_enabled", | |
| "exclude_patterns": "json_output_exclude_patterns", | |
| "verbose": "json_output_verbose", | |
| "parallel": "json_output_parallel", | |
| "include_children": "json_output_include_children", | |
| "include_child_content": "json_output_include_child_content", | |
| "main_index_mode": "json_output_main_index_mode", | |
| "max_main_index_docs": "json_output_max_main_index_docs", | |
| } | |
| old_key = old_config_map.get(key) | |
| if old_key and hasattr(config, old_key): | |
| return getattr(config, old_key) | |
| return default | |
| def is_content_gated(config: Config, docname: str) -> bool: | |
| """ | |
| Check if a document is content gated by checking Sphinx's exclude_patterns. | |
| This works with the content_gating extension that adds restricted documents | |
| to exclude_patterns during config-inited event. | |
| """ | |
| sphinx_exclude_patterns = getattr(config, "exclude_patterns", []) | |
| if not sphinx_exclude_patterns: | |
| return False | |
| # Convert docname to potential file paths that might be in exclude_patterns | |
| possible_paths = [docname + ".md", docname + ".rst", docname] | |
| for possible_path in possible_paths: | |
| # Check if this path matches any exclude pattern using fnmatch (supports glob patterns) | |
| for pattern in sphinx_exclude_patterns: | |
| if isinstance(pattern, str) and fnmatch.fnmatch(possible_path, pattern): | |
| logger.debug(f"Document {docname} is content gated (matches pattern: {pattern})") | |
| return True | |
| return False | |
| def should_generate_json(config: Config, docname: str) -> bool: | |
| """Check if JSON should be generated for this document.""" | |
| if not get_setting(config, "enabled", True): | |
| return False | |
| if not docname or not isinstance(docname, str): | |
| logger.warning(f"Invalid docname for JSON generation: {docname}") | |
| return False | |
| # CRITICAL: Check content gating first - if document is content gated, don't generate JSON | |
| if is_content_gated(config, docname): | |
| logger.info(f"Excluding {docname} from JSON generation due to content gating") | |
| return False | |
| # Check JSON output extension's own exclude patterns | |
| for pattern in get_setting(config, "exclude_patterns", []): | |
| if isinstance(pattern, str) and docname.startswith(pattern): | |
| return False | |
| return True | |
| def get_document_url(app: Sphinx, docname: str) -> str: | |
| """Get the URL for a document.""" | |
| if not docname or not isinstance(docname, str): | |
| logger.warning(f"Invalid docname for URL generation: {docname}") | |
| return "invalid.html" | |
| try: | |
| if hasattr(app.builder, "get_target_uri"): | |
| return app.builder.get_target_uri(docname) | |
| except Exception as e: # noqa: BLE001 | |
| logger.warning(f"Failed to get target URI for {docname}: {e}") | |
| return docname + ".html" | |