[issue46085] OrderedDict iterator allocates di_result unnecessarily

2021-12-15 Thread Kevin Shweh


New submission from Kevin Shweh :

The OrderedDict iterator caches a di_result tuple for use with 
iter(od.items()). It's *supposed* to only do that for the items() case, but the 
code does

if (kind & (_odict_ITER_KEYS | _odict_ITER_VALUES))

to test for this case. This is the wrong test. It should be

if ((kind & _odict_ITER_KEYS) && (kind &_odict_ITER_VALUES))

The current test allocates di_result for key and value iterators as well as 
items iterators.

--
components: Library (Lib)
messages: 408616
nosy: Kevin Shweh
priority: normal
severity: normal
status: open
title: OrderedDict iterator allocates di_result unnecessarily
type: resource usage
versions: Python 3.10, Python 3.11, Python 3.8, Python 3.9

___
Python tracker 
<https://bugs.python.org/issue46085>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue46085] OrderedDict iterator allocates di_result unnecessarily

2021-12-16 Thread Kevin Shweh


Kevin Shweh  added the comment:

Almost - C's weird bitwise operator precedence means it has to be parenthesized 
as

if ((kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS)

--

___
Python tracker 
<https://bugs.python.org/issue46085>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue46726] Thread spuriously marked dead after interrupting a join call

2022-02-11 Thread Kevin Shweh


New submission from Kevin Shweh :

This code in Thread._wait_for_tstate_lock:

try:
if lock.acquire(block, timeout):
lock.release()
self._stop()
except:
if lock.locked():
# bpo-45274: lock.acquire() acquired the lock, but the function
# was interrupted with an exception before reaching the
# lock.release(). It can happen if a signal handler raises an
# exception, like CTRL+C which raises KeyboardInterrupt.
lock.release()
self._stop()
raise

has a bug. The "if lock.locked()" check doesn't check whether this code managed 
to acquire the lock. It checks if *anyone at all* is holding the lock. The lock 
is almost always locked, so this code will perform a spurious call to 
self._stop() if it gets interrupted while trying to acquire the lock.

Thread.join uses this method to wait for a thread to finish, so a thread will 
spuriously be marked dead if you interrupt a join call with Ctrl-C while it's 
trying to acquire the lock. Here's a reproducer:


import time
import threading
 
event = threading.Event()
 
def target():
event.wait()
print('thread done')
 
t = threading.Thread(target=target)
t.start()
print('joining now')
try:
t.join()
except KeyboardInterrupt:
pass
print(t.is_alive())
event.set()


Interrupt this code with Ctrl-C during the join(), and print(t.is_alive()) will 
print False.

--
components: Library (Lib)
messages: 413106
nosy: Kevin Shweh
priority: normal
severity: normal
status: open
title: Thread spuriously marked dead after interrupting a join call
type: behavior
versions: Python 3.10, Python 3.11, Python 3.9

___
Python tracker 
<https://bugs.python.org/issue46726>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue46726] Thread spuriously marked dead after interrupting a join call

2022-02-11 Thread Kevin Shweh


Kevin Shweh  added the comment:

Issue 45274 was a subtly different issue. That was a problem that happened if 
the thread got interrupted *between* the acquire and the release, causing it to 
*not* release the lock and *not* perform end-of-thread cleanup.

The fix for that issue caused this issue, which happens if the thread gets 
interrupted *during* the acquire, in which case it *does* release the lock 
(that someone else is holding) and *does* perform end-of-thread cleanup even 
though it's not supposed to do either of those things.

--

___
Python tracker 
<https://bugs.python.org/issue46726>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue46726] Thread spuriously marked dead after interrupting a join call

2022-02-11 Thread Kevin Shweh


Kevin Shweh  added the comment:

The PR you submitted doesn't work, unfortunately. It essentially reintroduces 
issue 45274. If this line:

if locked := lock.acquire(block, timeout):

gets interrupted between the acquire and the assignment, locked is still False. 
That's rare, but so is an interruption between the acquire and the release, 
which is the original form of issue 45274.

--

___
Python tracker 
<https://bugs.python.org/issue46726>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue46722] Different behavior for functiools.partial between inspect.isfunction() and other inspect.is*function()

2022-02-11 Thread Kevin Shweh


Kevin Shweh  added the comment:

Frankly, it doesn't make sense that isgeneratorfunction or iscoroutinefunction 
unwrap partials at all. The original justification for making them do that back 
in https://bugs.python.org/issue34890 was invalid - the original argument was 
that isfunction unwraps partials, but it doesn't, and I don't think it ever did.

isfunction is supposed to be a very specific check for Python function objects. 
It rejects all sorts of other callables, like sum (a built-in function), super 
(a type), or method objects (which wrap functions in a very similar way to 
partial). Having it be a check for *either* a Python function object *or* a 
partial object wrapping a Python function object seems to just make it less 
useful.

------
nosy: +Kevin Shweh

___
Python tracker 
<https://bugs.python.org/issue46722>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue38908] Troubles with @runtime_checkable protocols

2021-04-17 Thread Kevin Shweh


Kevin Shweh  added the comment:

It seems like the straightforward, minimal fix would be to just add

if (getattr(cls, '_is_protocol', False) and
not getattr(cls, '_is_runtime_protocol', False) and
not _allow_reckless_class_cheks()):
raise TypeError(...)

to _ProtocolMeta.__instancecheck__. Does that fail on some edge case (that the 
current implementation works on)? It's a little weird that 
_ProtocolMeta.__instancecheck__ doesn't explicitly check that the protocol is 
runtime-checkable.

--
nosy: +Kevin Shweh

___
Python tracker 
<https://bugs.python.org/issue38908>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue44921] dict subclassing is slow

2021-08-17 Thread Kevin Shweh


Kevin Shweh  added the comment:

Of course it's reasonable to support dict subclasses. We already have a bunch 
of dict subclasses in the standard library, like collections.defaultdict and 
collections.Counter, and collections.Counter is significantly slower than it 
could be because of this issue. (collections.defaultdict seems to be unaffected 
due to differences between classes implemented in C and Python.) 
dict.__getitem__ even has dedicated support for a __missing__ hook, which is 
only useful for subclasses.

--
nosy: +Kevin Shweh

___
Python tracker 
<https://bugs.python.org/issue44921>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue45104] Error in __new__ docs

2021-09-04 Thread Kevin Shweh

New submission from Kevin Shweh :

The data model docs for __new__ say "If __new__() is invoked during object 
construction and it returns an instance or subclass of cls, then the new 
instance’s __init__() method will be invoked..."

"instance or subclass of cls" is incorrect - if for some reason __new__ returns 
a subclass of cls, __init__ will not be invoked, unless the subclass also 
happens to be an instance of cls (which can happen with metaclasses).

This should probably say something like "instance of cls (including subclass 
instances)", or "instance of cls or of a subclass of cls", or just "instance of 
cls".

