[issue45833] NamedTemporaryFile deleted before enclosing context manager exit

2021-11-17 Thread Brian McCutchon


New submission from Brian McCutchon :

Consider the following code:

# Copyright 2021 Google LLC.
# SPDX-License-Identifier: Apache-2.0
import contextlib
import os

@contextlib.contextmanager
def my_tmp_file():
  with tempfile.NamedTemporaryFile('w') as f:
yield f

os.stat(my_tmp_file().__enter__().name)  # File not found
os.stat(contextlib.ExitStack().enter_context(my_tmp_file()).name)  # Same

I would expect the file to still exist, as __exit__ has not been called and I 
can't see why the file would have been closed. Also, it performs as expected 
when using NamedTemporaryFile directly, but not when it is nested in another 
context manager. It also performs as expected when my_tmp_file() or 
contextlib.ExitStack() is used in a "with" statement.

--
components: Library (Lib)
messages: 406494
nosy: Brian McCutchon
priority: normal
severity: normal
status: open
title: NamedTemporaryFile deleted before enclosing context manager exit
type: behavior
versions: Python 3.9

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



[issue36395] Add deferred single-threaded/fake executor to concurrent.futures

2019-03-21 Thread Brian McCutchon


New submission from Brian McCutchon :

Currently, it is possible to make a basic single-threaded executor for unit 
testing:

class FakeExecutor(futures.Executor):

  def submit(self, f, *args, **kwargs):
future = futures.Future()
future.set_result(f(*args, **kwargs))
return future

  def shutdown(self, wait=True):
pass

However, this evaluates the provided function eagerly, which may be undesirable 
for tests. It prevents the tests from catching a whole class of errors (those 
where the caller forgot to call .result() on a future that is only desirable 
for its side-effects). It would be great to have an Executor implementation 
where the function is only called when .result() is called so tests can catch 
those errors.

I might add that, while future.set_result is documented as being supported for 
unit tests, a comment in the CPython source says that Future.__init__() "Should 
not be called by clients" 
(https://github.com/python/cpython/blob/master/Lib/concurrent/futures/_base.py#L317),
 suggesting that even the above code is unsupported and leaving me wondering 
how I should test future-heavy code without using mock.patch on everything.

-- Alternatives that don't work --

One might think it possible to create a FakeFuture to do this:

class FakeFuture(object):

  def __init__(self, to_invoke):
self._to_invoke = to_invoke

  def result(self, timeout=None):
return self._to_invoke()

However, futures.wait is not happy with this:

futures.wait([FakeFuture(lambda x: 1)])  # AttributeError: 'FakeFuture' object 
has no attribute '_condition'

If FakeFuture is made to extend futures.Future, the above line instead hangs:

class FakeFuture(futures.Future):

  def __init__(self, to_invoke):
super(FakeFuture, self).__init__()
self._to_invoke = to_invoke

  def result(self, timeout=None):
return self._to_invoke()

I feel like I shouldn't have to patch out wait() in order to get good unit 
tests.

--
messages: 338576
nosy: Brian McCutchon
priority: normal
severity: normal
status: open
title: Add deferred single-threaded/fake executor to concurrent.futures
type: enhancement
versions: Python 3.7

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



[issue36395] Add deferred single-threaded/fake executor to concurrent.futures

2019-05-06 Thread Brian McCutchon


Brian McCutchon  added the comment:

Mostly nondeterminism. It seems like creating a ThreadPoolExecutor with one 
worker could still be nondeterministic, as there are two threads: the main 
thread and the worker thread. It gets worse if multiple executors are needed.

Another option would be to design and document futures.Executor to be extended 
so that I can make my own fake executor.

--

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



[issue36395] Add deferred single-threaded/fake executor to concurrent.futures

2019-05-06 Thread Brian McCutchon


Brian McCutchon  added the comment:

I understand your hesitation to add a fake. Would it be better to make it 
possible to subclass Executor so that a third party implementation of this can 
be developed?

As for an example, here is an example of nondeterminism when using a 
ThreadPoolExecutor with a single worker. It sometimes prints "False" and 
sometimes "True" on my machine.

from concurrent import futures
import time

complete = False

def complete_eventually():
  global complete
  for _ in range(15):
pass
  complete = True

with futures.ThreadPoolExecutor(max_workers=1) as pool:
  pool.submit(complete_eventually)
  print(complete)

--

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



[issue36395] Add deferred single-threaded/fake executor to concurrent.futures

2019-05-07 Thread Brian McCutchon


Brian McCutchon  added the comment:

No, I do not have such an example, as most of my tests try to fake the 
executors.

--

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