Невозможно обработать объект 'dict_keys' - валидатор dict с правилами ключей - PullRequest
0 голосов
/ 18 июня 2020
UPDATEABLE_FIELDS_KEYS = dict.fromkeys(["subject", "target"]).keys()

update_schema = {
    "internal_id": {
        "required": True,
        "type": "string",
        "regex": UUIDV4,
        "empty": False,
        "excludes": "message_code",
    },
    "message_code": {
        "required": True,
        "type": "string",
        "empty": False,
        "excludes": "internal_id",
        "coerce": to_uppercase_fn,
    },
    "fields": {
        "required": True,
        "type": "dict",
        "keysrules": {
            "required": False,
            "type": "string",
            "allowed": UPDATEABLE_FIELDS_KEYS,
        },
    },
}

Если я проверю что-то вроде этого:

data = {
  "message_code": "ABC123",
  "fields": {
    "this_one_not_valid": "some words",
    "subject": "a thing",
    "target": "something else"
  }
}

validator = Validator(update_schema, allow_unknown=False)
validator(data)
validator.errors

, я получаю эту ошибку: TypeError: cannot pickle 'dict_keys' object

Я здесь что-то делаю не так? Он работает приемлемо в «правильных» случаях, но не тогда, когда я указываю недопустимое имя ключа.

Stacktrace, некоторые слова изменены, но приведенный выше код в противном случае является кодом, который я использую.

  File "/Users/c/Development/ub/app/blueprints/p/p.py", line 201, in update_existing
    return jsonify(validator.errors), 422
  File "/Users/c/.pyenv/versions/3.8.1/envs/ub/lib/python3.8/site-packages/cerberus/validator.py", line 464, in errors
    return self.error_handler(self._errors)
  File "/Users/c/.pyenv/versions/3.8.1/envs/ub/lib/python3.8/site-packages/cerberus/errors.py", line 493, in __call__
    self.extend(errors)
  File "/Users/c/.pyenv/versions/3.8.1/envs/ub/lib/python3.8/site-packages/cerberus/errors.py", line 397, in extend
    self.add(error)
  File "/Users/c/.pyenv/versions/3.8.1/envs/ub/lib/python3.8/site-packages/cerberus/errors.py", line 510, in add
    error = deepcopy(error)
  File "/Users/c/.pyenv/versions/3.8.1/lib/python3.8/copy.py", line 172, in deepcopy
    y = _reconstruct(x, memo, *rv)
  File "/Users/c/.pyenv/versions/3.8.1/lib/python3.8/copy.py", line 269, in _reconstruct
    state = deepcopy(state, memo)
  File "/Users/c/.pyenv/versions/3.8.1/lib/python3.8/copy.py", line 146, in deepcopy
    y = copier(x, memo)
  File "/Users/c/.pyenv/versions/3.8.1/lib/python3.8/copy.py", line 229, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
  File "/Users/c/.pyenv/versions/3.8.1/lib/python3.8/copy.py", line 146, in deepcopy
    y = copier(x, memo)
  File "/Users/c/.pyenv/versions/3.8.1/lib/python3.8/copy.py", line 229, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
  File "/Users/c/.pyenv/versions/3.8.1/lib/python3.8/copy.py", line 161, in deepcopy
    rv = reductor(4)
TypeError: cannot pickle 'dict_keys' object

1 Ответ

2 голосов
/ 18 июня 2020

Единственный способ увидеть, что это действительно сломано, - это мое предположение выше о UPDATEABLE_FIELDS_KEYS

, ваш код использует some_dict.keys() для установки того значения, которое возвращает представление ключей (dict_keys введите python)

корректировка кода в вашем вопросе, если я изменю:

-UPDATEABLE_FIELDS_KEYS = ["subject", "target"]
+UPDATEABLE_FIELDS_KEYS = dict.fromkeys(["subject", "target"]).keys()

Затем я могу воспроизвести трассировку стека.

Простое решение - не вызывать .keys() (единственный допустимый случай, который я видел для вызова .keys() в python, - это использовать его как setlike, в любом другом случае, который я видел, лучше выполнить либо (1), либо перебрать словарь напрямую, либо (2 ) используйте in для включения (3) преобразовать в нужный вам тип с помощью итератора)

В этом случае вам, вероятно, понадобится список, кортеж или набор, например:

SOME_DICT = {"subject": 1, "target": 1}

UPDATEABLE_FIELDS_KEYS = frozenset(SOME_DICT)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...