def delete_bytes(fobj, size, offset, BUFFER_SIZE=2**16):
    """Delete size bytes of empty space starting at offset.

    fobj must be an open file object, open rb+ or
    equivalent. Mutagen tries to use mmap to resize the file, but
    falls back to a significantly slower method if mmap fails.
    """

    locked = False
    assert 0 < size
    assert 0 <= offset
    fobj.seek(0, 2)
    filesize = fobj.tell()
    movesize = filesize - offset - size
    assert 0 <= movesize
    try:
        if movesize > 0:
            fobj.flush()
            try:
                import mmap
                file_map = mmap.mmap(fobj.fileno(), filesize)
                try:
                    file_map.move(offset, offset + size, movesize)
                finally:
                    file_map.close()
            except (ValueError, EnvironmentError, ImportError):
                # handle broken mmap scenarios
                locked = lock(fobj)
                fobj.seek(offset + size)
                buf = fobj.read(BUFFER_SIZE)
                while buf:
                    fobj.seek(offset)
                    fobj.write(buf)
                    offset += len(buf)
                    fobj.seek(offset + size)
                    buf = fobj.read(BUFFER_SIZE)
        fobj.truncate(filesize - size)
        fobj.flush()
    finally:
        if locked:
            unlock(fobj)

def
delete_bytes
(
fobj
,
size
,
offset
,
BUFFER_SIZE
=
2
**
16
)
:
locked
=
False
assert
0
<
size
assert
0
<=
offset
fobj
.
seek
(
0
,
2
)
filesize
=
fobj
.
tell
(
)
movesize
=
filesize
offset
size
assert
0
<=
movesize
try
:
if
movesize
>
0
:
fobj
.
flush
(
)
try
:
import
mmap
file_map
=
mmap
.
mmap
(
fobj
.
fileno
(
)
,
filesize
)
try
:
file_map
.
move
(
offset
,
offset
+
size
,
movesize
)
finally
:
file_map
.
close
(
)
except
(
ValueError
,
EnvironmentError
,
ImportError
)
:
# handle broken mmap scenarios
locked
=
lock
(
fobj
)
fobj
.
seek
(
offset
+
size
)
buf
=
fobj
.
read
(
BUFFER_SIZE
)
while
buf
:
fobj
.
seek
(
offset
)
fobj
.
write
(
buf
)
offset
+=
len
(
buf
)
fobj
.
seek
(
offset
+
size
)
buf
=
fobj
.
read
(
BUFFER_SIZE
)
fobj
.
truncate
(
filesize
size
)
fobj
.
flush
(
)
finally
:
if
locked
:
unlock
(
fobj
)

Delete size bytes of empty space starting at offset .


def utf8(data):
    """Convert a basestring to a valid UTF-8 str."""

    if isinstance(data, bytes):
        return data.decode("utf-8", "replace").encode("utf-8")
    elif isinstance(data, text_type):
        return data.encode("utf-8")
    else:
        raise TypeError("only unicode/bytes types can be converted to UTF-8")

Convert a basestring to a valid UTF - 8 str .


def add_change(self, action, record_set):
        """
        Adds a change to this change set.

        :param str action: Must be one of either 'CREATE' or 'DELETE'.
        :param resource_record_set.ResourceRecordSet record_set: The
            ResourceRecordSet object that was created or deleted.
        """

        action = action.upper()

        if action not in ['CREATE', 'DELETE']:
            raise Route53Error("action must be one of 'CREATE' or 'DELETE'")

        change_tuple = (action, record_set)

        if action == 'CREATE':
            self.creations.append(change_tuple)
        else:
            self.deletions.append(change_tuple)


def parse_change_info(e_change_info):
    """
    Parses a ChangeInfo tag. Seen in CreateHostedZone, DeleteHostedZone,
    and ChangeResourceRecordSetsRequest.

    :param lxml.etree._Element e_change_info: A ChangeInfo element.
    :rtype: dict
    :returns: A dict representation of the change info.
    """

    if e_change_info is None:
        return e_change_info

    status = e_change_info.find('./{*}Status').text
    submitted_at = e_change_info.find('./{*}SubmittedAt').text
    submitted_at = parse_iso_8601_time_str(submitted_at)

    return {
        'request_id': id,
        'request_status': status,
        'request_submitted_at': submitted_at
    }

def parse_change_info ( e_change_info ) : if e_change_info is None : return e_change_info status = e_change_info . find ( './{*}Status' ) . text submitted_at = e_change_info . find ( './{*}SubmittedAt' ) . text submitted_at = parse_iso_8601_time_str ( submitted_at ) return { 'request_id' : id , 'request_status' : status , 'request_submitted_at' : submitted_at }

Parses a ChangeInfo tag . Seen in CreateHostedZone DeleteHostedZone and ChangeResourceRecordSetsRequest .


def measure_string(self, str):
        '''Calculates the width of the given string in this font.

        :param str: the string to measure
        :return float: width of the string, in pixels
        '''
        style = bacon.text.Style(self)
        run = bacon.text.GlyphRun(style, str)
        glyph_layout = bacon.text.GlyphLayout([run], 0, 0)
        return glyph_layout.content_width

def measure_string ( self , str ) : style = bacon . text . Style ( self ) run = bacon . text . GlyphRun ( style , str ) glyph_layout = bacon . text . GlyphLayout ( [ run ] , 0 , 0 ) return glyph_layout . content_width

Calculates the width of the given string in this font .


def is_modified(self):
        """
        Determines whether this record set has been modified since the
        last retrieval or save.

        :rtype: bool
        :returns: ``True` if the record set has been modified,
            and ``False`` if not.
        """

        for key, val in self._initial_vals.items():
            if getattr(self, key) != val:
                # One of the initial values doesn't match, we know
                # this object has been touched.
                return True

        return False

Determines whether this record set has been modified since the last retrieval or save .


def delete(self):
        """
        Deletes this record set.
        """

        cset = ChangeSet(connection=self.connection, hosted_zone_id=self.zone_id)
        cset.add_change('DELETE', self)

        return self.connection._change_resource_record_sets(cset)

def delete ( self ) : cset = ChangeSet ( connection = self . connection , hosted_zone_id = self . zone_id ) cset . add_change ( 'DELETE' , self ) return self . connection . _change_resource_record_sets ( cset )


def save(self):
        """
        Saves any changes to this record set.
        """

        cset = ChangeSet(connection=self.connection, hosted_zone_id=self.zone_id)
        # Record sets can't actually be modified. You have to delete the
        # existing one and create a new one. Since this happens within a single
        # change set, it appears that the values were modified, when instead
        # the whole thing is replaced.
        cset.add_change('DELETE', self)
        cset.add_change('CREATE', self)
        retval = self.connection._change_resource_record_sets(cset)

        # Now copy the current attribute values on this instance to
        # the initial_vals dict. This will re-set the modification tracking.
        for key, val in self._initial_vals.items():
            self._initial_vals[key] = getattr(self, key)

        return retval


def ParseID3v1(data):
    """Parse an ID3v1 tag, returning a list of ID3v2.4 frames."""

    try:
        data = data[data.index(b'TAG'):]
    except ValueError:
        return None
    if 128 < len(data) or len(data) < 124:
        return None

    # Issue #69 - Previous versions of Mutagen, when encountering
    # out-of-spec TDRC and TYER frames of less than four characters,
    # wrote only the characters available - e.g. "1" or "" - into the
    # year field. To parse those, reduce the size of the year field.
    # Amazingly, "0s" works as a struct format string.
    unpack_fmt = "3s30s30s30s%ds29sBB" % (len(data) - 124)

    try:
        tag, title, artist, album, year, comment, track, genre = unpack(
            unpack_fmt, data)
    except StructError:
        return None

    if tag != b"TAG":
        return None

    def fix(data):
        return data.split(b'\x00')[0].strip().decode('latin1')

    title, artist, album, year, comment = map(
        fix, [title, artist, album, year, comment])

    frames = {}
    if title:
        frames['TIT2'] = TIT2(encoding=0, text=title)
    if artist:
        frames['TPE1'] = TPE1(encoding=0, text=[artist])
    if album:
        frames['TALB'] = TALB(encoding=0, text=album)
    if year:
        frames['TDRC'] = TDRC(encoding=0, text=year)
    if comment:
        frames['COMM'] = COMM(encoding=0, lang='eng', desc="ID3v1 Comment",
                              text=comment)

    # Don't read a track number if it looks like the comment was
    # padded with spaces instead of nulls (thanks, WinAmp).
    if track and ((track != 32) or (data[-3] == b'\x00'[0])):
        frames['TRCK'] = TRCK(encoding=0, text=str(track))
    if genre != 255:
        frames['TCON'] = TCON(encoding=0, text=str(genre))
    return frames

Parse an ID3v1 tag returning a list of ID3v2 . 4 frames .


def MakeID3v1(id3):
    """Return an ID3v1.1 tag string from a dict of ID3v2.4 frames."""

    v1 = {}

    for v2id, name in {"TIT2": "title", "TPE1": "artist",
                       "TALB": "album"}.items():
        if v2id in id3:
            text = id3[v2id].text[0].encode('latin1', 'replace')[:30]
        else:
            text = b''
        v1[name] = text + (b'\x00' * (30 - len(text)))

    if "COMM" in id3:
        cmnt = id3["COMM"].text[0].encode('latin1', 'replace')[:28]
    else:
        cmnt = b''
    v1['comment'] = cmnt + (b'\x00' * (29 - len(cmnt)))

    if "TRCK" in id3:
        try:
            v1["track"] = chr_(+id3["TRCK"])
        except ValueError:
            v1["track"] = b'\x00'
    else:
        v1["track"] = b'\x00'

    if "TCON" in id3:
        try:
            genre = id3["TCON"].genres[0]
        except IndexError:
            pass
        else:
            if genre in TCON.GENRES:
                v1["genre"] = chr_(TCON.GENRES.index(genre))
    if "genre" not in v1:
        v1["genre"] = b"\xff"

    if "TDRC" in id3:
        year = text_type(id3["TDRC"]).encode('latin1', 'replace')
    elif "TYER" in id3:
        year = text_type(id3["TYER"]).encode('latin1', 'replace')
    else:
        year = b''
    v1['year'] = (year + b'\x00\x00\x00\x00')[:4]

    return (b'TAG' +
            v1['title'] +
            v1['artist'] +
            v1['album'] +
            v1['year'] +
            v1['comment'] +
            v1['track'] +
            v1['genre'])

def MakeID3v1 ( id3 ) : v1 = { } for v2id , name in { "TIT2" : "title" , "TPE1" : "artist" , "TALB" : "album" } . items ( ) : if v2id in id3 : text = id3 [ v2id ] . text [ 0 ] . encode ( 'latin1' , 'replace' ) [ : 30 ] else : text = b'' v1 [ name ] = text + ( b'\x00' * ( 30 - len ( text ) ) ) if "COMM" in id3 : cmnt = id3 [ "COMM" ] . text [ 0 ] . encode ( 'latin1' , 'replace' ) [ : 28 ] else : cmnt = b'' v1 [ 'comment' ] = cmnt + ( b'\x00' * ( 29 - len ( cmnt ) ) ) if "TRCK" in id3 : try : v1 [ "track" ] = chr_ ( + id3 [ "TRCK" ] ) except ValueError : v1 [ "track" ] = b'\x00' else : v1 [ "track" ] = b'\x00' if "TCON" in id3 : try : genre = id3 [ "TCON" ] . genres [ 0 ] except IndexError : pass else : if genre in TCON . GENRES : v1 [ "genre" ] = chr_ ( TCON . GENRES . index ( genre ) ) if "genre" not in v1 : v1 [ "genre" ] = b"\xff" if "TDRC" in id3 : year = text_type ( id3 [ "TDRC" ] ) . encode ( 'latin1' , 'replace' ) elif "TYER" in id3 : year = text_type ( id3 [ "TYER" ] ) . encode ( 'latin1' , 'replace' ) else : year = b'' v1 [ 'year' ] = ( year + b'\x00\x00\x00\x00' ) [ : 4 ] return ( b'TAG' + v1 [ 'title' ] + v1 [ 'artist' ] + v1 [ 'album' ] + v1 [ 'year' ] + v1 [ 'comment' ] + v1 [ 'track' ] + v1 [ 'genre' ] )

