Skip to content

Commit

Permalink
Type hints: Code generation (#3207)
Browse files Browse the repository at this point in the history
* First type hints for code generation

* Remove redundant code relating to support for multiple VL versions and other things

* Rename codegen._get_args to get_args and use a dataclass as return value

* Remaining type hints
  • Loading branch information
binste authored Sep 29, 2023
1 parent 5a7814c commit 19bd5a5
Show file tree
Hide file tree
Showing 7 changed files with 304 additions and 275 deletions.
2 changes: 1 addition & 1 deletion altair/vegalite/v5/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2859,7 +2859,7 @@ class RepeatChart(TopLevelMixin, core.TopLevelRepeatSpec):

# Because TopLevelRepeatSpec is defined as a union as of Vega-Lite schema 4.9,
# we set the arguments explicitly here.
# TODO: Should we instead use tools/schemapi/codegen._get_args?
# TODO: Should we instead use tools/schemapi/codegen.get_args?
@utils.use_signature(core.TopLevelRepeatSpec)
def __init__(
self,
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ module = [
"pandas.lib.*",
"nbformat.*",
"ipykernel.*",
"m2r.*",
]
ignore_missing_imports = true

Expand Down
29 changes: 17 additions & 12 deletions tools/generate_api_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@
import sys
import types
from os.path import abspath, dirname, join
from typing import Final, Optional, Iterator, List
from types import ModuleType

# Import Altair from head
ROOT_DIR = abspath(join(dirname(__file__), ".."))
sys.path.insert(0, ROOT_DIR)
import altair as alt # noqa: E402

API_FILENAME = join(ROOT_DIR, "doc", "user_guide", "api.rst")
API_FILENAME: Final = join(ROOT_DIR, "doc", "user_guide", "api.rst")

API_TEMPLATE = """\
API_TEMPLATE: Final = """\
.. _api:
API Reference
Expand Down Expand Up @@ -68,8 +70,11 @@


def iter_objects(
mod, ignore_private=True, restrict_to_type=None, restrict_to_subclass=None
):
mod: ModuleType,
ignore_private: bool = True,
restrict_to_type: Optional[type] = None,
restrict_to_subclass: Optional[type] = None,
) -> Iterator[str]:
for name in dir(mod):
obj = getattr(mod, name)
if ignore_private:
Expand All @@ -84,26 +89,26 @@ def iter_objects(
yield name


def toplevel_charts():
return sorted(iter_objects(alt.api, restrict_to_subclass=alt.TopLevelMixin))
def toplevel_charts() -> List[str]:
return sorted(iter_objects(alt.api, restrict_to_subclass=alt.TopLevelMixin)) # type: ignore[attr-defined]


def encoding_wrappers():
def encoding_wrappers() -> List[str]:
return sorted(iter_objects(alt.channels, restrict_to_subclass=alt.SchemaBase))


def api_functions():
def api_functions() -> List[str]:
# Exclude typing.cast
altair_api_functions = [
obj_name
for obj_name in iter_objects(alt.api, restrict_to_type=types.FunctionType)
for obj_name in iter_objects(alt.api, restrict_to_type=types.FunctionType) # type: ignore[attr-defined]
if obj_name != "cast"
]
return sorted(altair_api_functions)


def lowlevel_wrappers():
objects = sorted(iter_objects(alt.schema.core, restrict_to_subclass=alt.SchemaBase))
def lowlevel_wrappers() -> List[str]:
objects = sorted(iter_objects(alt.schema.core, restrict_to_subclass=alt.SchemaBase)) # type: ignore[attr-defined]
# The names of these two classes are also used for classes in alt.channels. Due to
# how imports are set up, these channel classes overwrite the two low-level classes
# in the top-level Altair namespace. Therefore, they cannot be imported as e.g.
Expand All @@ -113,7 +118,7 @@ def lowlevel_wrappers():
return objects


def write_api_file():
def write_api_file() -> None:
print("Updating API docs\n ->{}".format(API_FILENAME))
sep = "\n "
with open(API_FILENAME, "w") as f:
Expand Down
Loading

0 comments on commit 19bd5a5

Please sign in to comment.