def do_fullscreen(self, line):
        """
        Make the current window fullscreen
        """
        self.bot.canvas.sink.trigger_fullscreen_action(True)
        print(self.response_prompt, file=self.stdout)

def do_fullscreen ( self , line ) : self . bot . canvas . sink . trigger_fullscreen_action ( True ) print ( self . response_prompt , file = self . stdout )


def do_windowed(self, line):
        """
        Un-fullscreen the current window
        """
        self.bot.canvas.sink.trigger_fullscreen_action(False)
        print(self.response_prompt, file=self.stdout)

def do_windowed ( self , line ) : self . bot . canvas . sink . trigger_fullscreen_action ( False ) print ( self . response_prompt , file = self . stdout )


def do_help(self, arg):
        """
        Show help on all commands.
        """
        print(self.response_prompt, file=self.stdout)
        return cmd.Cmd.do_help(self, arg)

def do_help ( self , arg ) : print ( self . response_prompt , file = self . stdout ) return cmd . Cmd . do_help ( self , arg )


def do_set(self, line):
        """
        Set a variable.
        """
        try:
            name, value = [part.strip() for part in line.split('=')]
            if name not in self.bot._vars:
                self.print_response('No such variable %s enter vars to see available vars' % name)
                return
            variable = self.bot._vars[name]
            variable.value = variable.sanitize(value.strip(';'))

            success, msg = self.bot.canvas.sink.var_changed(name, variable.value)
            if success:
                print('{}={}'.format(name, variable.value), file=self.stdout)
            else:
                print('{}\n'.format(msg), file=self.stdout)
        except Exception as e:
            print('Invalid Syntax.', e)
            return


def precmd(self, line):
        """
        Allow commands to have a last parameter of 'cookie=somevalue'

        TODO somevalue will be prepended onto any output lines so
        that editors can distinguish output from certain kinds
        of events they have sent.

        :param line:
        :return:
        """
        args = shlex.split(line or "")
        if args and 'cookie=' in args[-1]:
            cookie_index = line.index('cookie=')
            cookie = line[cookie_index + 7:]
            line = line[:cookie_index].strip()
            self.cookie = cookie
        if line.startswith('#'):
            return ''
        elif '=' in line:
            # allow  somevar=somevalue

            # first check if we really mean a command
            cmdname = line.partition(" ")[0]
            if hasattr(self, "do_%s" % cmdname):
                return line

            if not line.startswith("set "):
                return "set " + line
            else:
                return line
        if len(args) and args[0] in self.shortcuts:
            return "%s %s" % (self.shortcuts[args[0]], " ".join(args[1:]))
        else:
            return line

Allow commands to have a last parameter of cookie = somevalue


def drawdaisy(x, y, color='#fefefe'):
    """
    Draw a daisy at x, y
    """
    # save location, size etc
    _ctx.push()

    # save fill and stroke
    _fill =_ctx.fill()
    _stroke = _ctx.stroke()

    sc = (1.0 / _ctx.HEIGHT) * float(y * 0.5) * 4.0

    # draw stalk
    _ctx.strokewidth(sc * 2.0)
    _ctx.stroke('#3B240B')

    _ctx.line(x + (sin(x * 0.1) * 10.0), y + 80, x + sin(_ctx.FRAME * 0.1), y)

    # draw flower
    _ctx.translate(-20, 0)
    _ctx.scale(sc)

    # draw petals
    _ctx.fill(color)
    _ctx.nostroke()
    for angle in xrange(0, 360, 45):
        _ctx.rotate(degrees=45)
        _ctx.rect(x, y, 40, 8, 1)

    # draw centre
    _ctx.fill('#F7FE2E')
    _ctx.ellipse(x + 15, y, 10, 10)

    # restore fill and stroke
    _ctx.fill(_fill)
    _ctx.stroke(_stroke)

    # restore location, size etc
    _ctx.pop()

def
drawdaisy
(
x
,
y
,
color
=
'#fefefe'
)
:
# save location, size etc
_ctx
.
push
(
)
# save fill and stroke
_fill
=
_ctx
.
fill
(
)
_stroke
=
_ctx
.
stroke
(
)
sc
=
(
1.0
/
_ctx
.
HEIGHT
)
*
float
(
y
*
0.5
)
*
4.0
# draw stalk
_ctx
.
strokewidth
(
sc
*
2.0
)
_ctx
.
stroke
(
'#3B240B'
)
_ctx
.
line
(
x
+
(
sin
(
x
*
0.1
)
*
10.0
)
,
y
+
80
,
x
+
sin
(
_ctx
.
FRAME
*
0.1
)
,
y
)
# draw flower
_ctx
.
translate
(
20
,
0
)
_ctx
.
scale
(
sc
)
# draw petals
_ctx
.
fill
(
color
)
_ctx
.
nostroke
(
)
for
angle
in
xrange
(
0
,
360
,
45
)
:
_ctx
.
rotate
(
degrees
=
45
)
_ctx
.
rect
(
x
,
y
,
40
,
8
,
1
)
# draw centre
_ctx
.
fill
(
'#F7FE2E'
)
_ctx
.
ellipse
(
x
+
15
,
y
,
10
,
10
)
# restore fill and stroke
_ctx
.
fill
(
_fill
)
_ctx
.
stroke
(
_stroke
)
# restore location, size etc
_ctx
.
pop
(
)


def get_source(self, doc):
        """
        Grab contents of 'doc' and return it

        :param doc: The active document
        :return:
        """
        start_iter = doc.get_start_iter()
        end_iter = doc.get_end_iter()
        source = doc.get_text(start_iter, end_iter, False)
        return source

def get_source ( self , doc ) : start_iter = doc . get_start_iter ( ) end_iter = doc . get_end_iter ( ) source = doc . get_text ( start_iter , end_iter , False ) return source


def loadGrammar(self, grammar, searchpaths=None):
        """load context-free grammar"""
        self.grammar = self._load(grammar, searchpaths=searchpaths)
        self.refs = {}
        for ref in self.grammar.getElementsByTagName("ref"):
            self.refs[ref.attributes["id"].value] = ref

def loadGrammar ( self , grammar , searchpaths = None ) : self . grammar = self . _load ( grammar , searchpaths = searchpaths ) self . refs = { } for ref in self . grammar . getElementsByTagName ( "ref" ) : self . refs [ ref . attributes [ "id" ] . value ] = ref


def refresh(self):
        """reset output buffer, re-parse entire source file, and return output

        Since parsing involves a good deal of randomness, this is an
        easy way to get new output without having to reload a grammar file
        each time.
        """
        self.reset()
        self.parse(self.source)
        return self.output()

def refresh ( self ) : self . reset ( ) self . parse ( self . source ) return self . output ( )

reset output buffer re - parse entire source file and return output Since parsing involves a good deal of randomness this is an easy way to get new output without having to reload a grammar file each time .


def randomChildElement(self, node):
        """choose a random child element of a node

        This is a utility method used by do_xref and do_choice.
        """
        choices = [e for e in node.childNodes
                   if e.nodeType == e.ELEMENT_NODE]
        chosen = random.choice(choices)
        if _debug:
            sys.stderr.write('%s available choices: %s\n' % \
                (len(choices), [e.toxml() for e in choices]))
            sys.stderr.write('Chosen: %s\n' % chosen.toxml())
        return chosen

def
randomChildElement
(
self
,
node
)
:
choices
=
[
e
for
e
in
node
.
childNodes
if
e
.
nodeType
==
e
.
ELEMENT_NODE
]
chosen
=
random
.
choice
(
choices
)
if
_debug
:
sys
.
stderr
.
write
(
'%s available choices: %s\n'
%
(
len
(
choices
)
,
[
e
.
toxml
(
)
for
e
in
choices
]
)
)
sys
.
stderr
.
write
(
'Chosen: %s\n'
%
chosen
.
toxml
(
)
)
return
chosen

choose a random child element of a node This is a utility method used by do_xref and do_choice .


def replace_entities(ustring, placeholder=" "):

    """Replaces HTML special characters by readable characters.

    As taken from Leif K-Brooks algorithm on:
    http://groups-beta.google.com/group/comp.lang.python

    """

    def _repl_func(match):
        try:
            if match.group(1): # Numeric character reference
                return unichr( int(match.group(2)) )
            else:
                try: return cp1252[ unichr(int(match.group(3))) ].strip()
                except: return unichr( name2codepoint[match.group(3)] )
        except:
            return placeholder

    # Force to Unicode.
    if not isinstance(ustring, unicode):
        ustring = UnicodeDammit(ustring).unicode

    # Don't want some weird unicode character here
    # that truncate_spaces() doesn't know of:
    ustring = ustring.replace(" ", " ")

    # The ^> makes sure nothing inside a tag (i.e. href with query arguments) gets processed.
    _entity_re = re.compile(r'&(?:(#)(\d+)|([^;^> ]+));')
    return _entity_re.sub(_repl_func, ustring)

Replaces HTML special characters by readable characters .


def not_found(url, wait=10):

    """ Returns True when the url generates a "404 Not Found" error.
    """

    try: connection = open(url, wait)
    except HTTP404NotFound:
        return True
    except:
        return False

    return False

def not_found ( url , wait = 10 ) : try : connection = open ( url , wait ) except HTTP404NotFound : return True except : return False return False

Returns True when the url generates a 404 Not Found error .


def is_type(url, types=[], wait=10):

    """ Determine the MIME-type of the document behind the url.

    MIME is more reliable than simply checking the document extension.
    Returns True when the MIME-type starts with anything in the list of types.

    """

    # Types can also be a single string for convenience.
    if isinstance(types, str):
        types = [types]

    try: connection = open(url, wait)
    except:
        return False

    type = connection.info()["Content-Type"]
    for t in types:
        if type.startswith(t): return True

    return False

Determine the MIME - type of the document behind the url .


def requirements(debug=True, with_examples=True, with_pgi=None):
    """
    Build requirements based on flags

    :param with_pgi: Use 'pgi' instead of 'gi' - False on CPython, True elsewhere
    :param with_examples:
    :return:
    """
    reqs = list(BASE_REQUIREMENTS)
    if with_pgi is None:
        with_pgi = is_jython

    if debug:
        print("setup options: ")
        print("with_pgi:      ", "yes" if with_pgi else "no")
        print("with_examples: ", "yes" if with_examples else "no")
    if with_pgi:
        reqs.append("pgi")
        if debug:
            print("warning, as of April 2019 typography does not work with pgi")
    else:
        reqs.append(PYGOBJECT)

    if with_examples:
        reqs.extend(EXAMPLE_REQUIREMENTS)

    if debug:
        print("")
        print("")
        for req in reqs:
            print(req)
    return reqs


def image(self, path, x, y, width=None, height=None, alpha=1.0, data=None, draw=True, **kwargs):
        '''Draws a image form path, in x,y and resize it to width, height dimensions.
        '''
        return self.Image(path, x, y, width, height, alpha, data, **kwargs)

def image ( self , path , x , y , width = None , height = None , alpha = 1.0 , data = None , draw = True , * * kwargs ) : return self . Image ( path , x , y , width , height , alpha , data , * * kwargs )

Draws a image form path in x y and resize it to width height dimensions .


def rect(self, x, y, width, height, roundness=0.0, draw=True, **kwargs):
        '''
        Draw a rectangle from x, y of width, height.

        :param startx: top left x-coordinate
        :param starty: top left y-coordinate

        :param width: height  Size of rectangle.
        :roundness: Corner roundness defaults to 0.0 (a right-angle).
        :draw: If True draws immediately.
        :fill: Optionally pass a fill color.

        :return: path representing the rectangle.

        '''
        path = self.BezierPath(**kwargs)
        path.rect(x, y, width, height, roundness, self.rectmode)
        if draw:
            path.draw()
        return path

def rect ( self , x , y , width , height , roundness = 0.0 , draw = True , * * kwargs ) : path = self . BezierPath ( * * kwargs ) path . rect ( x , y , width , height , roundness , self . rectmode ) if draw : path . draw ( ) return path

Draw a rectangle from x y of width height .


def rectmode(self, mode=None):
        '''
        Set the current rectmode.

        :param mode: CORNER, CENTER, CORNERS
        :return: rectmode if mode is None or valid.
        '''
        if mode in (self.CORNER, self.CENTER, self.CORNERS):
            self.rectmode = mode
            return self.rectmode
        elif mode is None:
            return self.rectmode
        else:
            raise ShoebotError(_("rectmode: invalid input"))

def
rectmode
(
self
,
mode
=
)
:
if
mode
in
(
self
.
CORNER
,
self
.
CENTER
,
self
.
CORNERS
)
:
self
.
rectmode
=
mode
return
self
.
rectmode
elif
mode
is
:
return
self
.
rectmode
else
:
raise
ShoebotError
(
_
(
"rectmode: invalid input"
)
)


def ellipsemode(self, mode=None):
        '''
        Set the current ellipse drawing mode.

        :param mode: CORNER, CENTER, CORNERS
        :return: ellipsemode if mode is None or valid.
        '''
        if mode in (self.CORNER, self.CENTER, self.CORNERS):
            self.ellipsemode = mode
            return self.ellipsemode
        elif mode is None:
            return self.ellipsemode
        else:
            raise ShoebotError(_("ellipsemode: invalid input"))

def
ellipsemode
(
self
,
mode
=
)
:
if
mode
in
(
self
.
CORNER
,
self
.
CENTER
,
self
.
CORNERS
)
:
self
.
ellipsemode
=
mode
return
self
.
ellipsemode
elif
mode
is
:
return
self
.
ellipsemode
else
:
raise
ShoebotError
(
_
(
"ellipsemode: invalid input"
)
)


def arrow(self, x, y, width, type=NORMAL, draw=True, **kwargs):
        '''Draw an arrow.

        Arrows can be two types: NORMAL or FORTYFIVE.

        :param x: top left x-coordinate
        :param y: top left y-coordinate
        :param width: width of arrow
        :param type:  NORMAL or FORTYFIVE
        :draw:  If True draws arrow immediately

        :return: Path object representing the arrow.
        '''
        # Taken from Nodebox
        path = self.BezierPath(**kwargs)
        if type == self.NORMAL:
            head = width * .4
            tail = width * .2
            path.moveto(x, y)
            path.lineto(x - head, y + head)
            path.lineto(x - head, y + tail)
            path.lineto(x - width, y + tail)
            path.lineto(x - width, y - tail)
            path.lineto(x - head, y - tail)
            path.lineto(x - head, y - head)
            path.lineto(x, y)
        elif type == self.FORTYFIVE:
            head = .3
            tail = 1 + head
            path.moveto(x, y)
            path.lineto(x, y + width * (1 - head))
            path.lineto(x - width * head, y + width)
            path.lineto(x - width * head, y + width * tail * .4)
            path.lineto(x - width * tail * .6, y + width)
            path.lineto(x - width, y + width * tail * .6)
            path.lineto(x - width * tail * .4, y + width * head)
            path.lineto(x - width, y + width * head)
            path.lineto(x - width * (1 - head), y)
            path.lineto(x, y)
        else:
            raise NameError(_("arrow: available types for arrow() are NORMAL and FORTYFIVE\n"))
        if draw:
            path.draw()
        return path


def star(self, startx, starty, points=20, outer=100, inner=50, draw=True, **kwargs):
        '''Draws a star.
        '''
        # Taken from Nodebox.
        self.beginpath(**kwargs)
        self.moveto(startx, starty + outer)

        for i in range(1, int(2 * points)):
            angle = i * pi / points
            x = sin(angle)
            y = cos(angle)
            if i % 2:
                radius = inner
            else:
                radius = outer
            x = startx + radius * x
            y = starty + radius * y
            self.lineto(x, y)

        return self.endpath(draw)

def
star
(
self
,
startx
,
starty
,
points
=
20
,
outer
=
100
,
inner
=
50
,
draw
=
True
,
*
*
kwargs
)
:
# Taken from Nodebox.
self
.
beginpath
(
*
*
kwargs
)
self
.
moveto
(
startx
,
starty
+
outer
)
for
i
in
range
(
1
,
int
(
2
*
points
)
)
:
angle
=
i
*
pi
/
points
x
=
sin
(
angle
)
y
=
cos
(
angle
)
if
i
%
2
:
radius
=
inner
else
:
radius
=
outer
x
=
startx
+
radius
*
x
y
=
starty
+
radius
*
y
self
.
lineto
(
x
,
y
)
return
self
.
endpath
(
draw
)


def relmoveto(self, x, y):
        '''Move relatively to the last point.'''
        if self._path is None:
            raise ShoebotError(_("No current path. Use beginpath() first."))
        self._path.relmoveto(x, y)


def rellineto(self, x, y):
        '''Draw a line using relative coordinates.'''
        if self._path is None:
            raise ShoebotError(_("No current path. Use beginpath() first."))
        self._path.rellineto(x, y)

Draw a line using relative coordinates .


def relcurveto(self, h1x, h1y, h2x, h2y, x, y):
        '''Draws a curve relatively to the last point.
        '''
        if self._path is None:
            raise ShoebotError(_("No current path. Use beginpath() first."))
        self._path.relcurveto(h1x, h1y, h2x, h2y, x, y)

Draws a curve relatively to the last point .


def transform(self, mode=None):
        '''
        Set the current transform mode.

        :param mode: CENTER or CORNER'''
        if mode:
            self._canvas.mode = mode
        return self._canvas.mode

def transform ( self , mode = None ) : if mode : self . _canvas . mode = mode return self . _canvas . mode


def scale(self, x=1, y=None):
        '''
        Set a scale at which to draw objects.

        1.0 draws objects at their natural size

        :param x: Scale on the horizontal plane
        :param y: Scale on the vertical plane
        '''
        if not y:
            y = x
        if x == 0:
            # Cairo borks on zero values
            x = 1
        if y == 0:
            y = 1
        self._canvas.scale(x, y)

def
scale
(
self
,
x
=
1
,
y
=
)
:
if
not
y
:
y
=
x
if
x
==
0
:
# Cairo borks on zero values
x
=
1
if
y
==
0
:
y
=
1
self
.
_canvas
.
scale
(
x
,
y
)


def nostroke(self):
        ''' Stop applying strokes to new paths.

        :return: stroke color before nostroke was called.
        '''
        c = self._canvas.strokecolor
        self._canvas.strokecolor = None
        return c

def nostroke ( self ) : c = self . _canvas . strokecolor self . _canvas . strokecolor = None return c


def strokewidth(self, w=None):
        '''Set the stroke width.

        :param w: Stroke width.
        :return: If no width was specified then current width is returned.
        '''
        if w is not None:
            self._canvas.strokewidth = w
        else:
            return self._canvas.strokewidth

def strokewidth ( self , w = None ) : if w is not None : self . _canvas . strokewidth = w else : return self . _canvas . strokewidth


def font(self, fontpath=None, fontsize=None):
        '''Set the font to be used with new text instances.

        :param fontpath: path to truetype or opentype font.
        :param fontsize: size of font

        :return: current current fontpath (if fontpath param not set)
        Accepts TrueType and OpenType files. Depends on FreeType being
        installed.'''
        if fontpath is not None:
            self._canvas.fontfile = fontpath
        else:
            return self._canvas.fontfile
        if fontsize is not None:
            self._canvas.fontsize = fontsize

def font ( self , fontpath = None , fontsize = None ) : if fontpath is not None : self . _canvas . fontfile = fontpath else : return self . _canvas . fontfile if fontsize is not None : self . _canvas . fontsize = fontsize

Set the font to be used with new text instances .


def fontsize(self, fontsize=None):
        '''
        Set or return size of current font.

        :param fontsize: Size of font.
        :return: Size of font (if fontsize was not specified)
        '''
        if fontsize is not None:
            self._canvas.fontsize = fontsize
        else:
            return self._canvas.fontsize

def fontsize ( self , fontsize = None ) : if fontsize is not None : self . _canvas . fontsize = fontsize else : return self . _canvas . fontsize


def text(self, txt, x, y, width=None, height=1000000, outline=False, draw=True, **kwargs):
        '''
        Draws a string of text according to current font settings.

        :param txt: Text to output
        :param x: x-coordinate of the top left corner
        :param y: y-coordinate of the top left corner
        :param width: text width
        :param height: text height
        :param outline: If True draws outline text (defaults to False)
        :param draw: Set to False to inhibit immediate drawing (defaults to True)
        :return: Path object representing the text.
        '''
        txt = self.Text(txt, x, y, width, height, outline=outline, ctx=None, **kwargs)
        if outline:
            path = txt.path
            if draw:
                path.draw()
            return path
        else:
            return txt

def text ( self , txt , x , y , width = None , height = 1000000 , outline = False , draw = True , * * kwargs ) : txt = self . Text ( txt , x , y , width , height , outline = outline , ctx = None , * * kwargs ) if outline : path = txt . path if draw : path . draw ( ) return path else : return txt

Draws a string of text according to current font settings .


def textheight(self, txt, width=None):
        '''Returns the height of a string of text according to the current
        font settings.

        :param txt: string to measure
        :param width: width of a line of text in a block
        '''
        w = width
        return self.textmetrics(txt, width=w)[1]

def textheight ( self , txt , width = None ) : w = width return self . textmetrics ( txt , width = w ) [ 1 ]

Returns the height of a string of text according to the current font settings .


def graph_background(s):

    """ Graph background color.
    """

    if s.background == None:
        s._ctx.background(None)
    else:
        s._ctx.background(s.background)

    if s.depth:
        try:
            clr = colors.color(s.background).darker(0.2)
            p = s._ctx.rect(0, 0, s._ctx.WIDTH, s._ctx.HEIGHT, draw=False)
            colors.gradientfill(p, clr, clr.lighter(0.35))
            colors.shadow(dx=0, dy=0, blur=2, alpha=0.935, clr=s.background)
        except:
            pass

def graph_background ( s ) : if s . background == None : s . _ctx . background ( None ) else : s . _ctx . background ( s . background ) if s . depth : try : clr = colors . color ( s . background ) . darker ( 0.2 ) p = s . _ctx . rect ( 0 , 0 , s . _ctx . WIDTH , s . _ctx . HEIGHT , draw = False ) colors . gradientfill ( p , clr , clr . lighter ( 0.35 ) ) colors . shadow ( dx = 0 , dy = 0 , blur = 2 , alpha = 0.935 , clr = s . background ) except : pass


def node(s, node, alpha=1.0):

    """ Visualization of a default node.
    """

    if s.depth:
        try: colors.shadow(dx=5, dy=5, blur=10, alpha=0.5*alpha)
        except: pass

    s._ctx.nofill()
    s._ctx.nostroke()
    if s.fill:
        s._ctx.fill(
            s.fill.r,
            s.fill.g,
            s.fill.b,
            s.fill.a * alpha
        )
    if s.stroke:
        s._ctx.strokewidth(s.strokewidth)
        s._ctx.stroke(
            s.stroke.r,
            s.stroke.g,
            s.stroke.b,
            s.stroke.a * alpha * 3
        )
    r = node.r
    s._ctx.oval(node.x-r, node.y-r, r*2, r*2)

def node ( s , node , alpha = 1.0 ) : if s . depth : try : colors . shadow ( dx = 5 , dy = 5 , blur = 10 , alpha = 0.5 * alpha ) except : pass s . _ctx . nofill ( ) s . _ctx . nostroke ( ) if s . fill : s . _ctx . fill ( s . fill . r , s . fill . g , s . fill . b , s . fill . a * alpha ) if s . stroke : s . _ctx . strokewidth ( s . strokewidth ) s . _ctx . stroke ( s . stroke . r , s . stroke . g , s . stroke . b , s . stroke . a * alpha * 3 ) r = node . r s . _ctx . oval ( node . x - r , node . y - r , r * 2 , r * 2 )


def node_label(s, node, alpha=1.0):

    """ Visualization of a node's id.
    """

    if s.text:
        #s._ctx.lineheight(1)
        s._ctx.font(s.font)
        s._ctx.fontsize(s.fontsize)
        s._ctx.nostroke()
        s._ctx.fill(
            s.text.r,
            s.text.g,
            s.text.b,
            s.text.a * alpha
        )

        # Cache an outlined label text and translate it.
        # This enhances the speed and avoids wiggling text.
        try: p = node._textpath
        except:
            txt = node.label
            try: txt = unicode(txt)
            except:
                try: txt = txt.decode("utf-8")
                except:
                    pass
            # Abbreviation.
            #root = node.graph.root
            #if txt != root and txt[-len(root):] == root:
            #    txt = txt[:len(txt)-len(root)]+root[0]+"."
            dx, dy = 0, 0
            if s.align == 2: #CENTER
                dx = -s._ctx.textwidth(txt, s.textwidth) / 2
                dy =  s._ctx.textheight(txt) / 2
            node._textpath = s._ctx.textpath(txt, dx, dy, width=s.textwidth)
            p = node._textpath

        if s.depth:
            try: __colors.shadow(dx=2, dy=4, blur=5, alpha=0.3*alpha)
            except: pass

        s._ctx.push()
        s._ctx.translate(node.x, node.y)
        s._ctx.scale(alpha)
        s._ctx.drawpath(p.copy())
        s._ctx.pop()


def edges(s, edges, alpha=1.0, weighted=False, directed=False):

    """ Visualization of the edges in a network.
    """

    p = s._ctx.BezierPath()

    if directed and s.stroke:
        pd = s._ctx.BezierPath()
    if weighted and s.fill:
        pw = [s._ctx.BezierPath() for i in range(11)]

    # Draw the edges in a single BezierPath for speed.
    # Weighted edges are divided into ten BezierPaths,
    # depending on their weight rounded between 0 and 10.
    if len(edges) == 0: return
    for e in edges:
        try:  s2 = e.node1.graph.styles[e.node1.style]
        except: s2 = s
        if s2.edge:
            s2.edge(s2, p, e, alpha)
            if directed and s.stroke:
                s2.edge_arrow(s2, pd, e, radius=10)
            if weighted and s.fill:
                s2.edge(s2, pw[int(e.weight*10)], e, alpha)

    s._ctx.autoclosepath(False)
    s._ctx.nofill()
    s._ctx.nostroke()

    # All weighted edges use the default fill.
    if weighted and s.fill:
        r = e.node1.__class__(None).r
        s._ctx.stroke(
            s.fill.r,
            s.fill.g,
            s.fill.b,
            s.fill.a * 0.65 * alpha
        )
        for w in range(1, len(pw)):
            s._ctx.strokewidth(r*w*0.1)
            s._ctx.drawpath(pw[w].copy())

    # All edges use the default stroke.
    if s.stroke:
        s._ctx.strokewidth(s.strokewidth)

        s._ctx.stroke(
            s.stroke.r,
            s.stroke.g,
            s.stroke.b,
            s.stroke.a * 0.65 * alpha
        )

    s._ctx.drawpath(p.copy())

    if directed and s.stroke:
        #clr = s._ctx.stroke().copy()
	clr=s._ctx.color(
            s.stroke.r,
            s.stroke.g,
            s.stroke.b,
            s.stroke.a * 0.65 * alpha
        )

        clr.a *= 1.3

	s._ctx.stroke(clr)

    	s._ctx.drawpath(pd.copy())

    for e in edges:
        try:  s2 = self.styles[e.node1.style]
        except: s2 = s
        if s2.edge_label:
            s2.edge_label(s2, e, alpha)

Visualization of the edges in a network .


def edge(s, path, edge, alpha=1.0):

    """ Visualization of a single edge between two nodes.
    """

    path.moveto(edge.node1.x, edge.node1.y)
    if edge.node2.style == BACK:
        path.curveto(
            edge.node1.x,
            edge.node2.y,
            edge.node2.x,
            edge.node2.y,
            edge.node2.x,
            edge.node2.y,
        )
    else:
        path.lineto(
            edge.node2.x,
            edge.node2.y
        )

def edge ( s , path , edge , alpha = 1.0 ) : path . moveto ( edge . node1 . x , edge . node1 . y ) if edge . node2 . style == BACK : path . curveto ( edge . node1 . x , edge . node2 . y , edge . node2 . x , edge . node2 . y , edge . node2 . x , edge . node2 . y , ) else : path . lineto ( edge . node2 . x , edge . node2 . y )

Visualization of a single edge between two nodes .


def edge_label(s, edge, alpha=1.0):

    """ Visualization of the label accompanying an edge.
    """

    if s.text and edge.label != "":
        s._ctx.nostroke()
        s._ctx.fill(
            s.text.r,
            s.text.g,
            s.text.b,
            s.text.a * alpha*0.75
        )
        s._ctx.lineheight(1)
        s._ctx.font(s.font)
        s._ctx.fontsize(s.fontsize*0.75)

        # Cache an outlined label text and translate it.
        # This enhances the speed and avoids wiggling text.
        try: p = edge._textpath
        except:
            try: txt = unicode(edge.label)
            except:
                try: txt = edge.label.decode("utf-8")
                except:
                    pass
            edge._textpath = s._ctx.textpath(txt, s._ctx.textwidth(" "), 0, width=s.textwidth)
            p = edge._textpath

        # Position the label centrally along the edge line.
        a  = degrees( atan2(edge.node2.y-edge.node1.y, edge.node2.x-edge.node1.x) )
        d  = sqrt((edge.node2.x-edge.node1.x)**2 +(edge.node2.y-edge.node1.y)**2)
        d  = abs(d-s._ctx.textwidth(edge.label)) * 0.5

        s._ctx.push()
        s._ctx.transform(CORNER)
        s._ctx.translate(edge.node1.x, edge.node1.y)
        s._ctx.rotate(-a)
        s._ctx.translate(d, s.fontsize*1.0)
        s._ctx.scale(alpha)

        # Flip labels on the left hand side so they are legible.
        if 90 < a%360 < 270:
            s._ctx.translate(s._ctx.textwidth(edge.label), -s.fontsize*2.0)
            s._ctx.transform(CENTER)
            s._ctx.rotate(180)
            s._ctx.transform(CORNER)

        s._ctx.drawpath(p.copy())
        s._ctx.pop()

Visualization of the label accompanying an edge .


def path(s, graph, path):

    """ Visualization of a shortest path between two nodes.
    """

    def end(n):
        r = n.r * 0.35
        s._ctx.oval(n.x-r, n.y-r, r*2, r*2)

    if path and len(path) > 1 and s.stroke:

        s._ctx.nofill()
        s._ctx.stroke(
            s.stroke.r,
            s.stroke.g,
            s.stroke.b,
            s.stroke.a
        )
        if s.name != DEFAULT:
            s._ctx.strokewidth(s.strokewidth)
        else:
            s._ctx.strokewidth(s.strokewidth*2)

        first = True
        for id in path:
            n = graph[id]
            if first:
                first = False
                s._ctx.beginpath(n.x, n.y)
                end(n)
            else:
                s._ctx.lineto(n.x, n.y)
        s._ctx.endpath()
        end(n)

def path ( s , graph , path ) : def end ( n ) : r = n . r * 0.35 s . _ctx . oval ( n . x - r , n . y - r , r * 2 , r * 2 ) if path and len ( path ) > 1 and s . stroke : s . _ctx . nofill ( ) s . _ctx . stroke ( s . stroke . r , s . stroke . g , s . stroke . b , s . stroke . a ) if s . name != DEFAULT : s . _ctx . strokewidth ( s . strokewidth ) else : s . _ctx . strokewidth ( s . strokewidth * 2 ) first = True for id in path : n = graph [ id ] if first : first = False s . _ctx . beginpath ( n . x , n . y ) end ( n ) else : s . _ctx . lineto ( n . x , n . y ) s . _ctx . endpath ( ) end ( n )

Visualization of a shortest path between two nodes .


def create(self, stylename, **kwargs):
        """ Creates a new style which inherits from the default style,
        or any other style which name is supplied to the optional template parameter.
        """
        if stylename == "default":
            self[stylename] = style(stylename, self._ctx, **kwargs)
            return self[stylename]
        k = kwargs.get("template", "default")
        s = self[stylename] = self[k].copy(stylename)
        for attr in kwargs:
            if s.__dict__.has_key(attr):
                s.__dict__[attr] = kwargs[attr]
        return s

def create ( self , stylename , * * kwargs ) : if stylename == "default" : self [ stylename ] = style ( stylename , self . _ctx , * * kwargs ) return self [ stylename ] k = kwargs . get ( "template" , "default" ) s = self [ stylename ] = self [ k ] . copy ( stylename ) for attr in kwargs : if s . __dict__ . has_key ( attr ) : s . __dict__ [ attr ] = kwargs [ attr ] return s

Creates a new style which inherits from the default style or any other style which name is supplied to the optional template parameter .


def copy(self, graph):
        """ Returns a copy of all styles and a copy of the styleguide.
        """
        s = styles(graph)
        s.guide = self.guide.copy(graph)
        dict.__init__(s, [(v.name, v.copy()) for v in self.values()])
        return s

def copy ( self , graph ) : s = styles ( graph ) s . guide = self . guide . copy ( graph ) dict . __init__ ( s , [ ( v . name , v . copy ( ) ) for v in self . values ( ) ] ) return s

Returns a copy of all styles and a copy of the styleguide .


def apply(self):
        """ Check the rules for each node in the graph and apply the style.
        """
        sorted = self.order + self.keys()
        unique = []; [unique.append(x) for x in sorted if x not in unique]
        for node in self.graph.nodes:
            for s in unique:
                if self.has_key(s) and self[s](self.graph, node):
                    node.style = s

def apply ( self ) : sorted = self . order + self . keys ( ) unique = [ ] [ unique . append ( x ) for x in sorted if x not in unique ] for node in self . graph . nodes : for s in unique : if self . has_key ( s ) and self [ s ] ( self . graph , node ) : node . style = s

Check the rules for each node in the graph and apply the style .


def copy(self, graph):
        """ Returns a copy of the styleguide for the given graph.
        """
        g = styleguide(graph)
        g.order = self.order
        dict.__init__(g, [(k, v) for k, v in self.iteritems()])
        return g

def copy ( self , graph ) : g = styleguide ( graph ) g . order = self . order dict . __init__ ( g , [ ( k , v ) for k , v in self . iteritems ( ) ] ) return g

Returns a copy of the styleguide for the given graph .


def open_socket(self):
        """
        Opens the socket and binds to the given host and port. Uses
        SO_REUSEADDR to be as robust as possible.
        """
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.socket.setblocking(0)
        self.socket.bind((self.host, self.port))

def open_socket ( self ) : self . socket = socket . socket ( socket . AF_INET , socket . SOCK_DGRAM ) self . socket . setsockopt ( socket . SOL_SOCKET , socket . SO_REUSEADDR , 1 ) self . socket . setblocking ( 0 ) self . socket . bind ( ( self . host , self . port ) )

Opens the socket and binds to the given host and port . Uses SO_REUSEADDR to be as robust as possible .


def load_profiles(self):
        """
        Loads all possible TUIO profiles and returns a dictionary with the
        profile addresses as keys and an instance of a profile as the value
        """
        _profiles = {}
        for name, klass in inspect.getmembers(profiles):
            if inspect.isclass(klass) and name.endswith('Profile') and name != 'TuioProfile':
                # Adding profile to the self.profiles dictionary
                profile = klass()
                _profiles[profile.address] = profile
                # setting convenient variable to access objects of profile
                try:
                    setattr(self, profile.list_label, profile.objs)
                except AttributeError:
                    continue
                # Mapping callback method to every profile
                self.manager.add(self.callback, profile.address)
        return _profiles


def update(self):
        """
        Tells the connection manager to receive the next 1024 byte of messages
        to analyze.
        """
        try:
            self.manager.handle(self.socket.recv(1024))
        except socket.error:
            pass

def update ( self ) : try : self . manager . handle ( self . socket . recv ( 1024 ) ) except socket . error : pass

Tells the connection manager to receive the next 1024 byte of messages to analyze .


def callback(self, *incoming):
        """
        Gets called by the CallbackManager if a new message was received
        """
        message = incoming[0]
        if message:
            address, command = message[0], message[2]
            profile = self.get_profile(address)
            if profile is not None:
                try:
                    getattr(profile, command)(self, message)
                except AttributeError:
                    pass

def callback ( self , * incoming ) : message = incoming [ 0 ] if message : address , command = message [ 0 ] , message [ 2 ] profile = self . get_profile ( address ) if profile is not None : try : getattr ( profile , command ) ( self , message ) except AttributeError : pass


def copytree(src, dst, symlinks=False, ignore=None):
    """
    copytree that works even if folder already exists
    """
    # http://stackoverflow.com/questions/1868714/how-do-i-copy-an-entire-directory-of-files-into-an-existing-directory-using-pyth
    if not os.path.exists(dst):
        os.makedirs(dst)
        shutil.copystat(src, dst)
    lst = os.listdir(src)
    if ignore:
        excl = ignore(src, lst)
        lst = [x for x in lst if x not in excl]
    for item in lst:
        s = os.path.join(src, item)
        d = os.path.join(dst, item)
        if symlinks and os.path.islink(s):
            if os.path.lexists(d):
                os.remove(d)
            os.symlink(os.readlink(s), d)
            try:
                st = os.lstat(s)
                mode = stat.S_IMODE(st.st_mode)
                os.lchmod(d, mode)
            except:
                pass  # lchmod not available
        elif os.path.isdir(s):
            copytree(s, d, symlinks, ignore)
        else:
            shutil.copy2(s, d)


def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
        allow_nan=True, cls=None, indent=None, separators=None,
        encoding='utf-8', default=None, **kw):
    """
    Serialize ``obj`` to a JSON formatted ``str``.

    If ``skipkeys`` is ``True`` then ``dict`` keys that are not basic types
    (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``)
    will be skipped instead of raising a ``TypeError``.

    If ``ensure_ascii`` is ``False``, then the return value will be a
    ``unicode`` instance subject to normal Python ``str`` to ``unicode``
    coercion rules instead of being escaped to an ASCII ``str``.

    If ``check_circular`` is ``False``, then the circular reference check
    for container types will be skipped and a circular reference will
    result in an ``OverflowError`` (or worse).

    If ``allow_nan`` is ``False``, then it will be a ``ValueError`` to
    serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in
    strict compliance of the JSON specification, instead of using the
    JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).

    If ``indent`` is a non-negative integer, then JSON array elements and
    object members will be pretty-printed with that indent level. An indent
    level of 0 will only insert newlines. ``None`` is the most compact
    representation.

    If ``separators`` is an ``(item_separator, dict_separator)`` tuple
    then it will be used instead of the default ``(', ', ': ')`` separators.
    ``(',', ':')`` is the most compact JSON representation.

    ``encoding`` is the character encoding for str instances, default is UTF-8.

    ``default(obj)`` is a function that should return a serializable version
    of obj or raise TypeError. The default simply raises TypeError.

    To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
    ``.default()`` method to serialize additional types), specify it with
    the ``cls`` kwarg.
    """
    # cached encoder
    if (skipkeys is False and ensure_ascii is True and
        check_circular is True and allow_nan is True and
        cls is None and indent is None and separators is None and
        encoding == 'utf-8' and default is None and not kw):
        return _default_encoder.encode(obj)
    if cls is None:
        cls = JSONEncoder
    return cls(
        skipkeys=skipkeys, ensure_ascii=ensure_ascii,
        check_circular=check_circular, allow_nan=allow_nan, indent=indent,
        separators=separators, encoding=encoding, default=default,
        **kw).encode(obj)

def
dumps
(
obj
,
skipkeys
=
False
,
ensure_ascii
=
True
,
check_circular
=
True
,
allow_nan
=
True
,
cls
=
,
indent
=
,
separators
=
,
encoding
=
'utf-8'
,
default
=
,
*
*
kw
)
:
# cached encoder
if
(
skipkeys
is
False
and
ensure_ascii
is
True
and
check_circular
is
True
and
allow_nan
is
True
and
cls
is
and
indent
is
and
separators
is
and
encoding
==
'utf-8'
and
default
is
and
not
kw
)
:
return
_default_encoder
.
encode
(
obj
)
if
cls
is
:
cls
=
JSONEncoder
return
cls
(
skipkeys
=
skipkeys
,
ensure_ascii
=
ensure_ascii
,
check_circular
=
check_circular
,
allow_nan
=
allow_nan
,
indent
=
indent
,
separators
=
separators
,
encoding
=
encoding
,
default
=
default
,
*
*
kw
)
.
encode
(
obj
)


def search(q, start=0, wait=10, asynchronous=False, cached=False):

    """ Returns a Google web query formatted as a GoogleSearch list object.
    """

    service = GOOGLE_SEARCH
    return GoogleSearch(q, start, service, "", wait, asynchronous, cached)

def search ( q , start = 0 , wait = 10 , asynchronous = False , cached = False ) : service = GOOGLE_SEARCH return GoogleSearch ( q , start , service , "" , wait , asynchronous , cached )

Returns a Google web query formatted as a GoogleSearch list object .


def search_images(q, start=0, size="", wait=10, asynchronous=False, cached=False):

    """ Returns a Google images query formatted as a GoogleSearch list object.
    """

    service = GOOGLE_IMAGES
    return GoogleSearch(q, start, service, size, wait, asynchronous, cached)

def search_images ( q , start = 0 , size = "" , wait = 10 , asynchronous = False , cached = False ) : service = GOOGLE_IMAGES return GoogleSearch ( q , start , service , size , wait , asynchronous , cached )

Returns a Google images query formatted as a GoogleSearch list object .


def search_news(q, start=0, wait=10, asynchronous=False, cached=False):

    """ Returns a Google news query formatted as a GoogleSearch list object.
    """

    service = GOOGLE_NEWS
    return GoogleSearch(q, start, service, "", wait, asynchronous, cached)

def search_news ( q , start = 0 , wait = 10 , asynchronous = False , cached = False ) : service = GOOGLE_NEWS return GoogleSearch ( q , start , service , "" , wait , asynchronous , cached )

Returns a Google news query formatted as a GoogleSearch list object .


def search_blogs(q, start=0, wait=10, asynchronous=False, cached=False):

    """ Returns a Google blogs query formatted as a GoogleSearch list object.
    """

    service = GOOGLE_BLOGS
    return GoogleSearch(q, start, service, "", wait, asynchronous, cached)

def search_blogs ( q , start = 0 , wait = 10 , asynchronous = False , cached = False ) : service = GOOGLE_BLOGS return GoogleSearch ( q , start , service , "" , wait , asynchronous , cached )

Returns a Google blogs query formatted as a GoogleSearch list object .


def hash(self, id):

        """ Creates a unique filename in the cache for the id.
        """

        h = md5(id).hexdigest()
        return os.path.join(self.path, h+self.type)

def hash ( self , id ) : h = md5 ( id ) . hexdigest ( ) return os . path . join ( self . path , h + self . type )

Creates a unique filename in the cache for the id .


def age(self, id):

        """ Returns the age of the cache entry, in days.
        """

        path = self.hash(id)
        if os.path.exists(path):
            modified = datetime.datetime.fromtimestamp(os.stat(path)[8])
            age = datetime.datetime.today() - modified
            return age.days
        else:
            return 0

def age ( self , id ) : path = self . hash ( id ) if os . path . exists ( path ) : modified = datetime . datetime . fromtimestamp ( os . stat ( path ) [ 8 ] ) age = datetime . datetime . today ( ) - modified return age . days else : return 0

Returns the age of the cache entry in days .


def angle(x0, y0, x1, y1):
    """ Returns the angle between two points.
    """
    return degrees(atan2(y1-y0, x1-x0))


def distance(x0, y0, x1, y1):
    """ Returns the distance between two points.
    """
    return sqrt(pow(x1-x0, 2) + pow(y1-y0, 2))

def distance ( x0 , y0 , x1 , y1 ) : return sqrt ( pow ( x1 - x0 , 2 ) + pow ( y1 - y0 , 2 ) )

Returns the distance between two points .


def line_line_intersection(x1, y1, x2, y2, x3, y3, x4, y4, infinite=False):
    """ Determines the intersection point of two lines, or two finite line segments if infinite=False.
        When the lines do not intersect, returns an empty list.
    """
    # Based on: P. Bourke, http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
    ua = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)
    ub = (x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)
    d = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1)
    if d == 0:
        if ua == ub == 0:
            # The lines are coincident
            return []
        else:
            # The lines are parallel.
            return []
    ua /= float(d)
    ub /= float(d)
    if not infinite and not (0 <= ua <= 1 and 0 <= ub <= 1):
        # Intersection point is not within both line segments.
        return None, None
    return [(x1 + ua * (x2 - x1),
             y1 + ua * (y2 - y1))]

Determines the intersection point of two lines or two finite line segments if infinite = False . When the lines do not intersect returns an empty list .


def circle_line_intersection(cx, cy, radius, x1, y1, x2, y2, infinite=False):
    """ Returns a list of points where the circle and the line intersect.
            Returns an empty list when the circle and the line do not intersect.
    """
    # Based on: http://www.vb-helper.com/howto_net_line_circle_intersections.html
    dx = x2 - x1
    dy = y2 - y1
    A = dx * dx + dy * dy
    B = 2 * (dx * (x1 - cx) + dy * (y1 - cy))
    C = pow(x1 - cx, 2) + pow(y1 - cy, 2) - radius * radius
    det = B * B - 4 * A * C
    if A <= 0.0000001 or det < 0:
        return []
    elif det == 0:
        # One point of intersection.
        t = -B / (2 * A)
        return [(x1 + t * dx, y1 + t * dy)]
    else:
        # Two points of intersection.
        # A point of intersection lies on the line segment if 0 <= t <= 1,
        # and on an extension of the segment otherwise.
        points = []
        det2 = sqrt(det)
        t1 = (-B + det2) / (2 * A)
        t2 = (-B - det2) / (2 * A)
        if infinite or 0 <= t1 <= 1:
            points.append((x1 + t1 * dx, y1 + t1 * dy))
        if infinite or 0 <= t2 <= 1:
            points.append((x1 + t2 * dx, y1 + t2 * dy))
        return points

Returns a list of points where the circle and the line intersect . Returns an empty list when the circle and the line do not intersect .


def invert(self):
        """ Multiplying a matrix by its inverse produces the identity matrix.
        """
        m = self.matrix
        d = m[0] * m[4] - m[1] * m[3]
        self.matrix = [
             m[4] / d, -m[1] / d, 0,
             -m[3] / d,  m[0] / d, 0,
             (m[3] * m[7] - m[4] * m[6]) / d,
             -(m[0] * m[7] - m[1] * m[6]) / d,
             1
        ]

Multiplying a matrix by its inverse produces the identity matrix .


def transform_path(self, path):
        """ Returns a BezierPath object with the transformation applied.
        """
        p = path.__class__() # Create a new BezierPath.
        for pt in path:
            if pt.cmd == "close":
                p.closepath()
            elif pt.cmd == "moveto":
                p.moveto(*self.apply(pt.x, pt.y))
            elif pt.cmd == "lineto":
                p.lineto(*self.apply(pt.x, pt.y))
            elif pt.cmd == "curveto":
                vx1, vy1 = self.apply(pt.ctrl1.x, pt.ctrl1.y)
                vx2, vy2 = self.apply(pt.ctrl2.x, pt.ctrl2.y)
                x, y = self.apply(pt.x, pt.y)
                p.curveto(vx1, vy1, vx2, vy2, x, y)
        return p

def
transform_path
(
self
,
path
)
:
p
=
path
.
__class__
(
)
# Create a new BezierPath.
for
pt
in
path
:
if
pt
.
cmd
==
"close"
:
p
.
closepath
(
)
elif
pt
.
cmd
==
"moveto"
:
p
.
moveto
(
*
self
.
apply
(
pt
.
x
,
pt
.
y
)
)
elif
pt
.
cmd
==
"lineto"
:
p
.
lineto
(
*
self
.
apply
(
pt
.
x
,
pt
.
y
)
)
elif
pt
.
cmd
==
"curveto"
:
vx1
,
vy1
=
self
.
apply
(
pt
.
ctrl1
.
x
,
pt
.
ctrl1
.
y
)
vx2
,
vy2
=
self
.
apply
(
pt
.
ctrl2
.
x
,
pt
.
ctrl2
.
y
)
x
,
y
=
self
.
apply
(
pt
.
x
,
pt
.
y
)
p
.
curveto
(
vx1
,
vy1
,
vx2
,
vy2
,
x
,
y
)
return
p

Returns a BezierPath object with the transformation applied .


def intersection(self, b):
        """ Returns bounds that encompass the intersection of the two.
            If there is no overlap between the two, None is returned.
        """
        if not self.intersects(b):
            return None
        mx, my = max(self.x, b.x), max(self.y, b.y)
        return Bounds(mx, my,
            min(self.x+self.width, b.x+b.width) - mx,
            min(self.y+self.height, b.y+b.height) - my)

def intersection ( self , b ) : if not self . intersects ( b ) : return None mx , my = max ( self . x , b . x ) , max ( self . y , b . y ) return Bounds ( mx , my , min ( self . x + self . width , b . x + b . width ) - mx , min ( self . y + self . height , b . y + b . height ) - my )

Returns bounds that encompass the intersection of the two . If there is no overlap between the two None is returned .


def union(self, b):
        """ Returns bounds that encompass the union of the two.
        """
        mx, my = min(self.x, b.x), min(self.y, b.y)
        return Bounds(mx, my,
            max(self.x+self.width, b.x+b.width) - mx,
            max(self.y+self.height, b.y+b.height) - my)

def union ( self , b ) : mx , my = min ( self . x , b . x ) , min ( self . y , b . y ) return Bounds ( mx , my , max ( self . x + self . width , b . x + b . width ) - mx , max ( self . y + self . height , b . y + b . height ) - my )

Returns bounds that encompass the union of the two .


def error(message):
    '''Prints an error message, the help message and quits'''
    global parser
    print (_("Error: ") + message)
    print ()
    parser.print_help()
    sys.exit()

def
error
(
message
)
:
global
parser
print
(
_
(
"Error: "
)
+
message
)
print
(
)
parser
.
print_help
(
)
sys
.
exit
(
)

Prints an error message the help message and quits


def textpath(self, txt, x, y, width=None, height=1000000, enableRendering=False, **kwargs):
        '''
        Draws an outlined path of the input text
        '''
        txt = self.Text(txt, x, y, width, height, **kwargs)
        path = txt.path
        if draw:
            path.draw()
        return path

def textpath ( self , txt , x , y , width = None , height = 1000000 , enableRendering = False , * * kwargs ) : txt = self . Text ( txt , x , y , width , height , * * kwargs ) path = txt . path if draw : path . draw ( ) return path


def draw_cornu_flat(x0, y0, t0, t1, s0, c0, flip, cs, ss, cmd):

    """ Raph Levien's code draws fast LINETO segments.
    """

    for j in range(0, 100):
        t = j * .01
        s, c = eval_cornu(t0 + t * (t1 - t0))
        s *= flip
        s -= s0
        c -= c0
        #print '%', c, s
        x = c * cs - s * ss
        y = s * cs + c * ss
        print_pt(x0 + x, y0 + y, cmd)
        cmd = 'lineto'
    return cmd

def
draw_cornu_flat
(
x0
,
y0
,
t0
,
t1
,
s0
,
c0
,
flip
,
cs
,
ss
,
cmd
)
:
for
j
in
range
(
0
,
100
)
:
t
=
j
*
.01
s
,
c
=
eval_cornu
(
t0
+
t
*
(
t1
t0
)
)
s
*=
flip
s
-=
s0
c
-=
c0
#print '%', c, s
x
=
c
*
cs
s
*
ss
y
=
s
*
cs
+
c
*
ss
print_pt
(
x0
+
x
,
y0
+
y
,
cmd
)
cmd
=
'lineto'
return
cmd

Raph Levien s code draws fast LINETO segments .


def draw_cornu_bezier(x0, y0, t0, t1, s0, c0, flip, cs, ss, cmd, scale, rot):

    """ Mark Meyer's code draws elegant CURVETO segments.
    """

    s = None
    for j in range(0, 5):
        # travel along the function two points at a time (at time t and t2)
        # the first time through we'll need to get both points
        # after that we only need the second point because the old second point
        # becomes the new first point
        t = j * .2
        t2 = t+ .2

        curvetime = t0 + t * (t1 - t0)
        curvetime2 = t0 + t2 * (t1 - t0)
        Dt = (curvetime2 - curvetime) * scale

        if not s:
            # get first point
            # avoid calling this again: the next time though x,y will equal x3, y3
            s, c = eval_cornu(curvetime)
            s *= flip
            s -= s0
            c -= c0
            # calculate derivative of fresnel function at point to get tangent slope
            # just take the integrand of the fresnel function
            dx1 =  cos(pow(curvetime, 2) + (flip * rot))
            dy1 =  flip * sin(pow(curvetime, 2) + (flip *rot))
            # x,y = first point on function
            x = ((c * cs - s * ss) +x0)
            y = ((s * cs + c * ss) + y0)

        #evaluate the fresnel further along the function to look ahead to the next point
        s2,c2 = eval_cornu(curvetime2)
        s2 *= flip
        s2 -= s0
        c2 -= c0

        dx2 = cos(pow(curvetime2, 2) + (flip * rot))
        dy2 = flip * sin(pow(curvetime2, 2) + (flip * rot))
        # x3, y3 = second point on function
        x3 = ((c2 * cs - s2 * ss)+x0)
        y3 = ((s2 * cs + c2 * ss)+y0)

        # calculate control points
        x1 = (x + ((Dt/3.0) * dx1))
        y1 = (y + ((Dt/3.0) * dy1))
        x2 = (x3 - ((Dt/3.0) * dx2))
        y2 = (y3 - ((Dt/3.0) * dy2))

        if cmd == 'moveto':
            print_pt(x, y, cmd)
            cmd = 'curveto'
        print_crv(x1, y1, x2, y2, x3, y3)

        dx1, dy1 = dx2, dy2
        x,y = x3, y3

    return cmd

Mark Meyer s code draws elegant CURVETO segments .


def search(q, start=1, count=10, context=None, wait=10, asynchronous=False, cached=False):

    """ Returns a Yahoo web query formatted as a YahooSearch list object.
    """

    service = YAHOO_SEARCH
    return YahooSearch(q, start, count, service, context, wait, asynchronous, cached)

def search ( q , start = 1 , count = 10 , context = None , wait = 10 , asynchronous = False , cached = False ) : service = YAHOO_SEARCH return YahooSearch ( q , start , count , service , context , wait , asynchronous , cached )

Returns a Yahoo web query formatted as a YahooSearch list object .


def search_images(q, start=1, count=10, wait=10, asynchronous=False, cached=False):

    """ Returns a Yahoo images query formatted as a YahooSearch list object.
    """

    service = YAHOO_IMAGES
    return YahooSearch(q, start, count, service, None, wait, asynchronous, cached)

def search_images ( q , start = 1 , count = 10 , wait = 10 , asynchronous = False , cached = False ) : service = YAHOO_IMAGES return YahooSearch ( q , start , count , service , None , wait , asynchronous , cached )

Returns a Yahoo images query formatted as a YahooSearch list object .


def search_news(q, start=1, count=10, wait=10, asynchronous=False, cached=False):

    """ Returns a Yahoo news query formatted as a YahooSearch list object.
    """

    service = YAHOO_NEWS
    return YahooSearch(q, start, count, service, None, wait, asynchronous, cached)

def search_news ( q , start = 1 , count = 10 , wait = 10 , asynchronous = False , cached = False ) : service = YAHOO_NEWS return YahooSearch ( q , start , count , service , None , wait , asynchronous , cached )

Returns a Yahoo news query formatted as a YahooSearch list object .


def suggest_spelling(q, wait=10, asynchronous=False, cached=False):

    """ Returns list of suggested spelling corrections for the given query.
    """

    return YahooSpelling(q, wait, asynchronous, cached)

def suggest_spelling ( q , wait = 10 , asynchronous = False , cached = False ) : return YahooSpelling ( q , wait , asynchronous , cached )

Returns list of suggested spelling corrections for the given query .


def layer(self, img, x=0, y=0, name=""):

        """Creates a new layer from file, Layer, PIL Image.

        If img is an image file or PIL Image object,
        Creates a new layer with the given image file.
        The image is positioned on the canvas at x, y.

        If img is a Layer,
        uses that layer's x and y position and name.

        """

        from types import StringType
        if isinstance(img, Image.Image):
            img = img.convert("RGBA")
            self.layers.append(Layer(self, img, x, y, name))
            return len(self.layers)-1
        if isinstance(img, Layer):
            img.canvas = self
            self.layers.append(img)
            return len(self.layers)-1
        if type(img) == StringType:
            img = Image.open(img)
            img = img.convert("RGBA")
            self.layers.append(Layer(self, img, x, y, name))
            return len(self.layers)-1

def layer ( self , img , x = 0 , y = 0 , name = "" ) : from types import StringType if isinstance ( img , Image . Image ) : img = img . convert ( "RGBA" ) self . layers . append ( Layer ( self , img , x , y , name ) ) return len ( self . layers ) - 1 if isinstance ( img , Layer ) : img . canvas = self self . layers . append ( img ) return len ( self . layers ) - 1 if type ( img ) == StringType : img = Image . open ( img ) img = img . convert ( "RGBA" ) self . layers . append ( Layer ( self , img , x , y , name ) ) return len ( self . layers ) - 1

Creates a new layer from file Layer PIL Image . If img is an image file or PIL Image object Creates a new layer with the given image file . The image is positioned on the canvas at x y . If img is a Layer uses that layer s x and y position and name .


def merge(self, layers):

        """Flattens the given layers on the canvas.

        Merges the given layers with the indices in the list
        on the bottom layer in the list.
        The other layers are discarded.

        """

        layers.sort()
        if layers[0] == 0: del layers[0]
        self.flatten(layers)

def merge ( self , layers ) : layers . sort ( ) if layers [ 0 ] == 0 : del layers [ 0 ] self . flatten ( layers )

Flattens the given layers on the canvas . Merges the given layers with the indices in the list on the bottom layer in the list . The other layers are discarded .


def export(self, filename):

        """Exports the flattened canvas.

        Flattens the canvas.
        PNG retains the alpha channel information.
        Other possibilities are JPEG and GIF.

        """

        self.flatten()
        self.layers[1].img.save(filename)
        return filename

def export ( self , filename ) : self . flatten ( ) self . layers [ 1 ] . img . save ( filename ) return filename

Exports the flattened canvas . Flattens the canvas . PNG retains the alpha channel information . Other possibilities are JPEG and GIF .


def delete(self):

        """Removes this layer from the canvas.

        """

        i = self.index()
        if i != None: del self.canvas.layers[i]

def delete ( self ) : i = self . index ( ) if i != None : del self . canvas . layers [ i ]


def up(self):

        """Moves the layer up in the stacking order.

        """

        i = self.index()
        if i != None:
            del self.canvas.layers[i]
            i = min(len(self.canvas.layers), i+1)
            self.canvas.layers.insert(i, self)

def up ( self ) : i = self . index ( ) if i != None : del self . canvas . layers [ i ] i = min ( len ( self . canvas . layers ) , i + 1 ) self . canvas . layers . insert ( i , self )

Moves the layer up in the stacking order .


def down(self):

        """Moves the layer down in the stacking order.

        """

        i = self.index()
        if i != None:
            del self.canvas.layers[i]
            i = max(0, i-1)
            self.canvas.layers.insert(i, self)

def down ( self ) : i = self . index ( ) if i != None : del self . canvas . layers [ i ] i = max ( 0 , i - 1 ) self . canvas . layers . insert ( i , self )

Moves the layer down in the stacking order .


def duplicate(self):

        """Creates a copy of the current layer.

        This copy becomes the top layer on the canvas.

        """

        i = self.canvas.layer(self.img.copy(), self.x, self.y, self.name)
        clone = self.canvas.layers[i]
        clone.alpha = self.alpha
        clone.blend = self.blend

def duplicate ( self ) : i = self . canvas . layer ( self . img . copy ( ) , self . x , self . y , self . name ) clone = self . canvas . layers [ i ] clone . alpha = self . alpha clone . blend = self . blend

Creates a copy of the current layer . This copy becomes the top layer on the canvas .


def brightness(self, value=1.0):

        """Increases or decreases the brightness in the layer.

        The given value is a percentage to increase
        or decrease the image brightness,
        for example 0.8 means brightness at 80%.

        """

        b = ImageEnhance.Brightness(self.img)
        self.img = b.enhance(value)

def brightness ( self , value = 1.0 ) : b = ImageEnhance . Brightness ( self . img ) self . img = b . enhance ( value )

Increases or decreases the brightness in the layer . The given value is a percentage to increase or decrease the image brightness for example 0 . 8 means brightness at 80% .


def contrast(self, value=1.0):

        """Increases or decreases the contrast in the layer.

        The given value is a percentage to increase
        or decrease the image contrast,
        for example 1.2 means contrast at 120%.

        """

        c = ImageEnhance.Contrast(self.img)
        self.img = c.enhance(value)

def contrast ( self , value = 1.0 ) : c = ImageEnhance . Contrast ( self . img ) self . img = c . enhance ( value )

Increases or decreases the contrast in the layer . The given value is a percentage to increase or decrease the image contrast for example 1 . 2 means contrast at 120% .


def desaturate(self):

        """Desaturates the layer, making it grayscale.

        Instantly removes all color information from the layer,
        while maintaing its alpha channel.

        """

        alpha = self.img.split()[3]
        self.img = self.img.convert("L")
        self.img = self.img.convert("RGBA")
        self.img.putalpha(alpha)

