classification
Title: Document the circumstances where the locals() dict get updated
Type: enhancement Stage: patch review
Components: Documentation Versions: Python 3.7, Python 3.6, Python 3.5, Python 2.7
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: docs@python Nosy List: amaury.forgeotdarc, bgailer, docs@python, eric.araujo, eric.snow, flox, georg.brandl, martin.panter, ncoghlan, nedbat, r.david.murray, techtonik, terry.reedy
Priority: normal Keywords: patch

Created on 2013-03-25 17:20 by techtonik, last changed 2016-12-03 04:44 by martin.panter.

Files
File name Uploaded Description Edit
locals_doc.patch r.david.murray, 2013-03-30 21:53
issue17546.stoneleaf.01.patch ethan.furman, 2015-01-15 04:44 review
locals_doc.03.patch martin.panter, 2015-06-29 15:09 review
locals_doc.04.patch martin.panter, 2016-12-03 04:44 review
Messages (42)
msg185213 - (view) Author: anatoly techtonik (techtonik) Date: 2013-03-25 17:20
-locals() returns object that does't walk like a duck.
+locals() returns object that does't work like a dict.

Much of the confusion with locals() comes from the fact that returned object is labelled a dict, but this heisendict changes its behavior when you're trying to introspect it. So, to give users a hint that this object is different, I propose to rename it to a different type and supply an appropriate help() for it.
msg185215 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2013-03-25 17:24
The documentation seems pretty clear on the nature of the dict returned by locals(). [1]  What documentation are you referring to?

[1] http://docs.python.org/3.4/library/functions.html#locals
msg185216 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2013-03-25 17:25
Sorry, didn't mean to change the attributed version.  However the 2.7 documentation says the same thing.
msg185260 - (view) Author: anatoly techtonik (techtonik) Date: 2013-03-26 07:37
1. The documentation doesn't say that the content of this dict may change sporadically even if you don't call locals()

2. I am referring to inline documentation:

    >>> h = locals()
    >>> type(h)
    <class 'dict'>
    >>> help(h)
msg185276 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2013-03-26 15:28
So the problem you are having is that inside functions the dict returned by locals() does not get updated when the "current local symbol table" changes?  Keep in mind that for modules and classes (the other two execution blocks), the dict returned by locals() does get updated.

This difference reflects that fact that, in CPython at least, the local execution namespace of a function call's stack frame is not stored in a dictionary.  When you call locals() in a function it is only making a copy of the frame's fast locals.  The fast locals never gets directly exposed except through normal name lookup/binding/deletion.  While technically possible, changing this simply isn't worth it.

The documentation already makes it clear that the dict returned by locals() represents the "current local symbol table" and that you should not expect changes to that dict to be reflected in the actual locals.  Are you recommending that it be more clear that the dict may be no more than a snapshot of the locals at the time locals() is called?
msg185282 - (view) Author: anatoly techtonik (techtonik) Date: 2013-03-26 17:49
Under the trace function, the dict is always updated, and that changed a workflow in the program I was debugging leading to heisenbug. But that's a different story. I'd like to concentrate on the reasons to rename locals() result type from 'dict' to 'livedict' (or other internal type with well-defined behavior).

dict() returned by locals() is sporadically updated. The problem is not with when it is updated, or how it is updated. The problem is that the fact that it is updated is not indicated in any way. And the problem that comes from this problem is that people don't realize that this dict may change its contents. As a result people become confused with Python.

The documentation is also ambiguous. Those people who don't know about self-updating behavior (I was) read "represents" like a "copy of symbol table", not like a "internally updated view of symbol table".

From the OOP point of view, the object doesn't behave like a normal dict, and it will be less confusing if it is renamed.


offtopic: "local execution namespace of a function call's stack frame" sounds cryptic - I am afraid that without visualization of local/global/namespace/scope/frame I am unable to understand that right now.

offtopic2: I also don't get "you should not expect changes to that dict to be reflected in the actual locals". I reads as if in some cases modifying the dict will change the locals. I thought that it is impossible as it is just a copy.
msg185290 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2013-03-26 19:14
Thanks for the details, Anatoly.  I am surprised by the behavior you've described.  It may be that functions don't use fast locals when tracing is turned on.  I'll have to check.  If that's the case, I think the documentation for locals() should be improved.  Either way, I agree that inconsistent (and undocumented) behavior is a headache.  However, changing the type of the object returned by locals() is going to take a lot more justification.  A doc update should be sufficient and a much easier sell.

Here are some further questions:

1. the dynamic update you described happens in function bodies (i.e. stack frames)?
2. does that behavior happen when you are not using a tracing function?

Also, if you have a minute, throw up a patch that reproduces the behavior you're talking about.  That will help get this resolved faster.

Keep in mind that locals() always returns a normal dict.  Just like any other dict, other code that has a reference to that "locals" dict can interact with it, which is what you have described.  In this case, the interpreter is doing so.  The only case where I find that surprising is where a stack frame is using fast locals, which is what function calls normally do.
msg185320 - (view) Author: anatoly techtonik (techtonik) Date: 2013-03-27 10:01
Raymond, could you please get the title back? You unintentionally hijacked the issue. The "Document the circumstances where the locals() dict gets updated" is not a describing title for this issue - it is one of the possible action items. I'd prefer to see a separate issue to document the stuff that "blocks" this one. It is quite evident that this action is required, but IMHO there is not enough evidence to conclude that it will be sufficient to close this ticket.

Eric, I need more time to answer your questions.
msg185321 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2013-03-27 10:24
The previous title, "rename type returned by locals() to livedict" did not describe the reality, since locals() returns a regular dict.
[Would you call x.__dict__ a livedict?]

So either this issue should be closed as invalid, because it's based on incorrect understandings of Python internals; or we could improve documentation about locals() in order to remove surprising behavior and (real) confusion in programmers' minds.
msg185324 - (view) Author: anatoly techtonik (techtonik) Date: 2013-03-27 12:01
Eric, here is the code that confirms changed behavior under trace function for both Python 2 and 3 - http://bugs.python.org/file15081/localstest.py

I agree that the documentation fix is necessary, and if you say that it is an easier sell - I tend to believe you. But with this fix the issue is still not fully covered, so it is interesting to know what builds up to the cost of renaming if we come to some common point about the type of this 'dict' from the user point of view.
msg185325 - (view) Author: anatoly techtonik (techtonik) Date: 2013-03-27 12:03
Amaury, from user's point of view (I am not a core developer - I just need to troubleshoot complicated Python code) the object (the internal structure) returned by locals() has different behavior than a normal dict.

Normal dict in Python is updated by user code (which "I as a user" can see and can inspect for further troubleshooting) and for locals's dict this is not correct. 

If dict and locals's object are of the same type, I'd expect them to be interchangeable.

By proposing a documentation fix as a final remedy, please think about the entry point through which users come to this "trap".
msg185327 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2013-03-27 12:45
> Normal dict in Python is updated by user code (which "I as a user" can
> see and can inspect for further troubleshooting) and for locals's dict
> this is not correct.

Do you have an example?
msg185332 - (view) Author: anatoly techtonik (techtonik) Date: 2013-03-27 13:48
Example:

    l = locals()
    z = dict(a=5, b=3)

    lc = dict(l)
    zc = dict(z)

    print(lc == l)
    print(zc == z)

Gives:

    False
    True
msg185335 - (view) Author: bob gailer (bgailer) Date: 2013-03-27 14:08
On 3/27/2013 9:48 AM, anatoly techtonik wrote:
> anatoly techtonik added the comment:
>
> Example:
>
>      l = locals()
>      z = dict(a=5, b=3)
>
>      lc = dict(l)
>      zc = dict(z)
>
>      print(lc == l)
>      print(zc == z)
>
> Gives:
>
>      False
>      True
Expected behavior.
lc is not another reference to locals(). It refers to a new object.
zc = ... updates locals() but not lc
msg185336 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2013-03-27 14:10
This is expected: "zc = xxx" updates locals!
but not the copy.
msg185339 - (view) Author: anatoly techtonik (techtonik) Date: 2013-03-27 14:43
> "I as a user" can
> see and can inspect for further troubleshooting

This doesn't work for this example, which was your question.

I still feel like this needs further clarification. For a user this behavior is not expected. User is someone who doesn't know the internal details of Python interpreter (and may not even remember that dict can be modified by reference). If you disagree with me - try to do corridor testing and see how many people will compile it in their head and give you the right answer to this example.
msg185350 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2013-03-27 16:58
Thanks for the script Anatoly.  That's pretty much what I was imagining from your description.  This definitely reinforces my belief that profiling.
msg185358 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2013-03-27 17:55
Okay, I found it.  sys.settrace() ultimately results in the setting of tstate->use_tracing to true and sets tstate->c_tracefunc and tstate_c_traceobj (see sys_settrace() in Python/sysmodule.c and PyEval_SetTrace() in Python/ceval.c).  tstate->c_tracefunc() gets set to trace_trampoline() in Python/sysmodule.c and tstate->c_traceobj gets set to your tracing function.

When an execution frame begins, the interpreter sets up tracing.  From Python/ceval.c:1124:

/* tstate->c_tracefunc, if defined, is a
   function that will be called on *every* entry
   to a code block.  Its return value, if not
   None, is a function that will be called at
   the start of each executed line of code.
   (Actually, the function must return itself
   in order to continue tracing.)  The trace
   functions are called with three arguments:
   a pointer to the current frame, a string
   indicating why the function is called, and
   an argument which depends on the situation.
   The global trace function is also called
   whenever an exception is detected. */

So trace_trampoline() gets at the start of each block and once for each line of Python code.  Each time it calls call_trampoline() (also in Python/sysmodule.c).  You'll find that in call_trampoline(), there is a call to PyFrame_FastToLocals() just before it calls your tracing function (at that point called "callback").

When called, PyFrame_FastToLocals() updates the contents of the frame's "slow" locals (f_locals) with the values in the fast locals.  And...wait for it...f_locals is the dict that gets returned by locals().

Thus, when tracing is on, the dict returned by locals() gets updated once per block and once per line of Python code.  That is exactly what you are seeing.

When tracing is not on, PyFrame_FastToLocals() would only be called when you call locals() (inside a function).  It's interesting to note that in that case locals() will return the exact same dictionary:

>>> def f():
...     return locals() is locals()
...
>>> f()
True

Conclusion
----------

The bottom line is that the docs for locals() could stand to have a little more detail for this case (including a link to the docs for tracing at sys.settrace() or wherever).  However, the behavior here is--at present--a CPython implementation detail.  Any note would likely say as much; something like this:

.. function:: locals()

   ...

   Each call to locals() will return the same dictionary, updated to
   the contents of the current local symbol table.

   .. impl-detail::

      Under tracing and profiling in CPython, the dict returned by
      ``locals()`` will be updated at the beginning of each code block
      and at each line of code.  See :func:`sys.settrace`.

The note is really only meaningful for functions since class bodies and modules don't use fast locals and f_locals is set to f_globals (i.e. locals() == globals()).  However, that point is superfluous to the above note since it remains true either way.
msg185359 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2013-03-27 18:01
I should also point out that the following from that note may actually also be a CPython implementation detail:

   Each call to locals() will return the same dictionary, updated to
   the contents of the current local symbol table.

We'd want to be sure that such should be expected from all implementations (since it basically adds to the language specification).  Otherwise it should also go in an impl-detail note.
msg185399 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2013-03-28 02:09
I've indicated that this issue supercedes issue #7083.
msg185404 - (view) Author: anatoly techtonik (techtonik) Date: 2013-03-28 06:32
It could be the implementation detail if locals() calls were not useful to majority of Python software, and if behavior of its returned dict did not affect the execution flow of user programs (was deterministic for users who should not care about the implementation details).

What I proposed initially is to wrap the locals(), the dict it returns and various calls that update this dict into a pattern called "livedict". This pattern has a defined behavior, and in OOP it would be encapsulated in a single object with one private method locals.__update (called by FastToLocals and other internals), and accessor method locals.todict() (name may vary) to receive a static copy of the live cache. If somebody needs access to real-time updated symbol table, it may request to work with realtime API of this locals object instead. This API is turn could have an implementation detail that transparently provided faster access to the local symbol table than copying dict into cache every time.

Wrapping this into a pattern also makes it easy to communicate details in case other Python implementation breaks this implementation detail of CPython. It may be easier for understanding to start with broken aspect of the pattern without digressing into implementation details, and read about implementation details later, than to go other way around.
msg185405 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2013-03-28 08:12
locals() being useful to the majority of Python software is news to me...
msg185440 - (view) Author: Ned Batchelder (nedbat) * (Python triager) Date: 2013-03-28 12:18
Changing the type of the locals() return isn't the right way to solve this problem.  Better docs is the way to do it.  If someone is calling locals(), they should read the docs.  Examining the type of values is discouraged in Python, we shouldn't expect people to discover nonintuitive behavior because the type has been artificially changed to "livedict".
msg185473 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2013-03-28 22:51
> Changing the type of the locals() return isn't the right way to solve
> this problem.  Better docs is the way to do it.  If someone is calling
> locals(), they should read the docs.  Examining the type of values is
> discouraged in Python, we shouldn't expect people to discover
> nonintuitive behavior because the type has been artificially changed
> to "livedict".

+1

Issue #7083 was created to promote a semantic change (ultimately) and it was rejected in deference to a doc change.  That's part of why this ticket was changed to focus on documentation.

My only concern is that locals() has some pretty heavy implementation specifics, so any doc change needs to respect that (or be part of an effort to tighten the spec for locals()).
msg185491 - (view) Author: anatoly techtonik (techtonik) Date: 2013-03-29 06:08
Ok. Maybe I proposed the solution too early. I am fine with doc fix, but given the previous experience I have doubts it will happen. Maybe opening a wiki page with a current draft can help:

   http://wiki.python.org/moin/Locals
    or better
   http://piratepad.net/locals

Describing implementation details is necessary, but they should include a recommendation how to work with locals safely and avoid hitting yourself in the foot if you don't want to read about internals. For that I propose "if you are not interested in implementation details, always copy locals() to dict to avoid potential problems with auto-updating behavior. This is also guaranteed to work with other Python implementations." Is that ok?
msg185544 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2013-03-30 05:34
After the last exchange on #7083, Guido emailed me that I could/should revised the doc a bit, but he said he did *not* want the details explained because he regards them as CPython implementation details and not part of the language definition. I have not done so yet because of other issues, especially the Idle PEP and related discussion. What is needed is something like

"The relationship between the local namespace and the locals dict is undefined between calls to locals(). Changes to either may or may not be propagated to the other."

Perhaps add "The dict returned by locals() is intended to be used immediately, either for introspection or for passing on to functions such as eval() and exec()." and even "It is not intended to be saved and used later."

What I have not figured out yet is how to integrate the above with the current text.
msg185558 - (view) Author: anatoly techtonik (techtonik) Date: 2013-03-30 14:00
> them as CPython implementation details and not part of the language definition

What is the formal language definition of locals() then? What behavior and functionality of locals() should be supported by all Python implementations? For a potential language developer, what should locals() calls return to be compatible with this Python definition?
msg185567 - (view) Author: Ned Batchelder (nedbat) * (Python triager) Date: 2013-03-30 15:28
I would say it something like this:

"The dictionary returned by locals() is an accurate snapshot of the local namespace at the time it is called.  After the call returns, changes to one may or may not be reflected in the other.  The dictionary may change unpredictably after the call, and how it does is implementation-specific.    Holding a reference to the dictionary may produce surprising effects."
msg185575 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2013-03-30 16:27
I also think 'free variable' should be replace by 'nonlocal name'.
msg185585 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2013-03-30 19:31
Terry: agreed.
msg185593 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2013-03-30 21:53
The problem with using 'nonlocal' is that it would naturally be read as 'those names referenced in a nonlocal statement', which I don't think is the case.  Maybe 'non-local', to differentiate it from the keyword?

I'm attaching a patch incorporating my understanding of the suggestions made so far.
msg185601 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2013-03-30 23:23
/non-local/Non-local/ If we add the hyphen, perhaps we should add 'non-global' also.

Thanks for the concrete draft. It is definitely an improvement.

The last sentence is somewhat redundant with the second. The problem with the last sentence is that it only said that changes to the dict might not propagate back the the namespace, while is is also true that changes to the namespace might or might not propagate to the dict. The new second sentence says both. In addition, I somewhat disagree with 'should not modify'. A person could have a perfectly good reason to do so, but they should not expect propagation of the changes. So I am tempted to drop the last sentence. On the other hand, 'undefined' should be somewhere.
msg185613 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2013-03-31 05:03
Hmm.  Perhaps the last sentence could be "... because changes to the local dict propagating to the local namespace cannot be relied upon to either happen or not happen".  That would make it less redundant, since it would essentially be referencing the previous statement in the specific case of the consequences of modification.

