Ejemplo n.º 1
0
 def __deepcopy__(self, memo):
     cls = type(self)
     obj = object.__new__(cls)
     obj.model = self.model
     for field in get_class_fields(cls):
         setattr(obj, field.name, getattr(self, field.name))
     return obj
Ejemplo n.º 2
0
    def __new__(mcs, name, bases, namespace, **kwargs):
        if kwargs.get('__base_definition__', False):
            kwargs.pop('__base_definition__')
            mcs.__root__ = super().__new__(mcs, name, bases, namespace,
                                           **kwargs)
            return mcs.__root__
        __type__ = namespace.pop('__type__', None)
        if __type__ is None or not isinstance(__type__, type):
            raise ValueError(f'__type__ field is be set to type for {name}')

        fields = get_class_fields(__type__)
        include = set(namespace.pop('__include__',
                                    set(f.name for f in fields)))
        exclude = set(namespace.pop('__exclude__', set()))
        force_required = set(namespace.pop('__force_required__', set()))
        autogen_nested = namespace.pop('__autogen_nested__', False)
        allow_polymorphism = namespace.pop('__allow_polymorphism__', False)
        subtype_models: Dict[str, Type[BaseModel]] = namespace.pop(
            '__subtype_models__', {})

        annotations = namespace.get('__annotations__', {})
        for field in fields:
            name = field.name
            if name in exclude or name not in include:
                continue
            if field.has_default and name not in namespace:
                namespace[name] = field.default
            if name not in annotations:
                field_type = field.type
                if autogen_nested:
                    field_type = _substitute_nested_type(
                        field_type, allow_polymorphism)
                annotations[name] = field_type
            if name in force_required:
                del namespace[name]
                annotations[name] = _make_not_optional(annotations[name])

        if allow_polymorphism and is_hierarchy_root(__type__):
            field_type_field = getattr(__type__, TYPE_FIELD_NAME_FIELD_NAME)
            annotations[field_type_field] = str

            def validate(cls: Type[BaseModel], value):
                if isinstance(value, dict) and field_type_field in value:
                    _subtype_name = value.pop(field_type_field)
                    _subtype = __type__._subtypes[_subtype_name]
                    if _subtype_name not in subtype_models:
                        subtype_models[_subtype_name] = _new_model(
                            _subtype,
                            nested=autogen_nested,
                            polymorphism=allow_polymorphism)
                    child_model = subtype_models[_subtype_name]
                    return child_model.validate(value)
                return super(cls).validate(value)

            namespace['validate'] = classmethod(validate)
        namespace['__annotations__'] = annotations
        new = super().__new__(mcs, name, bases, namespace, **kwargs)
        new.__type__ = __type__
        return new
Ejemplo n.º 3
0
 def update(self, other: 'DockerBuildArgs'):
     for field in get_class_fields(DockerBuildArgs):
         if field.name == 'templates_dir':
             self._templates_dir += other._templates_dir
         else:
             value = getattr(other, f'_{field.name}')
             if value is not None:
                 setattr(self, f'_{field.name}', value)
Ejemplo n.º 4
0
 def __deepcopy__(self, memo):
     cls = type(self)
     obj = object.__new__(cls)
     obj.io = self.io
     obj.model = self.model
     obj.methods = self.methods
     obj.requirements = self.requirements
     for field in get_class_fields(cls):
         setattr(obj, field.name, getattr(self, field.name))
     return obj
Ejemplo n.º 5
0
def assert_objects_equal_except_fields(o1,
                                       o2,
                                       *,
                                       excepted_fields: List[str] = None):
    excepted_fields = excepted_fields or []
    excepted_fields = set(excepted_fields)

    assert type(o1) == type(o2)
    fields1 = [f.name for f in get_class_fields(type(o1))]
    fields2 = [f.name for f in get_class_fields(type(o2))]
    assert fields1 == fields2

    for field1, field2 in zip(fields1, fields2):
        assert field1 == field2
        v1 = getattr(o1, field1)
        v2 = getattr(o2, field2)
        if field1 in excepted_fields:
            assert v1 != v2
        else:
            assert v1 == v2
Ejemplo n.º 6
0
def test_get_class_fields():
    class AClass:
        def __init__(self, field1: str, field2: int = 0):
            pass

    fields = get_class_fields(AClass)

    assert fields == [
        Field('field1', str, False),
        Field('field2', int, True, 0)
    ]
Ejemplo n.º 7
0
def test_field_repr():
    class AClass:
        def __init__(self,
                     field1: str,
                     field2: Union[str, int],
                     field3: List[str] = []):
            pass

    f1, f2, f3 = get_class_fields(AClass)

    assert str(f1) == 'field1: str'
    assert str(f2) == 'field2: Union[str, int]'
    assert str(f3) == 'field3: List[str] = []'
Ejemplo n.º 8
0
def _serialize_to_list(cls, obj):
    result = []
    fields = get_class_fields(cls)
    for f in fields:
        name = f.name
        field = getattr(obj, name)
        if field is not None:
            result.append(serialize(field))

    if type_field_position_is(cls, Position.INSIDE):
        type_field_name = get_type_field_name(cls)
        result = [getattr(cls, type_field_name)] + result
    return result
