Skip to main content

1704. gopy object / type / class-callable full-file ports

Rule

Every CPython source file in scope is ported in full. No function in those files may be left unported. The deliverable for each file is a Go file whose function list 1:1 covers the C function list. Once this spec lands we never come back to these files for a missing slot.

Files in scope

#CPython fileLinesgopy targetStatus
AObjects/object.c~2,600objects/object.go + objects/object_proto.gopartial
BObjects/typeobject.c~12,000objects/type.go + objects/usertype.go + objects/type_call.go + objects/type_inherit.gopartial
CObjects/classobject.c~620objects/method.go (BoundMethod block)partial
DObjects/funcobject.c~1,260objects/function.go + objects/method.go (classmethod, staticmethod blocks)partial
EPython/ceval.c name ops~80vm/eval_simple.go (storeIn / lookupIn / deleteIn)partial
FInclude/cpython/classobject.h30objects/method.go struct decldone
GInclude/cpython/funcobject.hvariousobjects/function.go + objects/method.go struct declsdone

Sources of truth live under /Users/apple/cpython-314/.

Phase index

Each phase ports one file (or one disjoint block of a file) end to end. Phases are independent unless the Blocks column says otherwise. Final gate closes #544.

PhaseFileBlockBlocksStatus
1A object.cobject_methods + object_getsets + object_* impls-done
2D funcobject.cPyClassMethod_Type (all cm_* functions)-partial
3D funcobject.cPyStaticMethod_Type (all sm_* functions)-partial
4D funcobject.cPyFunction_Type (all func_* functions)-partial
5C classobject.cPyMethod_Type (all method_* functions)-partial
6B typeobject.ctype_new pipeline (type_new_* functions)1,2,3,4,5partial
7B typeobject.cinherit_slots (every slot edge)6partial
8E ceval.cSTORE_NAME / LOAD_NAME / DELETE_NAME-partial
Gate-enum + re + fnmatch smokeallpending

Phase 1 - Objects/object.c full port

Functions to port

CPython lists these in object_methods (around line 6048) and object_getsets (around line 6075), plus the supporting object_* implementations earlier in the file. Every row must land.

C functionExposed asgopy hookStatus
object_newobject.__new__SetTypeDescr(objectType, "__new__", ...)done
object_initobject.__init__SetTypeDescr(objectType, "__init__", ...)done
object_reprobject.__repr__SetTypeDescr(objectType, "__repr__", ...)done
object_strobject.__str__SetTypeDescr(objectType, "__str__", ...)done
object_richcompare__eq__, __ne__, __lt__, __le__, __gt__, __ge__six entries on objectTypedone
object_get_class / object_set_classobject.__class__ getsetNewGetSetDescr("__class__", ...)done (setter rejects with TypeError; full compat check deferred)
object_getattroobject.__getattribute__already wired as GenericGetAttr (verify)done
object_setattroobject.__setattr__ / __delattr__already wired (verify)done
object_hashobject.__hash__SetTypeDescr(objectType, "__hash__", ...)done
object_formatobject.__format__SetTypeDescr(objectType, "__format__", ...)done
object_sizeofobject.__sizeof__SetTypeDescr(objectType, "__sizeof__", ...)done (uses reflect.Size; CPython tp_basicsize equivalent deferred)
object___dir__object.__dir__SetTypeDescr(objectType, "__dir__", ...)done
object___reduce__object.__reduce__SetTypeDescr(objectType, "__reduce__", ...)done (forwards to __reduce_ex__(2); pickle deferred)
object___reduce_ex__object.__reduce_ex__SetTypeDescr(objectType, "__reduce_ex__", ...)done (override detection + fallback TypeError; copyreg deferred)
object___getstate__object.__getstate__SetTypeDescr(objectType, "__getstate__", ...)done (simple case; __slotnames__ deferred)
object___subclasshook__object.__subclasshook__ (classmethod)wrap in NewClassMethoddone
object___init_subclass__object.__init_subclass__ (classmethod)wrap in NewClassMethoddone
object_get_dict / object_set_dictobject.__dict__ getsetNewGetSetDescr("__dict__", ...)done (getter; setter deferred to type_new dict layout work)
object___class_getitem__object.__class_getitem__ (classmethod)SetTypeDescr + classmethoddeferred (not in CPython 3.14 object_methods; lives on subclasses)

