Mailing List Archive

1 2 3 4  View All
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
On 12/01/21 11:32 am, ?ukasz Langa wrote:
>
> EdgeDB uses stringified annotations exclusively which
> minimizes runtime memory usage of annotations because those strings are
> pretty much all ASCII and many can be interned.
>
> 946 -> s_schema.Schema
> 362 -> str
> 298 -> sd.CommandContext

Seems to me the code objects for those would be identical
wherever they're used, and so could be cached and re-used
the same way as interned strings.

--
Greg
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/MYI2JXMBR52HGVL46DRM2KW5T34GC7OP/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
On Mon, 2021-01-11 at 17:56 -0800, Larry Hastings wrote:

> On 1/11/21 5:02 PM, Paul Bryan wrote:
>
> >
> > Some more questions...
> >
> > "Binding"," bound" and "unbound" code objects:
> > Is your use of "binding" terminology in the PEP identical to the
> > binding of a function to an object instance as a method during
> > object creation?
> I'm not.  In PEP 649 I think every reference of "binding" is talking
> about binding a code object to a globals dict to produce a function
> object.   The process of binding a function to an object instance to
> make a method is conceptually very similar, but distinct.
> (and btw, functions aren't bound to their object to make methods
> during object creation, it's done lazily at the time you ask for it--
> that's what the "descriptor protocol" is all about!)
I think it'd be worth briefly describing binding, to avoid confusion.
I'm now more educated on function/method binding lifecycle though, so
bonus! ????

> > Function Annotations:
> >
> > > When binding an unbound annotation code object, a function will
> > > use its own __globals__ as the new function's globals.
> > I'm having trouble parsing this. Does this mean the newly bound
> > __co_annotations__ function will inherit __globals__ from the
> > function it's annotating?
> Yes.  Though I wouldn't use "inherit", I'd just say it "uses" the
> __globals__ from the function.

Then I think this solves my particular scoping problem with 3.10
string-evaluated annotations!

> > Exceptions:
> > It's quite possible for a __co_annotation__ function call to raise
> > an exception (e.g. NameError). When accessing __annotations__, if
> > such an exception is raised during the call to __co_annotations__,
> > what is the expected behavior?
> If the function fails for any reason--throws an exception, or just
> doesn't return an acceptable value--then the getter immediately
> exits, and the internal state of the object is unchanged.  If you
> wanted to, you could catch the exception, fix the error, and get
> __annotations__ again, and it'd work.
OK.

> > s/__co_//?:
> > I'm probably naive, but is there a reason that one could not just
> > store a callable in __annotations__, and use the descriptor to
> > resolve it to a dictionary and store it when it is accessed? It
> > would be one less dunder in the Python data model.
> That would work, but I think the API is a bit of a code smell. 
> __annotations__ would no longer be stable:
> > a.__annotations__ = o
> > assert a.__annotations__ == o
> Would that assert fail?  It depends on what type(o) is, which is
> surprising.

Equally surprising?:

a.__co_annotations__ = o
a.__annotations__
assert a.__co_annotations__ == o

Paul
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
On 12/01/21 2:56 pm, Larry Hastings wrote:
>
> In PEP 649 I think every reference of "binding" is talking
> about binding a code object to a globals dict to produce a function
> object.   The process of binding a function to an object instance to
> make a method is conceptually very similar, but distinct.

Maybe "bare code object" would be a less confusing term?

--
Greg
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/EMVOMYUEQN3ZV5Y2P5B4NEZEJ2KMJTLM/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
On 1/11/21 6:29 PM, Greg Ewing wrote:
> On 12/01/21 10:41 am, Larry Hastings wrote:
>
>> So: if you're using annotations for something besides "type hints",
>
> Didn't Guido decree that using annotations for anything other than
> type hints is no longer supported?


It was never an official decree.  And, for what it's worth, Guido mostly
walked that back, last month:

https://mail.python.org/archives/list/python-dev@python.org/message/OSA7VKZSAHQTTVEJDU2MZXESQKTDNKTB/


Cheers,


//arry/
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
On 1/11/21 6:34 PM, Paul Bryan wrote:
>>>
>>> a.__annotations__ = o
>>> assert a.__annotations__ == o
>>>
>> Would that assert fail?  It depends on what type(o) is, which is
>> surprising.
>>
>
> Equally surprising?:
>
> a.__co_annotations__ = o
> a.__annotations__
> assert a.__co_annotations__ == o


Well, since you asked, no.  It's a good point, but I think my example is
a touch more "surprising".  In my example, a.__annotations__ has two
different True values; in yours, a.__co_annotations__ goes from True to
False.  It's acting more like a cache.

Also consider: if you set o.__annotations__ to a function, what if you
want to examine the function later?  What if you want to examine the
function built by Python?

def enhance_annotations(co_annotations):
    def enhance():
        d = co_annotations()
        d['extra'] = ...
        return d
o.__co_annotations__ = enhance_annotations(o.__co_annotations__)

Finally, it's just a code smell to have one attribute support such a
bewildering variety of types.  Of course, this /works,/ but it's bad
hygiene to store such violently different types in what is ostensibly
the same attribute.


Cheers,


//arry/
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
On Mon, Jan 11, 2021 at 1:20 PM Larry Hastings <larry@hastings.org> wrote:

> PEP 563 states:
>
> For code that uses type hints, the typing.get_type_hints(obj,
> globalns=None, localns=None) function correctly evaluates expressions back
> from its string form.
>
> So, if you are passing in a localns argument that isn't None, okay, but
> you're not using them "correctly" according to the language. Also, this
> usage won't be compatible with static type checkers.
>
I think you're misreading PEP 563 here. The mention of globalns=None,
localns=None refers to the fact that these parameters have defaults, not
that you must pass None. Note that the next paragraph in that PEP mentions
eval(ann, globals, locals) -- it doesn't say eval(ann, {}, {}). There is
considerable discussion below in that same section, but it doesn't come
closer than stating "using local state in annotations is no longer possible
in general", and it states that get_type_hints() correctly provides the
right localns for classes.

Apart from how PEP 563 should be interpreted (maybe we should ask Lukasz) I
would say that basically all feedback I've seen over the changed semantics
of annotations in 3.10 is about this problem, and when I first saw your
proposal I thought that this would solve those issues. I'd be much less
enthusiastic if we're still going to force annotations to only reference
globals.

My read on PEP 563 is that it *primarily* solves the issue of having to put
forward references in string quotes (the most common case probably being
methods that accept or return an instance of the class in which they are
being defined). You have come up with a better solution for that -- the
solution that eluded us all when we were debating PEP 563. But I think that
you should try for maximal backward compatibility with the state of the
world *before* PEP 563.

In particular, static type checkers have no problem with annotations
referencing types defined in the local scope. This has always worked (hence
the complaints about PEP 563) and it would actually be extra work to forbid
this in certain situations but not others.


[...]

> *2. __co_annotations__ scope?*
>
> I'm wondering why __co_annotations__ function could not be scoped (within
> a closure?) such that it can access the values where the function, method,
> class or module are being declared? I acknowledge that I'm railing against
> PEP 563 again, trying to reclaim lost ground.
>
> This is addressed in PEP 563, when it rejected the idea of using "function
> local state when defining annotations":
>
> This would be prohibitively expensive for highly annotated code as the
> frames would keep all their objects alive. That includes predominantly
> objects that won't ever be accessed again.
>
>
> https://www.python.org/dev/peps/pep-0563/#keeping-the-ability-to-use-function-local-state-when-defining-annotations
>
>
But that's a strawman for your PEP. In PEP 563, they would have to keep the
whole frame alive. But with your PEP only the cells containing objects that
are *actually* referenced by annotations, i.e. exactly the objects that the
user wants to see preserved in `__annotations__`. (Well, at Instagram they
probably don't want to see any annotations survive the compilation stage,
but they can hack their own Python compiler -- we know they do that anyway.
:-)

Later in that same section, PEP 563 points out a problem with annotations
that reference class-scoped variables, and claims that the implementation
would run into problems because methods can't "see" the class scope. This
is indeed a problem for PEP 563, but *you* can easily generate correct
code, assuming the containing class exists in the global scope (and your
solution requires that anyway). So in this case
```
class Outer:
class Inner:
...
def method(self, a: Inner, b: Outer) -> None:
...
```
The generated code for the `__annotations__` property could just have a
reference to `Outer.Inner` for such cases:
```
def __annotations__():
return {"a": Outer.Inner, "b": Outer, "return": None}
```

(Note that for *function* locals you don't have to do anything, they just
work, because of closures -- you may not understand them, but they are
important here. :-)

--
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*
<http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
On Mon, Jan 11, 2021 at 3:51 PM Larry Hastings <larry@hastings.org> wrote:

> [...]
>
> This passage in PEP 563 appears not true in Python 3.9 with __future__
> annotations, emphasis mine:
>
> The get_type_hints() function automatically resolves the correct value of
> globalns for functions and classes. *It also automatically provides the
> correct localns for classes.*
>
>
> If this passage was true, I believe the issue that resulted in my affixing
> type hints could have been averted.
>
> As you've discovered, this is one of the places where PEP 563 seems to be
> out-of-date with respect to its implementation. I sifted through the
> source code to typing.get_type_hints() twice, and near as I can figure out,
> localns is literally only ever set to None unless you override it with the
> parameter.
>

