Index: sasmodels/compare.py
===================================================================
--- sasmodels/compare.py	(revision e65c3ba5944b729f651cf8747f7b64bed2cbb826)
+++ sasmodels/compare.py	(revision 32398dc2bc07e72d622b3194d14257671e3a932f)
@@ -43,11 +43,12 @@
 from .data import plot_theory, empty_data1D, empty_data2D, load_data
 from .direct_model import DirectModel, get_mesh
-from .convert import revert_name, revert_pars, constrain_new_to_old
+from .convert import revert_name, revert_pars
 from .generate import FLOAT_RE
 from .weights import plot_weights
 
+# pylint: disable=unused-import
 try:
     from typing import Optional, Dict, Any, Callable, Tuple
-except Exception:
+except ImportError:
     pass
 else:
@@ -55,4 +56,5 @@
     from .data import Data
     Calculator = Callable[[float], np.ndarray]
+# pylint: enable=unused-import
 
 USAGE = """
@@ -97,5 +99,4 @@
     -single/-double/-half/-fast sets an OpenCL calculation engine
     -single!/-double!/-quad! sets an OpenMP calculation engine
-    -sasview sets the sasview calculation engine
 
     === plotting ===
@@ -237,7 +238,6 @@
         pass
 
-    def __exit__(self, exc_type, exc_value, tb):
+    def __exit__(self, exc_type, exc_value, trace):
         # type: (Any, BaseException, Any) -> None
-        # TODO: better typing for __exit__ method
         np.random.set_state(self._state)
 
@@ -258,6 +258,4 @@
     """
     Add a beam stop of the given *radius*.  If *outer*, make an annulus.
-
-    Note: this function does not require sasview
     """
     if hasattr(data, 'qx_data'):
@@ -625,113 +623,4 @@
     return pars
 
-# TODO: remove support for sasview 3.x models
-def eval_sasview(model_info, data):
-    # type: (Modelinfo, Data) -> Calculator
-    """
-    Return a model calculator using the pre-4.0 SasView models.
-    """
-    # importing sas here so that the error message will be that sas failed to
-    # import rather than the more obscure smear_selection not imported error
-    import sas
-    import sas.models
-    from sas.models.qsmearing import smear_selection
-    from sas.models.MultiplicationModel import MultiplicationModel
-    from sas.models.dispersion_models import models as dispersers
-
-    def _get_model_class(name):
-        # type: (str) -> "sas.models.BaseComponent"
-        #print("new",sorted(_pars.items()))
-        __import__('sas.models.' + name)
-        ModelClass = getattr(getattr(sas.models, name, None), name, None)
-        if ModelClass is None:
-            raise ValueError("could not find model %r in sas.models"%name)
-        return ModelClass
-
-    # WARNING: ugly hack when handling model!
-    # Sasview models with multiplicity need to be created with the target
-    # multiplicity, so we cannot create the target model ahead of time for
-    # for multiplicity models.  Instead we store the model in a list and
-    # update the first element of that list with the new multiplicity model
-    # every time we evaluate.
-
-    # grab the sasview model, or create it if it is a product model
-    if model_info.composition:
-        composition_type, parts = model_info.composition
-        if composition_type == 'product':
-            P, S = [_get_model_class(revert_name(p))() for p in parts]
-            model = [MultiplicationModel(P, S)]
-        else:
-            raise ValueError("sasview mixture models not supported by compare")
-    else:
-        old_name = revert_name(model_info)
-        if old_name is None:
-            raise ValueError("model %r does not exist in old sasview"
-                             % model_info.id)
-        ModelClass = _get_model_class(old_name)
-        model = [ModelClass()]
-    model[0].disperser_handles = {}
-
-    # build a smearer with which to call the model, if necessary
-    smearer = smear_selection(data, model=model)
-    if hasattr(data, 'qx_data'):
-        q = np.sqrt(data.qx_data**2 + data.qy_data**2)
-        index = ((~data.mask) & (~np.isnan(data.data))
-                 & (q >= data.qmin) & (q <= data.qmax))
-        if smearer is not None:
-            smearer.model = model  # because smear_selection has a bug
-            smearer.accuracy = data.accuracy
-            smearer.set_index(index)
-            def _call_smearer():
-                smearer.model = model[0]
-                return smearer.get_value()
-            theory = _call_smearer
-        else:
-            theory = lambda: model[0].evalDistribution([data.qx_data[index],
-                                                        data.qy_data[index]])
-    elif smearer is not None:
-        theory = lambda: smearer(model[0].evalDistribution(data.x))
-    else:
-        theory = lambda: model[0].evalDistribution(data.x)
-
-    def calculator(**pars):
-        # type: (float, ...) -> np.ndarray
-        """
-        Sasview calculator for model.
-        """
-        oldpars = revert_pars(model_info, pars)
-        # For multiplicity models, create a model with the correct multiplicity
-        control = oldpars.pop("CONTROL", None)
-        if control is not None:
-            # sphericalSLD has one fewer multiplicity.  This update should
-            # happen in revert_pars, but it hasn't been called yet.
-            model[0] = ModelClass(control)
-        # paying for parameter conversion each time to keep life simple, if not fast
-        for k, v in oldpars.items():
-            if k.endswith('.type'):
-                par = k[:-5]
-                if v == 'gaussian': continue
-                cls = dispersers[v if v != 'rectangle' else 'rectangula']
-                handle = cls()
-                model[0].disperser_handles[par] = handle
-                try:
-                    model[0].set_dispersion(par, handle)
-                except Exception:
-                    exception.annotate_exception("while setting %s to %r"
-                                                 %(par, v))
-                    raise
-
-
-        #print("sasview pars",oldpars)
-        for k, v in oldpars.items():
-            name_attr = k.split('.')  # polydispersity components
-            if len(name_attr) == 2:
-                par, disp_par = name_attr
-                model[0].dispersion[par][disp_par] = v
-            else:
-                model[0].setParam(k, v)
-        return theory()
-
-    calculator.engine = "sasview"
-    return calculator
 
 DTYPE_MAP = {
@@ -827,7 +716,5 @@
     than OpenCL.
     """