Gates

GateCommandExpectedStatus
1.1gopy -c 'print(object.__repr__)'repr-of-method-descriptorpass
1.2gopy -c 'class C: pass; print(C.__class__ is type)'Truepass
1.3gopy -c 'class C: pass; print(object.__new__(C).__class__ is C)'Truepass
1.4gopy -c 'class C: pass; print(sorted(dir(C())) == EXPECTED_LIST)'Truepass (dir produces canonical set)
1.5gopy -c 'print(hash(object.__hash__))'runs without exceptionpass
1.6gopy -c 'class C: pass; print(C().__class__)'<class '__main__.C'>pass
1.7gopy -c 'object.__format__(42, "")''42'pass

CPython citations

#Reference
1Objects/object.c:6048 object_methods table
2Objects/object.c:6075 object_getsets table
3Objects/object.c:5800 object___subclasshook__
4Objects/object.c:5750 object___init_subclass__
5Objects/object.c:766 object_format
6Objects/object.c:884 object_richcompare
7Objects/object.c:1146 object_get_class / object_set_class
8Objects/object.c:1462 object_get_dict / object_set_dict
9Objects/object.c:5900 object___getstate__

Phase 2 - Objects/funcobject.c classmethod block

Functions to port

C functionSurfaceStatus
cm_initclassmethod(fn) constructordone
cm_descr_get__get__(obj, type) returning BoundMethod(fn, type)done
cm_traverseGC visit cm_callable and cm_dictdone (visits callable only)
cm_dealloc(Go has GC, no-op)n/a
cm_clear(Go has GC, no-op)n/a
cm_repr<classmethod object> textdone
cm_memberlist__func__ memberpending
cm_getsetlist__wrapped__, __isabstractmethod__, __dict__pending
__set_name__ forwardingcall cm.__func__.__set_name__(owner, name)pending
PEP 487 forwardingclassmethod inherits PEP 487 hooks from wrapped fnpending

Gates

GateCommandExpected
2.1gopy -c 'class C:\n @classmethod\n def f(cls): pass\nprint(C.__dict__["f"].__func__.__name__)'f
2.2gopy -c 'class C:\n @classmethod\n def f(cls): pass\nprint(C.__dict__["f"].__wrapped__ is C.__dict__["f"].__func__)'True
2.3gopy -c 'class C:\n @classmethod\n def f(cls): pass\nprint(C.__dict__["f"].__isabstractmethod__)'False

CPython citations

#Reference
1Objects/funcobject.c:1059 cm_init
2Objects/funcobject.c:1024 cm_descr_get
3Objects/funcobject.c:1097 cm_memberlist
4Objects/funcobject.c:1106 cm_traverse
5Objects/funcobject.c:1119 PyClassMethod_Type

Phase 3 - Objects/funcobject.c staticmethod block

Functions to port

C functionSurfaceStatus
sm_initstaticmethod(fn) constructordone
sm_descr_get__get__(obj, type) returns wrapped fndone
sm_traverseGC visit sm_callable and sm_dictdone (callable only)
sm_dealloc / sm_clear(Go GC, no-op)n/a
sm_repr<staticmethod object> textdone
sm_calldirect call forwards to wrapped fn (CPython 3.10+)pending
sm_memberlist__func__ memberpending
sm_getsetlist__wrapped__, __isabstractmethod__, __dict__, __name__, __qualname__, __module__pending
__set_name__ forwardingforward to wrapped fnpending

Gates

