Esempio n. 1
0
    def _BUILD_init(cls) -> Callable[[], None]:
        kwonlyargs = ['*', '__strict__=True', '__faust=None', '**kwargs']
        fields = cls._options.fieldpos
        optional = cls._options.optionalset
        models = cls._options.models
        converse = cls._options.converse
        initfield = cls._options.initfield = {}
        has_post_init = hasattr(cls, '__post_init__')
        required = []
        opts = []
        setters = []
        for field in fields.values():
            model = models.get(field)
            conv = converse.get(field)
            fieldval = f'{field}'
            if model is not None:
                initfield[field] = _field_callback(model, _to_model)
                assert initfield[field] is not None
                fieldval = f'self._init_field("{field}", {field})'
            if conv is not None:
                initfield[field] = _field_callback(*conv)
                assert initfield[field] is not None
                fieldval = f'self._init_field("{field}", {field})'
            if field in optional:
                opts.append(f'{field}=None')
                setters.extend([
                    f'if {field} is not None:',
                    f'  self.{field} = {fieldval}',
                    f'else:',
                    f'  self.{field} = self._options.defaults["{field}"]',
                ])
            else:
                required.append(field)
                setters.append(f'self.{field} = {fieldval}')

        rest = [
            'if kwargs and __strict__:',
            '    from mode.utils.text import pluralize',
            '    message = "{} got unexpected {}: {}".format(',
            '        self.__class__.__name__,',
            '        pluralize(kwargs.__len__(), "argument"),',
            '        ", ".join(map(str, sorted(kwargs))))',
            '    raise TypeError(message)',
            'self.__dict__.update(kwargs)',
        ]

        if has_post_init:
            rest.extend([
                'self.__post_init__()',
            ])

        return codegen.InitMethod(
            required + opts + kwonlyargs,
            setters + rest,
            globals=globals(),
            locals=locals(),
        )
Esempio n. 2
0
    def _BUILD_init(cls) -> Callable[[], None]:
        kwonlyargs = ['*', '__strict__=True', '__faust=None', '**kwargs']
        options = cls._options
        fields = options.fields
        field_positions = options.fieldpos
        optional = options.optionalset
        needs_validation = options.validation
        descriptors = options.descriptors
        has_post_init = hasattr(cls, '__post_init__')
        required = []
        opts = []
        setters = []
        for field in field_positions.values():
            fieldval = (f'{field} if __strict__ '
                        f'else self._init_field("{field}", {field})')
            if field in optional:
                opts.append(f'{field}=None')
                setters.extend([
                    f'if {field} is not None:',
                    f'  self.{field} = {fieldval}',
                    f'else:',
                    f'  self.{field} = self._options.defaults["{field}"]',
                ])
            else:
                required.append(field)
                setters.append(f'self.{field} = {fieldval}')

        rest = [
            'if kwargs and __strict__:',
            '    from mode.utils.text import pluralize',
            '    message = "{} got unexpected {}: {}".format(',
            '        self.__class__.__name__,',
            '        pluralize(kwargs.__len__(), "argument"),',
            '        ", ".join(map(str, sorted(kwargs))))',
            '    raise TypeError(message)',
            'self.__dict__.update(kwargs)',
        ]

        if has_post_init:
            rest.extend([
                'self.__post_init__()',
            ])

        if needs_validation:
            rest.extend([
                'self.validate_or_raise()',
            ])

        return codegen.InitMethod(
            required + opts + kwonlyargs,
            setters + rest,
            globals=globals(),
            locals=locals(),
        )
