[PATCH 05 of 23 yams] [mypy] type __init__.py and add types.py

Laurent Peuch cortex at worlddomination.be
Tue Feb 25 23:27:44 CET 2020


Hey Frank,

Thx for the feedback!

> >  # This provides a way to specify callable objects as default values
> >  # First level is the final type, second is the keyword to callable map
> >-KEYWORD_MAP = {
> >+_current_date_or_datetime_constructor_type = Callable[[], Union[date, datetime]]
> >+KEYWORD_MAP: Dict[str, Dict[str, _current_date_or_datetime_constructor_type]] = {
> >      'Datetime': {'NOW': datetime.now,
> >                   'TODAY': datetime.today},
> >      'TZDatetime': {'NOW': datetime.utcnow,
> >@@ -74,21 +78,33 @@ KEYWORD_MAP = {
> >      'Date': {'TODAY': date.today}
> >  }
> >+# bw compat for literal date/time values stored as strings in schemas
> >-# bw compat for literal date/time values stored as strings in schemas
> >-DATE_FACTORY_MAP = {
> >+# parse_datetime_or_time_type = Union[Callable[[str], datetime],
> >+#                                     Callable[[str], float],
> >+#                                     # strptime_time can have an optional format argument
> >+#                                     Callable[[str, str], float]]
> 
> 
> If the second argument is optional and is never used (which seems to be the
> case) you can remove this lat type.

Done.

> Also, you can take a look at TypedDict which seems to be appropriate to type
> this kind of values:
> https://mypy.readthedocs.io/en/latest/more_types.html#id3
> (this is only available since python3.8 but there is a backport in the
> typing-extensions package).

So I've actually explored a bit this option before realising that it
won't work here :/ Why? Because, as quote from the documentation:

> Mypy will also reject a runtime-computed expression as a key, as it
> can’t verify that it’s a valid key. You can only use string literals
> as TypedDict keys.

So everytime we have code like:

> KEYWORD_MAP[some_variable]

or even worst

> return KEYWORD_MAP[rdef.object][default.upper()]()

We'll either have a mypy error or have to change to code to something
like:

> if rdef.object == "Datetime":
>     KEYWORD_MAP["Datetime"]...
> elif rdef.object == "Date":
>     KEYWORD_MAP["Date"]...

Everywhere we uses those dictionary in the code or put "# type:
ignore" everywhere which kinda really defeat the purpose :/

For reference here is the commit introducing it
https://hg.logilab.org/users/lpeuch/yams/rev/97a3dc17efbe (and I'm
going to send this one and two other patchs in reply to this email
because I don't trust hgweb a lot)

> 
> >+# Apparently this is not possible, see https://github.com/python/mypy/issues/8282
> >+# DATE_FACTORY_MAP: Dict[str, parse_datetime_or_time_type] = {
> >+DATE_FACTORY_MAP: Dict[str, Callable[[str], Union[datetime, float]]] = {
> >      'Datetime': lambda x: ':' in x and strptime(x, '%Y/%m/%d %H:%M') or strptime(x, '%Y/%m/%d'),
> >      'Date': lambda x: strptime(x, '%Y/%m/%d'),
> >-    'Time': strptime_time
> >+    'Time': strptime_time  # returns a float (from time())
> >  }
> >-KNOWN_METAATTRIBUTES = set(('format', 'encoding', 'name'))
> >+KNOWN_METAATTRIBUTES: Set[str] = set(('format', 'encoding', 'name'))
> >+
> >+
> >+_type_of_default = TypeVar('_type_of_default')
> >-def convert_default_value(rdef, default):
> >+def convert_default_value(rdef: _RdefType,
> >+                          default: _type_of_default) -> Union[_type_of_default, datetime,
> >+                                                              date, float, str, int, bool]:
> 
> Why int and bool ?

I've been running some tests to grab all values recieved by this
function and those were in it.

-- 

Laurent Peuch -- Bram



More information about the cubicweb-devel mailing list