Ejemplo n.º 9
0
def type_to_schema(field_type, has_default=False, default=None):
    """
    Facade method converting arbitrary type to OpenAPI schema definitions.
    Has special support for builtins, collections and instances of :class:`.TypeWithSpec` subclasses.

    :param field_type: type to generate schema for
    :param has_default: specifies whether given type has default value
    :param default: specifies default value for given type
    :return: dict with OpenAPI schema definition
    """
    if field_type in BUILTIN_TYPES:
        result = {'type': BUILTIN_TYPES[field_type]}
        if has_default:
            result['default'] = default
        return result

    elif is_generic(field_type):
        if is_collection(field_type):
            return make_array(get_collection_internal_type(field_type),
                              has_default=has_default,
                              default=default)
        elif is_mapping(field_type):
            kt, vt = get_mapping_types(field_type)
            if kt != str:
                raise ValueError('Only string keys supported')
            return make_object(arbitrary_properties_type=vt,
                               has_default=has_default,
                               default=default)

    elif issubclass(field_type, TypeWithSpec):
        if issubclass(field_type, PrimitiveDatasetType):
            return type_to_schema(field_type.to_type, has_default, default)

        # noinspection PyArgumentList
        spec = field_type.get_spec()
        # noinspection PyArgumentList
        is_list = field_type.is_list()
        # noinspection PyArgumentList
        list_size = field_type.list_size()
        if is_list:
            item_types = set(a.type for a in spec)
            if len(item_types) > 1:
                raise ValueError(
                    'All items must be of same type for {}'.format(field_type))
            item_type = next(iter(item_types))
            return make_array(item_type, list_size, list_size)
        else:
            return make_object(spec)
        # return schema_from_typespec(field)
    else:
        return make_object(get_class_fields(field_type))
Ejemplo n.º 10
0
def create_configurable(cls: Type[Configurable], kind):
    kind = cls.KNOWN.get(kind, kind)
    args = {"type": kind}
    clazz = resolve_subtype(cls, args)
    for field in get_class_fields(clazz):
        try:
            cast = field.type.__args__[0] if is_union(
                field.type) else field.type
            args[field.name] = cast(
                click.prompt(f"{field.name} value?", default=field.default))
        except ValueError:
            raise NotImplementedError(
                f"Not yet implemented for type {field.type}")
    return deserialize(args, cls)
Ejemplo n.º 11
0
def update_object_fields(o, *, excepted_fields: List[str] = None):
    excepted_fields = excepted_fields or []
    excepted_fields = set(excepted_fields)

    for field in [f.name for f in get_class_fields(type(o))]:
        additional_value = 2

        if field not in excepted_fields:
            v = getattr(o, field)

            if isinstance(v, str):
                additional_value = str(additional_value)
            if isinstance(v, datetime.datetime):
                additional_value = datetime.timedelta(additional_value)
            setattr(o, field, v + additional_value)
    return o
Ejemplo n.º 12
0
def _construct_from_list(obj, as_class):
    args = []
    if type_field_position_is(as_class, Position.INSIDE):
        obj = obj[1:]
    for i, f in enumerate(get_class_fields(as_class)):
        field_type = _get_field_type(f, obj)

        if i >= len(obj):
            if f.has_default:
                continue
            else:
                raise ValueError(
                    "Too few arguments for type  {} ".format(as_class))
        else:
            args.append(deserialize(obj[i], field_type))
    return as_class(*args)
Ejemplo n.º 13
0
def _construct_from_dict(obj, as_class):
    kwargs = {}
    for f in get_class_fields(as_class):
        name = f.name
        field_type = _get_field_type(f, obj)

        if hasattr(as_class, FIELD_MAPPING_NAME_FIELD):
            name = getattr(as_class, FIELD_MAPPING_NAME_FIELD).get(name, name)

        if name not in obj:
            if f.has_default:
                continue
            else:
                raise ValueError("Type {} has required argument {}".format(
                    as_class, name))
        else:
            kwargs[f.name] = deserialize(obj[name], field_type)
    return as_class(**kwargs)
Ejemplo n.º 14
0
def _serialize_to_dict(cls, obj):
    result = {}
    fields = get_class_fields(cls)
    for f in fields:
        name = f.name
        field = getattr(obj, name)
        if field is not None:
            if hasattr(cls, FIELD_MAPPING_NAME_FIELD):
                name = getattr(cls, FIELD_MAPPING_NAME_FIELD).get(name, name)
            result[name] = serialize(field, f.type)

    if type_field_position_is(cls, Position.INSIDE):
        type_field_name = get_type_field_name(cls)
        if type_field_name in result:
            raise SerializationError(
                'Type field name {} conflicts with field name in {}'.format(
                    type_field_name, cls))
        result[type_field_name] = getattr(cls, type_field_name)
    return result