0

I have a mapping variable which looks like this:

from datetime import datetime, date, time

default_types_map = {
    datetime: 'DATETIME',
    date: 'DATE',
    time: 'TIME',
    str: 'STRING',
    bool: 'BOOLEAN',
    float: 'FLOAT',
    int: 'INTEGER'
}

I want to create a function which takes that variable as default value, but I don't know how to anotate the type hint of the keys:

from typing import Mapping

def to_schema(types_map: Mapping[???, str]=default_types_map):
    ...

In other words, what should I place in the ??? type hint if all they keys should be classes?

Luiscri
  • 913
  • 1
  • 13
  • 40
  • `typing.Type` ought to work. – Samwise Aug 18 '22 at 18:46
  • 2
    @Samwise or just `type` – juanpa.arrivillaga Aug 18 '22 at 18:54
  • `typing.Mapping` is deprecated, too, consider replacing it with `collections.abc.Mapping`. – Roj Aug 18 '22 at 19:16
  • Beside the point, but you're using a [mutable default argument](https://docs.python-guide.org/writing/gotchas/) here. From context though, I assume it wouldn't be mutated, but just to be safe, you might want to use [a read-only version of it, like `types_map=MappingProxyType(default_types_map)`](/q/2703599/4518341). – wjandrea Aug 18 '22 at 19:17

3 Answers3

1

Classes are instances of type, so:

Mapping[type, str]
wjandrea
  • 28,235
  • 9
  • 60
  • 81
0

For type hinting a class, you should use from typing import Type. From the docs:

class typing.Type(Generic[CT_co])

A variable annotated with C may accept a value of type C. In contrast, a variable annotated with Type[C] may accept values that are classes themselves - specifically, it will accept the class object of C.

wjandrea
  • 28,235
  • 9
  • 60
  • 81
PApostol
  • 2,152
  • 2
  • 11
  • 21
  • Also note in the docs: "*Deprecated since version 3.9*: [`builtins.type`](https://docs.python.org/3/library/functions.html#type "type") now supports `[]`. See [**PEP 585**](https://www.python.org/dev/peps/pep-0585) and [Generic Alias Type](https://docs.python.org/3/library/stdtypes.html#types-genericalias)." – wjandrea Aug 18 '22 at 19:06
  • 1
    Correct me if I'm wrong, but isn't `typing.Type` meant to be used exclusively as a generic? Using it with `mypy --strict` results in `error: Missing type parameters for generic type "Type"`. – wjandrea Aug 18 '22 at 19:08
0

You can achieve it like this:

from collections.abc import Mapping
from datetime import datetime, date, time

Key = type[datetime] | type[date] | type[time] | type[str] | type[bool] | type[float] | type[int]

default_types_map: Mapping[Key, str] = {
    datetime: 'DATETIME',
    date: 'DATE',
    time: 'TIME',
    str: 'STRING',
    bool: 'BOOLEAN',
    float: 'FLOAT',
    int: 'INTEGER'
}

from typing import Mapping

def to_schema(types_map: Mapping[Key, str]=default_types_map):
    …
Roj
  • 995
  • 1
  • 8
  • 22
  • Note that `type[...]` requires 3.9+ – wjandrea Aug 18 '22 at 19:24
  • 2
    Are you sure this is what OP's looking for? I mean, `default_types_map` is not a constant, so why restrict what type of keys it can take? Why rule out, say, `bytes`? I'm pretty sure OP's just looking for a type hint that the key is a class -- any class. – wjandrea Aug 18 '22 at 19:27