33from collections .abc import Mapping , Sequence
44import warnings
55import operator
6+ try :
7+ import annotationlib # py3.14+
8+ except ImportError :
9+ annotationlib = None # py3.13-
610
711from amaranth ._utils import final
812from amaranth .hdl import *
@@ -1209,7 +1213,19 @@ def __repr__(self):
12091213
12101214class _AggregateMeta (ShapeCastable , type ):
12111215 def __new__ (metacls , name , bases , namespace ):
1212- if "__annotations__" not in namespace :
1216+ annotations = None
1217+ skipped_annotations = set ()
1218+ wrapped_annotate = None
1219+ if annotationlib is not None :
1220+ if annotate := annotationlib .get_annotate_from_class_namespace (namespace ):
1221+ annotations = annotationlib .call_annotate_function (
1222+ annotate , format = annotationlib .Format .VALUE )
1223+ def wrapped_annotate (format ):
1224+ annos = annotationlib .call_annotate_function (annotate , format , owner = cls )
1225+ return {k : v for k , v in annos .items () if k not in skipped_annotations }
1226+ else :
1227+ annotations = namespace .get ("__annotations__" )
1228+ if annotations is None :
12131229 # This is a base class without its own layout. It is not shape-castable, and cannot
12141230 # be instantiated. It can be used to share behavior.
12151231 return type .__new__ (metacls , name , bases , namespace )
@@ -1218,13 +1234,14 @@ def __new__(metacls, name, bases, namespace):
12181234 # be instantiated. It can also be subclassed, and used to share layout and behavior.
12191235 layout = dict ()
12201236 default = dict ()
1221- for field_name in {** namespace [ "__annotations__" ] }:
1237+ for field_name in {** annotations }:
12221238 try :
1223- Shape .cast (namespace [ "__annotations__" ] [field_name ])
1239+ Shape .cast (annotations [field_name ])
12241240 except TypeError :
12251241 # Not a shape-castable annotation; leave as-is.
12261242 continue
1227- layout [field_name ] = namespace ["__annotations__" ].pop (field_name )
1243+ skipped_annotations .add (field_name )
1244+ layout [field_name ] = annotations .pop (field_name )
12281245 if field_name in namespace :
12291246 default [field_name ] = namespace .pop (field_name )
12301247 cls = type .__new__ (metacls , name , bases , namespace )
@@ -1235,6 +1252,8 @@ def __new__(metacls, name, bases, namespace):
12351252 .format (", " .join (default .keys ())))
12361253 cls .__layout = cls .__layout_cls (layout )
12371254 cls .__default = default
1255+ if wrapped_annotate is not None :
1256+ cls .__annotate__ = wrapped_annotate
12381257 return cls
12391258 else :
12401259 # This is a class that has a base class with a layout and annotations. Such a class
0 commit comments