-    if dtype == 'sasview':
-        return eval_sasview(model_info, data)
-    elif dtype is None or not dtype.endswith('!'):
+    if dtype is None or not dtype.endswith('!'):
         return eval_opencl(model_info, data, dtype=dtype, cutoff=cutoff)
     else:
@@ -1075,5 +962,4 @@
     'engine=',
     'half', 'fast', 'single', 'double', 'single!', 'double!', 'quad!',
-    'sasview',  # TODO: remove sasview 3.x support
 
     # Output options
@@ -1258,5 +1144,4 @@
         elif arg == '-double!': opts['engine'] = 'double!'
         elif arg == '-quad!':   opts['engine'] = 'quad!'
-        elif arg == '-sasview': opts['engine'] = 'sasview'
         elif arg == '-edit':    opts['explore'] = True
         elif arg == '-demo':    opts['use_demo'] = True
Index: sasmodels/compare_many.py
===================================================================
--- sasmodels/compare_many.py	(revision f72d70a9055bf8a3cc610ed4abd84799154108ca)
+++ sasmodels/compare_many.py	(revision 32398dc2bc07e72d622b3194d14257671e3a932f)
@@ -22,5 +22,5 @@
 from .compare import (randomize_pars, suppress_pd, make_data,
                       make_engine, get_pars, columnize,
-                      constrain_pars, constrain_new_to_old)
+                      constrain_pars)
 
 MODELS = core.list_models()
@@ -80,8 +80,7 @@
     'double!': 5e-14,
     'quad!': 5e-18,
-    'sasview': 5e-14,
 }
 def compare_instance(name, data, index, N=1, mono=True, cutoff=1e-5,
-                     base='sasview', comp='double'):
+                     base='single', comp='double'):
     r"""
     Compare the model under different calculation engines.
@@ -164,8 +163,7 @@
         print("Model %s %d"%(name, k+1), file=sys.stderr)
         seed = np.random.randint(1e6)
-        pars_i = randomize_pars(model_info, pars, seed)
+        np.random.seed(seed)
+        pars_i = randomize_pars(model_info, pars)
         constrain_pars(model_info, pars_i)
-        if 'sasview' in (base, comp):
-            constrain_new_to_old(model_info, pars_i)
         if mono:
             pars_i = suppress_pd(pars_i)
Index: sasmodels/convert.py
===================================================================
--- sasmodels/convert.py	(revision e65c3ba5944b729f651cf8747f7b64bed2cbb826)
+++ sasmodels/convert.py	(revision 32398dc2bc07e72d622b3194d14257671e3a932f)
@@ -6,4 +6,6 @@
 import math
 import warnings
+
+import numpy as np
 
 from .conversion_table import CONVERSION_TABLE
@@ -146,5 +148,5 @@
     return newpars
 
-def _conversion_target(model_name, version=(3,1,2)):
+def _conversion_target(model_name, version=(3, 1, 2)):
     """
     Find the sasmodel name which translates into the sasview name.
@@ -600,5 +602,7 @@
 
     pars = compare.get_pars(model_info, use_demo=False)
-    pars = compare.randomize_pars(model_info, pars, seed=seed)
+    if seed is not None:
+        np.random.seed(seed)
+    pars = compare.randomize_pars(model_info, pars)
     if name == "teubner_strey":
         # T-S model is underconstrained, so fix the assumptions.
