def _get_field_meta(cls, field: Field, schema_type: SchemaType) -> Tuple[FieldMeta, bool]: required = True field_meta = FieldMeta(schema_type=schema_type) default_value = MISSING if field.default is not MISSING: # In case of default value given default_value = field.default elif field.default_factory is not MISSING and field.default_factory is not None: # type: ignore # In case of a default factory given, we call it default_value = field.default_factory() # type: ignore if default_value is not MISSING: field_meta.default = cls._encode_field(field.type, default_value, omit_none=False) required = False if field.metadata is not None: if "examples" in field.metadata: field_meta.examples = [ cls._encode_field(field.type, example, omit_none=False) for example in field.metadata["examples"] ] if "extensions" in field.metadata: field_meta.extensions = field.metadata["extensions"] if "description" in field.metadata: field_meta.description = field.metadata["description"] if "title" in field.metadata: field_meta.title = field.metadata["title"] if schema_type == SchemaType.OPENAPI_3: field_meta.read_only = field.metadata.get("read_only") if field_meta.read_only and default_value is MISSING: warnings.warn(f"Read-only fields should have a default value") field_meta.write_only = field.metadata.get("write_only") return field_meta, required
def get_dataclass_default(field: Field, omit_default: Optional[bool]) -> Any: if not omit_default: return MISSING # type ignore because of https://github.com/python/mypy/issues/6910 if field.default_factory != MISSING: # type: ignore return field.default_factory() # type: ignore return field.default
def _get_field_meta(cls, field: Field, schema_type: SchemaType) -> Tuple[FieldMeta, bool]: required = True field_meta = FieldMeta() default_value = None if field.default is not MISSING and field.default is not None: # In case of default value given default_value = field.default elif field.default_factory is not MISSING and field.default_factory is not None: # type: ignore # In case of a default factory given, we call it default_value = field.default_factory() # type: ignore if default_value is not None: field_meta.default = cls._encode_field(field.type, default_value, omit_none=False) required = False if field.metadata is not None: if "description" in field.metadata: field_meta.description = field.metadata["description"] if schema_type == SchemaType.OPENAPI_3: field_meta.read_only = field.metadata.get("read_only") if field_meta.read_only and default_value is None: raise ValueError( f"Read-only fields must have a default value") field_meta.write_only = field.metadata.get("write_only") return field_meta, required
def get_default(field: Field, schema: Schema[T]) -> Any: if not schema.omit_default: return MISSING # type ignore because of https://github.com/python/mypy/issues/6910 if field.default_factory != MISSING: # type: ignore return field.default_factory() # type: ignore return field.default
def get_default_value_for_field(field: Field) -> Any: if field.default != MISSING: return field.default elif field.default_factory != MISSING: # type: ignore return field.default_factory() # type: ignore elif is_optional(field.type): return None raise DefaultValueNotFoundError()
def _get_default_value_for_field(field: Field) -> Any: if field.default != MISSING: return field.default elif field.default_factory != MISSING: return field.default_factory() elif _is_optional(field.type): return None else: raise MissingValueError(field)
def _get_dataclass_field_default(field: Field) -> Any: if field.default_factory is not MISSING: # pyre-fixme[29]: `Union[dataclasses._MISSING_TYPE, # dataclasses._DefaultFactory[typing.Any]]` is not a function. return field.default_factory() elif field.default is not MISSING: return field.default else: return None
def _convert_dataclass_field(value, field: dataclasses.Field): if value is not dataclasses.MISSING: return convert(value, field.type) if field.default is not dataclasses.MISSING: return field.default if field.default_factory is not dataclasses.MISSING: return field.default_factory() elif is_optional(field.type): return None else: raise MissingException
def _get_field_default(field: dataclasses.Field): """ Return a marshmallow default value given a dataclass default value >>> _get_field_default(dataclasses.field()) <marshmallow.missing> """ if field.default_factory is not dataclasses.MISSING: return field.default_factory() elif field.default is dataclasses.MISSING: return marshmallow.missing return field.default
def _default_value(x: Field): """Return the default value of the input Field. Args: x (Field): input Field. Returns: object: default value of the input Field. """ if x.default not in (MISSING, _MISSING): return x.default if x.default_factory not in (MISSING, _MISSING): return x.default_factory() return x.default
def _add_type_list(group: argparse._ArgumentGroup, field: dataclasses.Field, name: str): group.add_argument( f"--{name}_{field.name}", type=typing.get_args(field.type)[0], default=None if field.default_factory is dataclasses.MISSING # type: ignore else field.default_factory(), # type: ignore required=field.default_factory is dataclasses.MISSING, # type: ignore choices=field.metadata.get( # type: ignore Options.POSSIBLE_VALUES, Options.POSSIBLE_VALUES.value), help=field.metadata.get(Options.HELP_TEXT, Options.HELP_TEXT.value), # type: ignore nargs="*", )
def _get_value_for_field(field: Field, data: Data, config: Config) -> Any: try: if field.name in config.prefixed: return _extract_nested_dict_for_prefix(config.prefixed[field.name], data) elif field.name in config.flattened: return _extract_flattened_fields(field, data, config.remap) else: key_name = config.remap.get(field.name, field.name) return data[key_name] except KeyError: if _is_optional(field.type): return None elif field.default != MISSING: return field.default elif field.default_factory != MISSING: return field.default_factory() else: raise MissingValueError(field)
def _get_default(catch_all_field: Field) -> Any: # access to the default factory currently causes # a false-positive mypy error (16. Dec 2019): # https://github.com/python/mypy/issues/6910 # noinspection PyProtectedMember has_default = not isinstance(catch_all_field.default, dataclasses._MISSING_TYPE) # noinspection PyProtectedMember has_default_factory = not isinstance(catch_all_field.default_factory, # type: ignore dataclasses._MISSING_TYPE) default_value = _CatchAllUndefinedParameters._SentinelNoDefault if has_default: default_value = catch_all_field.default elif has_default_factory: # This might be unwanted if the default factory constructs # something expensive, # because we have to construct it again just for this test default_value = catch_all_field.default_factory() # type: ignore return default_value
def _get_field_meta(cls, field: Field, schema_type: SchemaType) -> Tuple[FieldMeta, bool]: required = True field_meta = FieldMeta() default_value = None if field.default is not MISSING and field.default is not None: # In case of default value given default_value = field.default elif field.default_factory is not MISSING and field.default_factory is not None: # type: ignore # In case of a default factory given, we call it default_value = field.default_factory() # type: ignore if default_value is not None: field_meta.default = cls._encode_field(field.type, default_value, omit_none=False) required = False if field.metadata is not None: if "description" in field.metadata: field_meta.description = field.metadata["description"] return field_meta, required
def get_default(field: Field) -> Any: if field.default_factory is not MISSING: value = field.default_factory() else: value = field.default return value if value is not MISSING else None
def colander_params( prop: dataclasses.Field, oid_prefix: str, schema: type, request: typing.Any, mode=None, **kwargs, ) -> dict: """ Get parameters for ``colander.SchemaNode`` constructor from ``dataclass.Field`` :param prop: ``dataclass.Field`` object :param oid_prefix: string prefix for use as field oid :param schema: ``dataclass`` based class :param request: ``request`` object. Accepts anything, as it is merely passed to validators :param mode: one of the following: ``'default'``, ``'edit'``, ``'edit-process'`` :param kwargs: additional parameters to be included into output. Will override derived parameters. :return: dictionary of parameters for ``colander.SchemaNode`` """ t = dataclass_get_type(prop) default_value = None if t["type"] == dict: default_value = {} elif t["type"] == list: default_value = [] elif t["type"] == set: default_value = set() if (not isinstance(prop.default, dataclasses._MISSING_TYPE) and prop.default is not None): default_value = prop.default elif (not isinstance(prop.default_factory, dataclasses._MISSING_TYPE) and prop.default_factory is not None): default_value = prop.default_factory() params = { "name": prop.name, "oid": "%s-%s" % (oid_prefix, prop.name), "missing": colander.required if t["required"] else default_value, "default": default_value, } if "deform.widget" in prop.metadata.keys(): params["widget"] = copy.copy(prop.metadata["deform.widget"]) elif "deform.widget_factory" in prop.metadata.keys(): params["widget"] = prop.metadata["deform.widget_factory"](request) validators = prop.metadata.get("validators", None) if validators: params["validator"] = ValidatorsWrapper(validators, schema=schema, request=request, mode=mode) preparers = prop.metadata.get("preparers", None) if preparers: params["preparer"] = PreparersWrapper(preparers, schema=schema, request=request, mode=mode) title = prop.metadata.get("title", None) if title: params["title"] = title description = prop.metadata.get("description", None) if description: params["description"] = description params.update(kwargs) return params
def default_field_value(f: Field) -> Any: if callable(f.default_factory): # type: ignore return f.default_factory() # type: ignore else: return f.default
def get_dataclass_default(field: Field) -> Any: # type ignore because of https://github.com/python/mypy/issues/6910 if field.default_factory != MISSING: # type: ignore return field.default_factory() # type: ignore return field.default
def _parse_dataclass_field(parser: ArgumentParser, field: dataclasses.Field): field_name = f"--{field.name}" kwargs = field.metadata.copy() # field.metadata is not used at all by Data Classes, # it is provided as a third-party extension mechanism. if isinstance(field.type, str): raise RuntimeError( "Unresolved type detected, which should have been done with the help of " "`typing.get_type_hints` method by default") origin_type = getattr(field.type, "__origin__", field.type) if origin_type is Union: if len(field.type.__args__) != 2 or type( None) not in field.type.__args__: raise ValueError( "Only `Union[X, NoneType]` (i.e., `Optional[X]`) is allowed for `Union`" ) if bool not in field.type.__args__: # filter `NoneType` in Union (except for `Union[bool, NoneType]`) field.type = (field.type.__args__[0] if isinstance( None, field.type.__args__[1]) else field.type.__args__[1]) origin_type = getattr(field.type, "__origin__", field.type) # A variable to store kwargs for a boolean field, if needed # so that we can init a `no_*` complement argument (see below) bool_kwargs = {} if isinstance(field.type, type) and issubclass(field.type, Enum): kwargs["choices"] = [x.value for x in field.type] kwargs["type"] = type(kwargs["choices"][0]) if field.default is not dataclasses.MISSING: kwargs["default"] = field.default else: kwargs["required"] = True elif field.type is bool or field.type is Optional[bool]: # Copy the currect kwargs to use to instantiate a `no_*` complement argument below. # We do not initialize it here because the `no_*` alternative must be instantiated after the real argument bool_kwargs = copy(kwargs) # Hack because type=bool in argparse does not behave as we want. kwargs["type"] = string_to_bool if field.type is bool or (field.default is not None and field.default is not dataclasses.MISSING): # Default value is False if we have no default when of type bool. default = False if field.default is dataclasses.MISSING else field.default # This is the value that will get picked if we don't include --field_name in any way kwargs["default"] = default # This tells argparse we accept 0 or 1 value after --field_name kwargs["nargs"] = "?" # This is the value that will get picked if we do --field_name (without value) kwargs["const"] = True elif isclass(origin_type) and issubclass(origin_type, list): kwargs["type"] = field.type.__args__[0] kwargs["nargs"] = "+" if field.default_factory is not dataclasses.MISSING: kwargs["default"] = field.default_factory() elif field.default is dataclasses.MISSING: kwargs["required"] = True else: kwargs["type"] = field.type if field.default is not dataclasses.MISSING: kwargs["default"] = field.default elif field.default_factory is not dataclasses.MISSING: kwargs["default"] = field.default_factory() else: kwargs["required"] = True parser.add_argument(field_name, **kwargs) # Add a complement `no_*` argument for a boolean field AFTER the initial field has already been added. # Order is important for arguments with the same destination! # We use a copy of earlier kwargs because the original kwargs have changed a lot before reaching down # here and we do not need those changes/additional keys. if field.default is True and (field.type is bool or field.type is Optional[bool]): bool_kwargs["default"] = False parser.add_argument(f"--no_{field.name}", action="store_false", dest=field.name, **bool_kwargs)
def has_default(self, field: dataclasses.Field) -> FieldDefault: if field.default != dataclasses.MISSING: return FieldDefault(True, field.default) if field.default_factory != dataclasses.MISSING: return FieldDefault(True, field.default_factory()) return FieldDefault()