def tempo(self, factor, audio_type=None, quick=False):
        '''Time stretch audio without changing pitch.

        This effect uses the WSOLA algorithm. The audio is chopped up into
        segments which are then shifted in the time domain and overlapped
        (cross-faded) at points where their waveforms are most similar as
        determined by measurement of least squares.

        Parameters
        ----------
        factor : float
            The ratio of new tempo to the old tempo.
            For ex. 1.1 speeds up the tempo by 10%; 0.9 slows it down by 10%.
        audio_type : str
            Type of audio, which optimizes algorithm parameters. One of:
             * m : Music,
             * s : Speech,
             * l : Linear (useful when factor is close to 1),
        quick : bool, default=False
            If True, this effect will run faster but with lower sound quality.

        See Also
        --------
        stretch, speed, pitch

        '''
        if not is_number(factor) or factor <= 0:
            raise ValueError("factor must be a positive number")

        if factor < 0.5 or factor > 2:
            logger.warning(
                "Using an extreme time stretching factor. "
                "Quality of results will be poor"
            )

        if abs(factor - 1.0) <= 0.1:
            logger.warning(
                "For this stretch factor, "
                "the stretch effect has better performance."
            )

        if audio_type not in [None, 'm', 's', 'l']:
            raise ValueError(
                "audio_type must be one of None, 'm', 's', or 'l'."
            )

        if not isinstance(quick, bool):
            raise ValueError("quick must be a boolean.")

        effect_args = ['tempo']

        if quick:
            effect_args.append('-q')

        if audio_type is not None:
            effect_args.append('-{}'.format(audio_type))

        effect_args.append('{:f}'.format(factor))

        self.effects.extend(effect_args)
        self.effects_log.append('tempo')

        return self

Time stretch audio without changing pitch .


def trim(self, start_time, end_time=None):
        '''Excerpt a clip from an audio file, given the start timestamp and end timestamp of the clip within the file, expressed in seconds. If the end timestamp is set to `None` or left unspecified, it defaults to the duration of the audio file.

        Parameters
        ----------
        start_time : float
            Start time of the clip (seconds)
        end_time : float or None, default=None
            End time of the clip (seconds)

        '''
        if not is_number(start_time) or start_time < 0:
            raise ValueError("start_time must be a positive number.")

        effect_args = [
            'trim',
            '{:f}'.format(start_time)
        ]

        if end_time is not None:
            if not is_number(end_time) or end_time < 0:
                raise ValueError("end_time must be a positive number.")
            if start_time >= end_time:
                raise ValueError("start_time must be smaller than end_time.")

            effect_args.append('{:f}'.format(end_time - start_time))

        self.effects.extend(effect_args)
        self.effects_log.append('trim')

        return self

Excerpt a clip from an audio file given the start timestamp and end timestamp of the clip within the file expressed in seconds . If the end timestamp is set to None or left unspecified it defaults to the duration of the audio file .


def vad(self, location=1, normalize=True, activity_threshold=7.0,
            min_activity_duration=0.25, initial_search_buffer=1.0,
            max_gap=0.25, initial_pad=0.0):
        '''Voice Activity Detector. Attempts to trim silence and quiet
        background sounds from the ends of recordings of speech. The algorithm
        currently uses a simple cepstral power measurement to detect voice, so
        may be fooled by other things, especially music.

        The effect can trim only from the front of the audio, so in order to
        trim from the back, the reverse effect must also be used.

        Parameters
        ----------
        location : 1 or -1, default=1
            If 1, trims silence from the beginning
            If -1, trims silence from the end
        normalize : bool, default=True
            If true, normalizes audio before processing.
        activity_threshold : float, default=7.0
            The measurement level used to trigger activity detection. This may
            need to be cahnged depending on the noise level, signal level, and
            other characteristics of the input audio.
        min_activity_duration : float, default=0.25
            The time constant (in seconds) used to help ignore short bursts of
            sound.
        initial_search_buffer : float, default=1.0
            The amount of audio (in seconds) to search for quieter/shorter
            bursts of audio to include prior to the detected trigger point.
        max_gap : float, default=0.25
            The allowed gap (in seconds) between quiteter/shorter bursts of
            audio to include prior to the detected trigger point
        initial_pad : float, default=0.0
            The amount of audio (in seconds) to preserve before the trigger
            point and any found quieter/shorter bursts.

        See Also
        --------
        silence

        Examples
        --------
        >>> tfm = sox.Transformer()

        Remove silence from the beginning of speech

        >>> tfm.vad(initial_pad=0.3)

        Remove silence from the end of speech

        >>> tfm.vad(location=-1, initial_pad=0.2)

        '''
        if location not in [-1, 1]:
            raise ValueError("location must be -1 or 1.")
        if not isinstance(normalize, bool):
            raise ValueError("normalize muse be a boolean.")
        if not is_number(activity_threshold):
            raise ValueError("activity_threshold must be a number.")
        if not is_number(min_activity_duration) or min_activity_duration < 0:
            raise ValueError("min_activity_duration must be a positive number")
        if not is_number(initial_search_buffer) or initial_search_buffer < 0:
            raise ValueError("initial_search_buffer must be a positive number")
        if not is_number(max_gap) or max_gap < 0:
            raise ValueError("max_gap must be a positive number.")
        if not is_number(initial_pad) or initial_pad < 0:
            raise ValueError("initial_pad must be a positive number.")

        effect_args = []

        if normalize:
            effect_args.append('norm')

        if location == -1:
            effect_args.append('reverse')

        effect_args.extend([
            'vad',
            '-t', '{:f}'.format(activity_threshold),
            '-T', '{:f}'.format(min_activity_duration),
            '-s', '{:f}'.format(initial_search_buffer),
            '-g', '{:f}'.format(max_gap),
            '-p', '{:f}'.format(initial_pad)
        ])

        if location == -1:
            effect_args.append('reverse')

        self.effects.extend(effect_args)
        self.effects_log.append('vad')

        return self

Voice Activity Detector . Attempts to trim silence and quiet background sounds from the ends of recordings of speech . The algorithm currently uses a simple cepstral power measurement to detect voice so may be fooled by other things especially music .


def vol(self, gain, gain_type='amplitude', limiter_gain=None):
        '''Apply an amplification or an attenuation to the audio signal.

        Parameters
        ----------
        gain : float
            Interpreted according to the given `gain_type`.
            If `gain_type' = 'amplitude', `gain' is a positive amplitude ratio.
            If `gain_type' = 'power', `gain' is a power (voltage squared).
            If `gain_type' = 'db', `gain' is in decibels.
        gain_type : string, default='amplitude'
            Type of gain. One of:
                - 'amplitude'
                - 'power'
                - 'db'
        limiter_gain : float or None, default=None
            If specified, a limiter is invoked on peaks greater than
            `limiter_gain' to prevent clipping.
            `limiter_gain` should be a positive value much less than 1.

        See Also
        --------
        gain, compand

        '''
        if not is_number(gain):
            raise ValueError('gain must be a number.')
        if limiter_gain is not None:
            if (not is_number(limiter_gain) or
                    limiter_gain <= 0 or limiter_gain >= 1):
                raise ValueError(
                    'limiter gain must be a positive number less than 1'
                )
        if gain_type in ['amplitude', 'power'] and gain < 0:
            raise ValueError(
                "If gain_type = amplitude or power, gain must be positive."
            )

        effect_args = ['vol']

        effect_args.append('{:f}'.format(gain))

        if gain_type == 'amplitude':
            effect_args.append('amplitude')
        elif gain_type == 'power':
            effect_args.append('power')
        elif gain_type == 'db':
            effect_args.append('dB')
        else:
            raise ValueError('gain_type must be one of amplitude power or db')

        if limiter_gain is not None:
            if gain_type in ['amplitude', 'power'] and gain > 1:
                effect_args.append('{:f}'.format(limiter_gain))
            elif gain_type == 'db' and gain > 0:
                effect_args.append('{:f}'.format(limiter_gain))

        self.effects.extend(effect_args)
        self.effects_log.append('vol')

        return self

Apply an amplification or an attenuation to the audio signal .


def join(self, room):
        """Lets a user join a room on a specific Namespace."""
        self.socket.rooms.add(self._get_room_name(room))

def join ( self , room ) : self . socket . rooms . add ( self . _get_room_name ( room ) )

Lets a user join a room on a specific Namespace .


def leave(self, room):
        """Lets a user leave a room on a specific Namespace."""
        self.socket.rooms.remove(self._get_room_name(room))

def leave ( self , room ) : self . socket . rooms . remove ( self . _get_room_name ( room ) )

Lets a user leave a room on a specific Namespace .


def socketio_manage(environ, namespaces, request=None, error_handler=None,
                    json_loads=None, json_dumps=None):
    """Main SocketIO management function, call from within your Framework of
    choice's view.

    The ``environ`` variable is the WSGI ``environ``.  It is used to extract
    Socket object from the underlying server (as the 'socketio' key), and will
    be attached to both the ``Socket`` and ``Namespace`` objects.

    The ``namespaces`` parameter is a dictionary of the namespace string
    representation as key, and the BaseNamespace namespace class descendant as
    a value.  The empty string ('') namespace is the global namespace.  You can
    use Socket.GLOBAL_NS to be more explicit. So it would look like:

    .. code-block:: python

      namespaces={'': GlobalNamespace,
                  '/chat': ChatNamespace}

    The ``request`` object is not required, but will probably be useful to pass
    framework-specific things into your Socket and Namespace functions. It will
    simply be attached to the Socket and Namespace object (accessible through
    ``self.request`` in both cases), and it is not accessed in any case by the
    ``gevent-socketio`` library.

    Pass in an ``error_handler`` if you want to override the default
    error_handler (which is :func:`socketio.virtsocket.default_error_handler`.
    The callable you pass in should have the same signature as the default
    error handler.

    The ``json_loads`` and ``json_dumps`` are overrides for the default
    ``json.loads`` and ``json.dumps`` function calls.  Override these at
    the top-most level here.  This will affect all sockets created by this
    socketio manager, and all namespaces inside.

    This function will block the current "view" or "controller" in your
    framework to do the recv/send on the socket, and dispatch incoming messages
    to your namespaces.

    This is a simple example using Pyramid:

    .. code-block:: python

      def my_view(request):
          socketio_manage(request.environ, {'': GlobalNamespace}, request)

    NOTE: You must understand that this function is going to be called
    *only once* per socket opening, *even though* you are using a long
    polling mechanism.  The subsequent calls (for long polling) will
    be hooked directly at the server-level, to interact with the
    active ``Socket`` instance.  This means you will *not* get access
    to the future ``request`` or ``environ`` objects.  This is of
    particular importance regarding sessions (like Beaker).  The
    session will be opened once at the opening of the Socket, and not
    closed until the socket is closed.  You are responsible for
    opening and closing the cookie-based session yourself if you want
    to keep its data in sync with the rest of your GET/POST calls.
    """
    socket = environ['socketio']
    socket._set_environ(environ)
    socket._set_namespaces(namespaces)

    if request:
        socket._set_request(request)

    if error_handler:
        socket._set_error_handler(error_handler)

    if json_loads:
        socket._set_json_loads(json_loads)
    if json_dumps:
        socket._set_json_dumps(json_dumps)

    receiver_loop = socket._spawn_receiver_loop()

    gevent.joinall([receiver_loop])

    # TODO: double check, what happens to the WSGI request here ? it vanishes ?
    return

def socketio_manage ( environ , namespaces , request = None , error_handler = None , json_loads = None , json_dumps = None ) : socket = environ [ 'socketio' ] socket . _set_environ ( environ ) socket . _set_namespaces ( namespaces ) if request : socket . _set_request ( request ) if error_handler : socket . _set_error_handler ( error_handler ) if json_loads : socket . _set_json_loads ( json_loads ) if json_dumps : socket . _set_json_dumps ( json_dumps ) receiver_loop = socket . _spawn_receiver_loop ( ) gevent . joinall ( [ receiver_loop ] ) return

