"""
todo - describe how to use the dimod sampler template
"""
from dimod.binary_quadratic_model_convert import to_qubo, to_ising, from_qubo, from_ising
from dimod.compatibility23 import RecursionError_
from dimod.exceptions import InvalidSampler
from dimod.vartypes import Vartype

__all__ = ['Sampler']


class Sampler(object):
    """todo

    """
    def __init__(self):
        self.sample_kwargs = {}
        self.properties = {}

    def sample(self, bqm, **sample_kwargs):
        """todo"""
        try:
            if bqm.vartype is Vartype.SPIN:
                Q, offset = to_qubo(bqm)
                response = self.sample_qubo(Q, **sample_kwargs)
                response.change_vartype(Vartype.SPIN, offset)
                return response
            elif bqm.vartype is Vartype.BINARY:
                h, J, offset = to_ising(bqm)
                response = self.sample_ising(h, J, **sample_kwargs)
                response.change_vartype(Vartype.BINARY, offset)
                return response
            else:
                raise RuntimeError("binary quadratic model has an unknown vartype")
        except RecursionError_:
            msg = ("A RecursionError has been occured. This most often happens when trying to use "
                   "the Sampler base class as a sampler.")
            raise InvalidSampler(msg)

    def sample_ising(self, h, J, **sample_kwargs):
        """todo"""
        bqm = from_ising(h, J)
        response = self.sample(bqm, **sample_kwargs)
        response.change_vartype(Vartype.SPIN)
        return response

    def sample_qubo(self, Q, **sample_kwargs):
        """todo"""
        bqm = from_qubo(Q)
        response = self.sample(bqm, **sample_kwargs)
        response.change_vartype(Vartype.BINARY)
        return response

@@ -427,16 +427,632 @@
 ies = %7B%7D
+%0A        self._methods_cycled = set()%0A%0A    def _ensure_finite_cycle(self, methodname):%0A        %22%22%22Ensure user-derived sampler implements at least one sampling method.%22%22%22%0A%0A        # (In current Sampler implementation, if 3 or more base sample* methods%0A        # are called, we have an infinite loop. The loop can be broken by%0A        # overridding at least one sample method in a subclass.)%0A        self._methods_cycled.add(methodname)%0A        if len(self._methods_cycled) %3E 2:%0A            raise InvalidSampler('Sampler subclass must override at least one '%0A                                 'of the sampling methods')
 %0A%0A    de
@@ -1120,23 +1120,52 @@
     
-try:%0A  
+self._ensure_finite_cycle('sample')%0A
         
   if
@@ -1160,18 +1160,16 @@
         
-  
 if bqm.v
@@ -1204,20 +1204,16 @@
         
-    
 Q, offse
@@ -1233,36 +1233,32 @@
 qm)%0A            
- 
-   
 response = self.
@@ -1281,36 +1281,32 @@
 *sample_kwargs)%0A
-    
             resp
@@ -1351,36 +1351,32 @@
 et)%0A            
-    
 return response%0A
@@ -1367,36 +1367,32 @@
 return response%0A
-    
         elif bqm
@@ -1431,20 +1431,16 @@
         
-    
 h, J, of
@@ -1464,36 +1464,32 @@
 qm)%0A            
-   
- 
 response = self.
@@ -1528,36 +1528,32 @@
 gs)%0A            
-    
 response.change_
@@ -1588,36 +1588,32 @@
 et)%0A            
-  
-  
 return response%0A
@@ -1620,20 +1620,16 @@
         
-    
 else:%0A  
@@ -1634,28 +1634,24 @@
             
- 
-   
 raise Runtim
@@ -1709,237 +1709,8 @@
 pe%22)
-%0A        except RecursionError_:%0A            msg = (%22A RecursionError has been occured. This most often happens when trying to use %22%0A                   %22the Sampler base class as a sampler.%22)%0A            raise InvalidSampler(msg)
 %0A%0A  
@@ -1769,32 +1769,82 @@
      %22%22%22todo%22%22%22%0A
+        self._ensure_finite_cycle('sample_ising')%0A
         bqm = fr
@@ -2040,32 +2040,81 @@
      %22%22%22todo%22%22%22%0A
+        self._ensure_finite_cycle('sample_qubo')%0A
         bqm = fr

Refactor infinite recursion test in Sampler base class