在数据类中加载递归dict时ForwardReference名称错误

2024-06-01 12:31:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用marshmallow dataclass加载一个json,它表示一系列规则,其中每个规则由一个LogicalGroup表示,并在其子表达式上应用一个逻辑运算符,因为知道表达式本身可以是LogicalGroup

输入dict遵循以下结构:

import marshmallow_dataclass
from dataclasses import field
from api_handler import BaseSchema
from typing import Sequence, Union, Literal, Type, List, ForwardRef, TypeVar, Generic

filter_input = { "rules" :
  [{
    "groupOperator" : "and",
    "expressions" : [
      { "field": "xxxxx", "operator": "eq", "value": 'level1' },
      { "field": "xxxxx", "operator": "eq", "value": 'm'},
      { "field": "xxxxx", "operator": "eq", "value": "test"},
      {
        "groupOperator" : "or",
        "expressions" : [
          { "field": "xxxx", "operator": "eq", "value": 'level2' },
          { "field": "xxxx", "operator": "eq", "value": 'm' },
          { "field": "xxxx", "operator": "eq", "value": "test" }
        ]
      }
    ]
  }]
}

我为此目的使用的数据类如下:

@marshmallow_dataclass.dataclass(base_schema=BaseSchema)
class Expression:
    field    : str
    operator : str
    value    : str 

@marshmallow_dataclass.dataclass(base_schema=BaseSchema)
class LogicalGroup:
    group_operator   : str
    expressions      : List[Union['LogicalGroup', Expression]] = field(default_factory=list)
  
@marshmallow_dataclass.dataclass(base_schema=BaseSchema)
class Filter:
    rules: List[LogicalGroup] = field(default_factory=list)

问题是,当我尝试使用Filter dataclass加载dict时,我得到以下错误

filt                = Filter.Schema().load(filter_input)
Traceback (most recent call last):
  File "/home/adam/billing/billing/filter/filter.py", line 96, in <module>
    filt                = Filter.Schema().load(filter_input)
  File "/home/adam/thanos-envv/lib/python3.9/site-packages/marshmallow_dataclass/__init__.py", line 628, in load
    all_loaded = super().load(data, many=many, **kwargs)
  File "/home/adam/thanos-envv/lib/python3.9/site-packages/marshmallow/schema.py", line 725, in load
    return self._do_load(
  File "/home/adam/thanos-envv/lib/python3.9/site-packages/marshmallow/schema.py", line 859, in _do_load
    result = self._deserialize(
  File "/home/adam/thanos-envv/lib/python3.9/site-packages/marshmallow/schema.py", line 667, in _deserialize
    value = self._call_and_store(
  File "/home/adam/thanos-envv/lib/python3.9/site-packages/marshmallow/schema.py", line 496, in _call_and_store
    value = getter_func(data)
  File "/home/adam/thanos-envv/lib/python3.9/site-packages/marshmallow/schema.py", line 664, in <lambda>
    getter = lambda val: field_obj.deserialize(
  File "/home/adam/thanos-envv/lib/python3.9/site-packages/marshmallow/fields.py", line 354, in deserialize
    output = self._deserialize(value, attr, data, **kwargs)
  File "/home/adam/thanos-envv/lib/python3.9/site-packages/marshmallow/fields.py", line 726, in _deserialize
    result.append(self.inner.deserialize(each, **kwargs))
  File "/home/adam/thanos-envv/lib/python3.9/site-packages/marshmallow/fields.py", line 354, in deserialize
    output = self._deserialize(value, attr, data, **kwargs)
  File "/home/adam/thanos-envv/lib/python3.9/site-packages/marshmallow/fields.py", line 609, in _deserialize
    return self._load(value, data, partial=partial)
  File "/home/adam/thanos-envv/lib/python3.9/site-packages/marshmallow/fields.py", line 592, in _load
    valid_data = self.schema.load(value, unknown=self.unknown, partial=partial)
  File "/home/adam/thanos-envv/lib/python3.9/site-packages/marshmallow_dataclass/__init__.py", line 628, in load
    all_loaded = super().load(data, many=many, **kwargs)
  File "/home/adam/thanos-envv/lib/python3.9/site-packages/marshmallow/schema.py", line 725, in load
    return self._do_load(
  File "/home/adam/thanos-envv/lib/python3.9/site-packages/marshmallow/schema.py", line 859, in _do_load
    result = self._deserialize(
  File "/home/adam/thanos-envv/lib/python3.9/site-packages/marshmallow/schema.py", line 667, in _deserialize
    value = self._call_and_store(
  File "/home/adam/thanos-envv/lib/python3.9/site-packages/marshmallow/schema.py", line 496, in _call_and_store
    value = getter_func(data)
  File "/home/adam/thanos-envv/lib/python3.9/site-packages/marshmallow/schema.py", line 664, in <lambda>
    getter = lambda val: field_obj.deserialize(
  File "/home/adam/thanos-envv/lib/python3.9/site-packages/marshmallow/fields.py", line 354, in deserialize
    output = self._deserialize(value, attr, data, **kwargs)
  File "/home/adam/thanos-envv/lib/python3.9/site-packages/marshmallow/fields.py", line 726, in _deserialize
    result.append(self.inner.deserialize(each, **kwargs))
  File "/home/adam/thanos-envv/lib/python3.9/site-packages/marshmallow/fields.py", line 354, in deserialize
    output = self._deserialize(value, attr, data, **kwargs)
  File "/home/adam/thanos-envv/lib/python3.9/site-packages/marshmallow_dataclass/union_field.py", line 56, in _deserialize
    typeguard.check_type(attr or "anonymous", result, typ)
  File "/home/adam/thanos-envv/lib/python3.9/site-packages/typeguard/__init__.py", line 655, in check_type
    expected_type = resolve_forwardref(expected_type, memo)
  File "/home/adam/thanos-envv/lib/python3.9/site-packages/typeguard/__init__.py", line 198, in resolve_forwardref
    return evaluate_forwardref(maybe_ref, memo.globals, memo.locals, frozenset())
  File "/usr/lib/python3.9/typing.py", line 533, in _evaluate
    eval(self.__forward_code__, globalns, localns),
  File "<string>", line 1, in <module>
NameError: name 'LogicalGroup' is not defined

我猜问题来自将LogicalGroup声明为类型提示联合内的ForwardRef,因为当我仅使用 Union['LogicalGroup']并将我的dict修改为逻辑组的嵌套dict,而不使用它工作正常的表达式

有人知道bug的来源吗?或者用另一种方式来解决这个问题

提前谢谢


Tags: inpyselfhomevaluelibpackagesline