Skip to content

Commit

Permalink
Use typecheck workaround for custom list/dicts
Browse files Browse the repository at this point in the history
As reported in python/mypy#11427, a "white lie" in typeshed
messes completely the type inference for classes inheriting from
``(MutableMapping, dict)`` and ``(MutableSequence, list)``.

This is a workaround that results in useful type inference.
  • Loading branch information
abravalheri committed Nov 2, 2021
1 parent 4c1e92a commit a5a76be
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 9 deletions.
7 changes: 3 additions & 4 deletions atoml/container.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import copy

from collections.abc import MutableMapping
from typing import Any, Dict, Iterator, List, Optional, Tuple, Union

from ._compat import decode
from ._utils import merge_dicts
from .exceptions import ATOMLError, KeyAlreadyPresent, NonExistentKey
from .items import AoT, Comment, Item, Key, Null, Table, Whitespace
from .items import AoT, Comment, Item, Key, Null, Table, Whitespace, _CustomDict
from .items import item as _item


_NOT_SET = object()


class Container(MutableMapping, dict):
class Container(_CustomDict):
"""
A container for items within a TOMLDocument.
"""
Expand Down Expand Up @@ -675,7 +674,7 @@ def _previous_item(
return prev[-1] if prev else None


class OutOfOrderTableProxy(MutableMapping, dict):
class OutOfOrderTableProxy(_CustomDict):
def __init__(self, container: Container, indices: Tuple[int]) -> None:
self._container = container
self._internal_container = Container(True)
Expand Down
32 changes: 27 additions & 5 deletions atoml/items.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import re
import string

from collections.abc import MutableMapping, MutableSequence
from datetime import date, datetime, time, tzinfo
from enum import Enum
from functools import lru_cache
Expand All @@ -22,8 +21,31 @@
from .toml_char import TOMLChar


if TYPE_CHECKING:
if TYPE_CHECKING: # pragma: no cover
# Define _CustomList and _CustomDict as a workaround for:
# https://github.com/python/mypy/issues/11427
#
# According to this issue, the typeshed contains a "white lie"
# (it adds MutableSequence to the ancestry of list and MutableMapping to
# the ancestry of dict) which completely messes with the type inference for
# Table, InlineTable, Array and Container.
#
# Importing from builtins is preferred over simple assignment, see issues:
# https://github.com/python/mypy/issues/8715
# https://github.com/python/mypy/issues/10068
from builtins import dict as _CustomDict
from builtins import list as _CustomList

# Allow type annotations but break circular imports
from . import container
else:
from collections.abc import MutableMapping, MutableSequence

class _CustomList(MutableSequence, list):
"""Adds MutableSequence mixin while pretending to be a builtin list"""

class _CustomDict(MutableMapping, dict):
"""Adds MutableMapping mixin while pretending to be a builtin dict"""


def item(value, _parent=None, _sort_keys=False):
Expand Down Expand Up @@ -792,7 +814,7 @@ def _getstate(self, protocol: int = 3) -> tuple:
)


class Array(Item, MutableSequence, list):
class Array(Item, _CustomList):
"""
An array literal
"""
Expand Down Expand Up @@ -1006,7 +1028,7 @@ def _getstate(self, protocol=3):
return self._value, self._trivia


class Table(Item, MutableMapping, dict):
class Table(Item, _CustomDict):
"""
A table literal.
"""
Expand Down Expand Up @@ -1197,7 +1219,7 @@ def _getstate(self, protocol: int = 3) -> tuple:
)


class InlineTable(Item, MutableMapping, dict):
class InlineTable(Item, _CustomDict):
"""
An inline table literal.
"""
Expand Down

0 comments on commit a5a76be

Please sign in to comment.