def desaturate ( self ) : alpha = self . img . split ( ) [ 3 ] self . img = self . img . convert ( "L" ) self . img = self . img . convert ( "RGBA" ) self . img . putalpha ( alpha )

Desaturates the layer making it grayscale . Instantly removes all color information from the layer while maintaing its alpha channel .


def invert(self):

        """Inverts the layer.

        """

        alpha = self.img.split()[3]
        self.img = self.img.convert("RGB")
        self.img = ImageOps.invert(self.img)
        self.img = self.img.convert("RGBA")
        self.img.putalpha(alpha)

def invert ( self ) : alpha = self . img . split ( ) [ 3 ] self . img = self . img . convert ( "RGB" ) self . img = ImageOps . invert ( self . img ) self . img = self . img . convert ( "RGBA" ) self . img . putalpha ( alpha )


def translate(self, x, y):

        """Positions the layer at the given coordinates.

        The x and y parameters define where to position
        the top left corner of the layer,
        measured from the top left of the canvas.

        """

        self.x = x
        self.y = y

def translate ( self , x , y ) : self . x = x self . y = y

Positions the layer at the given coordinates . The x and y parameters define where to position the top left corner of the layer measured from the top left of the canvas .


def scale(self, w=1.0, h=1.0):

        """Resizes the layer to the given width and height.

        When width w or height h is a floating-point number,
        scales percentual,
        otherwise scales to the given size in pixels.

        """

        from types import FloatType
        w0, h0 = self.img.size
        if type(w) == FloatType: w = int(w*w0)
        if type(h) == FloatType: h = int(h*h0)

        self.img = self.img.resize((w,h), INTERPOLATION)
        self.w = w
        self.h = h

def scale ( self , w = 1.0 , h = 1.0 ) : from types import FloatType w0 , h0 = self . img . size if type ( w ) == FloatType : w = int ( w * w0 ) if type ( h ) == FloatType : h = int ( h * h0 ) self . img = self . img . resize ( ( w , h ) , INTERPOLATION ) self . w = w self . h = h

Resizes the layer to the given width and height . When width w or height h is a floating - point number scales percentual otherwise scales to the given size in pixels .


def rotate(self, angle):

        """Rotates the layer.

        Rotates the layer by given angle.
        Positive numbers rotate counter-clockwise,
        negative numbers rotate clockwise.

        Rotate commands are executed instantly,
        so many subsequent rotates will distort the image.

        """

        #When a layer rotates, its corners will fall outside
        #of its defined width and height.
        #Thus, its bounding box needs to be expanded.

        #Calculate the diagonal width, and angle from the layer center.
        #This way we can use the layers's corners
        #to calculate the bounding box.

        from math import sqrt, pow, sin, cos, degrees, radians, asin
        w0, h0 = self.img.size
        d = sqrt(pow(w0,2) + pow(h0,2))
        d_angle = degrees(asin((w0*0.5) / (d*0.5)))

        angle = angle % 360
        if angle > 90 and angle <= 270: d_angle += 180

        w = sin(radians(d_angle + angle)) * d
        w = max(w, sin(radians(d_angle - angle)) * d)
        w = int(abs(w))

        h = cos(radians(d_angle + angle)) * d
        h = max(h, cos(radians(d_angle - angle)) * d)
        h = int(abs(h))

        dx = int((w-w0) / 2)
        dy = int((h-h0) / 2)
        d = int(d)

        #The rotation box's background color
        #is the mean pixel value of the rotating image.
        #This is the best option to avoid borders around
        #the rotated image.

        bg = ImageStat.Stat(self.img).mean
        bg = (int(bg[0]), int(bg[1]), int(bg[2]), 0)

        box = Image.new("RGBA", (d,d), bg)
        box.paste(self.img, ((d-w0)/2, (d-h0)/2))
        box = box.rotate(angle, INTERPOLATION)
        box = box.crop(((d-w)/2+2, (d-h)/2, d-(d-w)/2, d-(d-h)/2))
        self.img = box

        #Since rotate changes the bounding box size,
        #update the layers' width, height, and position,
        #so it rotates from the center.

        self.x += (self.w-w)/2
        self.y += (self.h-h)/2
        self.w = w
        self.h = h

Rotates the layer . Rotates the layer by given angle . Positive numbers rotate counter - clockwise negative numbers rotate clockwise . Rotate commands are executed instantly so many subsequent rotates will distort the image .


def flip(self, axis=HORIZONTAL):

        """Flips the layer, either HORIZONTAL or VERTICAL.

        """

        if axis == HORIZONTAL:
            self.img = self.img.transpose(Image.FLIP_LEFT_RIGHT)
        if axis == VERTICAL:
            self.img = self.img.transpose(Image.FLIP_TOP_BOTTOM)

def flip ( self , axis = HORIZONTAL ) : if axis == HORIZONTAL : self . img = self . img . transpose ( Image . FLIP_LEFT_RIGHT ) if axis == VERTICAL : self . img = self . img . transpose ( Image . FLIP_TOP_BOTTOM )

Flips the layer either HORIZONTAL or VERTICAL .


def sharpen(self, value=1.0):

        """Increases or decreases the sharpness in the layer.

        The given value is a percentage to increase
        or decrease the image sharpness,
        for example 0.8 means sharpness at 80%.

        """

        s = ImageEnhance.Sharpness(self.img)
        self.img = s.enhance(value)

def sharpen ( self , value = 1.0 ) : s = ImageEnhance . Sharpness ( self . img ) self . img = s . enhance ( value )

Increases or decreases the sharpness in the layer . The given value is a percentage to increase or decrease the image sharpness for example 0 . 8 means sharpness at 80% .


def levels(self):

        """Returns a histogram for each RGBA channel.

        Returns a 4-tuple of lists, r, g, b, and a.
        Each list has 255 items, a count for each pixel value.

        """

        h = self.img.histogram()
        r = h[0:255]
        g = h[256:511]
        b = h[512:767]
        a = h[768:1024]

        return r, g, b, a

Returns a histogram for each RGBA channel . Returns a 4 - tuple of lists r g b and a . Each list has 255 items a count for each pixel value .


def hue(self, img1, img2):

        """Applies the hue blend mode.

        Hues image img1 with image img2.
        The hue filter replaces the hues of pixels in img1
        with the hues of pixels in img2.
        Returns a composite image with the alpha channel retained.

        """

        import colorsys

        p1 = list(img1.getdata())
        p2 = list(img2.getdata())
        for i in range(len(p1)):

            r1, g1, b1, a1 = p1[i]
            r1 = r1 / 255.0
            g1 = g1 / 255.0
            b1 = b1 / 255.0

            h1, s1, v1 = colorsys.rgb_to_hsv(r1, g1, b1)

            r2, g2, b2, a2 = p2[i]
            r2 = r2 / 255.0
            g2 = g2 / 255.0
            b2 = b2 / 255.0
            h2, s2, v2 = colorsys.rgb_to_hsv(r2, g2, b2)

            r3, g3, b3 = colorsys.hsv_to_rgb(h2, s1, v1)

            r3 = int(r3*255)
            g3 = int(g3*255)
            b3 = int(b3*255)
            p1[i] = (r3, g3, b3, a1)

        img = Image.new("RGBA", img1.size, 255)
        img.putdata(p1)
        return img

Applies the hue blend mode . Hues image img1 with image img2 . The hue filter replaces the hues of pixels in img1 with the hues of pixels in img2 . Returns a composite image with the alpha channel retained .


def _load_namespace(self, namespace, filename=None):
        """
        Initialise bot namespace with info in shoebot.data

        :param filename: Will be set to __file__ in the namespace
        """
        from shoebot import data
        for name in dir(data):
            namespace[name] = getattr(data, name)

        for name in dir(self):
            if name[0] != '_':
                namespace[name] = getattr(self, name)

        namespace['_ctx'] = self  # Used in older nodebox scripts.
        namespace['__file__'] = filename

def
_load_namespace
(
self
,
namespace
,
filename
=
)
:
from
shoebot
import
data
for
name
in
dir
(
data
)
:
namespace
[
name
]
=
getattr
(
data
,
name
)
for
name
in
dir
(
self
)
:
if
name
[
0
]
!=
'_'
:
namespace
[
name
]
=
getattr
(
self
,
name
)
namespace
[
'_ctx'
]
=
self
# Used in older nodebox scripts.
namespace
[
'__file__'
]
=
filename

Initialise bot namespace with info in shoebot . data


def _should_run(self, iteration, max_iterations):
        ''' Return False if bot should quit '''
        if iteration == 0:
            # First frame always runs
            return True
        if max_iterations:
            if iteration < max_iterations:
                return True
        elif max_iterations is None:
            if self._dynamic:
                return True
            else:
                return False
            return True
        if not self._dynamic:
            return False

        return False

def
_should_run
(
self
,
iteration
,
max_iterations
)
:
if
iteration
==
0
:
# First frame always runs
return
True
if
max_iterations
:
if
iteration
<
max_iterations
:
return
True
elif
max_iterations
is
:
if
self
.
_dynamic
:
return
True
else
:
return
False
return
True
if
not
self
.
_dynamic
:
return
False
return
False


def _frame_limit(self, start_time):
        """
        Limit to framerate, should be called after
        rendering has completed

        :param start_time: When execution started
        """
        if self._speed:
            completion_time = time()
            exc_time = completion_time - start_time
            sleep_for = (1.0 / abs(self._speed)) - exc_time
            if sleep_for > 0:
                sleep(sleep_for)

def _frame_limit ( self , start_time ) : if self . _speed : completion_time = time ( ) exc_time = completion_time - start_time sleep_for = ( 1.0 / abs ( self . _speed ) ) - exc_time if sleep_for > 0 : sleep ( sleep_for )

Limit to framerate should be called after rendering has completed


def _addvar(self, v):
        ''' Sets a new accessible variable.

        :param v: Variable.
        '''
        oldvar = self._oldvars.get(v.name)
        if oldvar is not None:
            if isinstance(oldvar, Variable):
                if oldvar.compliesTo(v):
                    v.value = oldvar.value
            else:
                # Set from commandline
                v.value = v.sanitize(oldvar)
        else:
            for listener in VarListener.listeners:
                listener.var_added(v)
        self._vars[v.name] = v
        self._namespace[v.name] = v.value
        self._oldvars[v.name] = v
        return v

def
_addvar
(
self
,
v
)
:
oldvar
=
self
.
_oldvars
.
get
(
v
.
name
)
if
oldvar
is
not
:
if
isinstance
(
oldvar
,
Variable
)
:
if
oldvar
.
compliesTo
(
v
)
:
v
.
value
=
oldvar
.
value
else
:
# Set from commandline
v
.
value
=
v
.
sanitize
(
oldvar
)
else
:
for
listener
in
VarListener
.
listeners
:
listener
.
var_added
(
v
)
self
.
_vars
[
v
.
name
]
=
v
self
.
_namespace
[
v
.
name
]
=
v
.
value
self
.
_oldvars
[
v
.
name
]
=
v
return
v


def hex_to_rgb(hex):
    """ Returns RGB values for a hex color string.
    """
    hex = hex.lstrip("#")
    if len(hex) < 6:
        hex += hex[-1] * (6 - len(hex))
    if len(hex) == 6:
        r, g, b = hex[0:2], hex[2:4], hex[4:]
        r, g, b = [int(n, 16) / 255.0 for n in (r, g, b)]
        a = 1.0
    elif len(hex) == 8:
        r, g, b, a = hex[0:2], hex[2:4], hex[4:6], hex[6:]
        r, g, b, a = [int(n, 16) / 255.0 for n in (r, g, b, a)]
    return r, g, b, a

def hex_to_rgb ( hex ) : hex = hex . lstrip ( "#" ) if len ( hex ) < 6 : hex += hex [ - 1 ] * ( 6 - len ( hex ) ) if len ( hex ) == 6 : r , g , b = hex [ 0 : 2 ] , hex [ 2 : 4 ] , hex [ 4 : ] r , g , b = [ int ( n , 16 ) / 255.0 for n in ( r , g , b ) ] a = 1.0 elif len ( hex ) == 8 : r , g , b , a = hex [ 0 : 2 ] , hex [ 2 : 4 ] , hex [ 4 : 6 ] , hex [ 6 : ] r , g , b , a = [ int ( n , 16 ) / 255.0 for n in ( r , g , b , a ) ] return r , g , b , a

Returns RGB values for a hex color string .


