<commit_before># -*- coding: utf-8 -*-
#
# Copyright (C) 2009-2018 the sqlparse authors and contributors
# <see AUTHORS file>
#
# This module is part of python-sqlparse and is released under
# the BSD License: https://opensource.org/licenses/BSD-3-Clause

from sqlparse import sql, tokens as T

class StatementSplitter(object):
    """Filter that split stream at individual statements"""

    def __init__(self):
        self._reset()

    def _reset(self):
        """Set the filter attributes to its default values"""
        self._in_declare = False
        self._is_create = False
        self._begin_depth = 0

        self.consume_ws = False
        self.tokens = []
        self.level = 0

    def _change_splitlevel(self, ttype, value):
        """Get the new split level (increase, decrease or remain equal)"""
        # ANSI
        # if normal token return
        # wouldn't parenthesis increase/decrease a level?
        # no, inside a parenthesis can't start new statement
        if ttype not in T.Keyword:
            return 0

        # Everything after here is ttype = T.Keyword
        # Also to note, once entered an If statement you are done and basically
        # returning
        unified = value.upper()

        # three keywords begin with CREATE, but only one of them is DDL
        # DDL Create though can contain more words such as "or replace"
        if ttype is T.Keyword.DDL and unified.startswith('CREATE'):
            self._is_create = True
            return 0

        # can have nested declare inside of being...
        if unified == 'DECLARE' and self._is_create and self._begin_depth == 0:
            self._in_declare = True
            return 1

        if unified == 'BEGIN':
            self._begin_depth += 1
            if self._is_create:
                # FIXME(andi): This makes no sense.
                return 1
            return 0

        # Should this respect a preceding BEGIN?
        # In CASE ... WHEN ... END this results in a split level -1.
        # Would having multiple CASE WHEN END and a Assignment Operator
        # cause the statement to cut off prematurely?
        if unified == 'END':
            self._begin_depth = max(0, self._begin_depth - 1)
            return -1

        if (unified in ('IF', 'FOR', 'WHILE')
                and self._is_create and self._begin_depth > 0):
            return 1

        if unified in ('END IF', 'END FOR', 'END WHILE'):
            return -1

        # Default
        return 0

    def process(self, stream):
        """Process the stream"""
        EOS_TTYPE = T.Whitespace, T.Comment.Single

        # Run over all stream tokens
        for ttype, value in stream:
            # Yield token if we finished a statement and there's no whitespaces
            # It will count newline token as a non whitespace. In this context
            # whitespace ignores newlines.
            # why don't multi line comments also count?
            if self.consume_ws and ttype not in EOS_TTYPE:
                yield sql.Statement(self.tokens)

                # Reset filter and prepare to process next statement
                self._reset()

            # Change current split level (increase, decrease or remain equal)
            self.level += self._change_splitlevel(ttype, value)

            # Append the token to the current statement
            self.tokens.append(sql.Token(ttype, value))

            # Check if we get the end of a statement
            if self.level <= 0 and ttype is T.Punctuation and value == ';':
                self.consume_ws = True

        # Yield pending statement (if any)
        if self.tokens:
            yield sql.Statement(self.tokens)
<commit_msg>Fixes #485<commit_after># -*- coding: utf-8 -*-
#
# Copyright (C) 2009-2018 the sqlparse authors and contributors
# <see AUTHORS file>
#
# This module is part of python-sqlparse and is released under
# the BSD License: https://opensource.org/licenses/BSD-3-Clause

from sqlparse import sql, tokens as T

class StatementSplitter(object):
    """Filter that split stream at individual statements"""

    def __init__(self):
        self._reset()

    def _reset(self):
        """Set the filter attributes to its default values"""
        self._in_declare = False
        self._is_create = False
        self._parenthesis_depth = 0
        self._begin_depth = 0

        self.consume_ws = False
        self.tokens = []
        self.level = 0

    def _change_splitlevel(self, ttype, value):
        """Get the new split level (increase, decrease or remain equal)"""

        # parenthesis increase/decrease a level
        if ttype is T.Punctuation and value == '(':
            return 1
        elif ttype is T.Punctuation and value == ')':
            return -1
        elif ttype not in T.Keyword: # if normal token return
            return 0

        # Everything after here is ttype = T.Keyword or ttype = T.
        # Also to note, once entered an If statement you are done and basically
        # returning
        unified = value.upper()

        # three keywords begin with CREATE, but only one of them is DDL
        # DDL Create though can contain more words such as "or replace"
        if ttype is T.Keyword.DDL and unified.startswith('CREATE'):
            self._is_create = True
            return 0

        # can have nested declare inside of being...
        if unified == 'DECLARE' and self._is_create and self._begin_depth == 0:
            self._in_declare = True
            return 1

        if unified == 'BEGIN':
            self._begin_depth += 1
            if self._is_create:
                # FIXME(andi): This makes no sense.
                return 1
            return 0

        # Should this respect a preceding BEGIN?
        # In CASE ... WHEN ... END this results in a split level -1.
        # Would having multiple CASE WHEN END and a Assignment Operator
        # cause the statement to cut off prematurely?
        if unified == 'END':
            self._begin_depth = max(0, self._begin_depth - 1)
            return -1

        if (unified in ('IF', 'FOR', 'WHILE')
                and self._is_create and self._begin_depth > 0):
            return 1

        if unified in ('END IF', 'END FOR', 'END WHILE'):
            return -1

        # Default
        return 0

    def process(self, stream):
        """Process the stream"""
        EOS_TTYPE = T.Whitespace, T.Comment.Single

        # Run over all stream tokens
        for ttype, value in stream:
            # Yield token if we finished a statement and there's no whitespaces
            # It will count newline token as a non whitespace. In this context
            # whitespace ignores newlines.
            # why don't multi line comments also count?
            if self.consume_ws and ttype not in EOS_TTYPE:
                yield sql.Statement(self.tokens)

                # Reset filter and prepare to process next statement
                self._reset()

            # Change current split level (increase, decrease or remain equal)
            self.level += self._change_splitlevel(ttype, value)

            # Append the token to the current statement
            self.tokens.append(sql.Token(ttype, value))

            # Check if we get the end of a statement
            if self.level <= 0 and ttype is T.Punctuation and value == ';':
                self.consume_ws = True

        # Yield pending statement (if any)
        if self.tokens:
            yield sql.Statement(self.tokens)
<|endoftext|>


<commit_before>"""
Boolean Functions

Interface Functions:
    num2point
    point2term
    num2term
    iter_points
    iter_terms

Interface Classes:
    Variable
    Function
    Slicer
    VectorFunction
"""

import collections

from pyeda.common import bit_on

def num2point(num, vs):
    """Convert a number to a point in an N-dimensional space."""
    return {v: bit_on(num, i) for i, v in enumerate(vs)}

def point2term(point, conj=False):
    """Convert a point in an N-dimension space to a min/max term."""
    if conj:
        return tuple(-v if val else v for v, val in point.items())
    else:
        return tuple(v if val else -v for v, val in point.items())

def num2term(num, vs, conj=False):
    """Return a tuple of all variables for a given term index.

    Parameters
    ----------
    num: int
    vs: [Variable]
    conj: bool
        conj=False for minterms, conj=True for maxterms

    Examples
    --------

    Table of min/max terms for Boolean space {a, b, c}

    +-----+----------+----------+
    | num |  minterm |  maxterm |
    +=====+==========+==========+
    | 0   | a' b' c' | a  b  c  |
    | 1   | a  b' c' | a' b  c  |
    | 2   | a' b  c' | a  b' c  |
    | 3   | a  b  c' | a' b' c  |
    | 4   | a' b' c  | a  b  c' |
    | 5   | a  b' c  | a' b  c' |
    | 6   | a' b  c  | a  b' c' |
    | 7   | a  b  c  | a' b' c' |
    +-------+----------+----------+
    """
    if conj:
        return tuple(-v if bit_on(num, i) else v for i, v in enumerate(vs))
    else:
        return tuple(v if bit_on(num, i) else -v for i, v in enumerate(vs))

def iter_points(vs):
    """Iterate through all points in an N-dimensional space.

    Parameters
    ----------
    vs : [Variable]
    """
    for num in range(1 << len(vs)):
        yield num2point(num, vs)

def iter_terms(vs, conj=False):
    """Iterate through all terms in an N-dimensional space.

    Parameters
    ----------
    vs: [Variable]
    """
    for num in range(1 << len(vs)):
        yield num2term(num, vs, conj)

VARIABLES = dict()

class Variable(object):
    """
    Abstract base class that defines an interface for a Boolean variable.

    A Boolean variable is a numerical quantity that may assume any value in the
    set B = {0, 1}.

    This implementation includes optional indices, nonnegative integers that
    can be used to construct multi-dimensional bit vectors.
    """

    _MEM = dict()
    _CNT = 1

    def __new__(cls, name, indices=None, namespace=None):
        if indices is None:
            indices = tuple()
        elif type(indices) is int:
            indices = (indices, )
        try:
            self = cls._MEM[(namespace, name, indices)]
        except KeyError:
            self = super(Variable, cls).__new__(cls)
            self.namespace = namespace
            self.name = name
            self.indices = indices
            self.uniqid = cls._CNT
            # NOTE: this is not thread-safe
            cls._CNT += 1
            cls._MEM[(self.namespace, self.name, self.indices)] = self
            VARIABLES[self.uniqid] = self
        return self

    def __repr__(self):
        return self.__str__()

    def __str__(self):
        suffix = "".join("[{}]".format(idx) for idx in self.indices)
        return self.qualname + suffix

    def __lt__(self, other):
        if self.name == other.name:
            return self.indices < other.indices
        else:
            return self.name < other.name

    @property
    def qualname(self):
        if self.namespace is None:
            return self.name
        else:
            return self.namespace + "." + self.name

class Function(object):
    """
    Abstract base class that defines an interface for a scalar Boolean function
    of :math:`N` variables.
    """
    @property
    def support(self):
        """Return the support set of a function.

        Let :math:`f(x_1, x_2, ..., x_n)` be a Boolean function of :math:`N`
        variables. The set :math:`\{x_1, x_2, ..., x_n\}` is called the
        *support* of the function.
        """
        raise NotImplementedError()

    @property
    def inputs(self):
        """Return the support set in name/index order."""
        raise NotImplementedError()

    @property
    def top(self):
        """Return the first variable in the ordered support set."""
        return self.inputs[0]

    @property
    def bottom(self):
        """Return the last variable in the ordered support set."""
        return self.inputs[-1]

    @property
    def degree(self):
        """Return the degree of a function.

        A function from :math:`B^{N} \Rightarrow B` is called a Boolean
        function of *degree* :math:`N`.
        """
        return len(self.support)

    @property
    def cardinality(self):
        """Return the cardinality of the relation :math:`B^{N} \Rightarrow B`.

        Always equal to :math:`2^{N}`.
        """
        return 1 << self.degree

    def iter_domain(self):
        """Iterate through all points in the domain."""
        for point in iter_points(self.inputs):
            yield point

    def iter_image(self):
        """Iterate through all elements in the image."""
        for point in iter_points(self.inputs):
            yield self.restrict(point)

    def iter_relation(self):
        """Iterate through all (point, element) pairs in the relation."""
        for point in iter_points(self.inputs):
            yield (point, self.restrict(point))

    def iter_zeros(self):
        """Iterate through all points this function maps to element zero."""
        raise NotImplementedError()

    def iter_ones(self):
        """Iterate through all points this function maps to element one."""
        raise NotImplementedError()

    def reduce(self):
        """Return the function reduced to a canonical form."""
        raise NotImplementedError()

    def restrict(self, point):
        """
        Return the Boolean function that results after restricting a subset of
        its input variables to :math:`\{0, 1\}`.

        :math:`g = f \: | \: x_i = b`
        """
        raise NotImplementedError()

    def vrestrict(self, point):
        """Expand all vectors before applying 'restrict'."""
        return self.restrict(_expand_vectors(point))

    def compose(self, mapping):
        """
        Return the Boolean function that results after substituting a subset of
        its input variables for other Boolean functions.

        :math:`g = f_1 \: | \: x_i = f2`
        """
        raise NotImplementedError()

    def satisfy_one(self):
        """
        If this function is satisfiable, return a satisfying input point. A
        tautology *may* return a zero-dimensional point; a contradiction *must*
        return None.
        """
        raise NotImplementedError()

    def satisfy_all(self):
        """Iterate through all satisfying input points."""
        raise NotImplementedError()

    def satisfy_count(self):
        """Return the cardinality of the set of all satisfying input points."""
        raise NotImplementedError()

    def iter_cofactors(self, vs=None):
        """Iterate through the cofactors of :math:`N` variables."""
        if vs is None:
            vs = list()
        elif not isinstance(vs, collections.Iterable):
            vs = [vs]
        for point in iter_points(vs):
            yield point, self.restrict(point)

    def cofactors(self, vs=None):
        """Return a tuple of cofactors of N variables.

        The *cofactor* of :math:`f(x_1, x_2, ..., x_i, ..., x_n)`
        with respect to variable :math:`x_i` is
        :math:`f_{x_i} = f(x_1, x_2, ..., 1, ..., x_n)`

        The *cofactor* of :math:`f(x_1, x_2, ..., x_i, ..., x_n)`
        with respect to variable :math:`x_i'` is
        :math:`f_{x_i'} = f(x_1, x_2, ..., 0, ..., x_n)`
        """
        return tuple(cf for p, cf in self.iter_cofactors(vs))

    def is_neg_unate(self, vs=None):
        """Return whether a function is negative unate.

        A function :math:`f(x_1, x_2, ..., x_i, ..., x_n)` is *negative unate*
        in variable :math:`x_i` if :math:`f_{x_i'} \geq f_{xi}`.
        """
        raise NotImplementedError()

    def is_pos_unate(self, vs=None):
        """Return whether a function is positive unate.

        A function :math:`f(x_1, x_2, ..., x_i, ..., x_n)` is *positive unate*
        in variable :math:`x_i` if :math:`f_{x_i} \geq f_{x_i'}`.
        """
        raise NotImplementedError()

    def is_binate(self, vs=None):
        """Return whether a function is binate.

        A function :math:`f(x_1, x_2, ..., x_i, ..., x_n)` is *binate* in
        variable :math:`x_i` if it is neither negative nor positive unate in
        :math:`x_i`.
        """
        return not (self.is_neg_unate(vs) or self.is_pos_unate(vs))

    def smoothing(self, vs=None):
        """Return the smoothing of a function.

        The *smoothing* of :math:`f(x_1, x_2, ..., x_i, ..., x_n)` with respect
        to variable :math:`x_i` is :math:`S_{x_i}(f) = f_{x_i} + f_{x_i'}`.
        """
        raise NotImplementedError()

    def consensus(self, vs=None):
        """Return the consensus of a function.

        The *consensus* of :math:`f(x_1, x_2, ..., x_i, ..., x_n)` with respect
        to variable :math:`x_i` is :math:`C_{x_i}(f) = f_{x_i} \cdot f_{x_i'}`.
        """
        raise NotImplementedError()

    def derivative(self, vs=None):
        r"""Return the derivative of a function.

        The *derivate* of :math:`f(x_1, x_2, ..., x_i, ..., x_n)` with respect
        to variable :math:`x_i` is
        :math:`\frac{\partial}{\partial x_i} f = f_{x_i} \oplus f_{x_i'}`.
        """
        raise NotImplementedError()

class Slicer(object):
    def __init__(self, items, start=0):
        self.items = items
        self.start = start

    @property
    def stop(self):
        return self.start + self.__len__()

    def __iter__(self):
        return iter(self.items)

    def __len__(self):
        return len(self.items)

    def getifz(self, i):
        """Get item from zero-based index."""
        return self.__getitem__(i + self.start)

    def __getitem__(self, sl):
        if isinstance(sl, int):
            return self.items[self._norm_idx(sl)]
        else:
            items = self.items[self._norm_slice(sl)]
            return self.__class__(items, sl.start)

    def __setitem__(self, sl, item):
        if isinstance(sl, int):
            self.items[self._norm_idx(sl)] = item
        else:
            self.items[self._norm_slice(sl)] = item

    def _norm_idx(self, i):
        """Return an index normalized to vector start index."""
        if i >= self.start and i < self.stop:
            idx = i - self.start
        elif i >= -self.stop and i < -self.start:
            idx = i + self.stop
        else:
            raise IndexError("list index out of range")
        return idx

    def _norm_slice(self, sl):
        """Return a slice normalized to vector start index."""
        limits = {'start': None, 'stop': None}
        for k in ('start', 'stop'):
            i = getattr(sl, k)
            if i is not None:
                if i >= self.start and i < self.stop:
                    limits[k] = i - self.start
                elif i >= -self.stop and i < -self.start:
                    limits[k] = i + self.stop
                else:
                    raise IndexError("list index out of range")
        return slice(limits['start'], limits['stop'])

class VectorFunction(Slicer):
    """
    Abstract base class that defines an interface for a vector Boolean function.
    """
    def restrict(self, point):
        """
        Return the vector that results from applying the 'restrict' method to
        all functions.
        """
        items = [f.restrict(point) for f in self]
        return self.__class__(items, self.start)

    def vrestrict(self, point):
        """Expand all vectors before applying 'restrict'."""
        return self.restrict(_expand_vectors(point))

    def to_uint(self):
        """Convert vector to an unsigned integer, if possible."""
        num = 0
        for i, f in enumerate(self):
            if f in {0, 1}:
                if f:
                    num += 1 << i
            else:
                raise ValueError("cannot convert to uint")
        return num

    def to_int(self):
        """Convert vector to an integer, if possible."""
        num = self.to_uint()
        if self.items[-1]:
            return num - (1 << self.__len__())
        else:
            return num

    def zext(self, num):
        """Zero extend this vector by N bits."""
        self.items += [0] * num

    def sext(self, num):
        """Sign extend this vector by N bits."""
        bit = self.items[-1]
        self.items += [bit] * num

    def append(self, f):
        """Append a function to the end of this vector."""
        self.items.append(f)

def _expand_vectors(point):
    """Expand all vectors in a substitution dict."""
    temp = { vf: val for vf, val in point.items() if
             isinstance(vf, VectorFunction) }
    point = {v: val for v, val in point.items() if v not in temp}
    while temp:
        vf, val = temp.popitem()
        if isinstance(vf, VectorFunction):
            assert len(vf) == len(val)
            for i, f in enumerate(val):
                point[vf.getifz(i)] = f
        else:
            point[vf] = val
    return point
<commit_msg>Update boolfunc top comment<commit_after>"""
Boolean Functions

Globals:
    VARIABLES

Interface Functions:
    num2point
    point2term
    num2term
    iter_points
    iter_terms

Interface Classes:
    Variable
    Function
    Slicer
    VectorFunction
"""

import collections

from pyeda.common import bit_on

def num2point(num, vs):
    """Convert a number to a point in an N-dimensional space."""
    return {v: bit_on(num, i) for i, v in enumerate(vs)}

def point2term(point, conj=False):
    """Convert a point in an N-dimension space to a min/max term."""
    if conj:
        return tuple(-v if val else v for v, val in point.items())
    else:
        return tuple(v if val else -v for v, val in point.items())

def num2term(num, vs, conj=False):
    """Return a tuple of all variables for a given term index.

    Parameters
    ----------
    num: int
    vs: [Variable]
    conj: bool
        conj=False for minterms, conj=True for maxterms

    Examples
    --------

    Table of min/max terms for Boolean space {a, b, c}

    +-----+----------+----------+
    | num |  minterm |  maxterm |
    +=====+==========+==========+
    | 0   | a' b' c' | a  b  c  |
    | 1   | a  b' c' | a' b  c  |
    | 2   | a' b  c' | a  b' c  |
    | 3   | a  b  c' | a' b' c  |
    | 4   | a' b' c  | a  b  c' |
    | 5   | a  b' c  | a' b  c' |
    | 6   | a' b  c  | a  b' c' |
    | 7   | a  b  c  | a' b' c' |
    +-------+----------+----------+
    """
    if conj:
        return tuple(-v if bit_on(num, i) else v for i, v in enumerate(vs))
    else:
        return tuple(v if bit_on(num, i) else -v for i, v in enumerate(vs))

def iter_points(vs):
    """Iterate through all points in an N-dimensional space.

    Parameters
    ----------
    vs : [Variable]
    """
    for num in range(1 << len(vs)):
        yield num2point(num, vs)

def iter_terms(vs, conj=False):
    """Iterate through all terms in an N-dimensional space.

    Parameters
    ----------
    vs: [Variable]
    """
    for num in range(1 << len(vs)):
        yield num2term(num, vs, conj)

VARIABLES = dict()

class Variable(object):
    """
    Abstract base class that defines an interface for a Boolean variable.

    A Boolean variable is a numerical quantity that may assume any value in the
    set B = {0, 1}.

    This implementation includes optional indices, nonnegative integers that
    can be used to construct multi-dimensional bit vectors.
    """

    _MEM = dict()
    _CNT = 1

    def __new__(cls, name, indices=None, namespace=None):
        if indices is None:
            indices = tuple()
        elif type(indices) is int:
            indices = (indices, )
        try:
            self = cls._MEM[(namespace, name, indices)]
        except KeyError:
            self = super(Variable, cls).__new__(cls)
            self.namespace = namespace
            self.name = name
            self.indices = indices
            self.uniqid = cls._CNT
            # NOTE: this is not thread-safe
            cls._CNT += 1
            cls._MEM[(self.namespace, self.name, self.indices)] = self
            VARIABLES[self.uniqid] = self
        return self

    def __repr__(self):
        return self.__str__()

    def __str__(self):
        suffix = "".join("[{}]".format(idx) for idx in self.indices)
        return self.qualname + suffix

    def __lt__(self, other):
        if self.name == other.name:
            return self.indices < other.indices
        else:
            return self.name < other.name

    @property
    def qualname(self):
        if self.namespace is None:
            return self.name
        else:
            return self.namespace + "." + self.name

class Function(object):
    """
    Abstract base class that defines an interface for a scalar Boolean function
    of :math:`N` variables.
    """
    @property
    def support(self):
        """Return the support set of a function.

        Let :math:`f(x_1, x_2, ..., x_n)` be a Boolean function of :math:`N`
        variables. The set :math:`\{x_1, x_2, ..., x_n\}` is called the
        *support* of the function.
        """
        raise NotImplementedError()

    @property
    def inputs(self):
        """Return the support set in name/index order."""
        raise NotImplementedError()

    @property
    def top(self):
        """Return the first variable in the ordered support set."""
        return self.inputs[0]

    @property
    def bottom(self):
        """Return the last variable in the ordered support set."""
        return self.inputs[-1]

    @property
    def degree(self):
        """Return the degree of a function.

        A function from :math:`B^{N} \Rightarrow B` is called a Boolean
        function of *degree* :math:`N`.
        """
        return len(self.support)

    @property
    def cardinality(self):
        """Return the cardinality of the relation :math:`B^{N} \Rightarrow B`.

        Always equal to :math:`2^{N}`.
        """
        return 1 << self.degree

    def iter_domain(self):
        """Iterate through all points in the domain."""
        for point in iter_points(self.inputs):
            yield point

    def iter_image(self):
        """Iterate through all elements in the image."""
        for point in iter_points(self.inputs):
            yield self.restrict(point)

    def iter_relation(self):
        """Iterate through all (point, element) pairs in the relation."""
        for point in iter_points(self.inputs):
            yield (point, self.restrict(point))

    def iter_zeros(self):
        """Iterate through all points this function maps to element zero."""
        raise NotImplementedError()

    def iter_ones(self):
        """Iterate through all points this function maps to element one."""
        raise NotImplementedError()

    def reduce(self):
        """Return the function reduced to a canonical form."""
        raise NotImplementedError()

    def restrict(self, point):
        """
        Return the Boolean function that results after restricting a subset of
        its input variables to :math:`\{0, 1\}`.

        :math:`g = f \: | \: x_i = b`
        """
        raise NotImplementedError()

    def vrestrict(self, point):
        """Expand all vectors before applying 'restrict'."""
        return self.restrict(_expand_vectors(point))

    def compose(self, mapping):
        """
        Return the Boolean function that results after substituting a subset of
        its input variables for other Boolean functions.

        :math:`g = f_1 \: | \: x_i = f2`
        """
        raise NotImplementedError()

    def satisfy_one(self):
        """
        If this function is satisfiable, return a satisfying input point. A
        tautology *may* return a zero-dimensional point; a contradiction *must*
        return None.
        """
        raise NotImplementedError()

    def satisfy_all(self):
        """Iterate through all satisfying input points."""
        raise NotImplementedError()

    def satisfy_count(self):
        """Return the cardinality of the set of all satisfying input points."""
        raise NotImplementedError()

    def iter_cofactors(self, vs=None):
        """Iterate through the cofactors of :math:`N` variables."""
        if vs is None:
            vs = list()
        elif not isinstance(vs, collections.Iterable):
            vs = [vs]
        for point in iter_points(vs):
            yield point, self.restrict(point)

    def cofactors(self, vs=None):
        """Return a tuple of cofactors of N variables.

        The *cofactor* of :math:`f(x_1, x_2, ..., x_i, ..., x_n)`
        with respect to variable :math:`x_i` is
        :math:`f_{x_i} = f(x_1, x_2, ..., 1, ..., x_n)`

        The *cofactor* of :math:`f(x_1, x_2, ..., x_i, ..., x_n)`
        with respect to variable :math:`x_i'` is
        :math:`f_{x_i'} = f(x_1, x_2, ..., 0, ..., x_n)`
        """
        return tuple(cf for p, cf in self.iter_cofactors(vs))

    def is_neg_unate(self, vs=None):
        """Return whether a function is negative unate.

        A function :math:`f(x_1, x_2, ..., x_i, ..., x_n)` is *negative unate*
        in variable :math:`x_i` if :math:`f_{x_i'} \geq f_{xi}`.
        """
        raise NotImplementedError()

    def is_pos_unate(self, vs=None):
        """Return whether a function is positive unate.

        A function :math:`f(x_1, x_2, ..., x_i, ..., x_n)` is *positive unate*
        in variable :math:`x_i` if :math:`f_{x_i} \geq f_{x_i'}`.
        """
        raise NotImplementedError()

    def is_binate(self, vs=None):
        """Return whether a function is binate.

        A function :math:`f(x_1, x_2, ..., x_i, ..., x_n)` is *binate* in
        variable :math:`x_i` if it is neither negative nor positive unate in
        :math:`x_i`.
        """
        return not (self.is_neg_unate(vs) or self.is_pos_unate(vs))

    def smoothing(self, vs=None):
        """Return the smoothing of a function.

        The *smoothing* of :math:`f(x_1, x_2, ..., x_i, ..., x_n)` with respect
        to variable :math:`x_i` is :math:`S_{x_i}(f) = f_{x_i} + f_{x_i'}`.
        """
        raise NotImplementedError()

    def consensus(self, vs=None):
        """Return the consensus of a function.

        The *consensus* of :math:`f(x_1, x_2, ..., x_i, ..., x_n)` with respect
        to variable :math:`x_i` is :math:`C_{x_i}(f) = f_{x_i} \cdot f_{x_i'}`.
        """
        raise NotImplementedError()

    def derivative(self, vs=None):
        r"""Return the derivative of a function.

        The *derivate* of :math:`f(x_1, x_2, ..., x_i, ..., x_n)` with respect
        to variable :math:`x_i` is
        :math:`\frac{\partial}{\partial x_i} f = f_{x_i} \oplus f_{x_i'}`.
        """
        raise NotImplementedError()

class Slicer(object):
    def __init__(self, items, start=0):
        self.items = items
        self.start = start

    @property
    def stop(self):
        return self.start + self.__len__()

    def __iter__(self):
        return iter(self.items)

    def __len__(self):
        return len(self.items)

    def getifz(self, i):
        """Get item from zero-based index."""
        return self.__getitem__(i + self.start)

    def __getitem__(self, sl):
        if isinstance(sl, int):
            return self.items[self._norm_idx(sl)]
        else:
            items = self.items[self._norm_slice(sl)]
            return self.__class__(items, sl.start)

    def __setitem__(self, sl, item):
        if isinstance(sl, int):
            self.items[self._norm_idx(sl)] = item
        else:
            self.items[self._norm_slice(sl)] = item

    def _norm_idx(self, i):
        """Return an index normalized to vector start index."""
        if i >= self.start and i < self.stop:
            idx = i - self.start
        elif i >= -self.stop and i < -self.start:
            idx = i + self.stop
        else:
            raise IndexError("list index out of range")
        return idx

    def _norm_slice(self, sl):
        """Return a slice normalized to vector start index."""
        limits = {'start': None, 'stop': None}
        for k in ('start', 'stop'):
            i = getattr(sl, k)
            if i is not None:
                if i >= self.start and i < self.stop:
                    limits[k] = i - self.start
                elif i >= -self.stop and i < -self.start:
                    limits[k] = i + self.stop
                else:
                    raise IndexError("list index out of range")
        return slice(limits['start'], limits['stop'])

class VectorFunction(Slicer):
    """
    Abstract base class that defines an interface for a vector Boolean function.
    """
    def restrict(self, point):
        """
        Return the vector that results from applying the 'restrict' method to
        all functions.
        """
        items = [f.restrict(point) for f in self]
        return self.__class__(items, self.start)

    def vrestrict(self, point):
        """Expand all vectors before applying 'restrict'."""
        return self.restrict(_expand_vectors(point))

    def to_uint(self):
        """Convert vector to an unsigned integer, if possible."""
        num = 0
        for i, f in enumerate(self):
            if f in {0, 1}:
                if f:
                    num += 1 << i
            else:
                raise ValueError("cannot convert to uint")
        return num

    def to_int(self):
        """Convert vector to an integer, if possible."""
        num = self.to_uint()
        if self.items[-1]:
            return num - (1 << self.__len__())
        else:
            return num

    def zext(self, num):
        """Zero extend this vector by N bits."""
        self.items += [0] * num

    def sext(self, num):
        """Sign extend this vector by N bits."""
        bit = self.items[-1]
        self.items += [bit] * num

    def append(self, f):
        """Append a function to the end of this vector."""
        self.items.append(f)

def _expand_vectors(point):
    """Expand all vectors in a substitution dict."""
    temp = { vf: val for vf, val in point.items() if
             isinstance(vf, VectorFunction) }
    point = {v: val for v, val in point.items() if v not in temp}
    while temp:
        vf, val = temp.popitem()
        if isinstance(vf, VectorFunction):
            assert len(vf) == len(val)
            for i, f in enumerate(val):
                point[vf.getifz(i)] = f
        else:
            point[vf] = val
    return point
<|endoftext|>


<commit_before>__author__ = 'Joe Linn'

