def create_bodies(self):
        '''Create physics bodies corresponding to each marker in our data.'''
        self.bodies = {}
        for label in self.channels:
            body = self.world.create_body(
                'sphere', name='marker:{}'.format(label), radius=0.02)
            body.is_kinematic = True
            body.color = 0.9, 0.1, 0.1, 0.5
            self.bodies[label] = body

def create_bodies ( self ) : self . bodies = { } for label in self . channels : body = self . world . create_body ( 'sphere' , name = 'marker:{}' . format ( label ) , radius = 0.02 ) body . is_kinematic = True body . color = 0.9 , 0.1 , 0.1 , 0.5 self . bodies [ label ] = body

Create physics bodies corresponding to each marker in our data .


def load_attachments(self, source, skeleton):
        '''Load attachment configuration from the given text source.

        The attachment configuration file has a simple format. After discarding
        Unix-style comments (any part of a line that starts with the pound (#)
        character), each line in the file is then expected to have the following
        format::

            marker-name body-name X Y Z

        The marker name must correspond to an existing "channel" in our marker
        data. The body name must correspond to a rigid body in the skeleton. The
        X, Y, and Z coordinates specify the body-relative offsets where the
        marker should be attached: 0 corresponds to the center of the body along
        the given axis, while -1 and 1 correspond to the minimal (maximal,
        respectively) extent of the body's bounding box along the corresponding
        dimension.

        Parameters
        ----------
        source : str or file-like
            A filename or file-like object that we can use to obtain text
            configuration that describes how markers are attached to skeleton
            bodies.

        skeleton : :class:`pagoda.skeleton.Skeleton`
            The skeleton to attach our marker data to.
        '''
        self.targets = {}
        self.offsets = {}

        filename = source
        if isinstance(source, str):
            source = open(source)
        else:
            filename = '(file-{})'.format(id(source))

        for i, line in enumerate(source):
            tokens = line.split('#')[0].strip().split()
            if not tokens:
                continue
            label = tokens.pop(0)
            if label not in self.channels:
                logging.info('%s:%d: unknown marker %s', filename, i, label)
                continue
            if not tokens:
                continue
            name = tokens.pop(0)
            bodies = [b for b in skeleton.bodies if b.name == name]
            if len(bodies) != 1:
                logging.info('%s:%d: %d skeleton bodies match %s',
                             filename, i, len(bodies), name)
                continue
            b = self.targets[label] = bodies[0]
            o = self.offsets[label] = \
                np.array(list(map(float, tokens))) * b.dimensions / 2
            logging.info('%s <--> %s, offset %s', label, b.name, o)

def
load_attachments
(
self
,
source
,
skeleton
)
:
self
.
targets
=
{
}
self
.
offsets
=
{
}
filename
=
source
if
isinstance
(
source
,
str
)
:
source
=
open
(
source
)
else
:
filename
=
'(file-{})'
.
format
(
id
(
source
)
)
for
i
,
line
in
enumerate
(
source
)
:
tokens
=
line
.
split
(
'#'
)
[
0
]
.
strip
(
)
.
split
(
)
if
not
tokens
:
continue
label
=
tokens
.
pop
(
0
)
if
label
not
in
self
.
channels
:
logging
.
info
(
'%s:%d: unknown marker %s'
,
filename
,
i
,
label
)
continue
if
not
tokens
:
continue
name
=
tokens
.
pop
(
0
)
bodies
=
[
b
for
b
in
skeleton
.
bodies
if
b
.
name
==
name
]
if
len
(
bodies
)
!=
1
:
logging
.
info
(
'%s:%d: %d skeleton bodies match %s'
,
filename
,
i
,
len
(
bodies
)
,
name
)
continue
b
=
self
.
targets
[
label
]
=
bodies
[
0
]
o
=
self
.
offsets
[
label
]
=
np
.
array
(
list
(
map
(
float
,
tokens
)
)
)
*
b
.
dimensions
/
2
logging
.
info
(
'%s <--> %s, offset %s'
,
label
,
b
.
name
,
o
)

Load attachment configuration from the given text source .


def attach(self, frame_no):
        '''Attach marker bodies to the corresponding skeleton bodies.

        Attachments are only made for markers that are not in a dropout state in
        the given frame.

        Parameters
        ----------
        frame_no : int
            The frame of data we will use for attaching marker bodies.
        '''
        assert not self.joints
        for label, j in self.channels.items():
            target = self.targets.get(label)
            if target is None:
                continue
            if self.visibility[frame_no, j] < 0:
                continue
            if np.linalg.norm(self.velocities[frame_no, j]) > 10:
                continue
            joint = ode.BallJoint(self.world.ode_world, self.jointgroup)
            joint.attach(self.bodies[label].ode_body, target.ode_body)
            joint.setAnchor1Rel([0, 0, 0])
            joint.setAnchor2Rel(self.offsets[label])
            joint.setParam(ode.ParamCFM, self.cfms[frame_no, j])
            joint.setParam(ode.ParamERP, self.erp)
            joint.name = label
            self.joints[label] = joint
        self._frame_no = frame_no

def attach ( self , frame_no ) : assert not self . joints for label , j in self . channels . items ( ) : target = self . targets . get ( label ) if target is None : continue if self . visibility [ frame_no , j ] < 0 : continue if np . linalg . norm ( self . velocities [ frame_no , j ] ) > 10 : continue joint = ode . BallJoint ( self . world . ode_world , self . jointgroup ) joint . attach ( self . bodies [ label ] . ode_body , target . ode_body ) joint . setAnchor1Rel ( [ 0 , 0 , 0 ] ) joint . setAnchor2Rel ( self . offsets [ label ] ) joint . setParam ( ode . ParamCFM , self . cfms [ frame_no , j ] ) joint . setParam ( ode . ParamERP , self . erp ) joint . name = label self . joints [ label ] = joint self . _frame_no = frame_no

Attach marker bodies to the corresponding skeleton bodies .


def reposition(self, frame_no):
        '''Reposition markers to a specific frame of data.

        Parameters
        ----------
        frame_no : int
            The frame of data where we should reposition marker bodies. Markers
            will be positioned in the appropriate places in world coordinates.
            In addition, linear velocities of the markers will be set according
            to the data as long as there are no dropouts in neighboring frames.
        '''
        for label, j in self.channels.items():
            body = self.bodies[label]
            body.position = self.positions[frame_no, j]
            body.linear_velocity = self.velocities[frame_no, j]

def reposition ( self , frame_no ) : for label , j in self . channels . items ( ) : body = self . bodies [ label ] body . position = self . positions [ frame_no , j ] body . linear_velocity = self . velocities [ frame_no , j ]

Reposition markers to a specific frame of data .


def distances(self):
        '''Get a list of the distances between markers and their attachments.

        Returns
        -------
        distances : ndarray of shape (num-markers, 3)
            Array of distances for each marker joint in our attachment setup. If
            a marker does not currently have an associated joint (e.g. because
            it is not currently visible) this will contain NaN for that row.
        '''
        distances = []
        for label in self.labels:
            joint = self.joints.get(label)
            distances.append([np.nan, np.nan, np.nan] if joint is None else
                             np.array(joint.getAnchor()) - joint.getAnchor2())
        return np.array(distances)

def distances ( self ) : distances = [ ] for label in self . labels : joint = self . joints . get ( label ) distances . append ( [ np . nan , np . nan , np . nan ] if joint is None else np . array ( joint . getAnchor ( ) ) - joint . getAnchor2 ( ) ) return np . array ( distances )

Get a list of the distances between markers and their attachments .


def forces(self, dx_tm1=None):
        '''Return an array of the forces exerted by marker springs.

        Notes
        -----

        The forces exerted by the marker springs can be approximated by::

          F = kp * dx

        where ``dx`` is the current array of marker distances. An even more
        accurate value is computed by approximating the velocity of the spring
        displacement::

          F = kp * dx + kd * (dx - dx_tm1) / dt

        where ``dx_tm1`` is an array of distances from the previous time step.

        Parameters
        ----------
        dx_tm1 : ndarray
            An array of distances from markers to their attachment targets,
            measured at the previous time step.

        Returns
        -------
        F : ndarray
            An array of forces that the markers are exerting on the skeleton.
        '''
        cfm = self.cfms[self._frame_no][:, None]
        kp = self.erp / (cfm * self.world.dt)
        kd = (1 - self.erp) / cfm
        dx = self.distances()
        F = kp * dx
        if dx_tm1 is not None:
            bad = np.isnan(dx) | np.isnan(dx_tm1)
            F[~bad] += (kd * (dx - dx_tm1) / self.world.dt)[~bad]
        return F

def forces ( self , dx_tm1 = None ) : cfm = self . cfms [ self . _frame_no ] [ : , None ] kp = self . erp / ( cfm * self . world . dt ) kd = ( 1 - self . erp ) / cfm dx = self . distances ( ) F = kp * dx if dx_tm1 is not None : bad = np . isnan ( dx ) | np . isnan ( dx_tm1 ) F [ ~ bad ] += ( kd * ( dx - dx_tm1 ) / self . world . dt ) [ ~ bad ] return F

Return an array of the forces exerted by marker springs .


def load_skeleton(self, filename, pid_params=None):
        '''Create and configure a skeleton in our model.

        Parameters
        ----------
        filename : str
            The name of a file containing skeleton configuration data.
        pid_params : dict, optional
            If given, use this dictionary to set the PID controller
            parameters on each joint in the skeleton. See
            :func:`pagoda.skeleton.pid` for more information.
        '''
        self.skeleton = skeleton.Skeleton(self)
        self.skeleton.load(filename, color=(0.3, 0.5, 0.9, 0.8))
        if pid_params:
            self.skeleton.set_pid_params(**pid_params)
        self.skeleton.erp = 0.1
        self.skeleton.cfm = 0

def load_skeleton ( self , filename , pid_params = None ) : self . skeleton = skeleton . Skeleton ( self ) self . skeleton . load ( filename , color = ( 0.3 , 0.5 , 0.9 , 0.8 ) ) if pid_params : self . skeleton . set_pid_params ( * * pid_params ) self . skeleton . erp = 0.1 self . skeleton . cfm = 0

Create and configure a skeleton in our model .


