{"record":{"id":"562932498be5706f","repo":"pandas-dev/pandas","slug":"k-is-a-python-keyword","errorCode":null,"errorMessage":"{k} is a python keyword","messagePattern":"(.+?) is a python keyword","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"pandas/_config/config.py","lineNumber":576,"sourceCode":"    key = key.lower()\n\n    if key in _registered_options:\n        raise OptionError(f\"Option '{key}' has already been registered\")\n    if key in _reserved_keys:\n        raise OptionError(f\"Option '{key}' is a reserved key\")\n\n    # the default value should be legal\n    if validator:\n        validator(defval)\n\n    # walk the nested dict, creating dicts as needed along the path\n    path = key.split(\".\")\n\n    for k in path:\n        if not re.match(\"^\" + tokenize.Name + \"$\", k):\n            raise ValueError(f\"{k} is not a valid identifier\")\n        if keyword.iskeyword(k):\n            raise ValueError(f\"{k} is a python keyword\")\n\n    cursor = _global_config\n    msg = \"Path prefix to option '{option}' is already an option\"\n\n    for i, p in enumerate(path[:-1]):\n        if not isinstance(cursor, dict):\n            raise OptionError(msg.format(option=\".\".join(path[:i])))\n        if p not in cursor:\n            cursor[p] = {}\n        cursor = cursor[p]\n\n    if not isinstance(cursor, dict):\n        raise OptionError(msg.format(option=\".\".join(path[:-1])))\n\n    # a namespace already lives here, i.e. `key` is a path prefix to one or\n    # more already-registered options; registering it would clobber them\n    # (GH#29242)\n    if isinstance(cursor.get(path[-1]), dict):","sourceCodeStart":558,"sourceCodeEnd":594,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/_config/config.py#L558-L594","documentation":"Raised by register_option (config.py:575-576) as a ValueError when any path segment of the key is a Python keyword (checked via keyword.iskeyword). Keywords cannot serve as identifiers because attribute access via DictWrapper would be impossible.","triggerScenarios":"cf.register_option('display.class', ...) or 'display.if' — 'class' and 'if' are Python keywords.","commonSituations":"Naming an option after a Python construct (class, return, lambda, for, while, etc.).","solutions":["Rename the segment to a non-keyword (e.g. 'display.klass' or 'display.if_value').","Pre-screen segments with `import keyword; keyword.iskeyword(seg)`.","Avoid Python reserved words when naming your option namespace."],"exampleFix":"# before\ncf.register_option('display.class', True)  # class is a python keyword\n\n# after\ncf.register_option('display.klass', True)","handlingStrategy":"validation","validationCode":"import keyword\ndef no_keywords(key: str) -> bool:\n    return not any(keyword.iskeyword(seg) for seg in key.lower().split('.'))","typeGuard":"def is_keyword_free(key: str) -> bool:\n    import keyword\n    return not any(keyword.iskeyword(s) for s in key.split('.'))","tryCatchPattern":null,"preventionTips":["Avoid Python reserved words in any segment of an option key.","Screen candidate names with keyword.iskeyword before registering.","Use domain-specific synonyms (klass, if_value) when a keyword is the natural name."],"tags":["config","register-option","keyword","validation"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}