Skip to content

Commit

Permalink
[cdd/shared/ast_utils.py] Implement deduplicate ; [cdd/docstring/ut…
Browse files Browse the repository at this point in the history
…ils/parse_utils.py] Add support for `Mapping` inference ; [cdd/tests/test_docstring/test_parse_docstring_utils.py] Test `Mapping` inference ; [cdd/__init__.py] Bump version
  • Loading branch information
SamuelMarks committed Feb 16, 2024
1 parent 61ff29c commit 467949e
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 8 deletions.
2 changes: 1 addition & 1 deletion cdd/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from logging import getLogger as get_logger

__author__ = "Samuel Marks" # type: str
__version__ = "0.0.99rc32" # type: str
__version__ = "0.0.99rc33" # type: str
__description__ = (
"Open API to/fro routes, models, and tests. "
"Convert between docstrings, classes, methods, argparse, pydantic, and SQLalchemy."
Expand Down
16 changes: 11 additions & 5 deletions cdd/docstring/utils/parse_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from operator import contains, itemgetter
from typing import List, Optional, Tuple, Union, cast

from cdd.shared.ast_utils import deduplicate
from cdd.shared.pure_utils import (
count_iter_items,
simple_types,
Expand Down Expand Up @@ -54,10 +55,11 @@
adhoc_3_tuple_to_collection = {
("List", " ", "of"): "List",
("Tuple", " ", "of"): "Tuple",
("Dictionary", " ", "of"): "Mapping",
}


def _union_literal_from_sentence(sentence):
def _union_literal_from_sentence(sentence, wrap_with="Union[{}]"):
"""
Extract the Union and/or Literal from a given sentence
Expand Down Expand Up @@ -97,8 +99,8 @@ def _union_literal_from_sentence(sentence):
)
if candidate_collection is not None:
return None
union = sorted(
frozenset(
union = list(
deduplicate(
map(
lambda k: adhoc_type_to_type.get(k.lower(), k),
filterfalse(str.isspace, union),
Expand Down Expand Up @@ -271,7 +273,11 @@ def parse_adhoc_doc_for_typ(doc, name, default_is_none):
and candidate_type is not None
):
wrap_type_with = "Union[{}, " + "{}]".format(candidate_type)
candidate_type: str = new_candidate_type
candidate_type: str = (
new_candidate_type[len("Union[") : -len("]")]
if wrap_type_with == "Mapping[{}]"
else new_candidate_type
)
if candidate_type is not None:
return wrap_type_with.format(candidate_type)

Expand All @@ -285,7 +291,7 @@ def parse_adhoc_doc_for_typ(doc, name, default_is_none):
return candidate_type
elif len(words) > 2:
if "/" in words[2]:
return "Union[{}]".format(",".join(sorted(words[2].split("/"))))
return "Union[{}]".format(",".join(deduplicate(words[2].split("/"))))
candidate_type: Optional[str] = next(
map(
adhoc_3_tuple_to_type.__getitem__,
Expand Down
15 changes: 15 additions & 0 deletions cdd/shared/ast_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2429,6 +2429,20 @@ def deduplicate_sorted_imports(module):
return module


def deduplicate(it):
"""
Deduplicate an iterable
:param it: An iterable|collection with hashable elements
:type it: ```Union[Iterable, Generator, List, Tuple, Set, FrozenSet]```
:return: Deduplicated iterable of the input
:rtype: ```Iterable```
"""
seen = set()
return (seen.add(e) or e for e in it if e not in seen)


NoneStr = "```(None)```" if PY_GTE_3_9 else "```None```"

__all__ = [
Expand All @@ -2448,6 +2462,7 @@ def deduplicate_sorted_imports(module):
"cmp_ast",
"code_quoted",
"construct_module_with_symbols",
"deduplicate",
"deduplicate_sorted_imports",
"del_ass_where_name",
"emit_ann_assign",
Expand Down
5 changes: 3 additions & 2 deletions cdd/tests/test_docstring/test_parse_docstring_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,11 @@ def test_parse_adhoc_doc_for_typ(self) -> None:
)["returns"]["return_type"]["typ"],
),
(
"Literal['auto', 'max', 'min']",
"Literal['auto', 'min', 'max']",
"String. One of `{'auto', 'min', 'max'}`. In `'min'` mode,",
),
(
'Union[Literal["epoch"], bool, int]',
'Union[Literal["epoch"], int, bool]',
'`"epoch"`, integer, or `False`.'
'When set to `"epoch" the callback saves the checkpoint at the end of each epoch.',
),
Expand All @@ -82,6 +82,7 @@ def test_parse_adhoc_doc_for_typ(self) -> None:
"String; `'bfloat16'`, `'float16'`, `'float32'`, or `'float64'`.",
),
("List[str]", "List of string."),
("Mapping[str, object]", "Dictionary of `{str: object}` pairs."),
),
),
maxlen=0,
Expand Down

0 comments on commit 467949e

Please sign in to comment.