Skip to content

Commit

Permalink
Specify type arguments for map_ (#230)
Browse files Browse the repository at this point in the history
* Fix partially unknown `map_`

* Fix type tests

* Ignore ruff error

---------

Co-authored-by: DeviousStoat <[email protected]>
  • Loading branch information
DeviousStoat and DeviousStoat authored Jul 21, 2024
1 parent 2a89f78 commit ed8a519
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 98 deletions.
4 changes: 2 additions & 2 deletions src/pydash/chaining/all_funcs.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -1111,8 +1111,8 @@ class AllFuncs:
) -> "Chain[t.List[T2]]": ...
@t.overload
def map_(
self: "Chain[t.Iterable]", iteratee: t.Union[IterateeObjT, None] = None
) -> "Chain[t.List]": ...
self: "Chain[t.Iterable[t.Any]]", iteratee: t.Union[IterateeObjT, None] = None
) -> "Chain[t.List[t.Any]]": ...
def map_(self, iteratee=None):
return self._wrap(pyd.map_)(iteratee)

Expand Down
4 changes: 3 additions & 1 deletion src/pydash/collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -989,7 +989,9 @@ def map_(


@t.overload
def map_(collection: t.Iterable, iteratee: t.Union[IterateeObjT, None] = None) -> t.List: ...
def map_(
collection: t.Iterable[t.Any], iteratee: t.Union[IterateeObjT, None] = None
) -> t.List[t.Any]: ...


def map_(collection, iteratee=None):
Expand Down
2 changes: 1 addition & 1 deletion src/pydash/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -2599,7 +2599,7 @@ def base_clone(value, is_deep=False, customizer=None, key=None, _cloned=False):
result = value

if cbk and not pyd.is_string(value) and not isinstance(value, bytes):
for key, subvalue in iterator(value):
for key, subvalue in iterator(value): # noqa: PLR1704
if is_deep:
val = base_clone(subvalue, is_deep, cbk, key, _cloned=True)
else:
Expand Down
2 changes: 1 addition & 1 deletion src/pydash/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from typing_extensions import Protocol


IterateeObjT = t.Union[int, str, t.List, t.Tuple, t.Dict]
IterateeObjT = t.Union[int, str, t.List[t.Any], t.Tuple[t.Any, ...], t.Dict[t.Any, t.Any]]
NumberT = t.Union[float, int, Decimal]
NumberNoDecimalT = t.Union[float, int]
PathT = t.Union[t.Hashable, t.List[t.Hashable]]
Expand Down
4 changes: 1 addition & 3 deletions tests/pytest_mypy_testing/test_chaining.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,4 @@ def test_mypy_tap() -> None:
def log(value):
data.append(value)

reveal_type(
_.chain([1, 2, 3, 4]).map(lambda x: x * 2).tap(log).value()
) # R: builtins.list[builtins.int]
reveal_type(_.chain([1, 2, 3, 4]).map(lambda x: x * 2).tap(log).value()) # R: builtins.list[builtins.int]
120 changes: 30 additions & 90 deletions tests/pytest_mypy_testing/test_objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,20 @@ def get_x(self) -> int:
@pytest.mark.mypy_testing
def test_mypy_assign() -> None:
obj = {b"d": 5.5}
reveal_type(
_.assign(obj, {"a": 1}, {"b": 2}, {"c": 3})
) # R: builtins.dict[Union[builtins.bytes, builtins.str], Union[builtins.float, builtins.int]]
reveal_type(_.assign(obj, {"a": 1}, {"b": 2}, {"c": 3})) # R: builtins.dict[Union[builtins.bytes, builtins.str], Union[builtins.float, builtins.int]]


@pytest.mark.mypy_testing
def test_mypy_assign_with() -> None:
def customizer(x: t.Union[int, None], y: int) -> float:
return float(y) if x is None else float(x + y)

reveal_type(
_.assign_with({"a": 1}, {"b": 2}, {"a": 3}, customizer=customizer)
) # R: builtins.dict[builtins.str, Union[builtins.int, builtins.float]]
reveal_type(_.assign_with({"a": 1}, {"b": 2}, {"a": 3}, customizer=customizer)) # R: builtins.dict[builtins.str, Union[builtins.int, builtins.float]]


@pytest.mark.mypy_testing
def test_mypy_callables() -> None:
reveal_type(
_.callables({"a": 1, "b": lambda: 2, "c": lambda: 3})
) # R: builtins.list[builtins.str]
reveal_type(_.callables({"a": 1, "b": lambda: 2, "c": lambda: 3})) # R: builtins.list[builtins.str]


@pytest.mark.mypy_testing
Expand All @@ -51,17 +45,13 @@ def test_mypy_clone_with() -> None:
def cbk(v: t.Union[int, t.Dict[str, int]], k: t.Union[str, None]) -> t.Union[int, None]:
return v + 2 if isinstance(v, int) and k else None

reveal_type(
_.clone_with(x, cbk)
) # R: builtins.dict[builtins.str, Union[builtins.int, builtins.dict[builtins.str, builtins.int], None]]
reveal_type(_.clone_with(x, cbk)) # R: builtins.dict[builtins.str, Union[builtins.int, builtins.dict[builtins.str, builtins.int], None]]


@pytest.mark.mypy_testing
def test_mypy_clone_deep() -> None:
x: t.Dict[str, t.Union[int, t.Dict[str, int]]] = {"a": 1, "b": 2, "c": {"d": 3}}
reveal_type(
_.clone_deep(x)
) # R: builtins.dict[builtins.str, Union[builtins.int, builtins.dict[builtins.str, builtins.int]]]
reveal_type(_.clone_deep(x)) # R: builtins.dict[builtins.str, Union[builtins.int, builtins.dict[builtins.str, builtins.int]]]


@pytest.mark.mypy_testing
Expand All @@ -71,25 +61,19 @@ def test_mypy_clone_deep_with() -> None:
def cbk(v: t.Union[int, t.Dict[str, int]], k: t.Union[str, None]) -> t.Union[int, None]:
return v + 2 if isinstance(v, int) and k else None

reveal_type(
_.clone_deep_with(x, cbk)
) # R: builtins.dict[builtins.str, Union[builtins.int, builtins.dict[builtins.str, builtins.int], None]]
reveal_type(_.clone_deep_with(x, cbk)) # R: builtins.dict[builtins.str, Union[builtins.int, builtins.dict[builtins.str, builtins.int], None]]


@pytest.mark.mypy_testing
def test_mypy_defaults() -> None:
obj = {"a": 1}
reveal_type(
_.defaults(obj, {"b": 2}, {"c": 3}, {"a": 4})
) # R: builtins.dict[builtins.str, builtins.int]
reveal_type(_.defaults(obj, {"b": 2}, {"c": 3}, {"a": 4})) # R: builtins.dict[builtins.str, builtins.int]


@pytest.mark.mypy_testing
def test_mypy_defaults_deep() -> None:
obj = {"a": {"b": 1}}
reveal_type(
_.defaults_deep(obj, {"a": {"b": 2, "c": 3}})
) # R: builtins.dict[builtins.str, builtins.dict[builtins.str, builtins.int]]
reveal_type(_.defaults_deep(obj, {"a": {"b": 2, "c": 3}})) # R: builtins.dict[builtins.str, builtins.dict[builtins.str, builtins.int]]


@pytest.mark.mypy_testing
Expand All @@ -115,9 +99,7 @@ def test_mypy_for_in() -> None:
def cb(v: int, k: str) -> None:
return None

reveal_type(
_.for_in({"a": 1, "b": 2, "c": 3}, cb)
) # R: builtins.dict[builtins.str, builtins.int]
reveal_type(_.for_in({"a": 1, "b": 2, "c": 3}, cb)) # R: builtins.dict[builtins.str, builtins.int]


@pytest.mark.mypy_testing
Expand Down Expand Up @@ -158,9 +140,7 @@ def test_mypy_invert_by() -> None:
def group_prefix(x: int) -> str:
return "group" + str(x)

reveal_type(
_.invert_by(obj, group_prefix)
) # R: builtins.dict[builtins.str, builtins.list[builtins.str]]
reveal_type(_.invert_by(obj, group_prefix)) # R: builtins.dict[builtins.str, builtins.list[builtins.str]]


@pytest.mark.mypy_testing
Expand All @@ -182,22 +162,16 @@ def test_mypy_map_keys() -> None:
def callback(value: int, key: str) -> str:
return key * 2

reveal_type(
_.map_keys({"a": 1, "b": 2, "c": 3}, callback)
) # R: builtins.dict[builtins.str, builtins.int]
reveal_type(_.map_keys({"a": 1, "b": 2, "c": 3}, callback)) # R: builtins.dict[builtins.str, builtins.int]


@pytest.mark.mypy_testing
def test_mypy_map_values() -> None:
def times_two(x: int) -> str:
return str(x * 2)

reveal_type(
_.map_values({"a": 1, "b": 2, "c": 3}, times_two)
) # R: builtins.dict[builtins.str, builtins.str]
reveal_type(
_.map_values({"a": 1, "b": {"d": 4}, "c": 3}, {"d": 4})
) # R: builtins.dict[Any, Any]
reveal_type(_.map_values({"a": 1, "b": 2, "c": 3}, times_two)) # R: builtins.dict[builtins.str, builtins.str]
reveal_type(_.map_values({"a": 1, "b": {"d": 4}, "c": 3}, {"d": 4})) # R: builtins.dict[Any, Any]


@pytest.mark.mypy_testing
Expand All @@ -213,9 +187,7 @@ def times_two(x: int) -> int:
@pytest.mark.mypy_testing
def test_mypy_merge() -> None:
obj = {"a": 2}
reveal_type(
_.merge(obj, {"a": 1}, {"b": 2, "c": 3}, {"d": 4})
) # R: builtins.dict[builtins.str, builtins.int]
reveal_type(_.merge(obj, {"a": 1}, {"b": 2, "c": 3}, {"d": 4})) # R: builtins.dict[builtins.str, builtins.int]


@pytest.mark.mypy_testing
Expand All @@ -228,16 +200,10 @@ def test_mypy_merge_with() -> None:

@pytest.mark.mypy_testing
def test_mypy_omit() -> None:
reveal_type(
_.omit({"a": 1, "b": 2, "c": 3}, "b", "c")
) # R: builtins.dict[builtins.str, builtins.int]
reveal_type(
_.omit({"a": 1, "b": 2, "c": 3}, ["a", "c"])
) # R: builtins.dict[builtins.str, builtins.int]
reveal_type(_.omit({"a": 1, "b": 2, "c": 3}, "b", "c")) # R: builtins.dict[builtins.str, builtins.int]
reveal_type(_.omit({"a": 1, "b": 2, "c": 3}, ["a", "c"])) # R: builtins.dict[builtins.str, builtins.int]
reveal_type(_.omit([1, 2, 3, 4], 0, 3)) # R: builtins.dict[builtins.int, builtins.int]
reveal_type(
_.omit({"a": {"b": {"c": "d"}}}, "a.b.c")
) # R: builtins.dict[builtins.str, builtins.dict[builtins.str, builtins.dict[builtins.str, builtins.str]]]
reveal_type(_.omit({"a": {"b": {"c": "d"}}}, "a.b.c")) # R: builtins.dict[builtins.str, builtins.dict[builtins.str, builtins.dict[builtins.str, builtins.str]]]
reveal_type(_.omit(MyClass(), "x")) # R: builtins.dict[Any, Any]


Expand All @@ -247,9 +213,7 @@ def is_int(v: t.Union[str, int]) -> bool:
return isinstance(v, int)

obj: t.Dict[str, t.Union[str, int]] = {"a": 1, "b": "2", "c": 3}
reveal_type(
_.omit_by(obj, is_int)
) # R: builtins.dict[builtins.str, Union[builtins.str, builtins.int]]
reveal_type(_.omit_by(obj, is_int)) # R: builtins.dict[builtins.str, Union[builtins.str, builtins.int]]
reveal_type(_.omit_by([1, 2, 3, 4], is_int)) # R: builtins.dict[builtins.int, builtins.int]
reveal_type(_.omit_by(MyClass(), is_int)) # R: builtins.dict[Any, Any]

Expand All @@ -262,9 +226,7 @@ def test_mypy_parse_int() -> None:

@pytest.mark.mypy_testing
def test_mypy_pick() -> None:
reveal_type(
_.pick({"a": 1, "b": 2, "c": 3}, "a", "b")
) # R: builtins.dict[builtins.str, builtins.int]
reveal_type(_.pick({"a": 1, "b": 2, "c": 3}, "a", "b")) # R: builtins.dict[builtins.str, builtins.int]
reveal_type(_.pick(MyClass(), "x")) # R: builtins.dict[Any, Any]


Expand All @@ -275,17 +237,13 @@ def is_int(v: t.Union[int, str]) -> bool:

obj: t.Dict[str, t.Union[int, str]] = {"a": 1, "b": "2", "c": 3}

reveal_type(
_.pick_by(obj, is_int)
) # R: builtins.dict[builtins.str, Union[builtins.int, builtins.str]]
reveal_type(_.pick_by(obj, is_int)) # R: builtins.dict[builtins.str, Union[builtins.int, builtins.str]]
reveal_type(_.pick(MyClass(), lambda v: isinstance(v, int))) # R: builtins.dict[Any, Any]


@pytest.mark.mypy_testing
def test_mypy_rename_keys() -> None:
reveal_type(
_.rename_keys({"a": 1, "b": 2, "c": 3}, {"a": "A", "b": "B"})
) # R: builtins.dict[builtins.str, builtins.int]
reveal_type(_.rename_keys({"a": 1, "b": 2, "c": 3}, {"a": "A", "b": "B"})) # R: builtins.dict[builtins.str, builtins.int]


@pytest.mark.mypy_testing
Expand All @@ -297,9 +255,7 @@ def test_mypy_set_() -> None:
@pytest.mark.mypy_testing
def test_mypy_set_with() -> None:
reveal_type(_.set_with({}, "[0][1]", "a", lambda: {})) # R: builtins.dict[Never, Never]
reveal_type(
_.set_with(MyClass(), "x", lambda: 10)
) # R: tests.pytest_mypy_testing.test_objects.MyClass
reveal_type(_.set_with(MyClass(), "x", lambda: 10)) # R: tests.pytest_mypy_testing.test_objects.MyClass


@pytest.mark.mypy_testing
Expand All @@ -313,9 +269,7 @@ def test_mypy_to_dict() -> None:
reveal_type(_.to_dict(obj)) # R: builtins.dict[builtins.str, builtins.int]
reveal_type(_.to_dict(MyClass())) # R: builtins.dict[Any, Any]
reveal_type(_.to_dict([1, 2, 3, 4])) # R: builtins.dict[builtins.int, builtins.int]
reveal_type(
_.to_dict([(1, 2), (3, 4)])
) # R: builtins.dict[builtins.int, Tuple[builtins.int, builtins.int]]
reveal_type(_.to_dict([(1, 2), (3, 4)])) # R: builtins.dict[builtins.int, Tuple[builtins.int, builtins.int]]


@pytest.mark.mypy_testing
Expand Down Expand Up @@ -364,29 +318,21 @@ def build_list(acc: t.List[t.Tuple[int, int]], v: int, k: int) -> None:
return acc.append((k, v))

base_list: t.List[t.Tuple[int, int]] = []
reveal_type(
_.transform([1, 2, 3, 4], build_list, base_list)
) # R: builtins.list[Tuple[builtins.int, builtins.int]]
reveal_type(_.transform([1, 2, 3, 4], build_list, base_list)) # R: builtins.list[Tuple[builtins.int, builtins.int]]


@pytest.mark.mypy_testing
def test_mypy_update() -> None:
reveal_type(_.update({}, ["a", "b"], lambda value: value)) # R: builtins.dict[Any, Any]
reveal_type(_.update([], [0, 0], lambda value: 1)) # R: builtins.list[Any]
reveal_type(
_.update(MyClass(), "x", lambda value: 10)
) # R: tests.pytest_mypy_testing.test_objects.MyClass
reveal_type(_.update(MyClass(), "x", lambda value: 10)) # R: tests.pytest_mypy_testing.test_objects.MyClass


@pytest.mark.mypy_testing
def test_mypy_update_with() -> None:
reveal_type(
_.update_with({}, "[0][1]", lambda x: "a", lambda x: {})
) # R: builtins.dict[Any, Any]
reveal_type(_.update_with({}, "[0][1]", lambda x: "a", lambda x: {})) # R: builtins.dict[Any, Any]
reveal_type(_.update_with([], [0, 0], lambda x: 1, lambda x: [])) # R: builtins.list[Any]
reveal_type(
_.update_with(MyClass(), "lst.0", lambda value: 10, lambda x: [])
) # R: tests.pytest_mypy_testing.test_objects.MyClass
reveal_type(_.update_with(MyClass(), "lst.0", lambda value: 10, lambda x: [])) # R: tests.pytest_mypy_testing.test_objects.MyClass


@pytest.mark.mypy_testing
Expand All @@ -411,9 +357,7 @@ def test_mypy_apply() -> None:

@pytest.mark.mypy_testing
def test_mypy_apply_if() -> None:
reveal_type(
_.apply_if("5", lambda x: int(x), lambda x: x.isdecimal())
) # R: Union[builtins.str, builtins.int]
reveal_type(_.apply_if("5", lambda x: int(x), lambda x: x.isdecimal())) # R: Union[builtins.str, builtins.int]


@pytest.mark.mypy_testing
Expand All @@ -425,9 +369,5 @@ def test_mypy_apply_if_not_none() -> None:

@pytest.mark.mypy_testing
def test_mypy_apply_catch() -> None:
reveal_type(
_.apply_catch(5, lambda x: x / 0, [ZeroDivisionError])
) # R: Union[builtins.int, builtins.float]
reveal_type(
_.apply_catch(5, lambda x: x / 0, [ZeroDivisionError], "error")
) # R: Union[builtins.float, builtins.str]
reveal_type(_.apply_catch(5, lambda x: x / 0, [ZeroDivisionError])) # R: Union[builtins.int, builtins.float]
reveal_type(_.apply_catch(5, lambda x: x / 0, [ZeroDivisionError], "error")) # R: Union[builtins.float, builtins.str]

0 comments on commit ed8a519

Please sign in to comment.