@@ -510,6 +510,72 @@ annotations from the class and puts them in a separate attribute:
510510 return typ
511511
512512
513+
514+ Creating a custom callable annotate function
515+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
516+
517+ Custom :term: `annotate functions <annotate function> ` may be literal functions like those
518+ automatically generated for functions, classes, and modules. Or, they may wish to utilise
519+ the encapsulation provided by classes, in which case any :term: `callable ` can be used as
520+ an :term: `annotate function `.
521+
522+ However, :term: `methods <method> `, class instances that implement
523+ :meth: `object.__call__ `, and most other callables, do not provide the same attributes as
524+ true functions, which are needed for the :attr: `~Format.VALUE_WITH_FAKE_GLOBALS `
525+ machinery to work. :func: `call_annotate_function ` and other :mod: `annotationlib `
526+ functions will attempt to infer those attributes where possible, but some of them must
527+ always be present for :attr: `~Format.VALUE_WITH_FAKE_GLOBALS ` to work.
528+
529+ Below is an example of a callable class that provides the necessary attributes to be
530+ used with all formats, and takes advantage of class encapsulation:
531+
532+ .. code-block :: python
533+
534+ class Annotate :
535+ called_formats = []
536+
537+ def __call__ (self , format = None , * , _self = None ):
538+ # When called with fake globals, `_self` will be the
539+ # actual self value, and `self` will be the format.
540+ if _self is not None :
541+ self , format = _self, self
542+
543+ self .called_formats.append(format )
544+ if format <= 2 : # VALUE or VALUE_WITH_FAKE_GLOBALS
545+ return {" x" : MyType}
546+ raise NotImplementedError
547+
548+ @ property
549+ def __defaults__ (self ):
550+ return (None ,)
551+
552+ @ property
553+ def __kwdefaults__ (self ):
554+ return {" _self" : self }
555+
556+ @ property
557+ def __code__ (self ):
558+ return self .__call__ .__code__
559+
560+ This can then be called with:
561+
562+ .. doctest ::
563+
564+ >>> from annotationlib import call_annotate_function, Format
565+ >>> call_annotate_function(Annotate(), format = Format.STRING )
566+ {'x': 'MyType'}
567+
568+ Or used as the annotate function for an object:
569+
570+ .. doctest ::
571+
572+ >>> from annotationlib import get_annotations, Format
573+ >>> class C :
574+ ... pass
575+ >>> C.__annotate__ = Annotate()
576+ >>> get_annotations(Annotate(), format = Format.STRING )
577+ {'x': 'MyType'}
578+
513579Limitations of the ``STRING `` format
514580------------------------------------
515581
0 commit comments