Esempio n. 3
0
    def _BUILD_init(cls) -> Callable[[], None]:
        kwonlyargs = ['*', '__strict__=True', '__faust=None', '**kwargs']
        options = cls._options
        fields = options.fields
        field_positions = options.fieldpos
        optional = options.optionalset
        needs_validation = options.validation
        models = options.models
        field_coerce = options.field_coerce
        initfield = options.initfield = {}
        descriptors = options.descriptors
        has_post_init = hasattr(cls, '__post_init__')
        required = []
        opts = []
        setters = []
        for field in field_positions.values():
            model = models.get(field)
            coerce = field_coerce.get(field)
            fieldval = f'{field}'
            if model is not None:
                initfield[field] = _field_callback(model, _to_model)
                assert initfield[field] is not None
                fieldval = f'self._init_field("{field}", {field})'
            else:
                field_type = fields[field]
                descr = options.descriptors[field]
                initfield[field] = _field_callback(field_type,
                                                   _using_descriptor,
                                                   descr=descr)
                fieldval = f'self._init_field("{field}", {field})'
            if coerce is not None:
                coerce_type, coerce_handler = coerce
                # Model reconstruction require two-arguments: typ, val.
                # Regular coercion callbacks just takes one argument, so
                # need to create an intermediate function to fix that.
                initfield[field] = _field_callback(
                    coerce_type, partial(cls._init_maybe_coerce,
                                         coerce_handler))
                assert initfield[field] is not None
                fieldval = f'self._init_field("{field}", {field})'
            if field in optional:
                opts.append(f'{field}=None')
                setters.extend([
                    f'if {field} is not None:',
                    f'  self.{field} = {fieldval}',
                    f'else:',
                    f'  self.{field} = self._options.defaults["{field}"]',
                ])
            else:
                required.append(field)
                setters.append(f'self.{field} = {fieldval}')

        rest = [
            'if kwargs and __strict__:',
            '    from mode.utils.text import pluralize',
            '    message = "{} got unexpected {}: {}".format(',
            '        self.__class__.__name__,',
            '        pluralize(kwargs.__len__(), "argument"),',
            '        ", ".join(map(str, sorted(kwargs))))',
            '    raise TypeError(message)',
            'self.__dict__.update(kwargs)',
        ]

        if has_post_init:
            rest.extend([
                'self.__post_init__()',
            ])

        if needs_validation:
            rest.extend([
                'self.validate_or_raise()',
            ])

        return codegen.InitMethod(
            required + opts + kwonlyargs,
            setters + rest,
            globals=globals(),
            locals=locals(),
        )
Esempio n. 4
0
    def _BUILD_init(cls) -> Callable[[], None]:
        kwonlyargs = ['*', '__strict__=True', '__faust=None', '**kwargs']
        options = cls._options
        field_positions = options.fieldpos
        optional = options.optionalset
        needs_validation = options.validation
        descriptors = options.descriptors
        has_post_init = hasattr(cls, '__post_init__')
        required = []
        opts = []
        preamble = [
            'self.__evaluated_fields__ = set()',
            '__defaults = self._options.defaults',
        ]
        _globals = {}
        _closures = {}

        def generate_setter(field: str, getval: str, out: List[str]) -> bool:
            """Generate code that sets attribute for field in class.

            Arguments:
                field: Name of field.
                getval: Source code that initializes value for field,
                    can be the field name itself for no inititalization
                    or for example: ``f"self._prepare_value({field})"``.
                out: Destination list where new source code lines are added.
                """
            if field in optional:
                out.extend([
                    f'    if {field} is not None:',
                    f'        self.{field} = {getval}',
                    f'    else:',
                    f'        self.{field} = __defaults["{field}"]',
                ])
                return True
            else:
                out.append(f'    self.{field} = {getval}')
                return False

        def generate_prepare_value(field: str) -> str:
            descriptor = descriptors[field]
            if descriptor.lazy_coercion:
                return field  # no initialization
            else:
                # Call descriptor.to_python
                local_field_init_name = f'_{field}_init_'
                global_field_init_name = f'__{field}_init'
                _globals[global_field_init_name] = descriptor.to_python
                _closures[local_field_init_name] = global_field_init_name
                return f'{local_field_init_name}({field})'

        data_setters = ['if __strict__:']
        for field in field_positions.values():
            is_optional = generate_setter(field, field, data_setters)
            if is_optional:
                opts.append(f'{field}=None')
            else:
                required.append(field)

        data_rest = [
            '    if kwargs:',
            '        from mode.utils.text import pluralize',
            '        message = "{} got unexpected {}: {}".format(',
            '            self.__class__.__name__,',
            '            pluralize(kwargs.__len__(), "argument"),',
            '            ", ".join(map(str, sorted(kwargs))))',
            '        raise TypeError(message)',
        ]

        if field_positions:
            init_setters = ['else:']
            for field in field_positions.values():
                fieldval = generate_prepare_value(field)
                generate_setter(field, fieldval, init_setters)
        else:
            # if there are no fields we cannot generate
            # the lines aboe as there will no be no code
            # in the else block.
            init_setters = []

        init_rest = ['self.__dict__.update(kwargs)']
        if has_post_init:
            init_rest.extend([
                'self.__post_init__()',
            ])

        if needs_validation:
            init_rest.extend([
                'self.validate_or_raise()',
            ])

        if _closures:
            source = codegen.build_closure_source(
                name='__init__',
                args=['self'] + required + opts + kwonlyargs,
                closures=_closures,
                body=(preamble + data_setters + data_rest + init_setters +
                      init_rest),
            )
            return codegen.build_closure(
                '__outer__',
                source,
                globals=_globals,
                locals={},
            )
        else:
            return codegen.InitMethod(
                required + opts + kwonlyargs,
                preamble + data_setters + data_rest + init_setters + init_rest,
                globals=_globals,
                locals={},
            )