Skip to content

Commit

Permalink
Modernize type annotations using pyupgrade (#3219)
Browse files Browse the repository at this point in the history
* https://peps.python.org/pep-0563/ - Postponed Evaluation of Annotations
* https://peps.python.org/pep-0585/ - Type Hinting Generics In Standard Collections
* https://peps.python.org/pep-0604/ - Allow writing union types as `X | Y`
  • Loading branch information
oprypin committed May 14, 2023
1 parent 3eb834e commit 62e3124
Show file tree
Hide file tree
Showing 21 changed files with 165 additions and 216 deletions.
10 changes: 5 additions & 5 deletions mkdocs/commands/build.py
Expand Up @@ -4,7 +4,7 @@
import logging
import os
import time
from typing import Any, Dict, Optional, Sequence, Set, Union
from typing import Any, Sequence
from urllib.parse import urlsplit

import jinja2
Expand All @@ -23,7 +23,7 @@ class DuplicateFilter:
"""Avoid logging duplicate messages."""

def __init__(self) -> None:
self.msgs: Set[str] = set()
self.msgs: set[str] = set()

def __call__(self, record: logging.LogRecord) -> bool:
rv = record.msg not in self.msgs
Expand All @@ -37,11 +37,11 @@ def __call__(self, record: logging.LogRecord) -> bool:

def get_context(
nav: Navigation,
files: Union[Sequence[File], Files],
files: Sequence[File] | Files,
config: MkDocsConfig,
page: Optional[Page] = None,
page: Page | None = None,
base_url: str = '',
) -> Dict[str, Any]:
) -> dict[str, Any]:
"""
Return the template context for a given page or template.
"""
Expand Down
5 changes: 2 additions & 3 deletions mkdocs/commands/gh_deploy.py
Expand Up @@ -4,7 +4,6 @@
import os
import re
import subprocess
from typing import Optional, Tuple, Union

import ghp_import
from packaging import version
Expand Down Expand Up @@ -45,7 +44,7 @@ def _get_current_sha(repo_path) -> str:
return sha


def _get_remote_url(remote_name: str) -> Union[Tuple[str, str], Tuple[None, None]]:
def _get_remote_url(remote_name: str) -> tuple[str, str] | tuple[None, None]:
# No CNAME found. We will use the origin URL to determine the GitHub
# Pages location.
remote = f"remote.{remote_name}.url"
Expand Down Expand Up @@ -97,7 +96,7 @@ def _check_version(branch: str) -> None:

def gh_deploy(
config: MkDocsConfig,
message: Optional[str] = None,
message: str | None = None,
force=False,
no_history=False,
ignore_version=False,
Expand Down
5 changes: 2 additions & 3 deletions mkdocs/commands/serve.py
Expand Up @@ -5,7 +5,6 @@
import shutil
import tempfile
from os.path import isdir, isfile, join
from typing import Optional
from urllib.parse import urlsplit

import jinja2.exceptions
Expand Down Expand Up @@ -59,7 +58,7 @@ def mount_path(config: MkDocsConfig):
live_server = livereload in ('dirty', 'livereload')
dirty = livereload == 'dirty'

def builder(config: Optional[MkDocsConfig] = None):
def builder(config: MkDocsConfig | None = None):
log.info("Building documentation...")
if config is None:
config = get_config()
Expand Down Expand Up @@ -87,7 +86,7 @@ def builder(config: Optional[MkDocsConfig] = None):
builder=builder, host=host, port=port, root=site_dir, mount_path=mount_path(config)
)

def error_handler(code) -> Optional[bytes]:
def error_handler(code) -> bytes | None:
if code in (404, 500):
error_page = join(site_dir, f'{code}.html')
if isfile(error_page):
Expand Down
36 changes: 12 additions & 24 deletions mkdocs/config/base.py
Expand Up @@ -6,19 +6,7 @@
import sys
from collections import UserDict
from contextlib import contextmanager
from typing import (
IO,
TYPE_CHECKING,
Generic,
Iterator,
List,
Optional,
Sequence,
Tuple,
TypeVar,
Union,
overload,
)
from typing import IO, TYPE_CHECKING, Generic, Iterator, List, Sequence, Tuple, TypeVar, overload

