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(), )
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(), )
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(), )
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={}, )