def simple_traceback(ex, source):
    """
    Format traceback, showing line number and surrounding source.
    """
    exc_type, exc_value, exc_tb = sys.exc_info()
    exc = traceback.format_exception(exc_type, exc_value, exc_tb)

    source_arr = source.splitlines()

    # Defaults...
    exc_location = exc[-2]
    for i, err in enumerate(exc):
        if 'exec source in ns' in err:
            exc_location = exc[i + 1]
            break

    # extract line number from traceback
    fn = exc_location.split(',')[0][8:-1]
    line_number = int(exc_location.split(',')[1].replace('line', '').strip())

    # Build error messages

    err_msgs = []

    # code around the error
    err_where = ' '.join(exc[i - 1].split(',')[1:]).strip()  # 'line 37 in blah"
    err_msgs.append('Error in the Shoebot script at %s:' % err_where)
    for i in xrange(max(0, line_number - 5), line_number):
        if fn == "<string>":
            line = source_arr[i]
        else:
            line = linecache.getline(fn, i + 1)
        err_msgs.append('%s: %s' % (i + 1, line.rstrip()))
    err_msgs.append('  %s^ %s' % (len(str(i)) * ' ', exc[-1].rstrip()))

    err_msgs.append('')
    # traceback
    err_msgs.append(exc[0].rstrip())
    for err in exc[3:]:
        err_msgs.append(err.rstrip())

    return '\n'.join(err_msgs)

def
simple_traceback
(
ex
,
source
)
:
exc_type
,
exc_value
,
exc_tb
=
sys
.
exc_info
(
)
exc
=
traceback
.
format_exception
(
exc_type
,
exc_value
,
exc_tb
)
source_arr
=
source
.
splitlines
(
)
# Defaults...
exc_location
=
exc
[
2
]
for
i
,
err
in
enumerate
(
exc
)
:
if
'exec source in ns'
in
err
:
exc_location
=
exc
[
i
+
1
]
break
# extract line number from traceback
fn
=
exc_location
.
split
(
','
)
[
0
]
[
8
:
1
]
line_number
=
int
(
exc_location
.
split
(
','
)
[
1
]
.
replace
(
'line'
,
''
)
.
strip
(
)
)
# Build error messages
err_msgs
=
[
]
# code around the error
err_where
=
' '
.
join
(
exc
[
i
1
]
.
split
(
','
)
[
1
:
]
)
.
strip
(
)
# 'line 37 in blah"
err_msgs
.
append
(
'Error in the Shoebot script at %s:'
%
err_where
)
for
i
in
xrange
(
max
(
0
,
line_number
5
)
,
line_number
)
:
if
fn
==
"<string>"
:
line
=
source_arr
[
i
]
else
:
line
=
linecache
.
getline
(
fn
,
i
+
1
)
err_msgs
.
append
(
'%s: %s'
%
(
i
+
1
,
line
.
rstrip
(
)
)
)
err_msgs
.
append
(
'  %s^ %s'
%
(
len
(
str
(
i
)
)
*
' '
,
exc
[
1
]
.
rstrip
(
)
)
)
err_msgs
.
append
(
''
)
# traceback
err_msgs
.
append
(
exc
[
0
]
.
rstrip
(
)
)
for
err
in
exc
[
3
:
]
:
err_msgs
.
append
(
err
.
rstrip
(
)
)
return
'\n'
.
join
(
err_msgs
)

Format traceback showing line number and surrounding source .


def create(self, name, overwrite=True):

        """Creates an SQLite database file.

        Creates an SQLite database with the given name.
        The .box file extension is added automatically.
        Overwrites any existing database by default.

        """

        self._name = name.rstrip(".db")
        from os import unlink
        if overwrite:
            try: unlink(self._name + ".db")
            except: pass
        self._con = sqlite.connect(self._name + ".db")
        self._cur = self._con.cursor()

def create ( self , name , overwrite = True ) : self . _name = name . rstrip ( ".db" ) from os import unlink if overwrite : try : unlink ( self . _name + ".db" ) except : pass self . _con = sqlite . connect ( self . _name + ".db" ) self . _cur = self . _con . cursor ( )

Creates an SQLite database file . Creates an SQLite database with the given name . The . box file extension is added automatically . Overwrites any existing database by default .


def create_table(self, name, fields=[], key="id"):

        """Creates a new table.

        Creates a table with the given name,
        containing the list of given fields.
        Since SQLite uses manifest typing, no data type need be supplied.
        The primary key is "id" by default,
        an integer that can be set or otherwise autoincrements.

        """

        for f in fields:
            if f == key: fields.remove(key)
        sql  = "create table "+name+" "
        sql += "("+key+" integer primary key"
        for f in fields: sql += ", "+f+" varchar(255)"
        sql += ")"
        self._cur.execute(sql)
        self._con.commit()
        self.index(name, key, unique=True)
        self.connect(self._name)

def
create_table
(
self
,
name
,
fields
=
[
]
,
key
=
"id"
)
:
for
f
in
fields
:
if
f
==
key
:
fields
.
remove
(
key
)
sql
=
"create table "
+
name
+
" "
sql
+=
"("
+
key
+
" integer primary key"
for
f
in
fields
:
sql
+=
", "
+
f
+
" varchar(255)"
sql
+=
")"
self
.
_cur
.
execute
(
sql
)
self
.
_con
.
commit
(
)
self
.
index
(
name
,
key
,
unique
=
True
)
self
.
connect
(
self
.
_name
)

Creates a new table . Creates a table with the given name containing the list of given fields . Since SQLite uses manifest typing no data type need be supplied . The primary key is id by default an integer that can be set or otherwise autoincrements .


def create_index(self, table, field, unique=False, ascending=True):

        """Creates a table index.

        Creates an index on the given table,
        on the given field with unique values enforced or not,
        in ascending or descending order.

        """

        if unique: u = "unique "
        else: u = ""
        if ascending: a = "asc"
        else: a = "desc"
        sql  = "create "+u+"index index_"+table+"_"+field+" "
        sql += "on "+table+"("+field+" "+a+")"
        self._cur.execute(sql)
        self._con.commit()

def
create_index
(
self
,
table
,
field
,
unique
=
False
,
ascending
=
True
)
:
if
unique
:
u
=
"unique "
else
:
u
=
""
if
ascending
:
a
=
"asc"
else
:
a
=
"desc"
sql
=
"create "
+
u
+
"index index_"
+
table
+
"_"
+
field
+
" "
sql
+=
"on "
+
table
+
"("
+
field
+
" "
+
a
+
")"
self
.
_cur
.
execute
(
sql
)
self
.
_con
.
commit
(
)

Creates a table index . Creates an index on the given table on the given field with unique values enforced or not in ascending or descending order .


def close(self):

        """Commits any pending transactions and closes the database.
        """

        self._con.commit()
        self._cur.close()
        self._con.close()

def close ( self ) : self . _con . commit ( ) self . _cur . close ( ) self . _con . close ( )

Commits any pending transactions and closes the database .


def sql(self, sql):

        """ Executes a raw SQL statement on the database.
        """

        self._cur.execute(sql)
        if sql.lower().find("select") >= 0:
            matches = []
            for r in self._cur: matches.append(r)
            return matches

def sql ( self , sql ) : self . _cur . execute ( sql ) if sql . lower ( ) . find ( "select" ) >= 0 : matches = [ ] for r in self . _cur : matches . append ( r ) return matches

Executes a raw SQL statement on the database .


def edit(self, id, *args, **kw):

        """ Edits the row with given id.
        """

        if args and kw:
            return
        if args and type(args[0]) == dict:
            fields = [k for k in args[0]]
            v = [args[0][k] for k in args[0]]
        if kw:
            fields = [k for k in kw]
            v = [kw[k] for k in kw]

        sql  = "update "+self._name+" set "+"=?, ".join(fields)+"=? where "+self._key+"="+unicode(id)
        self._db._cur.execute(sql, v)
        self._db._i += 1
        if self._db._i >= self._db._commit:
            self._db._i = 0
            self._db._con.commit()

def
edit
(
self
,
id
,
*
args
,
*
*
kw
)
:
if
args
and
kw
:
return
if
args
and
type
(
args
[
0
]
)
==
dict
:
fields
=
[
k
for
k
in
args
[
0
]
]
v
=
[
args
[
0
]
[
k
]
for
k
in
args
[
0
]
]
if
kw
:
fields
=
[
k
for
k
in
kw
]
v
=
[
kw
[
k
]
for
k
in
kw
]
sql
=
"update "
+
self
.
_name
+
" set "
+
"=?, "
.
join
(
fields
)
+
"=? where "
+
self
.
_key
+
"="
+
unicode
(
id
)
self
.
_db
.
_cur
.
execute
(
sql
,
v
)
self
.
_db
.
_i
+=
1
if
self
.
_db
.
_i
>=
self
.
_db
.
_commit
:
self
.
_db
.
_i
=
0
self
.
_db
.
_con
.
commit
(
)


def remove(self, id, operator="=", key=None):

        """ Deletes the row with given id.
        """

        if key == None: key = self._key
        try: id = unicode(id)
        except: pass
        sql = "delete from "+self._name+" where "+key+" "+operator+" ?"
        self._db._cur.execute(sql, (id,))

def
remove
(
self
,
id
,
operator
=
"="
,
key
=
)
:
if
key
==
:
key
=
self
.
_key
try
:
id
=
unicode
(
id
)
except
:
pass
sql
=
"delete from "
+
self
.
_name
+
" where "
+
key
+
" "
+
operator
+
" ?"
self
.
_db
.
_cur
.
execute
(
sql
,
(
id
,
)
)


def next_event(block=False, timeout=None):
    """
    Get the next available event or None

    :param block:
    :param timeout:
    :return: None or (event, data)
    """
    try:
        return channel.listen(block=block, timeout=timeout).next()['data']
    except StopIteration:
        return None

def next_event ( block = False , timeout = None ) : try : return channel . listen ( block = block , timeout = timeout ) . next ( ) [ 'data' ] except StopIteration : return None


def publish_event(event_t, data=None, extra_channels=None, wait=None):
    """
    Publish an event ot any subscribers.

    :param event_t:  event type
    :param data:     event data
    :param extra_channels:
    :param wait:
    :return:
    """
    event = Event(event_t, data)
    pubsub.publish("shoebot", event)
    for channel_name in extra_channels or []:
        pubsub.publish(channel_name, event)
    if wait is not None:
        channel = pubsub.subscribe(wait)
        channel.listen(wait)

def publish_event ( event_t , data = None , extra_channels = None , wait = None ) : event = Event ( event_t , data ) pubsub . publish ( "shoebot" , event ) for channel_name in extra_channels or [ ] : pubsub . publish ( channel_name , event ) if wait is not None : channel = pubsub . subscribe ( wait ) channel . listen ( wait )


def _set_mode(self, mode):
        '''
        Sets call_transform_mode to point to the
        center_transform or corner_transform
        '''
        if mode == CENTER:
            self._call_transform_mode = self._center_transform
        elif mode == CORNER:
            self._call_transform_mode = self._corner_transform
        else:
            raise ValueError('mode must be CENTER or CORNER')

def
_set_mode
(
self
,
mode
)
:
if
mode
==
CENTER
:
self
.
_call_transform_mode
=
self
.
_center_transform
elif
mode
==
CORNER
:
self
.
_call_transform_mode
=
self
.
_corner_transform
else
:
raise
ValueError
(
'mode must be CENTER or CORNER'
)


def inheritFromContext(self, ignore=()):
        """
        Doesn't store exactly the same items as Nodebox for ease of implementation,
        it has enough to get the Nodebox Dentrite example working.
        """
        for canvas_attr, grob_attr in STATES.items():
            if canvas_attr in ignore:
                continue
            setattr(self, grob_attr, getattr(self._bot._canvas, canvas_attr))

def inheritFromContext ( self , ignore = ( ) ) : for canvas_attr , grob_attr in STATES . items ( ) : if canvas_attr in ignore : continue setattr ( self , grob_attr , getattr ( self . _bot . _canvas , canvas_attr ) )

Doesn t store exactly the same items as Nodebox for ease of implementation it has enough to get the Nodebox Dentrite example working .


def load_edited_source(self, source, good_cb=None, bad_cb=None, filename=None):
        """
        Load changed code into the execution environment.

        Until the code is executed correctly, it will be
        in the 'tenuous' state.
        """
        with LiveExecution.lock:
            self.good_cb = good_cb
            self.bad_cb = bad_cb
            try:
                # text compile
                compile(source + '\n\n', filename or self.filename, "exec")
                self.edited_source = source
            except Exception as e:
                if bad_cb:
                    self.edited_source = None
                    tb = traceback.format_exc()
                    self.call_bad_cb(tb)
                return
            if filename is not None:
                self.filename = filename

