@@ -96,6 +96,45 @@ def provides_nodes(decl_type):
9696 return isinstance (decl_type , type ) and issubclass (decl_type , Node )
9797
9898
99+ def get_only_type_arg (decl_type ):
100+ type_args = get_type_arguments (decl_type )
101+ if len (type_args ) == 1 :
102+ return type_args [0 ]
103+ else :
104+ return None
105+
106+
107+ def process_annotated_property (name , decl_type , known_property_names ):
108+ multiplicity = Multiplicity .SINGULAR
109+ is_reference = False
110+ if get_type_origin (decl_type ) is ReferenceByName :
111+ decl_type = get_only_type_arg (decl_type ) or decl_type
112+ is_reference = True
113+ if is_sequence_type (decl_type ):
114+ decl_type = get_only_type_arg (decl_type ) or decl_type
115+ multiplicity = Multiplicity .MANY
116+ if get_type_origin (decl_type ) is Union :
117+ type_args = get_type_arguments (decl_type )
118+ if len (type_args ) == 1 :
119+ decl_type = type_args [0 ]
120+ elif len (type_args ) == 2 :
121+ if type_args [0 ] is type (None ):
122+ decl_type = type_args [1 ]
123+ elif type_args [1 ] is type (None ):
124+ decl_type = type_args [0 ]
125+ else :
126+ raise Exception (f"Unsupported feature { name } of type { decl_type } " )
127+ if multiplicity == Multiplicity .SINGULAR :
128+ multiplicity = Multiplicity .OPTIONAL
129+ else :
130+ raise Exception (f"Unsupported feature { name } of type { decl_type } " )
131+ if not isinstance (decl_type , type ):
132+ raise Exception (f"Unsupported feature { name } of type { decl_type } " )
133+ is_containment = provides_nodes (decl_type ) and not is_reference
134+ known_property_names .add (name )
135+ return PropertyDescription (name , decl_type , is_containment , is_reference , multiplicity )
136+
137+
99138class Concept (ABCMeta ):
100139
101140 def __init__ (cls , what , bases = None , dict = None ):
@@ -115,50 +154,12 @@ def node_properties(cls):
115154 yield from cls ._direct_node_properties (cl , names )
116155
117156 def _direct_node_properties (cls , cl , known_property_names ):
118- def get_type_arg (decl_type ):
119- type_args = get_type_arguments (decl_type )
120- if len (type_args ) == 1 :
121- return type_args [0 ]
122- else :
123- return decl_type
124-
125157 anns = getannotations (cl )
126158 if not anns :
127159 return
128160 for name in anns :
129161 if name not in known_property_names and cls .is_node_property (name ):
130- is_containment = False
131- multiplicity = Multiplicity .SINGULAR
132- decl_type = None
133- is_reference = False
134- if name in anns :
135- decl_type = anns [name ]
136- if get_type_origin (decl_type ) is ReferenceByName :
137- decl_type = get_type_arg (decl_type )
138- is_reference = True
139- if is_sequence_type (decl_type ):
140- decl_type = get_type_arg (decl_type )
141- multiplicity = Multiplicity .MANY
142- if get_type_origin (decl_type ) is Union :
143- type_args = get_type_arguments (decl_type )
144- if len (type_args ) == 1 :
145- decl_type = type_args [0 ]
146- elif len (type_args ) == 2 :
147- if type_args [0 ] is type (None ):
148- decl_type = type_args [1 ]
149- elif type_args [1 ] is type (None ):
150- decl_type = type_args [0 ]
151- else :
152- raise Exception (f"Unsupported feature { name } of type { decl_type } " )
153- if multiplicity == Multiplicity .SINGULAR :
154- multiplicity = Multiplicity .OPTIONAL
155- else :
156- raise Exception (f"Unsupported feature { name } of type { decl_type } " )
157- if not isinstance (decl_type , type ):
158- raise Exception (f"Unsupported feature { name } of type { decl_type } " )
159- is_containment = provides_nodes (decl_type ) and not is_reference
160- known_property_names .add (name )
161- yield PropertyDescription (name , decl_type , is_containment , is_reference , multiplicity )
162+ yield process_annotated_property (name , anns [name ], known_property_names )
162163 for name in dir (cl ):
163164 if name not in known_property_names and cls .is_node_property (name ):
164165 known_property_names .add (name )
@@ -211,7 +212,8 @@ def source(self) -> Optional[Source]:
211212
212213 @internal_property
213214 def properties (self ):
214- return (PropertyDescription (p .name , p .type , p .is_containment , p .is_reference , p .multiplicity , getattr (self , p .name ))
215+ return (PropertyDescription (p .name , p .type , p .is_containment , p .is_reference , p .multiplicity ,
216+ getattr (self , p .name ))
215217 for p in self .__class__ .node_properties )
216218
217219 @internal_property
0 commit comments