-
-
Notifications
You must be signed in to change notification settings - Fork 374
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
Possible lazy=True Feature? #573
Comments
It's absolutely unclear how to map a straightforward simple thing like plain cached attributes into something matching declared attributes mixed with computation |
I think if anything this falls under the greater topic of treating properties as first-class citizens. |
OK thanks. So it's basically file it under the heading of "might be nice but not doable", right? Anyone know any alternatives to what I'm doing with If the |
Something might be doable when we start working on first class property support (that I'd like to have myself, but there's more pressing work in |
OK, thank you very much for the response and consideration. |
@pwwang Thanks! Not sure how I missed that when you posted it! Apologies for the delay. Any thoughts on if this is "production ready"? @hynek & @RonnyPfannschmidt Would any what pwwang work for some of the desired/planned property stuff? I didn't know if there was a way to incorporate that as a starting point. I'm only digging into attrs internals recently, but I'm willing to help if I can. Thanks |
Currently the main focus of mine (if you can talk about focus in these times…) is to finish up the work around |
Hello! :) I have a little bit different issues, though they also can be solved with UPD: I was wrong, I've found out that I can redefine all attributes of interest in my child class and then allow any defaults logic I'd like. Though, I still find the half-initialized self pretty confusing and think that having a lazy factory based on I've found myself writing class hierarchies like this:
This trick with extra-class is required, as I can't use This whole machinery allows me to get away from half-initialized self issues to manual attribute dependency management, but looks gross, so I was thinking that maybe it deserves a shortcut. The API update proposal is following:
Then, child class from my example can be rewritten in following ways
|
I've though about the design from the previous post and it seems that these "lazy" factories are pretty messy in composition with converters.
Considering issues with converters, I assume that the right way of thinking about In such approach, my example can be rewritten as:
There was another request for not setting a value and leaving it to descriptor - #354 . Maybe if an attribute descriptor is set, we can leave the value empty if got I've checked attr-property project but it looks very clumsy and doesn't seem to allow usage of existing descriptor. |
Oof November! Sorry for taking me so long – it's one of those classic "this needs a proper response when I have the time". 😂😭 Firstly, I'm glad the lazy Factory approach is off the table because it honestly felt off in my gut, without being able to put the finger on it. I have to admit that I've never used descriptors in anger, so I have a hard time to comment on this competently. It does seem fair tho to consider it a more low-level construct with the implications you noted. We could add it as an experimental feature with the caveat that it might change (like attr.define basically) with the possibility of adding more high-level capabilities down the road, if necessary. How complicated do you thing is it gonna be to integrate? However I'm afraid to ask you for an MVP because I already do have two PRs that cut deep into attrs' bowels and I'm afraid to send you on a constant-rebasing mission. 🤔 IOW: I want to land #731 and #627 before starting new big surgeries inside of |
Hi, @hynek , thanks for the comment! :) It seems a pretty simple feature to integrate - I believe I can make some MVP (with a shortcut that puts descriptor into metadata and using field_transformer to set it on the class itself) in an evening. It wouldn't solve non-init case, though, and also would break mypy plugin/PyCharm inspections. TBH being able to set a classvar with the same name as |
Argl, I thought I'm answering to #746 and wondered why your wording changed. |
Initializing the SecretsManager as an attr factory caused the client to be initialized too early to mock it out with moto for unit testing, as was called out in hynek#24. Until python-attrs/attrs#573 is fixed, we need to manually lazy-init the client for SecretsManager
Initializing the SecretsManager as an attr factory caused the client to be initialized too early to mock it out with moto for unit testing, as was called out in hynek#24. Until python-attrs/attrs#573 is fixed, we need to manually lazy-init the client for SecretsManager
* testing: allow lazy init of boto client Initializing the SecretsManager as an attr factory caused the client to be initialized too early to mock it out with moto for unit testing, as was called out in #24. Until python-attrs/attrs#573 is fixed, we need to manually lazy-init the client for SecretsManager * 21.3.0 drops Python 2.7 support. I mean, you _can_ import awssm, but the tests don't work on 2.7 any more. Co-authored-by: Chris Rose <[email protected]>
Hi, maybe something like this can be useful: https://gist.github.com/waszil/171d64e5b94cdd51c404d41332f476c0 |
@pymarv, I think you can achieve the desired behaviour by combining a private attribute with the import attr
from functools import cached_property # Python>=3.8
@attr.s
class MyClass:
a = attr.ib(
validator=attr.validators.instance_of(int),
converter=int,
)
_b = attr.ib(
validator=attr.validators.optional(attr.validators.instance_of(str)),
default=None
)
_c = attr.ib(
validator=attr.validators.optional(attr.validators.instance_of(int)),
default=None
)
@cached_property
def b(self):
if self._b is None:
return str(self.a) * 3
else:
return self._b
@cached_property
def c(self):
if self._c is None:
return int(self.b) * 3
else:
return self._c
foo = MyClass(a='1')
print(f'foo.a: {foo.a}')
print(f'foo.b: {foo.b}')
print(f'foo.c: {foo.c}') |
Hi Everyone,
First, thanks for the great tool -- I really love writing Python code with it!
I find myself doing things like this a lot when I want
b
andc
to only run when called (and then only once with the result cached).But then I have to "break out of attrs" and loose the other goodness it provides. I know I can do something like this:
But then
b
andc
get "run" or "built" every time, even if they aren't needed (and I'm obviously assuming in reality they do more work they my toy example here shows).What I really want to do is something like:
Or even better, something that doesn't require me to specify
takes_self=True
every time... maybe something like:Thoughts on if something like this would be possible? I haven't dug into guts of attrs yet enough to know if it's doable, but it seems like it would be a great enhancement if something like that is possible. I came not too long ago from a non-Python environment where we built classes almost exactly like I show in my last example above, and it's a super efficient and expressive way to do things.
Thanks!
The text was updated successfully, but these errors were encountered: