Issue 25843: code_richcompare() don't use constant type when comparing code constants (original) (raw)

Created on 2015-12-11 19:23 by Tijs Van Oevelen, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (53)

msg256229 - (view)

Author: Tijs Van Oevelen (Tijs Van Oevelen)

Date: 2015-12-11 19:23

The bug is described on Stack Overflow in length:

http://stackoverflow.com/questions/34100732/unexpected-output-using-pythons-ternary-operator-in-combination-with-lambda

msg256230 - (view)

Author: R. David Murray (r.david.murray) * (Python committer)

Date: 2015-12-11 19:33

For reference, the minimal reproducer is:

f1, f2 = lambda: 1, lambda: 1.0 f2() 1

The cause (according to the answer in the link) is that the two lambda's incorrectly compare as equal and end up sharing the same code object...one of the inequality checks is line number, so this only happens when the lambdas are on the same line.

Aside: it would be helpful if people would post bug summaries instead of just linking to an outside article. The link is of course very valuable information, but it saves us time if the poster summarizes the bug so the right people know to look at it.

msg256233 - (view)

Author: Tijs Van Oevelen (Tijs Van Oevelen)

Date: 2015-12-11 20:05

Apologies for not posting a summary of the bug. I really had no idea how to describe the problem, as it is over my head. I could only refer to my question on Stack Overflow that triggered the discovery of the bug.

msg256234 - (view)

Author: Tijs Van Oevelen (Tijs Van Oevelen)

Date: 2015-12-11 20:08

It's definitely also in 3.4 by the way.

msg256235 - (view)

Author: R. David Murray (r.david.murray) * (Python committer)

Date: 2015-12-11 20:13

Thanks for posting the bug. I added the aside because this is the third or fourth of these reference-only things I've seen in the past couple weeks and I finally figured out what bothered me about them. We should put something about this in the devguide on bug reporting, but of course most people reporting bugs will for good reason not read that. So, I just have to live with it :)

And yes, the reproducer reproduces the problem in all python versions currently under maintenance.

I've now changed the title to reflect the underlying bug.

msg256245 - (view)

Author: Raymond Hettinger (rhettinger) * (Python committer)

Date: 2015-12-11 23:29

The equality of code objects is determined by the code_richcompare() logic in Objects/codeobject.c.

Two code objects are equal if all of their attributes compare equal. That includes co_name, co_argcount, co_kwonlyargcount, co_nlocals, co_flags, co_firstlineno, co_code, co_consts, co_names, co_varnames, co_freevars, and co_cellvars.

At the heart of David Murray's minimal example, the reason the two distinct code objects compare equal is that their co_consts compare as equal.

If you wanted to fix this, code objects would need to recursively check for both normal equality and type equality.

f1 = lambda: 1 f2 = lambda: 1.0 f1.code.co_consts == f2.code.co_consts True map(type, f1.code.co_consts) == map(type, f2.code.co_consts) False

msg256250 - (view)

Author: Kevin Shweh (Kevin Shweh)

Date: 2015-12-12 02:51

A type-based check runs into problems with 0.0 vs -0.0. For example, on Python 2.7.11:

x, y = lambda: 0.0, lambda: -0.0 y() 0.0

I wasn't able to reproduce the -0.0 problem with Python 3.4 on Ideone; y.code.co_consts seems to have an unused 0.0 in it on 3.4. I don't have access to Python 3.5, so I don't know what the situation is like on that version.

msg256251 - (view)

Author: Raymond Hettinger (rhettinger) * (Python committer)

Date: 2015-12-12 02:52

Here's another variant (courtesy of Nick Coghlan):

python3.5 -c "seq1 = [1.0 for x in range(5)]; seq2 = [True for x in range(5)]; print(seq1); print(seq2)"

msg256252 - (view)

Author: Raymond Hettinger (rhettinger) * (Python committer)

Date: 2015-12-12 02:55

One possible solution for all these variants is to let code objects track both the co.firstlineno and co.firstrowno.

msg256274 - (view)

Author: Raymond Hettinger (rhettinger) * (Python committer)

