Re: [Python-Dev] PEP 567 v2

2018-01-10 Thread Nathaniel Smith
On Tue, Jan 9, 2018 at 2:59 AM, Yury Selivanov wrote: > > >> On Jan 9, 2018, at 11:18 AM, Nathaniel Smith wrote: >> The approach I took in PEP 568 is even simpler, I think. The PEP is a >> few pages long because I wanted to be exhaustive to make sure we >>

Re: [Python-Dev] PEP 567 v2

2018-01-09 Thread Yury Selivanov
> On Jan 9, 2018, at 11:18 AM, Nathaniel Smith wrote: > >> On Thu, Jan 4, 2018 at 9:42 PM, Guido van Rossum wrote: >>> On Thu, Jan 4, 2018 at 7:58 PM, Nathaniel Smith wrote: >>> This does make me think that I should write up a short PEP for

Re: [Python-Dev] PEP 567 v2

2018-01-08 Thread Nathaniel Smith
On Thu, Jan 4, 2018 at 9:42 PM, Guido van Rossum wrote: > On Thu, Jan 4, 2018 at 7:58 PM, Nathaniel Smith wrote: >> This does make me think that I should write up a short PEP for >> extending PEP 567 to add context lookup, PEP 550 style: it can start >> out in

Re: [Python-Dev] PEP 567 v2

2018-01-05 Thread Nathaniel Smith
On Fri, Jan 5, 2018 at 2:43 PM, Chris Jerdonek wrote: > One thing that I think could be contributing to confusion around the > proposed API is that there is a circular relationship between Context > and ContextVar, e.g. ContextVar.get() does a lookup in the current >

Re: [Python-Dev] PEP 567 v2

2018-01-05 Thread Nathaniel Smith
On Thu, Jan 4, 2018 at 4:48 PM, Guido van Rossum wrote: > Your suggestions sound reasonable, but we are now running into a logistical > problem -- I don't want to decide this unilaterally but Yury is on vacation > until Jan 15. That gives us at most 2 weeks for approval of the

Re: [Python-Dev] PEP 567 v2

2018-01-05 Thread Elvis Pranskevichus
On Friday, January 5, 2018 5:43:24 PM EST Chris Jerdonek wrote: > Is there a reason ContextVar needs to be exposed publicly at all? For > example, the API could use string keys like contextvars.get(name) or > Context.get(name) (class method). There could be separate functions > to initialize keys

Re: [Python-Dev] PEP 567 v2

2018-01-05 Thread Nathaniel Smith
On Thu, Jan 4, 2018 at 3:18 PM, Nathaniel Smith wrote: > I think the fix is a little bit cumbersome, but straightforward, and > actually *simplifies* caching. [...] > And then the caching in get() becomes: > > def get(self): > if tstate->current_context != self->last_context:

Re: [Python-Dev] PEP 567 v2

2018-01-05 Thread Guido van Rossum
On Fri, Jan 5, 2018 at 2:43 PM, Chris Jerdonek wrote: > On Fri, Jan 5, 2018 at 8:29 AM, Guido van Rossum wrote: > > On Fri, Jan 5, 2018 at 2:05 AM, Victor Stinner > > > wrote: > >> > >> Currently, Context.get(var) returns

Re: [Python-Dev] PEP 567 v2

2018-01-05 Thread Chris Jerdonek
On Fri, Jan 5, 2018 at 8:29 AM, Guido van Rossum wrote: > On Fri, Jan 5, 2018 at 2:05 AM, Victor Stinner > wrote: >> >> Currently, Context.get(var) returns None when "var in context" is false. >> That's surprising and different than var.get(),

Re: [Python-Dev] PEP 567 v2

2018-01-05 Thread Guido van Rossum
Some inline responses to Paul (I snipped everything I agree with). On Wed, Jan 3, 2018 at 3:34 AM, Paul Moore wrote: > On 28 December 2017 at 06:08, Yury Selivanov > wrote: > > This is a second version of PEP 567. > [...] > > > The notion of

Re: [Python-Dev] PEP 567 v2

2018-01-05 Thread Guido van Rossum
On Fri, Jan 5, 2018 at 3:10 AM, Paul Moore wrote: > On 5 January 2018 at 11:06, Victor Stinner > wrote: > >> Le 5 janv. 2018 11:42 AM, "Paul Moore" a écrit : > >> """ > >> A Context is a mapping from ContextVar objects to

Re: [Python-Dev] PEP 567 v2

2018-01-05 Thread Guido van Rossum
On Fri, Jan 5, 2018 at 2:41 AM, Paul Moore wrote: > On 4 January 2018 at 23:58, Guido van Rossum wrote: > > Do you have a specific proposal for a wording change? PEP 567 describes > > Context as "a read-only mapping, implemented using an immutable >

Re: [Python-Dev] PEP 567 v2

2018-01-05 Thread Guido van Rossum
On Fri, Jan 5, 2018 at 2:05 AM, Victor Stinner wrote: > Currently, Context.get(var) returns None when "var in context" is false. > That's surprising and different than var.get(), especially when var has a > default value. > I don't see the problem. Context.get() is

Re: [Python-Dev] PEP 567 v2

2018-01-05 Thread Paul Moore
On 5 January 2018 at 11:06, Victor Stinner wrote: >> Le 5 janv. 2018 11:42 AM, "Paul Moore" a écrit : >> """ >> A Context is a mapping from ContextVar objects to their values. The >> Context itself exposes the Mapping interface, so cannot be

Re: [Python-Dev] PEP 567 v2

2018-01-05 Thread Victor Stinner
You can only modify a context when it's the current context, so using ContextVar.set() in Context.run(). Victor Le 5 janv. 2018 11:42 AM, "Paul Moore" a écrit : On 4 January 2018 at 23:58, Guido van Rossum wrote: > On Thu, Jan 4, 2018 at 9:27 AM, Paul

Re: [Python-Dev] PEP 567 v2

2018-01-05 Thread Paul Moore
On 4 January 2018 at 23:58, Guido van Rossum wrote: > On Thu, Jan 4, 2018 at 9:27 AM, Paul Moore wrote: >> >> On 4 January 2018 at 15:56, Guido van Rossum wrote: >> > It was get_context() in an earlier version of PEP 567. We changed it to

Re: [Python-Dev] PEP 567 v2

2018-01-05 Thread Victor Stinner
Currently, Context.get(var) returns None when "var in context" is false. That's surprising and different than var.get(), especially when var has a default value. Code: --- import contextvars name = contextvars.ContextVar('name', default='victor') context = contextvars.copy_context() print(name

Re: [Python-Dev] PEP 567 v2

2018-01-04 Thread Guido van Rossum
On Thu, Jan 4, 2018 at 7:58 PM, Nathaniel Smith wrote: > On Thu, Jan 4, 2018 at 6:09 PM, Guido van Rossum wrote: > > However you've not convinced me that it would be better to make Context > > implement the full MutableMapping interface (with `__delitem__`

Re: [Python-Dev] PEP 567 v2

2018-01-04 Thread Greg Ewing
Guido van Rossum wrote: Well, it's not *immutable* (it shouldn't support hash()), but it doesn't follow the MutableMapping protocol -- it only follows the Mapping protocol. That's why I wrote "mapping" with a small "m". If there's a better term for "collection of associations between keys and

Re: [Python-Dev] PEP 567 v2

2018-01-04 Thread Nathaniel Smith
On Thu, Jan 4, 2018 at 6:09 PM, Guido van Rossum wrote: > However you've not convinced me that it would be better to make Context > implement the full MutableMapping interface (with `__delitem__` always > raising). There are use cases for inspecting Context, e.g. a debugger that

Re: [Python-Dev] PEP 567 v2

2018-01-04 Thread Guido van Rossum
On Tue, Jan 2, 2018 at 4:30 PM, Victor Stinner wrote: > Hum, it seems like the specification (API) part of the PEP is polluted by > its implementation. The PEP just require a few minor changes to better > describe the behaviour/API instead of insisting on the read only

Re: [Python-Dev] PEP 567 v2

2018-01-04 Thread Guido van Rossum
Your suggestions sound reasonable, but we are now running into a logistical problem -- I don't want to decide this unilaterally but Yury is on vacation until Jan 15. That gives us at most 2 weeks for approval of the PEP and review + commit of the implementation (

Re: [Python-Dev] PEP 567 v2

2018-01-04 Thread Guido van Rossum
On Thu, Jan 4, 2018 at 4:56 PM, Greg Ewing wrote: > Guido van Rossum wrote: > >> It was get_context() in an earlier version of PEP 567. We changed it to >> copy_context() believing that that would clarify that you get a clone that >> is unaffected by subsequent

Re: [Python-Dev] PEP 567 v2

2018-01-04 Thread Guido van Rossum
On Thu, Jan 4, 2018 at 9:27 AM, Paul Moore wrote: > On 4 January 2018 at 15:56, Guido van Rossum wrote: > > It was get_context() in an earlier version of PEP 567. We changed it to > > copy_context() believing that that would clarify that you get a clone >

Re: [Python-Dev] PEP 567 v2

2018-01-04 Thread Greg Ewing
Guido van Rossum wrote: It was get_context() in an earlier version of PEP 567. We changed it to copy_context() believing that that would clarify that you get a clone that is unaffected by subsequent ContextVar.set() operations (which affect the *current* context rather than the copy you just

Re: [Python-Dev] PEP 567 v2

2018-01-04 Thread Nathaniel Smith
On Thu, Jan 4, 2018 at 8:30 AM, Guido van Rossum wrote: > On Wed, Jan 3, 2018 at 6:35 PM, Nathaniel Smith wrote: >> - Context is a mutable object representing a mapping >> - BUT it doesn't allow mutation through the MutableMapping interface; >> instead, the only

Re: [Python-Dev] PEP 567 v2

2018-01-04 Thread Guido van Rossum
On Wed, Jan 3, 2018 at 6:35 PM, Nathaniel Smith wrote: > On Wed, Jan 3, 2018 at 3:44 PM, Victor Stinner > wrote: > > Ok, I finally got access to a computer and I was able to test the PEP > > 567 implementation: see my code snippet below. > > > > The

Re: [Python-Dev] PEP 567 v2

2018-01-04 Thread Paul Moore
On 4 January 2018 at 15:56, Guido van Rossum wrote: > It was get_context() in an earlier version of PEP 567. We changed it to > copy_context() believing that that would clarify that you get a clone that > is unaffected by subsequent ContextVar.set() operations (which affect the

Re: [Python-Dev] PEP 567 v2

2018-01-04 Thread Guido van Rossum
On Thu, Jan 4, 2018 at 3:25 AM, Paul Moore wrote: > On 4 January 2018 at 00:17, Greg Ewing > wrote: > > Guido van Rossum wrote: > >> > >> contextvars.copy_context().run(func, ) > > > > If contexts are immutable, why is there something > > called

Re: [Python-Dev] PEP 567 v2

2018-01-04 Thread Paul Moore
On 4 January 2018 at 00:17, Greg Ewing wrote: > Guido van Rossum wrote: >> >> contextvars.copy_context().run(func, ) > > > If contexts are immutable, why is there something > called copy_context? Agreed. This was something that bothered me, too. I mentioned it in my

Re: [Python-Dev] PEP 567 v2

2018-01-03 Thread Greg Ewing
Guido van Rossum wrote: contextvars.copy_context().run(func, ) If contexts are immutable, why is there something called copy_context? -- Greg ___ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev

Re: [Python-Dev] PEP 567 v2

2018-01-03 Thread Greg Ewing
Guido van Rossum wrote: There needs to be some way to introspect a Context, for debugging. It could have a read-only introspection interface without having to be a full Mapping. -- Greg ___ Python-Dev mailing list Python-Dev@python.org

Re: [Python-Dev] PEP 567 v2

2018-01-03 Thread Nathaniel Smith
On Wed, Jan 3, 2018 at 3:44 PM, Victor Stinner wrote: > Ok, I finally got access to a computer and I was able to test the PEP > 567 implementation: see my code snippet below. > > The behaviour is more tricky than what I expected. While running > context.run(), the

Re: [Python-Dev] PEP 567 v2

2018-01-03 Thread Victor Stinner
2018-01-04 0:44 GMT+01:00 Victor Stinner : > The behaviour is more tricky than what I expected. While running > context.run(), the context object is out of sync of the "current > context". It's only synchronized again at run() exit. So > ContextVar.set() doesn't

Re: [Python-Dev] PEP 567 v2

2018-01-03 Thread Guido van Rossum
That was actually Yury's original design, but I insisted on a Mapping so you can introspect it. (There needs to be some way to introspect a Context, for debugging.) Again, more later. :-( On Wed, Jan 3, 2018 at 4:44 PM, Victor Stinner wrote: > Ok, I finally got access

Re: [Python-Dev] PEP 567 v2

2018-01-03 Thread Guido van Rossum
Oh, dang, I forgot about this. ContextVar.set() modifies the current Context in-place using a private API. In the PEP, asyncio copies the Context once and then calls run() repeatedly (for each _step call). So run() isn't stateless, it just saves and restores the notion of the current context (in

Re: [Python-Dev] PEP 567 v2

2018-01-03 Thread Victor Stinner
Ok, I finally got access to a computer and I was able to test the PEP 567 implementation: see my code snippet below. The behaviour is more tricky than what I expected. While running context.run(), the context object is out of sync of the "current context". It's only synchronized again at run()

Re: [Python-Dev] PEP 567 v2

2018-01-03 Thread Victor Stinner
2018-01-03 23:01 GMT+01:00 Guido van Rossum : > Heh, you're right, I forgot about that. It should be more like this: > > def run(self, func, *args, **kwds): > old = _get_current_context() > _set_current_context(self) # <--- changed line > try: > return

Re: [Python-Dev] PEP 567 v2

2018-01-03 Thread Guido van Rossum
On Wed, Jan 3, 2018 at 12:32 PM, Glenn Linderman wrote: > On 1/3/2018 11:16 AM, Guido van Rossum wrote: > > Maybe I should clarify again what run() does. Here's how I think of it in > pseudo code: > > def run(self, func, *args, **kwds): > old = _get_current_context() >

Re: [Python-Dev] PEP 567 v2

2018-01-03 Thread Glenn Linderman
On 1/3/2018 11:16 AM, Guido van Rossum wrote: Maybe I should clarify again what run() does. Here's how I think of it in pseudo code: def run(self, func, *args, **kwds):     old = _get_current_context()     new = old.copy()     _set_current_context(new)     try:     return func(*args,

Re: [Python-Dev] PEP 567 v2

2018-01-03 Thread Guido van Rossum
I think decimal is a bit of a red herring, because the entire decimal context is stored as a single thread-local variable (_local.__decimal_context__ in _pydecimal.py, where _local is a global threading.local instance; using "___DECIMAL_CTX__" as a key in the C-level dict of thread-locals in the C

Re: [Python-Dev] PEP 567 v2

2018-01-03 Thread Victor Stinner
> Do you have any use case for modifying a variable inside some context? > numpy, decimal, or some sort of tracing for http requests or async frameworks like asyncio do not need that. Maybe I misunderstood how contextvars is supposed to be used. So let me give you an example. I understand that

Re: [Python-Dev] PEP 567 v2

2018-01-03 Thread Victor Stinner
Victor: > ContextVar would be simpler if the default would be mandatory as well :-) If we modify ContextVar to use None as the default value, the 'default' parameter of ContextVar.get() becomes useless, ContextVar.get() and context[var] behaviour becomes obvious. Token.MISSING could also be

Re: [Python-Dev] PEP 567 v2

2018-01-03 Thread Paul Moore
On 28 December 2017 at 06:08, Yury Selivanov wrote: > This is a second version of PEP 567. Overall, I like the proposal. It's relatively straightforward to follow, and makes sense. One thing I *don't* see in the PEP is an example of how code using thread-local storage

Re: [Python-Dev] PEP 567 v2

2018-01-03 Thread Yury Selivanov
I think we can expose the default property. If it's not set we can return MISSING. Yury Sent from my iPhone > On Jan 3, 2018, at 1:04 PM, Victor Stinner wrote: > > Le 3 janv. 2018 06:38, "Guido van Rossum" a écrit : > But is there a common use

Re: [Python-Dev] PEP 567 v2

2018-01-03 Thread Victor Stinner
Le 3 janv. 2018 06:38, "Guido van Rossum" a écrit : But is there a common use case? For var.get() I'd rather just pass the default or catch the exception if the flow is different. Using ctx[var] is rare (mostly for printing contexts, and perhaps for explaining var.get()). I

Re: [Python-Dev] PEP 567 v2

2018-01-03 Thread Victor Stinner
Le 3 janv. 2018 06:34, "Guido van Rossum" a écrit : I think the issue here is a bit different than Yury's response suggests -- it's more like how a variable containing an immutable value (e.g. a string) can be modified, e.g. x = 'a' x += 'b' In our case the *variable* is the

Re: [Python-Dev] PEP 567 v2

2018-01-03 Thread Yury Selivanov
> On Jan 3, 2018, at 12:26 PM, Victor Stinner wrote: > > Le 3 janv. 2018 06:05, "Yury Selivanov" a écrit : > tuples in Python are immutable, but you can have a tuple with a dict as its > single element. The tuple is immutable, the dict is

Re: [Python-Dev] PEP 567 v2

2018-01-03 Thread Victor Stinner
Le 3 janv. 2018 06:05, "Yury Selivanov" a écrit : tuples in Python are immutable, but you can have a tuple with a dict as its single element. The tuple is immutable, the dict is mutable. At the C level we have APIs that can mutate a tuple though. Now, tuple is not a

Re: [Python-Dev] PEP 567 v2

2018-01-02 Thread Guido van Rossum
Do you see any average Python users on this thread? We are trying to pick the PEP apart from the POV of having to use the complicated parts of the API in a framework. Victor's questions are reasonable. On Tue, Jan 2, 2018 at 10:13 PM, Yury Selivanov wrote: > I don't

Re: [Python-Dev] PEP 567 v2

2018-01-02 Thread Guido van Rossum
On Tue, Jan 2, 2018 at 4:51 PM, Victor Stinner wrote: > Why ContextVar.reset(token) does nothing at the second call with the same > token? What is the purpose of Token._used? I guess that there is an use > case to justify this behaviour. > > reset() should have a

Re: [Python-Dev] PEP 567 v2

2018-01-02 Thread Guido van Rossum
On Tue, Jan 2, 2018 at 4:45 PM, Victor Stinner wrote: > Le 2 janv. 2018 18:57, "Guido van Rossum" a écrit : > > Oh, the "Specification" section in the PEP is too brief on several of > these subjects. It doesn't really specify what var.get() does if

Re: [Python-Dev] PEP 567 v2

2018-01-02 Thread Guido van Rossum
On Tue, Jan 2, 2018 at 5:30 PM, Victor Stinner wrote: > Hum, it seems like the specification (API) part of the PEP is polluted by > its implementation. The PEP just require a few minor changes to better > describe the behaviour/API instead of insisting on the read only

Re: [Python-Dev] PEP 567 v2

2018-01-02 Thread Yury Selivanov
I don't want to expose a SetContext operation because of, again, potential incompatibility with PEP 550, where generators expect to fully control push/pop context operation. Second, Context.run is 100% enough for *any* async framework to add support for PEP 567. And because the PEP is focused

Re: [Python-Dev] PEP 567 v2

2018-01-02 Thread Yury Selivanov
On Wed, Jan 3, 2018 at 3:04 AM Victor Stinner wrote: > What is the behaviour of ContextVar.reset(token) if the token was created > from a different variable? Raise an exception? > > token = var1.set("value") > var2.reset(token) > > The PEP states that Token.var only

Re: [Python-Dev] PEP 567 v2

2018-01-02 Thread Yury Selivanov
On Wed, Jan 3, 2018 at 2:36 AM Victor Stinner wrote: > > I would really like to invite more people to review this PEP! I expect > I'll be accepting it in the next two weeks, but it needs to go through more > rigorous review. > > I read again the PEP and I am still very

Re: [Python-Dev] PEP 567 v2

2018-01-02 Thread Victor Stinner
Hum, it seems like the specification (API) part of the PEP is polluted by its implementation. The PEP just require a few minor changes to better describe the behaviour/API instead of insisting on the read only internal thing which is specific to the proposed implementation which is just one

Re: [Python-Dev] PEP 567 v2

2018-01-02 Thread Victor Stinner
What is the behaviour of ContextVar.reset(token) if the token was created from a different variable? Raise an exception? token = var1.set("value") var2.reset(token) The PEP states that Token.var only exists for debug or introspection. Victor Le 3 janv. 2018 00:51, "Victor Stinner"

Re: [Python-Dev] PEP 567 v2

2018-01-02 Thread Victor Stinner
PEP: "int PyContext_Enter(PyContext *) and int PyContext_Exit(PyContext *) allow to set and restore the context for the current OS thread." What is the difference between Enter and Exit? Why not having a single Py_SetContext() function? Victor ___

Re: [Python-Dev] PEP 567 v2

2018-01-02 Thread Victor Stinner
Why ContextVar.reset(token) does nothing at the second call with the same token? What is the purpose of Token._used? I guess that there is an use case to justify this behaviour. reset() should have a result: true if the variable was restored to its previous state, false if reset() did nothing

Re: [Python-Dev] PEP 567 v2

2018-01-02 Thread Victor Stinner
Le 2 janv. 2018 18:57, "Guido van Rossum" a écrit : Oh, the "Specification" section in the PEP is too brief on several of these subjects. It doesn't really specify what var.get() does if the value is not set, nor does it even mention var.get() except in the code examples for

Re: [Python-Dev] PEP 567 v2

2018-01-02 Thread Victor Stinner
> I would really like to invite more people to review this PEP! I expect I'll be accepting it in the next two weeks, but it needs to go through more rigorous review. I read again the PEP and I am still very confused by Context.run(). The PEP states multiple times that a context is immutable: *

Re: [Python-Dev] PEP 567 v2

2018-01-02 Thread Guido van Rossum
Oh, the "Specification" section in the PEP is too brief on several of these subjects. It doesn't really specify what var.get() does if the value is not set, nor does it even mention var.get() except in the code examples for var.reset(). It's also subtle that ctx[var] returns the default (if there

Re: [Python-Dev] PEP 567 v2

2017-12-28 Thread Victor Stinner
NLe 28 déc. 2017 11:20 AM, "Nathaniel Smith" a écrit : On Thu, Dec 28, 2017 at 1:51 AM, Victor Stinner wrote: > var = ContextVar('var', default=42) > > and: > > var = ContextVar('var') > var.set (42) > > behaves the same, no? No, they're different. The

Re: [Python-Dev] PEP 567 v2

2017-12-28 Thread Guido van Rossum
Keep MISSING. On Dec 28, 2017 8:44 AM, "Yury Selivanov" wrote: > On Thu, Dec 28, 2017 at 4:51 AM, Victor Stinner > wrote: > > Hi, > > > > I like the new version of the PEP using "read only mapping" and > > copy_context(). It's easier to

Re: [Python-Dev] PEP 567 v2

2017-12-28 Thread Yury Selivanov
On Thu, Dec 28, 2017 at 4:51 AM, Victor Stinner wrote: > Hi, > > I like the new version of the PEP using "read only mapping" and > copy_context(). It's easier to understand. Thanks, Victor! > > I'm ok with seeing a context as a mapping, but I am confused about a

Re: [Python-Dev] PEP 567 v2

2017-12-28 Thread Yury Selivanov
On Thu, Dec 28, 2017 at 5:28 AM, Chris Jerdonek wrote: > I have a couple basic questions around how this API could be used in > practice. Both of my questions are for the Python API as applied to Tasks in > asyncio. > > 1) Would this API support looking up the value of a

Re: [Python-Dev] PEP 567 v2

2017-12-28 Thread Chris Jerdonek
I have a couple basic questions around how this API could be used in practice. Both of my questions are for the Python API as applied to Tasks in asyncio. 1) Would this API support looking up the value of a context variable for **another** Task? For example, if you're managing multiple tasks

Re: [Python-Dev] PEP 567 v2

2017-12-28 Thread Nathaniel Smith
On Thu, Dec 28, 2017 at 1:51 AM, Victor Stinner wrote: > var = ContextVar('var', default=42) > > and: > > var = ContextVar('var') > var.set (42) > > behaves the same, no? No, they're different. The second sets the value in the current context. The first sets the value

Re: [Python-Dev] PEP 567 v2

2017-12-28 Thread Victor Stinner
Hi, I like the new version of the PEP using "read only mapping" and copy_context(). It's easier to understand. I'm ok with seeing a context as a mapping, but I am confused about a context variable considered as a mapping item. I still see a context variable as a variable, so something which has

[Python-Dev] PEP 567 v2

2017-12-27 Thread Yury Selivanov
This is a second version of PEP 567. A few things have changed: 1. I now have a reference implementation: https://github.com/python/cpython/pull/5027 2. The C API was updated to match the implementation. 3. The get_context() function was renamed to copy_context() to better reflect what it is