Call an __annotate__ function. __annotate__ functions are normally generated by the compiler to defer the evaluation of annotations. They can be called with any of the format arguments in the Format enum, but compiler-generated __annotate__ functions only support the VALUE format. Th
(annotate, format, *, owner=None, _is_evaluate=False)
| 695 | |
| 696 | |
| 697 | def call_annotate_function(annotate, format, *, owner=None, _is_evaluate=False): |
| 698 | """Call an __annotate__ function. __annotate__ functions are normally |
| 699 | generated by the compiler to defer the evaluation of annotations. They |
| 700 | can be called with any of the format arguments in the Format enum, but |
| 701 | compiler-generated __annotate__ functions only support the VALUE format. |
| 702 | This function provides additional functionality to call __annotate__ |
| 703 | functions with the FORWARDREF and STRING formats. |
| 704 | |
| 705 | *annotate* must be an __annotate__ function, which takes a single argument |
| 706 | and returns a dict of annotations. |
| 707 | |
| 708 | *format* must be a member of the Format enum or one of the corresponding |
| 709 | integer values. |
| 710 | |
| 711 | *owner* can be the object that owns the annotations (i.e., the module, |
| 712 | class, or function that the __annotate__ function derives from). With the |
| 713 | FORWARDREF format, it is used to provide better evaluation capabilities |
| 714 | on the generated ForwardRef objects. |
| 715 | |
| 716 | """ |
| 717 | if format == Format.VALUE_WITH_FAKE_GLOBALS: |
| 718 | raise ValueError("The VALUE_WITH_FAKE_GLOBALS format is for internal use only") |
| 719 | try: |
| 720 | return annotate(format) |
| 721 | except NotImplementedError: |
| 722 | pass |
| 723 | if format == Format.STRING: |
| 724 | # STRING is implemented by calling the annotate function in a special |
| 725 | # environment where every name lookup results in an instance of _Stringifier. |
| 726 | # _Stringifier supports every dunder operation and returns a new _Stringifier. |
| 727 | # At the end, we get a dictionary that mostly contains _Stringifier objects (or |
| 728 | # possibly constants if the annotate function uses them directly). We then |
| 729 | # convert each of those into a string to get an approximation of the |
| 730 | # original source. |
| 731 | |
| 732 | # Attempt to call with VALUE_WITH_FAKE_GLOBALS to check if it is implemented |
| 733 | # See: https://github.com/python/cpython/issues/138764 |
| 734 | # Only fail on NotImplementedError |
| 735 | try: |
| 736 | annotate(Format.VALUE_WITH_FAKE_GLOBALS) |
| 737 | except NotImplementedError: |
| 738 | # Both STRING and VALUE_WITH_FAKE_GLOBALS are not implemented: fallback to VALUE |
| 739 | return annotations_to_string(annotate(Format.VALUE)) |
| 740 | except Exception: |
| 741 | pass |
| 742 | |
| 743 | globals = _StringifierDict({}, format=format) |
| 744 | is_class = isinstance(owner, type) |
| 745 | closure, _ = _build_closure( |
| 746 | annotate, owner, is_class, globals, allow_evaluation=False |
| 747 | ) |
| 748 | func = types.FunctionType( |
| 749 | annotate.__code__, |
| 750 | globals, |
| 751 | closure=closure, |
| 752 | argdefs=annotate.__defaults__, |
| 753 | kwdefaults=annotate.__kwdefaults__, |
| 754 | ) |
no test coverage detected
searching dependent graphs…