from yaml import YAMLError

Expand All @@ -36,7 +24,7 @@

class BaseConfigOption(Generic[T]):
def __init__(self) -> None:
self.warnings: List[str] = []
self.warnings: list[str] = []
self.default = None

@property
Expand Down Expand Up @@ -129,7 +117,7 @@ class Config(UserDict):
"""

_schema: PlainConfigSchema
config_file_path: Optional[str]
config_file_path: str | None

def __init_subclass__(cls):
schema = dict(getattr(cls, '_schema', ()))
Expand All @@ -153,9 +141,9 @@ def __new__(cls, *args, **kwargs) -> Config:
return LegacyConfig(*args, **kwargs)
return super().__new__(cls)

def __init__(self, config_file_path: Optional[Union[str, bytes]] = None):
def __init__(self, config_file_path: str | bytes | None = None):
super().__init__()
self.user_configs: List[dict] = []
self.user_configs: list[dict] = []
self.set_defaults()

self._schema_keys = {k for k, v in self._schema}
Expand All @@ -176,7 +164,7 @@ def set_defaults(self) -> None:
for key, config_option in self._schema:
self[key] = config_option.default

def _validate(self) -> Tuple[ConfigErrors, ConfigWarnings]:
def _validate(self) -> tuple[ConfigErrors, ConfigWarnings]:
failed: ConfigErrors = []
warnings: ConfigWarnings = []

Expand All @@ -194,7 +182,7 @@ def _validate(self) -> Tuple[ConfigErrors, ConfigWarnings]:

return failed, warnings

def _pre_validate(self) -> Tuple[ConfigErrors, ConfigWarnings]:
def _pre_validate(self) -> tuple[ConfigErrors, ConfigWarnings]:
failed: ConfigErrors = []
warnings: ConfigWarnings = []

Expand All @@ -208,7 +196,7 @@ def _pre_validate(self) -> Tuple[ConfigErrors, ConfigWarnings]:

return failed, warnings

def _post_validate(self) -> Tuple[ConfigErrors, ConfigWarnings]:
def _post_validate(self) -> tuple[ConfigErrors, ConfigWarnings]:
failed: ConfigErrors = []
warnings: ConfigWarnings = []

Expand All @@ -222,7 +210,7 @@ def _post_validate(self) -> Tuple[ConfigErrors, ConfigWarnings]:

return failed, warnings

def validate(self) -> Tuple[ConfigErrors, ConfigWarnings]:
def validate(self) -> tuple[ConfigErrors, ConfigWarnings]:
failed, warnings = self._pre_validate()

run_failed, run_warnings = self._validate()
Expand Down Expand Up @@ -278,13 +266,13 @@ class LegacyConfig(Config):
A configuration object for plugins, as just a dict without type-safe attribute access.
"""

def __init__(self, schema: PlainConfigSchema, config_file_path: Optional[str] = None):
def __init__(self, schema: PlainConfigSchema, config_file_path: str | None = None):
self._schema = tuple((k, v) for k, v in schema) # Re-create just for validation
super().__init__(config_file_path)