Date: 2015-12-12 08:45

FWIW, the bug is present in PyPy as well.

msg256285 - (view)

Author: Alyssa Coghlan (ncoghlan) * (Python committer)

Date: 2015-12-12 13:38

From what I can see:

The "values of the same constant type that are distinct but equivalent may still compare equal" case is obscure enough that I think the lower impact change is likely a better option, especially as 3.x currently "handles" the "lambda: -0.0" case by having both the unfolded 0.0 and the folded -0.0 in the constant list.


Additional detail for those interested:

The lowest impact fix from a code change would be to add a type equivalence check for constants as Raymond first suggested, as that only involves adding an extra check to code_richcompare: https://hg.python.org/cpython/file/tip/Objects/codeobject.c#l416

However, the idea of tracking "co_firstcolno" in addition to "co_firstlineno" is a more robust fix, as it means any lexically distinct code objects will necessarily be considered distinct by the interpreter. The downside is that it means touching more code and adding a new public API, since PyCode_New doesn't currently accept a "firstcolno" parameter - code objects are implicitly assumed to be one-per-line.

Out of curiosity, I also went looking for the code in the code generator that collapses the "equivalent" code objects together. The issue is that constants are stored in a dict (mapping them to their co_consts index) during compilation and assembly, so equivalent objects will be merged together (and refer to the index of the first one defined).

msg256290 - (view)

Author: Raymond Hettinger (rhettinger) * (Python committer)

Date: 2015-12-12 19:28

Interestingly, co_filename is not used as part of the equivalence criteria, so code object equivalence can be fooled across multiple input files. Fortunately in this case, the false equivalence isn't relied on by the code generator.

$ cat a.py def f(): return 1

$ cat b.py def f(): return 1.0

$ ./python.exe -q

import a, b a.f.code == b.f.code # False equivalence True a.f() 1 b.f() # Generated code is correct 1.0

Besides aliasing int/float/decimal/fraction/complex/bool, codeobj.eq() can also alias str/unicode on Python 2.7. Likewise, 0.0 and -0.0 can be conflated. NaNs don't seem to be a problem.

I think we should focus on fixing the spec for code object equivalents. Perhaps the test can be simplified to use (co_firstlineno, co_firstrowno, co_filename).

msg256317 - (view)

Author: Armin Rigo (arigo) * (Python committer)

Date: 2015-12-13 07:51

Other possible minimal fixes:

msg256318 - (view)

Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer)

Date: 2015-12-13 08:54

The lowest impact fix from a code change would be to add a type equivalence check for constants as Raymond first suggested, as that only involves adding an extra check to code_richcompare: https://hg.python.org/cpython/file/tip/Objects/codeobject.c#l416

It is not so easy. (1,) and (1.0,) are equal and have the same type. To make correct type-sensitive equivalence check, you need to introduce new protocol, new special method on low level and new operator/function on high level.

msg256320 - (view)

Author: David MacIver (David MacIver) *

Date: 2015-12-13 09:47

Note that 3.x does not correctly handle -0.0, you just have to work a bit harder:

(lambda: (-0.0, 0.0), lambda: (0.0, -0.0))1 (-0.0, 0.0)

msg256321 - (view)

Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer)

Date: 2015-12-13 10:53

I think we should focus on fixing the spec for code object equivalents. Perhaps the test can be simplified to use (co_firstlineno, co_firstrowno, co_filename).

This is not enough if the code was compiled from a string.

x = eval('lambda: 1') y = eval('lambda: 1.0') x.code == y.code True x.code.co_filename == y.code.co_filename True

msg256323 - (view)

Author: Anilyka Barry (abarry) * (Python triager)

Date: 2015-12-13 16:53

Nobody seems to have asked this, so I'll be that guy. In which circumstances does comparing two code objects (at function creation time, what's more) make any sense? I mean, I'm fine with being able to compare two code objects, but I don't think that's something that should be automated.

Is there any particular reason why this is so? The only reason I could think of was that small, identical functions could use the same code object -- but then Raymond proved that different files will not share the code object, and identical functions on different lines will not, either.