GateCommandExpected
3.1gopy -c 'class C:\n @staticmethod\n def f(): return 1\nprint(C.__dict__["f"].__func__())'1
3.2gopy -c 'sm = staticmethod(lambda: 7); print(sm())'7 (sm_call)
3.3gopy -c 'class C:\n @staticmethod\n def f(): pass\nprint(C.__dict__["f"].__name__)'f

CPython citations

#Reference
1Objects/funcobject.c:1184 sm_init
2Objects/funcobject.c:1167 sm_descr_get
3Objects/funcobject.c:1148 sm_call
4Objects/funcobject.c:1211 sm_memberlist
5Objects/funcobject.c:1220 sm_traverse
6Objects/funcobject.c:1233 PyStaticMethod_Type

Phase 4 - Objects/funcobject.c PyFunction_Type block

Functions to port

C functionSurfaceStatus
PyFunction_Newconstructordone
PyFunction_NewWithQualNameconstructor with qualnamedone
func_get_code / func_set_code__code__ getsetdone
func_get_name / func_set_name__name__ getsetdone
func_get_qualname / func_set_qualname__qualname__ getsetdone
func_get_defaults / func_set_defaults__defaults__ getsetdone
func_get_kwdefaults / func_set_kwdefaults__kwdefaults__ getsetdone
func_get_annotations / func_set_annotations__annotations__ getsetdone
func_get_dict / func_set_dict__dict__ getsetdone
func_get_module / func_set_module__module__ getsetpartial (verify)
func_repr<function name at 0x...>partial (verify exact format)
func_call / func_vectorcallfunction calldone
func_descr_get__get__ returns BoundMethoddone
func_traverseGC visit globals, defaults, etc.partial
function_memberlist__globals__, __closure__, __builtins__partial
function___get_signature__(CPython internal)n/a
func_iternext(none)n/a

Gates

GateCommandExpected
4.1gopy -c 'def f(): pass\nprint(f.__globals__ is globals())'True
4.2gopy -c 'def f(): pass\nprint(f.__module__)'__main__
4.3gopy -c 'def f(): pass\nprint(repr(f).startswith("<function f at"))'True

CPython citations

#Reference
1Objects/funcobject.c:30 PyFunction_NewWithQualName
2Objects/funcobject.c:760 func_getsetlist
3Objects/funcobject.c:810 func_memberlist
4Objects/funcobject.c:920 func_repr
5Objects/funcobject.c:1232 PyFunction_Type

Phase 5 - Objects/classobject.c PyMethod_Type full port

Functions to port

C functionSurfaceStatus
PyMethod_Newconstructordone
method_repr<bound method ClassName.fn of <obj>>partial (wrong text)
method_call / method_vectorcallcall with self prependeddone
method_getattroattribute forward through to im_funcdone
method_traverseGC visit im_func and im_selfdone
method_richcompare__eq__ / __ne__ over (func, self)pending
method_hashhash combining im_func + im_selfpending
method_memberlist__func__ / __self__ membersdone (via getset)
method_getset__doc__, __name__, __module__, __qualname__, __self_class__pending
method___reduce__pickle hookpending
PyMethod_Function / PyMethod_SelfC API accessorsdone (as Go methods)

Gates

GateCommandExpected
5.1gopy -c 'class C:\n def f(self): pass\nc = C()\nprint(c.f == c.f)'True
5.2gopy -c 'class C:\n def f(self): pass\nprint(C().f != C().f)'True
5.3gopy -c 'class C:\n def f(self): pass\nprint({C().f, C().f})'set with 2 entries
5.4gopy -c 'class C:\n def f(self): pass\nprint(C().f.__name__)'f
5.5gopy -c 'class C:\n def f(self): pass\nprint(repr(C().f).startswith("<bound method C.f of"))'True

CPython citations

