Skip to content

Commit

Permalink
Meta: refactor generate_init to take dict of options
Browse files Browse the repository at this point in the history
  • Loading branch information
biqqles committed Jun 1, 2021
1 parent 866cd0b commit 734ee76
Showing 1 changed file with 5 additions and 6 deletions.
11 changes: 5 additions & 6 deletions dataclassy/dataclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,7 @@ def __new__(mcs, name, bases, dict_, **kwargs):
del dict_['__slots__']

if options['init'] and all_annotations and '__init__' not in all_attrs:
dict_.setdefault('__init__', generate_init(all_annotations, all_defaults, post_init,
options['kwargs'], options['frozen']))
dict_.setdefault('__init__', generate_init(all_annotations, all_defaults, options, post_init))

if options['repr']:
'__repr__' in all_attrs or dict_.setdefault('__repr__', __repr__)
Expand Down Expand Up @@ -164,14 +163,14 @@ def is_user_func(obj: Any, object_methods=frozenset(vars(object).values())) -> b
return type(obj) is Function and obj not in object_methods and not hasattr(obj, '__dataclass__')


def generate_init(annotations: Dict, defaults: Dict, user_init: bool, gen_kwargs: bool, frozen: bool) -> Function:
def generate_init(annotations: Dict, defaults: Dict, options: Dict, user_init: bool) -> Function:
"""Generate and return an __init__ method for a data class. This method has as parameters all fields of the data
class. When the data class is initialised, arguments to this function are applied to the fields of the new instance.
A user-defined __init__, if present, must be aliased to avoid conflicting."""
arguments = [a for a in annotations if a not in defaults]
default_arguments = [f'{a}={a}' for a in defaults]
args = ['*args'] if user_init else []
kwargs = ['**kwargs'] if user_init or gen_kwargs else []
kwargs = ['**kwargs'] if user_init or options['kwargs'] else []

parameters = ', '.join(arguments + default_arguments + args + kwargs)

Expand All @@ -184,7 +183,7 @@ def generate_init(annotations: Dict, defaults: Dict, user_init: bool, gen_kwargs
else n for n in annotations}

# if the class is frozen, use the necessary but far slower object.__setattr__
assignments = [f'object.__setattr__(self, {n!r}, {r})' if frozen
assignments = [f'object.__setattr__(self, {n!r}, {r})' if options['frozen']
else f'self.{n} = {r}' for n, r in references.items()]

# generate the function
Expand All @@ -195,7 +194,7 @@ def generate_init(annotations: Dict, defaults: Dict, user_init: bool, gen_kwargs
return eval_function('__init__', lines, annotations, defaults, default_names)


def generate_hash(annotations: Dict) -> Function:
def generate_hash(annotations: Dict[str, Type]) -> Function:
"""Generate a __hash__ method for a data class. The hashed value consists of a tuple of the instance's type
followed by any fields marked as "Hashed"."""
hash_of = ', '.join(['self.__class__', *(f'self.{f}' for f, h in annotations.items() if Hashed.is_hinted(h))])
Expand Down

0 comments on commit 734ee76

Please sign in to comment.