classification
Title: Add the @cached_property decorator
Type: enhancement Stage: patch review
Components: Library (Lib) Versions: Python 3.8
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: Omer.Katz, alex, carljm, eric.araujo, madison.may, ncoghlan, pitrou, pydanny, r.david.murray, rhettinger, serhiy.storchaka, sir-sigurd
Priority: normal Keywords: patch

Created on 2014-04-03 10:28 by Omer.Katz, last changed 2018-06-17 10:20 by sir-sigurd.

Files
File name Uploaded Description Edit
cached_property.diff carljm, 2016-11-10 21:17 diff to add cached_property decorator, with tests and docs review
cached_property.diff carljm, 2016-11-11 20:18 same as previous, with doc note and better error message for object with __slots__ review
cached_property.diff carljm, 2016-11-11 21:52 same as previous, but thread-safe review
Pull Requests
URL Status Linked Edit
PR 6982 open carljm, 2018-05-19 04:55
Messages (41)
msg215439 - (view) Author: Omer Katz (Omer.Katz) Date: 2014-04-03 10:28
cached properties are widely used in various prominent Python projects such as Django and pip (and many more).
They are not very complicated and there are proven implementation out there. Unfortunately there are way too many of them. This situation leads me to suggest adding it to the builtins.

Possible benefits:
* Implementation in C can improve caching performance
* Standardized implementation that can be used anywhere
msg215488 - (view) Author: Madison May (madison.may) * Date: 2014-04-04 03:42
There's currently an example of a cached property decorator implementation in the wiki, although it doesn't leverage functools:
https://wiki.python.org/moin/PythonDecoratorLibrary#Cached_Properties
msg215564 - (view) Author: Éric Araujo (eric.araujo) * (Python committer) Date: 2014-04-04 21:11
It could make sense to add clean, working recipes to e.g. the functools documentation.  The cached_property in the wiki uses a TTL, other like Pyramid’s reify decorator make properties that ensure the fget function is called only once per instance, and there may be subtly different variants out there.  I don’t know if there’s a universally useful variant that should be added to the sdlib right now.  (I don’t think a C implementation is needed.)

On a related note, the Python docs about desciptors may be missing entry-level explanations, as described here: http://me.veekun.com/blog/2012/05/23/python-faq-descriptors/
msg215654 - (view) Author: Omer Katz (Omer.Katz) Date: 2014-04-06 10:31
The default implementation should simple:
Once the property is accessed for the first time calculate the result and
never calculate again.
It's what both Django & pip uses.
You can add an optional TTL.
There aren't any other features I can come up with that are common enough.
If needed, one can inherit from cached_property and do whatever is needed.
Eric, Why don't you think a C implementation is needed? It's a simple
operation for sure but it is meant to increase runtime efficiency.

2014-04-05 1:11 GMT+04:00 Éric Araujo <report@bugs.python.org>:

>
> Éric Araujo added the comment:
>
> It could make sense to add clean, working recipes to e.g. the functools
> documentation.  The cached_property in the wiki uses a TTL, other like
> Pyramid's reify decorator make properties that ensure the fget function is
> called only once per instance, and there may be subtly different variants
> out there.  I don't know if there's a universally useful variant that
> should be added to the sdlib right now.  (I don't think a C implementation
> is needed.)
>
> On a related note, the Python docs about desciptors may be missing
> entry-level explanations, as described here:
> http://me.veekun.com/blog/2012/05/23/python-faq-descriptors/
>
> ----------
> nosy: +eric.araujo, rhettinger
>
> _______________________________________
> Python tracker <report@bugs.python.org>
> <http://bugs.python.org/issue21145>
> _______________________________________
>
msg215655 - (view) Author: Omer Katz (Omer.Katz) Date: 2014-04-06 10:49
I just checked and werkzeug uses the same implementation as Django & pip.

2014-04-06 14:31 GMT+04:00 Omer Katz <report@bugs.python.org>:

>
> Omer Katz added the comment:
>
> The default implementation should simple:
> Once the property is accessed for the first time calculate the result and
> never calculate again.
> It's what both Django & pip uses.
> You can add an optional TTL.
> There aren't any other features I can come up with that are common enough.
> If needed, one can inherit from cached_property and do whatever is needed.
> Eric, Why don't you think a C implementation is needed? It's a simple
> operation for sure but it is meant to increase runtime efficiency.
>
> 2014-04-05 1:11 GMT+04:00 Éric Araujo <report@bugs.python.org>:
>
> >
> > Éric Araujo added the comment:
> >
> > It could make sense to add clean, working recipes to e.g. the functools
> > documentation.  The cached_property in the wiki uses a TTL, other like
> > Pyramid's reify decorator make properties that ensure the fget function
> is
> > called only once per instance, and there may be subtly different variants
> > out there.  I don't know if there's a universally useful variant that
> > should be added to the sdlib right now.  (I don't think a C
> implementation
> > is needed.)
> >
> > On a related note, the Python docs about desciptors may be missing
> > entry-level explanations, as described here:
> > http://me.veekun.com/blog/2012/05/23/python-faq-descriptors/
> >
> > ----------
> > nosy: +eric.araujo, rhettinger
> >
> > _______________________________________
> > Python tracker <report@bugs.python.org>
> > <http://bugs.python.org/issue21145>
> > _______________________________________
> >
>
> ----------
>
> _______________________________________
> Python tracker <report@bugs.python.org>
> <http://bugs.python.org/issue21145>
> _______________________________________
>
msg218750 - (view) Author: Daniel Greenfeld (pydanny) Date: 2014-05-18 18:11
For what it's worth, I just released cached-property on PyPI and someone suggested I join the discussion here. 

Package: https://pypi.python.org/pypi/cached-property
Repo: https://github.com/pydanny/cached-property

Notes:

* 92% test coverage, albeit with a simple, arguably naive test.
* I plan to increase the coverage to 100%.
* I'm not entirely sure where to give credit for the original implementation. Right now I think it's Bottle, but I'm not certain. See  https://github.com/pydanny/cached-property/issues/1
msg218760 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2014-05-18 22:36
Does this work for you?

>>> class X:
...   @property
...   @functools.lru_cache(None)
...   def get_x(self):
...     print("computing")
...     return 5
... 
>>> x = X()
>>> x.get_x
computing
5
>>> x.get_x
5
msg218761 - (view) Author: Alex Gaynor (alex) * (Python committer) Date: 2014-05-18 22:39
Will that implementation cause a memory leak? Won't the lru_cache have a dict mapping {self: result}, meaning that `self` will live forever, instead of storing result in self.__dict__, where the lifetimes are correct.
msg218762 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2014-05-18 22:40
> Will that implementation cause a memory leak? Won't the lru_cache have
> a dict mapping {self: result}, meaning that `self` will live forever,
> instead of storing result in self.__dict__, where the lifetimes are
> correct.

Oh, you're right. Sorry for the noise.
msg260308 - (view) Author: Omer Katz (Omer.Katz) Date: 2016-02-15 11:11
Can we make this happen for 3.6?
msg260312 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2016-02-15 13:56
May be. If somebody provide a patch.
msg260319 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2016-02-15 16:33
I like the idea of an helper to build a property on-demand, but I dislike the TTL idea, it seems too specific.

If you need TTL, implement your own decorator, or use a regular property and implement your own logic there.
msg260321 - (view) Author: Omer Katz (Omer.Katz) Date: 2016-02-15 17:45
Most implementations these days support TTL because they require it.
The whole point is to remove the need to reimplement such basic
functionality over and over.

‫בתאריך יום ב׳, 15 בפבר׳ 2016 ב-18:33 מאת ‪STINNER Victor‬‏ <‪
report@bugs.python.org‬‏>:‬

>
> STINNER Victor added the comment:
>
> I like the idea of an helper to build a property on-demand, but I dislike
> the TTL idea, it seems too specific.
>
> If you need TTL, implement your own decorator, or use a regular property
> and implement your own logic there.
>
> ----------
>
> _______________________________________
> Python tracker <report@bugs.python.org>
> <http://bugs.python.org/issue21145>
> _______________________________________
>
msg260322 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2016-02-15 17:51
The TTL idea is completely outlandish in a general-purpose library. Let's keep things simple and not try to build a kitchen-sink decorator.
msg260323 - (view) Author: Omer Katz (Omer.Katz) Date: 2016-02-15 17:53
In that case, most of the users won't use the standard library
@cached_property anyway since they require it.

On Mon, Feb 15, 2016, 19:51 Antoine Pitrou <report@bugs.python.org> wrote:

>
> Antoine Pitrou added the comment:
>
> The TTL idea is completely outlandish in a general-purpose library. Let's
> keep things simple and not try to build a kitchen-sink decorator.
>
> ----------
>
> _______________________________________
> Python tracker <report@bugs.python.org>
> <http://bugs.python.org/issue21145>
> _______________________________________
>
msg260324 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2016-02-15 17:54
I'm sure many people don't need a TTL on a cached property. Please stop arguing about that.
msg260326 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2016-02-15 18:05
"Most implementations these days support TTL because they require it."

I used this pattern a lot in my old Hachoir project, but I never needed the TTL thing. In my case, data come from the disk and are never invalidated.

Example with the description property:

https://bitbucket.org/haypo/hachoir3/src/9ae394a18d74bb20b5562964e57074e5624132f5/hachoir/field/field.py?at=default&fileviewer=file-view-default#field.py-79
msg280534 - (view) Author: Carl Meyer (carljm) * Date: 2016-11-10 18:48
I've used the cached_property pattern across many different projects, and never yet wanted a TTL. The simple "cache for the lifetime of the instance" behavior is easy to implement, easy to understand, and useful for a wide range of scenarios where instances are effectively immutable. +1 for adding this to the stdlib (not just as a docs recipe); I'll see about providing a patch.
msg280541 - (view) Author: Carl Meyer (carljm) * Date: 2016-11-10 21:17
Attaching a patch with the simplest version of cached_property (tehnique is not original, similar code is found in Django, Bottle, Flask, the cached_property lib, and many other places).
msg280542 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2016-11-10 21:20
The decorator should support classes with __slots__.
msg280547 - (view) Author: Carl Meyer (carljm) * Date: 2016-11-10 21:50
How do you propose that slots should be supported?

Part of the value of cached_property is that cached access is a normal Python attribute access with no function call overhead. I am not interested in adding support for slots if it loses that benefit. I would not use such an implementation myself.

I may be missing some option, but I can't see how to add slots support without losing that benefit, because it requires the ability to store an instance attribute under the same name as the descriptor, taking advantage of the fact that instance dict overrides a non-data descriptor.

This implementation of cached_property has been in wide use in multiple very popular projects for many years. The fact that none of those implementations have ever needed to add slots support suggests that it isn't actually that important.

If you have an idea for how to support slots without making cached_property less valuable for the common case, please share it and I am willing to implement it.

Otherwise, I propose that this implementation which is already proved in wide usage should be added to the stdlib; I can add a documentation note that objects with slots are not supported. If there is demand for cached_property_with_slots, it can be added separately.
msg280597 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2016-11-11 16:55
Carl's patch looks good to me, but my one request in relation to the __slots__ situation would be to give it a custom error message better indicating that lazy initialization of pre-assigned instance slots isn't supported.

Currently that case just lets the underlying AttributeError escape, which is going to be thoroughly cryptic for folks that try it and may look like an accidental oversight rather than a deliberate design decision:

    >>> class NoDict:
    ...     __slots__ = ()
    ... 
    >>> NoDict().__dict__
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'NoDict' object has no attribute '__dict__'

Suggested error message:

    TypeError: No '__dict__' attribute on 'objtype' instance to cache 'attrname' property.

Essentially, this line:

    val = instance.__dict__[self.func.__name__] = self.func(instance)

would become:

    attrname = self.func.__name__
    try:
        cache = instance.__dict__
    except AttributeError:
        msg = f"No '__dict__' attribute on {type(instance).__name__!r} instance to cache {attrname!r} property."
        raise TypeError(msg) from None
    val = cache[attrname] = self.func(instance)


I believe a future C implementation could potentially be reworked to be __slots__ compatible, but I'd have to go read the source code to be sure, and I don't think that's necessary.

Note: the class machinery itself already detects actual name conflicts between slot and method definitions:

    >>> class SlotConflict:
    ...     __slots__ = ("attr")
    ...     @property
    ...     def attr(self):
    ...         return 42
    ... 
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: 'attr' in __slots__ conflicts with class variable

The requested runtime check for the `__dict__` AttributeError covers the case where __slots__ is defined, and the cached property *isn't* listed as one of the instance attributes, but neither is __dict__.
msg280601 - (view) Author: Carl Meyer (carljm) * Date: 2016-11-11 17:09
Makes sense, Nick, thanks. The current error message for that situation is pretty cryptic indeed. I'll update the patch with your suggestion. Do you think a documentation note about slots is also warranted?
msg280602 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2016-11-11 17:45
Please no need to rush. We have 1.5 years to do this right.

I believe supporting __slots__ is very important. But this is not easy task. Seems this requires C implementation.

We should also design the behavior in case of setting or deleting cached property.

How about just methods without arguments? Some APIs use methods without arguments instead of properties. Wouldn't be better to design a decorator that memoizes both properties and methods without arguments?
msg280608 - (view) Author: Carl Meyer (carljm) * Date: 2016-11-11 20:25
Uploaded a patch updated per Nick's comment.

Not opposed to waiting to see if someone is motivated to implement a version in C that supports __slots__, but if that doesn't happen by the Python 3.7 feature deadline, I don't think it should block this proven version.

It also occurred to me that we could probably support __slots__ in pure Python without harming the non-slots case by implementing a fallback cache in the descriptor itself, keyed by instance in a WeakKeyDictionary. I don't love having the behavior differ so much between the slots and non-slots case, but maybe it's better than not supporting slots at all.