def load_markers(self, filename, attachments, max_frames=1e100):
        '''Load marker data and attachment preferences into the model.

        Parameters
        ----------
        filename : str
            The name of a file containing marker data. This currently needs to
            be either a .C3D or a .CSV file. CSV files must adhere to a fairly
            strict column naming convention; see :func:`Markers.load_csv` for
            more information.
        attachments : str
            The name of a text file specifying how markers are attached to
            skeleton bodies.
        max_frames : number, optional
            Only read in this many frames of marker data. By default, the entire
            data file is read into memory.

        Returns
        -------
        markers : :class:`Markers`
            Returns a markers object containing loaded marker data as well as
            skeleton attachment configuration.
        '''
        self.markers = Markers(self)
        fn = filename.lower()
        if fn.endswith('.c3d'):
            self.markers.load_c3d(filename, max_frames=max_frames)
        elif fn.endswith('.csv') or fn.endswith('.csv.gz'):
            self.markers.load_csv(filename, max_frames=max_frames)
        else:
            logging.fatal('%s: not sure how to load markers!', filename)
        self.markers.load_attachments(attachments, self.skeleton)

def
load_markers
(
self
,
filename
,
attachments
,
max_frames
=
1e100
)
:
self
.
markers
=
Markers
(
self
)
fn
=
filename
.
lower
(
)
if
fn
.
endswith
(
'.c3d'
)
:
self
.
markers
.
load_c3d
(
filename
,
max_frames
=
max_frames
)
elif
fn
.
endswith
(
'.csv'
)
or
fn
.
endswith
(
'.csv.gz'
)
:
self
.
markers
.
load_csv
(
filename
,
max_frames
=
max_frames
)
else
:
logging
.
fatal
(
'%s: not sure how to load markers!'
,
filename
)
self
.
markers
.
load_attachments
(
attachments
,
self
.
skeleton
)

Load marker data and attachment preferences into the model .


def step(self, substeps=2):
        '''Advance the physics world by one step.

        Typically this is called as part of a :class:`pagoda.viewer.Viewer`, but
        it can also be called manually (or some other stepping mechanism
        entirely can be used).
        '''
        # by default we step by following our loaded marker data.
        self.frame_no += 1
        try:
            next(self.follower)
        except (AttributeError, StopIteration) as err:
            self.reset()


def settle_to_markers(self, frame_no=0, max_distance=0.05, max_iters=300,
                          states=None):
        '''Settle the skeleton to our marker data at a specific frame.

        Parameters
        ----------
        frame_no : int, optional
            Settle the skeleton to marker data at this frame. Defaults to 0.
        max_distance : float, optional
            The settling process will stop when the mean marker distance falls
            below this threshold. Defaults to 0.1m (10cm). Setting this too
            small prevents the settling process from finishing (it will loop
            indefinitely), and setting it too large prevents the skeleton from
            settling to a stable state near the markers.
        max_iters : int, optional
            Attempt to settle markers for at most this many iterations. Defaults
            to 1000.
        states : list of body states, optional
            If given, set the bodies in our skeleton to these kinematic states
            before starting the settling process.
        '''
        if states is not None:
            self.skeleton.set_body_states(states)
        dist = None
        for _ in range(max_iters):
            for _ in self._step_to_marker_frame(frame_no):
                pass
            dist = np.nanmean(abs(self.markers.distances()))
            logging.info('settling to frame %d: marker distance %.3f', frame_no, dist)
            if dist < max_distance:
                return self.skeleton.get_body_states()
            for b in self.skeleton.bodies:
                b.linear_velocity = 0, 0, 0
                b.angular_velocity = 0, 0, 0
        return states

Settle the skeleton to our marker data at a specific frame .


def follow_markers(self, start=0, end=1e100, states=None):
        '''Iterate over a set of marker data, dragging its skeleton along.

        Parameters
        ----------
        start : int, optional
            Start following marker data after this frame. Defaults to 0.
        end : int, optional
            Stop following marker data after this frame. Defaults to the end of
            the marker data.
        states : list of body states, optional
            If given, set the states of the skeleton bodies to these values
            before starting to follow the marker data.
        '''
        if states is not None:
            self.skeleton.set_body_states(states)
        for frame_no, frame in enumerate(self.markers):
            if frame_no < start:
                continue
            if frame_no >= end:
                break
            for states in self._step_to_marker_frame(frame_no):
                yield states

def follow_markers ( self , start = 0 , end = 1e100 , states = None ) : if states is not None : self . skeleton . set_body_states ( states ) for frame_no , frame in enumerate ( self . markers ) : if frame_no < start : continue if frame_no >= end : break for states in self . _step_to_marker_frame ( frame_no ) : yield states

Iterate over a set of marker data dragging its skeleton along .


def _step_to_marker_frame(self, frame_no, dt=None):
        '''Update the simulator to a specific frame of marker data.

        This method returns a generator of body states for the skeleton! This
        generator must be exhausted (e.g., by consuming this call in a for loop)
        for the simulator to work properly.

        This process involves the following steps:

        - Move the markers to their new location:
          - Detach from the skeleton
          - Update marker locations
          - Reattach to the skeleton
        - Detect ODE collisions
        - Yield the states of the bodies in the skeleton
        - Advance the ODE world one step

        Parameters
        ----------
        frame_no : int
            Step to this frame of marker data.
        dt : float, optional
            Step with this time duration. Defaults to ``self.dt``.

        Returns
        -------
        states : sequence of state tuples
            A generator of a sequence of one body state for the skeleton. This
            generator must be exhausted for the simulation to work properly.
        '''
        # update the positions and velocities of the markers.
        self.markers.detach()
        self.markers.reposition(frame_no)
        self.markers.attach(frame_no)

        # detect collisions.
        self.ode_space.collide(None, self.on_collision)

        # record the state of each skeleton body.
        states = self.skeleton.get_body_states()
        self.skeleton.set_body_states(states)

        # yield the current simulation state to our caller.
        yield states

        # update the ode world.
        self.ode_world.step(dt or self.dt)

        # clear out contact joints to prepare for the next frame.
        self.ode_contactgroup.empty()

Update the simulator to a specific frame of marker data .


def inverse_kinematics(self, start=0, end=1e100, states=None, max_force=20):
        '''Follow a set of marker data, yielding kinematic joint angles.

        Parameters
        ----------
        start : int, optional
            Start following marker data after this frame. Defaults to 0.
        end : int, optional
            Stop following marker data after this frame. Defaults to the end of
            the marker data.
        states : list of body states, optional
            If given, set the states of the skeleton bodies to these values
            before starting to follow the marker data.
        max_force : float, optional
            Allow each degree of freedom in the skeleton to exert at most this
            force when attempting to maintain its equilibrium position. This
            defaults to 20N. Set this value higher to simulate a stiff skeleton
            while following marker data.

        Returns
        -------
        angles : sequence of angle frames
            Returns a generator of joint angle data for the skeleton. One set of
            joint angles will be generated for each frame of marker data between
            `start` and `end`.
        '''
        zeros = None
        if max_force > 0:
            self.skeleton.enable_motors(max_force)
            zeros = np.zeros(self.skeleton.num_dofs)
        for _ in self.follow_markers(start, end, states):
            if zeros is not None:
                self.skeleton.set_target_angles(zeros)
            yield self.skeleton.joint_angles

def inverse_kinematics ( self , start = 0 , end = 1e100 , states = None , max_force = 20 ) : zeros = None if max_force > 0 : self . skeleton . enable_motors ( max_force ) zeros = np . zeros ( self . skeleton . num_dofs ) for _ in self . follow_markers ( start , end , states ) : if zeros is not None : self . skeleton . set_target_angles ( zeros ) yield self . skeleton . joint_angles

Follow a set of marker data yielding kinematic joint angles .


def inverse_dynamics(self, angles, start=0, end=1e100, states=None, max_force=100):
        '''Follow a set of angle data, yielding dynamic joint torques.

        Parameters
        ----------
        angles : ndarray (num-frames x num-dofs)
            Follow angle data provided by this array of angle values.
        start : int, optional
            Start following angle data after this frame. Defaults to the start
            of the angle data.
        end : int, optional
            Stop following angle data after this frame. Defaults to the end of
            the angle data.
        states : list of body states, optional
            If given, set the states of the skeleton bodies to these values
            before starting to follow the marker data.
        max_force : float, optional
            Allow each degree of freedom in the skeleton to exert at most this
            force when attempting to follow the given joint angles. Defaults to
            100N. Setting this value to be large results in more accurate
            following but can cause oscillations in the PID controllers,
            resulting in noisy torques.

        Returns
        -------
        torques : sequence of torque frames
            Returns a generator of joint torque data for the skeleton. One set
            of joint torques will be generated for each frame of angle data
            between `start` and `end`.
        '''
        if states is not None:
            self.skeleton.set_body_states(states)

        for frame_no, frame in enumerate(angles):
            if frame_no < start:
                continue
            if frame_no >= end:
                break

            self.ode_space.collide(None, self.on_collision)

            states = self.skeleton.get_body_states()
            self.skeleton.set_body_states(states)

            # joseph's stability fix: step to compute torques, then reset the
            # skeleton to the start of the step, and then step using computed
            # torques. thus any numerical errors between the body states after
            # stepping using angle constraints will be removed, because we
            # will be stepping the model using the computed torques.

            self.skeleton.enable_motors(max_force)
            self.skeleton.set_target_angles(angles[frame_no])
            self.ode_world.step(self.dt)
            torques = self.skeleton.joint_torques
            self.skeleton.disable_motors()

            self.skeleton.set_body_states(states)
            self.skeleton.add_torques(torques)
            yield torques
            self.ode_world.step(self.dt)

            self.ode_contactgroup.empty()

Follow a set of angle data yielding dynamic joint torques .


def forward_dynamics(self, torques, start=0, states=None):
        '''Move the body according to a set of torque data.'''
        if states is not None:
            self.skeleton.set_body_states(states)
        for frame_no, torque in enumerate(torques):
            if frame_no < start:
                continue
            if frame_no >= end:
                break
            self.ode_space.collide(None, self.on_collision)
            self.skeleton.add_torques(torque)
            self.ode_world.step(self.dt)
            yield
            self.ode_contactgroup.empty()

def forward_dynamics ( self , torques , start = 0 , states = None ) : if states is not None : self . skeleton . set_body_states ( states ) for frame_no , torque in enumerate ( torques ) : if frame_no < start : continue if frame_no >= end : break self . ode_space . collide ( None , self . on_collision ) self . skeleton . add_torques ( torque ) self . ode_world . step ( self . dt ) yield self . ode_contactgroup . empty ( )

Move the body according to a set of torque data .


def resorted(values):
    """
    Sort values, but put numbers after alphabetically sorted words.

    This function is here to make outputs diff-compatible with Aleph.

    Example::
        >>> sorted(["b", "1", "a"])
        ['1', 'a', 'b']
        >>> resorted(["b", "1", "a"])
        ['a', 'b', '1']

    Args:
        values (iterable): any iterable object/list/tuple/whatever.

    Returns:
        list of sorted values, but with numbers after words
    """
    if not values:
        return values

    values = sorted(values)

    # look for first word
    first_word = next(
        (cnt for cnt, val in enumerate(values)
             if val and not val[0].isdigit()),
        None
    )

    # if not found, just return the values
    if first_word is None:
        return values

    words = values[first_word:]
    numbers = values[:first_word]

    return words + numbers