As functions grow in size and complexity, having two virtually identical functions is probably bad design to begin with. So, seeing as this causes more harm than good (and I doubt it's of any use nowadays - it might have been back then, I don't know), I suggest we simply drop the implcit code objects compare-and-replace that's happening here.

msg256327 - (view)

Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer)

Date: 2015-12-13 18:24

I suppose this is needed above all for testing. test_compile, test_codeop, test_marshal, and few other tests compare code objects.

msg256330 - (view)

Author: Anilyka Barry (abarry) * (Python triager)

Date: 2015-12-13 19:40

I'm not suggesting to get rid of the rich compare ability of code objects, which makes sense to me. What doesn't make sense to me, however, is when a function's code object is replaced by another one because it compares equal. I see no use case for this, and only leads to head-scratching.

I believe code objects should not be touched at all.

msg256332 - (view)

Author: Armin Rigo (arigo) * (Python committer)

Date: 2015-12-13 19:56

That's what I suggested ("compile.c:compiler_addop(): special-case code objects too, and stick their identity in the tuple 't'.") and how I fixed the same bug in PyPy (https://bitbucket.org/pypy/pypy/commits/7ec3e1d02197).

msg256381 - (view)

Author: Raymond Hettinger (rhettinger) * (Python committer)

Date: 2015-12-14 15:28

[Emanuel Barry]

In which circumstances does comparing two code objects (at function creation time, what's more) make any sense?

It makes closures efficient:

>>> def f(x):
        def g(y):
                return x + y
        return g

>>> h = f(1)
>>> i = f(2)
>>> h.__code__ is i.__code__
True

msg256382 - (view)

Author: Mark Lawrence (BreamoreBoy) *

Date: 2015-12-14 15:47

http://code.activestate.com/recipes/578353-code-to-source-and-back/ compares code objects as part of round trip testing.

msg256383 - (view)

Author: Anilyka Barry (abarry) * (Python triager)

Date: 2015-12-14 15:54

I see. Is there any to special-case those so that only closures use that? Maybe by checking on the function object itself - the function itself would be quite similar, as well.

@Mark - I think you've misunderstood me (others did too, so I'm going to assume I just explained poorly) - I'm not debating the use of comparing code objects, I'm talking about the implicit replacement of code objects in functions. However, it seems to be of use, so outright removing the behaviour isn't an option.

msg256386 - (view)

Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer)

Date: 2015-12-14 16:07

It makes closures efficient:

No, code objects are not compared here. The code object is constant, and f() returns different closure objects using the same code object.

AFAIK the comparison of different code objects is used exclusively in testing.

msg256390 - (view)

Author: R. David Murray (r.david.murray) * (Python committer)

Date: 2015-12-14 16:30

Serhiy: that can't be entirely true, since we have here a bug where two lambdas on the same line are getting the same code object incorrectly, and that is not a testing context.

msg256398 - (view)

Author: R. David Murray (r.david.murray) * (Python committer)

Date: 2015-12-14 16:52

Ah, haypo explained the code to me, and now I understand your comment Serhiy.

So, the replacement happens because of (a) an optimizer general rule and (b) the fact that code object can be compared.

So it sounds like Armin's suggestion of making an exception for code objects in the optimizer is the correct solution.

The issue with code objects that aren't really equal comparing equal would then be a separate bug that affects, as Serhiy said, only testing (that we know of...who knows what people like PJE might be doing with comparing code objects :)

msg256399 - (view)

Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer)

Date: 2015-12-14 16:55

Indeed. My answer actually is an answer to implicit question: could we make different code objects be always non-equal? Answer: no, because we use the comparison of different code objects to test compiler and marshaller.

May be we can get rid of code objects comparability and provide separate function specially for testing. Of course this likely will break tests in third-party packages that do low-level hacking on code objects.

msg256400 - (view)

Author: STINNER Victor (vstinner) * (Python committer)

Date: 2015-12-14 16:55

compiler_add_o() uses an heuristic to compare and merge duplicated constants. It has special cases for float and complex numbers, but it's not designed to handle more types.

Funny, I had the same isue last week why I added support for tuple and frozenset "constants" in AST. I had to explicitly support these types in compiler_add_o().

I see two options:

(1) share code between compiler_add_o() and code_richcompare() to ensure that 1 and 1.0 constants are not seen as equal (2) modify compiler_add_o() to never merge code objects, always considere them as unequal

For (2), there is a minor technical issue: you have to generate an unique key for the dictionary.

I prefer option (1) for consistency.

msg256401 - (view)

Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer)

Date: 2015-12-14 17:03

Would option (1) work if wrap 1 and 1.0 in a tuple? In a list? In a custom collection?

msg256402 - (view)

Author: STINNER Victor (vstinner) * (Python committer)

Date: 2015-12-14 17:04

code_richcompare.patch: fix code_richcompare() to not consider that constants (1,) and (1.0,) are equal.

The patch lacks an unit test.

We may use the new _PyCode_ConstantKey() function to compare other code attributes?

msg256403 - (view)

Author: STINNER Victor (vstinner) * (Python committer)

Date: 2015-12-14 17:07

Would option (1) work if wrap 1 and 1.0 in a tuple? In a list? In a custom collection?

Right now, the Python compiler is quite limited. It only produces constants for integers and strings, not complex types. The peephole optimizers is responsible to produce tuple and frozenset constants, and the optimizer is more naive. It doesn't try to merge constants, nor remove items from co_consts to only keep the new container. Example:

def f(): ... return (1,2,3) ... f.code.co_consts (None, 1, 2, 3, (1, 2, 3))

1, 2, 3 constants are kept, whereas only (1, 2, 3) constant is used.

Test with my patch:

f1, f2 = lambda x: x in {1,}, lambda x: x in {1.0,}

f1.code is f2.code False f1.code.co_consts (None, 1, frozenset({1})) f2.code.co_consts (None, 1.0, frozenset({1.0}))

The frozenset are different are expected.

msg256404 - (view)

Author: STINNER Victor (vstinner) * (Python committer)

Date: 2015-12-14 17:12

The frozenset are different are expected.

Oh wait, in this example, it works, but not because of the expected reason. frozenset({1}) is equal to frozenset({1.0}) and code_richcompare() doesn't create a special key to make them different.

The example only works because the peephole optimizer is lazy and leave 1 and 1.0 in co_consts which are seen as different by the patched code_richcompare().

msg256405 - (view)

Author: STINNER Victor (vstinner) * (Python committer)

Date: 2015-12-14 17:31

code_richcompare-2.patch: Updated patch to handle also frozenset, the other constant type generated by the peephole optimizer.

msg256406 - (view)

Author: STINNER Victor (vstinner) * (Python committer)

Date: 2015-12-14 17:31

code_eq.py: code to test that frozenset() are inequal. The code hacks constants, don't run the code with new constants or it will crash!

msg256409 - (view)

Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer)

Date: 2015-12-14 19:32

If go this way, I would add explicit support of all types supported in marshal, and include id(obj) into the key of all other types.

msg258532 - (view)

Author: STINNER Victor (vstinner) * (Python committer)

Date: 2016-01-18 17:22

FYI this issue is linked to the issue #26146 which allows to emit constants from an AST optimizer (see also the PEP 511).

msg258683 - (view)

Author: STINNER Victor (vstinner) * (Python committer)

Date: 2016-01-20 14:15

Let me try to explain this issue again.

"f1, f2 = lambda: 1, lambda: 1.0" is compiled to two MAKE_FUNCTION instructions, MAKE_FUNCTION takes a code object as parameter (and a name). The Python compiler merges constants which are seen as "equal", with exceptions to not merge values of different types, or float of different sign.

Merging duplicate code objects is a cool micro optimization, I prefer to keep it. My patch keeps this micro optimization, but fix the bug: it ensures that equal constants having different types are not seen as equal. For example, 0 is equal to 0.0, but if when used for code constants, the code objects are seen a different.

Patch version 3:

@Serhiy: does it look good to you now?

Would option (1) work if wrap 1 and 1.0 in a tuple? In a list? In a custom collection?

My patch now uses id(obj) in the "constant key" for unknown types. The compiler only emits simple type (int, str, ...), tuple, frozenset and code objects.

You can other types if you patch manually constants with custom objects, since code_richcomp() now uses the "constant key" function to compare constants. For example, my fat project has a replace_consts() function to inject builtin functions in constants: http://fatoptimizer.readthedocs.org/en/latest/fat.html#replace_consts

There is also @asconstants decorator of codetransformer which allow to inject arbitrary types in function constants: https://pypi.python.org/pypi/codetransformer

msg258707 - (view)

Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer)

Date: 2016-01-20 18:19

It looks to me that the patch makes set and frozenset constants to be equal, but makes sets with different order (as {262, 1} and {1, 262}) differ. And looks you had missed my comments to previous patches.

msg258724 - (view)

Author: STINNER Victor (vstinner) * (Python committer)

Date: 2016-01-20 23:05

Patch version 4:

Fix _PyCode_ConstantKey:

Other minor changes to take Serhiy's comments in account.

Thanks Serhiy for good suggestions!

msg258725 - (view)

Author: STINNER Victor (vstinner) * (Python committer)

Date: 2016-01-20 23:05

And sorry, I missed your comments, it looks like some emails were seen as spam :-/

msg258753 - (view)

Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer)

Date: 2016-01-21 10:22

I meant that set shouldn't be handled in _PyCode_ConstantKey at all. Only frozenset constants can be considered equal. Sets as well as lists all should be different.

There is yet one issue with string and bytes literals. When run Python with the -b option:

a, b = lambda: 'a', lambda: b'a' sys:1: BytesWarning: Comparison between bytes and string sys:1: BytesWarning: Comparison between bytes and string

May be the type should be the first item in the key.

msg258756 - (view)

Author: STINNER Victor (vstinner) * (Python committer)

Date: 2016-01-21 12:49

Updated patch version 5.

I meant that set shouldn't be handled in _PyCode_ConstantKey at all. Only frozenset constants can be considered equal. Sets as well as lists all should be different.

Ok, I dropped support for set type to only keep support for frozenset. set are now always considered as different, as list and other "unsupported types".

There is yet one issue with string and bytes literals. When run Python with the -b option: (...) May be the type should be the first item in the key.

Oh, good catch. It's an old bug.

Yeah, putting the type as the first parameter fixes the issue. I made this change. I had to update compile.c to exchange the type and the value in the tuple.

msg258795 - (view)

Author: Roundup Robot (python-dev) (Python triager)

Date: 2016-01-22 11:37

New changeset 6c33d4cc9b8f by Victor Stinner in branch 'default': code_richcompare() now uses the constants types https://hg.python.org/cpython/rev/6c33d4cc9b8f

msg258796 - (view)

Author: STINNER Victor (vstinner) * (Python committer)

Date: 2016-01-22 11:40

I pushed my latest patch with minor changes in comments.

I will wait for buildbots before backporting the change to Python 2.7 and 3.5. For the backport, I will probably remove the optimization on frozenset since it's only useful for AST optimizers (the optimization is a new feature, I considered that it was worth it to add it Python 3.6 as part of my work on the PEP 511).

msg258814 - (view)

Author: Roundup Robot (python-dev) (Python triager)

Date: 2016-01-22 14:59

New changeset 8e0a736b82ff by Victor Stinner in branch '3.5': code_richcompare() now uses the constants types https://hg.python.org/cpython/rev/8e0a736b82ff

msg258815 - (view)

Author: STINNER Victor (vstinner) * (Python committer)

Date: 2016-01-22 15:17

I will probably remove the optimization on frozenset since it's only useful for AST optimizers (the optimization is a new feature, I considered that it was worth it to add it Python 3.6 as part of my work on the PEP 511).

Hum, it doesn't work: test_compile_ast() of test_compile fails without this code. The test relies (indirectly) on the fact that two code objects using a frozenset constant are equal.

