Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test_nested_configs fails on python311 #40

Open
mweinelt opened this issue May 9, 2023 · 2 comments
Open

test_nested_configs fails on python311 #40

mweinelt opened this issue May 9, 2023 · 2 comments

Comments

@mweinelt
Copy link

mweinelt commented May 9, 2023

coqpit> ==================================== ERRORS ====================================
coqpit> ________________ ERROR collecting tests/test_nested_configs.py _________________
coqpit> tests/test_nested_configs.py:24: in <module>
coqpit>     @dataclass
coqpit> /nix/store/7cf5i5czbwbv1j9ikwn25pnzf9hq4dzs-python3-3.11.3/lib/python3.11/dataclasses.py:1223: in dataclass
coqpit>     return wrap(cls)
coqpit> /nix/store/7cf5i5czbwbv1j9ikwn25pnzf9hq4dzs-python3-3.11.3/lib/python3.11/dataclasses.py:1213: in wrap
coqpit>     return _process_class(cls, init, repr, eq, order, unsafe_hash,
coqpit> /nix/store/7cf5i5czbwbv1j9ikwn25pnzf9hq4dzs-python3-3.11.3/lib/python3.11/dataclasses.py:958: in _process_class
coqpit>     cls_fields.append(_get_field(cls, name, type, kw_only))
coqpit> /nix/store/7cf5i5czbwbv1j9ikwn25pnzf9hq4dzs-python3-3.11.3/lib/python3.11/dataclasses.py:815: in _get_field
coqpit>     raise ValueError(f'mutable default {type(f.default)} for field '
coqpit> E   ValueError: mutable default <class 'tests.test_nested_configs.SimpleConfig'> for field sc is not allowed: use default_factory
coqpit> =========================== short test summary info ============================
coqpit> ERROR tests/test_nested_configs.py - ValueError: mutable default <class 'tests.test_nested_configs.SimpleConfig'...

@dataclass
class NestedConfig(Coqpit):
val_d: int = 10
val_e: int = None
val_f: str = "Coqpit is great!"
sc_list: List[SimpleConfig] = None
sc: SimpleConfig = SimpleConfig()
union_var: Union[List[SimpleConfig], SimpleConfig] = field(default_factory=lambda: [SimpleConfig(), SimpleConfig()])

@mweinelt
Copy link
Author

Similar error, once I disabled the one above.

coqpit> ______________________ test_init_argparse_list_and_nested ______________________
coqpit> 
coqpit>     def test_init_argparse_list_and_nested():
coqpit>         @dataclass
coqpit>         class SimplerConfig2(Coqpit):
coqpit>             val_a: int = field(default=None, metadata={"help": "this is val_a"})
coqpit>     
coqpit> >       @dataclass
coqpit> 
coqpit> tests/test_parse_argparse.py:146: 
coqpit> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
coqpit> /nix/store/r7wqbdnn0af1s1p23n18pxf70crqqakg-python3-3.11.3/lib/python3.11/dataclasses.py:1223: in dataclass
coqpit>     return wrap(cls)
coqpit> /nix/store/r7wqbdnn0af1s1p23n18pxf70crqqakg-python3-3.11.3/lib/python3.11/dataclasses.py:1213: in wrap
coqpit>     return _process_class(cls, init, repr, eq, order, unsafe_hash,
coqpit> /nix/store/r7wqbdnn0af1s1p23n18pxf70crqqakg-python3-3.11.3/lib/python3.11/dataclasses.py:958: in _process_class
coqpit>     cls_fields.append(_get_field(cls, name, type, kw_only))
coqpit> _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
coqpit> 
coqpit> cls = <class 'tests.test_parse_argparse.test_init_argparse_list_and_nested.<locals>.SimpleConfig2'>
coqpit> a_name = 'nested_config'
coqpit> a_type = <class 'tests.test_parse_argparse.test_init_argparse_list_and_nested.<locals>.SimplerConfig2'>
coqpit> default_kw_only = False
coqpit> 
coqpit>     def _get_field(cls, a_name, a_type, default_kw_only):
coqpit>         # Return a Field object for this field name and type.  ClassVars and
coqpit>         # InitVars are also returned, but marked as such (see f._field_type).
coqpit>         # default_kw_only is the value of kw_only to use if there isn't a field()
coqpit>         # that defines it.
coqpit>     
coqpit>         # If the default value isn't derived from Field, then it's only a
coqpit>         # normal default value.  Convert it to a Field().
coqpit>         default = getattr(cls, a_name, MISSING)
coqpit>         if isinstance(default, Field):
coqpit>             f = default
coqpit>         else:
coqpit>             if isinstance(default, types.MemberDescriptorType):
coqpit>                 # This is a field in __slots__, so it has no default value.
coqpit>                 default = MISSING
coqpit>             f = field(default=default)
coqpit>     
coqpit>         # Only at this point do we know the name and the type.  Set them.
coqpit>         f.name = a_name
coqpit>         f.type = a_type
coqpit>     
coqpit>         # Assume it's a normal field until proven otherwise.  We're next
coqpit>         # going to decide if it's a ClassVar or InitVar, everything else
coqpit>         # is just a normal field.
coqpit>         f._field_type = _FIELD
coqpit>     
coqpit>         # In addition to checking for actual types here, also check for
coqpit>         # string annotations.  get_type_hints() won't always work for us
coqpit>         # (see https://github.com/python/typing/issues/508 for example),
coqpit>         # plus it's expensive and would require an eval for every string
coqpit>         # annotation.  So, make a best effort to see if this is a ClassVar
coqpit>         # or InitVar using regex's and checking that the thing referenced
coqpit>         # is actually of the correct type.
coqpit>     
coqpit>         # For the complete discussion, see https://bugs.python.org/issue33453
coqpit>     
coqpit>         # If typing has not been imported, then it's impossible for any
coqpit>         # annotation to be a ClassVar.  So, only look for ClassVar if
coqpit>         # typing has been imported by any module (not necessarily cls's
coqpit>         # module).
coqpit>         typing = sys.modules.get('typing')
coqpit>         if typing:
coqpit>             if (_is_classvar(a_type, typing)
coqpit>                 or (isinstance(f.type, str)
coqpit>                     and _is_type(f.type, cls, typing, typing.ClassVar,
coqpit>                                  _is_classvar))):
coqpit>                 f._field_type = _FIELD_CLASSVAR
coqpit>     
coqpit>         # If the type is InitVar, or if it's a matching string annotation,
coqpit>         # then it's an InitVar.
coqpit>         if f._field_type is _FIELD:
coqpit>             # The module we're checking against is the module we're
coqpit>             # currently in (dataclasses.py).
coqpit>             dataclasses = sys.modules[__name__]
coqpit>             if (_is_initvar(a_type, dataclasses)
coqpit>                 or (isinstance(f.type, str)
coqpit>                     and _is_type(f.type, cls, dataclasses, dataclasses.InitVar,
coqpit>                                  _is_initvar))):
coqpit>                 f._field_type = _FIELD_INITVAR
coqpit>     
coqpit>         # Validations for individual fields.  This is delayed until now,
coqpit>         # instead of in the Field() constructor, since only here do we
coqpit>         # know the field name, which allows for better error reporting.
coqpit>     
coqpit>         # Special restrictions for ClassVar and InitVar.
coqpit>         if f._field_type in (_FIELD_CLASSVAR, _FIELD_INITVAR):
coqpit>             if f.default_factory is not MISSING:
coqpit>                 raise TypeError(f'field {f.name} cannot have a '
coqpit>                                 'default factory')
coqpit>             # Should I check for other field settings? default_factory
coqpit>             # seems the most serious to check for.  Maybe add others.  For
coqpit>             # example, how about init=False (or really,
coqpit>             # init=<not-the-default-init-value>)?  It makes no sense for
coqpit>             # ClassVar and InitVar to specify init=<anything>.
coqpit>     
coqpit>         # kw_only validation and assignment.
coqpit>         if f._field_type in (_FIELD, _FIELD_INITVAR):
coqpit>             # For real and InitVar fields, if kw_only wasn't specified use the
coqpit>             # default value.
coqpit>             if f.kw_only is MISSING:
coqpit>                 f.kw_only = default_kw_only
coqpit>         else:
coqpit>             # Make sure kw_only isn't set for ClassVars
coqpit>             assert f._field_type is _FIELD_CLASSVAR
coqpit>             if f.kw_only is not MISSING:
coqpit>                 raise TypeError(f'field {f.name} is a ClassVar but specifies '
coqpit>                                 'kw_only')
coqpit>     
coqpit>         # For real fields, disallow mutable defaults.  Use unhashable as a proxy
coqpit>         # indicator for mutability.  Read the __hash__ attribute from the class,
coqpit>         # not the instance.
coqpit>         if f._field_type is _FIELD and f.default.__class__.__hash__ is None:
coqpit> >           raise ValueError(f'mutable default {type(f.default)} for field '
coqpit>                              f'{f.name} is not allowed: use default_factory')
coqpit> E           ValueError: mutable default <class 'tests.test_parse_argparse.test_init_argparse_list_and_nested.<locals>.SimplerConfig2'> for field nested_config is not allowed: use default_factory
coqpit> 
coqpit> /nix/store/r7wqbdnn0af1s1p23n18pxf70crqqakg-python3-3.11.3/lib/python3.11/dataclasses.py:815: ValueError

@erogol
Copy link
Member

erogol commented Jun 8, 2023

I'll check when we migrate TTS to 3.11

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants