Repository: ZeitOnline/pyramid_dogpile_cache2 (language: python)

Issue:
Support for caching functions with annotations
Attempting to cache a function with annotations, e.g.

```python
@cache_long_term.cache_on_arguments()
def my_funct(arg1: str) -> int:
    pass
```

raises an error:

```pytb
.tox/py36/lib/python3.6/site-packages/dogpile/cache/region.py:1234: in decorator
    key_generator = function_key_generator(namespace, fn)
.tox/py36/lib/python3.6/site-packages/pyramid_dogpile_cache2/cache.py:11: in key_generator
    args = inspect.getargspec(fn)
/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/inspect.py:1075: in getargspec
    raise ValueError("Function has keyword-only parameters or annotations"
E   ValueError: Function has keyword-only parameters or annotations, use getfullargspec() API which can support them
```


Discussion / hints:

Fix patch:
diff --git a/src/pyramid_dogpile_cache2/cache.py b/src/pyramid_dogpile_cache2/cache.py
index 02e4dc9..11236a9 100644
--- a/src/pyramid_dogpile_cache2/cache.py
+++ b/src/pyramid_dogpile_cache2/cache.py
@@ -8,7 +8,10 @@ def key_generator(ns, fn, to_str=dogpile.util.compat.text_type):
     non-ascii function arguments, and supports not just plain functions, but
     methods as well.
     """
-    args = inspect.getargspec(fn)
+    if dogpile.util.compat.py2k:
+        args = inspect.getargspec(fn)
+    else:
+        args = inspect.getfullargspec(fn)
     has_self = args[0] and args[0][0] in ('self', 'cls')
 
     def generate_key(*args, **kw):
diff --git a/tox.ini b/tox.ini
index 257c294..a14d3eb 100644
--- a/tox.ini
+++ b/tox.ini
@@ -6,5 +6,7 @@ minversion = 1.6
 deps =
     pytest
     pytest-cov
+setenv =
+    py27: PYTEST_ADDOPTS=--ignore {toxinidir}/src/pyramid_dogpile_cache2/tests/test_cache_py3.py
 commands = py.test --tb=native {toxinidir}/src
-usedevelop = True
\ No newline at end of file
+usedevelop = True


Test patch:
diff --git a/src/pyramid_dogpile_cache2/tests/test_cache_py3.py b/src/pyramid_dogpile_cache2/tests/test_cache_py3.py
new file mode 100644
index 0000000..c16980d
--- /dev/null
+++ b/src/pyramid_dogpile_cache2/tests/test_cache_py3.py
@@ -0,0 +1,14 @@
+import dogpile.cache.util
+import pyramid_dogpile_cache2.cache
+import pytest
+
+
+@pytest.mark.skipif(
+    dogpile.util.compat.py2k,
+    reason='Python 2 does not support type annotation syntax')
+def test_key_generator_handles_type_annotations():
+    def function_with_annotations() -> None:
+        pass
+
+    gen = pyramid_dogpile_cache2.cache.key_generator(None, function_with_annotations)
+    assert gen() == 'pyramid_dogpile_cache2.tests.test_cache_py3.function_with_annotations|'