--
assignee: docs@python
components: Documentation
messages: 401065
nosy: Kevin Shweh, docs@python
priority: normal
severity: normal
status: open
title: Error in __new__ docs
versions: Python 3.10, Python 3.11, Python 3.8, Python 3.9

___
Python tracker 
<https://bugs.python.org/issue45104>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue38947] dataclass defaults behave inconsistently for init=True/init=False when default is a descriptor

2019-11-30 Thread Kevin Shweh


New submission from Kevin Shweh :

The following code:

from dataclasses import dataclass, field
from typing import Callable
 
@dataclass
class Foo:
callback: Callable[[int], int] = lambda x: x**2
 
@dataclass
class Bar:
callback: Callable[[int], int] = field(init=False, default=lambda x: 
x**2)
 
print(Foo().callback(2))
print(Bar().callback(2))

prints 4 for the first print, but throws a TypeError for the second. This is 
because Foo() stores the default callback in the instance dict, while Bar() 
only has it in the class dict. Bar().callback triggers the descriptor protocol 
and produces a method object instead of the original callback.

There does not seem to be any indication in the dataclasses documentation that 
these fields will behave differently. It seems like they should behave the 
same, and/or the documentation should be clearer about how the default 
value/non-init field interaction behaves.

--
components: Library (Lib)
messages: 357669
nosy: Kevin Shweh
priority: normal
severity: normal
status: open
title: dataclass defaults behave inconsistently for init=True/init=False when 
default is a descriptor
type: behavior
versions: Python 3.7, Python 3.8

___
Python tracker 
<https://bugs.python.org/issue38947>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue42190] global declarations affect too much inside exec or compile

2020-10-28 Thread Kevin Shweh


New submission from Kevin Shweh :

A global declaration inside a function is only supposed to affect assignments 
inside that function, but in code executed with exec, a global declaration 
affects assignments outside the function:

>>> gdict = {}
>>> ldict = {}
>>> exec('x = 1', gdict, ldict)
>>> 'x' in gdict
False
>>> 'x' in ldict
True
>>> 
>>> gdict = {}
>>> ldict = {}
>>> exec('''
... x = 1
... def f(): global x''', gdict, ldict)
>>> 'x' in gdict
True
>>> 'x' in ldict
False

Here, we can see that the presence of a "global x" declaration inside f causes 
the "x = 1" outside of f to assign to globals instead of locals. This also 
affects code objects compiled with compile().

--
components: Interpreter Core
messages: 379855
nosy: Kevin Shweh
priority: normal
severity: normal
status: open
title: global declarations affect too much inside exec or compile
type: behavior
versions: Python 3.8

___
Python tracker 
<https://bugs.python.org/issue42190>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue36951] Wrong types for PyMemberDefs in Objects/typeobject.c

2019-05-17 Thread Kevin Shweh


New submission from Kevin Shweh :

In Objects/typeobject.c, the PyMemberDefs for __flags__, __weakrefoffset__, and 
__dictoffset__ all use T_LONG:

{"__flags__", T_LONG, offsetof(PyTypeObject, tp_flags), READONLY},
{"__weakrefoffset__", T_LONG,
 offsetof(PyTypeObject, tp_weaklistoffset), READONLY},
...
{"__dictoffset__", T_LONG,
 offsetof(PyTypeObject, tp_dictoffset), READONLY},

{"__weakrefoffset__", T_LONG,
 offsetof(PyTypeObject, tp_weaklistoffset), READONLY},

but in Include/object.h or Include/cpython/object.h, the corresponding struct 
members have types unsigned long, Py_ssize_t, and Py_ssize_t respectively:

/* Flags to define presence of optional/expanded features */
unsigned long tp_flags;
...
/* weak reference enabler */
Py_ssize_t tp_weaklistoffset;
...
Py_ssize_t tp_dictoffset;

These uses of T_LONG should be changed to T_ULONG and T_PYSSIZE_T.

This was checked on 3.7.3 and master.

--
components: Interpreter Core
messages: 342759
nosy: Kevin Shweh
priority: normal
severity: normal
status: open
title: Wrong types for PyMemberDefs in Objects/typeobject.c
type: behavior
versions: Python 3.7, Python 3.8

___
Python tracker 
<https://bugs.python.org/issue36951>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue36951] Wrong types for PyMemberDefs in Objects/typeobject.c

2019-05-17 Thread Kevin Shweh


Kevin Shweh  added the comment:

Looks like I accidentally doubled the PyMemberDef for __weakrefoffset__ while 
editing. There's no double definition in the actual file.

--

___
Python tracker 
<https://bugs.python.org/issue36951>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue31127] Abstract classes derived from built-in classes don't block instance creation

2017-08-06 Thread Kevin Shweh

New submission from Kevin Shweh:

The only check that prevents instantiating abstract classes is in 
object.__new__, but most built-in classes never actually call object.__new__. 
That means you can do stuff like

import abc

class Foo(list, metaclass=abc.ABCMeta):
@abc.abstractmethod
def abstract(self):
pass

Foo()

and the Foo() call will silently succeed.

Ideally, the Foo() call should fail. Other options include having the Foo class 
definition itself fail, or just making a note in the documentation describing 
the limitation. (As far as I can see, this is currently undocumented.)

--
assignee: docs@python
components: Documentation, Library (Lib)
messages: 299810
nosy: Kevin Shweh, docs@python
priority: normal
severity: normal
status: open
title: Abstract classes derived from built-in classes don't block instance 
creation
type: behavior
versions: Python 2.7, Python 3.6

___
Python tracker 
<http://bugs.python.org/issue31127>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue14385] Support other types than dict for __builtins__

2019-03-05 Thread Kevin Shweh


Kevin Shweh  added the comment:

The patch for this issue changed LOAD_GLOBAL to use PyObject_GetItem when 
globals() is a dict subclass, but LOAD_NAME, STORE_GLOBAL, and DELETE_GLOBAL 
weren't changed. (LOAD_NAME uses PyObject_GetItem for builtins now, but not for 
globals.)

This means that global lookup doesn't respect overridden __getitem__ inside a 
class statement (unless you explicitly declare the name global with a global 
statement, in which case LOAD_GLOBAL gets used instead of LOAD_NAME).

I don't have a strong opinion on whether STORE_GLOBAL or DELETE_GLOBAL should 
respect overridden __setitem__ or __delitem__, but the inconsistency between 
LOAD_GLOBAL and LOAD_NAME seems like a bug that should be fixed.

For reference, in the following code, the first 3 exec calls successfully print 
5, and the last exec call fails, due to the LOAD_GLOBAL/LOAD_NAME inconsistency:

class Foo(dict):
def __getitem__(self, index):
return 5 if index == 'y' else super().__getitem__(index)
 
exec('print(y)', Foo())
exec('global y; print(y)', Foo())
exec('''
class UsesLOAD_NAME:
global y
print(y)''', Foo())
exec('''
class UsesLOAD_NAME:
print(y)''', Foo())

--
nosy: +Kevin Shweh

___
Python tracker 
<https://bugs.python.org/issue14385>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue36220] LOAD_NAME and LOAD_GLOBAL handle dict subclasses for globals() differently

2019-03-06 Thread Kevin Shweh


New submission from Kevin Shweh :

LOAD_NAME and LOAD_GLOBAL don't treat dict subclasses for globals() the same 
way. If globals() is a dict subclass, LOAD_GLOBAL will respect overridden 
__getitem__, but LOAD_NAME will use PyDict_GetItem. This causes global lookup 
to behave differently in class statements; for example, in the following code, 
the final exec is the only one where print(y) causes a NameError:

class Foo(dict):
def __getitem__(self, index):
return 5 if index == 'y' else super().__getitem__(index)
 
exec('print(y)', Foo())
exec('global y; print(y)', Foo())
exec('''
class UsesLOAD_NAME:
global y
print(y)''', Foo())
exec('''
class UsesLOAD_NAME:
print(y)''', Foo())


STORE_GLOBAL and DELETE_GLOBAL also go straight for PyDict_SetItem and 
PyDict_DelItem; I don't know whether those should be considered bugs as well, 
but the inconsistency between LOAD_NAME and LOAD_GLOBAL definitely seems wrong.

(For reference, the change that introduced the inconsistency was made for issue 
#14385, which was intended to support non-dict __builtins__.)

--
components: Interpreter Core
messages: 337356
nosy: Kevin Shweh
priority: normal
severity: normal
status: open
title: LOAD_NAME and LOAD_GLOBAL handle dict subclasses for globals() 
differently
type: behavior
versions: Python 3.7, Python 3.8

___
Python tracker 
<https://bugs.python.org/issue36220>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue15606] re.VERBOSE whitespace behavior not completely documented

2017-11-10 Thread Kevin Shweh

Kevin Shweh  added the comment:

It looks to me like there are more situations than the patch lists where 
whitespace still separates tokens. For example, *? is a reluctant quantifier 
and * ? is a syntax error, even in verbose mode.

--
nosy: +Kevin Shweh

___
Python tracker 
<https://bugs.python.org/issue15606>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue29581] __init_subclass__ causes TypeError when used with standard library metaclasses (such as ABCMeta)

2017-02-20 Thread Kevin Shweh

Kevin Shweh added the comment:

Doesn't that ignore_extra_args thing prevent InitX.__init_subclass__ from 
receiving the x argument it wanted? It doesn't seem like a solution.

--
nosy: +Kevin Shweh

___
Python tracker 
<http://bugs.python.org/issue29581>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue7406] int arithmetic relies on C signed overflow behaviour

2015-06-24 Thread Kevin Shweh

Kevin Shweh added the comment:

It looks like the fast paths for INPLACE_ADD and INPLACE_SUBTRACT in Python 2 
don't have the cast-to-unsigned fix, so they're still relying on undefined 
behavior. For example, in INPLACE_ADD:


/* INLINE: int + int */
register long a, b, i;
a = PyInt_AS_LONG(v);
b = PyInt_AS_LONG(w);
i = a + b;
if ((i^a) < 0 && (i^b) < 0)
goto slow_iadd;

--
nosy: +Kevin Shweh

___
Python tracker 
<http://bugs.python.org/issue7406>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue25843] lambdas on the same line may incorrectly share code objects

2015-12-11 Thread Kevin Shweh

Kevin Shweh added the comment:

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.

--
nosy: +Kevin Shweh

___
Python tracker 
<http://bugs.python.org/issue25843>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com