[issue44807] typing.Protocol silently overrides __init__ method of delivered class

2022-02-28 Thread Adrian Garcia Badaracco


Adrian Garcia Badaracco  added the comment:

I am not sure if that solves anything (other than the fact that __new__ is much 
less common to implement than __init__), but I may just be slow to pick up the 
implications of moving the check to __new__

--

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



[issue44807] typing.Protocol silently overrides __init__ method of delivered class

2022-02-28 Thread Adrian Garcia Badaracco


Adrian Garcia Badaracco  added the comment:

Guido, it looks like you replied while I was typing my reply out.

Yurii can correct me here but I believe PR #27543 was an attempt to disallow 
defining `__init__` on a Protocol completely. What I proposed above is the 
opposite behavior, while still fixing the issue of `__init__` getting silently 
overridden (which is the crux / title of this issue).

I'm not sure which approach is right.

--

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



[issue44807] typing.Protocol silently overrides __init__ method of delivered class

2022-02-28 Thread Adrian Garcia Badaracco


Adrian Garcia Badaracco  added the comment:

Agreed.

What if we allow protocols that implement `__init__` but still disallow 
instantiating a protocol that does not? It's a 1 line change, all existing 
tests pass and it would still catch what I think was the original intention 
(trying to instantiate a Protocol class with no __init__): 
https://github.com/python/cpython/pull/31628/files#diff-ddb987fca5f5df0c9a2f5521ed687919d70bb3d64eaeb8021f98833a2a716887

--

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



[issue44807] typing.Protocol silently overrides __init__ method of delivered class

2022-02-28 Thread Adrian Garcia Badaracco


Change by Adrian Garcia Badaracco :


--
pull_requests: +29750
stage: test needed -> patch review
pull_request: https://github.com/python/cpython/pull/31628

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



[issue44807] typing.Protocol silently overrides __init__ method of delivered class

2022-02-27 Thread Adrian Garcia Badaracco


Adrian Garcia Badaracco  added the comment:

Apologies if that was noise, I filed an issue on the MyPy issue tracker: 
https://github.com/python/mypy/issues/12261

--

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



[issue44807] typing.Protocol silently overrides __init__ method of delivered class

2022-02-27 Thread Adrian Garcia Badaracco


Adrian Garcia Badaracco  added the comment:

While this is figured out, would it be possible to remove the silent 
overriding? This seems like something type checkers should be doing, not silent 
runtime modification of classes. Pyright already (correctly) checks this, so I 
think it would just need to be added to MyPy.

>>> class C(Protocol):
...   def __init__(self) -> None:
... print('init!')
...
>>> c = C()  # Pyright error, MyPy says it's okay

I came across this while trying to create a class that requires concrete 
subclasses to define a specific field, and it seems like Protocol is the only 
thing that can pull this off because of how type checkers special case it: 
https://gist.github.com/adriangb/6c1a001ee7035bad5bd56df70e0cf5e6

I don't particularly like this use of Protocol, but it works (aside from the 
overriding issue).

I don't know if this usage of implementing `__init__` on a protocol class 
should be valid or not, but I do think it's interesting that `__init__` is 
never called on the protocol class itself, even if the protocol class is the 
one defining it. It is only called on `MyAPIKey`, which is a concrete class 
that happens to inherit the implementation from a protocol class. So maybe that 
should be valid? I'm not sure.

But I do know that making type checkers enforce this instead runtime would 
allow this use case to work while still prohibiting the (in my opinion invalid) 
use case of calling `__init__` on the protocol class itself.

--
nosy: +adriangb
status: pending -> open

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



[issue17005] Add a topological sort algorithm

2021-11-29 Thread Adrian Garcia Badaracco


Adrian Garcia Badaracco  added the comment:

As part of working on a tool that deals with dependencies, I was building my 
own topological sort. I iterated through various APIs (iterable of tasks, 
iterable of parallelizable groups of tasks, etc.) until I found the (now 
stdlib) version which ended up being exactly the API I needed to most 
efficiently execute dependencies. So, kudos on the design!

I actually ended up re-writing it in Rust, partly because I wanted a good 
project to learn Rust, partly because I wanted to be able to modify the API a 
bit. Namely:
1. I needed the ability to re-execute the same DAG multiple times without 
re-checking for cycles and re-adding all nodes (so basically copying 
`npredecessors` before executing).
2. I needed the ability to remove nodes from the graph. The real-world 
application is removing pruning subgraphs corresponding to cached dependencies. 
Again, I wanted to do this without rebuilding the entire thing (removing nodes 
can never lead to a cycle, and it is possible to keep track of new leaf nodes 
as you remove them instead of iterating over the entire graph again to find 
leaf nodes).

Here's the implementation in case anyone is interested: 
https://github.com/adriangb/graphlib2

The algorithm is the same, but I had to change the data structures somewhat to 
cope w/ Rusts' borrowing rules (namely I can't hold a mutable reference to two 
values in `node2nodeinfo` at the same time, which the current implementation 
does here 
https://github.com/python/cpython/blob/32f1491a9770b7f2989507ecf8f13ef35dd95b0b/Lib/graphlib.py#L190,
 so I split them out into two separate mappings).

--
nosy: +adriangb

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



[issue26175] Fully implement IOBase abstract on SpooledTemporaryFile

2021-11-16 Thread Adrian Garcia Badaracco


Change by Adrian Garcia Badaracco :


--
nosy: +adriangb

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



[issue44834] contextvars.Context.run w/ coroutines gives inconsistent behavior

2021-08-04 Thread Adrian Garcia Badaracco


Change by Adrian Garcia Badaracco :


--
nosy: +yselivanov

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



[issue42815] new thread doesn't copy context of the parent thread

2021-08-04 Thread Adrian Garcia Badaracco


Change by Adrian Garcia Badaracco :


--
nosy: +adriangb

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



[issue44834] contextvars.Context.run w/ coroutines gives inconsistent behavior

2021-08-04 Thread Adrian Garcia Badaracco


New submission from Adrian Garcia Badaracco :

I recently tried to use `contextvars.Context.run` w/ coroutines, expecting the 
same behavior as with regular functions, but it seems that 
`contextvars.Context.run` does not work w/ coroutines.

I'm sorry if this is something obvious to do with how coroutines work under the 
hood, if so I'd appreciate some help in understanding why this is the expected 
behavior.

```python
import asyncio
import contextvars


ctxvar = contextvars.ContextVar("ctxvar", default="spam")


def func():
assert ctxvar.get() == "spam"

async def coro():
func()


async def main():
ctx = contextvars.copy_context()
ctxvar.set("ham")
ctx.run(func)  # works
await ctx.run(coro)  # breaks

asyncio.run(main())
```

Thanks!

--
components: Library (Lib)
messages: 398924
nosy: adriangb
priority: normal
severity: normal
status: open
title: contextvars.Context.run w/ coroutines gives inconsistent behavior
type: behavior
versions: Python 3.9

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