Main SocketIO management function call from within your Framework of choice s view .


def _save_ack_callback(self, msgid, callback):
        """Keep a reference of the callback on this socket."""
        if msgid in self.ack_callbacks:
            return False
        self.ack_callbacks[msgid] = callback

def _save_ack_callback ( self , msgid , callback ) : if msgid in self . ack_callbacks : return False self . ack_callbacks [ msgid ] = callback

Keep a reference of the callback on this socket .


def _pop_ack_callback(self, msgid):
        """Fetch the callback for a given msgid, if it exists, otherwise,
        return None"""
        if msgid not in self.ack_callbacks:
            return None
        return self.ack_callbacks.pop(msgid)

def _pop_ack_callback ( self , msgid ) : if msgid not in self . ack_callbacks : return None return self . ack_callbacks . pop ( msgid )

Fetch the callback for a given msgid if it exists otherwise return None


def get_multiple_client_msgs(self, **kwargs):
        """Get multiple messages, in case we're going through the various
        XHR-polling methods, on which we can pack more than one message if the
        rate is high, and encode the payload for the HTTP channel."""
        client_queue = self.client_queue
        msgs = [client_queue.get(**kwargs)]
        while client_queue.qsize():
            msgs.append(client_queue.get())
        return msgs

def get_multiple_client_msgs ( self , ** kwargs ) : client_queue = self . client_queue msgs = [ client_queue . get ( ** kwargs ) ] while client_queue . qsize ( ) : msgs . append ( client_queue . get ( ) ) return msgs

Get multiple messages in case we re going through the various XHR - polling methods on which we can pack more than one message if the rate is high and encode the payload for the HTTP channel .


def remove_namespace(self, namespace):
        """This removes a Namespace object from the socket.

        This is usually called by
        :meth:`~socketio.namespace.BaseNamespace.disconnect`.

        """
        if namespace in self.active_ns:
            del self.active_ns[namespace]

        if len(self.active_ns) == 0 and self.connected:
            self.kill(detach=True)

def remove_namespace ( self , namespace ) : if namespace in self . active_ns : del self . active_ns [ namespace ] if len ( self . active_ns ) == 0 and self . connected : self . kill ( detach = True )

This removes a Namespace object from the socket .


def send_packet(self, pkt):
        """Low-level interface to queue a packet on the wire (encoded as wire
        protocol"""
        self.put_client_msg(packet.encode(pkt, self.json_dumps))

def send_packet ( self , pkt ) : self . put_client_msg ( packet . encode ( pkt , self . json_dumps ) )

