classification
Title: get_type_hints does not evaluate ForwardRefs inside NewType
Type: behavior Stage:
Components: Library (Lib) Versions: Python 3.11, Python 3.10
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: AlexWaygood, andreash, gvanrossum, kj, sobolevn
Priority: normal Keywords:

Created on 2022-01-13 21:49 by andreash, last changed 2022-01-14 15:57 by andreash.

Messages (4)
msg410528 - (view) Author: Andreas H. (andreash) * Date: 2022-01-13 21:49
Consider the following: 

    NewT = typing.NewType("NewT", typing.List[typing.Optional['Z']] )

    class Z:
        pass


Now get_type_hints() does not resolve the ForwardRef within NewType (but it does so for TypedDict, dataclasses, NamedTuple).


Neither of the following works.

1)  
    class dummy:
        test: NewT

    get_type_hints(test,None,None)
    
    print( NewT.__supertype__.__args__[0].__args__[0]__.__forward_evaluated__ )
    # --> False
    
Note: investigating the return value of get_type_hints does not change the outcome. 
get_type_hints() patches ForwardRefs in-place.


2) 
    get_type_hints(NewT,None,None)
    # --> TypeError   is not a module, class, method, or function



For Python 3.10+ a workaround exists, but requires access to implementation details of NewType:
  
   class dummy:
       test: NewT.__supertype__
   get_type_hints( dummy, globalns=sys.modules[NewT.__module__].__dict__, localns=None )


Possible solution could be 
 A) to extent `get_type_hints` to explicitly handle NewType (basically call _eval_type for the __supertype__ member).
    That makes approach 2) work (but not 1)
 or B) to extend _eval_type() to handle process NewType as well. This would make 1) work (but not 2).

I guess, since NewType is supposed to be semantically a subclass of the referred type, 2) is probably the preferred approach, which would suggest A). 


Strictly speaking this issue exits in all Python versions that have NewType, but it is easier to fix in 3.10 because there NewType has the __module__ member.
msg410548 - (view) Author: Nikita Sobolev (sobolevn) * (Python triager) Date: 2022-01-14 09:50
I think we should go with `1)` and `A`.
Adding a special case for getting hints from `NewType` directly does seem inconsistent with other type-constructs.

Do you want to fix this? :)
Or I can work on it today if you wish!
msg410549 - (view) Author: Nikita Sobolev (sobolevn) * (Python triager) Date: 2022-01-14 09:50
Oh, I mean `1)` and `B`
msg410569 - (view) Author: Andreas H. (andreash) * Date: 2022-01-14 15:57
Allright. B) sounds good to me. I dont think I have time today, so please feel to tackle the issue. If not I can look at it the next week.
History
Date User Action Args
2022-01-14 15:57:38andreashsetmessages: + msg410569
2022-01-14 09:50:43sobolevnsetmessages: + msg410549
2022-01-14 09:50:10sobolevnsetmessages: + msg410548
2022-01-14 07:23:13AlexWaygoodsetnosy: + sobolevn, AlexWaygood
2022-01-13 21:49:34andreashcreate