lesteve: @aabadie if you are around and have some spare bandwidth, I would definitely be interested to have your opinion on this!

I may have overlooked some important reasons about why `__reduce__` functions were implemented this way.
codecov[bot]: # [Codecov](https://codecov.io/gh/joblib/joblib/pull/746?src=pr&el=h1) Report
> Merging [#746](https://codecov.io/gh/joblib/joblib/pull/746?src=pr&el=desc) into [master](https://codecov.io/gh/joblib/joblib/commit/aaba4f0ce048b1c39fde202a826ea09e4d4fadba?src=pr&el=desc) will **decrease** coverage by `4.01%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/joblib/joblib/pull/746/graphs/tree.svg?width=650&height=150&src=pr&token=gA6LF5DGTW)](https://codecov.io/gh/joblib/joblib/pull/746?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #746      +/-   ##
==========================================
- Coverage   95.28%   91.26%   -4.02%     
==========================================
  Files          42       42              
  Lines        6128     6171      +43     
==========================================
- Hits         5839     5632     -207     
- Misses        289      539     +250
```


| [Impacted Files](https://codecov.io/gh/joblib/joblib/pull/746?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [joblib/test/test\_memory.py](https://codecov.io/gh/joblib/joblib/pull/746/diff?src=pr&el=tree#diff-am9ibGliL3Rlc3QvdGVzdF9tZW1vcnkucHk=) | `97.61% <100%> (+0.12%)` | :arrow_up: |
| [joblib/memory.py](https://codecov.io/gh/joblib/joblib/pull/746/diff?src=pr&el=tree#diff-am9ibGliL21lbW9yeS5weQ==) | `94.98% <100%> (-0.39%)` | :arrow_down: |
| [joblib/\_memory\_helpers.py](https://codecov.io/gh/joblib/joblib/pull/746/diff?src=pr&el=tree#diff-am9ibGliL19tZW1vcnlfaGVscGVycy5weQ==) | `3.07% <0%> (-70.77%)` | :arrow_down: |
| [joblib/backports.py](https://codecov.io/gh/joblib/joblib/pull/746/diff?src=pr&el=tree#diff-am9ibGliL2JhY2twb3J0cy5weQ==) | `33.33% <0%> (-62.51%)` | :arrow_down: |
| [joblib/test/test\_dask.py](https://codecov.io/gh/joblib/joblib/pull/746/diff?src=pr&el=tree#diff-am9ibGliL3Rlc3QvdGVzdF9kYXNrLnB5) | `83.01% <0%> (-15.1%)` | :arrow_down: |
| [joblib/format\_stack.py](https://codecov.io/gh/joblib/joblib/pull/746/diff?src=pr&el=tree#diff-am9ibGliL2Zvcm1hdF9zdGFjay5weQ==) | `71.77% <0%> (-11.49%)` | :arrow_down: |
| [joblib/\_multiprocessing\_helpers.py](https://codecov.io/gh/joblib/joblib/pull/746/diff?src=pr&el=tree#diff-am9ibGliL19tdWx0aXByb2Nlc3NpbmdfaGVscGVycy5weQ==) | `66.66% <0%> (-9.53%)` | :arrow_down: |
| [joblib/my\_exceptions.py](https://codecov.io/gh/joblib/joblib/pull/746/diff?src=pr&el=tree#diff-am9ibGliL215X2V4Y2VwdGlvbnMucHk=) | `88.67% <0%> (-9.44%)` | :arrow_down: |
| [joblib/\_compat.py](https://codecov.io/gh/joblib/joblib/pull/746/diff?src=pr&el=tree#diff-am9ibGliL19jb21wYXQucHk=) | `90.9% <0%> (-9.1%)` | :arrow_down: |
| [joblib/pool.py](https://codecov.io/gh/joblib/joblib/pull/746/diff?src=pr&el=tree#diff-am9ibGliL3Bvb2wucHk=) | `83.62% <0%> (-7.76%)` | :arrow_down: |
| ... and [19 more](https://codecov.io/gh/joblib/joblib/pull/746/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/joblib/joblib/pull/746?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/joblib/joblib/pull/746?src=pr&el=footer). Last update [aaba4f0...a31ca64](https://codecov.io/gh/joblib/joblib/pull/746?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

lesteve: > it feels like there is some tension between hashing and cloning in the implementation of `__reduce__`. 

Just to elaborate on this, let's take the example of `verbose` in `Memory`:
- argument for `hashing`. If you have a snippet like this:
```py
memory = Memory(location='/my/location')
pipe = Pipeline(memory=memory, ...)

func_cached = memory.cache(func)

func_cached(pipe)
```
you don't want the hash of `pipe` to change if you change `memory.verbose` because that could lead to time-consuming recomputations. In this case, you don't want `verbose` in `Memory.__reduce__`.

- argument for `cloning`. You have a snippet like this:
```py
memory = Memory(location='/my/location', verbose=10)
memory_copy = copy.deepcopy(memory)
assert memory_copy.verbose == 10  # this seems like a very reasonable expectation
```
The assert will fail unless you have `verbose` in `Memory.__reduce__`.
lesteve: > I think this is more complex than it should be. I don't think we need to introduce _reconstruction_from_parameters_dict.

I tried using `__getstate__` to make it simpler. Looking at the code in 0.11, it feels like all the `__reduce__` was trying to do is ignore `timestamp` (for hashing purposes)

> I don't think we should change the stored attributes on the objects just to make pickling easier to manage.

I have reduced attribute changes to a minimum. The only thing I have kept is `compress` because it is needed to be passed properly to `MemorizedFunc`

> And I wonder if the tests are too complicated to read: what are the practical differences between this and my tests?

IIRC you were only testing `Memory`, whereas because I found problems with `MemorizedFunc` and `MemorizedResult` so I decided to test them too. More than happy to make the test easier to read if you have suggestions!

ogrisel: This does not solve the problem of piclkle in 0.11 and load in 0.12 though:

```
>>> import pickle
>>> pickle
pickle.loads(b'\x80\x03cjoblib.memory\nMemory\nq\x00(X\t\x00\x00\x00/tmp/testq\x01N\x89K\x01tq\x02Rq\x03.')
Traceback (most recent call last):
  File "<ipython-input-3-1cde88ec75ed>", line 2, in <module>
    pickle.loads(b'\x80\x03cjoblib.memory\nMemory\nq\x00(X\t\x00\x00\x00/tmp/testq\x01N\x89K\x01tq\x02Rq\x03.')
  File "/volatile/ogrisel/code/joblib/joblib/memory.py", line 837, in __init__
    location, cachedir))