@contextmanager
def _open_config_file(config_file: Optional[Union[str, IO]]) -> Iterator[IO]:
def _open_config_file(config_file: str | IO | None) -> Iterator[IO]:
"""
A context manager which yields an open file descriptor ready to be read.
Expand Down Expand Up @@ -331,7 +319,7 @@ def _open_config_file(config_file: Optional[Union[str, IO]]) -> Iterator[IO]:
result_config_file.close()


def load_config(config_file: Optional[Union[str, IO]] = None, **kwargs) -> MkDocsConfig:
def load_config(config_file: str | IO | None = None, **kwargs) -> MkDocsConfig:
"""
Load the configuration for a given file object or name
Expand Down
42 changes: 20 additions & 22 deletions mkdocs/config/config_options.py
Expand Up @@ -14,14 +14,12 @@
Any,
Callable,
Collection,
Dict,
Generic,
Iterator,
List,
Mapping,
MutableMapping,
NamedTuple,
Tuple,
TypeVar,
Union,
overload,
Expand Down Expand Up @@ -61,7 +59,7 @@ class SubConfig(Generic[SomeConfig], BaseConfigOption[SomeConfig]):

@overload
def __init__(
self: SubConfig[SomeConfig], config_class: t.Type[SomeConfig], *, validate: bool = True
self: SubConfig[SomeConfig], config_class: type[SomeConfig], *, validate: bool = True
):
"""Create a sub-config in a type-safe way, using fields defined in a Config subclass."""

Expand Down Expand Up @@ -155,7 +153,7 @@ class ListOfItems(Generic[T], BaseConfigOption[List[T]]):
E.g. for `config_options.ListOfItems(config_options.Type(int))` a valid item is `[1, 2, 3]`.
"""

required: Union[bool, None] = None # Only for subclasses to set.
required: bool | None = None # Only for subclasses to set.

def __init__(self, option_type: BaseConfigOption[T], default=None) -> None:
super().__init__()
Expand All @@ -170,7 +168,7 @@ def pre_validation(self, config: Config, key_name: str):
self._config = config
self._key_name = key_name

def run_validation(self, value: object) -> List[T]:
def run_validation(self, value: object) -> list[T]:
if value is None:
if self.required or self.default is None:
raise ValidationError("Required configuration not provided.")
Expand Down Expand Up @@ -232,11 +230,11 @@ class Type(Generic[T], OptionallyRequired[T]):
"""

@overload
def __init__(self, type_: t.Type[T], length: t.Optional[int] = None, **kwargs):
def __init__(self, type_: type[T], length: int | None = None, **kwargs):
...

@overload
def __init__(self, type_: Tuple[t.Type[T], ...], length: t.Optional[int] = None, **kwargs):
def __init__(self, type_: tuple[type[T], ...], length: int | None = None, **kwargs):
...

def __init__(self, type_, length=None, **kwargs) -> None:
Expand Down Expand Up @@ -265,7 +263,7 @@ class Choice(Generic[T], OptionallyRequired[T]):
Validate the config option against a strict set of values.
"""

def __init__(self, choices: Collection[T], default: t.Optional[T] = None, **kwargs) -> None:
def __init__(self, choices: Collection[T], default: T | None = None, **kwargs) -> None:
super().__init__(default=default, **kwargs)
try:
length = len(choices)
Expand Down Expand Up @@ -297,10 +295,10 @@ class Deprecated(BaseConfigOption):

def __init__(
self,
moved_to: t.Optional[str] = None,
message: t.Optional[str] = None,
moved_to: str | None = None,
message: str | None = None,
removed: bool = False,
option_type: t.Optional[BaseConfigOption] = None,
option_type: BaseConfigOption | None = None,
) -> None:
super().__init__()
self.default = None
Expand Down Expand Up @@ -464,7 +462,7 @@ def __getattr__(self, key):
def pre_validation(self, config: Config, key_name: str):
return self.option.pre_validation(config, key_name)

def run_validation(self, value: object) -> Union[T, None]:
def run_validation(self, value: object) -> T | None:
if value is None:
return None
return self.option.validate(value)
Expand Down Expand Up @@ -559,7 +557,7 @@ def __init__(self, formatter, data) -> None:
def format(self, path, path_noext):
return self.formatter.format(self.data, path=path, path_noext=path_noext)

def __init__(self, edit_uri_key: t.Optional[str] = None) -> None:
def __init__(self, edit_uri_key: str | None = None) -> None:
super().__init__()
self.edit_uri_key = edit_uri_key

Expand Down Expand Up @@ -610,7 +608,7 @@ class FilesystemObject(Type[str]):
def __init__(self, exists: bool = False, **kwargs) -> None:
super().__init__(type_=str, **kwargs)
self.exists = exists
self.config_dir: t.Optional[str] = None
self.config_dir: str | None = None

def pre_validation(self, config: Config, key_name: str):
self.config_dir = (
Expand Down Expand Up @@ -848,9 +846,9 @@ class MarkdownExtensions(OptionallyRequired[List[str]]):

def __init__(
self,
builtins: t.Optional[List[str]] = None,
builtins: list[str] | None = None,
configkey: str = 'mdx_configs',
default: List[str] = [],
default: list[str] = [],
**kwargs,
) -> None:
super().__init__(default=default, **kwargs)
Expand All @@ -867,7 +865,7 @@ def validate_ext_cfg(self, ext, cfg):
self.configdata[ext] = cfg

def run_validation(self, value: object):
self.configdata: Dict[str, dict] = {}
self.configdata: dict[str, dict] = {}
if not isinstance(value, (list, tuple, dict)):
raise ValidationError('Invalid Markdown Extensions configuration')
extensions = []
Expand Down Expand Up @@ -921,12 +919,12 @@ class Plugins(OptionallyRequired[plugins.PluginCollection]):
initializing the plugin class.
"""

