@@ -1065,12 +1065,14 @@ def generate_getseter_declarations(cl: ClassIR, emitter: Emitter) -> None:
10651065 getter_name (cl , attr , emitter .names ), cl .struct_name (emitter .names )
10661066 )
10671067 )
1068- emitter .emit_line ("static int" )
1069- emitter .emit_line (
1070- "{}({} *self, PyObject *value, void *closure);" .format (
1071- setter_name (cl , attr , emitter .names ), cl .struct_name (emitter .names )
1068+ # Final attributes are read-only, so they have no setter.
1069+ if attr not in cl .final_attributes :
1070+ emitter .emit_line ("static int" )
1071+ emitter .emit_line (
1072+ "{}({} *self, PyObject *value, void *closure);" .format (
1073+ setter_name (cl , attr , emitter .names ), cl .struct_name (emitter .names )
1074+ )
10721075 )
1073- )
10741076
10751077 for prop , (getter , setter ) in cl .properties .items ():
10761078 if getter .decl .implicit :
@@ -1099,11 +1101,15 @@ def generate_getseters_table(cl: ClassIR, name: str, emitter: Emitter) -> None:
10991101 if not cl .is_trait :
11001102 for attr in cl .attributes :
11011103 emitter .emit_line (f'{{"{ attr } ",' )
1102- emitter .emit_line (
1103- " (getter){}, (setter){}," .format (
1104- getter_name (cl , attr , emitter .names ), setter_name (cl , attr , emitter .names )
1104+ if attr in cl .final_attributes :
1105+ # Final attributes are read-only, so emit a NULL setter.
1106+ emitter .emit_line (f" (getter){ getter_name (cl , attr , emitter .names )} , NULL," )
1107+ else :
1108+ emitter .emit_line (
1109+ " (getter){}, (setter){}," .format (
1110+ getter_name (cl , attr , emitter .names ), setter_name (cl , attr , emitter .names )
1111+ )
11051112 )
1106- )
11071113 emitter .emit_line (" NULL, NULL}," )
11081114 for prop , (getter , setter ) in cl .properties .items ():
11091115 if getter .decl .implicit :
@@ -1129,8 +1135,10 @@ def generate_getseters(cl: ClassIR, emitter: Emitter) -> None:
11291135 if not cl .is_trait :
11301136 for i , (attr , rtype ) in enumerate (cl .attributes .items ()):
11311137 generate_getter (cl , attr , rtype , emitter )
1132- emitter .emit_line ("" )
1133- generate_setter (cl , attr , rtype , emitter )
1138+ # Final attributes are read-only, so they have no setter.
1139+ if attr not in cl .final_attributes :
1140+ emitter .emit_line ("" )
1141+ generate_setter (cl , attr , rtype , emitter )
11341142 if i < len (cl .attributes ) - 1 :
11351143 emitter .emit_line ("" )
11361144 for prop , (getter , setter ) in cl .properties .items ():
0 commit comments