Skip to content

attrs factory late evaluation support #38

@zadca123

Description

@zadca123

Hi,
Im using the lib with the attrs and i get this error

$ python3 test.py --user john
Traceback (most recent call last):
  File "/tmp/test.py", line 31, in <module>
    main()
  File "/tmp/test.py", line 26, in main
    args = parse(Args)
           ^^^^^^^^^^^
  File "/tmp/.venv/lib/python3.11/site-packages/datargs/make.py", line 489, in parse
    return cls(**result)
           ^^^^^^^^^^^^^
  File "<attrs generated methods __main__.Args>", line 31, in __init__
  File "/tmp/test.py", line 20, in is_mail_correct
    raise ValueError(
ValueError: Email 'Factory(factory=<function Args._set_email_with_attrs at 0x7f60e72aafc0>, takes_self=True)' is not valid, expected something from ['default@example.com', 'john@example.com']

datargs disables evaluation of the attributes which are dependent on another ones

my program looks like this

from attrs import define, field
from datargs import parse


@define(auto_attribs=True, kw_only=True)
class Args:
    user: str = field()
    email: str = field()

    @email.default
    def _set_email_with_attrs(self) -> str:
        return self.user + "@example.com"

    @email.validator
    def is_mail_correct(self, attribute, value):
        valid_emails = [f"{u}@example.com" for u in ["default", self.user]]
        if value not in valid_emails:
            raise ValueError(
                f"Email '{value}' is not valid, expected something from {valid_emails}"
            )


def main():
    args = parse(Args)
    print(args)


if __name__ == "__main__":
    main()

and how class works without datargs, it sets attribute based on another one

>>> Args(user="john")
Args(user='john', email='john@example.com')
>>> Args(user="john", email="john@example.com")
Args(user='john', email='john@example.com')
>>> Args(user="john", email="idk@example.com")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<attrs generated methods test.Args>", line 31, in __init__
  File "/tmp/test.py", line 20, in is_mail_correct
    raise ValueError(
ValueError: Email 'idk@example.com' is not valid, expected something from ['default@example.com', 'john@example.com']

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions