Return a Stochastic subclass made from a particular distribution.

    :Parameters:
      name : string
        The name of the new class.
      logp : function
        The log-probability function.
      random : function
        The random function
      dtype : numpy dtype
        The dtype of values of instances.
      mv : boolean
        A flag indicating whether this class represents
        array-valued variables.

    :Example:
      >>> Exponential = stochastic_from_dist('exponential',
                                              logp=exponential_like,
                                              random=rexponential,
                                              dtype=np.float,
                                              mv=False)
      >>> A = Exponential(self_name, value, beta)

    .. note::
      new_dist_class is a more flexible class factory. Also consider
      subclassing Stochastic directly.
      stochastic_from_data is suited for non-parametric distributions.

    :SeeAlso:
      new_dist_class, stochastic_from_data

def stochastic_from_dist(
        name, logp, random=None, logp_partial_gradients={}, dtype=np.float, mv=False):
    """
    Return a Stochastic subclass made from a particular distribution.

    :Parameters:
      name : string
        The name of the new class.
      logp : function
        The log-probability function.
      random : function
        The random function
      dtype : numpy dtype
        The dtype of values of instances.
      mv : boolean
        A flag indicating whether this class represents
        array-valued variables.

    :Example:
      >>> Exponential = stochastic_from_dist('exponential',
                                              logp=exponential_like,
                                              random=rexponential,
                                              dtype=np.float,
                                              mv=False)
      >>> A = Exponential(self_name, value, beta)

    .. note::
      new_dist_class is a more flexible class factory. Also consider
      subclassing Stochastic directly.
      stochastic_from_data is suited for non-parametric distributions.

    :SeeAlso:
      new_dist_class, stochastic_from_data
    """

    (args, defaults) = utils.get_signature(logp)
    parent_names = args[1:]
    try:
        parents_default = dict(zip(args[-len(defaults):], defaults))
    except TypeError:  # No parents at all.
        parents_default = {}

    name = capitalize(name)

    # Build docstring from distribution
    parents_str = ''
    if parent_names:
        parents_str = ', '.join(parent_names) + ', '
    docstr = name[0] + ' = ' + name + \
        '(name, ' + parents_str + 'value=None, observed=False,'
    if not mv:
        docstr += ' size=1,'
    docstr += ' trace=True, rseed=True, doc=None, verbose=-1, debug=False)\n\n'
    docstr += 'Stochastic variable with ' + name + \
        ' distribution.\nParents are: ' + ', '.join(parent_names) + '.\n\n'
    docstr += 'Docstring of log-probability function:\n'
    try:
        docstr += logp.__doc__
    except TypeError:
        pass  # This will happen when logp doesn't have a docstring

    logp = valuewrapper(logp)
    distribution_arguments = logp.__dict__

    wrapped_logp_partial_gradients = {}

    for parameter, func in six.iteritems(logp_partial_gradients):
        wrapped_logp_partial_gradients[parameter] = valuewrapper(
            logp_partial_gradients[parameter],
            arguments=distribution_arguments)

    return new_dist_class(dtype, name, parent_names, parents_default, docstr,
                          logp, random, mv, wrapped_logp_partial_gradients)