import requests
import json
from requests.exceptions import HTTPError
from pyflare import APIError

class PyflareClient(object):

    CLOUDFLARE_URL = 'https://www.cloudflare.com/api_json.html'

    def __init__(self, email, token):
        """
        Instantiate a Pyflare client object
        :param email: The email address associated with your Cloudflare account
        :type email: str
        :param token: The API key associated with your Cloudflare account
        :type token: str
        """
        self._email = email
        self._token = token

    def stats(self, zone, interval):
        """
        Retrive the current stats and settings for a particular website.
        :param zone:  The domain for which statistics are being retrieved.
        :type zone: str
        :param interval: The time interval for the statistics denoted by the following values:
            20 = Past 30 days
            30 = Past 7 days
            40 = Past day

            The values are for Pro accounts
            100 = 24 hours ago
            110 = 12 hours ago
            120 = 6 hours ago
        :type interval: int
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'stats',
            'z': zone,
            'interval': interval
        })

    def zone_load_multi(self):
        """
        Lists all domains in a CloudFlare account, along with other data.
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'zone_load_multi'
        })

    def rec_load_all(self, zone):
        """
        Lists all DNS records for the given domain
        :param zone: the domain for which records are being retrieved
        :type zone: str
        :return:
        :rtype: generator
        """
        has_more = True
        current_count = 0
        while has_more:
            records = self._request({
                'a': 'rec_load_all',
                'o': current_count,
                'z': zone
            })
            try:
                has_more = records['response']['recs']['has_more']
                current_count += records['response']['recs']['count']
                for record in records['response']['recs']['objs']:
                    yield record
            except KeyError:
                has_more = False

    def zone_check(self, zones):
        """
        Checks for active zones and returns their corresponding zids
        :param zones: List of zones
        :type zones: list of str
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'zone_check',
            'zones': ','.join(zones)
        })

    def zone_ips(self, zone, hours=24, ip_class=None, geo=False):
        """
        Retrieve IP addresses of recent visitors
        :param zone: the target domain
        :type zone: str
        :param hours: Past number of hours to query. Defaults to 24, maximum is 48.
        :type hours: int
        :param ip_class: Optional. Restrict the result set to a given class as given by:
            "r" -- regular
            "s" -- crawler
            "t" -- threat
        :type ip_class: str
        :param geo: Optional. Set to True to add longitude and latitude information to response
        :type geo: bool
        :return:
        :rtype: dict
        """
        params = {
            'a': 'zone_ips',
            'z': zone,
            'hours': hours,
            'class': ip_class,
        }
        if geo:
            params['geo'] = geo
        return self._request(params)

    def ip_lkup(self, ip):
        """
        Find the current threat score for a given IP. Note that scores are on a logarithmic scale, where a higher score
        indicates a higher threat.
        :param ip: the target IP
        :type ip: str
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'ip_lkup',
            'ip': ip
        })

    def zone_settings(self, zone):
        """
        Retrieves all current settings for a given domain.
        :param zone: the target domain
        :type zone: str
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'zone_settings',
            'z': zone
        })

    def sec_lvl(self, zone, level):
        """
        Set the security level for the given zone
        :param zone: domain name
        :type zone: str
        :param level: security level:
            "help" -- I'm under attack!
            "high" -- High
            "med" -- Medium
            "low" -- Low
            "eoff" -- Essentially Off
        :type level: str
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'sec_lvl',
            'z': zone,
            'v': level
        })

    def cache_lvl(self, zone, level):
        """
        Set the caching level for the given zone
        :param zone: domain name
        :type zone: str
        :param level: cache level:
            "agg" -- Aggressive
            "basic" -- Basic
        :type level: str
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'cache_lvl',
            'z': zone,
            'v': level
        })

    def devmode(self, zone, enabled):
        """
        This function allows you to toggle Development Mode on or off for a particular domain.
        When Development Mode is on the cache is bypassed. Development mode remains on for 3 hours or
        until when it is toggled back off.
        :param zone: domain name
        :type zone: str
        :param enabled: True to turn dev mode on, False to turn dev mode off.
        :type enabled: bool
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'devmode',
            'z': zone,
            'v': int(enabled)
        })

    def fpurge_ts(self, zone):
        """
        This function will purge CloudFlare of any cached files. It may take up to 48 hours for the cache to
        rebuild and optimum performance to be achieved so this function should be used sparingly.
        :param zone: domain name
        :type zone: str
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'fpurge_ts',
            'z': zone,
            'v': 1      # Value can only be "1."
        })

    def zone_file_purge(self, zone, url):
        """
        This function will purge a single file from CloudFlare's cache.
        :param zone: domain name
        :type zone: str
        :param url: The full URL of the file that needs to be purged from Cloudflare's cache. Keep in mind
            that if an HTTP and an HTTPS version of the file exists, then both versions will need to be purged
            independently.
        :type url: str
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'zone_file_purge',
            'z': zone,
            'url': url
        })

    def zone_grab(self, zone_id):
        """
        Update the snapshot of site for CloudFlare's challenge page
        :param zone_id: ID of zone, found in zone_check
        :type zone_id: int
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'zone_grab',
            'zid': zone_id
        })

    def wl(self, ip):
        """
        Whitelist an ip address
        :param ip: The IP address you want to whitelist
        :type ip: str
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'wl',
            'key': ip
        })

    def ban(self, ip):
        """
        Blacklist an ip address
        :param ip: The IP address you want to ban
        :type ip: str
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'ban',
            'key': ip
        })

    def nul(self, ip):
        """
        Remove an IP address from the whitelist or blacklist
        :param ip: The IP address to remove
        :type ip: str
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'nul',
            'key': ip
        })

    def ipv46(self, zone, enable):
        """
        Toggles IPv6 support
        :param zone: domain name
        :type zone: str
        :param enable: True to enable, False to disable.
        :type enable: bool
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'ipv46',
            'z': zone,
            'v': int(enable)
        })

    def async(self, zone, setting):
        """
        Changes Rocket Loader setting
        :param zone: domain name
        :type zone: str
        :param setting: [0 = off, a = automatic, m = manual]
        :type setting: int or str
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'async',
            'z': zone,
            'v': setting
        })

    def minify(self, zone, setting):
        """
        Changes minification settings
        :param zone: domain name
        :type zone: str
        :param setting:
            0 = off
            1 = JavaScript only
            2 = CSS only
            3 = JavaScript and CSS
            4 = HTML only
            5 = JavaScript and HTML
            6 = CSS and HTML
            7 = CSS, JavaScript, and HTML
        :type setting: int
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'minify',
            'z': zone,
            'v': setting
        })

    def mirage2(self, zone, enable):
        """
        Toggles mirage2 support
        :param zone: domain name
        :type zone: str
        :param enable: True to enable, False to disable.
        :type enable: bool
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'mirage2',
            'z': zone,
            'v': int(enable)
        })

    def rec_new(self, zone, record_type, name, content, ttl=1, priority=None, service=None, service_name=None,
                protocol=None, weight=None, port=None, target=None):
        """
        Create a DNS record for the given zone
        :param zone: domain name
        :type zone: str
        :param record_type: Type of DNS record. Valid values are [A/CNAME/MX/TXT/SPF/AAAA/NS/SRV/LOC]
        :type record_type: str
        :param name: name of the DNS record
        :type name: str
        :param content: content of the DNS record
        :type content: str
        :param ttl: TTL of the DNS record in seconds. 1 = Automatic, otherwise, value must in between 120 and
            4,294,967,295 seconds.
        :type ttl: int
        :param priority: [applies to MX/SRV] MX record priority.
        :type priority: int
        :param service: Service for SRV record
        :type service: str
        :param service_name: Service Name for SRV record
        :type service_name: str
        :param protocol: Protocol for SRV record. Values are [_tcp/_udp/_tls].
        :type protocol: str
        :param weight: Weight for SRV record.
        :type weight: int
        :param port: Port for SRV record
        :type port: int
        :param target: Target for SRV record
        :type target: str
        :return:
        :rtype: dict
        """
        params = {
            'a': 'rec_new',
            'z': zone,
            'type': record_type,
            'name': name,
            'content': content,
            'ttl': ttl
        }
        if priority is not None:
            params['prio'] = priority
        if service is not None:
            params['service'] = service
        if service_name is not None:
            params['srvname'] = service_name
        if protocol is not None:
            params['protocol'] = protocol
        if weight is not None:
            params['weight'] = weight
        if port is not None:
            params['port'] = port
        if target is not None:
            params['target'] = target
        return self._request(params)

    def rec_edit(self, zone, record_type, record_id, name, content, ttl=1, service_mode=None, priority=None,
                 service=None, service_name=None, protocol=None, weight=None, port=None, target=None):
        """
        Edit a DNS record for the given zone.
        :param zone: domain name
        :type zone: str
        :param record_type: Type of DNS record. Valid values are [A/CNAME/MX/TXT/SPF/AAAA/NS/SRV/LOC]
        :type record_type: str
        :param record_id: DNS Record ID. Available by using the rec_load_all call.
        :type record_id: int
        :param name: Name of the DNS record
        :type name: str
        :param content: The content of the DNS record, will depend on the the type of record being added
        :type content: str
        :param ttl: TTL of record in seconds. 1 = Automatic, otherwise, value must in between 120 and 4,294,967,295
            seconds.
        :type ttl: int
        :param service_mode: [applies to A/AAAA/CNAME] Status of CloudFlare Proxy, 1 = orange cloud, 0 = grey cloud.
        :type service_mode: int
        :param priority: [applies to MX/SRV] MX record priority.
        :type priority: int
        :param service: Service for SRV record
        :type service: str
        :param service_name: Service Name for SRV record
        :type service_name: str
        :param protocol: Protocol for SRV record. Values are [_tcp/_udp/_tls].
        :type protocol: str
        :param weight: Weight for SRV record.
        :type weight: int
        :param port: Port for SRV record
        :type port: int
        :param target: Target for SRV record
        :type target: str
        :return:
        :rtype: dict
        """
        params = {
            'a': 'rec_edit',
            'z': zone,
            'type': record_type,
            'id': record_id,
            'name': name,
            'content': content,
            'ttl': ttl
        }
        if service_mode is not None:
            params['service_mode'] = service_mode
        if priority is not None:
            params['prio'] = priority
        if service is not None:
            params['service'] = service
        if service_name is not None:
            params['srvname'] = service_name
        if protocol is not None:
            params['protocol'] = protocol
        if weight is not None:
            params['weight'] = weight
        if port is not None:
            params['port'] = port
        if target is not None:
            params['target'] = target
        return self._request(params)

    def rec_delete(self, zone, record_id):
        """
        Delete a record for the given domain.
        :param zone: domain name
        :type zone: str
        :param record_id: DNS Record ID. Available by using the rec_load_all call.
        :type record_id: int
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'rec_delete',
            'z': zone,
            'id': record_id
        })

    def _request(self, data):
        """

        :param data: Request body to be sent to Cloudflare
        :type data: dict
        :return: Response from Cloudflare
        :rtype: dict
        """
        data['tkn'] = self._token
        data['email'] = self._email
        response = requests.post(self.CLOUDFLARE_URL, data=data)
        deserialized_response = self._deserialize_response(response.content.decode("utf-8"))

        if deserialized_response.get('result') == 'error':
            api_error = APIError(dezerialized_response['msg'], deserialized_response['err_code'])
            api_error.response = response
            raise api_error

        return deserialized_response

    def _deserialize_response(self, response):
        """
        :param: response: Response body returned from Cloudflare
        :return: deserialized json response if valid, else raise ResponseError
        :rtype: dict
        """

        try:
            return json.loads(response)
        except APIError:
            raise APIError("Unexpected response from Cloudflare API")
<commit_msg>Fix global name error and remove redundancy<commit_after>__author__ = 'Joe Linn'

import requests
import json
from requests.exceptions import HTTPError
from pyflare import APIError

class PyflareClient(object):

    CLOUDFLARE_URL = 'https://www.cloudflare.com/api_json.html'

    def __init__(self, email, token):
        """
        Instantiate a Pyflare client object
        :param email: The email address associated with your Cloudflare account
        :type email: str
        :param token: The API key associated with your Cloudflare account
        :type token: str
        """
        self._email = email
        self._token = token

    def stats(self, zone, interval):
        """
        Retrive the current stats and settings for a particular website.
        :param zone:  The domain for which statistics are being retrieved.
        :type zone: str
        :param interval: The time interval for the statistics denoted by the following values:
            20 = Past 30 days
            30 = Past 7 days
            40 = Past day

            The values are for Pro accounts
            100 = 24 hours ago
            110 = 12 hours ago
            120 = 6 hours ago
        :type interval: int
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'stats',
            'z': zone,
            'interval': interval
        })

    def zone_load_multi(self):
        """
        Lists all domains in a CloudFlare account, along with other data.
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'zone_load_multi'
        })

    def rec_load_all(self, zone):
        """
        Lists all DNS records for the given domain
        :param zone: the domain for which records are being retrieved
        :type zone: str
        :return:
        :rtype: generator
        """
        has_more = True
        current_count = 0
        while has_more:
            records = self._request({
                'a': 'rec_load_all',
                'o': current_count,
                'z': zone
            })
            try:
                has_more = records['response']['recs']['has_more']
                current_count += records['response']['recs']['count']
                for record in records['response']['recs']['objs']:
                    yield record
            except KeyError:
                has_more = False

    def zone_check(self, zones):
        """
        Checks for active zones and returns their corresponding zids
        :param zones: List of zones
        :type zones: list of str
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'zone_check',
            'zones': ','.join(zones)
        })

    def zone_ips(self, zone, hours=24, ip_class=None, geo=False):
        """
        Retrieve IP addresses of recent visitors
        :param zone: the target domain
        :type zone: str
        :param hours: Past number of hours to query. Defaults to 24, maximum is 48.
        :type hours: int
        :param ip_class: Optional. Restrict the result set to a given class as given by:
            "r" -- regular
            "s" -- crawler
            "t" -- threat
        :type ip_class: str
        :param geo: Optional. Set to True to add longitude and latitude information to response
        :type geo: bool
        :return:
        :rtype: dict
        """
        params = {
            'a': 'zone_ips',
            'z': zone,
            'hours': hours,
            'class': ip_class,
        }
        if geo:
            params['geo'] = geo
        return self._request(params)

    def ip_lkup(self, ip):
        """
        Find the current threat score for a given IP. Note that scores are on a logarithmic scale, where a higher score
        indicates a higher threat.
        :param ip: the target IP
        :type ip: str
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'ip_lkup',
            'ip': ip
        })

    def zone_settings(self, zone):
        """
        Retrieves all current settings for a given domain.
        :param zone: the target domain
        :type zone: str
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'zone_settings',
            'z': zone
        })

    def sec_lvl(self, zone, level):
        """
        Set the security level for the given zone
        :param zone: domain name
        :type zone: str
        :param level: security level:
            "help" -- I'm under attack!
            "high" -- High
            "med" -- Medium
            "low" -- Low
            "eoff" -- Essentially Off
        :type level: str
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'sec_lvl',
            'z': zone,
            'v': level
        })

    def cache_lvl(self, zone, level):
        """
        Set the caching level for the given zone
        :param zone: domain name
        :type zone: str
        :param level: cache level:
            "agg" -- Aggressive
            "basic" -- Basic
        :type level: str
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'cache_lvl',
            'z': zone,
            'v': level
        })

    def devmode(self, zone, enabled):
        """
        This function allows you to toggle Development Mode on or off for a particular domain.
        When Development Mode is on the cache is bypassed. Development mode remains on for 3 hours or
        until when it is toggled back off.
        :param zone: domain name
        :type zone: str
        :param enabled: True to turn dev mode on, False to turn dev mode off.
        :type enabled: bool
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'devmode',
            'z': zone,
            'v': int(enabled)
        })

    def fpurge_ts(self, zone):
        """
        This function will purge CloudFlare of any cached files. It may take up to 48 hours for the cache to
        rebuild and optimum performance to be achieved so this function should be used sparingly.
        :param zone: domain name
        :type zone: str
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'fpurge_ts',
            'z': zone,
            'v': 1      # Value can only be "1."
        })

    def zone_file_purge(self, zone, url):
        """
        This function will purge a single file from CloudFlare's cache.
        :param zone: domain name
        :type zone: str
        :param url: The full URL of the file that needs to be purged from Cloudflare's cache. Keep in mind
            that if an HTTP and an HTTPS version of the file exists, then both versions will need to be purged
            independently.
        :type url: str
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'zone_file_purge',
            'z': zone,
            'url': url
        })

    def zone_grab(self, zone_id):
        """
        Update the snapshot of site for CloudFlare's challenge page
        :param zone_id: ID of zone, found in zone_check
        :type zone_id: int
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'zone_grab',
            'zid': zone_id
        })

    def wl(self, ip):
        """
        Whitelist an ip address
        :param ip: The IP address you want to whitelist
        :type ip: str
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'wl',
            'key': ip
        })

    def ban(self, ip):
        """
        Blacklist an ip address
        :param ip: The IP address you want to ban
        :type ip: str
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'ban',
            'key': ip
        })

    def nul(self, ip):
        """
        Remove an IP address from the whitelist or blacklist
        :param ip: The IP address to remove
        :type ip: str
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'nul',
            'key': ip
        })

    def ipv46(self, zone, enable):
        """
        Toggles IPv6 support
        :param zone: domain name
        :type zone: str
        :param enable: True to enable, False to disable.
        :type enable: bool
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'ipv46',
            'z': zone,
            'v': int(enable)
        })

    def async(self, zone, setting):
        """
        Changes Rocket Loader setting
        :param zone: domain name
        :type zone: str
        :param setting: [0 = off, a = automatic, m = manual]
        :type setting: int or str
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'async',
            'z': zone,
            'v': setting
        })

    def minify(self, zone, setting):
        """
        Changes minification settings
        :param zone: domain name
        :type zone: str
        :param setting:
            0 = off
            1 = JavaScript only
            2 = CSS only
            3 = JavaScript and CSS
            4 = HTML only
            5 = JavaScript and HTML
            6 = CSS and HTML
            7 = CSS, JavaScript, and HTML
        :type setting: int
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'minify',
            'z': zone,
            'v': setting
        })

    def mirage2(self, zone, enable):
        """
        Toggles mirage2 support
        :param zone: domain name
        :type zone: str
        :param enable: True to enable, False to disable.
        :type enable: bool
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'mirage2',
            'z': zone,
            'v': int(enable)
        })

    def rec_new(self, zone, record_type, name, content, ttl=1, priority=None, service=None, service_name=None,
                protocol=None, weight=None, port=None, target=None):
        """
        Create a DNS record for the given zone
        :param zone: domain name
        :type zone: str
        :param record_type: Type of DNS record. Valid values are [A/CNAME/MX/TXT/SPF/AAAA/NS/SRV/LOC]
        :type record_type: str
        :param name: name of the DNS record
        :type name: str
        :param content: content of the DNS record
        :type content: str
        :param ttl: TTL of the DNS record in seconds. 1 = Automatic, otherwise, value must in between 120 and
            4,294,967,295 seconds.
        :type ttl: int
        :param priority: [applies to MX/SRV] MX record priority.
        :type priority: int
        :param service: Service for SRV record
        :type service: str
        :param service_name: Service Name for SRV record
        :type service_name: str
        :param protocol: Protocol for SRV record. Values are [_tcp/_udp/_tls].
        :type protocol: str
        :param weight: Weight for SRV record.
        :type weight: int
        :param port: Port for SRV record
        :type port: int
        :param target: Target for SRV record
        :type target: str
        :return:
        :rtype: dict
        """
        params = {
            'a': 'rec_new',
            'z': zone,
            'type': record_type,
            'name': name,
            'content': content,
            'ttl': ttl
        }
        if priority is not None:
            params['prio'] = priority
        if service is not None:
            params['service'] = service
        if service_name is not None:
            params['srvname'] = service_name
        if protocol is not None:
            params['protocol'] = protocol
        if weight is not None:
            params['weight'] = weight
        if port is not None:
            params['port'] = port
        if target is not None:
            params['target'] = target
        return self._request(params)

    def rec_edit(self, zone, record_type, record_id, name, content, ttl=1, service_mode=None, priority=None,
                 service=None, service_name=None, protocol=None, weight=None, port=None, target=None):
        """
        Edit a DNS record for the given zone.
        :param zone: domain name
        :type zone: str
        :param record_type: Type of DNS record. Valid values are [A/CNAME/MX/TXT/SPF/AAAA/NS/SRV/LOC]
        :type record_type: str
        :param record_id: DNS Record ID. Available by using the rec_load_all call.
        :type record_id: int
        :param name: Name of the DNS record
        :type name: str
        :param content: The content of the DNS record, will depend on the the type of record being added
        :type content: str
        :param ttl: TTL of record in seconds. 1 = Automatic, otherwise, value must in between 120 and 4,294,967,295
            seconds.
        :type ttl: int
        :param service_mode: [applies to A/AAAA/CNAME] Status of CloudFlare Proxy, 1 = orange cloud, 0 = grey cloud.
        :type service_mode: int
        :param priority: [applies to MX/SRV] MX record priority.
        :type priority: int
        :param service: Service for SRV record
        :type service: str
        :param service_name: Service Name for SRV record
        :type service_name: str
        :param protocol: Protocol for SRV record. Values are [_tcp/_udp/_tls].
        :type protocol: str
        :param weight: Weight for SRV record.
        :type weight: int
        :param port: Port for SRV record
        :type port: int
        :param target: Target for SRV record
        :type target: str
        :return:
        :rtype: dict
        """
        params = {
            'a': 'rec_edit',
            'z': zone,
            'type': record_type,
            'id': record_id,
            'name': name,
            'content': content,
            'ttl': ttl
        }
        if service_mode is not None:
            params['service_mode'] = service_mode
        if priority is not None:
            params['prio'] = priority
        if service is not None:
            params['service'] = service
        if service_name is not None:
            params['srvname'] = service_name
        if protocol is not None:
            params['protocol'] = protocol
        if weight is not None:
            params['weight'] = weight
        if port is not None:
            params['port'] = port
        if target is not None:
            params['target'] = target
        return self._request(params)

    def rec_delete(self, zone, record_id):
        """
        Delete a record for the given domain.
        :param zone: domain name
        :type zone: str
        :param record_id: DNS Record ID. Available by using the rec_load_all call.
        :type record_id: int
        :return:
        :rtype: dict
        """
        return self._request({
            'a': 'rec_delete',
            'z': zone,
            'id': record_id
        })

    def _request(self, data):
        """

        :param data: Request body to be sent to Cloudflare
        :type data: dict
        :return: Response from Cloudflare
        :rtype: dict
        """
        data['tkn'] = self._token
        data['email'] = self._email
        response = requests.post(self.CLOUDFLARE_URL, data=data)
        deserialized_response = self._deserialize_response(response.content.decode("utf-8"))

        if deserialized_response.get('result') == 'error':
            raise APIError(deserialized_response['msg'], deserialized_response['err_code'])

        return deserialized_response

    def _deserialize_response(self, response):
        """
        :param: response: Response body returned from Cloudflare
        :return: deserialized json response if valid, else raise ResponseError
        :rtype: dict
        """

        try:
            return json.loads(response)
        except APIError:
            raise APIError("Unexpected response from Cloudflare API")
<|endoftext|>


<commit_before>from .fmodobject import *
from .fmodobject import _dll
from .structures import TAG
from .globalvars import get_class

class ConeSettings(object):
    def __init__(self, sptr):
        self._sptr = sptr
        self._in = c_float()
        self._out = c_float()
        self._outvol = c_float()
        ckresult(_dll.FMOD_Sound_Get3DConeSettings(self._sptr, byref(self._in), byref(self._out), byref(self._outvol)))

    @property
    def inside_angle(self):
        return self._in.value
    @inside_angle.setter
    def inside_angle(self, angle):
        self._in = c_float(angle)
        self._commit()

    @property
    def outside_angle(self):
        return self._out.value
    @outside_angle.setter
    def outside_angle(self, angle):
        self._out = c_float(angle)
        self._commit()

    @property
    def outside_volume(self):
        return self._outvol.value
    @outside_volume.setter
    def outside_volume(self, vol):
        self._outvol = c_float(vol)
        self._commit()

    def _commit(self):
        ckresult(_dll.FMOD_Sound_Set3DConeSettings(self._sptr, self._in, self._out, self._outvol))

class Sound(FmodObject):
    def add_sync_point(self, offset, offset_type, name):
        s_ptr = c_int()
        ckresult(_dll.FMOD_Sound_AddSyncPoint(self._ptr, offset, offset_type, name, byref(s_ptr)))
        return s_ptr

    def delete_sync_point(self, point):
        ckresult(_dll.FMOD_Sound_DeleteSyncPoint(self._ptr, point))

    @property
    def threed_cone_settings(self):
        return ConeSettings(self._ptr)

    @property
    def _min_max_distance(self):
        min = c_float()
        max = c_float()
        ckresult(_dll.FMOD_Sound_Get3DMinMaxDistance(self._ptr, byref(min), byref(max)))
        return (min.value, max.value)
    @_min_max_distance.setter
    def _min_max_distance(self, dists):
        ckresult(_dll.FMOD_Sound_Set3DMinMaxDistance(self._ptr, c_float(dists[0]), c_float(dists[1])))

    @property
    def min_distance(self):
        return self._min_max_distance[0]
    @min_distance.setter
    def min_distance(self, dist):
        self._min_max_distance = (dist, self._min_max_distance[1])

    @property
    def max_distance(self):
        return self._min_max_distance[1]
    @max_distance.setter
    def max_distance(self, dist):
        self._min_max_distance = (self._min_max_distance[0], dist)

    @property
    def _defaults(self):
        freq = c_float()
        vol = c_float()
        pan = c_float()
        pri = c_int()
        ckresult(_dll.FMOD_Sound_GetDefaults(self._ptr, byref(freq), byref(vol), byref(pan), byref(pri)))
        return [freq.value, vol.value, pan.value, pri.value]
    @_defaults.setter
    def _defaults(self, vals):
        ckresult(_dll.FMOD_Sound_SetDefaults(self._ptr, c_float(vals[0]), c_float(vals[1]), c_float(vals[2]), vals[3]))

    @property
    def default_frequency(self):
        return self._defaults[0]
    @default_frequency.setter
    def default_frequency(self, freq):
        d = self._defaults
        d[0] = freq
        self._defaults = d

    @property
    def default_volume(self):
        return self._defaults[1]
    @default_volume.setter
    def default_volume(self, vol):
        d = self._defaults
        d[1] = vol
        self._defaults = d

    @property
    def default_pan(self):
        return self._defaults[2]
    @default_pan.setter
    def default_pan(self, pan):
        d = self._defaults
        d[2] = pan
        self._defaults = d

    @property
    def default_priority(self):
        return self._defaults[3]
    @default_priority.setter
    def default_priority(self, pri):
        d = self._defaults
        d[3] = pri
        self._defaults = d

    @property
    def format(self):
        type = c_int()
        format = c_int()
        bits = c_int()
        ckresult(_dll.FMOD_Sound_GetFormat(self._ptr, byref(type), byref(format), byref(bits)))
        return so(type=type.value, format=format.value, bits=bits.value)

    def get_length(self, ltype):
        len = c_uint()
        ckresult(_dll.FMOD_Sound_GetLength(self._ptr, byref(len), ltype))
        return len.value

    @property
    def loop_count(self):
        c = c_int()
        ckresult(_dll.FMOD_Sound_GetLoopCount(self._ptr, byref(c)))
        return c.value
    @loop_count.setter
    def loop_count(self, count):
        ckresult(_dll.FMOD_Sound_SetLoopCount(self._ptr, count))

    @property
    def loop_points(self):
        """Returns tuple of two tuples ((start, startunit),(end, endunit))"""
        start = c_uint()
        startunit = c_int()
        end = c_uint()
        endunit = c_int()
        ckresult(_dll.FMOD_Sound_GetLoopPoints(self._ptr, byref(start), byref(startunit), byref(end), byref(endunit)))
        return ((start.value, startunit.value), (end.value, endunit.value))
    @loop_points.setter
    def loop_points(self, p):
        """Same format as returned from this property is required to successfully call this setter."""
        ckresult(_dll.FMOD_Sound_SetLoopPoints(self._ptr, p[0][0], p[0][1], p[1][0], p[1][1]))

    @property
    def mode(self):
        mode = c_int()
        ckresult(_dll.FMOD_Sound_GetMode(self._ptr, byref(mode)))
        return mode.value
    @mode.setter
    def mode(self, m):
        ckresult(_dll.FMOD_Sound_SetMode(self._ptr, m))

    def get_music_channel_volume(self, channel):
        v = c_int()
        ckresult(_dll.FMOD_Sound_GetMusiChannelVolume(self._ptr, channel, byref(v)))
        return v.value
    def set_music_channel_volume(self, id, vol):
        ckresult(_dll.FMOD_Sound_SetMusiChannelVolume(self._ptr, id, c_float(vol)))

    @property
    def num_music_channels(self):
        num = c_int()
        ckresult(_dll.FMOD_Sound_GetMusicNumChannels(self._ptr, byref(num)))
        return num.value

    @property
    def name(self):
        name = create_string_buffer(256)
        ckresult(_dll.FMOD_Sound_GetName(self._ptr, byref(name), 256))
        return name.value

    @property
    def num_subsounds(self):
        num = c_int()
        ckresult(_dll.FMOD_Sound_GetNumSubSounds(self._ptr, byref(num)))
        return num.value

    @property
    def num_sync_points(self):
        num = c_int()
        ckresult(_dll.FMOD_Sound_GetNumSyncPoints(self._ptr, byref(num)))
        return num.value

    @property
    def num_tags(self):
        num = c_int()
        ckresult(_dll.FMOD_Sound_GetNumTags(self._ptr, byref(num)))
        return num.value

    @property
    def open_state(self):
        state = c_int()
        percentbuffered = c_uint()
        starving = c_bool()
        diskbusy = c_bool()
        ckresult(_dll.FMOD_Sound_GetOpenState(self._ptr, byref(state), byref(percentbuffered), byref(starving), byref(diskbusy)))
        return so(state=state.value, percent_buffered=percentbuffered.value, starving=starving.value, disk_busy=diskbusy.value)

    @property
    def sound_group(self):
        grp_ptr = c_int()
        ckresult(_dll.FMOD_Sound_GetSoundGroup(self._ptr, byref(grp_ptr)))
        return get_class("SoundGroup")(grp_ptr)
    @sound_group.setter
    def sound_group(self, group):
        check_type(group, get_class("SoundGroup"))
        ckresult(_dll.FMOD_Sound_SetSoundGroup(self._ptr, group._ptr))

    def get_subsound(self, index):
        sh_ptr = c_int()
        ckresult(_dll.FMOD_Sound_GetSubSound(self._ptr, index, byref(sh_ptr)))
        return Sound(sh_ptr)

    def get_sync_point(self, index):
        sp = c_int()
        ckresult(_dll.FMOD_Sound_GetSyncPoint(self._ptr, index, byref(sp)))
        return sp.value

    def get_sync_point_info(self, point):
        name = c_char_p()
        offset = c_uint()
        offsettype = c_int()
        ckresult(_dll.FMOD_Sound_GetSyncPointInfo(self._ptr, point, byref(name), 256, byref(offset), byref(offsettype)))
        return so(name=name.value, offset=offset.value, offset_type=offsettype.value)

    @property
    def system_object(self):
        sptr = c_int()
        ckresult(_dll.FMOD_Sound_GetSystemObject(self._ptr, byref(sptr)))
        return get_class("System")(sptr, False)

    def play(self, paused=False):
        return self.system_object.play_sound(self, paused)

    def get_tag(self, index, name=None):
        tag = TAG()
        ckresult(_dll.FMOD_Sound_GetTag(self._ptr, name, index, byref(tag)))
        return tag

    @property
    def _variations(self):
        freq = c_float()
        vol = c_float()
        pan = c_float()
        ckresult(_dll.FMOD_Sound_GetVariations(self._ptr, byref(freq), byref(vol), byref(pan)))
        return [freq.value, vol.value, pan.value]
    @_variations.setter
    def _variations(self, vars):
        ckresult(_dll.FMOD_Sound_SetVariations(self._ptr, c_float(vars[0]), c_float(vars[1]), c_float(vars[2])))

    @property
    def frequency_variation(self):
        return self._variations[0]
    @frequency_variation.setter
    def frequency_variation(self, var):
        v = self._variations
        v[0] = var
        self._variations = var

    @property
    def volume_variation(self):
        return self._variations[1]
    @volume_variation.setter
    def volume_variation(self, var):
        v = self._variations
        v[1] = var
        self._variations = var

    @property
    def pan_variation(self):
        return self._variations[2]
    @pan_variation.setter
    def pan_variation(self, var):
        v = self._variations
        v[2] = var
        self._variations = var

    def lock(self, offset, length):
        ptr1 = c_void_p()
        len1 = c_uint()
        ptr2 = c_void_p()
        len2 = c_uint()
        ckresult(_dll.FMOD_Sound_Lock(self._ptr, offset, length, byref(ptr1), byref(ptr2), byref(len1), byref(len2)))
        return ((ptr1, len1), (ptr2, len2))

    def release(self):
        ckresult(_dll.FMOD_Sound_Release(self._ptr))

    def set_subsound(self, index, snd):
        check_type(snd, Sound)
        ckresult(_dll.FMOD_Sound_SetSubSound(self._ptr, index, snd._ptr))

    def set_subsound_sentence(self, sounds):
        a = c_int * len(sounds)
        ptrs = [o._ptr for o in sounds]
        ai = a(*ptrs)
        ckresult(_dll.FMOD_Sound_SetSubSoundSentence(self._ptr, ai, len(ai)))

    def unlock(self, i1, i2):
        """I1 and I2 are tuples of form (ptr, len)."""
        ckresult(_dll.FMOD_Sound_Unlock(self._ptr, i1[0], i2[0], i1[1], i2[1]))

    @property
    def music_speed(self):
        speed = c_float()
        self._call_fmod("FMOD_Sound_GetMusicSpeed", byref(speed))
        return speed.value
    @music_speed.setter
    def music_speed(self, speed):
        self._call_fmod("FMOD_Sound_SetMusicSpeed", c_float(speed))
<commit_msg>Fix return type of Sound.get_music_channel_volume. Closes #2.<commit_after>from .fmodobject import *
from .fmodobject import _dll
from .structures import TAG
from .globalvars import get_class

class ConeSettings(object):
    def __init__(self, sptr):
        self._sptr = sptr
        self._in = c_float()
        self._out = c_float()
        self._outvol = c_float()
        ckresult(_dll.FMOD_Sound_Get3DConeSettings(self._sptr, byref(self._in), byref(self._out), byref(self._outvol)))

    @property
    def inside_angle(self):
        return self._in.value
    @inside_angle.setter
    def inside_angle(self, angle):
        self._in = c_float(angle)
        self._commit()

    @property
    def outside_angle(self):
        return self._out.value
    @outside_angle.setter
    def outside_angle(self, angle):
        self._out = c_float(angle)
        self._commit()

    @property
    def outside_volume(self):
        return self._outvol.value
    @outside_volume.setter
    def outside_volume(self, vol):
        self._outvol = c_float(vol)
        self._commit()

    def _commit(self):
        ckresult(_dll.FMOD_Sound_Set3DConeSettings(self._sptr, self._in, self._out, self._outvol))

class Sound(FmodObject):
    def add_sync_point(self, offset, offset_type, name):
        s_ptr = c_int()
        ckresult(_dll.FMOD_Sound_AddSyncPoint(self._ptr, offset, offset_type, name, byref(s_ptr)))
        return s_ptr

    def delete_sync_point(self, point):
        ckresult(_dll.FMOD_Sound_DeleteSyncPoint(self._ptr, point))

    @property
    def threed_cone_settings(self):
        return ConeSettings(self._ptr)

    @property
    def _min_max_distance(self):
        min = c_float()
        max = c_float()
        ckresult(_dll.FMOD_Sound_Get3DMinMaxDistance(self._ptr, byref(min), byref(max)))
        return (min.value, max.value)
    @_min_max_distance.setter
    def _min_max_distance(self, dists):
        ckresult(_dll.FMOD_Sound_Set3DMinMaxDistance(self._ptr, c_float(dists[0]), c_float(dists[1])))

    @property
    def min_distance(self):
        return self._min_max_distance[0]
    @min_distance.setter
    def min_distance(self, dist):
        self._min_max_distance = (dist, self._min_max_distance[1])

    @property
    def max_distance(self):
        return self._min_max_distance[1]
    @max_distance.setter
    def max_distance(self, dist):
        self._min_max_distance = (self._min_max_distance[0], dist)

    @property
    def _defaults(self):
        freq = c_float()
        vol = c_float()
        pan = c_float()
        pri = c_int()
        ckresult(_dll.FMOD_Sound_GetDefaults(self._ptr, byref(freq), byref(vol), byref(pan), byref(pri)))
        return [freq.value, vol.value, pan.value, pri.value]
    @_defaults.setter
    def _defaults(self, vals):
        ckresult(_dll.FMOD_Sound_SetDefaults(self._ptr, c_float(vals[0]), c_float(vals[1]), c_float(vals[2]), vals[3]))

    @property
    def default_frequency(self):
        return self._defaults[0]
    @default_frequency.setter
    def default_frequency(self, freq):
        d = self._defaults
        d[0] = freq
        self._defaults = d

    @property
    def default_volume(self):
        return self._defaults[1]
    @default_volume.setter
    def default_volume(self, vol):
        d = self._defaults
        d[1] = vol
        self._defaults = d

    @property
    def default_pan(self):
        return self._defaults[2]
    @default_pan.setter
    def default_pan(self, pan):
        d = self._defaults
        d[2] = pan
        self._defaults = d

    @property
    def default_priority(self):
        return self._defaults[3]
    @default_priority.setter
    def default_priority(self, pri):
        d = self._defaults
        d[3] = pri
        self._defaults = d

    @property
    def format(self):
        type = c_int()
        format = c_int()
        bits = c_int()
        ckresult(_dll.FMOD_Sound_GetFormat(self._ptr, byref(type), byref(format), byref(bits)))
        return so(type=type.value, format=format.value, bits=bits.value)

    def get_length(self, ltype):
        len = c_uint()
        ckresult(_dll.FMOD_Sound_GetLength(self._ptr, byref(len), ltype))
        return len.value

    @property
    def loop_count(self):
        c = c_int()
        ckresult(_dll.FMOD_Sound_GetLoopCount(self._ptr, byref(c)))
        return c.value
    @loop_count.setter
    def loop_count(self, count):
        ckresult(_dll.FMOD_Sound_SetLoopCount(self._ptr, count))

    @property
    def loop_points(self):
        """Returns tuple of two tuples ((start, startunit),(end, endunit))"""
        start = c_uint()
        startunit = c_int()
        end = c_uint()
        endunit = c_int()
        ckresult(_dll.FMOD_Sound_GetLoopPoints(self._ptr, byref(start), byref(startunit), byref(end), byref(endunit)))
        return ((start.value, startunit.value), (end.value, endunit.value))
    @loop_points.setter
    def loop_points(self, p):
        """Same format as returned from this property is required to successfully call this setter."""
        ckresult(_dll.FMOD_Sound_SetLoopPoints(self._ptr, p[0][0], p[0][1], p[1][0], p[1][1]))

    @property
    def mode(self):
        mode = c_int()
        ckresult(_dll.FMOD_Sound_GetMode(self._ptr, byref(mode)))
        return mode.value
    @mode.setter
    def mode(self, m):
        ckresult(_dll.FMOD_Sound_SetMode(self._ptr, m))

    def get_music_channel_volume(self, channel):
        v = c_float()
        ckresult(_dll.FMOD_Sound_GetMusiChannelVolume(self._ptr, channel, byref(v)))
        return v.value
    def set_music_channel_volume(self, id, vol):
        ckresult(_dll.FMOD_Sound_SetMusiChannelVolume(self._ptr, id, c_float(vol)))

    @property
    def num_music_channels(self):
        num = c_int()
        ckresult(_dll.FMOD_Sound_GetMusicNumChannels(self._ptr, byref(num)))
        return num.value

    @property
    def name(self):
        name = create_string_buffer(256)
        ckresult(_dll.FMOD_Sound_GetName(self._ptr, byref(name), 256))
        return name.value

    @property
    def num_subsounds(self):
        num = c_int()
        ckresult(_dll.FMOD_Sound_GetNumSubSounds(self._ptr, byref(num)))
        return num.value

    @property
    def num_sync_points(self):
        num = c_int()
        ckresult(_dll.FMOD_Sound_GetNumSyncPoints(self._ptr, byref(num)))
        return num.value

    @property
    def num_tags(self):
        num = c_int()
        ckresult(_dll.FMOD_Sound_GetNumTags(self._ptr, byref(num)))
        return num.value

    @property
    def open_state(self):
        state = c_int()
        percentbuffered = c_uint()
        starving = c_bool()
        diskbusy = c_bool()
        ckresult(_dll.FMOD_Sound_GetOpenState(self._ptr, byref(state), byref(percentbuffered), byref(starving), byref(diskbusy)))
        return so(state=state.value, percent_buffered=percentbuffered.value, starving=starving.value, disk_busy=diskbusy.value)

    @property
    def sound_group(self):
        grp_ptr = c_int()
        ckresult(_dll.FMOD_Sound_GetSoundGroup(self._ptr, byref(grp_ptr)))
        return get_class("SoundGroup")(grp_ptr)
    @sound_group.setter
    def sound_group(self, group):
        check_type(group, get_class("SoundGroup"))
        ckresult(_dll.FMOD_Sound_SetSoundGroup(self._ptr, group._ptr))

    def get_subsound(self, index):
        sh_ptr = c_int()
        ckresult(_dll.FMOD_Sound_GetSubSound(self._ptr, index, byref(sh_ptr)))
        return Sound(sh_ptr)

    def get_sync_point(self, index):
        sp = c_int()
        ckresult(_dll.FMOD_Sound_GetSyncPoint(self._ptr, index, byref(sp)))
        return sp.value

    def get_sync_point_info(self, point):
        name = c_char_p()
        offset = c_uint()
        offsettype = c_int()
        ckresult(_dll.FMOD_Sound_GetSyncPointInfo(self._ptr, point, byref(name), 256, byref(offset), byref(offsettype)))
        return so(name=name.value, offset=offset.value, offset_type=offsettype.value)

    @property
    def system_object(self):
        sptr = c_int()
        ckresult(_dll.FMOD_Sound_GetSystemObject(self._ptr, byref(sptr)))
        return get_class("System")(sptr, False)

    def play(self, paused=False):
        return self.system_object.play_sound(self, paused)

    def get_tag(self, index, name=None):
        tag = TAG()
        ckresult(_dll.FMOD_Sound_GetTag(self._ptr, name, index, byref(tag)))
        return tag

    @property
    def _variations(self):
        freq = c_float()
        vol = c_float()
        pan = c_float()
        ckresult(_dll.FMOD_Sound_GetVariations(self._ptr, byref(freq), byref(vol), byref(pan)))
        return [freq.value, vol.value, pan.value]
    @_variations.setter
    def _variations(self, vars):
        ckresult(_dll.FMOD_Sound_SetVariations(self._ptr, c_float(vars[0]), c_float(vars[1]), c_float(vars[2])))

    @property
    def frequency_variation(self):
        return self._variations[0]
    @frequency_variation.setter
    def frequency_variation(self, var):
        v = self._variations
        v[0] = var
        self._variations = var

    @property
    def volume_variation(self):
        return self._variations[1]
    @volume_variation.setter
    def volume_variation(self, var):
        v = self._variations
        v[1] = var
        self._variations = var

    @property
    def pan_variation(self):
        return self._variations[2]
    @pan_variation.setter
    def pan_variation(self, var):
        v = self._variations
        v[2] = var
        self._variations = var

    def lock(self, offset, length):
        ptr1 = c_void_p()
        len1 = c_uint()
        ptr2 = c_void_p()
        len2 = c_uint()
        ckresult(_dll.FMOD_Sound_Lock(self._ptr, offset, length, byref(ptr1), byref(ptr2), byref(len1), byref(len2)))
        return ((ptr1, len1), (ptr2, len2))

    def release(self):
        ckresult(_dll.FMOD_Sound_Release(self._ptr))

    def set_subsound(self, index, snd):
        check_type(snd, Sound)
        ckresult(_dll.FMOD_Sound_SetSubSound(self._ptr, index, snd._ptr))

    def set_subsound_sentence(self, sounds):
        a = c_int * len(sounds)
        ptrs = [o._ptr for o in sounds]
        ai = a(*ptrs)
        ckresult(_dll.FMOD_Sound_SetSubSoundSentence(self._ptr, ai, len(ai)))

    def unlock(self, i1, i2):
        """I1 and I2 are tuples of form (ptr, len)."""
        ckresult(_dll.FMOD_Sound_Unlock(self._ptr, i1[0], i2[0], i1[1], i2[1]))

    @property
    def music_speed(self):
        speed = c_float()
        self._call_fmod("FMOD_Sound_GetMusicSpeed", byref(speed))
        return speed.value
    @music_speed.setter
    def music_speed(self, speed):
        self._call_fmod("FMOD_Sound_SetMusicSpeed", c_float(speed))
<|endoftext|>


<commit_before>from django.apps import AppConfig
import rpfti.shared_config
import importlib
mainbot = None

# Check if bot is launched under uwsgi
has_uwsgi = False
if importlib.util.find_spec("uwsgi") is not None:
    import uwsgi
    has_uwsgi = True

def get_bot():
    global mainbot
    return mainbot

class RpftiConfig(AppConfig):
    name = 'rpfti'

    def ready(self):
        from rpfti.rpfti_telegram.core import BotCore
        from rpfti.rpfti_telegram.core_addon import core_addon
        from rpfti.rpfti_telegram.whoami import noporn_addon
        from rpfti.rpfti_telegram.stats import stats_addon
        from rpfti.rpfti_telegram.rss import rss_addon
        from rpfti.models import Bot, TelegramUser, TelegramChat
        from rpfti.models import Message, Like, ScheduledTask

        global mainbot
        shared_config = rpfti.shared_config
        main_models = {}
        main_models["Bots"] = Bot
        main_models["Chats"] = TelegramChat
        main_models["Users"] = TelegramUser
        main_models["Messages"] = Message
        main_models["Likes"] = Like
        main_models["Tasks"] = ScheduledTask

        settings = {}
        settings["url"] = shared_config.WEBHOOK_URL_BASE + \
            shared_config.WEBHOOK_URL_PATH
        settings["cert"] = shared_config.WEBHOOK_SSL_CERT
        settings["token"] = shared_config.TOKEN_NOPORN
        settings["name"] = "RemoveThatPicBot"
        settings["description"] = "Porn remover bot"

        roles = {}
        roles["o_range"] = "ADMIN"

        mainbot = BotCore(main_models, settings, roles)
        mainbot.insert_addon(core_addon)
        mainbot.insert_addon(noporn_addon)
        mainbot.insert_addon(stats_addon)
        mainbot.insert_addon(rss_addon)
        mainbot.bind()
        mainbot.declare()

        def check_tasks(signum):
            mainbot.check_tasks()

        if has_uwsgi:
            uwsgi.register_signal(99, "", check_tasks)
            uwsgi.add_timer(99, 10)

        for k, v in roles.items():
            if v == "ADMIN":
                db_chat = mainbot.models["Chats"].objects.get(
                    bot__name=mainbot.name, user_name=k)
                mainbot.send_message(db_chat, "Бот перезапущен")

        ctrl_settings = {}
        ctrl_settings["url"] = shared_config.WEBHOOK_URL_BASE + \
            shared_config.WEBHOOK_URL_PATH_CONTROL
        ctrl_settings["cert"] = shared_config.WEBHOOK_SSL_CERT
        ctrl_settings["token"] = shared_config.TOKEN_TEST
        ctrl_settings["name"] = "Control_Bot"
        ctrl_settings["description"] = "Control bot"

        # controlbot = BotCore(main_models, ctrl_settings, roles)
        # controlbot.insert_addon(core_addon)
        # controlbot.bind()

        print("READY!")
<commit_msg>At last fixed UWSGI search bug<commit_after>from django.apps import AppConfig
import rpfti.shared_config
mainbot = None

# Check if bot is launched under uwsgi
has_uwsgi = False
try:
    import uwsgi
    has_uwsgi = True
except:
    print("WARNING! No UWSGI found")

def get_bot():
    global mainbot
    return mainbot

class RpftiConfig(AppConfig):
    name = 'rpfti'

    def ready(self):
        from rpfti.rpfti_telegram.core import BotCore
        from rpfti.rpfti_telegram.core_addon import core_addon
        from rpfti.rpfti_telegram.whoami import noporn_addon
        from rpfti.rpfti_telegram.stats import stats_addon
        from rpfti.rpfti_telegram.rss import rss_addon
        from rpfti.models import Bot, TelegramUser, TelegramChat
        from rpfti.models import Message, Like, ScheduledTask

        global mainbot
        shared_config = rpfti.shared_config
        main_models = {}
        main_models["Bots"] = Bot
        main_models["Chats"] = TelegramChat
        main_models["Users"] = TelegramUser
        main_models["Messages"] = Message
        main_models["Likes"] = Like
        main_models["Tasks"] = ScheduledTask

        settings = {}
        settings["url"] = shared_config.WEBHOOK_URL_BASE + \
            shared_config.WEBHOOK_URL_PATH
        settings["cert"] = shared_config.WEBHOOK_SSL_CERT
        settings["token"] = shared_config.TOKEN_NOPORN
        settings["name"] = "RemoveThatPicBot"
        settings["description"] = "Porn remover bot"

        roles = {}
        roles["o_range"] = "ADMIN"

        mainbot = BotCore(main_models, settings, roles)
        mainbot.insert_addon(core_addon)
        mainbot.insert_addon(noporn_addon)
        mainbot.insert_addon(stats_addon)
        mainbot.insert_addon(rss_addon)
        mainbot.bind()
        mainbot.declare()

        def check_tasks(signum):
            mainbot.check_tasks()

        if has_uwsgi:
            uwsgi.register_signal(99, "", check_tasks)
            uwsgi.add_timer(99, 10)

        for k, v in roles.items():
            if v == "ADMIN":
                db_chat = mainbot.models["Chats"].objects.get(
                    bot__name=mainbot.name, user_name=k)
                mainbot.send_message(db_chat, "Бот перезапущен")

        ctrl_settings = {}
        ctrl_settings["url"] = shared_config.WEBHOOK_URL_BASE + \
            shared_config.WEBHOOK_URL_PATH_CONTROL
        ctrl_settings["cert"] = shared_config.WEBHOOK_SSL_CERT
        ctrl_settings["token"] = shared_config.TOKEN_TEST
        ctrl_settings["name"] = "Control_Bot"
        ctrl_settings["description"] = "Control bot"

        # controlbot = BotCore(main_models, ctrl_settings, roles)
        # controlbot.insert_addon(core_addon)
        # controlbot.bind()

        print("READY!")
<|endoftext|>