msg258817 - (view)

Author: Roundup Robot (python-dev) (Python triager)

Date: 2016-01-22 15:51

New changeset 9e13d97ceca2 by Victor Stinner in branch '2.7': code_richcompare() now uses the constants types https://hg.python.org/cpython/rev/9e13d97ceca2

msg258818 - (view)

Author: STINNER Victor (vstinner) * (Python committer)

Date: 2016-01-22 15:54

Ok, the fix is now pushed to Python 2.7, 3.5 and 3.6.

Thanks Tijs Van Oevelen for your bug report ;-)

A workaround look to define the two lambda functions on two different lines. Or maybe cast explicitly to float? I don't think that it's a common bug so you should be able to survive with it until the next bugfix version is released :-)

msg259016 - (view)

Author: Roundup Robot (python-dev) (Python triager)

Date: 2016-01-27 11:20

New changeset 16f60cd918e0 by Victor Stinner in branch 'default': PEP 511 https://hg.python.org/peps/rev/16f60cd918e0

msg268555 - (view)

Author: Larry Hastings (larry) * (Python committer)

Date: 2016-06-14 12:53

Someone asked on reddit. The Misc/NEWS entry for this reads:

Issue #25843: When compiling code, don’t merge constants if they are equal but have a different types. For example, f1, f2 = lambda: 1, lambda: 1.0 is now correctly compiled to two different functions: f1() returns 1 (int) and f2() returns 1.0 (int), even if 1 and 1.0 are equal.

Shouldn't that last part read

"and f2() returns 1.0 (float), even if 1 and 1.0 are equal." ^^^^^

As in, f2 returns a float, not an int.

If this is a mistake, let me fix it for 3.5.2 final and I'll merge it back into trunk etc. If you fix it it wouldn't ship in 3.5.2 final.

msg268556 - (view)

Author: Roundup Robot (python-dev) (Python triager)

Date: 2016-06-14 13:05

New changeset a36238de31ae by Victor Stinner in branch '3.5': Issue #25843: Fix the NEWS entry https://hg.python.org/cpython/rev/a36238de31ae

msg268557 - (view)

Author: STINNER Victor (vstinner) * (Python committer)

Date: 2016-06-14 13:06

Oh, I fixed the typo in the Misc/NEWS in 3.5 and default branches.

msg268588 - (view)

Author: Larry Hastings (larry) * (Python committer)

Date: 2016-06-14 22:44

Yes, which doesn't help 3.5.2 final as I don't pull revisions by default after rc1. :p

History

Date

User

Action

Args

2022-04-11 14:58:24

admin

set

github: 70030

2016-06-14 22:44:29

larry

set

messages: +

2016-06-14 13:06:03

vstinner

set

messages: +

2016-06-14 13:05:47

python-dev

set

messages: +

2016-06-14 12:53:48

larry

set

nosy: + larry
messages: +

2016-01-27 11:20:21

python-dev

set

messages: +

2016-01-22 15:54:05

vstinner

set

status: open -> closed
resolution: fixed
messages: +

2016-01-22 15:51:28

python-dev

set

messages: +

2016-01-22 15:17:29

vstinner

set

messages: +

2016-01-22 14:59:49

python-dev

set

messages: +

2016-01-22 11:40:37

vstinner

set

messages: +

2016-01-22 11:37:50

python-dev

set

nosy: + python-dev
messages: +

2016-01-21 17:00:14

vstinner

link

issue26146 dependencies

2016-01-21 12:49:06

vstinner

set

files: + code_richcompare-5.patch

messages: +

2016-01-21 10:22:10

serhiy.storchaka

set

messages: +

2016-01-20 23:05:43

vstinner

set

messages: +

2016-01-20 23:05:23

vstinner

set

files: + code_richcompare-4.patch

messages: +

2016-01-20 18:19:47

serhiy.storchaka

set

stage: patch review
messages: +
versions: - Python 3.4

2016-01-20 14:16:14

vstinner

set

title: lambdas on the same line may incorrectly share code objects -> code_richcompare() don't use constant type when comparing code constants

