# Disable Flake8 because of all the sphinx imports # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you 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. """Configuration of Airflow Chart Docs.""" from __future__ import annotations # Airflow documentation build configuration file, created by # sphinx-quickstart on Thu Oct 9 20:50:01 2014. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import json import logging import os import re from typing import Any import yaml from docs.utils.conf_constants import ( AIRFLOW_FAVICON_PATH, AIRFLOW_REPO_ROOT_PATH, AUTOAPI_OPTIONS, BASIC_AUTOAPI_IGNORE_PATTERNS, BASIC_SPHINX_EXTENSIONS, SMARTQUOTES_EXCLUDES, SPELLING_WORDLIST_PATH, SPHINX_DESIGN_STATIC_PATH, SUPPRESS_WARNINGS, filter_autoapi_ignore_entries, get_autodoc_mock_imports, get_html_context, get_html_sidebars, get_html_theme_options, get_intersphinx_mapping, get_rst_epilogue, ) from packaging.version import parse as parse_version import airflow PACKAGE_NAME = "helm-chart" CHART_ROOT_PATH = AIRFLOW_REPO_ROOT_PATH / "chart" CHART_DOC_PATH = CHART_ROOT_PATH / "docs" CHART_STATIC_PATH = CHART_DOC_PATH / "static" os.environ["AIRFLOW_PACKAGE_NAME"] = PACKAGE_NAME CHART_YAML_FILE_PATH = CHART_ROOT_PATH / "Chart.yaml" with CHART_YAML_FILE_PATH.open() as chart_file: chart_yaml_contents = yaml.safe_load(chart_file) PACKAGE_VERSION: str = chart_yaml_contents["version"] # Adds to environment variables for easy access from other plugins like airflow_intersphinx. os.environ["AIRFLOW_PACKAGE_NAME"] = PACKAGE_NAME # Hack to allow changing for piece of the code to behave differently while # the docs are being built. The main objective was to alter the # behavior of the utils.apply_default that was hiding function headers os.environ["BUILDING_AIRFLOW_DOCS"] = "TRUE" # Use for generate rst_epilog and other post-generation substitutions global_substitutions = { "version": PACKAGE_VERSION, "airflow-version": airflow.__version__, "experimental": "This is an :ref:`experimental feature `.", } # == Sphinx configuration ====================================================== # -- Project information ------------------------------------------------------- # See: https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information # General information about the project. project = PACKAGE_NAME # # The version info for the project you're documenting version = PACKAGE_VERSION # The full version, including alpha/beta/rc tags. release = PACKAGE_VERSION # -- General configuration ----------------------------------------------------- # See: https://www.sphinx-doc.org/en/master/usage/configuration.html rst_epilog = get_rst_epilogue(PACKAGE_VERSION, False) smartquotes_excludes = SMARTQUOTES_EXCLUDES # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = BASIC_SPHINX_EXTENSIONS extensions.append("sphinx_jinja") # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns: list[str] = [] # Add any paths that contain templates here, relative to this directory. templates_path = ["templates"] # If true, keep warnings as "system message" paragraphs in the built documents. keep_warnings = True # -- Options for HTML output --------------------------------------------------- # See: https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = "sphinx_airflow_theme" html_title = f"{PACKAGE_NAME} Documentation" conf_py_path = "/chart/docs/" # A dictionary of values to pass into the template engine's context for all pages. html_context = get_html_context(conf_py_path) # A shorter title for the navigation bar. Default is the same as html_title. html_short_title = "" # given, this must be the name of an image file (path relative to the # configuration directory) that is the favicon of the docs. Modern browsers # use this as the icon for tabs, windows and bookmarks. It should be a # Windows-style icon file (.ico), which is 16x16 or 32x32 pixels large. html_favicon = AIRFLOW_FAVICON_PATH.as_posix() # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = [CHART_STATIC_PATH.as_posix(), SPHINX_DESIGN_STATIC_PATH.as_posix()] html_js_files = ["gh-jira-links.js"] html_css_files = ["custom.css"] # -- Theme configuration ------------------------------------------------------- # Custom sidebar templates, maps document names to template names. html_sidebars = get_html_sidebars(PACKAGE_VERSION) # If false, no index is generated. html_use_index = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. html_show_copyright = False html_theme_options: dict[str, Any] = get_html_theme_options() # A dictionary of values to pass into the template engine's context for all pages. html_context = get_html_context(conf_py_path) # == Extensions configuration ================================================== # -- Options for sphinx_jinja ------------------------------------------ # See: https://github.com/tardyp/sphinx-jinja airflow_version = parse_version( re.search( # type: ignore[union-attr,arg-type] r"__version__ = \"([0-9\.]*)(\.dev[0-9]*)?\"", (AIRFLOW_REPO_ROOT_PATH / "airflow-core" / "src" / "airflow" / "__init__.py").read_text(), ).groups(0)[0] ) def _str_representer(dumper, data): style = "|" if "\n" in data else None # show as a block scalar if we have more than 1 line return dumper.represent_scalar("tag:yaml.org,2002:str", data, style) yaml.add_representer(str, _str_representer) def _format_default(value: Any) -> str: if value == "": return '""' if value is None: return "~" return str(value) def _format_examples(param_name: str, schema: dict) -> str | None: if not schema.get("examples"): return None # Nicer to have the parameter name shown as well out = "" for ex_data in schema["examples"]: ex = [ex_data] if schema["type"] == "array" else ex_data out += yaml.dump({param_name: ex}) return out def _get_params(root_schema: dict, prefix: str = "", default_section: str = "") -> list[dict]: """ Retrieve params. Given an jsonschema objects properties dict, return a flattened list of all parameters from that object and any nested objects """ out = [] for param_name, schema in root_schema.items(): prefixed_name = f"{prefix}.{param_name}" if prefix else param_name section_name = schema["x-docsSection"] if "x-docsSection" in schema else default_section common_out = { "section": section_name, "name": prefixed_name, } if section_name and "description" in schema and schema["description"] and "default" in schema: out.append( { **common_out, "description": schema["description"], "default": _format_default(schema["default"]), "examples": _format_examples(param_name, schema), } ) if schema.get("properties"): out += _get_params(schema["properties"], prefixed_name, section_name) items = schema.get("items") if items: out.extend(_process_array_items(items, prefixed_name, param_name, section_name)) return out def _process_array_items(items: dict, parent_name: str, param_name: str, default_section: str) -> list[dict]: """Extract parameters from array item schemas.""" item_prefix = f"{parent_name}[]" section_name = items.get("x-docsSection", default_section) if items.get("properties"): return _get_params(items["properties"], item_prefix, section_name) if section_name and items.get("description") and "default" in items: return [ { "section": section_name, "name": item_prefix, "description": items["description"], "default": _format_default(items["default"]), "examples": _format_examples(param_name, items), } ] return [] schema_file = CHART_ROOT_PATH / "values.schema.json" with schema_file.open() as config_file: chart_schema = json.load(config_file) params = _get_params(chart_schema["properties"]) # Now, split into sections sections: dict[str, list[dict[str, str]]] = {} for param in params: if param["section"] not in sections: sections[param["section"]] = [] sections[param["section"]].append(param) # and order each section for section in sections.values(): # type: ignore section.sort(key=lambda i: i["name"]) # type: ignore # and finally order the sections! ordered_sections = [] for name in chart_schema["x-docsSectionOrder"]: if name not in sections: raise ValueError(f"Unable to find any parameters for section: {name}") ordered_sections.append({"name": name, "params": sections.pop(name)}) if sections: raise ValueError(f"Found section(s) which were not in `section_order`: {list(sections.keys())}") jinja_contexts = { "params_ctx": {"sections": ordered_sections}, "official_download_page": { "base_url": "https://downloads.apache.org/airflow/helm-chart", "closer_lua_url": "https://www.apache.org/dyn/closer.lua/airflow/helm-chart", "package_name": PACKAGE_NAME, "package_version": PACKAGE_VERSION, }, } # -- Options for sphinx.ext.autodoc -------------------------------------------- # See: https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html # This value contains a list of modules to be mocked up. This is useful when some external dependencies # are not met at build time and break the building process. autodoc_mock_imports = get_autodoc_mock_imports() # The default options for autodoc directives. They are applied to all autodoc directives automatically. autodoc_default_options = {"show-inheritance": True, "members": True} autodoc_typehints = "description" autodoc_typehints_description_target = "documented" autodoc_typehints_format = "short" # -- Options for sphinx.ext.intersphinx ---------------------------------------- # See: https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html # This config value contains names of other projects that should # be linked to in this documentation. # Inventories are only downloaded once by docs/exts/docs_build/fetch_inventories.py. intersphinx_mapping = get_intersphinx_mapping() # -- Options for sphinx.ext.viewcode ------------------------------------------- # See: https://www.sphinx-doc.org/es/master/usage/extensions/viewcode.html # If this is True, viewcode extension will emit viewcode-follow-imported event to resolve the name of # the module by other extensions. The default is True. viewcode_follow_imported_members = True # -- Options for sphinx-autoapi ------------------------------------------------ # See: https://sphinx-autoapi.readthedocs.io/en/latest/config.html # Paths (relative or absolute) to the source code that you wish to generate # your API documentation from. autoapi_dirs = [CHART_ROOT_PATH.as_posix()] # A list of patterns to ignore when finding files autoapi_ignore = BASIC_AUTOAPI_IGNORE_PATTERNS autoapi_log = logging.getLogger("sphinx.autoapi.mappers.base") autoapi_log.addFilter(filter_autoapi_ignore_entries) # Keep the AutoAPI generated files on the filesystem after the run. # Useful for debugging. autoapi_keep_files = True # Relative path to output the AutoAPI files into. This can also be used to place the generated documentation # anywhere in your documentation hierarchy. autoapi_root = "_api" # Whether to insert the generated documentation into the TOC tree. If this is False, the default AutoAPI # index page is not generated and you will need to include the generated documentation in a # TOC tree entry yourself. autoapi_add_toctree_entry = False # By default autoapi will include private members -- we don't want that! autoapi_options = AUTOAPI_OPTIONS suppress_warnings = SUPPRESS_WARNINGS # -- Options for ext.exampleinclude -------------------------------------------- exampleinclude_sourceroot = os.path.abspath("..") # -- Options for ext.redirects ------------------------------------------------- redirects_file = "redirects.txt" # -- Options for sphinxcontrib-spelling ---------------------------------------- spelling_word_list_filename = [SPELLING_WORDLIST_PATH.as_posix()] spelling_exclude_patterns = ["changelog.rst"] spelling_ignore_contributor_names = False spelling_ignore_importable_modules = True graphviz_output_format = "svg"