Repository: youknowone/ring

Issue:
[BUG] It doesn't work for classmethod very well
~Even if "cls" is different in classmethod, Ring doesn't distinguish them~

Now cls is correctly passed to classmethod, but not about subclasses.

Related test: https://github.com/youknowone/ring/blob/master/tests/test_key.py#L64

Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/youknowone/ring/pull/80?src=pr&el=h1) Report
> Merging [#80](https://codecov.io/gh/youknowone/ring/pull/80?src=pr&el=desc) into [master](https://codecov.io/gh/youknowone/ring/commit/33fd69eed378616ed031a0560e14007b6d43008a?src=pr&el=desc) will **decrease** coverage by `1.27%`.
> The diff coverage is `100%`.


```diff
@@            Coverage Diff             @@
##           master      #80      +/-   ##
==========================================
- Coverage   97.88%   96.61%   -1.27%     
==========================================
  Files          13       13              
  Lines        1084     1090       +6     
==========================================
- Hits         1061     1053       -8     
- Misses         23       37      +14
```





Patch:
diff --git a/ring/wire.py b/ring/wire.py
index 069ec40..078cb04 100644
--- a/ring/wire.py
+++ b/ring/wire.py
@@ -56,10 +56,17 @@ class Wire(object):
 
         _shared_attrs = {'attrs': {}}
 
-        if is_method(cwrapper) or is_classmethod(cwrapper):
+        c_is_method = is_method(cwrapper)
+        c_is_classmethod = is_classmethod(cwrapper)
+        if c_is_method or c_is_classmethod:
             @WiredProperty
             def _w(self):
-                wrapper_name = '__wrapper_' + cwrapper.code.co_name
+                wrapper_name_parts = ['__wire_', cwrapper.code.co_name]
+                if c_is_classmethod:
+                    self_cls = self if type(self) == type else type(self)  # fragile
+                    wrapper_name_parts.extend(('_', self_cls.__name__))
+                    self = self_cls
+                wrapper_name = ''.join(wrapper_name_parts)
                 wrapper = getattr(self, wrapper_name, None)
                 if wrapper is None:
                     _wrapper = cls(cwrapper, _shared_attrs)


Test patch:
diff --git a/tests/test_key.py b/tests/test_key.py
index bf08f0a..5f87fe4 100644
--- a/tests/test_key.py
+++ b/tests/test_key.py
@@ -1,3 +1,4 @@
+import six
 import ring
 from ring.key import FormatKey, CallableKey
 
@@ -61,7 +62,22 @@ def test_classmethod_key():
         pass
 
     assert A.f.key().endswith('.A.f:A'), A.f.key()
-    # assert B.f.key().endswith('.A.f:B'), B.f.key() -- TODO
+    if six.PY2:
+        assert B.f.key().endswith('.B.f:B'), B.f.key()
+    else:
+        assert B.f.key().endswith('.A.f:B'), B.f.key()
+
+    a = A()
+    b = B()
+
+    assert a.f.key().endswith('.A.f:A'), a.f.key()
+    if six.PY2:
+        assert b.f.key().endswith('.B.f:B'), b.f.key()
+    else:
+        assert b.f.key().endswith('.A.f:B'), b.f.key()
+
+    assert A.f.key() == a.f.key()
+    assert B.f.key() == b.f.key()
 
 
 def test_unexisting_ring_key():