ValueError: You set both "location='/tmp/test' and "cachedir=False". 'cachedir' has been deprecated in version 0.12 and will be removed in version 0.14.
Please only set "location='/tmp/test'"
```
aabadie: Thanks for providing a fix @lesteve. Using set_state looks more robust than reduce.

> I may have overlooked some important reasons about why __reduce__ functions were implemented this way.

The changes here may impact related projects that already provide custom store backends, like joblib-s3 or joblib-hadoop. They will probably need an update (not verified yet)
ogrisel: Thanks for the fix @lesteve!

@jnothman I think I prefer the `__getstate__` solution to yours and plan to merge this PR so as to be able to release joblib 0.12.2 with this fix before scikit-learn 0.20 final. Any final review/comment prior to merging?
aabadie: @lesteve, just in case #752 was merged and this one needs rebase now.
lesteve: Rebased.
aabadie: Adding an entry in the changelog would be great.
diff --git a/CHANGES.rst b/CHANGES.rst
index 35f50e2..b048c67 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,13 +1,17 @@
 Latest changes
 ===============
 
-Release 0.12.3
---------------
+master
+------
 
 Alexandre Abadie
 
     Fix MemorizedResult not picklable (#747).
 
+Loïc Estève
+
+    Fix Memory, MemorizedFunc and MemorizedResult round-trip pickling +
+    unpickling (#746).
 
 Release 0.12.2
 --------------
diff --git a/examples/compressors_comparison.py b/examples/compressors_comparison.py
index 5dee5a7..bc10f42 100644
--- a/examples/compressors_comparison.py
+++ b/examples/compressors_comparison.py
@@ -33,7 +33,7 @@ names = ("duration, protocol_type, service, flag, src_bytes, "
          "root_shell, su_attempted, num_root, "
          "num_file_creations, ").split(', ')
 
-data = pd.read_csv(url, names=names, nrows=1000)
+data = pd.read_csv(url, names=names, nrows=1e6)
 
 ###############################################################################
 # Dump and load the dataset without compression
@@ -196,7 +196,7 @@ p2 = plt.bar(ind, load_durations, width, bottom=dump_durations)
 plt.ylabel('Time in seconds')
 plt.title('Dump and load durations')
 plt.xticks(ind, ('Raw', 'LZ4', 'Zlib', 'LZMA'))
-plt.yticks(np.arange(0, lzma_load_duration + lzma_dump_duration, 0.01))
+plt.yticks(np.arange(0, lzma_load_duration + lzma_dump_duration))
 plt.legend((p1[0], p2[0]), ('Dump duration', 'Load duration'))
 
 ###############################################################################
diff --git a/joblib/memory.py b/joblib/memory.py
index 1cebe63..8243b79 100644
--- a/joblib/memory.py
+++ b/joblib/memory.py
@@ -262,10 +262,11 @@ class MemorizedResult(Logger):
                         func=self.func,
                         args_id=self.args_id
                         ))
-    def __reduce__(self):
-        return (self.__class__,
-                (self.store_backend, self.func, self.args_id),
-                {'mmap_mode': self.mmap_mode})
+
+    def __getstate__(self):
+        state = self.__dict__.copy()
+        state['timestamp'] = None
+        return state
 
 
 class NotMemorizedResult(object):
@@ -330,9 +331,6 @@ class NotMemorizedFunc(object):
     def call_and_shelve(self, *args, **kwargs):
         return NotMemorizedResult(self.func(*args, **kwargs))
 
-    def __reduce__(self):
-        return (self.__class__, (self.func,))
-
     def __repr__(self):
         return '{0}(func={1})'.format(self.__class__.__name__, self.func)
 
@@ -392,6 +390,7 @@ class MemorizedFunc(Logger):
         self.mmap_mode = mmap_mode
         self.compress = compress
         self.func = func
+
         if ignore is None:
             ignore = []
         self.ignore = ignore
@@ -516,13 +515,13 @@ class MemorizedFunc(Logger):
     def __call__(self, *args, **kwargs):
         return self._cached_call(args, kwargs)[0]
 
-    def __reduce__(self):
+    def __getstate__(self):
         """ We don't store the timestamp when pickling, to avoid the hash
             depending from it.
-            In addition, when unpickling, we run the __init__
         """
-        return (self.__class__, (self.func, self.store_backend, self.ignore,
-                self.mmap_mode, self.compress, self._verbose))
+        state = self.__dict__.copy()
+        state['timestamp'] = None
+        return state
 
     # ------------------------------------------------------------------------
     # Private interface
@@ -823,6 +822,7 @@ class Memory(Logger):
         self.timestamp = time.time()
         self.bytes_limit = bytes_limit
         self.backend = backend
+        self.compress = compress
         if backend_options is None:
             backend_options = {}
         self.backend_options = backend_options
@@ -906,9 +906,11 @@ class Memory(Logger):
             mmap_mode = self.mmap_mode
         if isinstance(func, MemorizedFunc):
             func = func.func
-        return MemorizedFunc(func, self.store_backend, mmap_mode=mmap_mode,
-                             ignore=ignore, verbose=verbose,
-                             timestamp=self.timestamp)
+        return MemorizedFunc(func, location=self.store_backend,
+                             backend=self.backend,
+                             ignore=ignore, mmap_mode=mmap_mode,
+                             compress=self.compress,
+                             verbose=verbose, timestamp=self.timestamp)
 
     def clear(self, warn=True):
         """ Erase the complete cache directory.
@@ -945,15 +947,10 @@ class Memory(Logger):
             self.__class__.__name__, (repr(None) if self.store_backend is None
                                       else repr(self.store_backend)))
 
-    def __reduce__(self):
+    def __getstate__(self):
         """ We don't store the timestamp when pickling, to avoid the hash
             depending from it.
-            In addition, when unpickling, we run the __init__
         """
-        # We need to remove 'joblib' from the end of cachedir
-        location = (repr(self.store_backend)[:-7]
-                    if self.store_backend is not None else None)
-        compress = self.store_backend.compress \
-            if self.store_backend is not None else False
-        return (self.__class__, (location, self.backend, self.mmap_mode,
-                                 compress, self._verbose))
+        state = self.__dict__.copy()
+        state['timestamp'] = None
+        return state

Memory.__reduce__ is broken since cachedir deprecation
Memory can't be pickled/unpickled.

It defines `__reduce__` to exclude a timestamp from the pickle.

But `__reduce__` includes:

```
        return (self.__class__, (location, self.backend, self.mmap_mode,
                                 compress, self._verbose))