def
resorted
(
values
)
:
if
not
values
:
return
values
values
=
sorted
(
values
)
# look for first word
first_word
=
next
(
(
cnt
for
cnt
,
val
in
enumerate
(
values
)
if
val
and
not
val
[
0
]
.
isdigit
(
)
)
,
)
# if not found, just return the values
if
first_word
is
:
return
values
words
=
values
[
first_word
:
]
numbers
=
values
[
:
first_word
]
return
words
+
numbers

Sort values but put numbers after alphabetically sorted words .


def render(self, dt):
        '''Draw all bodies in the world.'''
        for frame in self._frozen:
            for body in frame:
                self.draw_body(body)
        for body in self.world.bodies:
            self.draw_body(body)

        if hasattr(self.world, 'markers'):
            # draw line between anchor1 and anchor2 for marker joints.
            window.glColor4f(0.9, 0.1, 0.1, 0.9)
            window.glLineWidth(3)
            for j in self.world.markers.joints.values():
                window.glBegin(window.GL_LINES)
                window.glVertex3f(*j.getAnchor())
                window.glVertex3f(*j.getAnchor2())
                window.glEnd()


def get_stream(self, error_callback=None, live=True):
        """ Get room stream to listen for messages.

        Kwargs:
            error_callback (func): Callback to call when an error occurred (parameters: exception)
            live (bool): If True, issue a live stream, otherwise an offline stream

        Returns:
            :class:`Stream`. Stream
        """
        self.join()
        return Stream(self, error_callback=error_callback, live=live)

def get_stream ( self , error_callback = None , live = True ) : self . join ( ) return Stream ( self , error_callback = error_callback , live = live )

Get room stream to listen for messages .


def get_users(self, sort=True):
        """ Get list of users in the room.

        Kwargs:
            sort (bool): If True, sort rooms by name

        Returns:
            array. List of users
        """
        self._load()
        if sort:
            self.users.sort(key=operator.itemgetter("name"))
        return self.users

def get_users ( self , sort = True ) : self . _load ( ) if sort : self . users . sort ( key = operator . itemgetter ( "name" ) ) return self . users


def set_name(self, name):
        """ Set the room name.

        Args:
            name (str): Name

        Returns:
            bool. Success
        """
        if not self._campfire.get_user().admin:
            return False

        result = self._connection.put("room/%s" % self.id, {"room": {"name": name}})
        if result["success"]:
            self._load()
        return result["success"]

def set_name ( self , name ) : if not self . _campfire . get_user ( ) . admin : return False result = self . _connection . put ( "room/%s" % self . id , { "room" : { "name" : name } } ) if result [ "success" ] : self . _load ( ) return result [ "success" ]


def set_topic(self, topic):
        """ Set the room topic.

        Args:
            topic (str): Topic

        Returns:
            bool. Success
        """
        if not topic:
            topic = ''
        result = self._connection.put("room/%s" % self.id, {"room": {"topic": topic}})
        if result["success"]:
            self._load()

        return result["success"]

def set_topic ( self , topic ) : if not topic : topic = '' result = self . _connection . put ( "room/%s" % self . id , { "room" : { "topic" : topic } } ) if result [ "success" ] : self . _load ( ) return result [ "success" ]


def speak(self, message):
        """ Post a message.

        Args:
            message (:class:`Message` or string): Message

        Returns:
            bool. Success
        """
        campfire = self.get_campfire()
        if not isinstance(message, Message):
            message = Message(campfire, message)

        result = self._connection.post(
            "room/%s/speak" % self.id,
            {"message": message.get_data()},
            parse_data=True,
            key="message"
        )

        if result["success"]:
            return Message(campfire, result["data"])
        return result["success"]

def speak ( self , message ) : campfire = self . get_campfire ( ) if not isinstance ( message , Message ) : message = Message ( campfire , message ) result = self . _connection . post ( "room/%s/speak" % self . id , { "message" : message . get_data ( ) } , parse_data = True , key = "message" ) if result [ "success" ] : return Message ( campfire , result [ "data" ] ) return result [ "success" ]


def get_xdg_dirs(self):
        # type: () -> List[str]
        """
        Returns a list of paths specified by the XDG_CONFIG_DIRS environment
        variable or the appropriate default.

        The list is sorted by precedence, with the most important item coming
        *last* (required by the existing config_resolver logic).
        """
        config_dirs = getenv('XDG_CONFIG_DIRS', '')
        if config_dirs:
            self._log.debug('XDG_CONFIG_DIRS is set to %r', config_dirs)
            output = []
            for path in reversed(config_dirs.split(':')):
                output.append(join(path, self.group_name, self.app_name))
            return output
        return ['/etc/xdg/%s/%s' % (self.group_name, self.app_name)]

def
get_xdg_dirs
(
self
)
:
# type: () -> List[str]
config_dirs
=
getenv
(
'XDG_CONFIG_DIRS'
,
''
)
if
config_dirs
:
self
.
_log
.
debug
(
'XDG_CONFIG_DIRS is set to %r'
,
config_dirs
)
output
=
[
]
for
path
in
reversed
(
config_dirs
.
split
(
':'
)
)
:
output
.
append
(
join
(
path
,
self
.
group_name
,
self
.
app_name
)
)
return
output
return
[
'/etc/xdg/%s/%s'
%
(
self
.
group_name
,
self
.
app_name
)
]

Returns a list of paths specified by the XDG_CONFIG_DIRS environment variable or the appropriate default .


def get_xdg_home(self):
        # type: () -> str
        """
        Returns the value specified in the XDG_CONFIG_HOME environment variable
        or the appropriate default.
        """
        config_home = getenv('XDG_CONFIG_HOME', '')
        if config_home:
            self._log.debug('XDG_CONFIG_HOME is set to %r', config_home)
            return expanduser(join(config_home, self.group_name, self.app_name))
        return expanduser('~/.config/%s/%s' % (self.group_name, self.app_name))

def
get_xdg_home
(
self
)
:
# type: () -> str
config_home
=
getenv
(
'XDG_CONFIG_HOME'
,
''
)
if
config_home
:
self
.
_log
.
debug
(
'XDG_CONFIG_HOME is set to %r'
,
config_home
)
return
expanduser
(
join
(
config_home
,
self
.
group_name
,
self
.
app_name
)
)
return
expanduser
(
'~/.config/%s/%s'
%
(
self
.
group_name
,
self
.
app_name
)
)

Returns the value specified in the XDG_CONFIG_HOME environment variable or the appropriate default .


def _effective_filename(self):
        # type: () -> str
        """
        Returns the filename which is effectively used by the application. If
        overridden by an environment variable, it will return that filename.
        """
        # same logic for the configuration filename. First, check if we were
        # initialized with a filename...
        config_filename = ''
        if self.filename:
            config_filename = self.filename

        # ... next, take the value from the environment
        env_filename = getenv(self.env_filename_name)
        if env_filename:
            self._log.info('Configuration filename was overridden with %r '
                           'by the environment variable %s.',
                           env_filename,
                           self.env_filename_name)
            config_filename = env_filename

        return config_filename

Returns the filename which is effectively used by the application . If overridden by an environment variable it will return that filename .


def check_file(self, filename):
        # type: (str) -> bool
        """
        Check if ``filename`` can be read. Will return boolean which is True if
        the file can be read, False otherwise.
        """
        if not exists(filename):
            return False

        # Check if the file is version-compatible with this instance.
        new_config = ConfigResolverBase()
        new_config.read(filename)
        if self.version and not new_config.has_option('meta', 'version'):
            # self.version is set, so we MUST have a version in the file!
            raise NoVersionError(
                "The config option 'meta.version' is missing in {}. The "
                "application expects version {}!".format(filename,
                                                         self.version))
        elif not self.version and new_config.has_option('meta', 'version'):
            # Automatically "lock-in" a version number if one is found.
            # This prevents loading a chain of config files with incompatible
            # version numbers!
            self.version = StrictVersion(new_config.get('meta', 'version'))
            self._log.info('%r contains a version number, but the config '
                           'instance was not created with a version '
                           'restriction. Will set version number to "%s" to '
                           'prevent accidents!',
                           filename, self.version)
        elif self.version:
            # This instance expected a certain version. We need to check the
            # version in the file and compare.
            file_version = new_config.get('meta', 'version')
            major, minor, _ = StrictVersion(file_version).version
            expected_major, expected_minor, _ = self.version.version
            if expected_major != major:
                self._log.error(
                    'Invalid major version number in %r. Expected %r, got %r!',
                    abspath(filename),
                    str(self.version),
                    file_version)
                return False

            if expected_minor != minor:
                self._log.warning(
                    'Mismatching minor version number in %r. '
                    'Expected %r, got %r!',
                    abspath(filename),
                    str(self.version),
                    file_version)
                return True
        return True

Check if filename can be read . Will return boolean which is True if the file can be read False otherwise .


def load(self, reload=False, require_load=False):
        # type: (bool, bool) -> None
        """
        Searches for an appropriate config file. If found, loads the file into
        the current instance. This method can also be used to reload a
        configuration. Note that you may want to set ``reload`` to ``True`` to
        clear the configuration before loading in that case.  Without doing
        that, values will remain available even if they have been removed from
        the config files.

        :param reload: if set to ``True``, the existing values are cleared
                       before reloading.
        :param require_load: If set to ``True`` this will raise a
                             :py:exc:`IOError` if no config file has been found
                             to load.
        """

        if reload:  # pragma: no cover
            self.config = None

        # only load the config if necessary (or explicitly requested)
        if self.config:  # pragma: no cover
            self._log.debug('Returning cached config instance. Use '
                            '``reload=True`` to avoid caching!')
            return

        path = self._effective_path()
        config_filename = self._effective_filename()

        # Next, use the resolved path to find the filenames. Keep track of
        # which files we loaded in order to inform the user.
        self._active_path = [join(_, config_filename) for _ in path]
        for dirname in path:
            conf_name = join(dirname, config_filename)
            readable = self.check_file(conf_name)
            if readable:
                action = 'Updating' if self._loaded_files else 'Loading initial'
                self._log.info('%s config from %s', action, conf_name)
                self.read(conf_name)
                if conf_name == expanduser("~/.%s/%s/%s" % (
                        self.group_name, self.app_name, self.filename)):
                    self._log.warning(
                        "DEPRECATION WARNING: The file "
                        "'%s/.%s/%s/app.ini' was loaded. The XDG "
                        "Basedir standard requires this file to be in "
                        "'%s/.config/%s/%s/app.ini'! This location "
                        "will no longer be parsed in a future version of "
                        "config_resolver! You can already (and should) move "
                        "the file!", expanduser("~"), self.group_name,
                        self.app_name, expanduser("~"), self.group_name,
                        self.app_name)
                self._loaded_files.append(conf_name)

        if not self._loaded_files and not require_load:
            self._log.warning(
                "No config file named %s found! Search path was %r",
                config_filename,
                path)
        elif not self._loaded_files and require_load:
            raise IOError("No config file named %s found! Search path "
                          "was %r" % (config_filename, path))