Re setting and deleting: under the current patch, if you set or delete a cached property, you set or delete the cached value. I think this is fine and useful behavior, but it could perhaps be added explicitly to the documentation.
msg280609 - (view) Author: Carl Meyer (carljm) * Date: 2016-11-11 20:26
(We wouldn't be able to match the set/delete behavior in a slots-supporting fallback implemented in Python.)
msg280610 - (view) Author: Daniel Greenfeld (pydanny) Date: 2016-11-11 20:28
I'm delighted to see a patch submitted, but I'm concerned that it isn't thread safe. This was implemented in the cached-property package I maintain:

* https://github.com/pydanny/cached-property/issues/6
* https://github.com/pydanny/cached-property/pull/9
* https://github.com/pydanny/cached-property#working-with-threads
msg280615 - (view) Author: Carl Meyer (carljm) * Date: 2016-11-11 21:52
Thanks, Danny. Uploaded a version of the patch that adds thread-safety (with a test). Unlike in your lib, I didn't make it a separate version of the decorator; since the lock is not checked on cached access, its slight overhead on the initial computation is probably not an issue, likely outweighed by the cost of the computation itself.

If someone decides to pursue a C version with slots support, hopefully at least these tests are still useful :-)
msg280616 - (view) Author: Carl Meyer (carljm) * Date: 2016-11-11 21:53
Speaking of this hypothetical C version, what's the current policy on shipping stdlib C code that can't be emulated in pure Python? (I'm thinking of e.g. PyPy).
msg280655 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2016-11-12 12:15
I realised that PEP 487's __set_name__ can be used to detect the `__slots__` conflict at class definition time rather than on first lookup:

    def __set_name__(self, owner, name):
        try:
            slots = owner.__slots__
        except AttributeError:
            return
        if "__dict__" not in slots:
            msg = f"'__dict__' attribute required on {owner.__name__!r} instances to cache {name!r} property."
            raise TypeError(msg)

It also occurred to me that at the expense of one level of indirection in the runtime lookup, PEP 487's __set_name__ hook and a specified naming convention already permits a basic, albeit inefficient, "cached_slot" implementation:

class cached_slot:
    def __init__(self, func):
        self.func = func
        self.cache_slot = func.__name__ + "_cache"
        self.__doc__ = func.__doc__
        self._lock = RLock()

    def __set_name__(self, owner, name):
        try:
            slots = owner.__slots__
        except AttributeError:
            msg = f"cached_slot requires '__slots__' on {owner!r}"
            raise TypeError(msg) from None
        if self.cache_slot not in slots:
            msg = f"cached_slot requires {self.cache_slot!r} slot on {owner!r}"
            raise TypeError(msg) from None

    def __get__(self, instance, cls=None):
        if instance is None:
            return self
        try:
            return getattr(instance, self.cache_slot)
        except AttributeError:
            # Cache not initialised yet, so proceed to double-checked locking
            pass
        with self.lock:
            # check if another thread filled cache while we awaited lock
            try:
                return getattr(instance, self.cache_slot)
            except AttributeError:
                # Cache still not initialised yet, so initialise it
                setattr(instance, self.cache_slot, self.func(instance))
        return getattr(instance, self.cache_slot)

    def __set__(self, instance, value):
        setattr(instance, self.cache_slot, value)

    def __delete__(self, instance):
        delattr(instance, self.cache_slot)

It can't be done as a data descriptor though (and can't be done efficiently in pure Python), so I don't think it makes sense to try to make cached_property itself work implicitly with both normal attributes and slot entries - instead, cached_property can handle the common case as simply and efficiently as possible, and the cached_slot case can be either handled separately or else not at all.

The "don't offer cached_slot at all" argument would be that, given slots are used for memory-efficiency when handling large numbers of objects and lazy initialization is used to avoid unnecessary computations, a "lazily initialised slot" can be viewed as "64 bits of frequently wasted space", and hence we can expect demand for the feature to be incredibly low (and the community experience to date bears out that expectation).
msg280657 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2016-11-12 12:35
Having just said that I don't see much use for lazily initialized slots, it does occur to me that __weakref__ is essentially such a slot, and __dict__ itself could usefully be such a slot for types where instances mostly have a fixed set of attributes, but still allow for arbitrary additional attributes at runtime.

However, I do think any such proposal should be considered as its own issue, rather than being treated as part of this one - the assumed absence of the instance dict creates too many differences in the design trade-offs involved and the potential use cases.
msg316535 - (view) Author: Carl Meyer (carljm) * Date: 2018-05-14 16:30
> I don't think it makes sense to try to make cached_property itself work implicitly with both normal attributes and slot entries - instead, cached_property can handle the common case as simply and efficiently as possible, and the cached_slot case can be either handled separately or else not at all.

So it sounds like the current approach here is good to move forward? If I update the patch during the PyCon sprints, we could merge it?
msg316643 - (view) Author: Omer Katz (Omer.Katz) Date: 2018-05-15 11:59
I believe so.
Let's do it :)

‫בתאריך יום ב׳, 14 במאי 2018 ב-19:30 מאת ‪Carl Meyer‬‏ <‪
report@bugs.python.org‬‏>:‬

>
> Carl Meyer <carl@oddbird.net> added the comment:
>
> > I don't think it makes sense to try to make cached_property itself work
> implicitly with both normal attributes and slot entries - instead,
> cached_property can handle the common case as simply and efficiently as
> possible, and the cached_slot case can be either handled separately or else
> not at all.
>
> So it sounds like the current approach here is good to move forward? If I
> update the patch during the PyCon sprints, we could merge it?
>
> ----------
>
> _______________________________________
> Python tracker <report@bugs.python.org>
> <https://bugs.python.org/issue21145>
> _______________________________________
>
msg316745 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2018-05-15 23:55
FWIW, over the past decade, I've used variants of CachedProperty a number of times and have often had issues that later required messing with its internals (needing a way to invalidate or clear the cache, mock patching the underlying function for testing, consistency between multiple cached properties cached in different threads, inability to run the method through a debugger, inadvertently killing logging or other instrumentation, moving the cache valued from an instance variables to an external weakref dictionary etc).

