【问题标题】:Passing additional arguments to _normalise_coerse methods in cerberus将附加参数传递给 cerberus 中的 _normalise_coerse 方法
【发布时间】:2022-08-02 21:06:07
【问题描述】:

我有一些代码见 EOM;它绝不是最终的,但它是(到目前为止)我见过/设想的以某种高性能方式验证多种日期格式的最佳方式。

我想知道是否有办法将附加参数传递给这种函数(_normalise_coerce),如果可以在模式中定义日期格式字符串会很好。就像是

{
   \"a_date\":{
      \"type\": \"datetime\",
      \"coerce\": \"to_datetime\",
      \"coerce_args\": \"%m/%d/%Y %H:%M\"
   }
}

VS 在函数中更改代码以支持额外的日期格式。我浏览了文档,没有发现任何引人注目的东西。相当好的机会,我认为这一切都错了,但认为询问专家是最好的方法。我认为在模式中定义是解决问题的最干净的解决方案,但我对事实、想法和意见全神贯注。

一些上下文:

  • 性能至关重要,因为这可能会针对 AWS lambda 中的数百万行运行(而 Cerbie(我对 cerberus 的昵称)并不完全是一只春鸡 :P)。
  • 所有模式都不会是原生 python 字典,因为它们都在 JSON/YAML 中定义,因此它们都需要对字符串友好。
  • 不使用内置强制,因为无法从字符串中解析 python 类型
  • 我不需要 datetime 对象,因此可以使用正则表达式,只是不那么明确且不那么面向未来。
  • 如果这一切都错了,我很无能,请温柔(づ。◕‿‿◕。)づ
def _normalize_coerce_to_datetime(self, value: Union(str, datetime, None)) -> Union(datetime, str, None):
        \'\'\'
        Casts valid datetime strings to the datetime python type.

        :param value: (str, datetime, None): python datetime, datetime string
        :return: datetime, string, None. python datetime, 
            invalid datetime string or None if the value is empty or None
        \'\'\'
        datetime_formats = [\'%m/%d/%Y %H:%M\']

        if isinstance(value, datetime):
            return value

        if value and not value.isspace():
            for format in datetime_formats:
                try:
                    return datetime.strptime(value, format)
                except ValueError:
                    date_time = value
            return date_time
        else:
            return None

    标签: cerberus


    【解决方案1】:

    我自己尝试过这样做,但没有找到将其他参数传递给自定义 normalize_coerce 规则的方法。如果您想扩展 Cerberus 库以包含自定义验证器,那么您可以包含参数,然后通过自定义验证器中的约束访问这些参数。下面是我用于条件强制转换的示例,但由于我需要指定条件以及要检查的值和要返回的值,所以我找不到使用 normalize_coerce 执行此操作的方法和因此在验证规则中应用并编辑了self.document,如代码所示。

    Schema:
            {
           "columns":{
              "Customer ID":{
                 "type":"number",
                 "conditional_to_default":{
                    "condition":"greater_than",
                    "value_to_check_against":100,
                    "value_to_return":22
                 }
              }
           }
        }
    
    
    
    
    def _validate_conditional_to_default(self, constraint, field, value):
        """
        Test the values and transform if conditions are met.
        :param constraint: Dictionary with the args needed for the conditional check.
        :param field: Field name.
        :param value: Field value.
        :return: the new document value if applicable, or keep the existing document value if not
        """
    
        value_to_check_against = constraint["value_to_check_against"]
        value_to_return = constraint["value_to_return"]
        rule_name = 'conditional_to_default'
    
        condition_mapping_dict = {"greater_than": operator.gt, "less_than": operator.lt, "equal_to": operator.eq,
                                  "less_than_or_equal_to": operator.le,
                                  "greater_than_or_equal_to": operator.ge}
    
        if constraint["condition"] in condition_mapping_dict:
            if condition_mapping_dict[constraint["condition"]](value, value_to_check_against):
                self.document[field] = value_to_return
                return self.document
            else:
                return self.document
        if constraint["condition"] not in condition_mapping_dict:
            custom_errors_list = []
            custom_error = cerberus.errors.ValidationError(document_path=(field, ), schema_path=(field, rule_name),
                                                           code=0x03, rule=rule_name, constraint="Condition must be "
                                                                                                 "one of: "
                                                                                                 "{condition_vals}"
                                                           .format(condition_vals=list(condition_mapping_dict.keys())),
                                                           value=value, info=())
            custom_errors_list.append(custom_error)
            self._error(custom_errors_list)
            return self.document
    

    这可能是错误的方法,所以我希望下面的内容能让你走得更远,同样我也在关注这个,看看是否有其他人找到了将参数传递给 _normlize_coerce 函数的方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-21
      • 2013-01-09
      • 1970-01-01
      • 2018-07-26
      • 1970-01-01
      • 1970-01-01
      • 2015-07-19
      • 2019-09-22
      相关资源
      最近更新 更多