Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

Using class methods strategy for structuring Enums fails without clear info

未关闭
#479 4 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
42/100
Issue 类型
缺陷
描述清晰度
基本清楚
活跃度
停滞
技术栈
python
领域
devtools

调研方向

Start with the reproduction in the issue, then inspect cattrs/converters.py around _structure_call, _single_dispatch, and function_dispatch, along with use_class_methods. Verify why the Enum handler bypasses the class method and compare structuring with unstructuring. Done means the intended dispatch behavior is resolved or the conflict is clearly reported, with the reproduction no longer producing the shown round-trip failure.

由索引模型根据 Issue 内容生成。

描述

enhancement
  • cattrs version: 23.2.3
  • Python version: Python 3.9.16
  • Operating System: macOS Ventura 13.5.2 (22G91)
Description

I want to ultimately serialize an Enum (anywhere it appears in dataclasses) using its name, rather than its value (as the value is an integer that isn't very human interpretable, whereas the name is).

It looks like for some of my other classes, the use_class_methods strategy will be very convenient, so I thought I would use that here. I know there are other approach I could and probably should take, but I was fairly surprised by the resulting behaviour so thought it was worth an issue.

What I Did

If I run this python script:

from enum import Enum

from cattrs import Converter
from cattrs.strategies import use_class_methods

class MyEnum(Enum):
    SomeName = 5
    AnotherName = 12
    @classmethod
    def _structure(cls, data: str) -> "MyEnum":
        return cls[data]
    def _unstructure(self) -> str:
        return self.name

converter = Converter()
use_class_methods(converter, "_structure", "_unstructure")

print(converter.unstructure(MyEnum["SomeName"]))
print(converter.structure(5, MyEnum))
print(converter.structure("SomeName", MyEnum))

The output show that the unstructuring behaviour is what I want (using the name), but structuring still expects a value, and doesn't work with a name:

SomeName
MyEnum.SomeName
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/ktdb353/workplace/kazu/.venv/lib/python3.9/site-packages/cattrs/converters.py", line 332, in structure
    return self._structure_func.dispatch(cl)(obj, cl)
  File "/Users/ktdb353/workplace/kazu/.venv/lib/python3.9/site-packages/cattrs/converters.py", line 430, in _structure_call
    return cl(obj)
  File "/Users/ktdb353/.pyenv/versions/3.9.16/lib/python3.9/enum.py", line 384, in __call__
    return cls.__new__(cls, value)
  File "/Users/ktdb353/.pyenv/versions/3.9.16/lib/python3.9/enum.py", line 702, in __new__
    raise ve_exc
ValueError: 'SomeName' is not a valid MyEnum

This now means you can't 'round-trip' with an unstructure and then a structure, or you will get an error, which feels quite unexpected.

It appears to me that this is because _structure_call is registered to handle Enum within the _single_dispatch for structure, which is tried before the function_dispatch that the use_class_methods function is using, so MyEnum._structure is never called.

By comparison, within unstructured, there's nothing for Enums until you get to the function_dispatch, so it does use the method from the class.

Is it worth doing something like when registering the class method functions, checking if there's a single or direct dispatch that will handle the class, and therefore if the method will never be used, and if so to log a warning or raise an error? Equally, the risk is something could be added later to the single or direct dispatch that still causes it to never be called.

主要语言
Python
星标
1.1k
派生
171
平均合并
14 小时 46 分钟
30 天内合并 PR
5

环境准备

  • 没有 Dockerfile 或 Docker Compose 文件
  • 没有 Pull Request 模板
  • 阅读贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

python-attrs/cattrs 的其他 Issue

查看 python-attrs/cattrs 的全部 Issue

相似的 Issue

更多 Python Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。