I proposed the idea of a CachedProperty in descriptor tutorials over a decade ago.  Since then, I've grown wary of the idea of making them available for general use.  Instead, we're better with a recipe that someone can use to build their understanding and then customize as necessary.  The basic recipe is simple so there isn't much of a value add by putting this in the standard library.

If we want to add another property() variant, the one I've had the best luck with is CommonProperty() which lets you re-use the same getter and setter methods for multiple properties (the name of the property variable gets passed in as the first argument).
msg316760 - (view) Author: Carl Meyer (carljm) * Date: 2018-05-16 03:13
> a way to invalidate or clear the cache

This is already supported by the simple implementation in the patch, it's spelled `del obj.the_cached_property`.

> mock patching the underlying function for testing

This is easy to do with the current implementation, you can replace the cached-property descriptor on the class with `mock.patch`.

> consistency between multiple cached properties cached in different threads

The patch attached here is already thread-safe and will be consistent between threads.

> inability to run the method through a debugger

If you `s` in the Python debugger on a line where a property or cached property is accessed, you will step into the decorated method. I've done this often, so I'm not sure what the issue would be here.

> moving the cache valued from an instance variables to an external weakref dictionary

This would be a totally different descriptor that doesn't share much implementation with the one proposed here, so I don't see how providing the common version inhibits anyone from writing something different they need for their case.

> The basic recipe is simple so there isn't much of a value add by putting this in the standard library.

It's simple once you understand what it does, but it's quite subtle in the way it relies on priority order of instance-dict attributes vs non-data descriptors.

