diff --git a/pyproject.toml b/pyproject.toml index cc0ecabad..ae15a8a4b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -457,12 +457,12 @@ include=[ "./doc/*.py", "./tests/**/*.py", "./tools/**/*.py", + "./sphinxext/**/*.py", ] ignore=[ "./altair/vegalite/v5/schema/channels.py", # 716 warns "./altair/vegalite/v5/schema/mixins.py", # 1001 warns - "./altair/jupyter/", - "./sphinxext/", - "./tests/test_jupyter_chart.py", - "../../../**/Lib", # stdlib + "./altair/jupyter/", # Mostly untyped + "./tests/test_jupyter_chart.py", # Based on untyped module + "../../../**/Lib", # stdlib ] diff --git a/sphinxext/altairgallery.py b/sphinxext/altairgallery.py index 062807d61..ea3a17837 100644 --- a/sphinxext/altairgallery.py +++ b/sphinxext/altairgallery.py @@ -14,7 +14,7 @@ from docutils import nodes from docutils.parsers.rst import Directive from docutils.parsers.rst.directives import flag -from docutils.statemachine import ViewList +from docutils.statemachine import StringList from sphinx.util.nodes import nested_parse_with_titles from altair.utils.execeval import eval_block @@ -184,7 +184,7 @@ def save_example_pngs( else: # the file changed or the image file does not exist. Generate it. print(f"-> saving {image_file!s}") - chart = eval_block(code) + chart = eval_block(code, strict=True) try: chart.save(image_file) hashes[filename] = example_hash @@ -303,7 +303,7 @@ def run(self) -> list[Node]: ) # parse and return documentation - result = ViewList() + result = StringList() for line in include.split("\n"): result.append(line, "") node = nodes.paragraph() diff --git a/sphinxext/code_ref.py b/sphinxext/code_ref.py index 8f5f4da0e..2eba68a6a 100644 --- a/sphinxext/code_ref.py +++ b/sphinxext/code_ref.py @@ -108,7 +108,7 @@ def gen() -> Iterator[nodes.Node]: def theme_names() -> tuple[Sequence[str], Sequence[str]]: - names: set[VegaThemes] = set(get_args(VegaThemes)) + names: set[str] = set(get_args(VegaThemes)) carbon = {nm for nm in names if nm.startswith("carbon")} return ["default", *sorted(names - carbon)], sorted(carbon) @@ -180,8 +180,8 @@ class ThemeDirective(SphinxDirective): https://pyscript.net/ """ - has_content: ClassVar[Literal[False]] = False - required_arguments: ClassVar[Literal[1]] = 1 + has_content: ClassVar[bool] = False + required_arguments: ClassVar[int] = 1 option_spec = { "packages": validate_packages, "dropdown-label": directives.unchanged, @@ -226,14 +226,16 @@ def run(self) -> Sequence[nodes.Node]: ) results.append(raw_html("

\n")) return maybe_details( - results, self.options, default_summary="Show Vega-Altair Theme Test" + results, + self.options, # pyright: ignore[reportArgumentType] + default_summary="Show Vega-Altair Theme Test", ) class PyScriptDirective(SphinxDirective): """Placeholder for non-theme related directive.""" - has_content: ClassVar[Literal[False]] = False + has_content: ClassVar[bool] = False option_spec = {"packages": directives.unchanged} def run(self) -> Sequence[nodes.Node]: @@ -282,9 +284,9 @@ class CodeRefDirective(SphinxDirective): https://github.com/vega/sphinxext-altair """ - has_content: ClassVar[Literal[False]] = False - required_arguments: ClassVar[Literal[1]] = 1 - option_spec: ClassVar[dict[_Option, Callable[[str], Any]]] = { + has_content: ClassVar[bool] = False + required_arguments: ClassVar[int] = 1 + option_spec: ClassVar[dict[_Option, Callable[[str], Any]]] = { # pyright: ignore[reportIncompatibleVariableOverride] "output": validate_output, "fold": directives.flag, "summary": directives.unchanged_required, @@ -302,8 +304,8 @@ def __init__( state: RSTState, state_machine: RSTStateMachine, ) -> None: - super().__init__(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine) # fmt: skip - self.options: dict[_Option, Any] + super().__init__(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine) # fmt: skip # pyright: ignore[reportArgumentType] + self.options: dict[_Option, Any] # pyright: ignore[reportIncompatibleVariableOverride] def run(self) -> Sequence[nodes.Node]: qual_name = self.arguments[0] diff --git a/sphinxext/schematable.py b/sphinxext/schematable.py index 5daaba4c5..323f8dfe7 100644 --- a/sphinxext/schematable.py +++ b/sphinxext/schematable.py @@ -8,7 +8,7 @@ from docutils import frontend, nodes, utils from docutils.parsers.rst import Directive from docutils.parsers.rst.directives import flag -from myst_parser.docutils_ import Parser +from myst_parser.parsers.docutils_ import Parser from sphinx import addnodes from tools.schemapi.utils import SchemaInfo, fix_docstring_issues @@ -95,7 +95,7 @@ def add_text(node: nodes.paragraph, text: str) -> nodes.paragraph: for part in reCode.split(text): if part: if is_text: - node += nodes.Text(part, part) + node += nodes.Text(part, part) # pyright: ignore[reportCallIssue] else: node += nodes.literal(part, part) @@ -108,7 +108,7 @@ def build_row( item: tuple[str, dict[str, Any]], rootschema: dict[str, Any] | None ) -> nodes.row: """Return nodes.row with property description.""" - prop, propschema, _ = item + prop, propschema = item row = nodes.row() # Property @@ -165,17 +165,16 @@ def build_schema_table( def select_items_from_schema( schema: dict[str, Any], props: list[str] | None = None -) -> Iterator[tuple[Any, Any, bool] | tuple[str, Any, bool]]: - """Return iterator (prop, schema.item, required) on prop, return all in None.""" +) -> Iterator[tuple[Any, Any] | tuple[str, Any]]: + """Return iterator (prop, schema.item) on prop, return all in None.""" properties = schema.get("properties", {}) - required = schema.get("required", []) if not props: for prop, item in properties.items(): - yield prop, item, prop in required + yield prop, item else: for prop in props: try: - yield prop, properties[prop], prop in required + yield prop, properties[prop] except KeyError as err: msg = f"Can't find property: {prop}" raise Exception(msg) from err diff --git a/sphinxext/utils.py b/sphinxext/utils.py index a27e4d340..743cf0913 100644 --- a/sphinxext/utils.py +++ b/sphinxext/utils.py @@ -46,7 +46,7 @@ def create_generic_image( arr = np.zeros((shape[0], shape[1], 3)) if gradient: # gradient from gray to white - arr += np.linspace(128, 255, shape[1])[:, None] + arr += np.linspace(128, 255, shape[1])[:, None] # pyright: ignore[reportCallIssue,reportArgumentType] im = Image.fromarray(arr.astype("uint8")) im.save(filename) @@ -138,12 +138,12 @@ def get_docstring_and_rest(filename: str) -> tuple[str, str | None, str, int]: try: # In python 3.7 module knows its docstring. # Everything else will raise an attribute error - docstring = node.docstring + docstring = node.docstring # pyright: ignore[reportAttributeAccessIssue] import tokenize from io import BytesIO - ts = tokenize.tokenize(BytesIO(content).readline) + ts = tokenize.tokenize(BytesIO(content).readline) # pyright: ignore[reportArgumentType] ds_lines = 0 # find the first string according to the tokenizer and get # it's end row @@ -163,7 +163,7 @@ def get_docstring_and_rest(filename: str) -> tuple[str, str | None, str, int]: and isinstance(node.body[0].value, (ast.Str, ast.Constant)) ): docstring_node = node.body[0] - docstring = docstring_node.value.s + docstring = docstring_node.value.s # pyright: ignore[reportAttributeAccessIssue] # python2.7: Code was read in bytes needs decoding to utf-8 # unless future unicode_literals is imported in source which # make ast output unicode strings @@ -203,8 +203,8 @@ def dict_hash(dct: dict[Any, Any]) -> Any: serialized = json.dumps(dct, sort_keys=True) try: - m = hashlib.sha256(serialized)[:32] + m = hashlib.sha256(serialized)[:32] # pyright: ignore[reportArgumentType,reportIndexIssue] except TypeError: - m = hashlib.sha256(serialized.encode())[:32] + m = hashlib.sha256(serialized.encode())[:32] # pyright: ignore[reportIndexIssue] return m.hexdigest()