Return an ID3v1 . 1 tag string from a dict of ID3v2 . 4 frames .


def __fullread(self, size):
        """ Read a certain number of bytes from the source file. """

        try:
            if size < 0:
                raise ValueError('Requested bytes (%s) less than zero' % size)
            if size > self.__filesize:
                raise EOFError('Requested %#x of %#x (%s)' % (
                    int(size), int(self.__filesize), self.filename))
        except AttributeError:
            pass
        data = self._fileobj.read(size)
        if len(data) != size:
            raise EOFError
        self.__readbytes += size
        return data

def
__fullread
(
self
,
size
)
:
try
:
if
size
<
0
:
raise
ValueError
(
'Requested bytes (%s) less than zero'
%
size
)
if
size
>
self
.
__filesize
:
raise
EOFError
(
'Requested %#x of %#x (%s)'
%
(
int
(
size
)
,
int
(
self
.
__filesize
)
,
self
.
filename
)
)
except
AttributeError
:
pass
data
=
self
.
_fileobj
.
read
(
size
)
if
len
(
data
)
!=
size
:
raise
EOFError
self
.
__readbytes
+=
size
return
data

Read a certain number of bytes from the source file .


def delall(self, key):
        """Delete all tags of a given kind; see getall."""
        if key in self:
            del(self[key])
        else:
            key = key + ":"
            for k in self.keys():
                if k.startswith(key):
                    del(self[k])

def delall ( self , key ) : if key in self : del ( self [ key ] ) else : key = key + ":" for k in self . keys ( ) : if k . startswith ( key ) : del ( self [ k ] )

Delete all tags of a given kind ; see getall .


def loaded_frame(self, tag):
        """Deprecated; use the add method."""
        # turn 2.2 into 2.3/2.4 tags
        if len(type(tag).__name__) == 3:
            tag = type(tag).__base__(tag)
        self[tag.HashKey] = tag

def
loaded_frame
(
self
,
tag
)
:
# turn 2.2 into 2.3/2.4 tags
if
len
(
type
(
tag
)
.
__name__
)
==
3
:
tag
=
type
(
tag
)
.
__base__
(
tag
)
self
[
tag
.
HashKey
]
=
tag


def __update_common(self):
        """Updates done by both v23 and v24 update"""

        if "TCON" in self:
            # Get rid of "(xx)Foobr" format.
            self["TCON"].genres = self["TCON"].genres

        if self.version < self._V23:
            # ID3v2.2 PIC frames are slightly different.
            pics = self.getall("APIC")
            mimes = {"PNG": "image/png", "JPG": "image/jpeg"}
            self.delall("APIC")
            for pic in pics:
                newpic = APIC(
                    encoding=pic.encoding, mime=mimes.get(pic.mime, pic.mime),
                    type=pic.type, desc=pic.desc, data=pic.data)
                self.add(newpic)

            # ID3v2.2 LNK frames are just way too different to upgrade.
            self.delall("LINK")


def update_to_v24(self):
        """Convert older tags into an ID3v2.4 tag.

        This updates old ID3v2 frames to ID3v2.4 ones (e.g. TYER to
        TDRC). If you intend to save tags, you must call this function
        at some point; it is called by default when loading the tag.
        """

        self.__update_common()

        if self.__unknown_version == self._V23:
            # convert unknown 2.3 frames (flags/size) to 2.4
            converted = []
            for frame in self.unknown_frames:
                try:
                    name, size, flags = unpack('>4sLH', frame[:10])
                    frame = BinaryFrame.fromData(self, flags, frame[10:])
                except (struct.error, error):
                    continue
                name = name.decode('ascii')
                converted.append(self.__save_frame(frame, name=name))
            self.unknown_frames[:] = converted
            self.__unknown_version = self._V24

        # TDAT, TYER, and TIME have been turned into TDRC.
        try:
            date = text_type(self.get("TYER", ""))
            if date.strip(u"\x00"):
                self.pop("TYER")
                dat = text_type(self.get("TDAT", ""))
                if dat.strip("\x00"):
                    self.pop("TDAT")
                    date = "%s-%s-%s" % (date, dat[2:], dat[:2])
                    time = text_type(self.get("TIME", ""))
                    if time.strip("\x00"):
                        self.pop("TIME")
                        date += "T%s:%s:00" % (time[:2], time[2:])
                if "TDRC" not in self:
                    self.add(TDRC(encoding=0, text=date))
        except UnicodeDecodeError:
            # Old ID3 tags have *lots* of Unicode problems, so if TYER
            # is bad, just chuck the frames.
            pass

        # TORY can be the first part of a TDOR.
        if "TORY" in self:
            f = self.pop("TORY")
            if "TDOR" not in self:
                try:
                    self.add(TDOR(encoding=0, text=str(f)))
                except UnicodeDecodeError:
                    pass

        # IPLS is now TIPL.
        if "IPLS" in self:
            f = self.pop("IPLS")
            if "TIPL" not in self:
                self.add(TIPL(encoding=f.encoding, people=f.people))

        # These can't be trivially translated to any ID3v2.4 tags, or
        # should have been removed already.
        for key in ["RVAD", "EQUA", "TRDA", "TSIZ", "TDAT", "TIME", "CRM"]:
            if key in self:
                del(self[key])

Convert older tags into an ID3v2 . 4 tag .


def unload(self):
        '''Release all resources associated with the sound.'''
        if self._handle != -1:
            lib.UnloadSound(self._handle)
            self._handle = -1

def unload ( self ) : if self . _handle != - 1 : lib . UnloadSound ( self . _handle ) self . _handle = - 1

Release all resources associated with the sound .


def play(self, gain=None, pan=None, pitch=None):
        '''Play the sound as a `one-shot`.

        The sound will be played to completion.  If the sound is played more than once at a time, it will mix
        with all previous instances of itself.  If you need more control over the playback of sounds, see
        :class:`Voice`.

        :param gain: optional volume level to play the sound back at, between 0.0 and 1.0 (defaults to 1.0)
        :param pan: optional stereo pan, between -1.0 (left) and 1.0 (right)
        :param pitch: optional sampling rate modification, between 0.4 and 16.0, where 1.0 represents the original pitch
        '''
        if gain is None and pan is None and pitch is None:
            lib.PlaySound(self._handle)
        else:
            voice = Voice(self)
            if gain is not None:
                voice.gain = gain
            if pan is not None:
                voice.pan = pan
            if pitch is not None:
                voice.pitch = pitch
            voice.play()

def play ( self , gain = None , pan = None , pitch = None ) : if gain is None and pan is None and pitch is None : lib . PlaySound ( self . _handle ) else : voice = Voice ( self ) if gain is not None : voice . gain = gain if pan is not None : voice . pan = pan if pitch is not None : voice . pitch = pitch voice . play ( )


def set_loop_points(self, start_sample=-1, end_sample=0):
        '''Set the loop points within the sound.

        The sound must have been created with ``loop=True``.  The default parameters cause the loop points to be set to
        the entire sound duration.

        :note: There is currently no API for converting sample numbers to times.
        :param start_sample: sample number to loop back to
        :param end_sample: sample number to loop at
        '''
        lib.SetVoiceLoopPoints(self._handle, start_sample, end_sample)

def set_loop_points ( self , start_sample = - 1 , end_sample = 0 ) : lib . SetVoiceLoopPoints ( self . _handle , start_sample , end_sample )


def adobe_glyph_values():
  """return the list of glyph names and their unicode values"""

  lines  = string.split( adobe_glyph_list, '\n' )
  glyphs = []
  values = []

  for line in lines:
    if line:
      fields = string.split( line, ';' )
#     print fields[1] + ' - ' + fields[0]
      subfields = string.split( fields[1], ' ' )
      if len( subfields ) == 1:
        glyphs.append( fields[0] )
        values.append( fields[1] )

  return glyphs, values

#     print fields[1] + ' - ' + fields[0]


def filter_glyph_names( alist, filter ):
  """filter `alist' by taking _out_ all glyph names that are in `filter'"""

  count  = 0
  extras = []

  for name in alist:
    try:
      filtered_index = filter.index( name )
    except:
      extras.append( name )

  return extras

def filter_glyph_names ( alist , filter ) : count = 0 extras = [ ] for name in alist : try : filtered_index = filter . index ( name ) except : extras . append ( name ) return extras

filter alist by taking _out_ all glyph names that are in filter


def dump_encoding( file, encoding_name, encoding_list ):
  """dump a given encoding"""

  write = file.write
  write( "  /* the following are indices into the SID name table */\n" )
  write( "  static const unsigned short  " + encoding_name +
         "[" + repr( len( encoding_list ) ) + "] =\n" )
  write( "  {\n" )

  line  = "    "
  comma = ""
  col   = 0
  for value in encoding_list:
    line += comma
    line += "%3d" % value
    comma = ","
    col  += 1
    if col == 16:
      col = 0
      comma = ",\n    "

  write( line + "\n  };\n\n\n" )


def dump_array( the_array, write, array_name ):
  """dumps a given encoding"""

  write( "  static const unsigned char  " + array_name +
         "[" + repr( len( the_array ) ) + "L] =\n" )
  write( "  {\n" )

  line  = ""
  comma = "    "
  col   = 0

  for value in the_array:
    line += comma
    line += "%3d" % ord( value )
    comma = ","
    col  += 1

    if col == 16:
      col   = 0
      comma = ",\n    "

    if len( line ) > 1024:
      write( line )
      line = ""

  write( line + "\n  };\n\n\n" )

def
dump_array
(
the_array
,
write
,
array_name
)
:
write
(
"  static const unsigned char  "
+
array_name
+
"["
+
repr
(
len
(
the_array
)
)
+
"L] =\n"
)
write
(
"  {\n"
)
line
=
""
comma
=
"    "
col
=
0
for
value
in
the_array
:
line
+=
comma
line
+=
"%3d"
%
ord
(
value
)
comma
=
","
col
+=
1
if
col
==
16
:
col
=
0
comma
=
",\n    "
if
len
(
line
)
>
1024
:
write
(
line
)
line
=
""
write
(
line
+
"\n  };\n\n\n"
)


def main():
  """main program body"""

  if len( sys.argv ) != 2:
    print __doc__ % sys.argv[0]
    sys.exit( 1 )

  file  = open( sys.argv[1], "w\n" )
  write = file.write

  count_sid = len( sid_standard_names )

  # `mac_extras' contains the list of glyph names in the Macintosh standard
  # encoding which are not in the SID Standard Names.
  #
  mac_extras = filter_glyph_names( mac_standard_names, sid_standard_names )

  # `base_list' contains the names of our final glyph names table.
  # It consists of the `mac_extras' glyph names, followed by the SID
  # standard names.
  #
  mac_extras_count = len( mac_extras )
  base_list        = mac_extras + sid_standard_names

  write( "/***************************************************************************/\n" )
  write( "/*                                                                         */\n" )

  write( "/*  %-71s*/\n" % os.path.basename( sys.argv[1] ) )

  write( "/*                                                                         */\n" )
  write( "/*    PostScript glyph names.                                              */\n" )
  write( "/*                                                                         */\n" )
  write( "/*  Copyright 2005, 2008, 2011 by                                          */\n" )
  write( "/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */\n" )
  write( "/*                                                                         */\n" )
  write( "/*  This file is part of the FreeType project, and may only be used,       */\n" )
  write( "/*  modified, and distributed under the terms of the FreeType project      */\n" )
  write( "/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */\n" )
  write( "/*  this file you indicate that you have read the license and              */\n" )
  write( "/*  understand and accept it fully.                                        */\n" )
  write( "/*                                                                         */\n" )
  write( "/***************************************************************************/\n" )
  write( "\n" )
  write( "\n" )
  write( "  /* This file has been generated automatically -- do not edit! */\n" )
  write( "\n" )
  write( "\n" )

  # dump final glyph list (mac extras + sid standard names)
  #
  st = StringTable( base_list, "ft_standard_glyph_names" )

  st.dump( file )
  st.dump_sublist( file, "ft_mac_names",
                   "FT_NUM_MAC_NAMES", mac_standard_names )
  st.dump_sublist( file, "ft_sid_names",
                   "FT_NUM_SID_NAMES", sid_standard_names )

  dump_encoding( file, "t1_standard_encoding", t1_standard_encoding )
  dump_encoding( file, "t1_expert_encoding", t1_expert_encoding )

  # dump the AGL in its compressed form
  #
  agl_glyphs, agl_values = adobe_glyph_values()
  dict = StringNode( "", 0 )

  for g in range( len( agl_glyphs ) ):
    dict.add( agl_glyphs[g], eval( "0x" + agl_values[g] ) )

  dict       = dict.optimize()
  dict_len   = dict.locate( 0 )
  dict_array = dict.store( "" )

  write( """\
  /*
   *  This table is a compressed version of the Adobe Glyph List (AGL),
   *  optimized for efficient searching.  It has been generated by the
   *  `glnames.py' python script located in the `src/tools' directory.
   *
   *  The lookup function to get the Unicode value for a given string
   *  is defined below the table.
   */

#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST

""" )

  dump_array( dict_array, write, "ft_adobe_glyph_list" )

  # write the lookup routine now
  #
  write( """\
  /*
   *  This function searches the compressed table efficiently.
   */
  static unsigned long
  ft_get_adobe_glyph_index( const char*  name,
                            const char*  limit )
  {
    int                   c = 0;
    int                   count, min, max;
    const unsigned char*  p = ft_adobe_glyph_list;

    if ( name == 0 || name >= limit )
      goto NotFound;

    c     = *name++;
    count = p[1];
    p    += 2;

    min = 0;
    max = count;

    while ( min < max )
    {
      int                   mid = ( min + max ) >> 1;
      const unsigned char*  q   = p + mid * 2;
      int                   c2;

      q = ft_adobe_glyph_list + ( ( (int)q[0] << 8 ) | q[1] );

      c2 = q[0] & 127;
      if ( c2 == c )
      {
        p = q;
        goto Found;
      }
      if ( c2 < c )
        min = mid + 1;
      else
        max = mid;
    }
    goto NotFound;

  Found:
    for (;;)
    {
      /* assert (*p & 127) == c */

      if ( name >= limit )
      {
        if ( (p[0] & 128) == 0 &&
             (p[1] & 128) != 0 )
          return (unsigned long)( ( (int)p[2] << 8 ) | p[3] );

        goto NotFound;
      }
      c = *name++;
      if ( p[0] & 128 )
      {
        p++;
        if ( c != (p[0] & 127) )
          goto NotFound;

        continue;
      }

      p++;
      count = p[0] & 127;
      if ( p[0] & 128 )
        p += 2;

      p++;

      for ( ; count > 0; count--, p += 2 )
      {
        int                   offset = ( (int)p[0] << 8 ) | p[1];
        const unsigned char*  q      = ft_adobe_glyph_list + offset;

        if ( c == ( q[0] & 127 ) )
        {
          p = q;
          goto NextIter;
        }
      }
      goto NotFound;

    NextIter:
      ;
    }

  NotFound:
    return 0;
  }

#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */

""" )

  if 0:  # generate unit test, or don't
    #
    # now write the unit test to check that everything works OK
    #
    write( "#ifdef TEST\n\n" )

    write( "static const char* const  the_names[] = {\n" )
    for name in agl_glyphs:
      write( '  "' + name + '",\n' )
    write( "  0\n};\n" )

    write( "static const unsigned long  the_values[] = {\n" )
    for val in agl_values:
      write( '  0x' + val + ',\n' )
    write( "  0\n};\n" )

    write( """
#include <stdlib.h>
#include <stdio.h>

  int
  main( void )
  {
    int                   result = 0;
    const char* const*    names  = the_names;
    const unsigned long*  values = the_values;

    for ( ; *names; names++, values++ )
    {
      const char*    name      = *names;
      unsigned long  reference = *values;
      unsigned long  value;

      value = ft_get_adobe_glyph_index( name, name + strlen( name ) );
      if ( value != reference )
      {
        result = 1;
        fprintf( stderr, "name '%s' => %04x instead of %04x\\n",
                         name, value, reference );
      }
    }

    return result;
  }
""" )

    write( "#endif /* TEST */\n" )

  write("\n/* END */\n")

"/*    PostScript glyph names.                                              */\n"


def  file_exists( pathname ):
    """checks that a given file exists"""
    result = 1
    try:
        file = open( pathname, "r" )
        file.close()
    except:
        result = None
        sys.stderr.write( pathname + " couldn't be accessed\n" )

    return result

def
file_exists
(
pathname
)
:
result
=
1
try
:
file
=
open
(
pathname
,
"r"
)
file
.
close
(
)
except
:
result
=
sys
.
stderr
.
write
(
pathname
+
" couldn't be accessed\n"
)
return
result


def  make_file_list( args = None ):
    """builds a list of input files from command-line arguments"""
    file_list = []
    # sys.stderr.write( repr( sys.argv[1 :] ) + '\n' )

    if not args:
        args = sys.argv[1 :]

    for pathname in args:
        if string.find( pathname, '*' ) >= 0:
            newpath = glob.glob( pathname )
            newpath.sort()  # sort files -- this is important because
                            # of the order of files
        else:
            newpath = [pathname]

        file_list.extend( newpath )

    if len( file_list ) == 0:
        file_list = None
    else:
        # now filter the file list to remove non-existing ones
        file_list = filter( file_exists, file_list )

    return file_list

builds a list of input files from command - line arguments


def parse_hosted_zone(e_zone, connection):
    """
    This a common parser that allows the passing of any valid HostedZone
    tag. It will spit out the appropriate HostedZone object for the tag.

    :param lxml.etree._Element e_zone: The root node of the etree parsed
        response from the API.
    :param Route53Connection connection: The connection instance used to
        query the API.
    :rtype: HostedZone
    :returns: An instantiated HostedZone object.
    """

    # This dict will be used to instantiate a HostedZone instance to yield.
    kwargs = {}
    # Within HostedZone tags are a number of sub-tags that include info
    # about the instance.
    for e_field in e_zone:
        # Cheesy way to strip off the namespace.
        tag_name = e_field.tag.split('}')[1]
        field_text = e_field.text

        if tag_name == 'Config':
            # Config has the Comment tag beneath it, needing
            # special handling.
            e_comment = e_field.find('./{*}Comment')
            kwargs['comment'] = e_comment.text if e_comment is not None else None
            continue
        elif tag_name == 'Id':
            # This comes back with a path prepended. Yank that sillyness.
            field_text = field_text.strip('/hostedzone/')

        # Map the XML tag name to a kwarg name.
        kw_name = HOSTED_ZONE_TAG_TO_KWARG_MAP[tag_name]
        # This will be the key/val pair used to instantiate the
        # HostedZone instance.
        kwargs[kw_name] = field_text

    return HostedZone(connection, **kwargs)

This a common parser that allows the passing of any valid HostedZone tag . It will spit out the appropriate HostedZone object for the tag .


def parse_delegation_set(zone, e_delegation_set):
    """
    Parses a DelegationSet tag. These often accompany HostedZone tags in
    responses like CreateHostedZone and GetHostedZone.

    :param HostedZone zone: An existing HostedZone instance to populate.
    :param lxml.etree._Element e_delegation_set: A DelegationSet element.
    """

    e_nameservers = e_delegation_set.find('./{*}NameServers')

    nameservers = []
    for e_nameserver in e_nameservers:
        nameservers.append(e_nameserver.text)

    zone._nameservers = nameservers

def parse_delegation_set ( zone , e_delegation_set ) : e_nameservers = e_delegation_set . find ( './{*}NameServers' ) nameservers = [ ] for e_nameserver in e_nameservers : nameservers . append ( e_nameserver . text ) zone . _nameservers = nameservers

Parses a DelegationSet tag . These often accompany HostedZone tags in responses like CreateHostedZone and GetHostedZone .


def writeblocks(blocks):
        """Render metadata block as a byte string."""
        data = []
        codes = [[block.code, block.write()] for block in blocks]
        codes[-1][0] |= 128
        for code, datum in codes:
            byte = chr_(code)
            if len(datum) > 2**24:
                raise error("block is too long to write")
            length = struct.pack(">I", len(datum))[-3:]
            data.append(byte + length + datum)
        return b"".join(data)

def
writeblocks
(
blocks
)
:
data
=
[
]
codes
=
[
[
block
.
code
,
block
.
write
(
)
]
for
block
in
blocks
]
codes
[
1
]
[
0
]
|=
128
for
code
,
datum
in
codes
:
byte
=
chr_
(
code
)
if
len
(
datum
)
>
2
**
24
:
raise
error
(
"block is too long to write"
)
length
=
struct
.
pack
(
">I"
,
len
(
datum
)
)
[
3
:
]
data
.
append
(
byte
+
length
+
datum
)
return
b""
.
join
(
data
)

Render metadata block as a byte string .


def group_padding(blocks):
        """Consolidate FLAC padding metadata blocks.

        The overall size of the rendered blocks does not change, so
        this adds several bytes of padding for each merged block.
        """

        paddings = [b for b in blocks if isinstance(b, Padding)]
        for p in paddings:
            blocks.remove(p)
        # total padding size is the sum of padding sizes plus 4 bytes
        # per removed header.
        size = sum(padding.length for padding in paddings)
        padding = Padding()
        padding.length = size + 4 * (len(paddings) - 1)
        blocks.append(padding)

Consolidate FLAC padding metadata blocks .


def delete(self, filename=None):
        """Remove Vorbis comments from a file.

        If no filename is given, the one most recently loaded is used.
        """
        if filename is None:
            filename = self.filename
        for s in list(self.metadata_blocks):
            if isinstance(s, VCFLACDict):
                self.metadata_blocks.remove(s)
                self.tags = None
                self.save()
                break

def delete ( self , filename = None ) : if filename is None : filename = self . filename for s in list ( self . metadata_blocks ) : if isinstance ( s , VCFLACDict ) : self . metadata_blocks . remove ( s ) self . tags = None self . save ( ) break


def save(self, filename=None, deleteid3=False):
        """Save metadata blocks to a file.

        If no filename is given, the one most recently loaded is used.
        """

        if filename is None:
            filename = self.filename
        f = open(filename, 'rb+')

        try:
            # Ensure we've got padding at the end, and only at the end.
            # If adding makes it too large, we'll scale it down later.
            self.metadata_blocks.append(Padding(b'\x00' * 1020))
            MetadataBlock.group_padding(self.metadata_blocks)

            header = self.__check_header(f)
            # "fLaC" and maybe ID3
            available = self.__find_audio_offset(f) - header
            data = MetadataBlock.writeblocks(self.metadata_blocks)

            # Delete ID3v2
            if deleteid3 and header > 4:
                available += header - 4
                header = 4

            if len(data) > available:
                # If we have too much data, see if we can reduce padding.
                padding = self.metadata_blocks[-1]
                newlength = padding.length - (len(data) - available)
                if newlength > 0:
                    padding.length = newlength
                    data = MetadataBlock.writeblocks(self.metadata_blocks)
                    assert len(data) == available

            elif len(data) < available:
                # If we have too little data, increase padding.
                self.metadata_blocks[-1].length += (available - len(data))
                data = MetadataBlock.writeblocks(self.metadata_blocks)
                assert len(data) == available

            if len(data) != available:
                # We couldn't reduce the padding enough.
                diff = (len(data) - available)
                insert_bytes(f, diff, header)

            f.seek(header - 4)
            f.write(b"fLaC" + data)

            # Delete ID3v1
            if deleteid3:
                try:
                    f.seek(-128, 2)
                except IOError:
                    pass
                else:
                    if f.read(3) == b"TAG":
                        f.seek(-128, 2)
                        f.truncate()
        finally:
            f.close()


def parse_rrset_alias(e_alias):
    """
    Parses an Alias tag beneath a ResourceRecordSet, spitting out the two values
    found within. This is specific to A records that are set to Alias.

    :param lxml.etree._Element e_alias: An Alias tag beneath a ResourceRecordSet.
    :rtype: tuple
    :returns: A tuple in the form of ``(alias_hosted_zone_id, alias_dns_name)``.
    """

    alias_hosted_zone_id = e_alias.find('./{*}HostedZoneId').text
    alias_dns_name = e_alias.find('./{*}DNSName').text
    return alias_hosted_zone_id, alias_dns_name

def parse_rrset_alias ( e_alias ) : alias_hosted_zone_id = e_alias . find ( './{*}HostedZoneId' ) . text alias_dns_name = e_alias . find ( './{*}DNSName' ) . text return alias_hosted_zone_id , alias_dns_name

Parses an Alias tag beneath a ResourceRecordSet spitting out the two values found within . This is specific to A records that are set to Alias .


def parse_rrset_record_values(e_resource_records):
    """
    Used to parse the various Values from the ResourceRecords tags on
    most rrset types.

    :param lxml.etree._Element e_resource_records: A ResourceRecords tag
        beneath a ResourceRecordSet.
    :rtype: list
    :returns: A list of resource record strings.
    """

    records = []

    for e_record in e_resource_records:
        for e_value in e_record:
            records.append(e_value.text)

    return records

def parse_rrset_record_values ( e_resource_records ) : records = [ ] for e_record in e_resource_records : for e_value in e_record : records . append ( e_value . text ) return records

Used to parse the various Values from the ResourceRecords tags on most rrset types .


def parse_rrset(e_rrset, connection, zone_id):
    """
    This a parser that allows the passing of any valid ResourceRecordSet
    tag. It will spit out the appropriate ResourceRecordSet object for the tag.

    :param lxml.etree._Element e_rrset: The root node of the etree parsed
        response from the API.
    :param Route53Connection connection: The connection instance used to
        query the API.
    :param str zone_id: The zone ID of the HostedZone these rrsets belong to.
    :rtype: ResourceRecordSet
    :returns: An instantiated ResourceRecordSet object.
    """

    # This dict will be used to instantiate a ResourceRecordSet instance to yield.
    kwargs = {
        'connection': connection,
        'zone_id': zone_id,
    }
    rrset_type = None

    for e_field in e_rrset:
        # Cheesy way to strip off the namespace.
        tag_name = e_field.tag.split('}')[1]
        field_text = e_field.text

        if tag_name == 'Type':
            # Need to store this to determine which ResourceRecordSet
            # subclass to instantiate.
            rrset_type = field_text
            continue
        elif tag_name == 'AliasTarget':
            # A records have some special field values we need.
            alias_hosted_zone_id, alias_dns_name = parse_rrset_alias(e_field)
            kwargs['alias_hosted_zone_id'] = alias_hosted_zone_id
            kwargs['alias_dns_name'] = alias_dns_name
            # Alias A entries have no TTL.
            kwargs['ttl'] = None
            continue
        elif tag_name == 'ResourceRecords':
            kwargs['records'] = parse_rrset_record_values(e_field)
            continue

        # Map the XML tag name to a kwarg name.
        kw_name = RRSET_TAG_TO_KWARG_MAP[tag_name]
        # This will be the key/val pair used to instantiate the
        # ResourceRecordSet instance.
        kwargs[kw_name] = field_text

    if not rrset_type:
        raise Route53Error("No Type tag found in ListResourceRecordSetsResponse.")

    if 'records' not in kwargs:
        # Not all rrsets have records.
        kwargs['records'] = []

    RRSetSubclass = RRSET_TYPE_TO_RSET_SUBCLASS_MAP[rrset_type]
    return RRSetSubclass(**kwargs)

This a parser that allows the passing of any valid ResourceRecordSet tag . It will spit out the appropriate ResourceRecordSet object for the tag .


def delete(self, force=False):
        """
        Deletes this hosted zone. After this method is ran, you won't be able
        to add records, or do anything else with the zone. You'd need to
        re-create it, as zones are read-only after creation.

        :keyword bool force: If ``True``, delete the
            :py:class:`HostedZone <route53.hosted_zone.HostedZone>`, even if it
            means nuking all associated record sets. If ``False``, an
            exception is raised if this
            :py:class:`HostedZone <route53.hosted_zone.HostedZone>`
            has record sets.
        :rtype: dict
        :returns: A dict of change info, which contains some details about
            the request.
        """

        self._halt_if_already_deleted()

        if force:
            # Forcing deletion by cleaning up all record sets first. We'll
            # do it all in one change set.
            cset = ChangeSet(connection=self.connection, hosted_zone_id=self.id)

            for rrset in self.record_sets:
                # You can delete a HostedZone if there are only SOA and NS
                # entries left. So delete everything but SOA/NS entries.
                if rrset.rrset_type not in ['SOA', 'NS']:
                    cset.add_change('DELETE', rrset)

            if cset.deletions or cset.creations:
                # Bombs away.
                self.connection._change_resource_record_sets(cset)

        # Now delete the HostedZone.
        retval = self.connection.delete_hosted_zone_by_id(self.id)

        # Used to protect against modifying a deleted HostedZone.
        self._is_deleted = True

        return retval

Deletes this hosted zone . After this method is ran you won t be able to add records or do anything else with the zone . You d need to re - create it as zones are read - only after creation .


def _add_record(self, record_set_class, name, values, ttl=60, weight=None,
                    region=None,set_identifier=None, alias_hosted_zone_id=None,
                    alias_dns_name=None):
        """
        Convenience method for creating ResourceRecordSets. Most of the calls
        are basically the same, this saves on repetition.

        :rtype: tuple
        :returns: A tuple in the form of ``(rrset, change_info)``, where
            ``rrset`` is the newly created ResourceRecordSet sub-class
             instance.
        """

        self._halt_if_already_deleted()

        rrset_kwargs = dict(
            connection=self.connection,
            zone_id=self.id,
            name=name,
            ttl=ttl,
            records=values,
            weight=weight,
            region=region,
            set_identifier=set_identifier,
            )

        if alias_hosted_zone_id or alias_dns_name:
            rrset_kwargs.update(dict(
                alias_hosted_zone_id=alias_hosted_zone_id,
                alias_dns_name=alias_dns_name
            ))

        rrset = record_set_class(**rrset_kwargs)

        cset = ChangeSet(connection=self.connection, hosted_zone_id=self.id)
        cset.add_change('CREATE', rrset)

        change_info = self.connection._change_resource_record_sets(cset)

        return rrset, change_info

def _add_record ( self , record_set_class , name , values , ttl = 60 , weight = None , region = None , set_identifier = None , alias_hosted_zone_id = None , alias_dns_name = None ) : self . _halt_if_already_deleted ( ) rrset_kwargs = dict ( connection = self . connection , zone_id = self . id , name = name , ttl = ttl , records = values , weight = weight , region = region , set_identifier = set_identifier , ) if alias_hosted_zone_id or alias_dns_name : rrset_kwargs . update ( dict ( alias_hosted_zone_id = alias_hosted_zone_id , alias_dns_name = alias_dns_name ) ) rrset = record_set_class ( * * rrset_kwargs ) cset = ChangeSet ( connection = self . connection , hosted_zone_id = self . id ) cset . add_change ( 'CREATE' , rrset ) change_info = self . connection . _change_resource_record_sets ( cset ) return rrset , change_info

Convenience method for creating ResourceRecordSets . Most of the calls are basically the same this saves on repetition .


def create_a_record(self, name, values, ttl=60, weight=None, region=None,
                     set_identifier=None, alias_hosted_zone_id=None,
                     alias_dns_name=None):
        """
        Creates and returns an A record attached to this hosted zone.

        :param str name: The fully qualified name of the record to add.
        :param list values: A list of value strings for the record.
        :keyword int ttl: The time-to-live of the record (in seconds).
        :keyword int weight: *For weighted record sets only*. Among resource record
            sets that have the same combination of DNS name and type, a value
            that determines what portion of traffic for the current resource
            record set is routed to the associated location. Ranges from 0-255.
        :keyword str region: *For latency-based record sets*. The Amazon EC2 region
            where the resource that is specified in this resource record set
            resides.
        :keyword str set_identifier: *For weighted and latency resource record
            sets only*. An identifier that differentiates among multiple
            resource record sets that have the same combination of DNS name
            and type. 1-128 chars.
        :keyword str alias_hosted_zone_id: Alias A records have this specified.
            It appears to be the hosted zone ID for the ELB the Alias points at.
        :keyword str alias_dns_name: Alias A records have this specified. It is
            the DNS name for the ELB that the Alias points to.
        :rtype: tuple
        :returns: A tuple in the form of ``(rrset, change_info)``, where
            ``rrset`` is the newly created
            :py:class:`AResourceRecordSet <route53.resource_record_set.AResourceRecordSet>`
            instance.
        """

        self._halt_if_already_deleted()

        # Grab the params/kwargs here for brevity's sake.
        values = locals()
        del values['self']

        return self._add_record(AResourceRecordSet, **values)

Creates and returns an A record attached to this hosted zone .


def create_aaaa_record(self, name, values, ttl=60, weight=None, region=None,
                        set_identifier=None):
        """
        Creates an AAAA record attached to this hosted zone.

        :param str name: The fully qualified name of the record to add.
        :param list values: A list of value strings for the record.
        :keyword int ttl: The time-to-live of the record (in seconds).
        :keyword int weight: *For weighted record sets only*. Among resource record
            sets that have the same combination of DNS name and type, a value
            that determines what portion of traffic for the current resource
            record set is routed to the associated location. Ranges from 0-255.
        :keyword str region: *For latency-based record sets*. The Amazon EC2 region
            where the resource that is specified in this resource record set
            resides.
        :keyword str set_identifier: *For weighted and latency resource record
            sets only*. An identifier that differentiates among multiple
            resource record sets that have the same combination of DNS name
            and type. 1-128 chars.
        :rtype: tuple
        :returns: A tuple in the form of ``(rrset, change_info)``, where
            ``rrset`` is the newly created AAAAResourceRecordSet instance.
        """

        self._halt_if_already_deleted()

        # Grab the params/kwargs here for brevity's sake.
        values = locals()
        del values['self']

        return self._add_record(AAAAResourceRecordSet, **values)

Creates an AAAA record attached to this hosted zone .


def create_cname_record(self, name, values, ttl=60, weight=None, region=None,
                           set_identifier=None):
        """
        Creates a CNAME record attached to this hosted zone.

        :param str name: The fully qualified name of the record to add.
        :param list values: A list of value strings for the record.
        :keyword int ttl: The time-to-live of the record (in seconds).
        :keyword int weight: *For weighted record sets only*. Among resource record
            sets that have the same combination of DNS name and type, a value
            that determines what portion of traffic for the current resource
            record set is routed to the associated location. Ranges from 0-255.
        :keyword str region: *For latency-based record sets*. The Amazon EC2 region
            where the resource that is specified in this resource record set
            resides.
        :keyword str set_identifier: *For weighted and latency resource record
            sets only*. An identifier that differentiates among multiple
            resource record sets that have the same combination of DNS name
            and type. 1-128 chars.
        :rtype: tuple
        :returns: A tuple in the form of ``(rrset, change_info)``, where
            ``rrset`` is the newly created CNAMEResourceRecordSet instance.
        """

        self._halt_if_already_deleted()

        # Grab the params/kwargs here for brevity's sake.
        values = locals()
        del values['self']

        return self._add_record(CNAMEResourceRecordSet, **values)