My experience over the past decade is different from yours; I've found that the simple `cached_property` proposed here is widely and frequently useful (basically it should be the preferred approach anytime an object which is intended to be immutable after construction has some calculated properties based on its other attributes), and additional complexity is rarely if ever needed. I think the wide usage of the version proposed here (without extensions) in code in the wild bears this out. Likely a main reason there hasn't been a stronger push to include this in the standard library sooner is that so many people are just using it from `django.utils.functional.cached_property` today.
msg316851 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2018-05-16 19:05
I agree this would be a useful addition to the stdlib.  The code might seem reasonably short, but implementing new descriptors is an advanced topic (I'd rather avoid it myself).
msg317096 - (view) Author: Carl Meyer (carljm) * Date: 2018-05-19 04:59
Sent a PR with the patch.

Nick, I tried your `__set_name__` proposal to get an earlier error in case of an object with slots, but it has the downside that Python seems to always raise a new chained exception if `__set_name__` raises any exception. So instead of getting a clear error, you get an opaque one about "error raised when calling __set_name__ on...", and you have to scroll up to see the real error message. I felt that this was too much usability regression and not worth the benefit of raising the error sooner. Let me know if you feel otherwise.
msg317097 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2018-05-19 05:38
I think it would make sense to remove the exception wrapping from the __set_name__ calls - I don't think we're improving the ease of understanding the tracebacks by converting everything to a generic RuntimeError, and we're hurting the UX of descriptor validation cases like this one.

[1] https://github.com/python/cpython/blob/master/Objects/typeobject.c#L7263
msg317100 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2018-05-19 05:41
I filed https://bugs.python.org/issue33576 to cover removing the exception wrapping from __set_name__ errors.
msg317101 - (view) Author: Carl Meyer (carljm) * Date: 2018-05-19 05:42
Makes sense to me. Sounds like a separate issue and PR; I filed issue33577 and will work on a patch.
msg317103 - (view) Author: Carl Meyer (carljm) * Date: 2018-05-19 05:43
Oops, never mind; closed mine as dupe.
History
Date User Action Args
2018-06-17 10:20:23sir-sigurdsetnosy: + sir-sigurd
2018-05-19 05:43:49carljmsetmessages: + msg317103
2018-05-19 05:42:21carljmsetmessages: + msg317101
2018-05-19 05:41:51ncoghlansetmessages: + msg317100
2018-05-19 05:38:03ncoghlansetmessages: + msg317097
2018-05-19 04:59:10carljmsetmessages: + msg317096
2018-05-19 04:55:25carljmsetstage: patch review
pull_requests: + pull_request6636
2018-05-19 00:33:03vstinnersetnosy: - vstinner
2018-05-16 19:05:05pitrousetmessages: + msg316851
2018-05-16 03:13:03carljmsetmessages: + msg316760
2018-05-15 23:55:40rhettingersetmessages: + msg316745
versions: + Python 3.8, - Python 3.7
2018-05-15 11:59:34Omer.Katzsetmessages: + msg316643
2018-05-14 16:30:58carljmsetmessages: + msg316535
2016-11-12 12:35:08ncoghlansetmessages: + msg280657
2016-11-12 12:15:33ncoghlansetmessages: + msg280655
2016-11-11 21:53:41carljmsetmessages: + msg280616
2016-11-11 21:52:12carljmsetfiles: + cached_property.diff

messages: + msg280615
2016-11-11 20:28:39pydannysetmessages: + msg280610
2016-11-11 20:26:16carljmsetmessages: + msg280609
2016-11-11 20:25:31carljmsetmessages: + msg280608
2016-11-11 20:18:43carljmsetfiles: + cached_property.diff
2016-11-11 17:45:07serhiy.storchakasetmessages: + msg280602
2016-11-11 17:09:08carljmsetmessages: + msg280601
2016-11-11 16:55:50ncoghlansetmessages: + msg280597
2016-11-11 05:52:41rhettingersetnosy: + ncoghlan
2016-11-10 21:50:19carljmsetmessages: + msg280547
2016-11-10 21:20:50serhiy.storchakasetmessages: + msg280542
2016-11-10 21:17:19carljmsetfiles: + cached_property.diff
versions: + Python 3.7, - Python 3.6
messages: + msg280541

components: + Library (Lib)
keywords: + patch
2016-11-10 18:48:57carljmsetnosy: + carljm
messages: + msg280534
2016-02-15 18:05:41vstinnersetmessages: + msg260326
2016-02-15 17:54:23pitrousetmessages: + msg260324
2016-02-15 17:53:35Omer.Katzsetmessages: + msg260323
2016-02-15 17:51:49pitrousetmessages: + msg260322
2016-02-15 17:45:16Omer.Katzsetmessages: + msg260321
2016-02-15 16:33:55vstinnersetmessages: + msg260319
2016-02-15 13:56:19serhiy.storchakasetmessages: + msg260312
2016-02-15 11:11:20Omer.Katzsetmessages: + msg260308
versions: + Python 3.6, - Python 3.5
2014-05-18 22:40:23pitrousetmessages: + msg218762
2014-05-18 22:39:12alexsetnosy: + alex
messages: + msg218761
2014-05-18 22:36:55pitrousetnosy: + pitrou, serhiy.storchaka
messages: + msg218760
2014-05-18 18:11:48pydannysetnosy: + pydanny
messages: + msg218750
2014-04-06 16:22:30r.david.murraysetnosy: + r.david.murray
2014-04-06 10:49:45Omer.Katzsetmessages: + msg215655
2014-04-06 10:31:33Omer.Katzsetmessages: + msg215654
2014-04-04 21:11:25eric.araujosetnosy: + rhettinger, eric.araujo
messages: + msg215564
2014-04-04 03:42:29madison.maysetnosy: + madison.may
messages: + msg215488
2014-04-03 11:39:42vstinnersetnosy: + vstinner
2014-04-03 10:28:52Omer.Katzcreate