On Wed, May 26, 2021 at 2:22 PM Matt del Valle <matthewgdv@gmail.com> wrote:
I'm still digesting this proposal (though I think I like it quite a bit), but there's one thing in particular that just really doesn't gel with me.

Is there any particular reason why you've proposed assignment decorators as being on the same line as the assignment statement rather than on the preceding line(s)?

No reason, very bikesheddable.

I like this:

@typing.TypeVar
T = str, bytes 

about a million times better than:

@typing.TypeVar T = str, bytes

Because the latter feels (to me) too similar for comfort to this:

int foo = 3

Which is in my mind not very pythonic. Also, my brain just has an easier time parsing the multiline version than the single-line one (though I concede that a combination of familiarity and syntax highlighting would solve that issue eventually).

It also represents an asymmetry between the syntax of the proposed assignment decorators and the syntax for function and class decorators.

And finally, it doesn't cleanly accommodate use-cases like those proposed by Stéfane in the previous thread:

@acl(READ, WRITE)
@constraint(10 < _ < 100)
@not_null
@indexed
@depends_on(whatever)
@inject
first_name: str

Whereas the multiline variant does.

Another question I've got is whether you've got any solution in mind for more complex assignment cases?

I do not as of yet. Still thinking about it.
 
After thinking about the proposals in the Steven's thread (the googly-eye symbol), I think I'm a fan of providing the name as a tuple of tuple of strings, like so:

@decorate
foo = first, _, third, *rest = bar = [0, 1, 2, 3, 4]

such that __decoration_call__ receives the following tuple for its second argument:

(('foo',), ('first', '_', 'third', '*rest'), ('bar',)
And it can then choose to do whatever it likes with all the available names without having to implement its own logic for parsing the names back out from a string.

My only other question would be, what would you think of adding a third argument to pass the type hint along? Function decorators can always access the __annotations__ on the function object they act on, but currently your __decoration_call__ can't capture type information. With such an argument, this:

@decorate
foo: int = 3

Would be provided to 'decorate' as:

def __decoration_call__(self, obj, names, annotation):
    print(obj)          # 3
    print(names)        # (('foo',),)
    print(annotation)   # int

I'd not be opposed.

Another (fourth) argument could be the code object from the RHS (if inspect.getsource can't be shoehorned into getting it for us).
 
---
Ricky.

"I've never met a Kentucky man who wasn't either thinking about going home or actually going home." - Happy Chandler