{"record":{"id":"e6b8ab2e1ff9657f","repo":"aosabook/500lines","slug":"fieldname-e6b8ab","errorCode":null,"errorMessage":"fieldname","messagePattern":"fieldname","errorType":"exception","errorClass":"AttributeError","httpStatus":null,"severity":"error","filePath":"objmodel/code/04-maps/objmodel.py","lineNumber":24,"sourceCode":"    def __init__(self, cls, fields):\n        \"\"\" Every object has a class. \"\"\"\n        self.cls = cls\n        self._fields = fields\n\n    def read_attr(self, fieldname):\n        \"\"\" read field 'fieldname' out of the object \"\"\"\n        result = self._read_dict(fieldname)\n        if result is not MISSING:\n            return result\n        result = self.cls._read_from_class(fieldname)\n        if _is_bindable(result):\n            return _make_boundmethod(result, self)\n        if result is not MISSING:\n            return result\n        meth = self.cls._read_from_class(\"__getattr__\")\n        if meth is not MISSING:\n            return meth(self, fieldname)\n        raise AttributeError(fieldname)\n\n    def write_attr(self, fieldname, value):\n        \"\"\" write field 'fieldname' into the object \"\"\"\n        meth = self.cls._read_from_class(\"__setattr__\")\n        return meth(self, fieldname, value)\n\n    def isinstance(self, cls):\n        \"\"\" return True if the object is an instance of class cls \"\"\"\n        return self.cls.issubclass(cls)\n\n    def callmethod(self, methname, *args):\n        \"\"\" call method 'methname' with arguments 'args' on object \"\"\"\n        meth = self.read_attr(methname)\n        return meth(*args)\n\n    def _read_dict(self, fieldname):\n        \"\"\" read an field 'fieldname' out of the object's dict \"\"\"\n        return self._fields.get(fieldname, MISSING)","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/aosabook/500lines/blob/fba689d101eb5600f5c8f4d7fd79912498e950e2/objmodel/code/04-maps/objmodel.py#L6-L42","documentation":"Raised by Base.read_attr in the 04-maps objmodel. Lookup order is identical to the 03-customizable variant (instance storage -> class MRO -> __getattr__), but instance storage is backed by a Map/shape mechanism rather than a plain dict. Reaching this raise means the field is absent from the instance's indexed storage, the class MRO, and no __getattr__ resolved it.","triggerScenarios":"Reading a field that was never stored on the instance and is not present in the class MRO, while the class defines no usable __getattr__. Because storage is map-indexed, the field must have been added through the Map's add_attribute path to be readable.","commonSituations":"Writing a field via a different storage path than the Map expects; referencing attributes before they are allocated in the instance's Map; typos; missing __getattr__ coverage.","solutions":["Store the field through write_attr so it is registered in the instance's Map storage.","Add the attribute to the Class fields so it resolves via _read_from_class.","Provide a __getattr__ on the class to handle unknown names gracefully."],"exampleFix":"// before\nobj.read_attr('height')   # AttributeError: height\n// after\nobj.write_attr('height', 180)\nobj.read_attr('height')","handlingStrategy":"validation","validationCode":"MISSING = object()\n\ndef safe_read(obj, fieldname, default=None):\n    if obj._read_dict(fieldname) is not MISSING:\n        return obj._read_dict(fieldname)\n    cls_val = obj.cls._read_from_class(fieldname)\n    if cls_val is not MISSING:\n        return cls_val\n    return default","typeGuard":"def has_field_or_getattr(obj, name):\n    MISSING = object()\n    return (obj._read_dict(name) is not MISSING\n            or obj.cls._read_from_class(name) is not MISSING\n            or obj.cls._read_from_class('__getattr__') is not MISSING)","tryCatchPattern":"try:\n    val = obj.read_attr(fieldname)\nexcept AttributeError:\n    val = <default>","preventionTips":["Use write_attr so the field is registered in the instance Map storage.","Provide __getattr__ on the class for graceful fallback.","Check storage and class MRO before read_attr."],"tags":["attribute-access","object-model","python","maps"],"backgroundTag":null,"analyzedSha":"fba689d101eb5600f5c8f4d7fd79912498e950e2","analyzedAt":"2026-08-13T06:26:32.792Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}