def __init__(self, theme_key: t.Optional[str] = None, **kwargs) -> None:
def __init__(self, theme_key: str | None = None, **kwargs) -> None:
super().__init__(**kwargs)
self.installed_plugins = plugins.get_plugins()
self.theme_key = theme_key
self._config: t.Optional[Config] = None
self.plugin_cache: Dict[str, plugins.BasePlugin] = {}
self._config: Config | None = None
self.plugin_cache: dict[str, plugins.BasePlugin] = {}

def pre_validation(self, config, key_name):
self._config = config
Expand All @@ -941,7 +939,7 @@ def run_validation(self, value: object) -> plugins.PluginCollection:
return self.plugins

@classmethod
def _parse_configs(cls, value: Union[list, tuple, dict]) -> Iterator[Tuple[str, dict]]:
def _parse_configs(cls, value: list | tuple | dict) -> Iterator[tuple[str, dict]]:
if isinstance(value, dict):
for name, cfg in value.items():
if not isinstance(name, str):
Expand All @@ -960,7 +958,7 @@ def _parse_configs(cls, value: Union[list, tuple, dict]) -> Iterator[Tuple[str,
raise ValidationError(f"'{name}' is not a valid plugin name.")
yield name, cfg

def load_plugin_with_namespace(self, name: str, config) -> Tuple[str, plugins.BasePlugin]:
def load_plugin_with_namespace(self, name: str, config) -> tuple[str, plugins.BasePlugin]:
if '/' in name: # It's already specified with a namespace.
# Special case: allow to explicitly skip namespaced loading:
if name.startswith('/'):
Expand Down
4 changes: 2 additions & 2 deletions mkdocs/contrib/search/__init__.py
Expand Up @@ -2,7 +2,7 @@

import logging
import os
from typing import Any, Dict, List
from typing import Any, List

from mkdocs import utils
from mkdocs.config import base
Expand Down Expand Up @@ -83,7 +83,7 @@ def on_pre_build(self, config: MkDocsConfig, **kwargs) -> None:
"Create search index instance for later use."
self.search_index = SearchIndex(**self.config)

def on_page_context(self, context: Dict[str, Any], **kwargs) -> None:
def on_page_context(self, context: dict[str, Any], **kwargs) -> None:
"Add page to search index."
self.search_index.add_entry_from_context(context['page'])

Expand Down

0 comments on commit 62e3124

Please sign in to comment.