Searches for an appropriate config file . If found loads the file into the current instance . This method can also be used to reload a configuration . Note that you may want to set reload to True to clear the configuration before loading in that case . Without doing that values will remain available even if they have been removed from the config files .


def get(self, q=None, page=None):
        """Get styles."""
        # Check cache to exit early if needed
        etag = generate_etag(current_ext.content_version.encode('utf8'))
        self.check_etag(etag, weak=True)

        # Build response
        res = jsonify(current_ext.styles)
        res.set_etag(etag)

        return res

def
get
(
self
,
q
=
,
page
=
)
:
# Check cache to exit early if needed
etag
=
generate_etag
(
current_ext
.
content_version
.
encode
(
'utf8'
)
)
self
.
check_etag
(
etag
,
weak
=
True
)
# Build response
res
=
jsonify
(
current_ext
.
styles
)
res
.
set_etag
(
etag
)
return
res


def create_from_settings(settings):
        """ Create a connection with given settings.

        Args:
            settings (dict): A dictionary of settings

        Returns:
            :class:`Connection`. The connection
        """
        return Connection(
            settings["url"],
            settings["base_url"],
            settings["user"],
            settings["password"],
            authorizations = settings["authorizations"],
            debug = settings["debug"]
        )

def create_from_settings ( settings ) : return Connection ( settings [ "url" ] , settings [ "base_url" ] , settings [ "user" ] , settings [ "password" ] , authorizations = settings [ "authorizations" ] , debug = settings [ "debug" ] )

Create a connection with given settings .


def delete(self, url=None, post_data={}, parse_data=False, key=None, parameters=None):
        """ Issue a PUT request.

        Kwargs:
            url (str): Destination URL
            post_data (dict): Dictionary of parameter and values
            parse_data (bool): If true, parse response data
            key (string): If parse_data==True, look for this key when parsing data
            parameters (dict): Additional GET parameters to append to the URL

        Returns:
            dict. Response (a dict with keys: success, data, info, body)

        Raises:
            AuthenticationError, ConnectionError, urllib2.HTTPError, ValueError, Exception
        """
        return self._fetch("DELETE", url, post_data=post_data, parse_data=parse_data, key=key, parameters=parameters, full_return=True)

def delete ( self , url = None , post_data = { } , parse_data = False , key = None , parameters = None ) : return self . _fetch ( "DELETE" , url , post_data = post_data , parse_data = parse_data , key = key , parameters = parameters , full_return = True )


def post(self, url=None, post_data={}, parse_data=False, key=None, parameters=None, listener=None):
        """ Issue a POST request.

        Kwargs:
            url (str): Destination URL
            post_data (dict): Dictionary of parameter and values
            parse_data (bool): If true, parse response data
            key (string): If parse_data==True, look for this key when parsing data
            parameters (dict): Additional GET parameters to append to the URL
            listener (func): callback called when uploading a file

        Returns:
            dict. Response (a dict with keys: success, data, info, body)

        Raises:
            AuthenticationError, ConnectionError, urllib2.HTTPError, ValueError, Exception
        """
        return self._fetch("POST", url, post_data=post_data, parse_data=parse_data, key=key, parameters=parameters, listener=listener, full_return=True)

def post ( self , url = None , post_data = { } , parse_data = False , key = None , parameters = None , listener = None ) : return self . _fetch ( "POST" , url , post_data = post_data , parse_data = parse_data , key = key , parameters = parameters , listener = listener , full_return = True )


def get(self, url=None, parse_data=True, key=None, parameters=None):
        """ Issue a GET request.

        Kwargs:
            url (str): Destination URL
            parse_data (bool): If true, parse response data
            key (string): If parse_data==True, look for this key when parsing data
            parameters (dict): Additional GET parameters to append to the URL

        Returns:
            dict. Response (a dict with keys: success, data, info, body)

        Raises:
            AuthenticationError, ConnectionError, urllib2.HTTPError, ValueError, Exception
        """
        return self._fetch("GET", url, post_data=None, parse_data=parse_data, key=key, parameters=parameters)

def get ( self , url = None , parse_data = True , key = None , parameters = None ) : return self . _fetch ( "GET" , url , post_data = None , parse_data = parse_data , key = key , parameters = parameters )


def get_headers(self):
        """ Get headers.

        Returns:
            tuple: Headers
        """
        headers = {
            "User-Agent": "kFlame 1.0"
        }

        password_url = self._get_password_url()
        if password_url and password_url in self._settings["authorizations"]:
            headers["Authorization"] = self._settings["authorizations"][password_url]

        return headers

def
get_headers
(
self
)
:
headers
=
{
"User-Agent"
:
"kFlame 1.0"
}
password_url
=
self
.
_get_password_url
(
)
if
password_url
and
password_url
in
self
.
_settings
[
"authorizations"
]
:
headers
[
"Authorization"
]
=
self
.
_settings
[
"authorizations"
]
[
password_url
]
return
headers

Get headers.

        Returns:
            tuple: Headers


def _get_password_url(self):
        """ Get URL used for authentication

        Returns:
            string: URL
        """
        password_url = None
        if self._settings["user"] or self._settings["authorization"]:
            if self._settings["url"]:
                password_url = self._settings["url"]
            elif self._settings["base_url"]:
                password_url = self._settings["base_url"]
        return password_url

def _get_password_url ( self ) : password_url = None if self . _settings [ "user" ] or self . _settings [ "authorization" ] : if self . _settings [ "url" ] : password_url = self . _settings [ "url" ] elif self . _settings [ "base_url" ] : password_url = self . _settings [ "base_url" ] return password_url


def parse(self, text, key=None):
        """ Parses a response.

        Args:
            text (str): Text to parse

        Kwargs:
            key (str): Key to look for, if any

        Returns:
            Parsed value

        Raises:
            ValueError
        """
        try:
            data = json.loads(text)
        except ValueError as e:
            raise ValueError("%s: Value: [%s]" % (e, text))

        if data and key:
            if key not in data:
                raise ValueError("Invalid response (key %s not found): %s" % (key, data))
            data = data[key]
        return data


def build_twisted_request(self, method, url, extra_headers={}, body_producer=None, full_url=False):
        """ Build a request for twisted

        Args:
            method (str): Request method (GET/POST/PUT/DELETE/etc.) If not specified, it will be POST if post_data is not None
            url (str): Destination URL (full, or relative)

        Kwargs:
            extra_headers (dict): Headers (override default connection headers, if any)
            body_producer (:class:`twisted.web.iweb.IBodyProducer`): Object producing request body
            full_url (bool): If False, URL is relative

        Returns:
            tuple. Tuple with two elements: reactor, and request
        """
        uri = url if full_url else self._url(url)

        raw_headers = self.get_headers()
        if extra_headers:
            raw_headers.update(extra_headers)

        headers = http_headers.Headers()
        for header in raw_headers:
            headers.addRawHeader(header, raw_headers[header])

        agent = client.Agent(reactor)
        request = agent.request(method, uri, headers, body_producer)

        return (reactor, request)

def build_twisted_request ( self , method , url , extra_headers = { } , body_producer = None , full_url = False ) : uri = url if full_url else self . _url ( url ) raw_headers = self . get_headers ( ) if extra_headers : raw_headers . update ( extra_headers ) headers = http_headers . Headers ( ) for header in raw_headers : headers . addRawHeader ( header , raw_headers [ header ] ) agent = client . Agent ( reactor ) request = agent . request ( method , uri , headers , body_producer ) return ( reactor , request )


def _fetch(self, method, url=None, post_data=None, parse_data=True, key=None, parameters=None, listener=None, full_return=False):
        """ Issue a request.

        Args:
            method (str): Request method (GET/POST/PUT/DELETE/etc.) If not specified, it will be POST if post_data is not None

        Kwargs:
            url (str): Destination URL
            post_data (str): A string of what to POST
            parse_data (bool): If true, parse response data
            key (string): If parse_data==True, look for this key when parsing data
            parameters (dict): Additional GET parameters to append to the URL
            listener (func): callback called when uploading a file
            full_return (bool): If set to True, get a full response (with success, data, info, body)

        Returns:
            dict. Response. If full_return==True, a dict with keys: success, data, info, body, otherwise the parsed data

        Raises:
            AuthenticationError, ConnectionError, urllib2.HTTPError, ValueError
        """

        headers = self.get_headers()
        headers["Content-Type"] = "application/json"

        handlers = []
        debuglevel = int(self._settings["debug"])

        handlers.append(urllib2.HTTPHandler(debuglevel=debuglevel))
        if hasattr(httplib, "HTTPS"):
            handlers.append(urllib2.HTTPSHandler(debuglevel=debuglevel))

        handlers.append(urllib2.HTTPCookieProcessor(cookielib.CookieJar()))

        password_url = self._get_password_url()
        if password_url and "Authorization" not in headers:
            pwd_manager = urllib2.HTTPPasswordMgrWithDefaultRealm()
            pwd_manager.add_password(None, password_url, self._settings["user"], self._settings["password"])
            handlers.append(HTTPBasicAuthHandler(pwd_manager))

        opener = urllib2.build_opener(*handlers)

        if post_data is not None:
            post_data = json.dumps(post_data)

        uri = self._url(url, parameters)
        request = RESTRequest(uri, method=method, headers=headers)
        if post_data is not None:
            request.add_data(post_data)

        response = None

        try:
            response = opener.open(request)
            body = response.read()
            if password_url and password_url not in self._settings["authorizations"] and request.has_header("Authorization"):
                self._settings["authorizations"][password_url] = request.get_header("Authorization")
        except urllib2.HTTPError as e:
            if e.code == 401:
                raise AuthenticationError("Access denied while trying to access %s" % uri)
            elif e.code == 404:
                raise ConnectionError("URL not found: %s" % uri)
            else:
                raise
        except urllib2.URLError as e:
            raise ConnectionError("Error while fetching from %s: %s" % (uri, e))
        finally:
            if response:
                response.close()

            opener.close()

        data = None
        if parse_data:
            if not key:
                key = string.split(url, "/")[0]

            data = self.parse(body, key)

        if full_return:
            info = response.info() if response else None
            status = int(string.split(info["status"])[0]) if (info and "status" in info) else None

            return {
                "success": (status >= 200 and status < 300),
                "data": data,
                "info": info,
                "body": body
            }

        return data