def
load_edited_source
(
self
,
source
,
good_cb
=
,
bad_cb
=
,
filename
=
)
:
with
LiveExecution
.
lock
:
self
.
good_cb
=
good_cb
self
.
bad_cb
=
bad_cb
try
:
# text compile
compile
(
source
+
'\n\n'
,
filename
or
self
.
filename
,
"exec"
)
self
.
edited_source
=
source
except
Exception
as
e
:
if
bad_cb
:
self
.
edited_source
=
tb
=
traceback
.
format_exc
(
)
self
.
call_bad_cb
(
tb
)
return
if
filename
is
not
:
self
.
filename
=
filename

Load changed code into the execution environment .


def reload_functions(self):
        """
        Replace functions in namespace with functions from edited_source.
        """
        with LiveExecution.lock:
            if self.edited_source:
                tree = ast.parse(self.edited_source)
                for f in [n for n in ast.walk(tree) if isinstance(n, ast.FunctionDef)]:
                    self.ns[f.name].__code__ = meta.decompiler.compile_func(f, self.filename, self.ns).__code__

def reload_functions ( self ) : with LiveExecution . lock : if self . edited_source : tree = ast . parse ( self . edited_source ) for f in [ n for n in ast . walk ( tree ) if isinstance ( n , ast . FunctionDef ) ] : self . ns [ f . name ] . __code__ = meta . decompiler . compile_func ( f , self . filename , self . ns ) . __code__

Replace functions in namespace with functions from edited_source .


def run_tenuous(self):
        """
        Run edited source, if no exceptions occur then it
        graduates to known good.
        """
        with LiveExecution.lock:
            ns_snapshot = copy.copy(self.ns)
            try:
                source = self.edited_source
                self.edited_source = None
                self.do_exec(source, ns_snapshot)
                self.known_good = source
                self.call_good_cb()
                return True, None
            except Exception as ex:
                tb = traceback.format_exc()
                self.call_bad_cb(tb)
                self.ns.clear()
                self.ns.update(ns_snapshot)
                return False, ex

def run_tenuous ( self ) : with LiveExecution . lock : ns_snapshot = copy . copy ( self . ns ) try : source = self . edited_source self . edited_source = None self . do_exec ( source , ns_snapshot ) self . known_good = source self . call_good_cb ( ) return True , None except Exception as ex : tb = traceback . format_exc ( ) self . call_bad_cb ( tb ) self . ns . clear ( ) self . ns . update ( ns_snapshot ) return False , ex

Run edited source if no exceptions occur then it graduates to known good .


def run(self):
        """
        Attempt to known good or tenuous source.
        """
        with LiveExecution.lock:
            if self.edited_source:
                success, ex = self.run_tenuous()
                if success:
                    return

            self.do_exec(self.known_good, self.ns)

def run ( self ) : with LiveExecution . lock : if self . edited_source : success , ex = self . run_tenuous ( ) if success : return self . do_exec ( self . known_good , self . ns )

Attempt to known good or tenuous source .


def run_context(self):
        """
        Context in which the user can run the source in a custom manner.

        If no exceptions occur then the source will move from 'tenuous'
        to 'known good'.

        >>> with run_context() as (known_good, source, ns):
        >>> ...  exec source in ns
        >>> ...  ns['draw']()

        """
        with LiveExecution.lock:
            if self.edited_source is None:
                yield True, self.known_good, self.ns
                return

            ns_snapshot = copy.copy(self.ns)
            try:
                yield False, self.edited_source, self.ns
                self.known_good = self.edited_source
                self.edited_source = None
                self.call_good_cb()
                return
            except Exception as ex:
                tb = traceback.format_exc()
                self.call_bad_cb(tb)
                self.edited_source = None
                self.ns.clear()
                self.ns.update(ns_snapshot)

def run_context ( self ) : with LiveExecution . lock : if self . edited_source is None : yield True , self . known_good , self . ns return ns_snapshot = copy . copy ( self . ns ) try : yield False , self . edited_source , self . ns self . known_good = self . edited_source self . edited_source = None self . call_good_cb ( ) return except Exception as ex : tb = traceback . format_exc ( ) self . call_bad_cb ( tb ) self . edited_source = None self . ns . clear ( ) self . ns . update ( ns_snapshot )

Context in which the user can run the source in a custom manner .


def separation(self, r=10):

        """ Boids keep a small distance from other boids.

        Ensures that boids don't collide into each other,
        in a smoothly accelerated motion.

        """

        vx = vy = vz = 0
        for b in self.boids:
            if b != self:
                if abs(self.x-b.x) < r: vx += (self.x-b.x)
                if abs(self.y-b.y) < r: vy += (self.y-b.y)
                if abs(self.z-b.z) < r: vz += (self.z-b.z)

        return vx, vy, vz

def separation ( self , r = 10 ) : vx = vy = vz = 0 for b in self . boids : if b != self : if abs ( self . x - b . x ) < r : vx += ( self . x - b . x ) if abs ( self . y - b . y ) < r : vy += ( self . y - b . y ) if abs ( self . z - b . z ) < r : vz += ( self . z - b . z ) return vx , vy , vz

Boids keep a small distance from other boids . Ensures that boids don t collide into each other in a smoothly accelerated motion .


def alignment(self, d=5):

        """ Boids match velocity with other boids.
        """

        vx = vy = vz = 0
        for b in self.boids:
           if b != self:
               vx, vy, vz = vx+b.vx, vy+b.vy, vz+b.vz

        n = len(self.boids)-1
        vx, vy, vz = vx/n, vy/n, vz/n

        return (vx-self.vx)/d, (vy-self.vy)/d, (vz-self.vz)/d

def alignment ( self , d = 5 ) : vx = vy = vz = 0 for b in self . boids : if b != self : vx , vy , vz = vx + b . vx , vy + b . vy , vz + b . vz n = len ( self . boids ) - 1 vx , vy , vz = vx / n , vy / n , vz / n return ( vx - self . vx ) / d , ( vy - self . vy ) / d , ( vz - self . vz ) / d


def limit(self, max=30):

        """ The speed limit for a boid.

        Boids can momentarily go very fast,
        something that is impossible for real animals.

        """

        if abs(self.vx) > max:
            self.vx = self.vx/abs(self.vx)*max
        if abs(self.vy) > max:
            self.vy = self.vy/abs(self.vy)*max
        if abs(self.vz) > max:
            self.vz = self.vz/abs(self.vz)*max

def limit ( self , max = 30 ) : if abs ( self . vx ) > max : self . vx = self . vx / abs ( self . vx ) * max if abs ( self . vy ) > max : self . vy = self . vy / abs ( self . vy ) * max if abs ( self . vz ) > max : self . vz = self . vz / abs ( self . vz ) * max

The speed limit for a boid . Boids can momentarily go very fast something that is impossible for real animals .


def _angle(self):

        """ Returns the angle towards which the boid is steering.
        """

        from math import atan, pi, degrees
        a = degrees(atan(self.vy/self.vx)) + 360
        if self.vx < 0: a += 180

        return a

def _angle ( self ) : from math import atan , pi , degrees a = degrees ( atan ( self . vy / self . vx ) ) + 360 if self . vx < 0 : a += 180 return a

Returns the angle towards which the boid is steering .


def goal(self, x, y, z, d=50.0):

        """ Tendency towards a particular place.
        """

        return (x-self.x)/d, (y-self.y)/d, (z-self.z)/d

def goal ( self , x , y , z , d = 50.0 ) : return ( x - self . x ) / d , ( y - self . y ) / d , ( z - self . z ) / d


def update(self,
               shuffled=True,
               cohesion=100,
               separation=10,
               alignment=5,
               goal=20,
               limit=30):

        """ Calculates the next motion frame for the flock.
        """

        # Shuffling the list of boids ensures fluid movement.
        # If you need the boids to retain their position in the list
        # each update, set the shuffled parameter to False.
        from random import shuffle
        if shuffled: shuffle(self)

        m1 = 1.0 # cohesion
        m2 = 1.0 # separation
        m3 = 1.0 # alignment
        m4 = 1.0 # goal

        # The flock scatters randomly with a Boids.scatter chance.
        # This means their cohesion (m1) is reversed,
        # and their joint alignment (m3) is dimished,
        # causing boids to oscillate in confusion.
        # Setting Boids.scatter(chance=0) ensures they never scatter.
        if not self.scattered and _ctx.random() < self._scatter:
            self.scattered = True
        if self.scattered:
            m1 = -m1
            m3 *= 0.25
            self._scatter_i += 1
        if self._scatter_i >= self._scatter_t:
            self.scattered = False
            self._scatter_i = 0

        # A flock can have a goal defined with Boids.goal(x,y,z),
        # a place of interest to flock around.
        if not self.has_goal:
            m4 = 0
        if self.flee:
            m4 = -m4

        for b in self:

            # A boid that is perching will continue to do so
            # until Boid._perch_t reaches zero.
            if b.is_perching:
                if b._perch_t > 0:
                    b._perch_t -= 1
                    continue
                else:
                    b.is_perching = False

            vx1, vy1, vz1 = b.cohesion(cohesion)
            vx2, vy2, vz2 = b.separation(separation)
            vx3, vy3, vz3 = b.alignment(alignment)
            vx4, vy4, vz4 = b.goal(self._gx, self._gy, self._gz, goal)

            b.vx += m1*vx1 + m2*vx2 + m3*vx3 + m4*vx4
            b.vy += m1*vy1 + m2*vy2 + m3*vy3 + m4*vy4
            b.vz += m1*vz1 + m2*vz2 + m3*vz3 + m4*vz4

            b.limit(limit)

            b.x += b.vx
            b.y += b.vy
            b.z += b.vz

        self.constrain()

Calculates the next motion frame for the flock .


def iterscan(self, string, idx=0, context=None):
        """
        Yield match, end_idx for each match
        """
        match = self.scanner.scanner(string, idx).match
        actions = self.actions
        lastend = idx
        end = len(string)
        while True:
            m = match()
            if m is None:
                break
            matchbegin, matchend = m.span()
            if lastend == matchend:
                break
            action = actions[m.lastindex]
            if action is not None:
                rval, next_pos = action(m, context)
                if next_pos is not None and next_pos != matchend:
                    # "fast forward" the scanner
                    matchend = next_pos
                    match = self.scanner.scanner(string, matchend).match
                yield rval, matchend
            lastend = matchend

def
iterscan
(
self
,
string
,
idx
=
0
,
context
=
)
:
match
=
self
.
scanner
.
scanner
(
string
,
idx
)
.
match
actions
=
self
.
actions
lastend
=
idx
end
=
len
(
string
)
while
True
:
m
=
match
(
)
if
m
is
:
break
matchbegin
,
matchend
=
m
.
span
(
)
if
lastend
==
matchend
:
break
action
=
actions
[
m
.
lastindex
]
if
action
is
not
:
rval
,
next_pos
=
action
(
m
,
context
)
if
next_pos
is
not
and
next_pos
!=
matchend
:
# "fast forward" the scanner
matchend
=
next_pos
match
=
self
.
scanner
.
scanner
(
string
,
matchend
)
.
match
yield
rval
,
matchend
lastend
=
matchend


def copy(self, graph):

        """ Returns a copy of the layout for the given graph.
        """

        l = self.__class__(graph, self.n)
        l.i = 0
        return l

def copy ( self , graph ) : l = self . __class__ ( graph , self . n ) l . i = 0 return l

Returns a copy of the layout for the given graph .


def can_reach(self, node, traversable=lambda node, edge: True):

        """ Returns True if given node can be reached over traversable edges.
        To enforce edge direction, use a node==edge.node1 traversable.
        """

        if isinstance(node, str):
            node = self.graph[node]
        for n in self.graph.nodes:
            n._visited = False
        return proximity.depth_first_search(self,
            visit=lambda n: node == n,
            traversable=traversable
            )

def can_reach ( self , node , traversable = lambda node , edge : True ) : if isinstance ( node , str ) : node = self . graph [ node ] for n in self . graph . nodes : n . _visited = False return proximity . depth_first_search ( self , visit = lambda n : node == n , traversable = traversable )

Returns True if given node can be reached over traversable edges . To enforce edge direction use a node == edge . node1 traversable .