```

where `__init__` is:

```
    def __init__(self, location=None, backend='local', cachedir=None,
                 mmap_mode=None, compress=False, verbose=1, bytes_limit=None,
                 backend_options={})
```

`cachedir`, not `mmap_mode` is now the third positional argument.  Perhaps it should be the last, and then `__reduce__` need not be changed. Or `__reduce__` can be fixed and changed again when the deprecation is completed.
diff --git a/joblib/test/test_memory.py b/joblib/test/test_memory.py
index 4690b5b..b333a48 100644
--- a/joblib/test/test_memory.py
+++ b/joblib/test/test_memory.py
@@ -14,6 +14,8 @@ import sys
 import time
 import datetime
 
+import pytest
+
 from joblib.memory import Memory
 from joblib.memory import MemorizedFunc, NotMemorizedFunc
 from joblib.memory import MemorizedResult, NotMemorizedResult
@@ -27,6 +29,7 @@ from joblib.test.common import with_numpy, np
 from joblib.test.common import with_multiprocessing
 from joblib.testing import parametrize, raises, warns
 from joblib._compat import PY3_OR_LATER
+from joblib.hashing import hash
 
 
 ###############################################################################
@@ -986,3 +989,52 @@ def test_memorized_result_pickle(tmpdir):
     assert memorized_result.func == memorized_result_loads.func
     assert memorized_result.args_id == memorized_result_loads.args_id
     assert str(memorized_result) == str(memorized_result_loads)
+
+
+def compare(left, right, ignored_attrs=None):
+    if ignored_attrs is None:
+        ignored_attrs = []
+
+    left_vars = vars(left)
+    right_vars = vars(right)
+    assert set(left_vars.keys()) == set(right_vars.keys())
+    for attr in left_vars.keys():
+        if attr in ignored_attrs:
+            continue
+        assert left_vars[attr] == right_vars[attr]
+
+
+@pytest.mark.parametrize('memory_kwargs',
+                         [{'compress': 3, 'verbose': 2},
+                          {'mmap_mode': 'r', 'verbose': 5, 'bytes_limit': 1e6,
+                           'backend_options': {'parameter': 'unused'}}])
+def test_memory_pickle_dump_load(tmpdir, memory_kwargs):
+    memory = Memory(location=tmpdir.strpath, **memory_kwargs)
+
+    memory_reloaded = pickle.loads(pickle.dumps(memory))
+
+    # Compare Memory instance before and after pickle roundtrip
+    compare(memory.store_backend, memory_reloaded.store_backend)
+    compare(memory, memory_reloaded,
+            ignored_attrs=set(['store_backend', 'timestamp']))
+    assert hash(memory) == hash(memory_reloaded)
+
+    func_cached = memory.cache(f)
+
+    func_cached_reloaded = pickle.loads(pickle.dumps(func_cached))
+
+    # Compare MemorizedFunc instance before/after pickle roundtrip
+    compare(func_cached.store_backend, func_cached_reloaded.store_backend)
+    compare(func_cached, func_cached_reloaded,
+            ignored_attrs=set(['store_backend', 'timestamp']))
+    assert hash(func_cached) == hash(func_cached_reloaded)
+
+    # Compare MemorizedResult instance before/after pickle roundtrip
+    memorized_result = func_cached.call_and_shelve(1)
+    memorized_result_reloaded = pickle.loads(pickle.dumps(memorized_result))
+
+    compare(memorized_result.store_backend,
+            memorized_result_reloaded.store_backend)
+    compare(memorized_result, memorized_result_reloaded,
+            ignored_attrs=set(['store_backend', 'timestamp']))
+    assert hash(memorized_result) == hash(memorized_result_reloaded)
diff --git a/joblib/test/test_parallel.py b/joblib/test/test_parallel.py
index fa0c69b..b5073b3 100644
--- a/joblib/test/test_parallel.py
+++ b/joblib/test/test_parallel.py
@@ -241,6 +241,17 @@ def test_nested_loop(parent_backend, child_backend):
         delayed(nested_loop)(child_backend) for _ in range(2))
 
 
+def raise_exception(backend):
+    raise ValueError
+
+
+def test_nested_loop_with_exception_with_loky():
+    with raises(ValueError):
+        with Parallel(n_jobs=2, backend="loky") as parallel:
+            parallel([delayed(nested_loop)("loky"),
+                      delayed(raise_exception)("loky")])
+
+
 def test_mutate_input_with_threads():
     """Input is mutable when using the threading backend"""
     q = Queue(maxsize=5)

pip install -e .
parse_log_pytest
pytest
pytest pytest-timeout pytest-cov codecov
3.6
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs @ file:///opt/conda/conda-bld/attrs_1642510447205/work
certifi==2021.5.30
charset-normalizer==2.0.12
codecov==2.1.13
coverage==6.2
idna==3.10
importlib-metadata @ file:///tmp/build/80754af9/importlib-metadata_1631916693255/work
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
-e git+https://github.com/joblib/joblib.git@6ce40a7c1efb2d577b0899e34cf9b787a1971d41#egg=joblib
more-itertools @ file:///tmp/build/80754af9/more-itertools_1637733554872/work
packaging @ file:///tmp/build/80754af9/packaging_1637314298585/work
pluggy @ file:///tmp/build/80754af9/pluggy_1615976315926/work
py @ file:///opt/conda/conda-bld/py_1644396412707/work
pyparsing @ file:///tmp/build/80754af9/pyparsing_1635766073266/work
pytest==6.2.4
pytest-cov==4.0.0
pytest-timeout==2.1.0
requests==2.27.1
toml @ file:///tmp/build/80754af9/toml_1616166611790/work
tomli==1.2.3
typing_extensions @ file:///opt/conda/conda-bld/typing_extensions_1647553014482/work
urllib3==1.26.20
zipp @ file:///tmp/build/80754af9/zipp_1633618647012/work

name: joblib
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - attrs=21.4.0=pyhd3eb1b0_0
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - importlib-metadata=4.8.1=py36h06a4308_0
  - importlib_metadata=4.8.1=hd3eb1b0_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - more-itertools=8.12.0=pyhd3eb1b0_0
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - packaging=21.3=pyhd3eb1b0_0
  - pip=21.2.2=py36h06a4308_0
  - pluggy=0.13.1=py36h06a4308_0
  - py=1.11.0=pyhd3eb1b0_0
  - pyparsing=3.0.4=pyhd3eb1b0_0
  - pytest=6.2.4=py36h06a4308_2
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - toml=0.10.2=pyhd3eb1b0_0
  - typing_extensions=4.1.1=pyh06a4308_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zipp=3.6.0=pyhd3eb1b0_0
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - charset-normalizer==2.0.12
      - codecov==2.1.13
      - coverage==6.2
      - idna==3.10
      - pytest-cov==4.0.0
      - pytest-timeout==2.1.0
      - requests==2.27.1
      - tomli==1.2.3
      - urllib3==1.26.20
prefix: /opt/conda/envs/joblib

joblib/test/test_memory.py::test_memory_pickle_dump_load[memory_kwargs0] joblib/test/test_memory.py::test_memory_pickle_dump_load[memory_kwargs1]
joblib/test/test_memory.py::test_memory_integration joblib/test/test_memory.py::test_no_memory joblib/test/test_memory.py::test_memory_kwarg joblib/test/test_memory.py::test_memory_lambda joblib/test/test_memory.py::test_memory_name_collision joblib/test/test_memory.py::test_memory_warning_lambda_collisions joblib/test/test_memory.py::test_memory_warning_collision_detection joblib/test/test_memory.py::test_memory_partial joblib/test/test_memory.py::test_memory_eval joblib/test/test_memory.py::test_argument_change joblib/test/test_memory.py::test_memory_exception joblib/test/test_memory.py::test_memory_ignore joblib/test/test_memory.py::test_partial_decoration[ignore0-100-r] joblib/test/test_memory.py::test_partial_decoration[ignore1-10-None] joblib/test/test_memory.py::test_func_dir joblib/test/test_memory.py::test_persistence joblib/test/test_memory.py::test_call_and_shelve joblib/test/test_memory.py::test_call_and_shelve_argument_hash joblib/test/test_memory.py::test_memorized_pickling joblib/test/test_memory.py::test_memorized_repr joblib/test/test_memory.py::test_memory_file_modification joblib/test/test_memory.py::test_memory_in_memory_function_code_change joblib/test/test_memory.py::test_clear_memory_with_none_location joblib/test/test_memory.py::test_memory_func_with_kwonly_args joblib/test/test_memory.py::test_memory_func_with_signature joblib/test/test_memory.py::test__get_items joblib/test/test_memory.py::test__get_items_to_delete joblib/test/test_memory.py::test_memory_reduce_size joblib/test/test_memory.py::test_memory_clear joblib/test/test_memory.py::test_cached_function_race_condition_when_persisting_output joblib/test/test_memory.py::test_cached_function_race_condition_when_persisting_output_2 joblib/test/test_memory.py::test_memory_recomputes_after_an_error_why_loading_results joblib/test/test_memory.py::test_deprecated_cachedir_behaviour joblib/test/test_memory.py::test_register_invalid_store_backends_key[None] joblib/test/test_memory.py::test_register_invalid_store_backends_key[invalid_prefix1] joblib/test/test_memory.py::test_register_invalid_store_backends_key[invalid_prefix2] joblib/test/test_memory.py::test_register_invalid_store_backends_object joblib/test/test_memory.py::test_memory_default_store_backend joblib/test/test_memory.py::test_instanciate_incomplete_store_backend joblib/test/test_memory.py::test_dummy_store_backend joblib/test/test_memory.py::test_memorized_result_pickle joblib/test/test_parallel.py::test_cpu_count joblib/test/test_parallel.py::test_effective_n_jobs joblib/test/test_parallel.py::test_simple_parallel[2-1-None] joblib/test/test_parallel.py::test_simple_parallel[2-1-loky] joblib/test/test_parallel.py::test_simple_parallel[2-1-multiprocessing] joblib/test/test_parallel.py::test_simple_parallel[2-1-sequential] joblib/test/test_parallel.py::test_simple_parallel[2-1-threading] joblib/test/test_parallel.py::test_simple_parallel[2-1-backend5] joblib/test/test_parallel.py::test_simple_parallel[2-1-backend6] joblib/test/test_parallel.py::test_simple_parallel[2-1-backend7] joblib/test/test_parallel.py::test_simple_parallel[2-1-backend8] joblib/test/test_parallel.py::test_simple_parallel[2-1-backend9] joblib/test/test_parallel.py::test_simple_parallel[2-2-None] joblib/test/test_parallel.py::test_simple_parallel[2-2-loky] joblib/test/test_parallel.py::test_simple_parallel[2-2-multiprocessing] joblib/test/test_parallel.py::test_simple_parallel[2-2-sequential] joblib/test/test_parallel.py::test_simple_parallel[2-2-threading] joblib/test/test_parallel.py::test_simple_parallel[2-2-backend5] joblib/test/test_parallel.py::test_simple_parallel[2-2-backend6] joblib/test/test_parallel.py::test_simple_parallel[2-2-backend7] joblib/test/test_parallel.py::test_simple_parallel[2-2-backend8] joblib/test/test_parallel.py::test_simple_parallel[2-2-backend9] joblib/test/test_parallel.py::test_simple_parallel[2--1-None] joblib/test/test_parallel.py::test_simple_parallel[2--1-loky] joblib/test/test_parallel.py::test_simple_parallel[2--1-multiprocessing] joblib/test/test_parallel.py::test_simple_parallel[2--1-sequential] joblib/test/test_parallel.py::test_simple_parallel[2--1-threading] joblib/test/test_parallel.py::test_simple_parallel[2--1-backend5] joblib/test/test_parallel.py::test_simple_parallel[2--1-backend6] joblib/test/test_parallel.py::test_simple_parallel[2--1-backend7] joblib/test/test_parallel.py::test_simple_parallel[2--1-backend8] joblib/test/test_parallel.py::test_simple_parallel[2--1-backend9] joblib/test/test_parallel.py::test_simple_parallel[2--2-None] joblib/test/test_parallel.py::test_simple_parallel[2--2-loky] joblib/test/test_parallel.py::test_simple_parallel[2--2-multiprocessing] joblib/test/test_parallel.py::test_simple_parallel[2--2-sequential] joblib/test/test_parallel.py::test_simple_parallel[2--2-threading] joblib/test/test_parallel.py::test_simple_parallel[2--2-backend5] joblib/test/test_parallel.py::test_simple_parallel[2--2-backend6] joblib/test/test_parallel.py::test_simple_parallel[2--2-backend7] joblib/test/test_parallel.py::test_simple_parallel[2--2-backend8] joblib/test/test_parallel.py::test_simple_parallel[2--2-backend9] joblib/test/test_parallel.py::test_simple_parallel[11-1-None] joblib/test/test_parallel.py::test_simple_parallel[11-1-loky] joblib/test/test_parallel.py::test_simple_parallel[11-1-multiprocessing] joblib/test/test_parallel.py::test_simple_parallel[11-1-sequential] joblib/test/test_parallel.py::test_simple_parallel[11-1-threading] joblib/test/test_parallel.py::test_simple_parallel[11-1-backend5] joblib/test/test_parallel.py::test_simple_parallel[11-1-backend6] joblib/test/test_parallel.py::test_simple_parallel[11-1-backend7] joblib/test/test_parallel.py::test_simple_parallel[11-1-backend8] joblib/test/test_parallel.py::test_simple_parallel[11-1-backend9] joblib/test/test_parallel.py::test_simple_parallel[11-2-None] joblib/test/test_parallel.py::test_simple_parallel[11-2-loky] joblib/test/test_parallel.py::test_simple_parallel[11-2-multiprocessing] joblib/test/test_parallel.py::test_simple_parallel[11-2-sequential] joblib/test/test_parallel.py::test_simple_parallel[11-2-threading] joblib/test/test_parallel.py::test_simple_parallel[11-2-backend5] joblib/test/test_parallel.py::test_simple_parallel[11-2-backend6] joblib/test/test_parallel.py::test_simple_parallel[11-2-backend7] joblib/test/test_parallel.py::test_simple_parallel[11-2-backend8] joblib/test/test_parallel.py::test_simple_parallel[11-2-backend9] joblib/test/test_parallel.py::test_simple_parallel[11--1-None] joblib/test/test_parallel.py::test_simple_parallel[11--1-loky] joblib/test/test_parallel.py::test_simple_parallel[11--1-multiprocessing] joblib/test/test_parallel.py::test_simple_parallel[11--1-sequential] joblib/test/test_parallel.py::test_simple_parallel[11--1-threading] joblib/test/test_parallel.py::test_simple_parallel[11--1-backend5] joblib/test/test_parallel.py::test_simple_parallel[11--1-backend6] joblib/test/test_parallel.py::test_simple_parallel[11--1-backend7] joblib/test/test_parallel.py::test_simple_parallel[11--1-backend8] joblib/test/test_parallel.py::test_simple_parallel[11--1-backend9] joblib/test/test_parallel.py::test_simple_parallel[11--2-None] joblib/test/test_parallel.py::test_simple_parallel[11--2-loky] joblib/test/test_parallel.py::test_simple_parallel[11--2-multiprocessing] joblib/test/test_parallel.py::test_simple_parallel[11--2-sequential] joblib/test/test_parallel.py::test_simple_parallel[11--2-threading] joblib/test/test_parallel.py::test_simple_parallel[11--2-backend5] joblib/test/test_parallel.py::test_simple_parallel[11--2-backend6] joblib/test/test_parallel.py::test_simple_parallel[11--2-backend7] joblib/test/test_parallel.py::test_simple_parallel[11--2-backend8] joblib/test/test_parallel.py::test_simple_parallel[11--2-backend9] joblib/test/test_parallel.py::test_simple_parallel[100-1-None] joblib/test/test_parallel.py::test_simple_parallel[100-1-loky] joblib/test/test_parallel.py::test_simple_parallel[100-1-multiprocessing] joblib/test/test_parallel.py::test_simple_parallel[100-1-sequential] joblib/test/test_parallel.py::test_simple_parallel[100-1-threading] joblib/test/test_parallel.py::test_simple_parallel[100-1-backend5] joblib/test/test_parallel.py::test_simple_parallel[100-1-backend6] joblib/test/test_parallel.py::test_simple_parallel[100-1-backend7] joblib/test/test_parallel.py::test_simple_parallel[100-1-backend8] joblib/test/test_parallel.py::test_simple_parallel[100-1-backend9] joblib/test/test_parallel.py::test_simple_parallel[100-2-None] joblib/test/test_parallel.py::test_simple_parallel[100-2-loky] joblib/test/test_parallel.py::test_simple_parallel[100-2-multiprocessing] joblib/test/test_parallel.py::test_simple_parallel[100-2-sequential] joblib/test/test_parallel.py::test_simple_parallel[100-2-threading] joblib/test/test_parallel.py::test_simple_parallel[100-2-backend5] joblib/test/test_parallel.py::test_simple_parallel[100-2-backend6] joblib/test/test_parallel.py::test_simple_parallel[100-2-backend7] joblib/test/test_parallel.py::test_simple_parallel[100-2-backend8] joblib/test/test_parallel.py::test_simple_parallel[100-2-backend9] joblib/test/test_parallel.py::test_simple_parallel[100--1-None] joblib/test/test_parallel.py::test_simple_parallel[100--1-loky] joblib/test/test_parallel.py::test_simple_parallel[100--1-multiprocessing] joblib/test/test_parallel.py::test_simple_parallel[100--1-sequential] joblib/test/test_parallel.py::test_simple_parallel[100--1-threading] joblib/test/test_parallel.py::test_simple_parallel[100--1-backend5] joblib/test/test_parallel.py::test_simple_parallel[100--1-backend6] joblib/test/test_parallel.py::test_simple_parallel[100--1-backend7] joblib/test/test_parallel.py::test_simple_parallel[100--1-backend8] joblib/test/test_parallel.py::test_simple_parallel[100--1-backend9] joblib/test/test_parallel.py::test_simple_parallel[100--2-None] joblib/test/test_parallel.py::test_simple_parallel[100--2-loky] joblib/test/test_parallel.py::test_simple_parallel[100--2-multiprocessing] joblib/test/test_parallel.py::test_simple_parallel[100--2-sequential] joblib/test/test_parallel.py::test_simple_parallel[100--2-threading] joblib/test/test_parallel.py::test_simple_parallel[100--2-backend5] joblib/test/test_parallel.py::test_simple_parallel[100--2-backend6] joblib/test/test_parallel.py::test_simple_parallel[100--2-backend7] joblib/test/test_parallel.py::test_simple_parallel[100--2-backend8] joblib/test/test_parallel.py::test_simple_parallel[100--2-backend9] joblib/test/test_parallel.py::test_main_thread_renamed_no_warning[None] joblib/test/test_parallel.py::test_main_thread_renamed_no_warning[loky] joblib/test/test_parallel.py::test_main_thread_renamed_no_warning[multiprocessing] joblib/test/test_parallel.py::test_main_thread_renamed_no_warning[sequential] joblib/test/test_parallel.py::test_main_thread_renamed_no_warning[threading] joblib/test/test_parallel.py::test_main_thread_renamed_no_warning[backend5] joblib/test/test_parallel.py::test_main_thread_renamed_no_warning[backend6] joblib/test/test_parallel.py::test_main_thread_renamed_no_warning[backend7] joblib/test/test_parallel.py::test_main_thread_renamed_no_warning[backend8] joblib/test/test_parallel.py::test_main_thread_renamed_no_warning[backend9] joblib/test/test_parallel.py::test_nested_parallel_warnings[loky-multiprocessing-True] joblib/test/test_parallel.py::test_nested_parallel_warnings[loky-loky-False] joblib/test/test_parallel.py::test_nested_parallel_warnings[multiprocessing-multiprocessing-True] joblib/test/test_parallel.py::test_nested_parallel_warnings[multiprocessing-loky-True] joblib/test/test_parallel.py::test_nested_parallel_warnings[threading-multiprocessing-True] joblib/test/test_parallel.py::test_nested_parallel_warnings[threading-loky-True] joblib/test/test_parallel.py::test_nested_loop[multiprocessing-multiprocessing] joblib/test/test_parallel.py::test_nested_loop[multiprocessing-threading] joblib/test/test_parallel.py::test_nested_loop[multiprocessing-sequential] joblib/test/test_parallel.py::test_nested_loop[multiprocessing-loky] joblib/test/test_parallel.py::test_nested_loop[threading-multiprocessing] joblib/test/test_parallel.py::test_nested_loop[threading-threading] joblib/test/test_parallel.py::test_nested_loop[threading-sequential] joblib/test/test_parallel.py::test_nested_loop[threading-loky] joblib/test/test_parallel.py::test_nested_loop[sequential-multiprocessing] joblib/test/test_parallel.py::test_nested_loop[sequential-threading] joblib/test/test_parallel.py::test_nested_loop[sequential-sequential] joblib/test/test_parallel.py::test_nested_loop[sequential-loky] joblib/test/test_parallel.py::test_nested_loop[loky-multiprocessing] joblib/test/test_parallel.py::test_nested_loop[loky-threading] joblib/test/test_parallel.py::test_nested_loop[loky-sequential] joblib/test/test_parallel.py::test_nested_loop[loky-loky] joblib/test/test_parallel.py::test_nested_loop_with_exception_with_loky joblib/test/test_parallel.py::test_mutate_input_with_threads joblib/test/test_parallel.py::test_parallel_kwargs[1] joblib/test/test_parallel.py::test_parallel_kwargs[2] joblib/test/test_parallel.py::test_parallel_kwargs[3] joblib/test/test_parallel.py::test_parallel_as_context_manager[multiprocessing] joblib/test/test_parallel.py::test_parallel_as_context_manager[loky] joblib/test/test_parallel.py::test_parallel_as_context_manager[threading] joblib/test/test_parallel.py::test_parallel_pickling joblib/test/test_parallel.py::test_parallel_timeout_success[multiprocessing] joblib/test/test_parallel.py::test_parallel_timeout_success[loky] joblib/test/test_parallel.py::test_parallel_timeout_success[threading] joblib/test/test_parallel.py::test_parallel_timeout_fail[multiprocessing] joblib/test/test_parallel.py::test_parallel_timeout_fail[loky] joblib/test/test_parallel.py::test_parallel_timeout_fail[threading] joblib/test/test_parallel.py::test_error_capture[multiprocessing] joblib/test/test_parallel.py::test_error_capture[loky] joblib/test/test_parallel.py::test_dispatch_one_job[1-expected_queue0-multiprocessing] joblib/test/test_parallel.py::test_dispatch_one_job[1-expected_queue0-threading] joblib/test/test_parallel.py::test_dispatch_one_job[1-expected_queue0-sequential] joblib/test/test_parallel.py::test_dispatch_one_job[1-expected_queue0-loky] joblib/test/test_parallel.py::test_dispatch_one_job[4-expected_queue1-multiprocessing] joblib/test/test_parallel.py::test_dispatch_one_job[4-expected_queue1-threading] joblib/test/test_parallel.py::test_dispatch_one_job[4-expected_queue1-sequential] joblib/test/test_parallel.py::test_dispatch_one_job[4-expected_queue1-loky] joblib/test/test_parallel.py::test_dispatch_multiprocessing[multiprocessing] joblib/test/test_parallel.py::test_dispatch_multiprocessing[loky] joblib/test/test_parallel.py::test_dispatch_multiprocessing[threading] joblib/test/test_parallel.py::test_batching_auto_threading joblib/test/test_parallel.py::test_batching_auto_subprocesses[multiprocessing] joblib/test/test_parallel.py::test_batching_auto_subprocesses[loky] joblib/test/test_parallel.py::test_exception_dispatch joblib/test/test_parallel.py::test_nested_exception_dispatch[loky] joblib/test/test_parallel.py::test_nested_exception_dispatch[multiprocessing] joblib/test/test_parallel.py::test_nested_exception_dispatch[threading] joblib/test/test_parallel.py::test_multiple_spawning joblib/test/test_parallel.py::test_invalid_backend joblib/test/test_parallel.py::test_invalid_njobs[None] joblib/test/test_parallel.py::test_invalid_njobs[loky] joblib/test/test_parallel.py::test_invalid_njobs[multiprocessing] joblib/test/test_parallel.py::test_invalid_njobs[sequential] joblib/test/test_parallel.py::test_invalid_njobs[threading] joblib/test/test_parallel.py::test_invalid_njobs[backend5] joblib/test/test_parallel.py::test_invalid_njobs[backend6] joblib/test/test_parallel.py::test_invalid_njobs[backend7] joblib/test/test_parallel.py::test_invalid_njobs[backend8] joblib/test/test_parallel.py::test_invalid_njobs[backend9] joblib/test/test_parallel.py::test_register_parallel_backend joblib/test/test_parallel.py::test_overwrite_default_backend joblib/test/test_parallel.py::test_backend_context_manager[multiprocessing] joblib/test/test_parallel.py::test_backend_context_manager[loky] joblib/test/test_parallel.py::test_backend_context_manager[threading] joblib/test/test_parallel.py::test_backend_context_manager[test_backend_0] joblib/test/test_parallel.py::test_backend_context_manager[test_backend_1] joblib/test/test_parallel.py::test_backend_context_manager[test_backend_2] joblib/test/test_parallel.py::test_parameterized_backend_context_manager joblib/test/test_parallel.py::test_direct_parameterized_backend_context_manager joblib/test/test_parallel.py::test_nested_backend_context_manager joblib/test/test_parallel.py::test_retrieval_context joblib/test/test_parallel.py::test_joblib_exception joblib/test/test_parallel.py::test_safe_function joblib/test/test_parallel.py::test_invalid_batch_size[0] joblib/test/test_parallel.py::test_invalid_batch_size[-1] joblib/test/test_parallel.py::test_invalid_batch_size[1.42] joblib/test/test_parallel.py::test_dispatch_race_condition[2-2-all-auto] joblib/test/test_parallel.py::test_dispatch_race_condition[2-2-n_jobs-auto] joblib/test/test_parallel.py::test_dispatch_race_condition[10-2-n_jobs-auto0] joblib/test/test_parallel.py::test_dispatch_race_condition[517-2-n_jobs-auto] joblib/test/test_parallel.py::test_dispatch_race_condition[10-2-n_jobs-auto1] joblib/test/test_parallel.py::test_dispatch_race_condition[10-4-n_jobs-auto] joblib/test/test_parallel.py::test_dispatch_race_condition[200-12-n_jobs-auto] joblib/test/test_parallel.py::test_dispatch_race_condition[25-12-2 joblib/test/test_parallel.py::test_dispatch_race_condition[250-12-all-1] joblib/test/test_parallel.py::test_dispatch_race_condition[250-12-2 joblib/test/test_parallel.py::test_dispatch_race_condition[200-12-2 joblib/test/test_parallel.py::test_default_mp_context joblib/test/test_parallel.py::test_parallel_with_interactively_defined_functions[multiprocessing] joblib/test/test_parallel.py::test_parallel_with_interactively_defined_functions[loky] joblib/test/test_parallel.py::test_parallel_with_interactively_defined_functions[spawn] joblib/test/test_parallel.py::test_parallel_with_unpicklable_functions_in_args[delayed-def joblib/test/test_parallel.py::test_parallel_with_unpicklable_functions_in_args[delayed-square joblib/test/test_parallel.py::test_parallel_with_unpicklable_functions_in_args[args-def joblib/test/test_parallel.py::test_parallel_with_unpicklable_functions_in_args[args-square joblib/test/test_parallel.py::test_parallel_with_unpicklable_functions_in_args[kwargs-def joblib/test/test_parallel.py::test_parallel_with_unpicklable_functions_in_args[kwargs-square joblib/test/test_parallel.py::test_parallel_with_interactively_defined_functions_default_backend joblib/test/test_parallel.py::test_parallel_with_interactively_defined_bound_method joblib/test/test_parallel.py::test_parallel_with_exhausted_iterator joblib/test/test_parallel.py::test_warning_about_timeout_not_supported_by_backend joblib/test/test_parallel.py::test_abort_backend[1-None] joblib/test/test_parallel.py::test_abort_backend[1-loky] joblib/test/test_parallel.py::test_abort_backend[1-multiprocessing] joblib/test/test_parallel.py::test_abort_backend[1-sequential] joblib/test/test_parallel.py::test_abort_backend[1-threading] joblib/test/test_parallel.py::test_abort_backend[1-backend5] joblib/test/test_parallel.py::test_abort_backend[1-backend6] joblib/test/test_parallel.py::test_abort_backend[1-backend7] joblib/test/test_parallel.py::test_abort_backend[1-backend8] joblib/test/test_parallel.py::test_abort_backend[1-backend9] joblib/test/test_parallel.py::test_abort_backend[2-None] joblib/test/test_parallel.py::test_abort_backend[2-loky] joblib/test/test_parallel.py::test_abort_backend[2-multiprocessing] joblib/test/test_parallel.py::test_abort_backend[2-sequential] joblib/test/test_parallel.py::test_abort_backend[2-threading] joblib/test/test_parallel.py::test_abort_backend[2-backend5] joblib/test/test_parallel.py::test_abort_backend[2-backend6] joblib/test/test_parallel.py::test_abort_backend[2-backend7] joblib/test/test_parallel.py::test_abort_backend[2-backend8] joblib/test/test_parallel.py::test_abort_backend[2-backend9] joblib/test/test_parallel.py::test_abort_backend[-2-None] joblib/test/test_parallel.py::test_abort_backend[-2-loky] joblib/test/test_parallel.py::test_abort_backend[-2-multiprocessing] joblib/test/test_parallel.py::test_abort_backend[-2-sequential] joblib/test/test_parallel.py::test_abort_backend[-2-threading] joblib/test/test_parallel.py::test_abort_backend[-2-backend5] joblib/test/test_parallel.py::test_abort_backend[-2-backend6] joblib/test/test_parallel.py::test_abort_backend[-2-backend7] joblib/test/test_parallel.py::test_abort_backend[-2-backend8] joblib/test/test_parallel.py::test_abort_backend[-2-backend9] joblib/test/test_parallel.py::test_abort_backend[-1-None] joblib/test/test_parallel.py::test_abort_backend[-1-loky] joblib/test/test_parallel.py::test_abort_backend[-1-multiprocessing] joblib/test/test_parallel.py::test_abort_backend[-1-sequential] joblib/test/test_parallel.py::test_abort_backend[-1-threading] joblib/test/test_parallel.py::test_abort_backend[-1-backend5] joblib/test/test_parallel.py::test_abort_backend[-1-backend6] joblib/test/test_parallel.py::test_abort_backend[-1-backend7] joblib/test/test_parallel.py::test_abort_backend[-1-backend8] joblib/test/test_parallel.py::test_abort_backend[-1-backend9] joblib/test/test_parallel.py::test_lambda_expression joblib/test/test_parallel.py::test_delayed_check_pickle_deprecated joblib/test/test_parallel.py::test_backend_batch_statistics_reset[multiprocessing] joblib/test/test_parallel.py::test_backend_batch_statistics_reset[loky] joblib/test/test_parallel.py::test_backend_hinting_and_constraints joblib/test/test_parallel.py::test_backend_hinting_and_constraints_with_custom_backends joblib/test/test_parallel.py::test_invalid_backend_hinting_and_constraints joblib/test/test_parallel.py::test_global_parallel_backend joblib/test/test_parallel.py::test_external_backends joblib/test/test_parallel.py::test_nested_parallelism_limit[loky] joblib/test/test_parallel.py::test_nested_parallelism_limit[threading] joblib/test/test_parallel.py::test_thread_bomb_mitigation[loky] joblib/test/test_parallel.py::test_thread_bomb_mitigation[threading]
examples/compressors_comparison.py joblib/memory.py CHANGES.rst
examples/compressors_comparison.py joblib/memory.py CHANGES.rst