def _url(self, url=None, parameters=None):
        """ Build destination URL.

        Kwargs:
            url (str): Destination URL
            parameters (dict): Additional GET parameters to append to the URL

        Returns:
            str. URL
        """

        uri = url or self._settings["url"]
        if url and self._settings["base_url"]:
            uri = "%s/%s" % (self._settings["base_url"], url)
        uri += ".json"
        if parameters:
            uri += "?%s" % urllib.urlencode(parameters)
        return uri

def _url ( self , url = None , parameters = None ) : uri = url or self . _settings [ "url" ] if url and self . _settings [ "base_url" ] : uri = "%s/%s" % ( self . _settings [ "base_url" ] , url ) uri += ".json" if parameters : uri += "?%s" % urllib . urlencode ( parameters ) return uri


def is_text(self):
        """ Tells if this message is a text message.

        Returns:
            bool. Success
        """
        return self.type in [
            self._TYPE_PASTE,
            self._TYPE_TEXT,
            self._TYPE_TWEET
        ]

def is_text ( self ) : return self . type in [ self . _TYPE_PASTE , self . _TYPE_TEXT , self . _TYPE_TWEET ]

Tells if this message is a text message .


def get_rooms(self, sort=True):
        """ Get rooms list.

        Kwargs:
            sort (bool): If True, sort rooms by name

        Returns:
            array. List of rooms (each room is a dict)
        """
        rooms = self._connection.get("rooms")
        if sort:
            rooms.sort(key=operator.itemgetter("name"))
        return rooms

def get_rooms ( self , sort = True ) : rooms = self . _connection . get ( "rooms" ) if sort : rooms . sort ( key = operator . itemgetter ( "name" ) ) return rooms


def get_room_by_name(self, name):
        """ Get a room by name.

        Returns:
            :class:`Room`. Room

        Raises:
            RoomNotFoundException
        """
        rooms = self.get_rooms()
        for room in rooms or []:
            if room["name"] == name:
                return self.get_room(room["id"])
        raise RoomNotFoundException("Room %s not found" % name)

def
get_room_by_name
(
self
,
name
)
:
rooms
=
self
.
get_rooms
(
)
for
room
in
rooms
or
[
]
:
if
room
[
"name"
]
==
name
:
return
self
.
get_room
(
room
[
"id"
]
)
raise
RoomNotFoundException
(
"Room %s not found"
%
name
)


def get_room(self, id):
        """ Get room.

        Returns:
            :class:`Room`. Room
        """
        if id not in self._rooms:
            self._rooms[id] = Room(self, id)
        return self._rooms[id]

def get_room ( self , id ) : if id not in self . _rooms : self . _rooms [ id ] = Room ( self , id ) return self . _rooms [ id ]

Get room.

        Returns:
            :class:`Room`. Room


def get_user(self, id = None):
        """ Get user.

        Returns:
            :class:`User`. User
        """
        if not id:
            id = self._user.id

        if id not in self._users:
            self._users[id] = self._user if id == self._user.id else User(self, id)

        return self._users[id]

def get_user ( self , id = None ) : if not id : id = self . _user . id if id not in self . _users : self . _users [ id ] = self . _user if id == self . _user . id else User ( self , id ) return self . _users [ id ]

Get user.

        Returns:
            :class:`User`. User


def search(self, terms):
        """ Search transcripts.

        Args:
            terms (str): Terms for search

        Returns:
            array. Messages
        """
        messages = self._connection.get("search/%s" % urllib.quote_plus(terms), key="messages")
        if messages:
            messages = [Message(self, message) for message in messages]
        return messages

def search ( self , terms ) : messages = self . _connection . get ( "search/%s" % urllib . quote_plus ( terms ) , key = "messages" ) if messages : messages = [ Message ( self , message ) for message in messages ] return messages


def attach(self, observer):
        """ Attach an observer.

        Args:
            observer (func): A function to be called when new messages arrive

        Returns:
            :class:`Stream`. Current instance to allow chaining
        """
        if not observer in self._observers:
            self._observers.append(observer)
        return self

def attach ( self , observer ) : if not observer in self . _observers : self . _observers . append ( observer ) return self


def incoming(self, messages):
        """ Called when incoming messages arrive.

        Args:
            messages (tuple): Messages (each message is a dict)
        """
        if self._observers:
            campfire = self._room.get_campfire()
            for message in messages:
                for observer in self._observers:
                    observer(Message(campfire, message))

def incoming ( self , messages ) : if self . _observers : campfire = self . _room . get_campfire ( ) for message in messages : for observer in self . _observers : observer ( Message ( campfire , message ) )


def fetch(self):
        """ Fetch new messages. """
        try:
            if not self._last_message_id:
                messages = self._connection.get("room/%s/recent" % self._room_id, key="messages", parameters={
                    "limit": 1
                })
                self._last_message_id = messages[-1]["id"]

            messages = self._connection.get("room/%s/recent" % self._room_id, key="messages", parameters={
                "since_message_id": self._last_message_id
            })
        except:
            messages = []

        if messages:
            self._last_message_id = messages[-1]["id"]

        self.received(messages)

def fetch ( self ) : try : if not self . _last_message_id : messages = self . _connection . get ( "room/%s/recent" % self . _room_id , key = "messages" , parameters = { "limit" : 1 } ) self . _last_message_id = messages [ - 1 ] [ "id" ] messages = self . _connection . get ( "room/%s/recent" % self . _room_id , key = "messages" , parameters = { "since_message_id" : self . _last_message_id } ) except : messages = [ ] if messages : self . _last_message_id = messages [ - 1 ] [ "id" ] self . received ( messages )


def received(self, messages):
        """ Called when new messages arrive.

        Args:
            messages (tuple): Messages
        """
        if messages:
            if self._queue:
                self._queue.put_nowait(messages)

            if self._callback:
                self._callback(messages)

def received ( self , messages ) : if messages : if self . _queue : self . _queue . put_nowait ( messages ) if self . _callback : self . _callback ( messages )


def connectionMade(self):
        """ Called when a connection is made, and used to send out headers """

        headers = [
            "GET %s HTTP/1.1" % ("/room/%s/live.json" % self.factory.get_stream().get_room_id())
        ]

        connection_headers = self.factory.get_stream().get_connection().get_headers()
        for header in connection_headers:
            headers.append("%s: %s" % (header, connection_headers[header]))

        headers.append("Host: streaming.campfirenow.com")

        self.transport.write("\r\n".join(headers) + "\r\n\r\n")
        self.factory.get_stream().set_protocol(self)

def
connectionMade
(
self
)
:
headers
=
[
"GET %s HTTP/1.1"
%
(
"/room/%s/live.json"
%
self
.
factory
.
get_stream
(
)
.
get_room_id
(
)
)
]
connection_headers
=
self
.
factory
.
get_stream
(
)
.
get_connection
(
)
.
get_headers
(
)
for
header
in
connection_headers
:
headers
.
append
(
"%s: %s"
%
(
header
,
connection_headers
[
header
]
)
)
headers
.
append
(
"Host: streaming.campfirenow.com"
)
self
.
transport
.
write
(
"\r\n"
.
join
(
headers
)
+
"\r\n\r\n"
)
self
.
factory
.
get_stream
(
)
.
set_protocol
(
self
)

Called when a connection is made and used to send out headers


def lineReceived(self, line):
        """ Callback issued by twisted when new line arrives.

        Args:
            line (str): Incoming line
        """
        while self._in_header:
            if line:
                self._headers.append(line)
            else:
                http, status, message = self._headers[0].split(" ", 2)
                status = int(status)
                if status == 200:
                    self.factory.get_stream().connected()
                else:
                    self.factory.continueTrying = 0
                    self.transport.loseConnection()
                    self.factory.get_stream().disconnected(RuntimeError(status, message))
                    return

                self._in_header = False
            break
        else:
            try:
                self._len_expected = int(line, 16)
                self.setRawMode()
            except:
                pass

def
lineReceived
(
self
,
line
)
:
while
self
.
_in_header
:
if
line
:
self
.
_headers
.
append
(
line
)
else
:
http
,
status
,
message
=
self
.
_headers
[
0
]
.
split
(
" "
,
2
)
status
=
int
(
status
)
if
status
==
200
:
self
.
factory
.
get_stream
(
)
.
connected
(
)
else
:
self
.
factory
.
continueTrying
=
0
self
.
transport
.
loseConnection
(
)
self
.
factory
.
get_stream
(
)
.
disconnected
(
RuntimeError
(
status
,
message
)
)
return
self
.
_in_header
=
False
break
else
:
try
:
self
.
_len_expected
=
int
(
line
,
16
)
self
.
setRawMode
(
)
except
:
pass

Callback issued by twisted when new line arrives .


def rawDataReceived(self, data):
        """ Process data.

        Args:
            data (str): Incoming data
        """
        if self._len_expected is not None:
            data, extra = data[:self._len_expected], data[self._len_expected:]
            self._len_expected -= len(data)
        else:
            extra = ""

        self._buffer += data
        if self._len_expected == 0:
            data = self._buffer.strip()
            if data:
                lines = data.split("\r")
                for line in lines:
                    try:
                        message = self.factory.get_stream().get_connection().parse(line)
                        if message:
                            self.factory.get_stream().received([message])
                    except ValueError:
                        pass

            self._buffer = ""
            self._len_expected = None
            self.setLineMode(extra)

def rawDataReceived ( self , data ) : if self . _len_expected is not None : data , extra = data [ : self . _len_expected ] , data [ self . _len_expected : ] self . _len_expected -= len ( data ) else : extra = "" self . _buffer += data if self . _len_expected == 0 : data = self . _buffer . strip ( ) if data : lines = data . split ( "\r" ) for line in lines : try : message = self . factory . get_stream ( ) . get_connection ( ) . parse ( line ) if message : self . factory . get_stream ( ) . received ( [ message ] ) except ValueError : pass self . _buffer = "" self . _len_expected = None self . setLineMode ( extra )


def styles(self):
        """Get a dictionary of CSL styles."""
        styles = get_all_styles()
        whitelist = self.app.config.get('CSL_STYLES_WHITELIST')
        if whitelist:
            return {k: v for k, v in styles.items() if k in whitelist}
        return styles