#Reference
1Objects/classobject.c:38 PyMethod_New
2Objects/classobject.c:75 method_getattro
3Objects/classobject.c:135 method_call / method_vectorcall
4Objects/classobject.c:206 method_richcompare
5Objects/classobject.c:230 method_hash
6Objects/classobject.c:262 method_traverse
7Objects/classobject.c:268 PyMethod_Type
8Objects/classobject.c:280 method_repr

Phase 6 - Objects/typeobject.c type_new pipeline

Functions to port

C functionPurposegopy hookStatus
type_newtop-level dispatchNewUserTypepartial
type_new_get_basesresolve bases tupleinline in NewUserTypedone
type_new_allocallocate type objectNewTypedone
type_new_set_attrsstamp __module__ / __qualname__ / __doc__, classmethod-wrap PEP 487 hookspartial (classmethod wrap done; defaults missing)partial
type_new_set_namesPEP 487 __set_name__ passtypeSetNamesdone
type_init_subclassPEP 487 __init_subclass__ passtypeInitSubclassdone
type_new_descriptors__slots__ -> MemberDescr tableinstallSlotsdone
type_new_implmro computationNewTypedone
type_new_set_docdocstring stampinginlinepending
type_callmetaclass call -> tp_new + tp_initTypeType.Callpartial
type_inittype.initn/a (Go init)done
type_getattrotype attribute lookuptypeGetAttrdone
type_setattrotype attribute settypeSetAttrdone
fixup_slot_dispatcherswire C slots from Python dundersfixupSlotDispatcherspartial

Gates

GateCommandExpected
6.1gopy -c 'class C: """doc"""\nprint(C.__doc__)'doc
6.2gopy -c 'class C: pass\nprint(C.__module__)'__main__
6.3gopy -c 'class C:\n class D: pass\nprint(C.D.__qualname__)'C.D
6.4gopy -c 'class M(type):\n def __init_subclass__(cls, **kw): cls.x=kw["x"]\nclass C(metaclass=M, x=1): pass\nprint(C.x)'1

CPython citations

#Reference
1Objects/typeobject.c:4153 type_new
2Objects/typeobject.c:4350 type_new_set_attrs
3Objects/typeobject.c:4419 type_new_set_attrs (classmethod wrap branch)
4Objects/typeobject.c:4549 type_new_set_names
5Objects/typeobject.c:4595 type_init_subclass
6Objects/typeobject.c:9874 fixup_slot_dispatchers

Phase 7 - Objects/typeobject.c inherit_slots

Slots to verify propagation for

Every row from CPython's slotdefs table must propagate from the base type when the subclass does not override it.

Slot groupSlotsStatus
BasicRepr, Str, Hash, Call, Getattro, Setattro, Iter, IterNext, RichCmp, DescrGet, DescrSetpartial (4 of 11 propagate)
NumberAdd, Subtract, Multiply, Remainder, Divmod, Power, Negative, Positive, Absolute, Bool, Invert, Lshift, Rshift, And, Xor, Or, Int, Float, InPlace*, FloorDivide, TrueDivide, Index, MatrixMultiplypending
MappingLength, GetItem, SetItem, DelItempending
SequenceLength, Concat, Repeat, GetItem, SetItem, Contains, InPlaceConcat, InPlaceRepeatpending
AsyncAwait, Aiter, Anextpending
BufferGetbuffer, Releasebufferpending

Gates

GateCommandExpected
7.1gopy -c 'class L(list): pass\nl=L([1,2,3])\nprint(len(l), l[1], list(reversed(l)))'3 2 [3, 2, 1]
7.2gopy -c 'class D(dict): pass\nd=D({"a":1})\nprint(d["a"], len(d), "a" in d)'1 1 True
7.3gopy -c 'class I(int): pass\nprint(I(3)+I(4), I(5)*I(2))'7 10

CPython citations

#Reference
1Objects/typeobject.c:7521 inherit_slots
2Objects/typeobject.c:9770 slotdefs table header

Phase 8 - Python/ceval.c name ops