The original included the caution against modifying it, and I think it is valid because of the inconsistent behavior.  Perhaps it could be weakened to "it is not a good idea to modify"?
msg185615 - (view) Author: anatoly techtonik (techtonik) Date: 2013-03-31 05:36
> ... cannot be relied upon to either happen or not happen...

IMHO this phrase is from Advanced English course.

> The original included the caution against modifying it, and I think it is
valid because of the inconsistent behavior.
> Perhaps it could be weakened to "it is not a good idea to modify"?

Ambiguity already adds fear and uncertainty. Just explaining the
consequences would be good style for the technical doc.
msg234049 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2015-01-15 04:44
Combined the second and last lines, discarded duplication.
msg234072 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2015-01-15 13:09
Your formulation is more concise, thank you.

I suggest dropping the word 'additionally'.  Also, "how it does" would be better phrased as "how it changes", I think.  (It really should be "whether and how it changes", but in deference to Anatoly's 'advanced English' comment I'm willing to let that imprecision slide).
msg234076 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2015-01-15 14:25
What about instead of

'''
Whether changes to one are reflected in the other after the call returns is undefined; additionally, the dictionary may change unpredictably after the call, and how it does is implementation-specific.
'''

substitue this wording:

'''
Whether changes to one are reflected in the other after the call returns, and when such updates occur, is undefined and implementation-specific.
'''

The old wording seems under-specified. It would allow a function call, garbage collection, etc, to clobber the dictionary, say overwriting with another function’s locals(), before you get a chance to work with the dictionary.
msg234078 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2015-01-15 14:59
Yeah, the question of thread-safety in regards to what we are talking about here also occurred to me.  That is, the wording makes one wonder if locals is thread safe or not.  I don't see your suggested wording as making it clearer, though.

The problem is that it *is* underspecified.

So I think the correct description of the current under-specification is that locals() returns a copy of the current locals namespace.  If you modify the thing returned by locals it may or may not update the local namespace.  If you modify the local namespace (by doing x = y or its equivalents) the change may or may not be reflected in the object that was returned by locals().

Now, how do we boil that down?  Or do we just say it more or less that way?
msg245922 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2015-06-29 06:54
Here is another attempt with different words:

'''
.. note::
   The dictionary returned by :func:`locals` is an accurate snapshot of the local namespace at the time it is called.  If the namespace changes after the call, the dictionary may become out of date, but it may also automatically update at any time.  The contents of the dictionary should not be modified by the user; it is undefined whether such changes affect the namespace or not.
'''
msg245924 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2015-06-29 07:39
I mostly like Martin's suggested wording, but would also note that I filed issue 17960 to tighten up the requirements for when we expect assigning to locals() to work.

To save folks reading the whole referenced email, I think it would be worth defining that modifying the namespace returned by locals() will affect the runtime namespace at module and class scope and when using exec, but will have no effect at function scope (as locals() returns a copy of the namespace in that case).
msg245942 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2015-06-29 15:09
I quickly scanned through the email thread from Issue 17960. I guess it makes sense to specify that locals() can be used to directly get a class’s namespace. Probably doesn’t hurt to say locals() is equivalent to globals() at module level, although this seems like a fairly redundant feature.

Here is locals_doc.03.patch, which uses my wording for function namespaces, and also adds more for class and global namespaces, as suggested by Nick.
msg282267 - (view) Author: Martin Panter (martin.panter) * (Python committer) Date: 2016-12-03 04:44
Some minor tweaks to my earlier patch:
* list comprehension → comprehension
* time it is called → time of the call
History
Date User Action Args
2016-12-03 04:44:05martin.pantersetfiles: + locals_doc.04.patch

messages: + msg282267
versions: + Python 3.6, Python 3.7, - Python 3.3, Python 3.4
2015-07-21 07:08:12ethan.furmansetnosy: - ethan.furman
2015-06-29 15:09:56martin.pantersetfiles: + locals_doc.03.patch

