codecov[bot]: # [Codecov](https://codecov.io/gh/joblib/joblib/pull/716?src=pr&el=h1) Report
> Merging [#716](https://codecov.io/gh/joblib/joblib/pull/716?src=pr&el=desc) into [master](https://codecov.io/gh/joblib/joblib/commit/6a2f9062dc01e1df013afb3886ffbaa266325764?src=pr&el=desc) will **decrease** coverage by `0.09%`.
> The diff coverage is `100%`.

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

```diff
@@            Coverage Diff            @@
##           master     #716     +/-   ##
=========================================
- Coverage   95.07%   94.98%   -0.1%     
=========================================
  Files          40       40             
  Lines        5751     5762     +11     
=========================================
+ Hits         5468     5473      +5     
- Misses        283      289      +6
```


| [Impacted Files](https://codecov.io/gh/joblib/joblib/pull/716?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [joblib/memory.py](https://codecov.io/gh/joblib/joblib/pull/716/diff?src=pr&el=tree#diff-am9ibGliL21lbW9yeS5weQ==) | `95.08% <100%> (-0.25%)` | :arrow_down: |
| [joblib/test/test\_memory.py](https://codecov.io/gh/joblib/joblib/pull/716/diff?src=pr&el=tree#diff-am9ibGliL3Rlc3QvdGVzdF9tZW1vcnkucHk=) | `97.49% <100%> (+0.03%)` | :arrow_up: |
| [joblib/testing.py](https://codecov.io/gh/joblib/joblib/pull/716/diff?src=pr&el=tree#diff-am9ibGliL3Rlc3RpbmcucHk=) | `87.5% <0%> (-7.5%)` | :arrow_down: |
| [joblib/func\_inspect.py](https://codecov.io/gh/joblib/joblib/pull/716/diff?src=pr&el=tree#diff-am9ibGliL2Z1bmNfaW5zcGVjdC5weQ==) | `91.42% <0%> (-3.43%)` | :arrow_down: |
| [joblib/disk.py](https://codecov.io/gh/joblib/joblib/pull/716/diff?src=pr&el=tree#diff-am9ibGliL2Rpc2sucHk=) | `88.33% <0%> (+6.66%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/joblib/joblib/pull/716?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/716?src=pr&el=footer). Last update [6a2f906...d449768](https://codecov.io/gh/joblib/joblib/pull/716?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

diff --git a/CHANGES.rst b/CHANGES.rst
index cb3bf00..3449861 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,6 +1,19 @@
 Latest changes
 ===============
 
+Release 0.12.1
+--------------
+
+Thomas Moreau
+
+    Make sure that any exception triggered when serializing jobs in the queue
+    will be wrapped as a PicklingError as in past versions of joblib.
+
+Noam Hershtig
+
+    Fix kwonlydefaults key error in filter_args (#715)
+
+
 Release 0.12
 ------------
 
diff --git a/doc/memory.rst b/doc/memory.rst
index 004a4e1..0850550 100644
--- a/doc/memory.rst
+++ b/doc/memory.rst
@@ -206,7 +206,7 @@ Getting a reference to the cache can be done using the
     >>> result = g.call_and_shelve(4)
     A long-running calculation, with parameter 4
     >>> result  #doctest: +ELLIPSIS
-    MemorizedResult(location="...", func="...g...", argument_hash="...")
+    MemorizedResult(location="...", func="...g...", args_id="...")
 
 Once computed, the output of `g` is stored on disk, and deleted from
 memory. Reading the associated value can then be performed with the
diff --git a/joblib/__init__.py b/joblib/__init__.py
index 7440f36..10ff437 100644
--- a/joblib/__init__.py
+++ b/joblib/__init__.py
@@ -106,7 +106,7 @@ Main features
 # Dev branch marker is: 'X.Y.dev' or 'X.Y.devN' where N is an integer.
 # 'X.Y.dev0' is the canonical version of 'X.Y.dev'
 #
-__version__ = '0.12.0'
+__version__ = '0.12.1'
 
 
 from .memory import Memory, MemorizedResult, register_store_backend
diff --git a/joblib/func_inspect.py b/joblib/func_inspect.py
index f8520c9..e9320b4 100644
--- a/joblib/func_inspect.py
+++ b/joblib/func_inspect.py
@@ -240,8 +240,10 @@ def filter_args(func, ignore_lst, args=(), kwargs=dict()):
     arg_spec = getfullargspec(func)
     arg_names = arg_spec.args + arg_spec.kwonlyargs
     arg_defaults = arg_spec.defaults or ()
-    arg_defaults = arg_defaults + tuple(arg_spec.kwonlydefaults[k]
-                                        for k in arg_spec.kwonlyargs)
+    if arg_spec.kwonlydefaults:
+        arg_defaults = arg_defaults + tuple(arg_spec.kwonlydefaults[k]
+                                            for k in arg_spec.kwonlyargs
+                                            if k in arg_spec.kwonlydefaults)
     arg_varargs = arg_spec.varargs
     arg_varkw = arg_spec.varkw
 
diff --git a/joblib/memory.py b/joblib/memory.py
index 0c0e15d..91204af 100644
--- a/joblib/memory.py
+++ b/joblib/memory.py
@@ -224,6 +224,15 @@ class MemorizedResult(Logger):
         self.verbose = verbose
         self.timestamp = timestamp
 
+    @property
+    def argument_hash(self):
+        warnings.warn(
+            "The 'argument_hash' attribute has been deprecated in version "
+            "0.12 and will be removed in version 0.14.\n"
+            "Use `args_id` attribute instead.",
+            DeprecationWarning, stacklevel=2)
+        return self.args_id
+
     def get(self):
         """Read value from cache and return it."""
         if self.verbose:
@@ -241,13 +250,12 @@ class MemorizedResult(Logger):
 
     def __repr__(self):
         return ('{class_name}(location="{location}", func="{func}", '
-                'argument_hash="{argument_hash}")'
+                'args_id="{args_id}")'
                 .format(class_name=self.__class__.__name__,
                         location=self.store_backend,
                         func=self.func,
-                        argument_hash=self.args_id
+                        args_id=self.args_id
                         ))
-
     def __reduce__(self):
         return (self.__class__,
                 (self.store_backend, self.func, self.args_id),
@@ -824,8 +832,8 @@ class Memory(Logger):
             warnings.warn(
                 "The 'cachedir' parameter has been deprecated in version "
                 "0.12 and will be removed in version 0.14.\n"
-                'You provided "cachedir={!r}", '
-                'use "location={!r}" instead.'.format(cachedir, location),
+                'You provided "cachedir={0!r}", '
+                'use "location={0!r}" instead.'.format(cachedir),
                 DeprecationWarning, stacklevel=2)
             location = cachedir
 

v0.12: 'MemorizedResult' object has no attribute 'argument_hash'
I our test suite I was checking that caching occurred properly by checking that a ``MemorizedResult`` instance would have the same hash after two calls to ``call_and_shelve``.

Now the ``argument_hash`` attr is gone, and I replaced ``argument_hash`` with ``timestamp`` in our tests.

I was wondering if this is an oversight or if it was intended? I coudln't find anything in the changelog
diff --git a/joblib/test/test_func_inspect.py b/joblib/test/test_func_inspect.py
index 1d094b0..baccecc 100644
--- a/joblib/test/test_func_inspect.py
+++ b/joblib/test/test_func_inspect.py
@@ -99,11 +99,25 @@ def test_filter_varargs(func, args, filtered_args):
     assert filter_args(func, *args) == filtered_args
 
 
+test_filter_kwargs_extra_params = []
+if PY3_OR_LATER:
+    m1 = m2 = None
+    # The following statements raise SyntaxError in python 2
+    # because kwargonly is not supported
+    exec("def m1(x, *, y): pass")
+    exec("def m2(x, *, y, z=3): pass")
+    test_filter_kwargs_extra_params.extend([
+        (m1, [[], (1,), {'y': 2}], {'x': 1, 'y': 2}),
+        (m2, [[], (1,), {'y': 2}], {'x': 1, 'y': 2, 'z': 3})
+    ])
+
+
 @parametrize('func,args,filtered_args',
              [(k, [[], (1, 2), {'ee': 2}],
                {'*': [1, 2], '**': {'ee': 2}}),
               (k, [[], (3, 4)],
-               {'*': [3, 4], '**': {}})])
+               {'*': [3, 4], '**': {}})] +
+             test_filter_kwargs_extra_params)
 def test_filter_kwargs(func, args, filtered_args):
     assert filter_args(func, *args) == filtered_args
 
diff --git a/joblib/test/test_memory.py b/joblib/test/test_memory.py
index e795e71..751e29a 100644
--- a/joblib/test/test_memory.py
+++ b/joblib/test/test_memory.py
@@ -451,6 +451,19 @@ def test_call_and_shelve(tmpdir):
         result.clear()  # Do nothing if there is no cache.
 
 
+def test_call_and_shelve_argument_hash(tmpdir):
+    # Verify that a warning is raised when accessing arguments_hash
+    # attribute from MemorizedResult
+    func = Memory(location=tmpdir.strpath, verbose=0).cache(f)
+    result = func.call_and_shelve(2)
+    assert isinstance(result, MemorizedResult)
+    with warns(DeprecationWarning) as w:
+        assert result.argument_hash == result.args_id
+    assert len(w) == 1
+    assert "The 'argument_hash' attribute has been deprecated" \
+        in str(w[-1].message)
+
+
 def test_memorized_pickling(tmpdir):
     for func in (MemorizedFunc(f, tmpdir.strpath), NotMemorizedFunc(f)):
         filename = tmpdir.join('pickling_test.dat').strpath

pip install -e .
parse_log_pytest
pytest
pytest
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
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@6a2f9062dc01e1df013afb3886ffbaa266325764#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
toml @ file:///tmp/build/80754af9/toml_1616166611790/work
typing_extensions @ file:///opt/conda/conda-bld/typing_extensions_1647553014482/work
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
prefix: /opt/conda/envs/joblib

joblib/test/test_func_inspect.py::test_filter_kwargs[m1-args2-filtered_args2] joblib/test/test_func_inspect.py::test_filter_kwargs[m2-args3-filtered_args3] joblib/test/test_memory.py::test_call_and_shelve_argument_hash
joblib/test/test_func_inspect.py::test_filter_args[f-args0-filtered_args0] joblib/test/test_func_inspect.py::test_filter_args[f-args1-filtered_args1] joblib/test/test_func_inspect.py::test_filter_args[f-args2-filtered_args2] joblib/test/test_func_inspect.py::test_filter_args[f-args3-filtered_args3] joblib/test/test_func_inspect.py::test_filter_args[f-args4-filtered_args4] joblib/test/test_func_inspect.py::test_filter_args[f-args5-filtered_args5] joblib/test/test_func_inspect.py::test_filter_args[f-args6-filtered_args6] joblib/test/test_func_inspect.py::test_filter_args[g-args7-filtered_args7] joblib/test/test_func_inspect.py::test_filter_args[i-args8-filtered_args8] joblib/test/test_func_inspect.py::test_filter_args_method joblib/test/test_func_inspect.py::test_filter_varargs[h-args0-filtered_args0] joblib/test/test_func_inspect.py::test_filter_varargs[h-args1-filtered_args1] joblib/test/test_func_inspect.py::test_filter_varargs[h-args2-filtered_args2] joblib/test/test_func_inspect.py::test_filter_varargs[h-args3-filtered_args3] joblib/test/test_func_inspect.py::test_filter_kwargs[k-args0-filtered_args0] joblib/test/test_func_inspect.py::test_filter_kwargs[k-args1-filtered_args1] joblib/test/test_func_inspect.py::test_filter_args_2 joblib/test/test_func_inspect.py::test_func_name[f-f] joblib/test/test_func_inspect.py::test_func_name[g-g] joblib/test/test_func_inspect.py::test_func_name[cached_func-cached_func] joblib/test/test_func_inspect.py::test_func_name_on_inner_func joblib/test/test_func_inspect.py::test_func_inspect_errors joblib/test/test_func_inspect.py::test_filter_args_python_3 joblib/test/test_func_inspect.py::test_bound_methods joblib/test/test_func_inspect.py::test_filter_args_error_msg[ValueError-ignore_lst joblib/test/test_func_inspect.py::test_filter_args_error_msg[ValueError-Ignore joblib/test/test_func_inspect.py::test_filter_args_error_msg[ValueError-Wrong joblib/test/test_func_inspect.py::test_clean_win_chars joblib/test/test_func_inspect.py::test_format_signature[g-args0-kwargs0-g([0, joblib/test/test_func_inspect.py::test_format_signature[k-args1-kwargs1-k(1, joblib/test/test_func_inspect.py::test_format_signature_long_arguments joblib/test/test_func_inspect.py::test_special_source_encoding joblib/test/test_func_inspect.py::test_func_code_consistency 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_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_concurrency_safe_write[multiprocessing] joblib/test/test_memory.py::test_concurrency_safe_write[loky] joblib/test/test_memory.py::test_concurrency_safe_write[threading] 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/memory.py joblib/func_inspect.py joblib/__init__.py doc/memory.rst CHANGES.rst
joblib/memory.py joblib/func_inspect.py joblib/__init__.py doc/memory.rst CHANGES.rst