Skip to content

An error is raised when dealing with dataclasses #30

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

Closed
ejulio opened this issue Jun 22, 2020 · 9 comments · Fixed by #41
Closed

An error is raised when dealing with dataclasses #30

ejulio opened this issue Jun 22, 2020 · 9 comments · Fixed by #41
Labels
enhancement New feature or request

Comments

@ejulio
Copy link

ejulio commented Jun 22, 2020

I think there may be some issue in repr or similar that raises an exception if the dataclass is empty (no values set).
Here is a minimal example..

from dataclasses import dataclass
from itemadapter import ItemAdapter

@dataclass(init=False)
class Product:
    name: str
    price: float

p = Product()
values = ItemAdapter(p).items()  # error
list(values)
# []
print(values)  # raises an error
@elacuesta
Copy link
Member

elacuesta commented Jun 22, 2020

Seems like the issue comes directly from dataclasses. __repr__ will just return fields and values, I guess it probably expects a custom __init__ method if you pass init=False.

Python 3.7.4 (default, Aug  6 2019, 15:53:23) 
[GCC 7.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from dataclasses import dataclass
>>> @dataclass(init=False)
... class Product:
...     name: str
...     price: float
... 
>>> p = Product()
>>> p      
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.7/dataclasses.py", line 357, in wrapper
    result = user_function(self)
  File "<string>", line 2, in __repr__
AttributeError: 'Product' object has no attribute 'name'

I get the impression that dataclasses are not really meant to be completely functional without an __init__ method that sets the defined fields, either automatically created by the module of explicitly provided by the user. In that sense, it seems to me like providing default values is the way to go:

from dataclasses import dataclass, field

@dataclass
class Product:
    name: str = field(default_factory=list)
    price: float = field(default_factory=list)

Do you think we should catch the AttributeError internally?

@ejulio
Copy link
Author

ejulio commented Jun 23, 2020

Agreed @elacuesta
An I think catching the exception makes sense, to some extent

@elacuesta
Copy link
Member

Also related: scrapy/scrapy#4642

@Gallaecio
Copy link
Member

Gallaecio commented Jun 25, 2020

Two cents from @kmike: delay item creation until load_item() is called

@elacuesta
Copy link
Member

@Gallaecio Should that last comment go in itemloaders instead?

@Gallaecio
Copy link
Member

Gallaecio commented Jun 29, 2020

Indeed 🤦

@Gallaecio Gallaecio added the enhancement New feature or request label Aug 13, 2020
@Gallaecio
Copy link
Member

Should we just re-raise as a ValueError in scenarios where this causes an exception to raise?

@ejulio
Copy link
Author

ejulio commented Aug 26, 2020

This would require users to set all fields as optional (so they don't get the error).
I see this as a modelling issue, where I need to set something that is required as optional and it can hide problems.

I guess a proper solution might require us to change the API a bit and not expose the item until it is created (load_item), or something like that.
Then, I think it makes sense to raise ValueError if the item can't be properly created because a required field was not set.

Maybe, the item we expose is a plain dict and has the interpretation of an intermediary item

@Gallaecio
Copy link
Member

I guess a proper solution might require us to change the API a bit and not expose the item until it is created (load_item), or
something like that.

Note that load_item is only relevant for itemloaders. And yes, for itemloaders we should do that, and I plan to work on it.

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

Successfully merging a pull request may close this issue.

3 participants