Skip to content

Commit

Permalink
chore: Move functions in annotation module to parse and typing.
Browse files Browse the repository at this point in the history
  • Loading branch information
DanCardin committed Aug 13, 2024
1 parent 1efae00 commit 5aa5b7b
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 67 deletions.
2 changes: 1 addition & 1 deletion docs/source/annotation.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ As such you can again, opt out of the "Mapping inference" entirely, by supplying
your own `parse` function.

```{note}
Mapping inference is built up out of component functions defined in `cappa.annotation`,
Mapping inference is built up out of component functions defined in `cappa.parse`,
such as `parse_list`, which know how to translate `list[int]` and a source list of raw
parser strings into a list of ints.

Expand Down
6 changes: 3 additions & 3 deletions docs/source/manual_construction.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ from the class in question, if much more manually.
from dataclasses import dataclass

import cappa
from cappa.annotation import parse_list
from cappa.parse import parse_list


@dataclass
Expand All @@ -37,14 +37,14 @@ result = cappa.parse(command, argv=["one", "2", "3"])
```

There are a number of built-in parser functions used to build up the existing
inference system. [parse_value](cappa.annotation.parse_value) the the main
inference system. [parse_value](cappa.parse.parse_value) the the main
entrypoint used by cappa internally, but each of the parser factory functions
below make up the component built-in parsers for each type.

For inherent types, like `int`, `float`, etc. Their constructor may serve as
their own parser.

```{eval-rst}
.. autoapimodule:: cappa.annotation
.. autoapimodule:: cappa.parse
:members: parse_value, parse_list, parse_tuple, parse_literal, parse_none, parse_set, parse_union
```
59 changes: 0 additions & 59 deletions src/cappa/annotation.py

This file was deleted.

3 changes: 2 additions & 1 deletion src/cappa/arg.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

from typing_inspect import is_optional_type

from cappa.annotation import detect_choices, is_sequence_type
from cappa.class_inspect import Field, extract_dataclass_metadata
from cappa.completion.completers import complete_choices
from cappa.completion.types import Completion
Expand All @@ -19,9 +18,11 @@
MISSING,
NoneType,
T,
detect_choices,
find_type_annotation,
get_optional_type,
is_of_type,
is_sequence_type,
is_subclass,
is_union_type,
missing,
Expand Down
3 changes: 1 addition & 2 deletions src/cappa/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@

from typing_inspect import is_literal_type

from cappa.annotation import repr_type
from cappa.file_io import FileMode
from cappa.typing import T, is_none_type, is_subclass, is_union_type
from cappa.typing import T, is_none_type, is_subclass, is_union_type, repr_type

__all__ = [
"parse_value",
Expand Down
37 changes: 36 additions & 1 deletion src/cappa/typing.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import enum
import sys
import types
import typing
Expand All @@ -9,7 +10,7 @@
import typing_extensions
import typing_inspect
from typing_extensions import Annotated, get_args, get_origin
from typing_inspect import is_literal_type
from typing_inspect import is_literal_type, is_optional_type

try:
from typing_extensions import Doc
Expand Down Expand Up @@ -159,6 +160,40 @@ def is_of_type(annotation, types):
return False


def detect_choices(annotation: type) -> list[str] | None:
if is_optional_type(annotation):
annotation = get_optional_type(annotation)

origin = typing.get_origin(annotation) or annotation
type_args = typing.get_args(annotation)
if is_subclass(origin, enum.Enum):
return [v.value for v in origin] # type: ignore

if is_subclass(origin, (tuple, list, set)):
origin = typing.cast(type, type_args[0])
type_args = typing.get_args(type_args[0])

if is_union_type(origin):
if all(is_literal_type(t) for t in type_args):
return [str(typing.get_args(t)[0]) for t in type_args]

if is_literal_type(origin):
return [str(t) for t in type_args]

return None


def is_sequence_type(typ):
return is_subclass(get_origin(typ) or typ, (typing.List, typing.Tuple, typing.Set))


def repr_type(t):
if isinstance(t, type) and not typing.get_origin(t):
return str(t.__name__)

return str(t).replace("typing.", "")


if sys.version_info >= (3, 10):
_get_type_hints = typing.get_type_hints

Expand Down

0 comments on commit 5aa5b7b

Please sign in to comment.