def styles ( self ) : styles = get_all_styles ( ) whitelist = self . app . config . get ( 'CSL_STYLES_WHITELIST' ) if whitelist : return { k : v for k , v in styles . items ( ) if k in whitelist } return styles


def startProducing(self, consumer):
        """ Start producing.

        Args:
            consumer: Consumer
        """
        self._consumer = consumer
        self._current_deferred = defer.Deferred()
        self._sent = 0
        self._paused = False

        if not hasattr(self, "_chunk_headers"):
            self._build_chunk_headers()

        if self._data:
            block = ""
            for field in self._data:
                block += self._chunk_headers[field]
                block += self._data[field]
                block += "\r\n"

            self._send_to_consumer(block)

        if self._files:
            self._files_iterator = self._files.iterkeys()
            self._files_sent = 0
            self._files_length = len(self._files)
            self._current_file_path = None
            self._current_file_handle = None
            self._current_file_length = None
            self._current_file_sent = 0

            result = self._produce()
            if result:
                return result
        else:
            return defer.succeed(None)

        return self._current_deferred

def startProducing ( self , consumer ) : self . _consumer = consumer self . _current_deferred = defer . Deferred ( ) self . _sent = 0 self . _paused = False if not hasattr ( self , "_chunk_headers" ) : self . _build_chunk_headers ( ) if self . _data : block = "" for field in self . _data : block += self . _chunk_headers [ field ] block += self . _data [ field ] block += "\r\n" self . _send_to_consumer ( block ) if self . _files : self . _files_iterator = self . _files . iterkeys ( ) self . _files_sent = 0 self . _files_length = len ( self . _files ) self . _current_file_path = None self . _current_file_handle = None self . _current_file_length = None self . _current_file_sent = 0 result = self . _produce ( ) if result : return result else : return defer . succeed ( None ) return self . _current_deferred


def _finish(self, forced=False):
        """ Cleanup code after asked to stop producing.

        Kwargs:
            forced (bool): If True, we were forced to stop
        """
        if hasattr(self, "_current_file_handle") and self._current_file_handle:
            self._current_file_handle.close()

        if self._current_deferred:
            self._current_deferred.callback(self._sent)
            self._current_deferred = None

        if not forced and self._deferred:
            self._deferred.callback(self._sent)

def _finish ( self , forced = False ) : if hasattr ( self , "_current_file_handle" ) and self . _current_file_handle : self . _current_file_handle . close ( ) if self . _current_deferred : self . _current_deferred . callback ( self . _sent ) self . _current_deferred = None if not forced and self . _deferred : self . _deferred . callback ( self . _sent )

Cleanup code after asked to stop producing .


def _send_to_consumer(self, block):
        """ Send a block of bytes to the consumer.

        Args:
            block (str): Block of bytes
        """
        self._consumer.write(block)
        self._sent += len(block)
        if self._callback:
            self._callback(self._sent, self.length)

def _send_to_consumer ( self , block ) : self . _consumer . write ( block ) self . _sent += len ( block ) if self . _callback : self . _callback ( self . _sent , self . length )


def _length(self):
        """ Returns total length for this request.

        Returns:
            int. Length
        """
        self._build_chunk_headers()

        length = 0

        if self._data:
            for field in self._data:
                length += len(self._chunk_headers[field])
                length += len(self._data[field])
                length += 2

        if self._files:
            for field in self._files:
                length += len(self._chunk_headers[field])
                length += self._file_size(field)
                length += 2

        length += len(self.boundary)
        length += 6

        return length

def _length ( self ) : self . _build_chunk_headers ( ) length = 0 if self . _data : for field in self . _data : length += len ( self . _chunk_headers [ field ] ) length += len ( self . _data [ field ] ) length += 2 if self . _files : for field in self . _files : length += len ( self . _chunk_headers [ field ] ) length += self . _file_size ( field ) length += 2 length += len ( self . boundary ) length += 6 return length


def _build_chunk_headers(self):
        """ Build headers for each field. """
        if hasattr(self, "_chunk_headers") and self._chunk_headers:
            return

        self._chunk_headers = {}
        for field in self._files:
            self._chunk_headers[field] = self._headers(field, True)
        for field in self._data:
            self._chunk_headers[field] = self._headers(field)

def _build_chunk_headers ( self ) : if hasattr ( self , "_chunk_headers" ) and self . _chunk_headers : return self . _chunk_headers = { } for field in self . _files : self . _chunk_headers [ field ] = self . _headers ( field , True ) for field in self . _data : self . _chunk_headers [ field ] = self . _headers ( field )


def _file_size(self, field):
        """ Returns the file size for given file field.

        Args:
            field (str): File field

        Returns:
            int. File size
        """
        size = 0
        try:
            handle = open(self._files[field], "r")
            size = os.fstat(handle.fileno()).st_size
            handle.close()
        except:
            size = 0
        self._file_lengths[field] = size
        return self._file_lengths[field]

def _file_size ( self , field ) : size = 0 try : handle = open ( self . _files [ field ] , "r" ) size = os . fstat ( handle . fileno ( ) ) . st_size handle . close ( ) except : size = 0 self . _file_lengths [ field ] = size return self . _file_lengths [ field ]

Returns the file size for given file field .


def _filename(draw, result_type=None):
    """Generate a path value of type result_type.

    result_type can either be bytes or text_type

    """
    # Various ASCII chars have a special meaning for the operating system,
    # so make them more common
    ascii_char = characters(min_codepoint=0x01, max_codepoint=0x7f)
    if os.name == 'nt':  # pragma: no cover
        # Windows paths can contain all surrogates and even surrogate pairs
        # if two paths are concatenated. This makes it more likely for them to
        # be generated.
        surrogate = characters(
            min_codepoint=0xD800, max_codepoint=0xDFFF)
        uni_char = characters(min_codepoint=0x1)
        text_strategy = text(
            alphabet=one_of(uni_char, surrogate, ascii_char))

        def text_to_bytes(path):
            fs_enc = sys.getfilesystemencoding()
            try:
                return path.encode(fs_enc, 'surrogatepass')
            except UnicodeEncodeError:
                return path.encode(fs_enc, 'replace')

        bytes_strategy = text_strategy.map(text_to_bytes)
    else:
        latin_char = characters(min_codepoint=0x01, max_codepoint=0xff)
        bytes_strategy = text(alphabet=one_of(latin_char, ascii_char)).map(
            lambda t: t.encode('latin-1'))

        unix_path_text = bytes_strategy.map(
            lambda b: b.decode(
                sys.getfilesystemencoding(),
                'surrogateescape' if PY3 else 'ignore'))

        # Two surrogates generated through surrogateescape can generate
        # a valid utf-8 sequence when encoded and result in a different
        # code point when decoded again. Can happen when two paths get
        # concatenated. Shuffling makes it possible to generate such a case.
        text_strategy = permutations(draw(unix_path_text)).map(u"".join)

    if result_type is None:
        return draw(one_of(bytes_strategy, text_strategy))
    elif result_type is bytes:
        return draw(bytes_strategy)
    else:
        return draw(text_strategy)

Generate a path value of type result_type .


def _str_to_path(s, result_type):
    """Given an ASCII str, returns a path of the given type."""

    assert isinstance(s, str)
    if isinstance(s, bytes) and result_type is text_type:
        return s.decode('ascii')
    elif isinstance(s, text_type) and result_type is bytes:
        return s.encode('ascii')
    return s

def _str_to_path ( s , result_type ) : assert isinstance ( s , str ) if isinstance ( s , bytes ) and result_type is text_type : return s . decode ( 'ascii' ) elif isinstance ( s , text_type ) and result_type is bytes : return s . encode ( 'ascii' ) return s

Given an ASCII str returns a path of the given type .


def _path_root(draw, result_type):
    """Generates a root component for a path."""

    # Based on https://en.wikipedia.org/wiki/Path_(computing)

    def tp(s=''):
        return _str_to_path(s, result_type)

    if os.name != 'nt':
        return tp(os.sep)

    sep = sampled_from([os.sep, os.altsep or os.sep]).map(tp)
    name = _filename(result_type)
    char = characters(min_codepoint=ord("A"), max_codepoint=ord("z")).map(
        lambda c: tp(str(c)))

    relative = sep
    # [drive_letter]:\
    drive = builds(lambda *x: tp().join(x), char, just(tp(':')), sep)
    # \\?\[drive_spec]:\
    extended = builds(
        lambda *x: tp().join(x), sep, sep, just(tp('?')), sep, drive)

    network = one_of([
        # \\[server]\[sharename]\
        builds(lambda *x: tp().join(x), sep, sep, name, sep, name, sep),
        # \\?\[server]\[sharename]\
        builds(lambda *x: tp().join(x),
               sep, sep, just(tp('?')), sep, name, sep, name, sep),
        # \\?\UNC\[server]\[sharename]\
        builds(lambda *x: tp().join(x),
               sep, sep, just(tp('?')), sep, just(tp('UNC')), sep, name, sep,
               name, sep),
        # \\.\[physical_device]\
        builds(lambda *x: tp().join(x),
               sep, sep, just(tp('.')), sep, name, sep),
    ])

    final = one_of(relative, drive, extended, network)

    return draw(final)


def fspaths(draw, allow_pathlike=None):
    """A strategy which generates filesystem path values.

    The generated values include everything which the builtin
    :func:`python:open` function accepts i.e. which won't lead to
    :exc:`ValueError` or :exc:`TypeError` being raised.

    Note that the range of the returned values depends on the operating
    system, the Python version, and the filesystem encoding as returned by
    :func:`sys.getfilesystemencoding`.

    :param allow_pathlike:
        If :obj:`python:None` makes the strategy include objects implementing
        the :class:`python:os.PathLike` interface when Python >= 3.6 is used.
        If :obj:`python:False` no pathlike objects will be generated. If
        :obj:`python:True` pathlike will be generated (Python >= 3.6 required)

    :type allow_pathlike: :obj:`python:bool` or :obj:`python:None`

    .. versionadded:: 3.15

    """
    has_pathlike = hasattr(os, 'PathLike')

    if allow_pathlike is None:
        allow_pathlike = has_pathlike
    if allow_pathlike and not has_pathlike:
        raise InvalidArgument(
            'allow_pathlike: os.PathLike not supported, use None instead '
            'to enable it only when available')

    result_type = draw(sampled_from([bytes, text_type]))

    def tp(s=''):
        return _str_to_path(s, result_type)

    special_component = sampled_from([tp(os.curdir), tp(os.pardir)])
    normal_component = _filename(result_type)
    path_component = one_of(normal_component, special_component)
    extension = normal_component.map(lambda f: tp(os.extsep) + f)
    root = _path_root(result_type)

    def optional(st):
        return one_of(st, just(result_type()))

    sep = sampled_from([os.sep, os.altsep or os.sep]).map(tp)
    path_part = builds(lambda s, l: s.join(l), sep, lists(path_component))
    main_strategy = builds(lambda *x: tp().join(x),
                           optional(root), path_part, optional(extension))

    if allow_pathlike and hasattr(os, 'fspath'):
        pathlike_strategy = main_strategy.map(lambda p: _PathLike(p))
        main_strategy = one_of(main_strategy, pathlike_strategy)

    return draw(main_strategy)