Creates a CNAME record attached to this hosted zone .


def create_mx_record(self, name, values, ttl=60):
        """
        Creates a MX record attached to this hosted zone.

        :param str name: The fully qualified name of the record to add.
        :param list values: A list of value strings for the record.
        :keyword int ttl: The time-to-live of the record (in seconds).
        :rtype: tuple
        :returns: A tuple in the form of ``(rrset, change_info)``, where
            ``rrset`` is the newly created MXResourceRecordSet instance.
        """

        self._halt_if_already_deleted()

        # Grab the params/kwargs here for brevity's sake.
        values = locals()
        del values['self']

        return self._add_record(MXResourceRecordSet, **values)

Creates a MX record attached to this hosted zone .


def create_ns_record(self, name, values, ttl=60):
        """
        Creates a NS record attached to this hosted zone.

        :param str name: The fully qualified name of the record to add.
        :param list values: A list of value strings for the record.
        :keyword int ttl: The time-to-live of the record (in seconds).
        :rtype: tuple
        :returns: A tuple in the form of ``(rrset, change_info)``, where
            ``rrset`` is the newly created NSResourceRecordSet instance.
        """

        self._halt_if_already_deleted()

        # Grab the params/kwargs here for brevity's sake.
        values = locals()
        del values['self']

        return self._add_record(NSResourceRecordSet, **values)

Creates a NS record attached to this hosted zone .


def create_ptr_record(self, name, values, ttl=60):
        """
        Creates a PTR record attached to this hosted zone.

        :param str name: The fully qualified name of the record to add.
        :param list values: A list of value strings for the record.
        :keyword int ttl: The time-to-live of the record (in seconds).
        :rtype: tuple
        :returns: A tuple in the form of ``(rrset, change_info)``, where
            ``rrset`` is the newly created PTRResourceRecordSet instance.
        """

        self._halt_if_already_deleted()

        # Grab the params/kwargs here for brevity's sake.
        values = locals()
        del values['self']

        return self._add_record(PTRResourceRecordSet, **values)

Creates a PTR record attached to this hosted zone .


def create_spf_record(self, name, values, ttl=60):
        """
        Creates a SPF record attached to this hosted zone.

        :param str name: The fully qualified name of the record to add.
        :param list values: A list of value strings for the record.
        :keyword int ttl: The time-to-live of the record (in seconds).
        :rtype: tuple
        :returns: A tuple in the form of ``(rrset, change_info)``, where
            ``rrset`` is the newly created SPFResourceRecordSet instance.
        """

        self._halt_if_already_deleted()

        # Grab the params/kwargs here for brevity's sake.
        values = locals()
        del values['self']

        return self._add_record(SPFResourceRecordSet, **values)

Creates a SPF record attached to this hosted zone .


def create_srv_record(self, name, values, ttl=60):
        """
        Creates a SRV record attached to this hosted zone.

        :param str name: The fully qualified name of the record to add.
        :param list values: A list of value strings for the record.
        :keyword int ttl: The time-to-live of the record (in seconds).
        :rtype: tuple
        :returns: A tuple in the form of ``(rrset, change_info)``, where
            ``rrset`` is the newly created SRVResourceRecordSet instance.
        """

        self._halt_if_already_deleted()

        # Grab the params/kwargs here for brevity's sake.
        values = locals()
        del values['self']

        return self._add_record(SRVResourceRecordSet, **values)

Creates a SRV record attached to this hosted zone .


def create_txt_record(self, name, values, ttl=60, weight=None, region=None,
                          set_identifier=None):
        """
        Creates a TXT record attached to this hosted zone.

        :param str name: The fully qualified name of the record to add.
        :param list values: A list of value strings for the record.
        :keyword int ttl: The time-to-live of the record (in seconds).
        :keyword int weight: *For weighted record sets only*. Among resource record
            sets that have the same combination of DNS name and type, a value
            that determines what portion of traffic for the current resource
            record set is routed to the associated location. Ranges from 0-255.
        :keyword str region: *For latency-based record sets*. The Amazon EC2 region
            where the resource that is specified in this resource record set
            resides.
        :keyword str set_identifier: *For weighted and latency resource record
            sets only*. An identifier that differentiates among multiple
            resource record sets that have the same combination of DNS name
            and type. 1-128 chars.
        :rtype: tuple
        :returns: A tuple in the form of ``(rrset, change_info)``, where
            ``rrset`` is the newly created TXTResourceRecordSet instance.
        """

        self._halt_if_already_deleted()

        # Grab the params/kwargs here for brevity's sake.
        values = locals()
        del values['self']

        return self._add_record(TXTResourceRecordSet, **values)

Creates a TXT record attached to this hosted zone .


def RegisterTXXXKey(cls, key, desc):
        """Register a user-defined text frame key.

        Some ID3 tags are stored in TXXX frames, which allow a
        freeform 'description' which acts as a subkey,
        e.g. TXXX:BARCODE.::

            EasyID3.RegisterTXXXKey('barcode', 'BARCODE').
        """
        frameid = "TXXX:" + desc

        def getter(id3, key):
            return list(id3[frameid])

        def setter(id3, key, value):
            try:
                frame = id3[frameid]
            except KeyError:
                enc = 0
                # Store 8859-1 if we can, per MusicBrainz spec.
                try:
                    for v in value:
                        v.encode('latin_1')
                except UnicodeError:
                    enc = 3

                id3.add(mutagen.id3.TXXX(encoding=enc, text=value, desc=desc))
            else:
                frame.text = value

        def deleter(id3, key):
            del(id3[frameid])

        cls.RegisterKey(key, getter, setter, deleter)

Register a user - defined text frame key .


def get_change_values(change):
    """
    In the case of deletions, we pull the change values for the XML request
    from the ResourceRecordSet._initial_vals dict, since we want the original
    values. For creations, we pull from the attributes on ResourceRecordSet.

    Since we're dealing with attributes vs. dict key/vals, we'll abstract
    this part away here and just always pass a dict to write_change.

    :rtype: dict
    :returns: A dict of change data, used by :py:func:`write_change` to
        write the change request XML.
    """

    action, rrset = change

    if action == 'CREATE':
        # For creations, we want the current values, since they don't need to
        # match an existing record set.
        values = dict()
        for key, val in rrset._initial_vals.items():
            # Pull from the record set's attributes, which are the current
            # values.
            values[key] = getattr(rrset, key)
        return values
    else:
        # We can look at the initial values dict for deletions, since we
        # have to match against the values currently in Route53.
        return rrset._initial_vals

In the case of deletions we pull the change values for the XML request from the ResourceRecordSet . _initial_vals dict since we want the original values . For creations we pull from the attributes on ResourceRecordSet .


def write_change(change):
    """
    Creates an XML element for the change.

    :param tuple change: A change tuple from a ChangeSet. Comes in the form
        of ``(action, rrset)``.
    :rtype: lxml.etree._Element
    :returns: A fully baked Change tag.
    """

    action, rrset = change

    change_vals = get_change_values(change)

    e_change = etree.Element("Change")

    e_action = etree.SubElement(e_change, "Action")
    e_action.text = action

    e_rrset = etree.SubElement(e_change, "ResourceRecordSet")

    e_name = etree.SubElement(e_rrset, "Name")
    e_name.text = change_vals['name']

    e_type = etree.SubElement(e_rrset, "Type")
    e_type.text = rrset.rrset_type

    if change_vals.get('set_identifier'):
        e_set_id = etree.SubElement(e_rrset, "SetIdentifier")
        e_set_id.text = change_vals['set_identifier']

    if change_vals.get('weight'):
        e_weight = etree.SubElement(e_rrset, "Weight")
        e_weight.text = change_vals['weight']

    if change_vals.get('alias_hosted_zone_id') or change_vals.get('alias_dns_name'):
        e_alias_target = etree.SubElement(e_rrset, "AliasTarget")

        e_hosted_zone_id = etree.SubElement(e_alias_target, "HostedZoneId")
        e_hosted_zone_id.text = change_vals['alias_hosted_zone_id']
        e_dns_name = etree.SubElement(e_alias_target, "DNSName")
        e_dns_name.text = change_vals['alias_dns_name']

    if change_vals.get('region'):
        e_weight = etree.SubElement(e_rrset, "Region")
        e_weight.text = change_vals['region']

    e_ttl = etree.SubElement(e_rrset, "TTL")
    e_ttl.text = str(change_vals['ttl'])

    if rrset.is_alias_record_set():
        # A record sets in Alias mode don't have any resource records.
        return e_change

    e_resource_records = etree.SubElement(e_rrset, "ResourceRecords")

    for value in change_vals['records']:
        e_resource_record = etree.SubElement(e_resource_records, "ResourceRecord")
        e_value = etree.SubElement(e_resource_record, "Value")
        e_value.text = value

    return e_change


def change_resource_record_set_writer(connection, change_set, comment=None):
    """
    Forms an XML string that we'll send to Route53 in order to change
    record sets.

    :param Route53Connection connection: The connection instance used to
        query the API.
    :param change_set.ChangeSet change_set: The ChangeSet object to create the
        XML doc from.
    :keyword str comment: An optional comment to go along with the request.
    """

    e_root = etree.Element(
        "ChangeResourceRecordSetsRequest",
        xmlns=connection._xml_namespace
    )

    e_change_batch = etree.SubElement(e_root, "ChangeBatch")

    if comment:
        e_comment = etree.SubElement(e_change_batch, "Comment")
        e_comment.text = comment

    e_changes = etree.SubElement(e_change_batch, "Changes")

    # Deletions need to come first in the change sets.
    for change in change_set.deletions + change_set.creations:
        e_changes.append(write_change(change))

    e_tree = etree.ElementTree(element=e_root)

    #print(prettyprint_xml(e_root))

    fobj = BytesIO()
    # This writes bytes.
    e_tree.write(fobj, xml_declaration=True, encoding='utf-8', method="xml")
    return fobj.getvalue().decode('utf-8')

Forms an XML string that we ll send to Route53 in order to change record sets .


def init_logs():
    """Initiate log file."""
    start_time = dt.fromtimestamp(time.time()).strftime('%Y%m%d_%H%M')
    logname = os.path.join(os.path.expanduser("~") + "/nanoGUI_" + start_time + ".log")
    handlers = [logging.FileHandler(logname)]
    logging.basicConfig(
        format='%(asctime)s %(message)s',
        handlers=handlers,
        level=logging.INFO)
    logging.info('NanoGUI {} started with NanoPlot {}'.format(__version__, nanoplot.__version__))
    logging.info('Python version is: {}'.format(sys.version.replace('\n', ' ')))
    return logname

def
init_logs
(
)
:
start_time
=
dt
.
fromtimestamp
(
time
.
time
(
)
)
.
strftime
(
'%Y%m%d_%H%M'
)
logname
=
os
.
path
.
join
(
os
.
path
.
expanduser
(
"~"
)
+
"/nanoGUI_"
+
start_time
+
".log"
)
handlers
=
[
logging
.
FileHandler
(
logname
)
]
logging
.
basicConfig
(
format
=
'%(asctime)s %(message)s'
,
handlers
=
handlers
,
level
=
logging
.
INFO
)
logging
.
info
(
'NanoGUI {} started with NanoPlot {}'
.
format
(
__version__
,
nanoplot
.
__version__
)
)
logging
.
info
(
'Python version is: {}'
.
format
(
sys
.
version
.
replace
(
'\n'
,
' '
)
)
)
return
logname


def alias_item(self, alias):
        """Gets an item by its alias."""
        ident = self.alias[alias]
        return self.items[ident]