messages: + msg245942
2015-06-29 07:39:56ncoghlansetmessages: + msg245924
2015-06-29 06:54:23martin.pantersetmessages: + msg245922
2015-01-15 14:59:23r.david.murraysetmessages: + msg234078
2015-01-15 14:25:02martin.pantersetnosy: + martin.panter
messages: + msg234076
2015-01-15 13:09:40r.david.murraysetmessages: + msg234072
2015-01-15 04:44:02ethan.furmansetfiles: + issue17546.stoneleaf.01.patch
versions: + Python 3.5
nosy: + ethan.furman

messages: + msg234049
2013-05-03 02:04:55ezio.melottisetnosy: + ncoghlan

stage: needs patch -> patch review
2013-03-31 09:09:36floxsetnosy: + flox
2013-03-31 05:36:25techtoniksetmessages: + msg185615
2013-03-31 05:03:38r.david.murraysetmessages: + msg185613
title: Document the circumstances where the locals() dict gets updated -> Document the circumstances where the locals() dict get updated
2013-03-30 23:23:25terry.reedysetmessages: + msg185601
2013-03-30 21:53:51r.david.murraysetfiles: + locals_doc.patch

nosy: + r.david.murray
messages: + msg185593

keywords: + patch
2013-03-30 19:31:02eric.araujosetnosy: + eric.araujo
messages: + msg185585
2013-03-30 16:27:29terry.reedysetmessages: + msg185575
2013-03-30 15:28:23nedbatsetmessages: + msg185567
2013-03-30 14:00:03techtoniksetmessages: + msg185558
2013-03-30 05:34:08terry.reedysetmessages: + msg185544
2013-03-30 05:19:26terry.reedysetnosy: + terry.reedy
2013-03-29 06:08:32techtoniksetmessages: + msg185491
2013-03-28 22:51:37eric.snowsetmessages: + msg185473
2013-03-28 12:18:23nedbatsetmessages: + msg185440
2013-03-28 08:12:59georg.brandlsetnosy: + georg.brandl
messages: + msg185405
2013-03-28 06:32:34techtoniksetmessages: + msg185404
2013-03-28 02:09:24eric.snowsetmessages: + msg185399
stage: needs patch
2013-03-28 02:07:08eric.snowlinkissue7083 superseder
2013-03-27 18:02:12nedbatsetnosy: + nedbat
2013-03-27 18:01:42eric.snowsetmessages: + msg185359
2013-03-27 17:55:53eric.snowsetmessages: + msg185358
2013-03-27 16:58:06eric.snowsetmessages: + msg185350
versions: + Python 3.3, Python 3.4
2013-03-27 14:43:12techtoniksetmessages: + msg185339
2013-03-27 14:10:24amaury.forgeotdarcsetmessages: + msg185336
2013-03-27 14:08:35bgailersetnosy: + bgailer

messages: + msg185335
title: Document the circumstances where the locals() dict gets updated -> Document the circumstances where the locals() dict gets updated
2013-03-27 13:48:24techtoniksetmessages: + msg185332
2013-03-27 12:45:05amaury.forgeotdarcsetmessages: + msg185327
2013-03-27 12:03:00techtoniksetmessages: + msg185325
2013-03-27 12:01:07techtoniksetmessages: + msg185324
2013-03-27 10:24:15amaury.forgeotdarcsetnosy: + amaury.forgeotdarc
messages: + msg185321
2013-03-27 10:01:21techtoniksetmessages: + msg185320
2013-03-27 07:14:05rhettingersetassignee: docs@python

nosy: + docs@python
components: + Documentation, - Library (Lib)
title: rename type returned by locals() to livedict -> Document the circumstances where the locals() dict gets updated
2013-03-26 19:14:05eric.snowsetmessages: + msg185290
2013-03-26 17:49:47techtoniksetmessages: + msg185282
2013-03-26 15:28:16eric.snowsetmessages: + msg185276
2013-03-26 07:37:16techtoniksetmessages: + msg185260
2013-03-25 17:25:36eric.snowsetmessages: + msg185216
versions: + Python 2.7, - Python 3.4
2013-03-25 17:24:11eric.snowsetversions: - Python 3.1, Python 2.7, Python 3.2, Python 3.3, Python 3.5
nosy: + eric.snow

messages: + msg185215

type: enhancement
2013-03-25 17:20:11techtonikcreate