A strategy which generates filesystem path values .


def _exec(self, globals_dict=None):
        """exec compiled code"""
        globals_dict = globals_dict or {}
        globals_dict.setdefault('__builtins__', {})
        exec(self._code, globals_dict)
        return globals_dict

def _exec ( self , globals_dict = None ) : globals_dict = globals_dict or { } globals_dict . setdefault ( '__builtins__' , { } ) exec ( self . _code , globals_dict ) return globals_dict


def handle_extends(self, text):
        """replace all blocks in extends with current blocks"""
        match = self.re_extends.match(text)
        if match:
            extra_text = self.re_extends.sub('', text, count=1)
            blocks = self.get_blocks(extra_text)
            path = os.path.join(self.base_dir, match.group('path'))
            with open(path, encoding='utf-8') as fp:
                return self.replace_blocks_in_extends(fp.read(), blocks)
        else:
            return None

def handle_extends ( self , text ) : match = self . re_extends . match ( text ) if match : extra_text = self . re_extends . sub ( '' , text , count = 1 ) blocks = self . get_blocks ( extra_text ) path = os . path . join ( self . base_dir , match . group ( 'path' ) ) with open ( path , encoding = 'utf-8' ) as fp : return self . replace_blocks_in_extends ( fp . read ( ) , blocks ) else : return None


def flush_buffer(self):
        """flush all buffered string into code"""
        self.code_builder.add_line('{0}.extend([{1}])',
                                   self.result_var, ','.join(self.buffered))
        self.buffered = []

def flush_buffer ( self ) : self . code_builder . add_line ( '{0}.extend([{1}])' , self . result_var , ',' . join ( self . buffered ) ) self . buffered = [ ]


def add_data(self, data):
        """ Add POST data.

        Args:
            data (dict): key => value dictionary
        """
        if not self._data:
            self._data = {}
        self._data.update(data)

def add_data ( self , data ) : if not self . _data : self . _data = { } self . _data . update ( data )


def log_error(self, text: str) -> None:
        '''
        Given some error text it will log the text if self.log_errors is True

        :param text: Error text to log
        '''
        if self.log_errors:
            with self._log_fp.open('a+') as log_file:
                log_file.write(f'{text}\n')

def log_error ( self , text : str ) -> None : if self . log_errors : with self . _log_fp . open ( 'a+' ) as log_file : log_file . write ( f'{text}\n' )

Given some error text it will log the text if self . log_errors is True


def parse_conll(self, texts: List[str], retry_count: int = 0) -> List[str]:
        '''
        Processes the texts using TweeboParse and returns them in CoNLL format.

        :param texts: The List of Strings to be processed by TweeboParse.
        :param retry_count: The number of times it has retried for. Default
                            0 does not require setting, main purpose is for
                            recursion.
        :return: A list of CoNLL formated strings.
        :raises ServerError: Caused when the server is not running.
        :raises :py:class:`requests.exceptions.HTTPError`: Caused when the
                input texts is not formated correctly e.g. When you give it a
                String not a list of Strings.
        :raises :py:class:`json.JSONDecodeError`: Caused if after self.retries
                attempts to parse the data it cannot decode the data.

        :Example:

        '''
        post_data = {'texts': texts, 'output_type': 'conll'}
        try:
            response = requests.post(f'http://{self.hostname}:{self.port}',
                                     json=post_data,
                                     headers={'Connection': 'close'})
            response.raise_for_status()
        except (requests.exceptions.ConnectionError,
                requests.exceptions.Timeout) as server_error:
            raise ServerError(server_error, self.hostname, self.port)
        except requests.exceptions.HTTPError as http_error:
            raise http_error
        else:
            try:
                return response.json()
            except json.JSONDecodeError as json_exception:
                if retry_count == self.retries:
                    self.log_error(response.text)
                    raise Exception('Json Decoding error cannot parse this '
                                    f':\n{response.text}')
                return self.parse_conll(texts, retry_count + 1)

Processes the texts using TweeboParse and returns them in CoNLL format .


def set_data(self, data={}, datetime_fields=[]):
        """ Set entity data

        Args:
            data (dict): Entity data
            datetime_fields (array): Fields that should be parsed as datetimes
        """
        if datetime_fields:
            for field in datetime_fields:
                if field in data:
                    data[field] = self._parse_datetime(data[field])

        super(CampfireEntity, self).set_data(data)

def set_data ( self , data = { } , datetime_fields = [ ] ) : if datetime_fields : for field in datetime_fields : if field in data : data [ field ] = self . _parse_datetime ( data [ field ] ) super ( CampfireEntity , self ) . set_data ( data )


def validate_xml_text(text):
    """validates XML text"""
    bad_chars = __INVALID_XML_CHARS & set(text)
    if bad_chars:
        for offset,c in enumerate(text):
            if c in bad_chars:
                raise RuntimeError('invalid XML character: ' + repr(c) + ' at offset ' + str(offset))

def
validate_xml_text
(
text
)
:
bad_chars
=
__INVALID_XML_CHARS
&
set
(
text
)
if
bad_chars
:
for
offset
,
c
in
enumerate
(
text
)
:
if
c
in
bad_chars
:
raise
RuntimeError
(
'invalid XML character: '
+
repr
(
c
)
+
' at offset '
+
str
(
offset
)
)


def validate_xml_name(name):
    """validates XML name"""
    if len(name) == 0:
        raise RuntimeError('empty XML name')

    if __INVALID_NAME_CHARS & set(name):
        raise RuntimeError('XML name contains invalid character')

    if name[0] in __INVALID_NAME_START_CHARS:
        raise RuntimeError('XML name starts with invalid character')


def on_enter_stage(self):
        """
        Prepare the actors, the world, and the messaging system to begin
        playing the game.

        This method is guaranteed to be called exactly once upon entering the
        game stage.
        """
        with self.world._unlock_temporarily():
            self.forum.connect_everyone(self.world, self.actors)

        # 1. Setup the forum.

        self.forum.on_start_game()

        # 2. Setup the world.

        with self.world._unlock_temporarily():
            self.world.on_start_game()

        # 3. Setup the actors.  Because this is done after the forum and the
        #    world have been setup, this signals to the actors that they can
        #    send messages and query the game world as usual.

        num_players = len(self.actors) - 1

        for actor in self.actors:
            actor.on_setup_gui(self.gui)

        for actor in self.actors:
            actor.on_start_game(num_players)

Prepare the actors the world and the messaging system to begin playing the game . This method is guaranteed to be called exactly once upon entering the game stage .


def on_update_stage(self, dt):
        """
        Sequentially update the actors, the world, and the messaging system.
        The theater terminates once all of the actors indicate that they are done.
        """

        for actor in self.actors:
            actor.on_update_game(dt)

        self.forum.on_update_game()

        with self.world._unlock_temporarily():
            self.world.on_update_game(dt)

        if self.world.has_game_ended():
            self.exit_stage()

def on_update_stage ( self , dt ) : for actor in self . actors : actor . on_update_game ( dt ) self . forum . on_update_game ( ) with self . world . _unlock_temporarily ( ) : self . world . on_update_game ( dt ) if self . world . has_game_ended ( ) : self . exit_stage ( )

Sequentially update the actors the world and the messaging system . The theater terminates once all of the actors indicate that they are done .


def on_exit_stage(self):
        """
        Give the actors, the world, and the messaging system a chance to react
        to the end of the game.
        """

        # 1. Let the forum react to the end of the game.  Local forums don't
        #    react to this, but remote forums take the opportunity to stop
        #    trying to extract tokens from messages.

        self.forum.on_finish_game()

        # 2. Let the actors react to the end of the game.

        for actor in self.actors:
            actor.on_finish_game()

        # 3. Let the world react to the end of the game.

        with self.world._unlock_temporarily():
            self.world.on_finish_game()

Give the actors the world and the messaging system a chance to react to the end of the game .


def render_vars(self):
        """Template variables."""
        return {
            'records': [
                {
                    'message': record.getMessage(),
                    'time': dt.datetime.fromtimestamp(record.created).strftime('%H:%M:%S'),
                } for record in self.handler.records
            ]
        }

def render_vars ( self ) : return { 'records' : [ { 'message' : record . getMessage ( ) , 'time' : dt . datetime . fromtimestamp ( record . created ) . strftime ( '%H:%M:%S' ) , } for record in self . handler . records ] }


def init_async(self, loop=None):
        """Use when application is starting."""
        self._loop = loop or asyncio.get_event_loop()
        self._async_lock = asyncio.Lock(loop=loop)

        # FIX: SQLITE in memory database
        if not self.database == ':memory:':
            self._state = ConnectionLocal()

def
init_async
(
self
,
loop
=
)
:
self
.
_loop
=
loop
or
asyncio
.
get_event_loop
(
)
self
.
_async_lock
=
asyncio
.
Lock
(
loop
=
loop
)
# FIX: SQLITE in memory database
if
not
self
.
database
==
':memory:'
:
self
.
_state
=
ConnectionLocal
(
)


async def async_connect(self):
        """Catch a connection asyncrounosly."""
        if self._async_lock is None:
            raise Exception('Error, database not properly initialized before async connection')

        async with self._async_lock:
            self.connect(True)

        return self._state.conn


def init_async(self, loop):
        """Initialize self."""
        super(PooledAIODatabase, self).init_async(loop)
        self._waiters = collections.deque()

def init_async ( self , loop ) : super ( PooledAIODatabase , self ) . init_async ( loop ) self . _waiters = collections . deque ( )


async def async_connect(self):
        """Asyncronously wait for a connection from the pool."""
        if self._waiters is None:
            raise Exception('Error, database not properly initialized before async connection')

        if self._waiters or self.max_connections and (len(self._in_use) >= self.max_connections):
            waiter = asyncio.Future(loop=self._loop)
            self._waiters.append(waiter)

            try:
                logger.debug('Wait for connection.')
                await waiter
            finally:
                self._waiters.remove(waiter)

        self.connect()
        return self._state.conn

Asyncronously wait for a connection from the pool .