This seems to be a bug in get_type_hints() for which someone should file a
bug on bpo, please!
--
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*
<http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
Will do.

On Mon, 2021-01-11 at 20:55 -0800, Guido van Rossum wrote:
> On Mon, Jan 11, 2021 at 3:51 PM Larry Hastings <larry@hastings.org>
> wrote:
> > [...]
> > > This passage in PEP 563 appears not true in Python 3.9 with
> > > __future__ annotations, emphasis mine:
> > >
> > > > The get_type_hints() function automatically resolves the
> > > > correct value of globalns for functions and classes. It also
> > > > automatically provides the correct localns for classes.
> > >
> > > If this passage was true, I believe the issue that resulted in my
> > > affixing type hints could have been averted.
> > As you've discovered, this is one of the places where PEP 563 seems
> > to be out-of-date with respect to its implementation.  I sifted
> > through the source code to typing.get_type_hints() twice, and near
> > as I can figure out, localns is literally only ever set to None
> > unless you override it with the parameter.
> >
>
>
> This seems to be a bug in get_type_hints() for which someone should
> file a bug on bpo, please!
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
Another thought about this PEP (hopefully my last one tonight).

The section on backwards compatibility doesn't mention what should happen
with annotations that are stringified by the user (as is needed for forward
references in code that hasn't been PEP-563-ified yet).

That's a PEP 484 feature. Should we start deprecating that at the same
time? Static checkers support it but don't need it (for example, stubs in
typeshed don't use it since their code is never evaluated).

At the very least I think your PEP should mention what happens for these --
presumably `__annotations__` will just contain the string literal, so
get_type_hints() would be needed to evaluate these.

--
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*
<http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
On 1/11/21 5:37 PM, Larry Hastings wrote:
> I'll have to let people with large code bases speak up about this, but
> my understanding is that most people would prefer Python to use less
> memory.  On my 64-bit Linux machine, a code object is 136 bytes, its
> empty __dict__ is 64 bytes, [...]


Oops: where I said "a code object is 136 bytes", I meant, a /function/
object is 136 bytes.  We regret the error.


//arry/
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
On 1/11/21 5:33 PM, Inada Naoki wrote:
> Note that PEP 563 semantics allows more efficient implementation.
> Annotation is just a single constant tuple, not a dict.
> We already have the efficient implementation for Python 3.10.
>
> The efficient implementation in 3.10 can share tuples. If there are
> hundreds of methods with the same signature, annotation is just a
> single tuple, not hundreds of tuples. This is very efficient for auto
> generated codebase. I think this PEP can share the code objects for
> same signature by removing co_firstlineno information too.

That's very clever!  My co_annotations repo was branched from before
this feature was added, and I haven't pulled and merged recently.  So I
hadn't seen it.


> Additionally, we should include the cost for loading annotations from
> PYC files, because most annotations are "load once, set once".
> Loading "simple code object" from pyc files is not so cheap. It may
> affect importing time of large annotated codebase and memory
> footprints.

I did some analysis in a separate message.  The summary is, the code
object for a single annotation costs us 232 bytes; that includes the
code object itself, the bytestring for the bytecode, and the bytestring
for the lnotab.  This grows slowly as you add new parameters; the code
object for ten parameters is 360 bytes.

It seems possible to create a hybrid of these two approaches! Here's my
idea: instead of the compiler storing a code object as the annotations
argument to MAKE_FUNCTION, store a tuple containing the fields you'd
need to /recreate/ the code object at runtime--bytecode, lnotab, names,
consts, etc. func_get_annotations would create the code object from
that, bind it to a function object, call it, and return the result. 
These code-object-tuples would then be automatically shared in the .pyc
file and at runtime the same way that 3.10 shares the tuples of
stringized annotations today.

That said, I suggest PEP 649's memory consumption isn't an urgent
consideration in choosing to accept or reject it.  PEP 649 is
competitive in terms of startup time and memory usage with PEP 563, and
PEP 563 was accepted and shipped with several versions of Python.


Cheers,


//arry/
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
Yes, PEP 649 is completely agnostic about what values you put in as
annotations.  You can put in strings, complex objects,
expressions--whatever you put in, you get back out later.

I'm happy to add some text to the PEP if this needs clarifying; I just
thought it was obvious.


Cheers,


//arry/

On 1/11/21 9:11 PM, Guido van Rossum wrote:
>  Another thought about this PEP (hopefully my last one tonight).
>
> The section on backwards compatibility doesn't mention what should
> happen with annotations that are stringified by the user (as is needed
> for forward references in code that hasn't been PEP-563-ified yet).
>
> That's a PEP 484 feature. Should we start deprecating that at the same
> time? Static checkers support it but don't need it (for example, stubs
> in typeshed don't use it since their code is never evaluated).
>
> At the very least I think your PEP should mention what happens for
> these -- presumably `__annotations__` will just contain the string
> literal, so get_type_hints() would be needed to evaluate these.
>
> --
> --Guido van Rossum (python.org/~guido <http://python.org/~guido>)
> /Pronouns: he/him //(why is my pronoun here?)/
> <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
On 1/12/21 8:47 AM, Larry Hastings wrote:
> It seems possible to create a hybrid of these two approaches! Here's
> my idea: instead of the compiler storing a code object as the
> annotations argument to MAKE_FUNCTION, store a tuple containing the
> fields you'd need to /recreate/ the code object at runtime--bytecode,
> lnotab, names, consts, etc. func_get_annotations would create the code
> object from that, bind it to a function object, call it, and return
> the result.  These code-object-tuples would then be automatically
> shared in the .pyc file and at runtime the same way that 3.10 shares
> the tuples of stringized annotations today.

Note that this only works in the current version of the PEP / prototype,
where annotations are strictly evaluated in module scope.  If we start
supporting closures, those need "cell" objects, which IIUC can't be
marshalled.


//arry/
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
Given all the effort that get_type_hints() puts into evaluating those
strings it seems important to spell out explicitly that they're not
special. (IIRC they *are* special in PEP 563.)

On Tue, Jan 12, 2021 at 8:56 AM Larry Hastings <larry@hastings.org> wrote:

>
> Yes, PEP 649 is completely agnostic about what values you put in as
> annotations. You can put in strings, complex objects,
> expressions--whatever you put in, you get back out later.
>
> I'm happy to add some text to the PEP if this needs clarifying; I just
> thought it was obvious.
>
>
> Cheers,
>
>
> */arry*
> On 1/11/21 9:11 PM, Guido van Rossum wrote:
>
> Another thought about this PEP (hopefully my last one tonight).
>
> The section on backwards compatibility doesn't mention what should happen
> with annotations that are stringified by the user (as is needed for forward
> references in code that hasn't been PEP-563-ified yet).
>
> That's a PEP 484 feature. Should we start deprecating that at the same
> time? Static checkers support it but don't need it (for example, stubs in
> typeshed don't use it since their code is never evaluated).
>
> At the very least I think your PEP should mention what happens for these
> -- presumably `__annotations__` will just contain the string literal, so
> get_type_hints() would be needed to evaluate these.
>
> --
> --Guido van Rossum (python.org/~guido)
> *Pronouns: he/him **(why is my pronoun here?)*
> <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
>
>

--
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*
<http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
Larry Hastings wrote:
> The control-flow exclusion is for /module//attribute/ or /class
> attribute/ annotations:
> class C:
>   if random.random() > 0.5:
>     my_attr:int=3
>   else:
>     my_attr2:float=3.5

That very example would be helpful in the FAQ, though I understand if you're concerned about making a minor sub-section seem too long.

If I understand correctly, the problem is that you can't store multiple alternative annotations on my_attr. Therefore:

class C:
my_attr:(int if random.random > 0.5 else float)

should be OK, because there is only a single annotation.

What about optional attributes, like:

class C:
  if random.random() > 0.5:
    my_attr:int=3

Also, would (conditionally defined) function variable attributes become a problem if they were actually stored? (Take Larry's class example, and make if a def instead of a class statement.)


My (weakly held, personal) opinion is that these restrictions would be reasonable, and a single release of deprecation would be enough, but it would be better if that code could trigger a deprecation warning during that release, even for code that hasn't done the future import. It would also be OK to just say "implementation-defined behavior; CPython 3.x ignores the annotation" instead of banning them.

-jJ
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/TRX23XWZ3NGROVQRC6DXLIU7NPPNEZRB/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
On 1/12/21 11:26 AM, Jim J. Jewett wrote:
> If I understand correctly, the problem is that you can't store multiple alternative annotations on my_attr. Therefore:
>
> class C:
> my_attr:(int if random.random > 0.5 else float)
>
> should be OK, because there is only a single annotation.

Sure, that works fine.  Any expression (except "yield" and ":=") is okay
in an annotation.


> What about optional attributes, like:
>
> class C:
>   if random.random() > 0.5:
>     my_attr:int=3
>
> Also, would (conditionally defined) function variable attributes become a problem if they were actually stored? (Take Larry's class example, and make if a def instead of a class statement.)

You mean attributions on function locals?

def foo():
  if random.random() > 0.5:
    x:int=3
  else:
    x:float=3.5

As I mentioned in my PEP, attributions on function locals have no effect
at runtime.  If they did, this would cause the same problem that doing
it in classes has.


Cheers,


//arry/
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
On Tue, 2021-01-12 at 09:54 -0800, Larry Hastings wrote:
> Note that this only works in the current version of the PEP /
> prototype, where annotations are strictly evaluated in module scope. 
> If we start supporting closures, those need "cell" objects, which
> IIUC can't be marshalled.
Since the __co_annotations__ function will get globals from the
function it annotates, doesn't it get more than just module scope?

Paul
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
Hello,

On Mon, 11 Jan 2021 13:44:45 -0800
Larry Hastings <larry@hastings.org> wrote:

> The control-flow exclusion is for /module//attribute/ or /class
> attribute/ annotations:
>
> class C:
>   if random.random() > 0.5:
>     my_attr:int=3
>   else:
>     my_attr2:float=3.5

Ok, let's take "module attribute" as an example. Why do you think
there's anything wrong with this code:

======
import config
from .types import *

if config.SUPPORT_BIGINT:
var: bigint = 1
else:
var: int64 = 1
======


> Your example doesn't define any module attributes or class attributes
> inside flow control statements, so that code should work fine. 
> (Defining functions/methods inside flow control statements isn't a
> problem.)

PEP649 criticizes PEP563's approach with big words like "It requires
Python implementations to stringize their annotations. This is
surprising behavior — unprecedented for a language-level feature." But
itself devolves to clauses like:

>>> It seems reasonable to declare that both are at the very least
>>> unsupported, and their use results in undefined behavior. It might
>>> be worth making a small effort to explicitly prohibit them with
>>> compile-time checks.


Isn't the fact that PEP563 doesn't have problems with annotations in
conditionals is a sign of PEP563 technical superiority? And its
"unprecedented" measure of storing annotations as strings is actually a
clever technical feat - it should have stored annotations as AST trees,
but such trees would take quite a lot of memory. So, PEP563 smartly
went to store those ASTs in a serialized format. So, those strings
aren't strings, but serialized ASTs.

Overall 2 comments/questions:

1. Was there an attempt to devise how to make PEP649 deal with existing
Python language features (like conditionals)?
2. As a general comment, PEP649, by placing arbitrary restrictions on
where annotations can appear, tries to dig under the foundations of
Python as a dynamic language. Which is absolutely great, it just the
PEP should be viewed as such - undermining Python's dynamic nature, as
if there's something wrong with it.



--
Best regards,
Paul mailto:pmiscml@gmail.com
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/2GLVNLJ4WZMQ5FPMNAFZFU7MSVK5GOTJ/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
On 1/12/21 12:16 PM, Paul Bryan wrote:
> On Tue, 2021-01-12 at 09:54 -0800, Larry Hastings wrote:
>>
>> Note that this only works in the current version of the PEP /
>> prototype, where annotations are strictly evaluated in module scope. 
>> If we start supporting closures, those need "cell" objects, which
>> IIUC can't be marshalled.
>>
> Since the __co_annotations__ function will get globals from the
> function it annotates, doesn't it get more than just module scope?


I'm not sure what you're asking.  And, uh, what's the difference between
"globals" and "module scope"?


//arry/
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
On Tue, Jan 12, 2021 at 11:31 AM Jim J. Jewett <jimjjewett@gmail.com> wrote:

> Larry Hastings wrote:
> > The control-flow exclusion is for /module//attribute/ or /class
> > attribute/ annotations:
> > class C:
> > if random.random() > 0.5:
> > my_attr:int=3
> > else:
> > my_attr2:float=3.5
>
> That very example would be helpful in the FAQ, though I understand if
> you're concerned about making a minor sub-section seem too long.
>

This elucidates a crucial point to me: Larry's proposal looks at the source
code of the annotations.


> If I understand correctly, the problem is that you can't store multiple
> alternative annotations on my_attr. Therefore:
>
> class C:
> my_attr:(int if random.random > 0.5 else float)
>
> should be OK, because there is only a single annotation.
>

Does that mean that the generated function would contain the entire
expression `(int if random.random > 0.5 else float)`? I guess that's what
it has to mean. But the PEP only uses such simple examples that it's easy
to miss this.

--
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*
<http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
On 13/01/21 6:54 am, Larry Hastings wrote:
> Note that this only works in the current version of the PEP / prototype,
> where annotations are strictly evaluated in module scope.  If we start
> supporting closures, those need "cell" objects, which IIUC can't be
> marshalled.

The cells belong to the enclosing scope, not the function that uses
them. I don't think they would interfere with sharing parts of code
objects between identical annotations.

--
Greg
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/QKMYWGBSQKNFUNBHXXWFJZ7WIRHGTEWI/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
On 13/01/21 5:47 am, Larry Hastings wrote:
>
> instead of the compiler storing a code object as the annotations
> argument to MAKE_FUNCTION, store a tuple containing the fields you'd
> need to /recreate/ the code object at runtime--bytecode, lnotab, names,
> consts, etc.

Would that tuple be significantly smaller than the corresponding
code object, though?

--
Greg
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/2NHFIGK55XN4U77V6V2KTBRGJ7TSGAAB/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
On 1/12/21 3:53 PM, Greg Ewing wrote:
> On 13/01/21 5:47 am, Larry Hastings wrote:
>>
>> instead of the compiler storing a code object as the annotations
>> argument to MAKE_FUNCTION, store a tuple containing the fields you'd
>> need to /recreate/ the code object at runtime--bytecode, lnotab,
>> names, consts, etc.
>
> Would that tuple be significantly smaller than the corresponding
> code object, though?

It would only be slightly smaller.  The point of doing it would be to
boil out fields that change per-object (e.g. co_name) so that functions
with identical signatures would share the same tuple both in the .pyc
and at runtime.  This idea is predicated on Inada-san's assertion that
this is an important memory optimization, that there are large
heavily-annotated projects with lots of functions/methods with identical
signatures where this memory savings is significant.


//arry/
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
On Wed, Jan 13, 2021 at 1:47 AM Larry Hastings <larry@hastings.org> wrote:
>
> On 1/11/21 5:33 PM, Inada Naoki wrote:
>
> Note that PEP 563 semantics allows more efficient implementation.
> Annotation is just a single constant tuple, not a dict.
> We already have the efficient implementation for Python 3.10.
>
> The efficient implementation in 3.10 can share tuples. If there are
> hundreds of methods with the same signature, annotation is just a
> single tuple, not hundreds of tuples. This is very efficient for auto
> generated codebase. I think this PEP can share the code objects for
> same signature by removing co_firstlineno information too.
>
> That's very clever! My co_annotations repo was branched from before this feature was added, and I haven't pulled and merged recently. So I hadn't seen it.
>

Please see this pull request too. It merges co_code and co_consts. It
will save more RAM and importing time of your implementation.
https://github.com/python/cpython/pull/23056

>
> Additionally, we should include the cost for loading annotations from
> PYC files, because most annotations are "load once, set once".
> Loading "simple code object" from pyc files is not so cheap. It may
> affect importing time of large annotated codebase and memory
> footprints.
>
> I did some analysis in a separate message. The summary is, the code object for a single annotation costs us 232 bytes; that includes the code object itself, the bytestring for the bytecode, and the bytestring for the lnotab. This grows slowly as you add new parameters; the code object for ten parameters is 360 bytes.
>
> It seems possible to create a hybrid of these two approaches! Here's my idea: instead of the compiler storing a code object as the annotations argument to MAKE_FUNCTION, store a tuple containing the fields you'd need to recreate the code object at runtime--bytecode, lnotab, names, consts, etc. func_get_annotations would create the code object from that, bind it to a function object, call it, and return the result. These code-object-tuples would then be automatically shared in the .pyc file and at runtime the same way that 3.10 shares the tuples of stringized annotations today.

It may be good idea if we can strip most code object members, like
argcount, kwonlyargcount, nlocals, flags, freevars, cellvars,
filename, name, firstlineno, linetable.
It can be smaller than Python 3.9.

>
> That said, I suggest PEP 649's memory consumption isn't an urgent consideration in choosing to accept or reject it. PEP 649 is competitive in terms of startup time and memory usage with PEP 563, and PEP 563 was accepted and shipped with several versions of Python.
>

I still want a real-world application/library with heavy annotation.
My goal is to use annotations in the stdlib without caring about
resource usage or importtime.
But I agree with you if PEP 649 will be smaller than Python 3.9.

Regards,
--
Inada Naoki <songofacandy@gmail.com>
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/CNXCFW2PXUCZ75OBFZTUS3TVKI3IEKZH/
Code of Conduct: http://python.org/psf/codeofconduct/
Re: PEP: Deferred Evaluation Of Annotations Using Descriptors [ In reply to ]
Paul Sokolovsky wrote:
> Ok, let's take "module attribute" as an example. Why do you think
> there's anything wrong with this code:
> ======
> import config
> from .types import *
> if config.SUPPORT_BIGINT:
> var: bigint = 1
> else:
> var: int64 = 1

"Wrong" is too strong, but it would be better as

mybigint = bigint if config.SUPPORT_BIGINT else int64
...
var:mybigint = 1

so asking people to rewrite it that way over the course of a major release is probably an acceptable price.

-jJ
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/FGZ4YK63MIZ6XVLQ4OMVJU7HUJPG73CD/
Code of Conduct: http://python.org/psf/codeofconduct/

1 2 3 4  View All