def alias_item ( self , alias ) : ident = self . alias [ alias ] return self . items [ ident ]


def freeze_dict(dict_):
    """Freezes ``dict`` into ``tuple``.

    A typical usage is packing ``dict`` into hashable.

    e.g.::

        >>> freeze_dict({'a': 1, 'b': 2})
        (('a', 1), ('b', 2))
    """
    pairs = dict_.items()
    key_getter = operator.itemgetter(0)
    return tuple(sorted(pairs, key=key_getter))

def freeze_dict ( dict_ ) : pairs = dict_ . items ( ) key_getter = operator . itemgetter ( 0 ) return tuple ( sorted ( pairs , key = key_getter ) )


def join_html_attrs(attrs):
    """Joins the map structure into HTML attributes.

    The return value is a 2-tuple ``(template, ordered_values)``. It should be
    passed into :class:`markupsafe.Markup` to prevent XSS attacked.

    e.g.::

        >>> join_html_attrs({'href': '/', 'data-active': 'true'})
        ('data-active="{0}" href="{1}"', ['true', '/'])
    """
    attrs = collections.OrderedDict(freeze_dict(attrs or {}))
    template = ' '.join('%s="{%d}"' % (k, i) for i, k in enumerate(attrs))
    return template, list(attrs.values())

def
join_html_attrs
(
attrs
)
:
attrs
=
collections
.
OrderedDict
(
freeze_dict
(
attrs
or
{
}
)
)
template
=
' '
.
join
(
'%s="{%d}"'
%
(
k
,
i
)
for
i
,
k
in
enumerate
(
attrs
)
)
return
template
,
list
(
attrs
.
values
(
)
)

Joins the map structure into HTML attributes .


def init_app(self, app):
        """Initializes an app to work with this extension.

        The app-context signals will be subscribed and the template context
        will be initialized.

        :param app: the :class:`flask.Flask` app instance.
        """
        # connects app-level signals
        appcontext_pushed.connect(self.initialize_bars, app)
        # integrate with jinja template
        app.add_template_global(self, 'nav')

def
init_app
(
self
,
app
)
:
# connects app-level signals
appcontext_pushed
.
connect
(
self
.
initialize_bars
,
app
)
# integrate with jinja template
app
.
add_template_global
(
self
,
'nav'
)

Initializes an app to work with this extension .


def initialize_bars(self, sender=None, **kwargs):
        """Calls the initializers of all bound navigation bars."""
        for bar in self.bars.values():
            for initializer in bar.initializers:
                initializer(self)

def initialize_bars ( self , sender = None , * * kwargs ) : for bar in self . bars . values ( ) : for initializer in bar . initializers : initializer ( self )

Calls the initializers of all bound navigation bars .


def bind_bar(self, sender=None, **kwargs):
        """Binds a navigation bar into this extension instance."""
        bar = kwargs.pop('bar')
        self.bars[bar.name] = bar

def bind_bar ( self , sender = None , * * kwargs ) : bar = kwargs . pop ( 'bar' ) self . bars [ bar . name ] = bar

Binds a navigation bar into this extension instance .


def args(self):
        """The arguments which will be passed to ``url_for``.

        :type: :class:`dict`
        """
        if self._args is None:
            return {}
        if callable(self._args):
            return dict(self._args())
        return dict(self._args)

def args ( self ) : if self . _args is None : return { } if callable ( self . _args ) : return dict ( self . _args ( ) ) return dict ( self . _args )

The arguments which will be passed to url_for .


def url(self):
        """The final url of this navigation item.

        By default, the value is generated by the :attr:`self.endpoint` and
        :attr:`self.args`.

        .. note::

           The :attr:`url` property require the app context without a provided
           config value :const:`SERVER_NAME`, because of :func:`flask.url_for`.

        :type: :class:`str`
        """
        if self.is_internal:
            return url_for(self.endpoint, **self.args)
        return self._url

def url ( self ) : if self . is_internal : return url_for ( self . endpoint , * * self . args ) return self . _url


def is_current(self):
        """``True`` if current request has same endpoint with the item.

        The property should be used in a bound request context, or the
        :class:`RuntimeError` may be raised.
        """
        if not self.is_internal:
            return False  # always false for external url
        has_same_endpoint = (request.endpoint == self.endpoint)
        has_same_args = (request.view_args == self.args)
        return has_same_endpoint and has_same_args

def
is_current
(
self
)
:
if
not
self
.
is_internal
:
return
False
# always false for external url
has_same_endpoint
=
(
request
.
endpoint
==
self
.
endpoint
)
has_same_args
=
(
request
.
view_args
==
self
.
args
)
return
has_same_endpoint
and
has_same_args

True if current request has same endpoint with the item .


def validate(metric_class):
    """
    Does basic Metric option validation.
    """
    if not hasattr(metric_class, 'label'):
        raise ImproperlyConfigured("No 'label' attribute found for metric %s." % metric_class.__name__)

    if not hasattr(metric_class, 'widget'):
        raise ImproperlyConfigured("No 'widget' attribute found for metric %s." % metric_class.__name__)


def get_statistic_by_name(stat_name):
    """
    Fetches a statistics based on the given class name. Does a look-up
    in the gadgets' registered statistics to find the specified one.
    """

    if stat_name == 'ALL':
        return get_statistic_models()

    for stat in get_statistic_models():
        if stat.__name__ == stat_name:
            return stat

    raise Exception, _("%(stat)s cannot be found.") % {'stat': stat_name}

def
get_statistic_by_name
(
stat_name
)
:
if
stat_name
==
'ALL'
:
return
get_statistic_models
(
)
for
stat
in
get_statistic_models
(
)
:
if
stat
.
__name__
==
stat_name
:
return
stat
raise
Exception
,
_
(
"%(stat)s cannot be found."
)
%
{
'stat'
:
stat_name
}

Fetches a statistics based on the given class name . Does a look - up in the gadgets registered statistics to find the specified one .


def calculate_statistics(stat, frequencies):
    """
    Calculates all of the metrics associated with the registered gadgets.
    """
    stats = ensure_list(stat)
    frequencies = ensure_list(frequencies)

    for stat in stats:
        for f in frequencies:
            print "Calculating %s (%s)..." % (stat.__name__, settings.STATISTIC_FREQUENCY_DICT[f])
            stat.calculate(f)

def
calculate_statistics
(
stat
,
frequencies
)
:
stats
=
ensure_list
(
stat
)
frequencies
=
ensure_list
(
frequencies
)
for
stat
in
stats
:
for
f
in
frequencies
:
print
"Calculating %s (%s)..."
%
(
stat
.
__name__
,
settings
.
STATISTIC_FREQUENCY_DICT
[
f
]
)
stat
.
calculate
(
f
)

Calculates all of the metrics associated with the registered gadgets .


def autodiscover():
    """
    Auto-discover INSTALLED_APPS gadgets.py modules and fail silently when
    not present. This forces an import on them to register any gadgets they
    may want.
    """
    from django.conf import settings
    from django.utils.importlib import import_module
    from django.utils.module_loading import module_has_submodule

    for app in settings.INSTALLED_APPS:
        mod = import_module(app)
        # Attempt to import the app's gadgets module.
        try:
            import_module('%s.gadgets' % app)
        except:
            # Decide whether to bubble up this error. If the app just
            # doesn't have a gadgets module, we can ignore the error
            # attempting to import it, otherwise we want it to bubble up.
            if module_has_submodule(mod, 'gadgets'):
                raise

Auto - discover INSTALLED_APPS gadgets . py modules and fail silently when not present . This forces an import on them to register any gadgets they may want .


def csv_dump(request, uid):
    """
    Returns a CSV dump of all of the specified metric's counts
    and cumulative counts.
    """

    metric = Metric.objects.get(uid=uid)
    frequency = request.GET.get('frequency', settings.STATISTIC_FREQUENCY_DAILY)

    response = HttpResponse(mimetype='text/csv')
    response['Content-Disposition'] = 'attachment; filename=%s%s.csv' % (uid, datetime.datetime.now().strftime("%Y%m%d-%H%M"))

    writer = csv.writer(response)
    writer.writerow([_('Date/time'), _('Count'), _('Cumulative count')])
    for stat in metric.statistics.filter(frequency=frequency).order_by('date_time'):
        writer.writerow([stat.date_time.strftime(settings.CSV_DATETIME_FORMAT), stat.count, stat.cumulative_count])

    return response

def
csv_dump
(
request
,
uid
)
:
metric
=
Metric
.
objects
.
get
(
uid
=
uid
)
frequency
=
request
.
GET
.
get
(
'frequency'
,
settings
.
STATISTIC_FREQUENCY_DAILY
)
response
=
HttpResponse
(
mimetype
=
'text/csv'
)
response
[
'Content-Disposition'
]
=
'attachment; filename=%s%s.csv'
%
(
uid
,
datetime
.
datetime
.
now
(
)
.
strftime
(
"%Y%m%d-%H%M"
)
)
writer
=
csv
.
writer
(
response
)
writer
.
writerow
(
[
_
(
'Date/time'
)
,
_
(
'Count'
)
,
_
(
'Cumulative count'
)
]
)
for
stat
in
metric
.
statistics
.
filter
(
frequency
=
frequency
)
.
order_by
(
'date_time'
)
:
writer
.
writerow
(
[
stat
.
date_time
.
strftime
(
settings
.
CSV_DATETIME_FORMAT
)
,
stat
.
count
,
stat
.
cumulative_count
]
)
return
response

Returns a CSV dump of all of the specified metric s counts and cumulative counts .


def handle(self, *args, **kwargs):
        """
        Command handler for the "metrics" command.
        """

        frequency = kwargs['frequency']
        frequencies = settings.STATISTIC_FREQUENCY_ALL if frequency == 'a' else (frequency.split(',') if ',' in frequency else [frequency])

        if kwargs['list']:
            maintenance.list_statistics()

        # if we're supposed to calculate the latest statistics
        elif kwargs['calculate']:
            maintenance.calculate_statistics(maintenance.get_statistic_by_name(kwargs['calculate']), frequencies)

        # pure reset of statistic(s)
        elif kwargs['reset']:
            maintenance.reset_statistics(maintenance.get_statistic_by_name(kwargs['reset']), frequencies, kwargs['reset_cumulative'])

        # recalculation of statistic(s)
        elif kwargs['recalculate']:
            maintenance.reset_statistics(maintenance.get_statistic_by_name(kwargs['recalculate']), frequencies, kwargs['reset_cumulative'], True)

Command handler for the metrics command .


def get_GET_array(request, var_name, fail_silently=True):
    """
    Returns the GET array's contents for the specified variable.
    """

    vals = request.GET.getlist(var_name)
    if not vals:
        if fail_silently:
            return []
        else:
            raise Exception, _("No array called '%(varname)s' in GET variables") % {'varname': var_name}

    return vals

Returns the GET array s contents for the specified variable .


def get_GET_bool(request, var_name, default=True):
    """
    Tries to extract a boolean variable from the specified request.
    """

    val = request.GET.get(var_name, default)
    if isinstance(val, str) or isinstance(val, unicode):
        val = True if val[0] == 't' else False

    return val

def get_GET_bool ( request , var_name , default = True ) : val = request . GET . get ( var_name , default ) if isinstance ( val , str ) or isinstance ( val , unicode ) : val = True if val [ 0 ] == 't' else False return val

Tries to extract a boolean variable from the specified request .


def get_next_colour():
    """
    Gets the next colour in the Geckoboard colour list.
    """

    colour = settings.GECKOBOARD_COLOURS[get_next_colour.cur_colour]

    get_next_colour.cur_colour += 1
    if get_next_colour.cur_colour >= len(settings.GECKOBOARD_COLOURS):
        get_next_colour.cur_colour = 0

    return colour