def _close(self, conn):
        """Release waiters."""
        super(PooledAIODatabase, self)._close(conn)
        for waiter in self._waiters:
            if not waiter.done():
                logger.debug('Release a waiter')
                waiter.set_result(True)
                break

def
_close
(
self
,
conn
)
:
super
(
PooledAIODatabase
,
self
)
.
_close
(
conn
)
for
waiter
in
self
.
_waiters
:
if
not
waiter
.
done
(
)
:
logger
.
debug
(
'Release a waiter'
)
waiter
.
set_result
(
True
)
break


def receive_id_from_server(self):
        """
        Listen for an id from the server.

        At the beginning of a game, each client receives an IdFactory from the
        server.  This factory are used to give id numbers that are guaranteed
        to be unique to tokens that created locally.  This method checks to see if such
        a factory has been received.  If it hasn't, this method does not block
        and immediately returns False.  If it has, this method returns True
        after saving the factory internally.  At this point it is safe to enter
        the GameStage.
        """
        for message in self.pipe.receive():
            if isinstance(message, IdFactory):
                self.actor_id_factory = message
                return True
        return False

def receive_id_from_server ( self ) : for message in self . pipe . receive ( ) : if isinstance ( message , IdFactory ) : self . actor_id_factory = message return True return False


def execute_sync(self, message):
        """
        Respond when the server indicates that the client is out of sync.

        The server can request a sync when this client sends a message that
        fails the check() on the server.  If the reason for the failure isn't
        very serious, then the server can decide to send it as usual in the
        interest of a smooth gameplay experience.  When this happens, the
        server sends out an extra response providing the clients with the
        information they need to resync themselves.
        """
        info("synchronizing message: {message}")

        # Synchronize the world.

        with self.world._unlock_temporarily():
            message._sync(self.world)
            self.world._react_to_sync_response(message)

        # Synchronize the tokens.

        for actor in self.actors:
            actor._react_to_sync_response(message)

def
execute_sync
(
self
,
message
)
:
info
(
"synchronizing message: {message}"
)
# Synchronize the world.
with
self
.
world
.
_unlock_temporarily
(
)
:
message
.
_sync
(
self
.
world
)
self
.
world
.
_react_to_sync_response
(
message
)
# Synchronize the tokens.
for
actor
in
self
.
actors
:
actor
.
_react_to_sync_response
(
message
)

Respond when the server indicates that the client is out of sync .


def execute_undo(self, message):
        """
        Manage the response when the server rejects a message.

        An undo is when required this client sends a message that the server
        refuses to pass on to the other clients playing the game.  When this
        happens, the client must undo the changes that the message made to the
        world before being sent or crash.  Note that unlike sync requests, undo
        requests are only reported to the client that sent the offending
        message.
        """
        info("undoing message: {message}")

        # Roll back changes that the original message made to the world.

        with self.world._unlock_temporarily():
            message._undo(self.world)
            self.world._react_to_undo_response(message)

        # Give the actors a chance to react to the error.  For example, a
        # GUI actor might inform the user that there are connectivity
        # issues and that their last action was countermanded.

        for actor in self.actors:
            actor._react_to_undo_response(message)

Manage the response when the server rejects a message .


def _relay_message(self, message):
        """
        Relay messages from the forum on the server to the client represented
        by this actor.
        """
        info("relaying message: {message}")

        if not message.was_sent_by(self._id_factory):
            self.pipe.send(message)
            self.pipe.deliver()

def
_relay_message
(
self
,
message
)
:
info
(
"relaying message: {message}"
)
if
not
message
.
was_sent_by
(
self
.
_id_factory
)
:
self
.
pipe
.
send
(
message
)
self
.
pipe
.
deliver
(
)

Relay messages from the forum on the server to the client represented by this actor .


def generate(request):
    """ Create a new DataItem. """
    models.DataItem.create(
        content=''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(20))
    )
    return muffin.HTTPFound('/')

def generate ( request ) : models . DataItem . create ( content = '' . join ( random . choice ( string . ascii_uppercase + string . digits ) for _ in range ( 20 ) ) ) return muffin . HTTPFound ( '/' )


def require_active_token(object):
    """
    Raise an ApiUsageError if the given object is not a token that is currently
    participating in the game.  To be participating in the game, the given
    token must have an id number and be associated with the world.
    """
    require_token(object)
    token = object

    if not token.has_id:
        raise ApiUsageError("""\
                token {token} should have an id, but doesn't.

                This error usually means that a token was added to the world
                without being assigned an id number.  To correct this, make
                sure that you're using a message (i.e. CreateToken) to create
                all of your tokens.""")

    if not token.has_world:
        raise ApiUsageError("""\
                token {token} (id={token.id}) not in world.

                You can get this error if you try to remove the same token from
                the world twice.  This might happen is you don't get rid of
                every reference to a token after it's removed the first time,
                then later on you try to remove the stale reference.""")

Raise an ApiUsageError if the given object is not a token that is currently participating in the game . To be participating in the game the given token must have an id number and be associated with the world .


def add_safety_checks(meta, members):
        """
        Iterate through each member of the class being created and add a
        safety check to every method that isn't marked as read-only.
        """
        for member_name, member_value in members.items():
            members[member_name] = meta.add_safety_check(
                    member_name, member_value)

def add_safety_checks ( meta , members ) : for member_name , member_value in members . items ( ) : members [ member_name ] = meta . add_safety_check ( member_name , member_value )

Iterate through each member of the class being created and add a safety check to every method that isn t marked as read - only .


def watch_method(self, method_name, callback):
        """
        Register the given callback to be called whenever the method with the
        given name is called.  You can easily take advantage of this feature in
        token extensions by using the @watch_token decorator.
        """

        # Make sure a token method with the given name exists, and complain if
        # nothing is found.

        try:
            method = getattr(self, method_name)
        except AttributeError:
            raise ApiUsageError("""\
                    {self.__class__.__name__} has no such method
                    {method_name}() to watch.

                    This error usually means that you used the @watch_token
                    decorator on a method of a token extension class that
                    didn't match the name of any method in the corresponding
                    token class.  Check for typos.""")

        # Wrap the method in a WatchedMethod object, if that hasn't already
        # been done.  This object manages a list of callback method and takes
        # responsibility for calling them after the method itself has been
        # called.

        if not isinstance(method, Token.WatchedMethod):
            setattr(self, method_name, Token.WatchedMethod(method))
            method = getattr(self, method_name)

        # Add the given callback to the watched method.

        method.add_watcher(callback)

Register the given callback to be called whenever the method with the given name is called . You can easily take advantage of this feature in token extensions by using the


def _remove_from_world(self):
        """
        Clear all the internal data the token needed while it was part of
        the world.

        Note that this method doesn't actually remove the token from the
        world.  That's what World._remove_token() does.  This method is just
        responsible for setting the internal state of the token being removed.
        """
        self.on_remove_from_world()
        self._extensions = {}
        self._disable_forum_observation()
        self._world = None
        self._id = None

def _remove_from_world ( self ) : self . on_remove_from_world ( ) self . _extensions = { } self . _disable_forum_observation ( ) self . _world = None self . _id = None

Clear all the internal data the token needed while it was part of the world .


def _unlock_temporarily(self):
        """
        Allow tokens to modify the world for the duration of a with-block.

        It's important that tokens only modify the world at appropriate times,
        otherwise the changes they make may not be communicated across the
        network to other clients.  To help catch and prevent these kinds of
        errors, the game engine keeps the world locked most of the time and
        only briefly unlocks it (using this method) when tokens are allowed to
        make changes.  When the world is locked, token methods that aren't
        marked as being read-only can't be called.  When the world is unlocked,
        any token method can be called.  These checks can be disabled by
        running python with optimization enabled.

        You should never call this method manually from within your own game.
        This method is intended to be used by the game engine, which was
        carefully designed to allow the world to be modified only when safe.
        Calling this method yourself disables an important safety check.
        """
        if not self._is_locked:
            yield
        else:
            try:
                self._is_locked = False
                yield
            finally:
                self._is_locked = True

def _unlock_temporarily ( self ) : if not self . _is_locked : yield else : try : self . _is_locked = False yield finally : self . _is_locked = True

Allow tokens to modify the world for the duration of a with - block .


def scan(xml):
    """Converts XML tree to event generator"""

    if xml.tag is et.Comment:
        yield {'type': COMMENT, 'text': xml.text}
        return

    if xml.tag is et.PI:
        if xml.text:
            yield {'type': PI, 'target': xml.target, 'text': xml.text}
        else:
            yield {'type': PI, 'target': xml.target}
        return

    obj = _elt2obj(xml)
    obj['type'] = ENTER
    yield obj

    assert type(xml.tag) is str, xml
    if xml.text:
        yield {'type': TEXT, 'text': xml.text}

    for c in xml:
        for x in scan(c): yield x
        if c.tail:
            yield {'type': TEXT, 'text': c.tail}

    yield {'type': EXIT}

def scan ( xml ) : if xml . tag is et . Comment : yield { 'type' : COMMENT , 'text' : xml . text } return if xml . tag is et . PI : if xml . text : yield { 'type' : PI , 'target' : xml . target , 'text' : xml . text } else : yield { 'type' : PI , 'target' : xml . target } return obj = _elt2obj ( xml ) obj [ 'type' ] = ENTER yield obj assert type ( xml . tag ) is str , xml if xml . text : yield { 'type' : TEXT , 'text' : xml . text } for c in xml : for x in scan ( c ) : yield x if c . tail : yield { 'type' : TEXT , 'text' : c . tail } yield { 'type' : EXIT }


def unscan(events, nsmap=None):
    """Converts events stream into lXML tree"""

    root = None
    last_closed_elt = None
    stack = []
    for obj in events:

        if obj['type'] == ENTER:
            elt = _obj2elt(obj, nsmap=nsmap)
            if stack:
                stack[-1].append(elt)
            elif root is not None:
                raise RuntimeError('Event stream tried to create second XML tree')
            else:
                root = elt
            stack.append(elt)
            last_closed_elt = None

        elif obj['type'] == EXIT:
            last_closed_elt = stack.pop()

        elif obj['type'] == COMMENT:
            elt = et.Comment(obj['text'])
            stack[-1].append(elt)

        elif obj['type'] == PI:
            elt = et.PI(obj['target'])
            if obj.get('text'):
                elt.text = obj['text']
            stack[-1].append(elt)

        elif obj['type'] == TEXT:
            text = obj['text']
            if text:
                if last_closed_elt is None:
                    stack[-1].text = (stack[-1].text or '') + text
                else:
                    last_closed_elt.tail = (last_closed_elt.tail or '') + text
        else:
            assert False, obj

    if root is None:
        raise RuntimeError('Empty XML event stream')

    return root