Functions to port

Opcodegopy hookCPython semanticsStatus
STORE_NAMEstoreInPyObject_SetItem(locals, name, v); fast-path when locals is exact dictdone
LOAD_NAMElookupInPyMapping_GetOptionalItem(locals, name), then globals, then builtinspartial (exact-dict fast path bypasses subclass getitem)
DELETE_NAMEdeleteInPyObject_DelItem(locals, name)partial (panics on non-Dict)
LOAD_CLASSDEREF (in class scope)lookupClassDerefsame protocol as LOAD_NAME for the class namespaceverify

Gates

GateCommandExpected
8.1gopy -c 'class D(dict):\n def __setitem__(self,k,v): super().__setitem__(k,v*2)\nclass M(type):\n @classmethod\n def __prepare__(mcs,n,b): return D()\nclass C(metaclass=M): x=10\nprint(C.x)'20
8.2gopy -c 'class D(dict):\n def __getitem__(self,k): return super().__getitem__(k)+1\nclass M(type):\n @classmethod\n def __prepare__(mcs,n,b): return D()\nclass C(metaclass=M):\n x=10\n y=x\nprint(C.y)'11
8.3gopy -c 'class D(dict):\n def __delitem__(self,k): super().__delitem__(k)\nclass M(type):\n @classmethod\n def __prepare__(mcs,n,b): return D()\nclass C(metaclass=M):\n x=10\n del x\nprint(hasattr(C,"x"))'False

CPython citations

#Reference
1Python/bytecodes.c STORE_NAME
2Python/bytecodes.c LOAD_NAME
3Python/bytecodes.c DELETE_NAME

Final gate

#CommandExpected
F.1gopy -c 'import enum; print(enum.FlagBoundary.STRICT)'FlagBoundary.STRICT
F.2gopy -c 'import enum; print(list(enum.FlagBoundary))'[STRICT, CONFORM, EJECT, KEEP] (or members in spec order)
F.3gopy -c 'import re; print(re.match(r"(\d+)-(\d+)", "12-34").groups())'('12', '34')
F.4gopy -c 'import fnmatch; print(fnmatch.fnmatch("foo.py", "*.py"))'True
F.5spec 1703 phase 7 rowflips to done
F.6spec 1702 enum rowflips to done

Out of scope

TopicReason
Full pickle (__reduce__, copyreg)Phase 1 wires the descriptor; real reduce_newobj follows in a pickle spec
__class__ reassignment validationPhase 1 wires the getset; large compat rules deferred
inherit_slots async + buffer rowsNo async / buffer subsystem ports landed
Locale-specific __hash__ for stringsstring subsystem owns its hash
GC tp_clear / tp_deallocGo has GC; explicit clear/dealloc only ported where they hold non-Go state

Today's already-landed pieces (do not redo)

FileHunkPhase
objects/usertype.gotypeSetNames PEP 487 pass6
objects/usertype.gotypeInitSubclass6
vm/eval_simple.gostoreIn dispatches through PyObject_SetItem for dict subclasses8
objects/function.goFunctionType.Hash = identityHash4
objects/function_builtin.goBuiltinFunctionType.Hash = identityHash(CPython inheritance)
objects/method_descr.goMethodDescrType.Hash = identityHash(CPython inheritance)

Tasks

One task per phase, all blocking #544.

TaskPhaseTitle
TBD1Port Objects/object.c methodlist + getsetlist in full
TBD2Port Objects/funcobject.c classmethod block in full
TBD3Port Objects/funcobject.c staticmethod block in full
TBD4Port Objects/funcobject.c PyFunction_Type block in full
TBD5Port Objects/classobject.c PyMethod_Type in full
TBD6Port Objects/typeobject.c type_new pipeline in full
TBD7Audit Objects/typeobject.c inherit_slots: every slot edge
TBD8Port Python/ceval.c STORE_NAME / LOAD_NAME / DELETE_NAME in full