def get_next_colour ( ) : colour = settings . GECKOBOARD_COLOURS [ get_next_colour . cur_colour ] get_next_colour . cur_colour += 1 if get_next_colour . cur_colour >= len ( settings . GECKOBOARD_COLOURS ) : get_next_colour . cur_colour = 0 return colour

Gets the next colour in the Geckoboard colour list .


def get_gecko_params(request, uid=None, days_back=0, cumulative=True,
    frequency=settings.STATISTIC_FREQUENCY_DAILY, min_val=0, max_val=100,
    chart_type='standard', percentage='show', sort=False):
    """
    Returns the default GET parameters for a particular Geckoboard
    view request.
    """

    return {
        'days_back'  : int(request.GET.get('daysback', days_back)),
        'uid'        : request.GET.get('uid', uid),
        'uids'       : get_GET_array(request, 'uids[]'),
        'cumulative' : get_GET_bool(request, 'cumulative', cumulative),
        'frequency'  : request.GET.get('frequency', frequency),
        'min'        : request.GET.get('min', min_val),
        'max'        : request.GET.get('max', max_val),
        'type'       : request.GET.get('type', chart_type),
        'percentage' : request.GET.get('percentage', percentage),
        'sort'       : get_GET_bool(request, 'sort', sort),
    }

def get_gecko_params ( request , uid = None , days_back = 0 , cumulative = True , frequency = settings . STATISTIC_FREQUENCY_DAILY , min_val = 0 , max_val = 100 , chart_type = 'standard' , percentage = 'show' , sort = False ) : return { 'days_back' : int ( request . GET . get ( 'daysback' , days_back ) ) , 'uid' : request . GET . get ( 'uid' , uid ) , 'uids' : get_GET_array ( request , 'uids[]' ) , 'cumulative' : get_GET_bool ( request , 'cumulative' , cumulative ) , 'frequency' : request . GET . get ( 'frequency' , frequency ) , 'min' : request . GET . get ( 'min' , min_val ) , 'max' : request . GET . get ( 'max' , max_val ) , 'type' : request . GET . get ( 'type' , chart_type ) , 'percentage' : request . GET . get ( 'percentage' , percentage ) , 'sort' : get_GET_bool ( request , 'sort' , sort ) , }

Returns the default GET parameters for a particular Geckoboard view request .


def geckoboard_number_widget(request):
    """
    Returns a number widget for the specified metric's cumulative total.
    """

    params = get_gecko_params(request, days_back=7)
    metric = Metric.objects.get(uid=params['uid'])
    try:
        latest_stat = metric.statistics.filter(frequency=params['frequency']).order_by('-date_time')[0]
    except IndexError:
        return (0, 0)

    try:
        prev_stat = metric.statistics.filter(frequency=params['frequency'],
            date_time__lte=latest_stat.date_time-timedelta(days=params['days_back'])).order_by('-date_time')[0]
    except IndexError:
        # if there is no previous stat
        return (latest_stat.cumulative_count, 0) if params['cumulative'] else (latest_stat.count, 0)

    return (latest_stat.cumulative_count, prev_stat.cumulative_count) if params['cumulative'] else (latest_stat.count, prev_stat.count)

def
geckoboard_number_widget
(
request
)
:
params
=
get_gecko_params
(
request
,
days_back
=
7
)
metric
=
Metric
.
objects
.
get
(
uid
=
params
[
'uid'
]
)
try
:
latest_stat
=
metric
.
statistics
.
filter
(
frequency
=
params
[
'frequency'
]
)
.
order_by
(
'-date_time'
)
[
0
]
except
IndexError
:
return
(
0
,
0
)
try
:
prev_stat
=
metric
.
statistics
.
filter
(
frequency
=
params
[
'frequency'
]
,
date_time__lte
=
latest_stat
.
date_time
timedelta
(
days
=
params
[
'days_back'
]
)
)
.
order_by
(
'-date_time'
)
[
0
]
except
IndexError
:
# if there is no previous stat
return
(
latest_stat
.
cumulative_count
,
0
)
if
params
[
'cumulative'
]
else
(
latest_stat
.
count
,
0
)
return
(
latest_stat
.
cumulative_count
,
prev_stat
.
cumulative_count
)
if
params
[
'cumulative'
]
else
(
latest_stat
.
count
,
prev_stat
.
count
)

Returns a number widget for the specified metric s cumulative total .


def geckoboard_rag_widget(request):
    """
    Searches the GET variables for metric UIDs, and displays
    them in a RAG widget.
    """

    params = get_gecko_params(request)
    print params['uids']
    max_date = datetime.now()-timedelta(days=params['days_back'])

    metrics = Metric.objects.filter(uid__in=params['uids'])
    results = [(metric.latest_count(frequency=params['frequency'], count=not params['cumulative'],
        cumulative=params['cumulative'], max_date=max_date), metric.title) for metric in metrics]

    return tuple(results)

def geckoboard_rag_widget ( request ) : params = get_gecko_params ( request ) print params [ 'uids' ] max_date = datetime . now ( ) - timedelta ( days = params [ 'days_back' ] ) metrics = Metric . objects . filter ( uid__in = params [ 'uids' ] ) results = [ ( metric . latest_count ( frequency = params [ 'frequency' ] , count = not params [ 'cumulative' ] , cumulative = params [ 'cumulative' ] , max_date = max_date ) , metric . title ) for metric in metrics ] return tuple ( results )

Searches the GET variables for metric UIDs and displays them in a RAG widget .


def geckoboard_line_chart(request):
    """
    Returns the data for a line chart for the specified metric.
    """

    params = get_gecko_params(request, cumulative=False, days_back=7)
    metric = Metric.objects.get(uid=params['uid'])

    start_date = datetime.now()-timedelta(days=params['days_back'])
    stats = [s for s in metric.statistics.filter(frequency=params['frequency'],
        date_time__gte=start_date).order_by('date_time')]

    if len(stats) == 0:
        raise Exception, _("No statistics for metric %(metric)s.") % {'metric': params['uid']}

    dates = [stats[0].date_time]

    # get up to 3 dates from the stats
    if len(stats) >= 3:
        mid = len(stats)/2
        if not mid:
            mid = 1
        dates.extend([stats[mid].date_time, stats[-1].date_time])
    elif len(stats) == 2:
        dates.extend([stats[-1].date_time])

    return (
        [s.count for s in stats],
        dates,
        metric.title,
    )

def
geckoboard_line_chart
(
request
)
:
params
=
get_gecko_params
(
request
,
cumulative
=
False
,
days_back
=
7
)
metric
=
Metric
.
objects
.
get
(
uid
=
params
[
'uid'
]
)
start_date
=
datetime
.
now
(
)
timedelta
(
days
=
params
[
'days_back'
]
)
stats
=
[
s
for
s
in
metric
.
statistics
.
filter
(
frequency
=
params
[
'frequency'
]
,
date_time__gte
=
start_date
)
.
order_by
(
'date_time'
)
]
if
len
(
stats
)
==
0
:
raise
Exception
,
_
(
"No statistics for metric %(metric)s."
)
%
{
'metric'
:
params
[
'uid'
]
}
dates
=
[
stats
[
0
]
.
date_time
]
# get up to 3 dates from the stats
if
len
(
stats
)
>=
3
:
mid
=
len
(
stats
)
/
2
if
not
mid
:
mid
=
1
dates
.
extend
(
[
stats
[
mid
]
.
date_time
,
stats
[
1
]
.
date_time
]
)
elif
len
(
stats
)
==
2
:
dates
.
extend
(
[
stats
[
1
]
.
date_time
]
)
return
(
[
s
.
count
for
s
in
stats
]
,
dates
,
metric
.
title
,
)

Returns the data for a line chart for the specified metric .


def geckoboard_geckometer(request):
    """
    Returns a Geck-o-Meter control for the specified metric.
    """

    params = get_gecko_params(request, cumulative=True)
    metric = Metric.objects.get(uid=params['uid'])

    return (metric.latest_count(frequency=params['frequency'], count=not params['cumulative'],
        cumulative=params['cumulative']), params['min'], params['max'])

def geckoboard_geckometer ( request ) : params = get_gecko_params ( request , cumulative = True ) metric = Metric . objects . get ( uid = params [ 'uid' ] ) return ( metric . latest_count ( frequency = params [ 'frequency' ] , count = not params [ 'cumulative' ] , cumulative = params [ 'cumulative' ] ) , params [ 'min' ] , params [ 'max' ] )

Returns a Geck - o - Meter control for the specified metric .


def geckoboard_funnel(request, frequency=settings.STATISTIC_FREQUENCY_DAILY):
    """
    Returns a funnel chart for the metrics specified in the GET variables.
    """

    # get all the parameters for this function
    params = get_gecko_params(request, cumulative=True)
    metrics = Metric.objects.filter(uid__in=params['uids'])
    items = [(metric.latest_count(frequency=params['frequency'], count=not params['cumulative'],
        cumulative=params['cumulative']), metric.title) for metric in metrics]

    return {
        'items'     : items,
        'type'      : params['type'],
        'percentage': params['percentage'],
        'sort'      : params['sort'],
    }

Returns a funnel chart for the metrics specified in the GET variables .


def get_active_stats(self):
        """
        Returns all of the active statistics for the gadgets currently registered.
        """
        stats = []
        for gadget in self._registry.values():
            for s in gadget.stats:
                if s not in stats:
                    stats.append(s)
        return stats

def get_active_stats ( self ) : stats = [ ] for gadget in self . _registry . values ( ) : for s in gadget . stats : if s not in stats : stats . append ( s ) return stats

Returns all of the active statistics for the gadgets currently registered .


def register(self, gadget):
        """
        Registers a gadget object.
        If a gadget is already registered, this will raise AlreadyRegistered.
        """
        if gadget in self._registry:
            raise AlreadyRegistered
        else:
            self._registry.append(gadget)

def register ( self , gadget ) : if gadget in self . _registry : raise AlreadyRegistered else : self . _registry . append ( gadget )

Registers a gadget object . If a gadget is already registered this will raise AlreadyRegistered .


def get_context_data(self, **kwargs):
        """
        Get the context for this view.
        """
        #max_columns, max_rows = self.get_max_dimension()
        context = {
            'gadgets': self._registry,
            'columns': self.columns,
            'rows': self.rows,
            'column_ratio': 100 - self.columns * 2,
            'row_ratio': 100 - self.rows * 2,
        }
        context.update(kwargs)
        return context


def error(self, message, code=1):
        """
        Print error and stop command
        """
        print >>sys.stderr, message
        sys.exit(code)

def error ( self , message , code = 1 ) : print >> sys . stderr , message sys . exit ( code )


def valid(schema=None):
        """ Validation data by specific validictory configuration """
        def dec(fun):
            @wraps(fun)
            def d_func(self, ctx, data, *a, **kw):
                try:
                    validate(data['params'], schema)
                except ValidationError as err:
                    raise InvalidParams(err)
                except SchemaError as err:
                    raise InternalError(err)
                return fun(self, ctx, data['params'], *a, **kw)
            return d_func
        return dec

def valid ( schema = None ) : def dec ( fun ) : @ wraps ( fun ) def d_func ( self , ctx , data , * a , * * kw ) : try : validate ( data [ 'params' ] , schema ) except ValidationError as err : raise InvalidParams ( err ) except SchemaError as err : raise InternalError ( err ) return fun ( self , ctx , data [ 'params' ] , * a , * * kw ) return d_func return dec


def long_input(prompt='Multi-line input\n' + \
        'Enter EOF on a blank line to end ' + \
        '(ctrl-D in *nix, ctrl-Z in windows)',
        maxlines = None, maxlength = None):
    """Get a multi-line string as input"""

    lines = []
    print(prompt)
    lnum = 1

    try:
        while True:

            if maxlines:

                if lnum > maxlines:
                    break

                else:
                    if maxlength:
                        lines.append(string_input('')[:maxlength])
                    else:
                        lines.append(string_input(''))
                    lnum += 1

            else:
                if maxlength:
                    lines.append(string_input('')[:maxlength])
                else:
                    lines.append(string_input(''))

    except EOFError:
        pass
    finally:
        return '\n'.join(lines)