2016-01-20 14:15:04

vstinner

set

files: + code_richcompare-3.patch

messages: +

2016-01-20 08:42:37

mark.dickinson

set

nosy: + mark.dickinson

2016-01-18 18:26:52

BreamoreBoy

set

nosy: - BreamoreBoy

2016-01-18 17:22:14

vstinner

set

messages: +

2015-12-14 19:32:23

serhiy.storchaka

set

messages: +

2015-12-14 17:31:48

vstinner

set

files: + code_eq.py

messages: +

2015-12-14 17:31:03

vstinner

set

files: + code_richcompare-2.patch

messages: +

2015-12-14 17:12:14

vstinner

set

messages: +

2015-12-14 17:07:43

vstinner

set

messages: +

2015-12-14 17:04:16

vstinner

set

files: + code_richcompare.patch
keywords: + patch
messages: +

2015-12-14 17:03:04

serhiy.storchaka

set

messages: +

2015-12-14 16:55:30

vstinner

set

messages: +

2015-12-14 16:55:25

serhiy.storchaka

set

messages: +

2015-12-14 16:52:39

r.david.murray

set

messages: +

2015-12-14 16:37:48

vstinner

set

nosy: + vstinner

2015-12-14 16:30:37

r.david.murray

set

messages: +

2015-12-14 16:07:55

serhiy.storchaka

set

messages: +

2015-12-14 15:54:45

abarry

set

messages: +

2015-12-14 15:47:15

BreamoreBoy

set

nosy: + BreamoreBoy
messages: +

2015-12-14 15:28:03

rhettinger

set

messages: +

2015-12-13 19:56:19

arigo

set

messages: +

2015-12-13 19:40:15

abarry

set

messages: +

2015-12-13 18:24:40

serhiy.storchaka

set

messages: +

2015-12-13 16:53:27

abarry

set

nosy: + abarry
messages: +

2015-12-13 10:53:11

serhiy.storchaka

set

messages: +

2015-12-13 09:47:45

David MacIver

set

nosy: + David MacIver
messages: +

2015-12-13 08:54:12

serhiy.storchaka

set

nosy: + serhiy.storchaka
messages: +

2015-12-13 07:51:13

arigo

set

messages: +

2015-12-12 23:28:20

torsten

set

nosy: + torsten

2015-12-12 19:28:09

rhettinger

set

nosy: + arigo, fijall
messages: +

2015-12-12 13:38:40

ncoghlan

set

nosy: + ncoghlan
messages: +

2015-12-12 13:02:38

donmez

set

nosy: + donmez

2015-12-12 10:41:33

ezio.melotti

set

nosy: + ezio.melotti

2015-12-12 08:45:29

rhettinger

set

messages: +

2015-12-12 02:55:18

rhettinger

set

messages: +

2015-12-12 02:52:01

rhettinger

set

messages: +

2015-12-12 02:51:33

Kevin Shweh

set

nosy: + Kevin Shweh
messages: +

2015-12-11 23:29:54

rhettinger

set

nosy: + rhettinger
messages: +

2015-12-11 20:13:29

r.david.murray

set

messages: +
title: unexpected output using pythons ternary operator in combination with lambda -> lambdas on the same line may incorrectly share code objects

2015-12-11 20:08:16

Tijs Van Oevelen

set

messages: +
versions: + Python 3.4

2015-12-11 20:05:46

Tijs Van Oevelen

set

messages: +

2015-12-11 19:36:19

ethan.furman

set

title: unexpected-output-using-pythons-ternary-operator-in-combination-with-lambda -> unexpected output using pythons ternary operator in combination with lambda

2015-12-11 19:33:49

r.david.murray

set

nosy: + r.david.murray, Tijs Van Oevelen

messages: +
versions: + Python 2.7, Python 3.5, Python 3.6, - Python 3.4

2015-12-11 19:24:04

Tijs Van Oevelen

set

nosy: - Tijs Van Oevelen
-> (no value)

2015-12-11 19:23:13

Tijs Van Oevelen

create