Low - level interface to queue a packet on the wire ( encoded as wire protocol


def spawn(self, fn, *args, **kwargs):
        """Spawn a new Greenlet, attached to this Socket instance.

        It will be monitored by the "watcher" method
        """

        log.debug("Spawning sub-Socket Greenlet: %s" % fn.__name__)
        job = gevent.spawn(fn, *args, **kwargs)
        self.jobs.append(job)
        return job

def
spawn
(
self
,
fn
,
*
args
,
**
kwargs
)
:
log
.
debug
(
"Spawning sub-Socket Greenlet: %s"
%
fn
.
__name__
)
job
=
gevent
.
spawn
(
fn
,
*
args
,
**
kwargs
)
self
.
jobs
.
append
(
job
)
return
job

Spawn a new Greenlet attached to this Socket instance .


def _receiver_loop(self):
        """This is the loop that takes messages from the queue for the server
        to consume, decodes them and dispatches them.

        It is the main loop for a socket.  We join on this process before
        returning control to the web framework.

        This process is not tracked by the socket itself, it is not going
        to be killed by the ``gevent.killall(socket.jobs)``, so it must
        exit gracefully itself.
        """

        while True:
            rawdata = self.get_server_msg()

            if not rawdata:
                continue  # or close the connection ?
            try:
                pkt = packet.decode(rawdata, self.json_loads)
            except (ValueError, KeyError, Exception) as e:
                self.error('invalid_packet',
                    "There was a decoding error when dealing with packet "
                    "with event: %s... (%s)" % (rawdata[:20], e))
                continue

            if pkt['type'] == 'heartbeat':
                # This is already dealth with in put_server_msg() when
                # any incoming raw data arrives.
                continue

            if pkt['type'] == 'disconnect' and pkt['endpoint'] == '':
                # On global namespace, we kill everything.
                self.kill(detach=True)
                continue

            endpoint = pkt['endpoint']

            if endpoint not in self.namespaces:
                self.error("no_such_namespace",
                    "The endpoint you tried to connect to "
                    "doesn't exist: %s" % endpoint, endpoint=endpoint)
                continue
            elif endpoint in self.active_ns:
                pkt_ns = self.active_ns[endpoint]
            else:
                new_ns_class = self.namespaces[endpoint]
                pkt_ns = new_ns_class(self.environ, endpoint,
                                        request=self.request)
                # This calls initialize() on all the classes and mixins, etc..
                # in the order of the MRO
                for cls in type(pkt_ns).__mro__:
                    if hasattr(cls, 'initialize'):
                        cls.initialize(pkt_ns)  # use this instead of __init__,
                                                # for less confusion

                self.active_ns[endpoint] = pkt_ns

            retval = pkt_ns.process_packet(pkt)

            # Has the client requested an 'ack' with the reply parameters ?
            if pkt.get('ack') == "data" and pkt.get('id'):
                if type(retval) is tuple:
                    args = list(retval)
                else:
                    args = [retval]
                returning_ack = dict(type='ack', ackId=pkt['id'],
                                     args=args,
                                     endpoint=pkt.get('endpoint', ''))
                self.send_packet(returning_ack)

            # Now, are we still connected ?
            if not self.connected:
                self.kill(detach=True)  # ?? what,s the best clean-up
                                        # when its not a
                                        # user-initiated disconnect
                return

This is the loop that takes messages from the queue for the server to consume decodes them and dispatches them .


def _watcher(self):
        """Watch out if we've been disconnected, in that case, kill
        all the jobs.

        """
        while True:
            gevent.sleep(1.0)
            if not self.connected:
                for ns_name, ns in list(six.iteritems(self.active_ns)):
                    ns.recv_disconnect()
                # Killing Socket-level jobs
                gevent.killall(self.jobs)
                break

def _watcher ( self ) : while True : gevent . sleep ( 1.0 ) if not self . connected : for ns_name , ns in list ( six . iteritems ( self . active_ns ) ) : ns . recv_disconnect ( ) gevent . killall ( self . jobs ) break

Watch out if we ve been disconnected in that case kill all the jobs .


def _heartbeat(self):
        """Start the heartbeat Greenlet to check connection health."""
        interval = self.config['heartbeat_interval']
        while self.connected:
            gevent.sleep(interval)
            # TODO: this process could use a timeout object like the disconnect
            #       timeout thing, and ONLY send packets when none are sent!
            #       We would do that by calling timeout.set() for a "sending"
            #       timeout.  If we're sending 100 messages a second, there is
            #       no need to push some heartbeats in there also.
            self.put_client_msg("2::")

def _heartbeat ( self ) : interval = self . config [ 'heartbeat_interval' ] while self . connected : gevent . sleep ( interval ) self . put_client_msg ( "2::" )

Start the heartbeat Greenlet to check connection health .


def _spawn_heartbeat(self):
        """This functions returns a list of jobs"""
        self.spawn(self._heartbeat)
        self.spawn(self._heartbeat_timeout)

def _spawn_heartbeat ( self ) : self . spawn ( self . _heartbeat ) self . spawn ( self . _heartbeat_timeout )


def encode(data, json_dumps=default_json_dumps):
    """
    Encode an attribute dict into a byte string.
    """
    payload = ''
    msg = str(MSG_TYPES[data['type']])

    if msg in ['0', '1']:
        # '1::' [path] [query]
        msg += '::' + data['endpoint']
        if 'qs' in data and data['qs'] != '':
            msg += ':' + data['qs']

    elif msg == '2':
        # heartbeat
        msg += '::'

    elif msg in ['3', '4', '5']:
        # '3:' [id ('+')] ':' [endpoint] ':' [data]
        # '4:' [id ('+')] ':' [endpoint] ':' [json]
        # '5:' [id ('+')] ':' [endpoint] ':' [json encoded event]
        # The message id is an incremental integer, required for ACKs.
        # If the message id is followed by a +, the ACK is not handled by
        # socket.io, but by the user instead.
        if msg == '3':
            payload = data['data']
        if msg == '4':
            payload = json_dumps(data['data'])
        if msg == '5':
            d = {}
            d['name'] = data['name']
            if 'args' in data and data['args'] != []:
                d['args'] = data['args']
            payload = json_dumps(d)
        if 'id' in data:
            msg += ':' + str(data['id'])
            if data['ack'] == 'data':
                msg += '+'
            msg += ':'
        else:
            msg += '::'
        if 'endpoint' not in data:
            data['endpoint'] = ''
        if payload != '':
            msg += data['endpoint'] + ':' + payload
        else:
            msg += data['endpoint']

    elif msg == '6':
        # '6:::' [id] '+' [data]
        msg += '::' + data.get('endpoint', '') + ':' + str(data['ackId'])
        if 'args' in data and data['args'] != []:
            msg += '+' + json_dumps(data['args'])

    elif msg == '7':
        # '7::' [endpoint] ':' [reason] '+' [advice]
        msg += ':::'
        if 'reason' in data and data['reason'] != '':
            msg += str(ERROR_REASONS[data['reason']])
        if 'advice' in data and data['advice'] != '':
            msg += '+' + str(ERROR_ADVICES[data['advice']])
        msg += data['endpoint']

    # NoOp, used to close a poll after the polling duration time
    elif msg == '8':
        msg += '::'

    return msg

def encode ( data , json_dumps = default_json_dumps ) : payload = '' msg = str ( MSG_TYPES [ data [ 'type' ] ] ) if msg in [ '0' , '1' ] : msg += '::' + data [ 'endpoint' ] if 'qs' in data and data [ 'qs' ] != '' : msg += ':' + data [ 'qs' ] elif msg == '2' : msg += '::' elif msg in [ '3' , '4' , '5' ] : if msg == '3' : payload = data [ 'data' ] if msg == '4' : payload = json_dumps ( data [ 'data' ] ) if msg == '5' : d = { } d [ 'name' ] = data [ 'name' ] if 'args' in data and data [ 'args' ] != [ ] : d [ 'args' ] = data [ 'args' ] payload = json_dumps ( d ) if 'id' in data : msg += ':' + str ( data [ 'id' ] ) if data [ 'ack' ] == 'data' : msg += '+' msg += ':' else : msg += '::' if 'endpoint' not in data : data [ 'endpoint' ] = '' if payload != '' : msg += data [ 'endpoint' ] + ':' + payload else : msg += data [ 'endpoint' ] elif msg == '6' : msg += '::' + data . get ( 'endpoint' , '' ) + ':' + str ( data [ 'ackId' ] ) if 'args' in data and data [ 'args' ] != [ ] : msg += '+' + json_dumps ( data [ 'args' ] ) elif msg == '7' : msg += ':::' if 'reason' in data and data [ 'reason' ] != '' : msg += str ( ERROR_REASONS [ data [ 'reason' ] ] ) if 'advice' in data and data [ 'advice' ] != '' : msg += '+' + str ( ERROR_ADVICES [ data [ 'advice' ] ] ) msg += data [ 'endpoint' ] elif msg == '8' : msg += '::' return msg

Encode an attribute dict into a byte string .


def decode(rawstr, json_loads=default_json_loads):
    """
    Decode a rawstr packet arriving from the socket into a dict.
    """
    decoded_msg = {}
    try:
        # Handle decoding in Python<3.
        rawstr = rawstr.decode('utf-8')
    except AttributeError:
        pass
    split_data = rawstr.split(":", 3)
    msg_type = split_data[0]
    msg_id = split_data[1]
    endpoint = split_data[2]

    data = ''

    if msg_id != '':
        if "+" in msg_id:
            msg_id = msg_id.split('+')[0]
            decoded_msg['id'] = int(msg_id)
            decoded_msg['ack'] = 'data'
        else:
            decoded_msg['id'] = int(msg_id)
            decoded_msg['ack'] = True

    # common to every message
    msg_type_id = int(msg_type)
    if msg_type_id in MSG_VALUES:
        decoded_msg['type'] = MSG_VALUES[int(msg_type)]
    else:
        raise Exception("Unknown message type: %s" % msg_type)

    decoded_msg['endpoint'] = endpoint

    if len(split_data) > 3:
        data = split_data[3]

    if msg_type == "0":  # disconnect
        pass

    elif msg_type == "1":  # connect
        decoded_msg['qs'] = data

    elif msg_type == "2":  # heartbeat
        pass

    elif msg_type == "3":  # message
        decoded_msg['data'] = data

    elif msg_type == "4":  # json msg
        decoded_msg['data'] = json_loads(data)

    elif msg_type == "5":  # event
        try:
            data = json_loads(data)
        except ValueError:
            print("Invalid JSON event message", data)
            decoded_msg['args'] = []
        else:
            decoded_msg['name'] = data.pop('name')
            if 'args' in data:
                decoded_msg['args'] = data['args']
            else:
                decoded_msg['args'] = []

    elif msg_type == "6":  # ack
        if '+' in data:
            ackId, data = data.split('+')
            decoded_msg['ackId'] = int(ackId)
            decoded_msg['args'] = json_loads(data)
        else:
            decoded_msg['ackId'] = int(data)
            decoded_msg['args'] = []

    elif msg_type == "7":  # error
        if '+' in data:
            reason, advice = data.split('+')
            decoded_msg['reason'] = REASONS_VALUES[int(reason)]
            decoded_msg['advice'] = ADVICES_VALUES[int(advice)]
        else:
            decoded_msg['advice'] = ''
            if data != '':
                decoded_msg['reason'] = REASONS_VALUES[int(data)]
            else:
                decoded_msg['reason'] = ''

    elif msg_type == "8":  # noop
        pass

    return decoded_msg

def
decode
(
rawstr
,
json_loads
=
default_json_loads
)
:
decoded_msg
=
{
}
try
:
rawstr
=
rawstr
.
decode
(
'utf-8'
)
except
AttributeError
:
pass
split_data
=
rawstr
.
split
(
":"
,
3
)
msg_type
=
split_data
[
0
]
msg_id
=
split_data
[
1
]
endpoint
=
split_data
[
2
]
data
=
''
if
msg_id
!=
''
:
if
"+"
in
msg_id
:
msg_id
=
msg_id
.
split
(
'+'
)
[
0
]
decoded_msg
[
'id'
]
=
int
(
msg_id
)
decoded_msg
[
'ack'
]
=
'data'
else
:
decoded_msg
[
'id'
]
=
int
(
msg_id
)
decoded_msg
[
'ack'
]
=
True
msg_type_id
=
int
(
msg_type
)
if
msg_type_id
in
MSG_VALUES
:
decoded_msg
[
'type'
]
=
MSG_VALUES
[
int
(
msg_type
)
]
else
:
raise
Exception
(
"Unknown message type: %s"
%
msg_type
)
decoded_msg
[
'endpoint'
]
=
endpoint
if
len
(
split_data
)
>
3
:
data
=
split_data
[
3
]
if
msg_type
==
"0"
:
pass
elif
msg_type
==
"1"
:
decoded_msg
[
'qs'
]
=
data
elif
msg_type
==
"2"
:
pass
elif
msg_type
==
"3"
:
decoded_msg
[
'data'
]
=
data
elif
msg_type
==
"4"
:
decoded_msg
[
'data'
]
=
json_loads
(
data
)
elif
msg_type
==
"5"
:
try
:
data
=
json_loads
(
data
)
except
ValueError
:
print
(
"Invalid JSON event message"
,
data
)
decoded_msg
[
'args'
]
=
[
]
else
:
decoded_msg
[
'name'
]
=
data
.
pop
(
'name'
)
if
'args'
in
data
:
decoded_msg
[
'args'
]
=
data
[
'args'
]
else
:
decoded_msg
[
'args'
]
=
[
]
elif
msg_type
==
"6"
:
if
'+'
in
data
:
ackId
,
data
=
data
.
split
(
'+'
)
decoded_msg
[
'ackId'
]
=
int
(
ackId
)
decoded_msg
[
'args'
]
=
json_loads
(
data
)
else
:
decoded_msg
[
'ackId'
]
=
int
(
data
)
decoded_msg
[
'args'
]
=
[
]
elif
msg_type
==
"7"
:
if
'+'
in
data
:
reason
,
advice
=
data
.
split
(
'+'
)
decoded_msg
[
'reason'
]
=
REASONS_VALUES
[
int
(
reason
)
]
decoded_msg
[
'advice'
]
=
ADVICES_VALUES
[
int
(
advice
)
]
else
:
decoded_msg
[
'advice'
]
=
''
if
data
!=
''
:
decoded_msg
[
'reason'
]
=
REASONS_VALUES
[
int
(
data
)
]
else
:
decoded_msg
[
'reason'
]
=
''
elif
msg_type
==
"8"
:
pass
return
decoded_msg

Decode a rawstr packet arriving from the socket into a dict .


def process_event(self, packet):
        """This function dispatches ``event`` messages to the correct
        functions. You should override this method only if you are not
        satisfied with the automatic dispatching to
        ``on_``-prefixed methods.  You could then implement your own dispatch.
        See the source code for inspiration.

        There are two ways to deal with callbacks from the client side
        (meaning, the browser has a callback waiting for data that this
        server will be sending back):

        The first one is simply to return an object.  If the incoming
        packet requested has an 'ack' field set, meaning the browser is
        waiting for callback data, it will automatically be packaged
        and sent, associated with the 'ackId' from the browser. The
        return value must be a *sequence* of elements, that will be
        mapped to the positional parameters of the callback function
        on the browser side.

        If you want to *know* that you're dealing with a packet
        that requires a return value, you can do those things manually
        by inspecting the ``ack`` and ``id`` keys from the ``packet``
        object.  Your callback will behave specially if the name of
        the argument to your method is ``packet``.  It will fill it
        with the unprocessed ``packet`` object for your inspection,
        like this:

        .. code-block:: python

          def on_my_callback(self, packet):
              if 'ack' in packet:
                  self.emit('go_back', 'param1', id=packet['id'])
        """
        args = packet['args']
        name = packet['name']
        if not allowed_event_name_regex.match(name):
            self.error("unallowed_event_name",
                       "name must only contains alpha numerical characters")
            return

        method_name = 'on_' + name.replace(' ', '_')
        # This means the args, passed as a list, will be expanded to
        # the method arg and if you passed a dict, it will be a dict
        # as the first parameter.

        return self.call_method_with_acl(method_name, packet, *args)

This function dispatches event messages to the correct functions . You should override this method only if you are not satisfied with the automatic dispatching to on_ - prefixed methods . You could then implement your own dispatch . See the source code for inspiration .


def call_method_with_acl(self, method_name, packet, *args):
        """You should always use this function to call the methods,
        as it checks if the user is allowed according to the ACLs.

        If you override :meth:`process_packet` or
        :meth:`process_event`, you should definitely want to use this
        instead of ``getattr(self, 'my_method')()``
        """
        if not self.is_method_allowed(method_name):
            self.error('method_access_denied',
                       'You do not have access to method "%s"' % method_name)
            return

        return self.call_method(method_name, packet, *args)

def
call_method_with_acl
(
self
,
method_name
,
packet
,
*
args
)
:
if
not
self
.
is_method_allowed
(
method_name
)
:
self
.
error
(
'method_access_denied'
,
'You do not have access to method "%s"'
%
method_name
)
return
return
self
.
call_method
(
method_name
,
packet
,
*
args
)

You should always use this function to call the methods as it checks if the user is allowed according to the ACLs .


def error(self, error_name, error_message, msg_id=None, quiet=False):
        """Use this to use the configured ``error_handler`` yield an
        error message to your application.

        :param error_name: is a short string, to associate messages to recovery
                           methods
        :param error_message: is some human-readable text, describing the error
        :param msg_id: is used to associate with a request
        :param quiet: specific to error_handlers. The default doesn't send a
                      message to the user, but shows a debug message on the
                      developer console.
        """
        self.socket.error(error_name, error_message, endpoint=self.ns_name,
                          msg_id=msg_id, quiet=quiet)

def error ( self , error_name , error_message , msg_id = None , quiet = False ) : self . socket . error ( error_name , error_message , endpoint = self . ns_name , msg_id = msg_id , quiet = quiet )

Use this to use the configured error_handler yield an error message to your application .


def send(self, message, json=False, callback=None):
        """Use send to send a simple string message.

        If ``json`` is True, the message will be encoded as a JSON object
        on the wire, and decoded on the other side.

        This is mostly for backwards compatibility.  ``emit()`` is more fun.

        :param callback: This is a callback function that will be
                         called automatically by the client upon
                         reception.  It does not verify that the
                         listener over there was completed with
                         success.  It just tells you that the browser
                         got a hold of the packet.
        :type callback: callable
        """
        pkt = dict(type="message", data=message, endpoint=self.ns_name)
        if json:
            pkt['type'] = "json"

        if callback:
            # By passing ack=True, we use the old behavior of being returned
            # an 'ack' packet, automatically triggered by the client-side
            # with no user-code being run.  The emit() version of the
            # callback is more useful I think :)  So migrate your code.
            pkt['ack'] = True
            pkt['id'] = msgid = self.socket._get_next_msgid()
            self.socket._save_ack_callback(msgid, callback)

        self.socket.send_packet(pkt)

def send ( self , message , json = False , callback = None ) : pkt = dict ( type = "message" , data = message , endpoint = self . ns_name ) if json : pkt [ 'type' ] = "json" if callback : pkt [ 'ack' ] = True pkt [ 'id' ] = msgid = self . socket . _get_next_msgid ( ) self . socket . _save_ack_callback ( msgid , callback ) self . socket . send_packet ( pkt )

Use send to send a simple string message .


def emit(self, event, *args, **kwargs):
        """Use this to send a structured event, with a name and arguments, to
        the client.

        By default, it uses this namespace's endpoint. You can send messages on
        other endpoints with something like:

            ``self.socket['/other_endpoint'].emit()``.

        However, it is possible that the ``'/other_endpoint'`` was not
        initialized yet, and that would yield a ``KeyError``.

        The only supported ``kwargs`` is ``callback``.  All other parameters
        must be passed positionally.

        :param event: The name of the event to trigger on the other end.
        :param callback: Pass in the callback keyword argument to define a
                         call-back that will be called when the client acks.

                         This callback is slightly different from the one from
                         ``send()``, as this callback will receive parameters
                         from the explicit call of the ``ack()`` function
                         passed to the listener on the client side.

                         The remote listener will need to explicitly ack (by
                         calling its last argument, a function which is
                         usually called 'ack') with some parameters indicating
                         success or error.  The 'ack' packet coming back here
                         will then trigger the callback function with the
                         returned values.
        :type callback: callable
        """
        callback = kwargs.pop('callback', None)

        if kwargs:
            raise ValueError(
                "emit() only supports positional argument, to stay "
                "compatible with the Socket.IO protocol. You can "
                "however pass in a dictionary as the first argument")
        pkt = dict(type="event", name=event, args=args,
                   endpoint=self.ns_name)

        if callback:
            # By passing 'data', we indicate that we *want* an explicit ack
            # by the client code, not an automatic as with send().
            pkt['ack'] = 'data'
            pkt['id'] = msgid = self.socket._get_next_msgid()
            self.socket._save_ack_callback(msgid, callback)

        self.socket.send_packet(pkt)

Use this to send a structured event with a name and arguments to the client .


def spawn(self, fn, *args, **kwargs):
        """Spawn a new process, attached to this Namespace.

        It will be monitored by the "watcher" process in the Socket. If the
        socket disconnects, all these greenlets are going to be killed, after
        calling BaseNamespace.disconnect()

        This method uses the ``exception_handler_decorator``.  See
        Namespace documentation for more information.

        """
        # self.log.debug("Spawning sub-Namespace Greenlet: %s" % fn.__name__)
        if hasattr(self, 'exception_handler_decorator'):
            fn = self.exception_handler_decorator(fn)
        new = gevent.spawn(fn, *args, **kwargs)
        self.jobs.append(new)
        return new

def spawn ( self , fn , * args , ** kwargs ) : if hasattr ( self , 'exception_handler_decorator' ) : fn = self . exception_handler_decorator ( fn ) new = gevent . spawn ( fn , * args , ** kwargs ) self . jobs . append ( new ) return new

Spawn a new process attached to this Namespace .


def get_socket(self, sessid=''):
        """Return an existing or new client Socket."""

        socket = self.sockets.get(sessid)

        if sessid and not socket:
            return None  # you ask for a session that doesn't exist!
        if socket is None:
            socket = Socket(self, self.config)
            self.sockets[socket.sessid] = socket
        else:
            socket.incr_hits()

        return socket

def get_socket ( self , sessid = '' ) : socket = self . sockets . get ( sessid ) if sessid and not socket : return None if socket is None : socket = Socket ( self , self . config ) self . sockets [ socket . sessid ] = socket else : socket . incr_hits ( ) return socket

Return an existing or new client Socket .


def create():
    """
    Handles post from the "Add room" form on the homepage, and
    redirects to the new room.
    """
    name = request.form.get("name")
    if name:
        room, created = get_or_create(ChatRoom, name=name)
        return redirect(url_for('room', slug=room.slug))
    return redirect(url_for('rooms'))

def create ( ) : name = request . form . get ( "name" ) if name : room , created = get_or_create ( ChatRoom , name = name ) return redirect ( url_for ( 'room' , slug = room . slug ) ) return redirect ( url_for ( 'rooms' ) )

Handles post from the Add room form on the homepage and redirects to the new room .


def get_messages_payload(self, socket, timeout=None):
        """This will fetch the messages from the Socket's queue, and if
        there are many messes, pack multiple messages in one payload and return
        """
        try:
            msgs = socket.get_multiple_client_msgs(timeout=timeout)
            data = self.encode_payload(msgs)
        except Empty:
            data = ""
        return data

def get_messages_payload ( self , socket , timeout = None ) : try : msgs = socket . get_multiple_client_msgs ( timeout = timeout ) data = self . encode_payload ( msgs ) except Empty : data = "" return data

This will fetch the messages from the Socket s queue and if there are many messes pack multiple messages in one payload and return


def encode_payload(self, messages):
        """Encode list of messages. Expects messages to be unicode.

        ``messages`` - List of raw messages to encode, if necessary

        """
        if not messages or messages[0] is None:
            return ''

        if len(messages) == 1:
            return messages[0].encode('utf-8')

        payload = u''.join([(u'\ufffd%d\ufffd%s' % (len(p), p))
                            for p in messages if p is not None])
        # FIXME: why is it so that we must filter None from here ?  How
        #        is it even possible that a None gets in there ?

        return payload.encode('utf-8')

def encode_payload ( self , messages ) : if not messages or messages [ 0 ] is None : return '' if len ( messages ) == 1 : return messages [ 0 ] . encode ( 'utf-8' ) payload = u'' . join ( [ ( u'\ufffd%d\ufffd%s' % ( len ( p ) , p ) ) for p in messages if p is not None ] ) return payload . encode ( 'utf-8' )

Encode list of messages . Expects messages to be unicode .


def write(self, data):
        """Just quote out stuff before sending it out"""
        args = parse_qs(self.handler.environ.get("QUERY_STRING"))
        if "i" in args:
            i = args["i"]
        else:
            i = "0"
        # TODO: don't we need to quote this data in here ?
        super(JSONPolling, self).write("io.j[%s]('%s');" % (i, data))

def write ( self , data ) : args = parse_qs ( self . handler . environ . get ( "QUERY_STRING" ) ) if "i" in args : i = args [ "i" ] else : i = "0" super ( JSONPolling , self ) . write ( "io.j[%s]('%s');" % ( i , data ) )


def broadcast_event(self, event, *args):
        """
        This is sent to all in the sockets in this particular Namespace,
        including itself.
        """
        pkt = dict(type="event",
                   name=event,
                   args=args,
                   endpoint=self.ns_name)

        for sessid, socket in six.iteritems(self.socket.server.sockets):
            socket.send_packet(pkt)

def broadcast_event ( self , event , * args ) : pkt = dict ( type = "event" , name = event , args = args , endpoint = self . ns_name ) for sessid , socket in six . iteritems ( self . socket . server . sockets ) : socket . send_packet ( pkt )

This is sent to all in the sockets in this particular Namespace including itself .


def add_parent(self, parent):
        """Add a parent to this role,
        and add role itself to the parent's children set.
        you should override this function if neccessary.

        Example::

            logged_user = RoleMixin('logged_user')
            student = RoleMixin('student')
            student.add_parent(logged_user)

        :param parent: Parent role to add in.
        """
        parent.children.add(self)
        self.parents.add(parent)

def add_parent ( self , parent ) : parent . children . add ( self ) self . parents . add ( parent )

Add a parent to this role and add role itself to the parent s children set . you should override this function if neccessary .


def allow(self, role, method, resource, with_children=True):
        """Add allowing rules.

        :param role: Role of this rule.
        :param method: Method to allow in rule, include GET, POST, PUT etc.
        :param resource: Resource also view function.
        :param with_children: Allow role's children in rule as well
                              if with_children is `True`
        """
        if with_children:
            for r in role.get_children():
                permission = (r.get_name(), method, resource)
                if permission not in self._allowed:
                    self._allowed.append(permission)
        if role == 'anonymous':
            permission = (role, method, resource)
        else:
            permission = (role.get_name(), method, resource)
        if permission not in self._allowed:
            self._allowed.append(permission)

def allow ( self , role , method , resource , with_children = True ) : if with_children : for r in role . get_children ( ) : permission = ( r . get_name ( ) , method , resource ) if permission not in self . _allowed : self . _allowed . append ( permission ) if role == 'anonymous' : permission = ( role , method , resource ) else : permission = ( role . get_name ( ) , method , resource ) if permission not in self . _allowed : self . _allowed . append ( permission )


def deny(self, role, method, resource, with_children=False):
        """Add denying rules.

        :param role: Role of this rule.
        :param method: Method to deny in rule, include GET, POST, PUT etc.
        :param resource: Resource also view function.
        :param with_children: Deny role's children in rule as well
                              if with_children is `True`
        """
        if with_children:
            for r in role.get_children():
                permission = (r.get_name(), method, resource)
                if permission not in self._denied:
                    self._denied.append(permission)
        permission = (role.get_name(), method, resource)
        if permission not in self._denied:
            self._denied.append(permission)

def deny ( self , role , method , resource , with_children = False ) : if with_children : for r in role . get_children ( ) : permission = ( r . get_name ( ) , method , resource ) if permission not in self . _denied : self . _denied . append ( permission ) permission = ( role . get_name ( ) , method , resource ) if permission not in self . _denied : self . _denied . append ( permission )


def exempt(self, resource):
        """Exempt a view function from being checked permission

        :param resource: The view function exempt from checking.
        """
        if resource not in self._exempt:
            self._exempt.append(resource)

def exempt ( self , resource ) : if resource not in self . _exempt : self . _exempt . append ( resource )


def is_allowed(self, role, method, resource):
        """Check whether role is allowed to access resource

        :param role: Role to be checked.
        :param method: Method to be checked.
        :param resource: View function to be checked.
        """
        return (role, method, resource) in self._allowed

def is_allowed ( self , role , method , resource ) : return ( role , method , resource ) in self . _allowed


def is_denied(self, role, method, resource):
        """Check wherther role is denied to access resource

        :param role: Role to be checked.
        :param method: Method to be checked.
        :param resource: View function to be checked.
        """
        return (role, method, resource) in self._denied

def is_denied ( self , role , method , resource ) : return ( role , method , resource ) in self . _denied


def allow(self, roles, methods, with_children=True):
        """This is a decorator function.

        You can allow roles to access the view func with it.

        An example::

            @app.route('/website/setting', methods=['GET', 'POST'])
            @rbac.allow(['administrator', 'super_user'], ['GET', 'POST'])
            def website_setting():
                return Response('Setting page.')

        :param roles: List, each name of roles. Please note that,
                      `anonymous` is refered to anonymous.
                      If you add `anonymous` to the rule,
                      everyone can access the resource,
                      unless you deny other roles.
        :param methods: List, each name of methods.
                        methods is valid in ['GET', 'POST', 'PUT', 'DELETE']
        :param with_children: Whether allow children of roles as well.
                              True by default.
        """
        def decorator(view_func):
            _methods = [m.upper() for m in methods]
            for r, m, v in itertools.product(roles, _methods, [view_func.__name__]):
                self.before_acl['allow'].append((r, m, v, with_children))
            return view_func
        return decorator

def allow ( self , roles , methods , with_children = True ) : def decorator ( view_func ) : _methods = [ m . upper ( ) for m in methods ] for r , m , v in itertools . product ( roles , _methods , [ view_func . __name__ ] ) : self . before_acl [ 'allow' ] . append ( ( r , m , v , with_children ) ) return view_func return decorator


def remove_binaries():
    """Remove all binary files in the adslib directory."""
    patterns = (
        "adslib/*.a",
        "adslib/*.o",
        "adslib/obj/*.o",
        "adslib/*.bin",
        "adslib/*.so",
    )

    for f in functools.reduce(operator.iconcat, [glob.glob(p) for p in patterns]):
        os.remove(f)

def remove_binaries ( ) : patterns = ( "adslib/*.a" , "adslib/*.o" , "adslib/obj/*.o" , "adslib/*.bin" , "adslib/*.so" , ) for f in functools . reduce ( operator . iconcat , [ glob . glob ( p ) for p in patterns ] ) : os . remove ( f )

Remove all binary files in the adslib directory .


def router_function(fn):
    # type: (Callable) -> Callable
    """Raise a runtime error if on Win32 systems.

    Decorator.

    Decorator for functions that interact with the router for the Linux
    implementation of the ADS library.

    Unlike the Windows implementation which uses a separate router daemon,
    the Linux library manages AMS routing in-process. As such, routing must be
    configured programatically via. the provided API. These endpoints are
    invalid on Win32 systems, so an exception will be raised.

    """

    @wraps(fn)
    def wrapper(*args, **kwargs):
        # type: (Any, Any) -> Callable
        if platform_is_windows():  # pragma: no cover, skipt Windows test
            raise RuntimeError(
                "Router interface is not available on Win32 systems.\n"
                "Configure AMS routes using the TwinCAT router service."
            )
        return fn(*args, **kwargs)

    return wrapper

Raise a runtime error if on Win32 systems .


def adsAddRoute(net_id, ip_address):
    # type: (SAmsNetId, str) -> None
    """Establish a new route in the AMS Router.

    :param pyads.structs.SAmsNetId net_id: net id of routing endpoint
    :param str ip_address: ip address of the routing endpoint

    """
    add_route = _adsDLL.AdsAddRoute
    add_route.restype = ctypes.c_long

    # Convert ip address to bytes (PY3) and get pointer.
    ip_address_p = ctypes.c_char_p(ip_address.encode("utf-8"))

    error_code = add_route(net_id, ip_address_p)

    if error_code:
        raise ADSError(error_code)

def adsAddRoute ( net_id , ip_address ) : add_route = _adsDLL . AdsAddRoute add_route . restype = ctypes . c_long ip_address_p = ctypes . c_char_p ( ip_address . encode ( "utf-8" ) ) error_code = add_route ( net_id , ip_address_p ) if error_code : raise ADSError ( error_code )

Establish a new route in the AMS Router .


def adsPortCloseEx(port):
    # type: (int) -> None
    """Close the connection to the TwinCAT message router."""
    port_close_ex = _adsDLL.AdsPortCloseEx
    port_close_ex.restype = ctypes.c_long
    error_code = port_close_ex(port)

    if error_code:
        raise ADSError(error_code)

def adsPortCloseEx ( port ) : port_close_ex = _adsDLL . AdsPortCloseEx port_close_ex . restype = ctypes . c_long error_code = port_close_ex ( port ) if error_code : raise ADSError ( error_code )

Close the connection to the TwinCAT message router .


def adsGetLocalAddressEx(port):
    # type: (int) -> AmsAddr
    """Return the local AMS-address and the port number.

    :rtype: pyads.structs.AmsAddr
    :return: AMS-address

    """
    get_local_address_ex = _adsDLL.AdsGetLocalAddressEx
    ams_address_struct = SAmsAddr()
    error_code = get_local_address_ex(port, ctypes.pointer(ams_address_struct))

    if error_code:
        raise ADSError(error_code)

    local_ams_address = AmsAddr()
    local_ams_address._ams_addr = ams_address_struct

    return local_ams_address

def adsGetLocalAddressEx ( port ) : get_local_address_ex = _adsDLL . AdsGetLocalAddressEx ams_address_struct = SAmsAddr ( ) error_code = get_local_address_ex ( port , ctypes . pointer ( ams_address_struct ) ) if error_code : raise ADSError ( error_code ) local_ams_address = AmsAddr ( ) local_ams_address . _ams_addr = ams_address_struct return local_ams_address

Return the local AMS - address and the port number .


def adsSyncReadStateReqEx(port, address):
    # type: (int, AmsAddr) -> Tuple[int, int]
    """Read the current ADS-state and the machine-state.

    Read the current ADS-state and the machine-state from the
    ADS-server.

    :param pyads.structs.AmsAddr address: local or remote AmsAddr
    :rtype: (int, int)
    :return: ads_state, device_state

    """
    sync_read_state_request = _adsDLL.AdsSyncReadStateReqEx

    # C pointer to ams address struct
    ams_address_pointer = ctypes.pointer(address.amsAddrStruct())

    # Current ADS status and corresponding pointer
    ads_state = ctypes.c_int()
    ads_state_pointer = ctypes.pointer(ads_state)

    # Current device status and corresponding pointer
    device_state = ctypes.c_int()
    device_state_pointer = ctypes.pointer(device_state)

    error_code = sync_read_state_request(
        port, ams_address_pointer, ads_state_pointer, device_state_pointer
    )

    if error_code:
        raise ADSError(error_code)

    return (ads_state.value, device_state.value)

def adsSyncReadStateReqEx ( port , address ) : sync_read_state_request = _adsDLL . AdsSyncReadStateReqEx ams_address_pointer = ctypes . pointer ( address . amsAddrStruct ( ) ) ads_state = ctypes . c_int ( ) ads_state_pointer = ctypes . pointer ( ads_state ) device_state = ctypes . c_int ( ) device_state_pointer = ctypes . pointer ( device_state ) error_code = sync_read_state_request ( port , ams_address_pointer , ads_state_pointer , device_state_pointer ) if error_code : raise ADSError ( error_code ) return ( ads_state . value , device_state . value )

Read the current ADS - state and the machine - state .


def adsSyncReadDeviceInfoReqEx(port, address):
    # type: (int, AmsAddr) -> Tuple[str, AdsVersion]
    """Read the name and the version number of the ADS-server.

    :param int port: local AMS port as returned by adsPortOpenEx()
    :param pyads.structs.AmsAddr address: local or remote AmsAddr
    :rtype: string, AdsVersion
    :return: device name, version

    """
    sync_read_device_info_request = _adsDLL.AdsSyncReadDeviceInfoReqEx

    # Get pointer to the target AMS address
    ams_address_pointer = ctypes.pointer(address.amsAddrStruct())

    # Create buffer to be filled with device name, get pointer to said buffer
    device_name_buffer = ctypes.create_string_buffer(20)
    device_name_pointer = ctypes.pointer(device_name_buffer)

    # Create ADS Version struct and get pointer.
    ads_version = SAdsVersion()
    ads_version_pointer = ctypes.pointer(ads_version)

    error_code = sync_read_device_info_request(
        port, ams_address_pointer, device_name_pointer, ads_version_pointer
    )

    if error_code:
        raise ADSError(error_code)

    return (device_name_buffer.value.decode(), AdsVersion(ads_version))

def adsSyncReadDeviceInfoReqEx ( port , address ) : sync_read_device_info_request = _adsDLL . AdsSyncReadDeviceInfoReqEx ams_address_pointer = ctypes . pointer ( address . amsAddrStruct ( ) ) device_name_buffer = ctypes . create_string_buffer ( 20 ) device_name_pointer = ctypes . pointer ( device_name_buffer ) ads_version = SAdsVersion ( ) ads_version_pointer = ctypes . pointer ( ads_version ) error_code = sync_read_device_info_request ( port , ams_address_pointer , device_name_pointer , ads_version_pointer ) if error_code : raise ADSError ( error_code ) return ( device_name_buffer . value . decode ( ) , AdsVersion ( ads_version ) )

Read the name and the version number of the ADS - server .


def adsSyncWriteControlReqEx(
    port, address, ads_state, device_state, data, plc_data_type
):
    # type: (int, AmsAddr, int, int, Any, Type) -> None
    """Change the ADS state and the machine-state of the ADS-server.

    :param int port: local AMS port as returned by adsPortOpenEx()
    :param pyads.structs.AmsAddr adr: local or remote AmsAddr
    :param int ads_state: new ADS-state, according to ADSTATE constants
    :param int device_state: new machine-state
    :param data: additional data
    :param int plc_data_type: plc datatype, according to PLCTYPE constants

    """
    sync_write_control_request = _adsDLL.AdsSyncWriteControlReqEx

    ams_address_pointer = ctypes.pointer(address.amsAddrStruct())
    ads_state_c = ctypes.c_ulong(ads_state)
    device_state_c = ctypes.c_ulong(device_state)

    if plc_data_type == PLCTYPE_STRING:
        data = ctypes.c_char_p(data.encode("utf-8"))
        data_pointer = data
        data_length = len(data_pointer.value) + 1
    else:
        data = plc_data_type(data)
        data_pointer = ctypes.pointer(data)
        data_length = ctypes.sizeof(data)

    error_code = sync_write_control_request(
        port,
        ams_address_pointer,
        ads_state_c,
        device_state_c,
        data_length,
        data_pointer,
    )

    if error_code:
        raise ADSError(error_code)

def adsSyncWriteControlReqEx ( port , address , ads_state , device_state , data , plc_data_type ) : sync_write_control_request = _adsDLL . AdsSyncWriteControlReqEx ams_address_pointer = ctypes . pointer ( address . amsAddrStruct ( ) ) ads_state_c = ctypes . c_ulong ( ads_state ) device_state_c = ctypes . c_ulong ( device_state ) if plc_data_type == PLCTYPE_STRING : data = ctypes . c_char_p ( data . encode ( "utf-8" ) ) data_pointer = data data_length = len ( data_pointer . value ) + 1 else : data = plc_data_type ( data ) data_pointer = ctypes . pointer ( data ) data_length = ctypes . sizeof ( data ) error_code = sync_write_control_request ( port , ams_address_pointer , ads_state_c , device_state_c , data_length , data_pointer , ) if error_code : raise ADSError ( error_code )

Change the ADS state and the machine - state of the ADS - server .


def adsSyncWriteReqEx(port, address, index_group, index_offset, value, plc_data_type):
    # type: (int, AmsAddr, int, int, Any, Type) -> None
    """Send data synchronous to an ADS-device.

    :param int port: local AMS port as returned by adsPortOpenEx()
    :param pyads.structs.AmsAddr address: local or remote AmsAddr
    :param int indexGroup: PLC storage area, according to the INDEXGROUP
        constants
    :param int index_offset: PLC storage address
    :param value: value to write to the storage address of the PLC
    :param int plc_data_type: type of the data given to the PLC,
        according to PLCTYPE constants

    """
    sync_write_request = _adsDLL.AdsSyncWriteReqEx

    ams_address_pointer = ctypes.pointer(address.amsAddrStruct())
    index_group_c = ctypes.c_ulong(index_group)
    index_offset_c = ctypes.c_ulong(index_offset)

    if plc_data_type == PLCTYPE_STRING:
        data = ctypes.c_char_p(value.encode("utf-8"))
        data_pointer = data  # type: Union[ctypes.c_char_p, ctypes.pointer]
        data_length = len(data_pointer.value) + 1  # type: ignore

    else:
        if type(plc_data_type).__name__ == "PyCArrayType":
            data = plc_data_type(*value)
        else:
            data = plc_data_type(value)

        data_pointer = ctypes.pointer(data)
        data_length = ctypes.sizeof(data)

    error_code = sync_write_request(
        port,
        ams_address_pointer,
        index_group_c,
        index_offset_c,
        data_length,
        data_pointer,
    )

    if error_code:
        raise ADSError(error_code)

def adsSyncWriteReqEx ( port , address , index_group , index_offset , value , plc_data_type ) : sync_write_request = _adsDLL . AdsSyncWriteReqEx ams_address_pointer = ctypes . pointer ( address . amsAddrStruct ( ) ) index_group_c = ctypes . c_ulong ( index_group ) index_offset_c = ctypes . c_ulong ( index_offset ) if plc_data_type == PLCTYPE_STRING : data = ctypes . c_char_p ( value . encode ( "utf-8" ) ) data_pointer = data data_length = len ( data_pointer . value ) + 1 else : if type ( plc_data_type ) . __name__ == "PyCArrayType" : data = plc_data_type ( * value ) else : data = plc_data_type ( value ) data_pointer = ctypes . pointer ( data ) data_length = ctypes . sizeof ( data ) error_code = sync_write_request ( port , ams_address_pointer , index_group_c , index_offset_c , data_length , data_pointer , ) if error_code : raise ADSError ( error_code )

Send data synchronous to an ADS - device .


def adsSyncReadReqEx2(
    port, address, index_group, index_offset, data_type, return_ctypes=False
):
    # type: (int, AmsAddr, int, int, Type, bool) -> Any
    """Read data synchronous from an ADS-device.

    :param int port: local AMS port as returned by adsPortOpenEx()
    :param pyads.structs.AmsAddr address: local or remote AmsAddr
    :param int index_group: PLC storage area, according to the INDEXGROUP
        constants
    :param int index_offset: PLC storage address
    :param Type data_type: type of the data given to the PLC, according to
        PLCTYPE constants
    :param bool return_ctypes: return ctypes instead of python types if True
        (default: False)
    :rtype: data_type
    :return: value: **value**

    """
    sync_read_request = _adsDLL.AdsSyncReadReqEx2

    ams_address_pointer = ctypes.pointer(address.amsAddrStruct())
    index_group_c = ctypes.c_ulong(index_group)
    index_offset_c = ctypes.c_ulong(index_offset)

    if data_type == PLCTYPE_STRING:
        data = (STRING_BUFFER * PLCTYPE_STRING)()
    else:
        data = data_type()

    data_pointer = ctypes.pointer(data)
    data_length = ctypes.c_ulong(ctypes.sizeof(data))

    bytes_read = ctypes.c_ulong()
    bytes_read_pointer = ctypes.pointer(bytes_read)

    error_code = sync_read_request(
        port,
        ams_address_pointer,
        index_group_c,
        index_offset_c,
        data_length,
        data_pointer,
        bytes_read_pointer,
    )

    if error_code:
        raise ADSError(error_code)

    # If we're reading a value of predetermined size (anything but a string),
    # validate that the correct number of bytes were read
    if data_type != PLCTYPE_STRING and bytes_read.value != data_length.value:
        raise RuntimeError(
            "Insufficient data (expected {0} bytes, {1} were read).".format(
                data_length.value, bytes_read.value
            )
        )

    if return_ctypes:
        return data

    if data_type == PLCTYPE_STRING:
        return data.value.decode("utf-8")

    if type(data_type).__name__ == "PyCArrayType":
        return [i for i in data]

    if hasattr(data, "value"):
        return data.value

    return data

Read data synchronous from an ADS - device .


def adsSyncReadByNameEx(port, address, data_name, data_type, return_ctypes=False):
    # type: (int, AmsAddr, str, Type, bool) -> Any
    """Read data synchronous from an ADS-device from data name.

    :param int port: local AMS port as returned by adsPortOpenEx()
    :param pyads.structs.AmsAddr address: local or remote AmsAddr
    :param string data_name: data name
    :param Type data_type: type of the data given to the PLC, according to
        PLCTYPE constants
    :param bool return_ctypes: return ctypes instead of python types if True
        (default: False)
    :rtype: data_type
    :return: value: **value**

    """
    # Get the handle of the PLC-variable
    handle = adsSyncReadWriteReqEx2(
        port,
        address,
        ADSIGRP_SYM_HNDBYNAME,
        0x0,
        PLCTYPE_UDINT,
        data_name,
        PLCTYPE_STRING,
    )

    # Read the value of a PLC-variable, via handle
    value = adsSyncReadReqEx2(
        port, address, ADSIGRP_SYM_VALBYHND, handle, data_type, return_ctypes
    )

    # Release the handle of the PLC-variable
    adsSyncWriteReqEx(port, address, ADSIGRP_SYM_RELEASEHND, 0, handle, PLCTYPE_UDINT)

    return value

def adsSyncReadByNameEx ( port , address , data_name , data_type , return_ctypes = False ) : handle = adsSyncReadWriteReqEx2 ( port , address , ADSIGRP_SYM_HNDBYNAME , 0x0 , PLCTYPE_UDINT , data_name , PLCTYPE_STRING , ) value = adsSyncReadReqEx2 ( port , address , ADSIGRP_SYM_VALBYHND , handle , data_type , return_ctypes ) adsSyncWriteReqEx ( port , address , ADSIGRP_SYM_RELEASEHND , 0 , handle , PLCTYPE_UDINT ) return value

Read data synchronous from an ADS - device from data name .


def adsSyncWriteByNameEx(port, address, data_name, value, data_type):
    # type: (int, AmsAddr, str, Any, Type) -> None
    """Send data synchronous to an ADS-device from data name.

    :param int port: local AMS port as returned by adsPortOpenEx()
    :param pyads.structs.AmsAddr address: local or remote AmsAddr
    :param string data_name: PLC storage address
    :param value: value to write to the storage address of the PLC
    :param Type data_type: type of the data given to the PLC,
        according to PLCTYPE constants

    """
    # Get the handle of the PLC-variable
    handle = adsSyncReadWriteReqEx2(
        port,
        address,
        ADSIGRP_SYM_HNDBYNAME,
        0x0,
        PLCTYPE_UDINT,
        data_name,
        PLCTYPE_STRING,
    )

    # Write the value of a PLC-variable, via handle
    adsSyncWriteReqEx(port, address, ADSIGRP_SYM_VALBYHND, handle, value, data_type)

    # Release the handle of the PLC-variable
    adsSyncWriteReqEx(port, address, ADSIGRP_SYM_RELEASEHND, 0, handle, PLCTYPE_UDINT)

def adsSyncWriteByNameEx ( port , address , data_name , value , data_type ) : handle = adsSyncReadWriteReqEx2 ( port , address , ADSIGRP_SYM_HNDBYNAME , 0x0 , PLCTYPE_UDINT , data_name , PLCTYPE_STRING , ) adsSyncWriteReqEx ( port , address , ADSIGRP_SYM_VALBYHND , handle , value , data_type ) adsSyncWriteReqEx ( port , address , ADSIGRP_SYM_RELEASEHND , 0 , handle , PLCTYPE_UDINT )

Send data synchronous to an ADS - device from data name .


def adsSyncAddDeviceNotificationReqEx(
    port, adr, data_name, pNoteAttrib, callback, user_handle=None
):
    # type: (int, AmsAddr, str, NotificationAttrib, Callable, int) -> Tuple[int, int]
    """Add a device notification.

    :param int port: local AMS port as returned by adsPortOpenEx()
    :param pyads.structs.AmsAddr adr: local or remote AmsAddr
    :param string data_name: PLC storage address
    :param pyads.structs.NotificationAttrib pNoteAttrib: notification attributes
    :param callback: Callback function to handle notification
    :param user_handle: User Handle
    :rtype: (int, int)
    :returns: notification handle, user handle

    """
    global callback_store

    if NOTEFUNC is None:
        raise TypeError("Callback function type can't be None")

    adsSyncAddDeviceNotificationReqFct = _adsDLL.AdsSyncAddDeviceNotificationReqEx

    pAmsAddr = ctypes.pointer(adr.amsAddrStruct())
    hnl = adsSyncReadWriteReqEx2(
        port, adr, ADSIGRP_SYM_HNDBYNAME, 0x0, PLCTYPE_UDINT, data_name, PLCTYPE_STRING
    )

    nIndexGroup = ctypes.c_ulong(ADSIGRP_SYM_VALBYHND)
    nIndexOffset = ctypes.c_ulong(hnl)
    attrib = pNoteAttrib.notificationAttribStruct()
    pNotification = ctypes.c_ulong()

    nHUser = ctypes.c_ulong(hnl)
    if user_handle is not None:
        nHUser = ctypes.c_ulong(user_handle)

    adsSyncAddDeviceNotificationReqFct.argtypes = [
        ctypes.c_ulong,
        ctypes.POINTER(SAmsAddr),
        ctypes.c_ulong,
        ctypes.c_ulong,
        ctypes.POINTER(SAdsNotificationAttrib),
        NOTEFUNC,
        ctypes.c_ulong,
        ctypes.POINTER(ctypes.c_ulong),
    ]
    adsSyncAddDeviceNotificationReqFct.restype = ctypes.c_long

    def wrapper(addr, notification, user):
        # type: (AmsAddr, SAdsNotificationHeader, int) -> Callable[[SAdsNotificationHeader, str], None]
        return callback(notification, data_name)

    c_callback = NOTEFUNC(wrapper)
    err_code = adsSyncAddDeviceNotificationReqFct(
        port,
        pAmsAddr,
        nIndexGroup,
        nIndexOffset,
        ctypes.byref(attrib),
        c_callback,
        nHUser,
        ctypes.byref(pNotification),
    )

    if err_code:
        raise ADSError(err_code)
    callback_store[pNotification.value] = c_callback
    return (pNotification.value, hnl)

def
adsSyncAddDeviceNotificationReqEx
(
port
,
adr
,
data_name
,
pNoteAttrib
,
callback
,
user_handle
=
)
:
global
callback_store
if
NOTEFUNC
is
:
raise
TypeError
(
"Callback function type can't be None"
)
adsSyncAddDeviceNotificationReqFct
=
_adsDLL
.
AdsSyncAddDeviceNotificationReqEx
pAmsAddr
=
ctypes
.
pointer
(
adr
.
amsAddrStruct
(
)
)
hnl
=
adsSyncReadWriteReqEx2
(
port
,
adr
,
ADSIGRP_SYM_HNDBYNAME
,
0x0
,
PLCTYPE_UDINT
,
data_name
,
PLCTYPE_STRING
)
nIndexGroup
=
ctypes
.
c_ulong
(
ADSIGRP_SYM_VALBYHND
)
nIndexOffset
=
ctypes
.
c_ulong
(
hnl
)
attrib
=
pNoteAttrib
.
notificationAttribStruct
(
)
pNotification
=
ctypes
.
c_ulong
(
)
nHUser
=
ctypes
.
c_ulong
(
hnl
)
if
user_handle
is
not
:
nHUser
=
ctypes
.
c_ulong
(
user_handle
)
adsSyncAddDeviceNotificationReqFct
.
argtypes
=
[
ctypes
.
c_ulong
,
ctypes
.
POINTER
(
SAmsAddr
)
,
ctypes
.
c_ulong
,
ctypes
.
c_ulong
,
ctypes
.
POINTER
(
SAdsNotificationAttrib
)
,
NOTEFUNC
,
ctypes
.
c_ulong
,
ctypes
.
POINTER
(
ctypes
.
c_ulong
)
,
]
adsSyncAddDeviceNotificationReqFct
.
restype
=
ctypes
.
c_long
def
wrapper
(
addr
,
notification
,
user
)
:
return
callback
(
notification
,
data_name
)
c_callback
=
NOTEFUNC
(
wrapper
)
err_code
=
adsSyncAddDeviceNotificationReqFct
(
port
,
pAmsAddr
,
nIndexGroup
,
nIndexOffset
,
ctypes
.
byref
(
attrib
)
,
c_callback
,
nHUser
,
ctypes
.
byref
(
pNotification
)
,
)
if
err_code
:
raise
ADSError
(
err_code
)
callback_store
[
pNotification
.
value
]
=
c_callback
return
(
pNotification
.
value
,
hnl
)


def adsSyncDelDeviceNotificationReqEx(port, adr, notification_handle, user_handle):
    # type: (int, AmsAddr, int, int) -> None
    """Remove a device notification.

    :param int port: local AMS port as returned by adsPortOpenEx()
    :param pyads.structs.AmsAddr adr: local or remote AmsAddr
    :param int notification_handle: Notification Handle
    :param int user_handle: User Handle

    """
    adsSyncDelDeviceNotificationReqFct = _adsDLL.AdsSyncDelDeviceNotificationReqEx

    pAmsAddr = ctypes.pointer(adr.amsAddrStruct())
    nHNotification = ctypes.c_ulong(notification_handle)
    err_code = adsSyncDelDeviceNotificationReqFct(port, pAmsAddr, nHNotification)
    callback_store.pop(notification_handle, None)
    if err_code:
        raise ADSError(err_code)

    adsSyncWriteReqEx(port, adr, ADSIGRP_SYM_RELEASEHND, 0, user_handle, PLCTYPE_UDINT)

def adsSyncDelDeviceNotificationReqEx ( port , adr , notification_handle , user_handle ) : adsSyncDelDeviceNotificationReqFct = _adsDLL . AdsSyncDelDeviceNotificationReqEx pAmsAddr = ctypes . pointer ( adr . amsAddrStruct ( ) ) nHNotification = ctypes . c_ulong ( notification_handle ) err_code = adsSyncDelDeviceNotificationReqFct ( port , pAmsAddr , nHNotification ) callback_store . pop ( notification_handle , None ) if err_code : raise ADSError ( err_code ) adsSyncWriteReqEx ( port , adr , ADSIGRP_SYM_RELEASEHND , 0 , user_handle , PLCTYPE_UDINT )


def adsSyncSetTimeoutEx(port, nMs):
    # type: (int, int) -> None
    """Set Timeout.

    :param int port: local AMS port as returned by adsPortOpenEx()
    :param int nMs: timeout in ms

    """
    adsSyncSetTimeoutFct = _adsDLL.AdsSyncSetTimeoutEx
    cms = ctypes.c_long(nMs)
    err_code = adsSyncSetTimeoutFct(port, cms)
    if err_code:
        raise ADSError(err_code)

def adsSyncSetTimeoutEx ( port , nMs ) : adsSyncSetTimeoutFct = _adsDLL . AdsSyncSetTimeoutEx cms = ctypes . c_long ( nMs ) err_code = adsSyncSetTimeoutFct ( port , cms ) if err_code : raise ADSError ( err_code )


def _generate_ranges(start_date, end_date):
        """
        Generate a list of 2 month ranges for the range requested with an
        intersection between months. This is necessary because we can't search
        for ranges longer than 3 months and the period searched has to encompass
        the whole period of the mission.
        """
        range_start = start_date
        while range_start < end_date:
            range_end = range_start + timedelta(days=60)
            yield (
                range_start.strftime("%d/%m/%Y"),
                range_end.strftime("%d/%m/%Y")
            )
            range_start += timedelta(days=30)

def _generate_ranges ( start_date , end_date ) : range_start = start_date while range_start < end_date : range_end = range_start + timedelta ( days = 60 ) yield ( range_start . strftime ( "%d/%m/%Y" ) , range_end . strftime ( "%d/%m/%Y" ) ) range_start += timedelta ( days = 30 )

Generate a list of 2 month ranges for the range requested with an intersection between months . This is necessary because we can t search for ranges longer than 3 months and the period searched has to encompass the whole period of the mission .


def fetch(self):
        """
        Fetches the list of deputies for the current term.
        """
        xml = urllib.request.urlopen(self.URL)

        tree = ET.ElementTree(file=xml)
        records = self._parse_deputies(tree.getroot())

        df = pd.DataFrame(records, columns=(
            'congressperson_id',
            'budget_id',
            'condition',
            'congressperson_document',
            'civil_name',
            'congressperson_name',
            'picture_url',
            'gender',
            'state',
            'party',
            'phone_number',
            'email'
        ))
        return self._translate(df)

def fetch ( self ) : xml = urllib . request . urlopen ( self . URL ) tree = ET . ElementTree ( file = xml ) records = self . _parse_deputies ( tree . getroot ( ) ) df = pd . DataFrame ( records , columns = ( 'congressperson_id' , 'budget_id' , 'condition' , 'congressperson_document' , 'civil_name' , 'congressperson_name' , 'picture_url' , 'gender' , 'state' , 'party' , 'phone_number' , 'email' ) ) return self . _translate ( df )

Fetches the list of deputies for the current term .


def remove_node(self, node):
        """Removes `node` from the hash ring and its replicas.
        """
        self.nodes.remove(node)
        for x in xrange(self.replicas):
            ring_key = self.hash_method(b("%s:%d" % (node, x)))
            self.ring.pop(ring_key)
            self.sorted_keys.remove(ring_key)

def remove_node ( self , node ) : self . nodes . remove ( node ) for x in xrange ( self . replicas ) : ring_key = self . hash_method ( b ( "%s:%d" % ( node , x ) ) ) self . ring . pop ( ring_key ) self . sorted_keys . remove ( ring_key )

Removes node from the hash ring and its replicas .


def mget(self, keys, *args):
        """
        Returns a list of values ordered identically to ``keys``
        """
        args = list_or_args(keys, args)
        server_keys = {}
        ret_dict = {}
        for key in args:
            server_name = self.get_server_name(key)
            server_keys[server_name] = server_keys.get(server_name, [])
            server_keys[server_name].append(key)
        for server_name, sub_keys in iteritems(server_keys):
            values = self.connections[server_name].mget(sub_keys)
            ret_dict.update(dict(zip(sub_keys, values)))
        result = []
        for key in args:
            result.append(ret_dict.get(key, None))
        return result

def mget ( self , keys , * args ) : args = list_or_args ( keys , args ) server_keys = { } ret_dict = { } for key in args : server_name = self . get_server_name ( key ) server_keys [ server_name ] = server_keys . get ( server_name , [ ] ) server_keys [ server_name ] . append ( key ) for server_name , sub_keys in iteritems ( server_keys ) : values = self . connections [ server_name ] . mget ( sub_keys ) ret_dict . update ( dict ( zip ( sub_keys , values ) ) ) result = [ ] for key in args : result . append ( ret_dict . get ( key , None ) ) return result

Returns a list of values ordered identically to keys


def lock(self, name, timeout=None, sleep=0.1):
        """
        Return a new Lock object using key ``name`` that mimics
        the behavior of threading.Lock.

        If specified, ``timeout`` indicates a maximum life for the lock.
        By default, it will remain locked until release() is called.

        ``sleep`` indicates the amount of time to sleep per loop iteration
        when the lock is in blocking mode and another client is currently
        holding the lock.
        """
        return Lock(self, name, timeout=timeout, sleep=sleep)

def lock ( self , name , timeout = None , sleep = 0.1 ) : return Lock ( self , name , timeout = timeout , sleep = sleep )

Return a new Lock object using key name that mimics the behavior of threading . Lock .


def parse_line(line, document=None):
    '''
    Return a language-server diagnostic from a line of the Mypy error report;
    optionally, use the whole document to provide more context on it.
    '''
    result = re.match(line_pattern, line)
    if result:
        _, lineno, offset, severity, msg = result.groups()
        lineno = int(lineno or 1)
        offset = int(offset or 0)
        errno = 2
        if severity == 'error':
            errno = 1
        diag = {
            'source': 'mypy',
            'range': {
                'start': {'line': lineno - 1, 'character': offset},
                # There may be a better solution, but mypy does not provide end
                'end': {'line': lineno - 1, 'character': offset + 1}
            },
            'message': msg,
            'severity': errno
        }
        if document:
            # although mypy does not provide the end of the affected range, we
            # can make a good guess by highlighting the word that Mypy flagged
            word = document.word_at_position(diag['range']['start'])
            if word:
                diag['range']['end']['character'] = (
                    diag['range']['start']['character'] + len(word))

        return diag

def parse_line ( line , document = None ) : result = re . match ( line_pattern , line ) if result : _ , lineno , offset , severity , msg = result . groups ( ) lineno = int ( lineno or 1 ) offset = int ( offset or 0 ) errno = 2 if severity == 'error' : errno = 1 diag = { 'source' : 'mypy' , 'range' : { 'start' : { 'line' : lineno - 1 , 'character' : offset } , 'end' : { 'line' : lineno - 1 , 'character' : offset + 1 } } , 'message' : msg , 'severity' : errno } if document : word = document . word_at_position ( diag [ 'range' ] [ 'start' ] ) if word : diag [ 'range' ] [ 'end' ] [ 'character' ] = ( diag [ 'range' ] [ 'start' ] [ 'character' ] + len ( word ) ) return diag

Return a language - server diagnostic from a line of the Mypy error report ; optionally use the whole document to provide more context on it .


async def connect(self):
        """ Establishes a connection to the Lavalink server. """
        await self._lavalink.bot.wait_until_ready()

        if self._ws and self._ws.open:
            log.debug('WebSocket still open, closing...')
            await self._ws.close()

        user_id = self._lavalink.bot.user.id
        shard_count = self._lavalink.bot.shard_count or self._shards

        headers = {
            'Authorization': self._password,
            'Num-Shards': shard_count,
            'User-Id': str(user_id)
        }
        log.debug('Preparing to connect to Lavalink')
        log.debug('    with URI: {}'.format(self._uri))
        log.debug('    with headers: {}'.format(str(headers)))
        log.info('Connecting to Lavalink...')

        try:
            self._ws = await websockets.connect(self._uri, loop=self._loop, extra_headers=headers)
        except OSError as error:
            log.exception('Failed to connect to Lavalink: {}'.format(str(error)))
        else:
            log.info('Connected to Lavalink!')
            self._loop.create_task(self.listen())
            version = self._ws.response_headers.get('Lavalink-Major-Version', 2)
            try:
                self._lavalink._server_version = int(version)
            except ValueError:
                self._lavalink._server_version = 2
            log.info('Lavalink server version is {}'.format(version))
            if self._queue:
                log.info('Replaying {} queued events...'.format(len(self._queue)))
                for task in self._queue:
                    await self.send(**task)

async
def
connect
(
self
)
:
await
self
.
_lavalink
.
bot
.
wait_until_ready
(
)
if
self
.
_ws
and
self
.
_ws
.
open
:
log
.
debug
(
'WebSocket still open, closing...'
)
await
self
.
_ws
.
close
(
)
user_id
=
self
.
_lavalink
.
bot
.
user
.
id
shard_count
=
self
.
_lavalink
.
bot
.
shard_count
or
self
.
_shards
headers
=
{
'Authorization'
:
self
.
_password
,
'Num-Shards'
:
shard_count
,
'User-Id'
:
str
(
user_id
)
}
log
.
debug
(
'Preparing to connect to Lavalink'
)
log
.
debug
(
'    with URI: {}'
.
format
(
self
.
_uri
)
)
log
.
debug
(
'    with headers: {}'
.
format
(
str
(
headers
)
)
)
log
.
info
(
'Connecting to Lavalink...'
)
try
:
self
.
_ws
=
await
websockets
.
connect
(
self
.
_uri
,
loop
=
self
.
_loop
,
extra_headers
=
headers
)
except
OSError
as
error
:
log
.
exception
(
'Failed to connect to Lavalink: {}'
.
format
(
str
(
error
)
)
)
else
:
log
.
info
(
'Connected to Lavalink!'
)
self
.
_loop
.
create_task
(
self
.
listen
(
)
)
version
=
self
.
_ws
.
response_headers
.
get
(
'Lavalink-Major-Version'
,
2
)
try
:
self
.
_lavalink
.
_server_version
=
int
(
version
)
except
ValueError
:
self
.
_lavalink
.
_server_version
=
2
log
.
info
(
'Lavalink server version is {}'
.
format
(
version
)
)
if
self
.
_queue
:
log
.
info
(
'Replaying {} queued events...'
.
format
(
len
(
self
.
_queue
)
)
)
for
task
in
self
.
_queue
:
await
self
.
send
(
**
task
)

Establishes a connection to the Lavalink server .


async def listen(self):
        """ Waits to receive a payload from the Lavalink server and processes it. """
        while not self._shutdown:
            try:
                data = json.loads(await self._ws.recv())
            except websockets.ConnectionClosed as error:
                log.warning('Disconnected from Lavalink: {}'.format(str(error)))
                for g in self._lavalink.players._players.copy().keys():
                    ws = self._lavalink.bot._connection._get_websocket(int(g))
                    await ws.voice_state(int(g), None)

                self._lavalink.players.clear()

                if self._shutdown:
                    break

                if await self._attempt_reconnect():
                    return

                log.warning('Unable to reconnect to Lavalink!')
                break

            op = data.get('op', None)
            log.debug('Received WebSocket data {}'.format(str(data)))

            if not op:
                return log.debug('Received WebSocket message without op {}'.format(str(data)))

            if op == 'event':
                log.debug('Received event of type {}'.format(data['type']))
                player = self._lavalink.players[int(data['guildId'])]
                event = None

                if data['type'] == 'TrackEndEvent':
                    event = TrackEndEvent(player, data['track'], data['reason'])
                elif data['type'] == 'TrackExceptionEvent':
                    event = TrackExceptionEvent(player, data['track'], data['error'])
                elif data['type'] == 'TrackStuckEvent':
                    event = TrackStuckEvent(player, data['track'], data['thresholdMs'])

                if event:
                    await self._lavalink.dispatch_event(event)
            elif op == 'playerUpdate':
                await self._lavalink.update_state(data)
            elif op == 'stats':
                self._lavalink.stats._update(data)
                await self._lavalink.dispatch_event(StatsUpdateEvent(self._lavalink.stats))

        log.debug('Closing WebSocket...')
        await self._ws.close()

Waits to receive a payload from the Lavalink server and processes it .


def connected_channel(self):
        """ Returns the voice channel the player is connected to. """
        if not self.channel_id:
            return None

        return self._lavalink.bot.get_channel(int(self.channel_id))

def connected_channel ( self ) : if not self . channel_id : return None return self . _lavalink . bot . get_channel ( int ( self . channel_id ) )

Returns the voice channel the player is connected to .


async def connect(self, channel_id: int):
        """ Connects to a voice channel. """
        ws = self._lavalink.bot._connection._get_websocket(int(self.guild_id))
        await ws.voice_state(self.guild_id, str(channel_id))

async def connect ( self , channel_id : int ) : ws = self . _lavalink . bot . _connection . _get_websocket ( int ( self . guild_id ) ) await ws . voice_state ( self . guild_id , str ( channel_id ) )


async def disconnect(self):
        """ Disconnects from the voice channel, if any. """
        if not self.is_connected:
            return

        await self.stop()

        ws = self._lavalink.bot._connection._get_websocket(int(self.guild_id))
        await ws.voice_state(self.guild_id, None)

async def disconnect ( self ) : if not self . is_connected : return await self . stop ( ) ws = self . _lavalink . bot . _connection . _get_websocket ( int ( self . guild_id ) ) await ws . voice_state ( self . guild_id , None )

Disconnects from the voice channel if any .


def store(self, key: object, value: object):
        """ Stores custom user data. """
        self._user_data.update({key: value})

def store ( self , key : object , value : object ) : self . _user_data . update ( { key : value } )


def fetch(self, key: object, default=None):
        """ Retrieves the related value from the stored user data. """
        return self._user_data.get(key, default)

def fetch ( self , key : object , default = None ) : return self . _user_data . get ( key , default )

Retrieves the related value from the stored user data .


def add(self, requester: int, track: dict):
        """ Adds a track to the queue. """
        self.queue.append(AudioTrack().build(track, requester))

def add ( self , requester : int , track : dict ) : self . queue . append ( AudioTrack ( ) . build ( track , requester ) )


def add_next(self, requester: int, track: dict):
        """ Adds a track to beginning of the queue """
        self.queue.insert(0, AudioTrack().build(track, requester))

def add_next ( self , requester : int , track : dict ) : self . queue . insert ( 0 , AudioTrack ( ) . build ( track , requester ) )


def add_at(self, index: int, requester: int, track: dict):
        """ Adds a track at a specific index in the queue. """
        self.queue.insert(min(index, len(self.queue) - 1), AudioTrack().build(track, requester))

def add_at ( self , index : int , requester : int , track : dict ) : self . queue . insert ( min ( index , len ( self . queue ) - 1 ) , AudioTrack ( ) . build ( track , requester ) )

Adds a track at a specific index in the queue .


async def play(self, track_index: int = 0, ignore_shuffle: bool = False):
        """ Plays the first track in the queue, if any or plays a track from the specified index in the queue. """
        if self.repeat and self.current:
            self.queue.append(self.current)

        self.previous = self.current
        self.current = None
        self.position = 0
        self.paused = False

        if not self.queue:
            await self.stop()
            await self._lavalink.dispatch_event(QueueEndEvent(self))
        else:
            if self.shuffle and not ignore_shuffle:
                track = self.queue.pop(randrange(len(self.queue)))
            else:
                track = self.queue.pop(min(track_index, len(self.queue) - 1))

            self.current = track
            await self._lavalink.ws.send(op='play', guildId=self.guild_id, track=track.track)
            await self._lavalink.dispatch_event(TrackStartEvent(self, track))

async def play ( self , track_index : int = 0 , ignore_shuffle : bool = False ) : if self . repeat and self . current : self . queue . append ( self . current ) self . previous = self . current self . current = None self . position = 0 self . paused = False if not self . queue : await self . stop ( ) await self . _lavalink . dispatch_event ( QueueEndEvent ( self ) ) else : if self . shuffle and not ignore_shuffle : track = self . queue . pop ( randrange ( len ( self . queue ) ) ) else : track = self . queue . pop ( min ( track_index , len ( self . queue ) - 1 ) ) self . current = track await self . _lavalink . ws . send ( op = 'play' , guildId = self . guild_id , track = track . track ) await self . _lavalink . dispatch_event ( TrackStartEvent ( self , track ) )

Plays the first track in the queue if any or plays a track from the specified index in the queue .


async def play_now(self, requester: int, track: dict):
        """ Add track and play it. """
        self.add_next(requester, track)
        await self.play(ignore_shuffle=True)

async def play_now ( self , requester : int , track : dict ) : self . add_next ( requester , track ) await self . play ( ignore_shuffle = True )


async def play_at(self, index: int):
        """ Play the queue from a specific point. Disregards tracks before the index. """
        self.queue = self.queue[min(index, len(self.queue) - 1):len(self.queue)]
        await self.play(ignore_shuffle=True)

async def play_at ( self , index : int ) : self . queue = self . queue [ min ( index , len ( self . queue ) - 1 ) : len ( self . queue ) ] await self . play ( ignore_shuffle = True )

Play the queue from a specific point . Disregards tracks before the index .


async def play_previous(self):
        """ Plays previous track if it exist, if it doesn't raises a NoPreviousTrack error. """
        if not self.previous:
            raise NoPreviousTrack
        self.queue.insert(0, self.previous)
        await self.play(ignore_shuffle=True)

async def play_previous ( self ) : if not self . previous : raise NoPreviousTrack self . queue . insert ( 0 , self . previous ) await self . play ( ignore_shuffle = True )

Plays previous track if it exist if it doesn t raises a NoPreviousTrack error .


async def stop(self):
        """ Stops the player, if playing. """
        await self._lavalink.ws.send(op='stop', guildId=self.guild_id)
        self.current = None

async def stop ( self ) : await self . _lavalink . ws . send ( op = 'stop' , guildId = self . guild_id ) self . current = None


async def set_pause(self, pause: bool):
        """ Sets the player's paused state. """
        await self._lavalink.ws.send(op='pause', guildId=self.guild_id, pause=pause)
        self.paused = pause

async def set_pause ( self , pause : bool ) : await self . _lavalink . ws . send ( op = 'pause' , guildId = self . guild_id , pause = pause ) self . paused = pause


async def seek(self, pos: int):
        """ Seeks to a given position in the track. """
        await self._lavalink.ws.send(op='seek', guildId=self.guild_id, position=pos)

async def seek ( self , pos : int ) : await self . _lavalink . ws . send ( op = 'seek' , guildId = self . guild_id , position = pos )

Seeks to a given position in the track .


async def handle_event(self, event):
        """ Makes the player play the next song from the queue if a song has finished or an issue occurred. """
        if isinstance(event, (TrackStuckEvent, TrackExceptionEvent)) or \
                isinstance(event, TrackEndEvent) and event.reason == 'FINISHED':
            await self.play()

async def handle_event ( self , event ) : if isinstance ( event , ( TrackStuckEvent , TrackExceptionEvent ) ) or isinstance ( event , TrackEndEvent ) and event . reason == 'FINISHED' : await self . play ( )

Makes the player play the next song from the queue if a song has finished or an issue occurred .


def get(self, guild_id):
        """ Returns a player from the cache, or creates one if it does not exist. """
        if guild_id not in self._players:
            p = self._player(lavalink=self.lavalink, guild_id=guild_id)
            self._players[guild_id] = p

        return self._players[guild_id]

def get ( self , guild_id ) : if guild_id not in self . _players : p = self . _player ( lavalink = self . lavalink , guild_id = guild_id ) self . _players [ guild_id ] = p return self . _players [ guild_id ]

Returns a player from the cache or creates one if it does not exist .


def remove(self, guild_id):
        """ Removes a player from the current players. """
        if guild_id in self._players:
            self._players[guild_id].cleanup()
            del self._players[guild_id]

def remove ( self , guild_id ) : if guild_id in self . _players : self . _players [ guild_id ] . cleanup ( ) del self . _players [ guild_id ]

Removes a player from the current players .


async def _play(self, ctx, *, query: str):
        """ Searches and plays a song from a given query. """
        player = self.bot.lavalink.players.get(ctx.guild.id)

        query = query.strip('<>')

        if not url_rx.match(query):
            query = f'ytsearch:{query}'

        tracks = await self.bot.lavalink.get_tracks(query)

        if not tracks:
            return await ctx.send('Nothing found!')

        embed = discord.Embed(color=discord.Color.blurple())

        if 'list' in query and 'ytsearch:' not in query:
            for track in tracks:
                player.add(requester=ctx.author.id, track=track)

            embed.title = 'Playlist enqueued!'
            embed.description = f'Imported {len(tracks)} tracks from the playlist!'
            await ctx.send(embed=embed)
        else:
            track_title = tracks[0]["info"]["title"]
            track_uri = tracks[0]["info"]["uri"]

            embed.title = "Track enqueued!"
            embed.description = f'[{track_title}]({track_uri})'
            player.add(requester=ctx.author.id, track=tracks[0])

        if not player.is_playing:
            await player.play()

Searches and plays a song from a given query .


async def _seek(self, ctx, *, time: str):
        """ Seeks to a given position in a track. """
        player = self.bot.lavalink.players.get(ctx.guild.id)

        if not player.is_playing:
            return await ctx.send('Not playing.')

        seconds = time_rx.search(time)
        if not seconds:
            return await ctx.send('You need to specify the amount of seconds to skip!')

        seconds = int(seconds.group()) * 1000
        if time.startswith('-'):
            seconds *= -1

        track_time = player.position + seconds
        await player.seek(track_time)

        await ctx.send(f'Moved track to **{lavalink.Utils.format_time(track_time)}**')


async def _now(self, ctx):
        """ Shows some stats about the currently playing song. """
        player = self.bot.lavalink.players.get(ctx.guild.id)
        song = 'Nothing'

        if player.current:
            position = lavalink.Utils.format_time(player.position)
            if player.current.stream:
                duration = '🔴 LIVE'
            else:
                duration = lavalink.Utils.format_time(player.current.duration)
            song = f'**[{player.current.title}]({player.current.uri})**\n({position}/{duration})'

        embed = discord.Embed(color=discord.Color.blurple(), title='Now Playing', description=song)
        await ctx.send(embed=embed)

Shows some stats about the currently playing song .


async def _queue(self, ctx, page: int = 1):
        """ Shows the player's queue. """
        player = self.bot.lavalink.players.get(ctx.guild.id)

        if not player.queue:
            return await ctx.send('There\'s nothing in the queue! Why not queue something?')

        items_per_page = 10
        pages = math.ceil(len(player.queue) / items_per_page)

        start = (page - 1) * items_per_page
        end = start + items_per_page

        queue_list = ''
        for index, track in enumerate(player.queue[start:end], start=start):
            queue_list += f'`{index + 1}.` [**{track.title}**]({track.uri})\n'

        embed = discord.Embed(colour=discord.Color.blurple(),
                              description=f'**{len(player.queue)} tracks**\n\n{queue_list}')
        embed.set_footer(text=f'Viewing page {page}/{pages}')
        await ctx.send(embed=embed)