def
long_input
(
prompt
=
'Multi-line input\n'
+
'Enter EOF on a blank line to end '
+
'(ctrl-D in *nix, ctrl-Z in windows)'
,
maxlines
=
,
maxlength
=
)
:
lines
=
[
]
print
(
prompt
)
lnum
=
1
try
:
while
True
:
if
maxlines
:
if
lnum
>
maxlines
:
break
else
:
if
maxlength
:
lines
.
append
(
string_input
(
''
)
[
:
maxlength
]
)
else
:
lines
.
append
(
string_input
(
''
)
)
lnum
+=
1
else
:
if
maxlength
:
lines
.
append
(
string_input
(
''
)
[
:
maxlength
]
)
else
:
lines
.
append
(
string_input
(
''
)
)
except
EOFError
:
pass
finally
:
return
'\n'
.
join
(
lines
)


def list_input(prompt='List input - enter each item on a seperate line\n' + \
        'Enter EOF on a blank line to end ' + \
        '(ctrl-D in *nix, ctrl-Z in windows)',
        maxitems=None, maxlength=None):
    """Get a list of strings as input"""

    lines = []
    print(prompt)
    inum = 1

    try:

        while True:

            if maxitems:

                if inum > maxitems:
                    break
                else:
                    if maxlength:
                        lines.append(string_input('')[:maxlength])
                    else:
                        lines.append(string_input(''))
                    inum += 1

            else:
                if maxlength:
                    lines.append(string_input('')[:maxlength])
                else:
                    lines.append(string_input(''))

    except EOFError:
        pass
    finally:
        return lines


def outfile_input(extension=None):
    """Get an output file name as input"""

    fileok = False

    while not fileok:
        filename = string_input('File name? ')
        if extension:
            if not filename.endswith(extension):
                if extension.startswith('.'):
                    filename = filename + extension
                else:
                    filename = filename + '.' + extension
        if os.path.isfile(filename):
            choice = choice_input(prompt=filename + \
                    ' already exists. Overwrite?',
                    options=['y', 'n'])
            if choice == 'y':
                try:
                    nowtime = time.time()
                    with open(filename, 'a') as f:
                        os.utime(filename, (nowtime, nowtime))
                    fileok = True
                except IOError:
                    print('Write permission denied on ' + filename + \
                            '. Try again.')
                except PermissionError:
                    print('Write permission denied on ' + filename + \
                            '. Try again.')
                except FileNotFoundError:
                    print(filename + ': directory not found. Try again.')

        else:
            choice = choice_input(
                    prompt=filename + ' does not exist. Create it?',
                    options=['y', 'n'])
            if choice == 'y':
                try:
                    nowtime = time.time()
                    with open(filename, 'w') as f:
                        os.utime(filename, (nowtime, nowtime))
                    fileok = True
                except IOError:
                    print('Write permission denied on ' + filename + \
                            '. Try again.')
                except PermissionError:
                    print('Write permission denied on ' + filename + \
                            '. Try again.')
                except FileNotFoundError:
                    print(filename + ': directory not found. Try again.')

    return filename

def
outfile_input
(
extension
=
)
:
fileok
=
False
while
not
fileok
:
filename
=
string_input
(
'File name? '
)
if
extension
:
if
not
filename
.
endswith
(
extension
)
:
if
extension
.
startswith
(
'.'
)
:
filename
=
filename
+
extension
else
:
filename
=
filename
+
'.'
+
extension
if
os
.
path
.
isfile
(
filename
)
:
choice
=
choice_input
(
prompt
=
filename
+
' already exists. Overwrite?'
,
options
=
[
'y'
,
'n'
]
)
if
choice
==
'y'
:
try
:
nowtime
=
time
.
time
(
)
with
open
(
filename
,
'a'
)
as
f
:
os
.
utime
(
filename
,
(
nowtime
,
nowtime
)
)
fileok
=
True
except
IOError
:
print
(
'Write permission denied on '
+
filename
+
'. Try again.'
)
except
PermissionError
:
print
(
'Write permission denied on '
+
filename
+
'. Try again.'
)
except
FileNotFoundError
:
print
(
filename
+
': directory not found. Try again.'
)
else
:
choice
=
choice_input
(
prompt
=
filename
+
' does not exist. Create it?'
,
options
=
[
'y'
,
'n'
]
)
if
choice
==
'y'
:
try
:
nowtime
=
time
.
time
(
)
with
open
(
filename
,
'w'
)
as
f
:
os
.
utime
(
filename
,
(
nowtime
,
nowtime
)
)
fileok
=
True
except
IOError
:
print
(
'Write permission denied on '
+
filename
+
'. Try again.'
)
except
PermissionError
:
print
(
'Write permission denied on '
+
filename
+
'. Try again.'
)
except
FileNotFoundError
:
print
(
filename
+
': directory not found. Try again.'
)
return
filename


def schedule(self, year):
        """Gets schedule information for a team-season.

        :year: The year for which we want the schedule.
        :returns: DataFrame of schedule information.
        """
        doc = self.get_year_doc('{}_games'.format(year))
        table = doc('table#games')
        df = sportsref.utils.parse_table(table)
        return df

def schedule ( self , year ) : doc = self . get_year_doc ( '{}_games' . format ( year ) ) table = doc ( 'table#games' ) df = sportsref . utils . parse_table ( table ) return df

Gets schedule information for a team - season .


def winner(self):
        """Returns the team ID of the winning team. Returns NaN if a tie."""
        hmScore = self.home_score()
        awScore = self.away_score()
        if hmScore > awScore:
            return self.home()
        elif hmScore < awScore:
            return self.away()
        else:
            return None

def winner ( self ) : hmScore = self . home_score ( ) awScore = self . away_score ( ) if hmScore > awScore : return self . home ( ) elif hmScore < awScore : return self . away ( ) else : return None

Returns the team ID of the winning team . Returns NaN if a tie .


def season(self):
        """
        Returns the year ID of the season in which this game took place.
        Useful for week 17 January games.

        :returns: An int representing the year of the season.
        """
        date = self.date()
        return date.year - 1 if date.month <= 3 else date.year

def season ( self ) : date = self . date ( ) return date . year - 1 if date . month <= 3 else date . year

Returns the year ID of the season in which this game took place . Useful for week 17 January games .


def starters(self):
        """Returns a DataFrame where each row is an entry in the starters table
        from PFR.

        The columns are:
        * player_id - the PFR player ID for the player (note that this column
        is not necessarily all unique; that is, one player can be a starter in
        multiple positions, in theory).
        * playerName - the listed name of the player; this too is not
        necessarily unique.
        * position - the position at which the player started for their team.
        * team - the team for which the player started.
        * home - True if the player's team was at home, False if they were away
        * offense - True if the player is starting on an offensive position,
        False if defense.

        :returns: A pandas DataFrame. See the description for details.
        """
        doc = self.get_doc()
        a = doc('table#vis_starters')
        h = doc('table#home_starters')
        data = []
        for h, table in enumerate((a, h)):
            team = self.home() if h else self.away()
            for i, row in enumerate(table('tbody tr').items()):
                datum = {}
                datum['player_id'] = sportsref.utils.rel_url_to_id(
                    row('a')[0].attrib['href']
                )
                datum['playerName'] = row('th').text()
                datum['position'] = row('td').text()
                datum['team'] = team
                datum['home'] = (h == 1)
                datum['offense'] = (i <= 10)
                data.append(datum)
        return pd.DataFrame(data)

def
starters
(
self
)
:
doc
=
self
.
get_doc
(
)
a
=
doc
(
'table#vis_starters'
)
h
=
doc
(
'table#home_starters'
)
data
=
[
]
for
h
,
table
in
enumerate
(
(
a
,
h
)
)
:
team
=
self
.
home
(
)
if
h
else
self
.
away
(
)
for
i
,
row
in
enumerate
(
table
(
'tbody tr'
)
.
items
(
)
)
:
datum
=
{
}
datum
[
'player_id'
]
=
sportsref
.
utils
.
rel_url_to_id
(
row
(
'a'
)
[
0
]
.
attrib
[
'href'
]
)
datum
[
'playerName'
]
=
row
(
'th'
)
.
text
(
)
datum
[
'position'
]
=
row
(
'td'
)
.
text
(
)
datum
[
'team'
]
=
team
datum
[
'home'
]
=
(
h
==
1
)
datum
[
'offense'
]
=
(
i
<=
10
)
data
.
append
(
datum
)
return
pd
.
DataFrame
(
data
)

Returns a DataFrame where each row is an entry in the starters table from PFR .


def surface(self):
        """The playing surface on which the game was played.

        :returns: string representing the type of surface. Returns np.nan if
        not avaiable.
        """
        doc = self.get_doc()
        table = doc('table#game_info')
        giTable = sportsref.utils.parse_info_table(table)
        return giTable.get('surface', np.nan)

def surface ( self ) : doc = self . get_doc ( ) table = doc ( 'table#game_info' ) giTable = sportsref . utils . parse_info_table ( table ) return giTable . get ( 'surface' , np . nan )

The playing surface on which the game was played .


def coin_toss(self):
        """Gets information relating to the opening coin toss.

        Keys are:
        * wonToss - contains the ID of the team that won the toss
        * deferred - bool whether the team that won the toss deferred it

        :returns: Dictionary of coin toss-related info.
        """
        doc = self.get_doc()
        table = doc('table#game_info')
        giTable = sportsref.utils.parse_info_table(table)
        if 'Won Toss' in giTable:
            # TODO: finish coinToss function
            pass
        else:
            return None

def
coin_toss
(
self
)
:
doc
=
self
.
get_doc
(
)
table
=
doc
(
'table#game_info'
)
giTable
=
sportsref
.
utils
.
parse_info_table
(
table
)
if
'Won Toss'
in
giTable
:
# TODO: finish coinToss function
pass
else
:
return

Gets information relating to the opening coin toss .


def weather(self):
        """Returns a dictionary of weather-related info.

        Keys of the returned dict:
        * temp
        * windChill
        * relHumidity
        * windMPH

        :returns: Dict of weather data.
        """
        doc = self.get_doc()
        table = doc('table#game_info')
        giTable = sportsref.utils.parse_info_table(table)
        if 'weather' in giTable:
            regex = (
                r'(?:(?P<temp>\-?\d+) degrees )?'
                r'(?:relative humidity (?P<relHumidity>\d+)%, )?'
                r'(?:wind (?P<windMPH>\d+) mph, )?'
                r'(?:wind chill (?P<windChill>\-?\d+))?'
            )
            m = re.match(regex, giTable['weather'])
            d = m.groupdict()

            # cast values to int
            for k in d:
                try:
                    d[k] = int(d[k])
                except TypeError:
                    pass

            # one-off fixes
            d['windChill'] = (d['windChill'] if pd.notnull(d['windChill'])
                              else d['temp'])
            d['windMPH'] = d['windMPH'] if pd.notnull(d['windMPH']) else 0
            return d
        else:
            # no weather found, because it's a dome
            # TODO: what's relative humidity in a dome?
            return {
                'temp': 70, 'windChill': 70, 'relHumidity': None, 'windMPH': 0
            }

Returns a dictionary of weather - related info .


def ref_info(self):
        """Gets a dictionary of ref positions and the ref IDs of the refs for
        that game.

        :returns: A dictionary of ref positions and IDs.
        """
        doc = self.get_doc()
        table = doc('table#officials')
        return sportsref.utils.parse_info_table(table)

def ref_info ( self ) : doc = self . get_doc ( ) table = doc ( 'table#officials' ) return sportsref . utils . parse_info_table ( table )

Gets a dictionary of ref positions and the ref IDs of the refs for that game .