<commit_before># -*- coding: utf8 -*-

# Copyright (C) 2016 - Philipp Temminghoff <phil65@kodi.tv>
# This program is Free Software see LICENSE file for details

import xbmcgui
import xbmc
from kodi65 import utils

class ListItem(object):
    ICON_OVERLAY_NONE = 0       # No overlay icon
    ICON_OVERLAY_RAR = 1        # Compressed *.rar files
    ICON_OVERLAY_ZIP = 2        # Compressed *.zip files
    ICON_OVERLAY_LOCKED = 3     # Locked files
    ICON_OVERLAY_UNWATCHED = 4  # For not watched files
    ICON_OVERLAY_WATCHED = 5    # For seen files
    ICON_OVERLAY_HD = 6         # Is on hard disk stored

    def __init__(self, label="", label2="", path="", infos=None, properties=None, size="", artwork=None, ratings=None, ids=None):
        """
        Kodi listitem, based on built-in datatypes
        """
        self.set_label(label)
        self.set_label2(label2)
        self.path = path
        self.size = ""
        self.videoinfo = []
        self.audioinfo = []
        self.subinfo = []
        self.cast = []
        self._properties = properties if properties else {}
        self._artwork = artwork if artwork else {}
        self._ratings = ratings if ratings else []
        self._ids = ids if ids else {}
        self._infos = infos if infos else {}
        self.specials = {}
        self._is_folder = False

    def __setitem__(self, key, value):
        self._properties[key] = value

    def __getitem__(self, key):
        if key in self._properties:
            return self._properties[key]
        elif key in self._artwork:
            return self._artwork[key]
        elif key in self._infos:
            return self._infos[key]
        elif key == "properties":
            return self._properties
        elif key == "infos":
            return self._infos
        elif key == "artwork":
            return self._artwork
        elif key == "label":
            return self.label
        elif key == "label2":
            return self.label2
        elif key == "path":
            return self.path
        else:
            raise KeyError(str(key))

    def __repr__(self):
        return "\n".join(["Label:", self.label,
                          "Label2:", self.label2,
                          "InfoLabels:", utils.dump_dict(self._infos),
                          "Properties:", utils.dump_dict(self._properties),
                          "Artwork:", utils.dump_dict(self._artwork),
                          "Specials:", utils.dump_dict(self.specials),
                          "", ""])

    def __contains__(self, key):
        if key in self._properties:
            return True
        elif key in self._artwork:
            return True
        elif key in self._infos:
            return True
        elif key in ["properties", "infos", "artwork", "label", "label2", "path"]:
            return True

    def __delitem__(self, key):
        if key in self._properties:
            del self._properties[key]

    def get(self, key, fallback=None):
        try:
            return self.__getitem__(key)
        except KeyError:
            return fallback

    def update_from_listitem(self, listitem):
        if not listitem:
            return None
        self.set_label(listitem.label)
        self.set_label2(listitem.label2)
        self.set_size(listitem.size)
        self.update_properties(listitem.get_properties())
        self.update_artwork(listitem.get_artwork())
        self.update_infos(listitem.get_infos())

    def set_label(self, label):
        self.label = label

    def set_label2(self, label):
        self.label2 = label

    def set_mimetype(self, mimetype):
        self.specials["mimetype"] = mimetype

    def fix_at_top(self):
        self.specials["specialsort"] = "top"

    def fix_at_bottom(self):
        self.specials["specialsort"] = "bottom"

    def set_startoffset(self, value):
        self.specials["startoffset"] = value

    def set_totaltime(self, value):
        self.specials["totaltime"] = value

    def set_resumetime(self, value):
        self.specials["resumetime"] = value

    def set_playable(self, value):
        self.specials["isPlayable"] = value

    def is_playable(self):
        return bool(self.specials.get("isPlayable"))

    def set_folder(self, value):
        self._is_folder = value

    def is_folder(self):
        return bool(self._is_folder)

# playlist_starting_track isspecial item_start isplayable

    def set_size(self, size):
        self.size = size

    def set_visible(self, condition):
        self.specials["node.visible"] = condition

    def set_target(self, target):
        self.specials["node.target"] = target

    def set_infos(self, infos):
        self._infos = infos

    def set_artwork(self, artwork):
        self._artwork = artwork

    def set_properties(self, properties):
        self._properties = properties

    def update_properties(self, properties):
        self._properties.update({k: v for k, v in properties.iteritems() if v})

    def update_artwork(self, artwork):
        self._artwork.update({k: v for k, v in artwork.iteritems() if v})

    def update_infos(self, infos):
        self._infos.update({k: v for k, v in infos.iteritems() if v})

    def set_art(self, key, value):
        self._artwork[key] = value

    def set_property(self, key, value):
        self._properties[key] = value

    def set_info(self, key, value):
        self._infos[key] = value

    def get_path(self):
        return self.path

    def get_art(self, key):
        value = self._artwork.get(key)
        return value if value else ""

    def get_info(self, key):
        value = self._infos.get(key)
        return value if value else ""

    def get_property(self, key):
        value = self._properties.get(key)
        return value if value else ""

    def get_artwork(self):
        return {k: v for k, v in self._artwork.iteritems() if v}

    def get_infos(self):
        return {k: v for k, v in self._infos.iteritems() if v}

    def get_properties(self):
        return {k: v for k, v in self._properties.iteritems() if v}

    def get_listitem(self):
        listitem = xbmcgui.ListItem(label=unicode(self.label) if self.label else "",
                                    label2=unicode(self.label2) if self.label2 else "",
                                    path=self.path)
        props = {k: unicode(v) for k, v in self._properties.iteritems() if v}
        infos = {k.lower(): v for k, v in self._infos.iteritems() if v}
        infos["path"] = self.path
        if "duration" in infos:
            props['duration(h)'] = utils.format_time(infos["duration"], "h")
            props['duration(m)'] = utils.format_time(infos["duration"], "m")
        for key, value in props.iteritems():
            listitem.setProperty(key, unicode(value))
        for key, value in self.specials.iteritems():
            listitem.setProperty(key, unicode(value))
        artwork = {k: v for k, v in self._artwork.iteritems() if v}
        if artwork:
            listitem.setArt(artwork)
        if infos:
            listitem.setInfo(self.type, infos)
        return listitem

    def to_windowprops(self, prefix="", window_id=10000):
        window = xbmcgui.Window(window_id)
        window.setProperty('%slabel' % (prefix), self.label)
        window.setProperty('%slabel2' % (prefix), self.label2)
        window.setProperty('%spath' % (prefix), self.path)
        dct = utils.merge_dicts(self.get_properties(),
                                self.get_artwork(),
                                self.get_infos())
        for k, v in dct.iteritems():
            window.setProperty('%s%s' % (prefix, k), unicode(v))

class AudioItem(ListItem):
    """
    Kodi audio listitem, based on built-in datatypes
    """
    props = ["id",
             "artist_instrument",
             "artist_style",
             "artist_mood",
             "artist_born",
             "artist_formed",
             "artist_description",
             "artist_genre",
             "artist_died",
             "artist_disbanded",
             "artist_yearsactive",
             "artist_born",
             "artist_died",
             "album_description",
             "album_theme",
             "album_mood",
             "album_style",
             "album_type",
             "album_label",
             "album_artist",
             "album_genre",
             "album_title",
             "album_rating",
             "album_userrating",
             "album_votes",
             "album_releasetype"]

    def __init__(self, *args, **kwargs):
        self.type = "music"
        super(AudioItem, self).__init__(*args, **kwargs)

    def from_listitem(self, listitem):
        info = listitem.getAudioInfoTag()
        self.label = listitem.getLabel().decode("utf-8")
        self.path = info.getPath().decode("utf-8")
        self._infos = {"dbid": info.GetDatabaseId(),
                       "mediatype": info.GetMediaType(),
                       "title": info.GetTitle().decode("utf-8"),
                       "votes": info.GetVotes(),
                       "rating": info.GetRating(),
                       "userrating": info.GetUserRating(),
                       "file": info.GetFile().decode("utf-8"),
                       "comment": info.getComment().decode("utf-8"),
                       "lyrics": info.getLyrics().decode("utf-8"),
                       "genre": info.getGenre().decode("utf-8"),
                       "lastplayed": info.getLastPlayed(),
                       "listeners": info.getListeners(),
                       "playcount": info.getPlayCount(),
                       "year": info.getReleaseDate()}
        self._properties = {key: listitem.getProperty(key) for key in self.props}

    def from_infolabels(self):
        self.label = xbmc.getInfoLabel("ListItem.Label")
        self.path = xbmc.getInfoLabel("ListItem.Path")
        self._infos = {"dbid": xbmc.getInfoLabel("ListItem.Label"),
                       "mediatype": xbmc.getInfoLabel("ListItem.DBType"),
                       "title": xbmc.getInfoLabel("ListItem.Title"),
                       "votes": xbmc.getInfoLabel("ListItem.Votes"),
                       "rating": xbmc.getInfoLabel("ListItem.Rating"),
                       "userrating": xbmc.getInfoLabel("ListItem.UserRating"),
                       "file": xbmc.getInfoLabel("ListItem.FileNameAndPath"),
                       "comment": xbmc.getInfoLabel("ListItem.Comment"),
                       "lyrics": xbmc.getInfoLabel("ListItem.Lyrics"),
                       "genre": xbmc.getInfoLabel("ListItem.Genre"),
                       "lastplayed": xbmc.getInfoLabel("ListItem.Label"),
                       "listeners": xbmc.getInfoLabel("ListItem.Listeners"),
                       "playcount": xbmc.getInfoLabel("ListItem.Playcount"),
                       "year": xbmc.getInfoLabel("ListItem.Year")}
        self._properties = {key: xbmc.getInfoLabel("ListItem.Property({}".format(key)) for key in self.props}

class VideoItem(ListItem):
    """
    Kodi video listitem, based on built-in datatypes
    """

    def __init__(self, *args, **kwargs):
        self.type = "video"
        super(VideoItem, self).__init__(*args, **kwargs)

    def __repr__(self):
        baseinfo = super(VideoItem, self).__repr__()
        return "\n".join([baseinfo,
                          "Cast:", utils.dump_dict(self.cast),
                          "VideoStreams:", utils.dump_dict(self.videoinfo),
                          "AudioStreams:", utils.dump_dict(self.audioinfo),
                          "Ratings:", utils.dump_dict(self._ratings),
                          "Ids:", utils.dump_dict(self._ids),
                          "Subs:", utils.dump_dict(self.subinfo),
                          "", ""])

    def from_listitem(self, listitem):
        info = listitem.getVideoInfoTag()
        self.label = listitem.getLabel().decode("utf-8")
        self.path = info.getPath().decode("utf-8")
        for provider in {"tmdb", "imdb", "trakt"}:
            self._ratings[provider] = listitem.getRating(provider)
        self._infos = {"dbid": info.getDbId(),
                       "mediatype": info.getMediaType(),
                       "plot": info.getPlot().decode("utf-8"),
                       "plotoutline": info.getPlotOutline().decode("utf-8"),
                       "tvshowtitle": info.getTVShowTitle().decode("utf-8"),
                       "title": info.getTitle().decode("utf-8"),
                       "votes": info.getVotes(),
                       "season": info.getSeason(),
                       "episode": info.getEpisode(),
                       "rating": info.getRating(),
                       "userrating": info.getUserRating(),
                       "pictureurl": info.getPictureURL(),
                       "cast": info.getCast(),
                       "file": info.getFile().decode("utf-8"),
                       "trailer": info.getTrailer().decode("utf-8"),
                       "originaltitle": info.getOriginalTitle().decode("utf-8"),
                       "tagline": info.getTagLine().decode("utf-8"),
                       "genre": info.getGenre().decode("utf-8"),
                       "director": info.getDirector().decode("utf-8"),
                       "writer": info.getWritingCredits().decode("utf-8"),
                       "lastplayed": info.getLastPlayed(),
                       "premiered": info.getPremiered(),
                       "firstaired": info.getFirstAired(),
                       "playcount": info.getPlayCount(),
                       "imdbnumber": info.getIMDBNumber(),
                       "year": info.getYear()}

    def update_from_listitem(self, listitem):
        if not listitem:
            return None
        super(VideoItem, self).update_from_listitem(listitem)
        self.set_videoinfos(listitem.videoinfo)
        self.set_audioinfos(listitem.audioinfo)
        self.set_subinfos(listitem.subinfo)
        self.set_cast(listitem.cast)

    def get_listitem(self):
        listitem = super(VideoItem, self).get_listitem()
        for item in self.videoinfo:
            listitem.addStreamInfo("video", item)
        for item in self.audioinfo:
            listitem.addStreamInfo("audio", item)
        for item in self.subinfo:
            listitem.addStreamInfo("subtitle", item)
        for item in self._ratings:
            listitem.setRating(item["type"], item["rating"], item["votes"], item["def"])
        listitem.setUniqueIDs(self._ids)
        listitem.setCast(self.cast)
        return listitem

    def add_videoinfo(self, info):
        self.videoinfo.append(info)

    def add_audioinfo(self, info):
        self.audioinfo.append(info)

    def add_subinfo(self, info):
        self.subinfo.append(info)

    def add_cast(self, value):
        self.cast.append(value)

    def set_cast(self, value):
        self.cast = value

    def set_videoinfos(self, infos):
        self.videoinfo = infos

    def set_audioinfos(self, infos):
        self.audioinfo = infos

    def set_subinfos(self, infos):
        self.subinfo = infos

    def get_rating(self, provider):
        for item in self._ratings:
            if item["provider"] == provider.lower():
                return item
        return None

    def add_rating(self, provider, rating, votes=None, default=None):
        self._ratings.append({"provider": provider.lower(),
                              "rating": rating,
                              "votes": int(votes),
                              "default": bool(default)})

    def set_id(self, provider, uid):
        self._ids[provider] = uid

    def get_id(self):
        return self._ids

    def movie_from_dbid(self, dbid):
        from LocalDB import local_db
        if not dbid:
            return None
        self.update_from_listitem(local_db.get_movie(dbid))

class GameItem(ListItem):
    """
    Kodi game listitem, based on built-in datatypes
    """

    def __init__(self, *args, **kwargs):
        self.type = "game"
        super(GameItem, self).__init__(*args, **kwargs)

<commit_msg>add get_ratings<commit_after># -*- coding: utf8 -*-

# Copyright (C) 2016 - Philipp Temminghoff <phil65@kodi.tv>
# This program is Free Software see LICENSE file for details

import xbmcgui
import xbmc
from kodi65 import utils

class ListItem(object):
    ICON_OVERLAY_NONE = 0       # No overlay icon
    ICON_OVERLAY_RAR = 1        # Compressed *.rar files
    ICON_OVERLAY_ZIP = 2        # Compressed *.zip files
    ICON_OVERLAY_LOCKED = 3     # Locked files
    ICON_OVERLAY_UNWATCHED = 4  # For not watched files
    ICON_OVERLAY_WATCHED = 5    # For seen files
    ICON_OVERLAY_HD = 6         # Is on hard disk stored

    def __init__(self, label="", label2="", path="", infos=None, properties=None, size="", artwork=None, ratings=None, ids=None):
        """
        Kodi listitem, based on built-in datatypes
        """
        self.set_label(label)
        self.set_label2(label2)
        self.path = path
        self.size = ""
        self.videoinfo = []
        self.audioinfo = []
        self.subinfo = []
        self.cast = []
        self._properties = properties if properties else {}
        self._artwork = artwork if artwork else {}
        self._ratings = ratings if ratings else []
        self._ids = ids if ids else {}
        self._infos = infos if infos else {}
        self.specials = {}
        self._is_folder = False

    def __setitem__(self, key, value):
        self._properties[key] = value

    def __getitem__(self, key):
        if key in self._properties:
            return self._properties[key]
        elif key in self._artwork:
            return self._artwork[key]
        elif key in self._infos:
            return self._infos[key]
        elif key == "properties":
            return self._properties
        elif key == "infos":
            return self._infos
        elif key == "artwork":
            return self._artwork
        elif key == "label":
            return self.label
        elif key == "label2":
            return self.label2
        elif key == "path":
            return self.path
        else:
            raise KeyError(str(key))

    def __repr__(self):
        return "\n".join(["Label:", self.label,
                          "Label2:", self.label2,
                          "InfoLabels:", utils.dump_dict(self._infos),
                          "Properties:", utils.dump_dict(self._properties),
                          "Artwork:", utils.dump_dict(self._artwork),
                          "Specials:", utils.dump_dict(self.specials),
                          "", ""])

    def __contains__(self, key):
        if key in self._properties:
            return True
        elif key in self._artwork:
            return True
        elif key in self._infos:
            return True
        elif key in ["properties", "infos", "artwork", "label", "label2", "path"]:
            return True

    def __delitem__(self, key):
        if key in self._properties:
            del self._properties[key]

    def get(self, key, fallback=None):
        try:
            return self.__getitem__(key)
        except KeyError:
            return fallback

    def update_from_listitem(self, listitem):
        if not listitem:
            return None
        self.set_label(listitem.label)
        self.set_label2(listitem.label2)
        self.set_size(listitem.size)
        self.update_properties(listitem.get_properties())
        self.update_artwork(listitem.get_artwork())
        self.update_infos(listitem.get_infos())

    def set_label(self, label):
        self.label = label

    def set_label2(self, label):
        self.label2 = label

    def set_mimetype(self, mimetype):
        self.specials["mimetype"] = mimetype

    def fix_at_top(self):
        self.specials["specialsort"] = "top"

    def fix_at_bottom(self):
        self.specials["specialsort"] = "bottom"

    def set_startoffset(self, value):
        self.specials["startoffset"] = value

    def set_totaltime(self, value):
        self.specials["totaltime"] = value

    def set_resumetime(self, value):
        self.specials["resumetime"] = value

    def set_playable(self, value):
        self.specials["isPlayable"] = value

    def is_playable(self):
        return bool(self.specials.get("isPlayable"))

    def set_folder(self, value):
        self._is_folder = value

    def is_folder(self):
        return bool(self._is_folder)

# playlist_starting_track isspecial item_start isplayable

    def set_size(self, size):
        self.size = size

    def set_visible(self, condition):
        self.specials["node.visible"] = condition

    def set_target(self, target):
        self.specials["node.target"] = target

    def set_infos(self, infos):
        self._infos = infos

    def set_artwork(self, artwork):
        self._artwork = artwork

    def set_properties(self, properties):
        self._properties = properties

    def update_properties(self, properties):
        self._properties.update({k: v for k, v in properties.iteritems() if v})

    def update_artwork(self, artwork):
        self._artwork.update({k: v for k, v in artwork.iteritems() if v})

    def update_infos(self, infos):
        self._infos.update({k: v for k, v in infos.iteritems() if v})

    def set_art(self, key, value):
        self._artwork[key] = value

    def set_property(self, key, value):
        self._properties[key] = value

    def set_info(self, key, value):
        self._infos[key] = value

    def get_path(self):
        return self.path

    def get_art(self, key):
        value = self._artwork.get(key)
        return value if value else ""

    def get_info(self, key):
        value = self._infos.get(key)
        return value if value else ""

    def get_property(self, key):
        value = self._properties.get(key)
        return value if value else ""

    def get_artwork(self):
        return {k: v for k, v in self._artwork.iteritems() if v}

    def get_infos(self):
        return {k: v for k, v in self._infos.iteritems() if v}

    def get_properties(self):
        return {k: v for k, v in self._properties.iteritems() if v}

    def get_listitem(self):
        listitem = xbmcgui.ListItem(label=unicode(self.label) if self.label else "",
                                    label2=unicode(self.label2) if self.label2 else "",
                                    path=self.path)
        props = {k: unicode(v) for k, v in self._properties.iteritems() if v}
        infos = {k.lower(): v for k, v in self._infos.iteritems() if v}
        infos["path"] = self.path
        if "duration" in infos:
            props['duration(h)'] = utils.format_time(infos["duration"], "h")
            props['duration(m)'] = utils.format_time(infos["duration"], "m")
        for key, value in props.iteritems():
            listitem.setProperty(key, unicode(value))
        for key, value in self.specials.iteritems():
            listitem.setProperty(key, unicode(value))
        artwork = {k: v for k, v in self._artwork.iteritems() if v}
        if artwork:
            listitem.setArt(artwork)
        if infos:
            listitem.setInfo(self.type, infos)
        return listitem

    def to_windowprops(self, prefix="", window_id=10000):
        window = xbmcgui.Window(window_id)
        window.setProperty('%slabel' % (prefix), self.label)
        window.setProperty('%slabel2' % (prefix), self.label2)
        window.setProperty('%spath' % (prefix), self.path)
        dct = utils.merge_dicts(self.get_properties(),
                                self.get_artwork(),
                                self.get_infos())
        for k, v in dct.iteritems():
            window.setProperty('%s%s' % (prefix, k), unicode(v))

class AudioItem(ListItem):
    """
    Kodi audio listitem, based on built-in datatypes
    """
    props = ["id",
             "artist_instrument",
             "artist_style",
             "artist_mood",
             "artist_born",
             "artist_formed",
             "artist_description",
             "artist_genre",
             "artist_died",
             "artist_disbanded",
             "artist_yearsactive",
             "artist_born",
             "artist_died",
             "album_description",
             "album_theme",
             "album_mood",
             "album_style",
             "album_type",
             "album_label",
             "album_artist",
             "album_genre",
             "album_title",
             "album_rating",
             "album_userrating",
             "album_votes",
             "album_releasetype"]

    def __init__(self, *args, **kwargs):
        self.type = "music"
        super(AudioItem, self).__init__(*args, **kwargs)

    def from_listitem(self, listitem):
        info = listitem.getAudioInfoTag()
        self.label = listitem.getLabel().decode("utf-8")
        self.path = info.getPath().decode("utf-8")
        self._infos = {"dbid": info.GetDatabaseId(),
                       "mediatype": info.GetMediaType(),
                       "title": info.GetTitle().decode("utf-8"),
                       "votes": info.GetVotes(),
                       "rating": info.GetRating(),
                       "userrating": info.GetUserRating(),
                       "file": info.GetFile().decode("utf-8"),
                       "comment": info.getComment().decode("utf-8"),
                       "lyrics": info.getLyrics().decode("utf-8"),
                       "genre": info.getGenre().decode("utf-8"),
                       "lastplayed": info.getLastPlayed(),
                       "listeners": info.getListeners(),
                       "playcount": info.getPlayCount(),
                       "year": info.getReleaseDate()}
        self._properties = {key: listitem.getProperty(key) for key in self.props}

    def from_infolabels(self):
        self.label = xbmc.getInfoLabel("ListItem.Label")
        self.path = xbmc.getInfoLabel("ListItem.Path")
        self._infos = {"dbid": xbmc.getInfoLabel("ListItem.Label"),
                       "mediatype": xbmc.getInfoLabel("ListItem.DBType"),
                       "title": xbmc.getInfoLabel("ListItem.Title"),
                       "votes": xbmc.getInfoLabel("ListItem.Votes"),
                       "rating": xbmc.getInfoLabel("ListItem.Rating"),
                       "userrating": xbmc.getInfoLabel("ListItem.UserRating"),
                       "file": xbmc.getInfoLabel("ListItem.FileNameAndPath"),
                       "comment": xbmc.getInfoLabel("ListItem.Comment"),
                       "lyrics": xbmc.getInfoLabel("ListItem.Lyrics"),
                       "genre": xbmc.getInfoLabel("ListItem.Genre"),
                       "lastplayed": xbmc.getInfoLabel("ListItem.Label"),
                       "listeners": xbmc.getInfoLabel("ListItem.Listeners"),
                       "playcount": xbmc.getInfoLabel("ListItem.Playcount"),
                       "year": xbmc.getInfoLabel("ListItem.Year")}
        self._properties = {key: xbmc.getInfoLabel("ListItem.Property({}".format(key)) for key in self.props}

class VideoItem(ListItem):
    """
    Kodi video listitem, based on built-in datatypes
    """

    def __init__(self, *args, **kwargs):
        self.type = "video"
        super(VideoItem, self).__init__(*args, **kwargs)

    def __repr__(self):
        baseinfo = super(VideoItem, self).__repr__()
        return "\n".join([baseinfo,
                          "Cast:", utils.dump_dict(self.cast),
                          "VideoStreams:", utils.dump_dict(self.videoinfo),
                          "AudioStreams:", utils.dump_dict(self.audioinfo),
                          "Ratings:", utils.dump_dict(self._ratings),
                          "Ids:", utils.dump_dict(self._ids),
                          "Subs:", utils.dump_dict(self.subinfo),
                          "", ""])

    def from_listitem(self, listitem):
        info = listitem.getVideoInfoTag()
        self.label = listitem.getLabel().decode("utf-8")
        self.path = info.getPath().decode("utf-8")
        for provider in {"tmdb", "imdb", "trakt"}:
            self._ratings[provider] = listitem.getRating(provider)
        self._infos = {"dbid": info.getDbId(),
                       "mediatype": info.getMediaType(),
                       "plot": info.getPlot().decode("utf-8"),
                       "plotoutline": info.getPlotOutline().decode("utf-8"),
                       "tvshowtitle": info.getTVShowTitle().decode("utf-8"),
                       "title": info.getTitle().decode("utf-8"),
                       "votes": info.getVotes(),
                       "season": info.getSeason(),
                       "episode": info.getEpisode(),
                       "rating": info.getRating(),
                       "userrating": info.getUserRating(),
                       "pictureurl": info.getPictureURL(),
                       "cast": info.getCast(),
                       "file": info.getFile().decode("utf-8"),
                       "trailer": info.getTrailer().decode("utf-8"),
                       "originaltitle": info.getOriginalTitle().decode("utf-8"),
                       "tagline": info.getTagLine().decode("utf-8"),
                       "genre": info.getGenre().decode("utf-8"),
                       "director": info.getDirector().decode("utf-8"),
                       "writer": info.getWritingCredits().decode("utf-8"),
                       "lastplayed": info.getLastPlayed(),
                       "premiered": info.getPremiered(),
                       "firstaired": info.getFirstAired(),
                       "playcount": info.getPlayCount(),
                       "imdbnumber": info.getIMDBNumber(),
                       "year": info.getYear()}

    def update_from_listitem(self, listitem):
        if not listitem:
            return None
        super(VideoItem, self).update_from_listitem(listitem)
        self.set_videoinfos(listitem.videoinfo)
        self.set_audioinfos(listitem.audioinfo)
        self.set_subinfos(listitem.subinfo)
        self.set_cast(listitem.cast)

    def get_listitem(self):
        listitem = super(VideoItem, self).get_listitem()
        for item in self.videoinfo:
            listitem.addStreamInfo("video", item)
        for item in self.audioinfo:
            listitem.addStreamInfo("audio", item)
        for item in self.subinfo:
            listitem.addStreamInfo("subtitle", item)
        for item in self._ratings:
            listitem.setRating(item["type"], item["rating"], item["votes"], item["default"])
        listitem.setUniqueIDs(self._ids)
        listitem.setCast(self.cast)
        return listitem

    def add_videoinfo(self, info):
        self.videoinfo.append(info)

    def add_audioinfo(self, info):
        self.audioinfo.append(info)

    def add_subinfo(self, info):
        self.subinfo.append(info)

    def add_cast(self, value):
        self.cast.append(value)

    def set_cast(self, value):
        self.cast = value

    def set_videoinfos(self, infos):
        self.videoinfo = infos

    def set_audioinfos(self, infos):
        self.audioinfo = infos

    def set_subinfos(self, infos):
        self.subinfo = infos

    def get_rating(self, provider):
        for item in self._ratings:
            if item["provider"] == provider.lower():
                return item
        return None

    def get_ratings(self):
        return self._ratings

    def add_rating(self, provider, rating, votes=None, default=None):
        self._ratings.append({"provider": provider.lower(),
                              "rating": rating,
                              "votes": int(votes),
                              "default": bool(default)})

    def set_id(self, provider, uid):
        self._ids[provider] = uid

    def get_id(self):
        return self._ids

    def movie_from_dbid(self, dbid):
        from LocalDB import local_db
        if not dbid:
            return None
        self.update_from_listitem(local_db.get_movie(dbid))

class GameItem(ListItem):
    """
    Kodi game listitem, based on built-in datatypes
    """

    def __init__(self, *args, **kwargs):
        self.type = "game"
        super(GameItem, self).__init__(*args, **kwargs)

<|endoftext|>


<commit_before>import os
from flask import render_template
from flask import request, url_for, redirect, flash, send_from_directory, send_file
from flask_user import login_required, confirm_email_required, roles_required, current_user
from flask_user.views import invite
from . import admin, db
from app import uploaded_photos
import imghdr
from flask_uploads import UploadNotAllowed
from .models import User, Role, UserRoles
from sqlalchemy.orm import aliased
from sqlalchemy.exc import IntegrityError
from .forms import UserForm, RoleForm, AvatarUploadForm
from array import array
from sqlalchemy.sql import exists
from werkzeug.utils import secure_filename

# Current user is admin
def current_user_is_admin() :
    value = False
    for r in current_user.roles:
        if r.name == "admin":
            value= True

    return value

# Save avatar - fuction
def save_avatar():
    f = request.files['photo']
    # Check intigrity image
    check_photo=imghdr.what(f)

    if check_photo is not None :
        fname = secure_filename(f.filename)
        fname=os.path.splitext(fname)
        #Rename file: avatar_id.ext
        f.filename = "avatar_"+str(current_user.id)+fname[1]

        try:
            # Save image in upload_photos
            filename_upload=uploaded_photos.save(f)

            # Remove image, if filename is diferent and filename save Database
            if filename_upload !=  current_user.avatar_photo and current_user.avatar_photo !=" ":
                remove_avatar(current_user)

            current_user.avatar_photo = filename_upload
            db.session.commit()

        # Image is not integrated
        except UploadNotAllowed:
            flash("The upload not image")

    # Image is not integrated
    else:
        flash("The upload not image")

# Remove avatar - function
def remove_avatar(user):
    # Selection image avatar
    folder=os.getenv('UPLOADED_PHOTOS_DEST')
    filename=user.avatar_photo
    photo_path = folder+"/"+filename

    # Remove file if it matches some parameters
    if photo_path != folder and photo_path != folder+"/" and photo_path != folder+"/ "  :
        os.remove(photo_path)

# Root - route
@admin.route('/')
def home_page():
    return redirect(url_for('admin.members_page') )

# About - route
@admin.route('/about')
def about_page():
    return render_template('about_admin_page.html', blueprint_title="Admin", title="About")

# Members - route
@admin.route('/members')
@login_required
def members_page():
    return render_template('members/members_page.html', users=db.session.query(User).all(),
        blueprint_title="Admin", title="Members" , current_user_is_admin=current_user_is_admin())

# Members_invite
@admin.route('/members/invite', methods=['GET', 'POST'])
@login_required
@roles_required('admin')
def members_invite():
    return invite()

# Users_profile - route
@admin.route('/members/profile/<username>')
@login_required
def profile_page(username):
    return render_template('members/profile_page.html',
        user=db.session.query(User).filter(User.username == username).first(),
        blueprint_title="Admin", title="Members", subtitle="Profile",
        current_user_is_admin=current_user_is_admin() )

# CurrentUser_profile_edit - route
@admin.route('/members/myprofile/edit', methods=['GET', 'POST'])
@login_required
def edit_myprofile():
    # Initialize form
    form_user = UserForm()
    form_avatar_upload = AvatarUploadForm()

    # Process valid POST- form_user
    if request.method == 'POST' and form_user.validate():
        # Copy form fields to user_profile fields
        form_user.populate_obj(current_user)

        # Save user_profile
        db.session.commit()

        # Redirect to home page
        return redirect(url_for('admin.edit_myprofile'))

    # Process valid POST - form_avatar_upload
    if  request.method == 'POST' and form_avatar_upload.validate():
        save_avatar()
        return redirect(url_for('admin.edit_myprofile'))
    elif request.method == 'POST':
        flash(('File isn\'t image'), 'success')
        return redirect(url_for('admin.edit_myprofile'))

    # Process GET or invalid POST
    return render_template('members/edit_myprofile.html',
        form_user=form_user, form_avatar_upload=form_avatar_upload,
         blueprint_title="Admin", title="Members", subtitle="Edit profile")

# CurrentUser_admin_role_profile_edit - route
@admin.route('/members/myprofile/edit/admin', methods=['GET', 'POST'])
@roles_required('admin')
def edit_myprofile_roles():
    # Initialize form
    form_user = UserForm()
    form_role = RoleForm()
    form_avatar_upload = AvatarUploadForm()

    # Process valid POST - form_user
    if request.method == 'POST' and form_user.validate():
        # Copy form fields to user_profile fields
        form_user.populate_obj(current_user)

        # Save user_profile
        db.session.commit()

        # Redirect to home page
        return redirect(url_for('admin.edit_myprofile_roles'))

    # Process valid POST - form_avatar_upload
    if  form_avatar_upload.validate_on_submit():
        save_avatar()
        return redirect(url_for('admin.edit_myprofile_roles'))
    elif request.method == 'POST':
        flash(('File isn\'t image'), 'success')
        return redirect(url_for('admin.edit_myprofile_roles'))

    return render_template('members/edit_myprofile_roles.html', form_user=form_user,
        form_role=form_role, form_avatar_upload=form_avatar_upload,
        roles=db.session.query(Role).all(),  blueprint_title="Admin", title="Members",
        subtitle="Profile edit")

# Edit_profile_roles - route
@admin.route('/members/profile/roles/edit/<username>' ,methods=['GET','POST'])
@roles_required('admin')
def  edit_profile_roles(username):
    user=db.session.query(User).filter(User.username == username).first()

    # Initialize form
    form_user = UserForm()
    form_role = RoleForm()

    return render_template('members/edit_profile_roles.html', user=user, form_user=form_user,
        form_role=form_role,roles=db.session.query(Role).all(),  blueprint_title="Admin", title="Members",
        subtitle="Profile edit" )

#Roles - route
@admin.route('/roles')
@roles_required('admin')
def roles_page():
    form_role = RoleForm()

    return render_template('roles/roles_page.html', form_role=form_role, roles=db.session.query(Role).all(),
      blueprint_title="Admin", title="Roles" )

#Add_role - route
@admin.route('/roles/add' ,methods=['GET','POST'])
@roles_required('admin')
def add_role():
    # Initialize form
    form_role = RoleForm()

    # Process valid POST
    if request.method == 'POST' and form_role.validate():

        #Add role, if role not exist
        if not Role.query.filter(Role.name==form_role.name.data).first():
            role = Role(name=form_role.name.data)
            db.session.add(role)
            db.session.commit()
        else:
            flash(('Role '+form_role.name.data+' exist.'), 'success')

    return "None"

#Add_role to user - route
@admin.route('/members/roles/add/<username>' ,methods=['GET','POST'])
@roles_required('admin')
def add_role_user(username) :
    user=db.session.query(User).filter(User.username == username).first()

    #User is current_user
    user_is_current_user=False
    if user == current_user:
        user_is_current_user=True

    form_role = RoleForm()

    if request.method == 'POST' and form_role.validate() :
        #Remove deselect roles
        remove_roles= [ ]

        #User Roles
        role_admin=False
        for r_user in user.roles :
            role_status=False

            #Role admin user
            if r_user.name == "admin" :
                role_admin=True

            #Roles checks
            for r_name in request.form.getlist("name") :
                #Compare with roles user, true If the role remains checked
                if r_user.name == r_name :
                    role_status=True
            #Add array remove_roles, If the role does not remains checked
            if not role_status :
                remove_roles.append(r_user.name)

        #Removes roles that are not checked now
        for r_role in remove_roles :
            role=db.session.query(Role).filter(Role.name==r_role).first()
            user.roles.remove(role)
            db.session.commit()

        #Add roles checked
        for r_name in request.form.getlist("name") :
            role=db.session.query(Role).filter(Role.name==r_name).first()

            #If it does not belong to the user it adds it
            if not db.session.query(User).join(User.roles).filter(User.username==user.username, Role.name==role.name).first() :
                user.roles.append(role)
                db.session.commit()

    if user_is_current_user and role_admin :
        return redirect(url_for('admin.edit_myprofile_roles', username=username))
    else:
        return redirect(url_for('admin.edit_profile_roles', username=username))

#Remove_role - route
@admin.route('/roles/remove', methods=['POST'])
@roles_required('admin')
def remove_role():

    if request.method == 'POST' :
        role_remove=db.session.query(Role).filter(Role.name==request.form["role_remove"]).first()

        db.session.delete(role_remove)
        db.session.commit()

    return "None"

#Remove_user - route
@admin.route('/user/remove', methods=['POST'])
@roles_required('admin')
def remove_user():
    if request.method == 'POST' :
        user_remove=db.session.query(User).filter(User.username==request.form["user_remove"]).first()

        db.session.delete(user_remove)
        db.session.commit()

        remove_avatar(user_remove)

    return "None"

#Load_avatar -route
@admin.route('/members/loaded/avatar/<username>')
@login_required
def loaded_avatar(username):
    #Selection image avatar database
    user=db.session.query(User).filter(User.username==username).first()
    filename = user.avatar_photo

    folder=os.getenv('UPLOADED_PHOTOS_DEST');

    #Load_path
    photo_path="../"+folder+"/"+filename

    #Look image
    return send_file(photo_path, mimetype='image/png'
    )
<commit_msg>views add confirm_email<commit_after>import os
from flask import render_template
from flask import request, url_for, redirect, flash, send_from_directory, send_file
from flask_user import login_required, confirm_email_required, roles_required, current_user
from flask_user.views import invite
from . import admin, db
from app import uploaded_photos
import imghdr
from flask_uploads import UploadNotAllowed
from .models import User, Role, UserRoles
from sqlalchemy.orm import aliased
from sqlalchemy.exc import IntegrityError
from .forms import UserForm, RoleForm, AvatarUploadForm
from array import array
from sqlalchemy.sql import exists
from werkzeug.utils import secure_filename

# Current user is admin
def current_user_is_admin() :
    value = False
    for r in current_user.roles:
        if r.name == "admin":
            value= True

    return value

# Save avatar - fuction
def save_avatar():
    f = request.files['photo']
    # Check intigrity image
    check_photo=imghdr.what(f)

    if check_photo is not None :
        fname = secure_filename(f.filename)
        fname=os.path.splitext(fname)
        #Rename file: avatar_id.ext
        f.filename = "avatar_"+str(current_user.id)+fname[1]

        try:
            # Save image in upload_photos
            filename_upload=uploaded_photos.save(f)

            # Remove image, if filename is diferent and filename save Database
            if filename_upload !=  current_user.avatar_photo and current_user.avatar_photo !=" ":
                remove_avatar(current_user)

            current_user.avatar_photo = filename_upload
            db.session.commit()

        # Image is not integrated
        except UploadNotAllowed:
            flash("The upload not image")

    # Image is not integrated
    else:
        flash("The upload not image")

# Remove avatar - function
def remove_avatar(user):
    # Selection image avatar
    folder=os.getenv('UPLOADED_PHOTOS_DEST')
    filename=user.avatar_photo
    photo_path = folder+"/"+filename

    # Remove file if it matches some parameters
    if photo_path != folder and photo_path != folder+"/" and photo_path != folder+"/ "  :
        os.remove(photo_path)

# Root - route
@admin.route('/')
@login_required
@confirm_email_required
def home_page():
    return redirect(url_for('admin.members_page') )

# About - route
@admin.route('/about')
@login_required
@confirm_email_required
def about_page():
    return render_template('about_admin_page.html', blueprint_title="Admin", title="About")

# Members - route
@admin.route('/members')
@login_required
@confirm_email_required
def members_page():
    return render_template('members/members_page.html', users=db.session.query(User).all(),
        blueprint_title="Admin", title="Members" , current_user_is_admin=current_user_is_admin())

# Members_invite
@admin.route('/members/invite', methods=['GET', 'POST'])
@login_required
@confirm_email_required
@roles_required('admin')
def members_invite():
    return invite()

# Users_profile - route
@admin.route('/members/profile/<username>')
@login_required
@confirm_email_required
def profile_page(username):
    return render_template('members/profile_page.html',
        user=db.session.query(User).filter(User.username == username).first(),
        blueprint_title="Admin", title="Members", subtitle="Profile",
        current_user_is_admin=current_user_is_admin() )

# CurrentUser_profile_edit - route
@admin.route('/members/myprofile/edit', methods=['GET', 'POST'])
@login_required
@confirm_email_required
def edit_myprofile():
    # Initialize form
    form_user = UserForm()
    form_avatar_upload = AvatarUploadForm()

    # Process valid POST- form_user
    if request.method == 'POST' and form_user.validate():
        # Copy form fields to user_profile fields
        form_user.populate_obj(current_user)

        # Save user_profile
        db.session.commit()

        # Redirect to home page
        return redirect(url_for('admin.edit_myprofile'))

    # Process valid POST - form_avatar_upload
    if  request.method == 'POST' and form_avatar_upload.validate():
        save_avatar()
        return redirect(url_for('admin.edit_myprofile'))
    elif request.method == 'POST':
        flash(('File isn\'t image'), 'success')
        return redirect(url_for('admin.edit_myprofile'))

    # Process GET or invalid POST
    return render_template('members/edit_myprofile.html',
        form_user=form_user, form_avatar_upload=form_avatar_upload,
         blueprint_title="Admin", title="Members", subtitle="Edit profile")

# CurrentUser_admin_role_profile_edit - route
@admin.route('/members/myprofile/edit/admin', methods=['GET', 'POST'])
@login_required
@confirm_email_required
@roles_required('admin')
def edit_myprofile_roles():
    # Initialize form
    form_user = UserForm()
    form_role = RoleForm()
    form_avatar_upload = AvatarUploadForm()

    # Process valid POST - form_user
    if request.method == 'POST' and form_user.validate():
        # Copy form fields to user_profile fields
        form_user.populate_obj(current_user)

        # Save user_profile
        db.session.commit()

        # Redirect to home page
        return redirect(url_for('admin.edit_myprofile_roles'))

    # Process valid POST - form_avatar_upload
    if  form_avatar_upload.validate_on_submit():
        save_avatar()
        return redirect(url_for('admin.edit_myprofile_roles'))
    elif request.method == 'POST':
        flash(('File isn\'t image'), 'success')
        return redirect(url_for('admin.edit_myprofile_roles'))

    return render_template('members/edit_myprofile_roles.html', form_user=form_user,
        form_role=form_role, form_avatar_upload=form_avatar_upload,
        roles=db.session.query(Role).all(),  blueprint_title="Admin", title="Members",
        subtitle="Profile edit")

# Edit_profile_roles - route
@admin.route('/members/profile/roles/edit/<username>' ,methods=['GET','POST'])
@login_required
@confirm_email_required
@roles_required('admin')
def  edit_profile_roles(username):
    user=db.session.query(User).filter(User.username == username).first()

    # Initialize form
    form_user = UserForm()
    form_role = RoleForm()

    return render_template('members/edit_profile_roles.html', user=user, form_user=form_user,
        form_role=form_role,roles=db.session.query(Role).all(),  blueprint_title="Admin", title="Members",
        subtitle="Profile edit" )

#Roles - route
@admin.route('/roles')
@login_required
@confirm_email_required
@roles_required('admin')
def roles_page():
    form_role = RoleForm()

    return render_template('roles/roles_page.html', form_role=form_role, roles=db.session.query(Role).all(),
      blueprint_title="Admin", title="Roles" )

#Add_role - route
@admin.route('/roles/add' ,methods=['GET','POST'])
@login_required
@confirm_email_required
@roles_required('admin')
def add_role():
    # Initialize form
    form_role = RoleForm()

    # Process valid POST
    if request.method == 'POST' and form_role.validate():

        #Add role, if role not exist
        if not Role.query.filter(Role.name==form_role.name.data).first():
            role = Role(name=form_role.name.data)
            db.session.add(role)
            db.session.commit()
        else:
            flash(('Role '+form_role.name.data+' exist.'), 'success')

    return "None"

#Add_role to user - route
@admin.route('/members/roles/add/<username>' ,methods=['GET','POST'])
@login_required
@confirm_email_required
@roles_required('admin')
def add_role_user(username) :
    user=db.session.query(User).filter(User.username == username).first()

    #User is current_user
    user_is_current_user=False
    if user == current_user:
        user_is_current_user=True

    form_role = RoleForm()

    if request.method == 'POST' and form_role.validate() :
        #Remove deselect roles
        remove_roles= [ ]

        #User Roles
        role_admin=False
        for r_user in user.roles :
            role_status=False

            #Role admin user
            if r_user.name == "admin" :
                role_admin=True

            #Roles checks
            for r_name in request.form.getlist("name") :
                #Compare with roles user, true If the role remains checked
                if r_user.name == r_name :
                    role_status=True
            #Add array remove_roles, If the role does not remains checked
            if not role_status :
                remove_roles.append(r_user.name)

        #Removes roles that are not checked now
        for r_role in remove_roles :
            role=db.session.query(Role).filter(Role.name==r_role).first()
            user.roles.remove(role)
            db.session.commit()

        #Add roles checked
        for r_name in request.form.getlist("name") :
            role=db.session.query(Role).filter(Role.name==r_name).first()

            #If it does not belong to the user it adds it
            if not db.session.query(User).join(User.roles).filter(User.username==user.username, Role.name==role.name).first() :
                user.roles.append(role)
                db.session.commit()

    if user_is_current_user and role_admin :
        return redirect(url_for('admin.edit_myprofile_roles', username=username))
    else:
        return redirect(url_for('admin.edit_profile_roles', username=username))

#Remove_role - route
@admin.route('/roles/remove', methods=['POST'])
@login_required
@confirm_email_required
@roles_required('admin')
def remove_role():

    if request.method == 'POST' :
        role_remove=db.session.query(Role).filter(Role.name==request.form["role_remove"]).first()

        db.session.delete(role_remove)
        db.session.commit()

    return "None"

#Remove_user - route
@admin.route('/user/remove', methods=['POST'])
@login_required
@confirm_email_required
@roles_required('admin')
def remove_user():
    if request.method == 'POST' :
        user_remove=db.session.query(User).filter(User.username==request.form["user_remove"]).first()

        db.session.delete(user_remove)
        db.session.commit()

        remove_avatar(user_remove)

    return "None"

#Load_avatar -route
@admin.route('/members/loaded/avatar/<username>')
@login_required
@confirm_email_required
def loaded_avatar(username):
    #Selection image avatar database
    user=db.session.query(User).filter(User.username==username).first()
    filename = user.avatar_photo

    folder=os.getenv('UPLOADED_PHOTOS_DEST');

    #Load_path
    photo_path="../"+folder+"/"+filename

    #Look image
    return send_file(photo_path, mimetype='image/png'
    )
<|endoftext|>


<commit_before># Lindley Graham 4/10/2013
"""
This module contains functions to pull data from ADCIRC output files and the
:class:`runSet` which controls the running of ADCIRC simulations within a set
of processors allocated by the submission script
"""
import numpy as np
import glob, os, subprocess, shutil
import polysim.pyADCIRC.fort13_management as f13
import polysim.pyADCIRC.fort14_management as f14
import polysim.run_framework.random_wall as rmw
import polysim.pyGriddata.table_to_mesh_map as tmm
import polysim.pyADCIRC.plotADCIRC as plot
import polysim.pyADCIRC.output as output
import scipy.io as sio
from scipy.interpolate import griddata
import polysim.run_framework.random_manningsn as rmn

def loadmat(save_file, base_dir, grid_dir, save_dir, basis_dir):
    """
    Loads data from ``save_file`` into a
    :class:`~polysim.run_framework.random_manningsn.runSet` object. Reconstructs
    :class:`~polysim.run_framework.random_manningsn.domain`. Fixes dry data if
    it was recorded.

    :param string save_file: local file name
    :param string grid_dir: directory containing ``fort.14``, ``fort.15``, and
        ``fort.22``
    :param string save_dir: directory where ``RF_directory_*`` are
        saved, and where fort.13 is located
    :param string basis_dir: directory where ``landuse_*`` folders are located
    :param string base_dir: directory that contains ADCIRC executables, and
        machine specific ``in.prep#`` files
    :rtype: tuple of :class:`~polysim.run_framework.random_wall.runSet`,
        :class:`~polysim.run_framework.random_manningsn.domain` objects, and
        two :class:`numpy.array`s
    :returns: (main_run, domain, mann_pts, wall_pts)

    """
    main_run, domain, mann_pts = rmn.loadmat(save_file, base_dir, grid_dir,
            save_dir, basis_dir)

       # load the data from at *.mat file
    mdat = sio.loadmat(save_dir+'/'+save_file)
    if mdat.has_key('wall_pts'):
        wall_pts = mdat['wall_pts']
    else:
        wall_pts = None
    Q = mdat['Q']
    points = mdat['points']

    return (main_run, domain, mann_pts, wall_pts, points, Q)

class runSet(rmw.runSet):
    """
    This class controls the running of :program:`ADCIRC` within the processors
    allocated by the submission script

    grid_dir
        directory containing ``fort.14``, ``fort.15``, and ``fort.22``
    save_dir
        directory where ``RF_directory_*`` are saved, and where fort.13 is
        located
    basis_dir
        directory where ``landuse_*`` folders are located
    base_dir
        directory that contains ADCIRC executables, and machine
        specific ``in.prep#`` files
    num_of_parallel_runs
        size of batch of jobs to be submitted to queue
    script_name
    nts_data
        non timeseries data
    ts_data
        timeseries data
    time_obs
        observation times for timeseries data

    """
    def __init__(self, grid_dir, save_dir, basis_dir,
            num_of_parallel_runs = 10, base_dir = None, script_name = None):
        """
        Initialization
        """
        super(runSet, self).__init__(grid_dir, save_dir, basis_dir,
            num_of_parallel_runs, base_dir, script_name)

    def update_mdict(self, mdict):
        """
        Set up references for ``mdict``

        :param dict() mdict: dictionary of run data

        """
        for k,v in self.nts_data.iteritems():
            mdict[k] = v
        mdict['Q'] = self.Q

    def run_nobatch_q(self, data, wall_points, mann_points, save_file,
            num_procs = 12, procs_pnode = 12, stations = None, screenout = True,
            num_writers = None, TpN = 12):
        """
        Runs :program:`ADCIRC` for all of the configurations specified by
        ``wall_points`` and ``mann_points`` and returns a dictonary of arrays
        containing data from output files. Runs batches of :program:`PADCIRC`
        as a single for loop and preps both the ``fort.13`` and fort.14`` in
        the same step.

        Stores only the QoI at the stations defined in `stations``. In this
        case the QoI is the ``maxele63`` at the designated station.

        Reads in a default Manning's *n* value from self.save_dir and stores
        it in data.manningsn_default
        :param data: :class:`~polysim.run_framework.domain`
        :type wall_points: :class:`np.array` of size (5, ``num_of_walls``)
        :param wall_points: containts the box_limits, and wall_height for each
            wall [ximin, xmax, ymin, ymax, wall_height]
        :type mann_points: :class:`np.array` of size (``num_of_basis_vec``,
            ``num_of_random_fields``), ``num_of_random_fields`` MUST be the
            same as ``num_of_walls``. The ith wall will be associated with
            the ith field specifed by mann_points
        :param mann_points: containts the weights to be used for each run
        :type save_file: string
        :param save_file: name of file to save mdict to
        :type num_procs: int or 12
        :param num_procs: number of processors per :program:`ADCIRC`
            simulation, 12 on lonestar, and 16 on stamped
        :param int procs_pnode: number of processors per node
        :param list() stations: list of stations to gather QoI from. If
            ``None`` uses the stations defined in ``data``
        :param boolean screenout: flag (True --  write ``ADCIRC`` output to
            screen, False -- write ``ADCIRC`` output to temp file
        :param int num_writers: number of MPI processes to dedicate soley to
            the task of writing ascii files. This MUST be < num_procs
        :param int TpN: number of tasks (cores to use) per node (wayness)
        :rtype: (:class:`np.array`, :class:`np.ndarray`, :class:`np.ndarray`)
        :returns: (``time_obs``, ``ts_data``, ``nts_data``)

        .. note:: Currently supports ADCIRC output files ``fort.6*``,
                  ``*.63``, ``fort.7*``, but NOT Hot Start Output
                  (``fort.67``, ``fort.68``)

        """
        # setup and save to shelf
        # set up saving
        if glob.glob(self.save_dir+'/'+save_file):
            os.remove(self.save_dir+'/'+save_file)

        # Save matricies to *.mat file for use by MATLAB or Python
        mdict = dict()
        mdict['mann_pts'] = mann_points
        mdict['wall_pts'] = wall_points

        self.save(mdict, save_file)

        #bv_array = tmm.get_basis_vec_array(self.basis_dir)
        bv_dict = tmm.get_basis_vectors(self.basis_dir)

        # Pre-allocate arrays for various data files
        num_points = mann_points.shape[1]
        num_walls = wall_points.shape[1]
        if num_points != num_points:
            print "Error: num_walls != num_points"
            quit()

        # store the wall points with the mann_points as points
        mdict['points'] = np.vstack((wall_points, mann_points))

        # Pre-allocate arrays for non-timeseries data
        nts_data = {}
        self.nts_data = nts_data
        nts_data['maxele63'] =  np.empty((data.node_num, self.num_of_parallel_runs))

        # Pre-allocate arrays for QoI data
        if stations == None:
            stations = data.stations['fort61']
        xi = np.array([[s.x, s.y] for s in stations])
        points = np.column_stack((data.array_x(), data.array_y()))
        Q = np.empty((num_points, xi.shape[0]))
        self.Q = Q
        mdict['Q'] = Q

        # Update and save
        self.update_mdict(mdict)
        self.save(mdict, save_file)

        default = data.read_default(path = self.save_dir)

        for k in xrange(0, num_points, self.num_of_parallel_runs):
            if k+self.num_of_parallel_runs >= num_points-1:
                stop = num_points
                step = stop-k
            else:
                stop = k+self.num_of_parallel_runs
                step = self.num_of_parallel_runs
            run_script = self.write_run_script(num_procs, step,
                    procs_pnode, TpN, screenout, num_writers)
            self.write_prep_script(5, step)
            # set walls
            wall_dim = wall_points[..., k]
            data.read_spatial_grid()
            data.add_wall(wall_dim[:4], wall_dim[-1])
            # update wall and prep all
            for rf_dir in self.rf_dirs:
                os.remove(rf_dir+'/fort.14')
                shutil.copy(self.grid_dir+'/fort.14', rf_dir)
                f14.update(data, path = rf_dir)
            #PARALLEL: update file containing the list of rf_dirs
            self.update_dir_file(self.num_of_parallel_runs)
            devnull = open(os.devnull, 'w')
            p = subprocess.Popen(['./prep_2.sh'], stdout = devnull, cwd = self.save_dir)
            p.communicate()
            devnull.close()
            for i in xrange(0, step):
                # generate the Manning's n field
                r_field = tmm.combine_basis_vectors(mann_points[..., i+k], bv_dict,
                          default, data.node_num)
                # create the fort.13 for r_field
                f13.update_mann(r_field, self.rf_dirs[i])
            # do a batch run of python
            #PARALLEL: update file containing the list of rf_dirs
            self.update_dir_file(self.num_of_parallel_runs)
            devnull = open(os.devnull, 'w')
            p = subprocess.Popen(['./prep_5.sh'], stdout = devnull, cwd = self.save_dir)
            p.communicate()
            devnull.close()
            devnull = open(os.devnull, 'w')
            p = subprocess.Popen(['./'+run_script], stdout = devnull,
                    cwd = self.base_dir)
            p.communicate()
            devnull.close()
            # get data
            for i, kk in enumerate(range(k, stop)):
                output.get_data_nts(i, self.rf_dirs[i], data, self.nts_data,
                        ["maxele.63"])
            # Update and save
            self.update_mdict(mdict)
            self.save(mdict, save_file)
            if (k+1)%(self.num_of_parallel_runs/4) == 0:
                msg = str(k)+" of "+str(self.num_of_parallel_runs)
                print msg+" runs have been completed."

        # save data
        # fix dry nodes and interpolate to obtain QoI
        self.fix_dry_nodes_nts(data)
        for i in self.num_of_parallel_runs:
            values = self.nts_data["maxele63"][:,i]
            Q[i,:] = griddata(points, values, xi)

        self.update_mdict(mdict)
        self.save(mdict, save_file)

        return Q

<commit_msg>debugging<commit_after># Lindley Graham 4/10/2013
"""
This module contains functions to pull data from ADCIRC output files and the
:class:`runSet` which controls the running of ADCIRC simulations within a set
of processors allocated by the submission script
"""
import numpy as np
import glob, os, subprocess, shutil
import polysim.pyADCIRC.fort13_management as f13
import polysim.pyADCIRC.fort14_management as f14
import polysim.run_framework.random_wall as rmw
import polysim.pyGriddata.table_to_mesh_map as tmm
import polysim.pyADCIRC.plotADCIRC as plot
import polysim.pyADCIRC.output as output
import scipy.io as sio
from scipy.interpolate import griddata
import polysim.run_framework.random_manningsn as rmn

def loadmat(save_file, base_dir, grid_dir, save_dir, basis_dir):
    """
    Loads data from ``save_file`` into a
    :class:`~polysim.run_framework.random_manningsn.runSet` object. Reconstructs
    :class:`~polysim.run_framework.random_manningsn.domain`. Fixes dry data if
    it was recorded.

    :param string save_file: local file name
    :param string grid_dir: directory containing ``fort.14``, ``fort.15``, and
        ``fort.22``
    :param string save_dir: directory where ``RF_directory_*`` are
        saved, and where fort.13 is located
    :param string basis_dir: directory where ``landuse_*`` folders are located
    :param string base_dir: directory that contains ADCIRC executables, and
        machine specific ``in.prep#`` files
    :rtype: tuple of :class:`~polysim.run_framework.random_wall.runSet`,
        :class:`~polysim.run_framework.random_manningsn.domain` objects, and
        two :class:`numpy.array`s
    :returns: (main_run, domain, mann_pts, wall_pts)

    """
    main_run, domain, mann_pts = rmn.loadmat(save_file, base_dir, grid_dir,
            save_dir, basis_dir)

       # load the data from at *.mat file
    mdat = sio.loadmat(save_dir+'/'+save_file)
    if mdat.has_key('wall_pts'):
        wall_pts = mdat['wall_pts']
    else:
        wall_pts = None
    Q = mdat['Q']
    points = mdat['points']

    return (main_run, domain, mann_pts, wall_pts, points, Q)

class runSet(rmw.runSet):
    """
    This class controls the running of :program:`ADCIRC` within the processors
    allocated by the submission script

    grid_dir
        directory containing ``fort.14``, ``fort.15``, and ``fort.22``
    save_dir
        directory where ``RF_directory_*`` are saved, and where fort.13 is
        located
    basis_dir
        directory where ``landuse_*`` folders are located
    base_dir
        directory that contains ADCIRC executables, and machine
        specific ``in.prep#`` files
    num_of_parallel_runs
        size of batch of jobs to be submitted to queue
    script_name
    nts_data
        non timeseries data
    ts_data
        timeseries data
    time_obs
        observation times for timeseries data

    """
    def __init__(self, grid_dir, save_dir, basis_dir,
            num_of_parallel_runs = 10, base_dir = None, script_name = None):
        """
        Initialization
        """
        super(runSet, self).__init__(grid_dir, save_dir, basis_dir,
            num_of_parallel_runs, base_dir, script_name)

    def update_mdict(self, mdict):
        """
        Set up references for ``mdict``

        :param dict() mdict: dictionary of run data

        """
        for k,v in self.nts_data.iteritems():
            mdict[k] = v
        mdict['Q'] = self.Q

    def run_nobatch_q(self, data, wall_points, mann_points, save_file,
            num_procs = 12, procs_pnode = 12, stations = None, screenout = True,
            num_writers = None, TpN = 12):
        """
        Runs :program:`ADCIRC` for all of the configurations specified by
        ``wall_points`` and ``mann_points`` and returns a dictonary of arrays
        containing data from output files. Runs batches of :program:`PADCIRC`
        as a single for loop and preps both the ``fort.13`` and fort.14`` in
        the same step.

        Stores only the QoI at the stations defined in `stations``. In this
        case the QoI is the ``maxele63`` at the designated station.

        Reads in a default Manning's *n* value from self.save_dir and stores
        it in data.manningsn_default
        :param data: :class:`~polysim.run_framework.domain`
        :type wall_points: :class:`np.array` of size (5, ``num_of_walls``)
        :param wall_points: containts the box_limits, and wall_height for each
            wall [ximin, xmax, ymin, ymax, wall_height]
        :type mann_points: :class:`np.array` of size (``num_of_basis_vec``,
            ``num_of_random_fields``), ``num_of_random_fields`` MUST be the
            same as ``num_of_walls``. The ith wall will be associated with
            the ith field specifed by mann_points
        :param mann_points: containts the weights to be used for each run
        :type save_file: string
        :param save_file: name of file to save mdict to
        :type num_procs: int or 12
        :param num_procs: number of processors per :program:`ADCIRC`
            simulation, 12 on lonestar, and 16 on stamped
        :param int procs_pnode: number of processors per node
        :param list() stations: list of stations to gather QoI from. If
            ``None`` uses the stations defined in ``data``
        :param boolean screenout: flag (True --  write ``ADCIRC`` output to
            screen, False -- write ``ADCIRC`` output to temp file
        :param int num_writers: number of MPI processes to dedicate soley to
            the task of writing ascii files. This MUST be < num_procs
        :param int TpN: number of tasks (cores to use) per node (wayness)
        :rtype: (:class:`np.array`, :class:`np.ndarray`, :class:`np.ndarray`)
        :returns: (``time_obs``, ``ts_data``, ``nts_data``)

        .. note:: Currently supports ADCIRC output files ``fort.6*``,
                  ``*.63``, ``fort.7*``, but NOT Hot Start Output
                  (``fort.67``, ``fort.68``)

        """
        # setup and save to shelf
        # set up saving
        if glob.glob(self.save_dir+'/'+save_file):
            os.remove(self.save_dir+'/'+save_file)

        # Save matricies to *.mat file for use by MATLAB or Python
        mdict = dict()
        mdict['mann_pts'] = mann_points
        mdict['wall_pts'] = wall_points

        self.save(mdict, save_file)

        #bv_array = tmm.get_basis_vec_array(self.basis_dir)
        bv_dict = tmm.get_basis_vectors(self.basis_dir)

        # Pre-allocate arrays for various data files
        num_points = mann_points.shape[1]
        num_walls = wall_points.shape[1]
        if num_points != num_points:
            print "Error: num_walls != num_points"
            quit()

        # store the wall points with the mann_points as points
        mdict['points'] = np.vstack((wall_points, mann_points))

        # Pre-allocate arrays for non-timeseries data
        nts_data = {}
        self.nts_data = nts_data
        nts_data['maxele63'] =  np.empty((data.node_num, self.num_of_parallel_runs))

        # Pre-allocate arrays for QoI data
        if stations == None:
            stations = data.stations['fort61']
        xi = np.array([[s.x, s.y] for s in stations])
        points = np.column_stack((data.array_x(), data.array_y()))
        Q = np.empty((num_points, xi.shape[0]))
        self.Q = Q
        mdict['Q'] = Q

        # Update and save
        self.update_mdict(mdict)
        self.save(mdict, save_file)

        default = data.read_default(path = self.save_dir)

        for k in xrange(0, num_points, self.num_of_parallel_runs):
            if k+self.num_of_parallel_runs >= num_points-1:
                stop = num_points
                step = stop-k
            else:
                stop = k+self.num_of_parallel_runs
                step = self.num_of_parallel_runs
            run_script = self.write_run_script(num_procs, step,
                    procs_pnode, TpN, screenout, num_writers)
            self.write_prep_script(5, step)
            # set walls
            wall_dim = wall_points[..., k]
            data.read_spatial_grid()
            data.add_wall(wall_dim[:4], wall_dim[-1])
            # update wall and prep all
            for rf_dir in self.rf_dirs:
                os.remove(rf_dir+'/fort.14')
                shutil.copy(self.grid_dir+'/fort.14', rf_dir)
                f14.update(data, path = rf_dir)
            #PARALLEL: update file containing the list of rf_dirs
            self.update_dir_file(self.num_of_parallel_runs)
            devnull = open(os.devnull, 'w')
            p = subprocess.Popen(['./prep_2.sh'], stdout = devnull, cwd = self.save_dir)
            p.communicate()
            devnull.close()
            for i in xrange(0, step):
                # generate the Manning's n field
                r_field = tmm.combine_basis_vectors(mann_points[..., i+k], bv_dict,
                          default, data.node_num)
                # create the fort.13 for r_field
                f13.update_mann(r_field, self.rf_dirs[i])
            # do a batch run of python
            #PARALLEL: update file containing the list of rf_dirs
            self.update_dir_file(self.num_of_parallel_runs)
            devnull = open(os.devnull, 'w')
            p = subprocess.Popen(['./prep_5.sh'], stdout = devnull, cwd = self.save_dir)
            p.communicate()
            devnull.close()
            devnull = open(os.devnull, 'w')
            p = subprocess.Popen(['./'+run_script], stdout = devnull,
                    cwd = self.base_dir)
            p.communicate()
            devnull.close()
            # get data
            for i, kk in enumerate(range(k, stop)):
                output.get_data_nts(i, self.rf_dirs[i], data, self.nts_data,
                        ["maxele.63"])
            # Update and save
            self.update_mdict(mdict)
            self.save(mdict, save_file)
            if (k+1)%(self.num_of_parallel_runs/4) == 0:
                msg = str(k)+" of "+str(self.num_of_parallel_runs)
                print msg+" runs have been completed."

        # save data
        # fix dry nodes and interpolate to obtain QoI
        self.fix_dry_nodes_nts(data)
        for i in xrange(self.num_of_parallel_runs):
            values = self.nts_data["maxele63"][:,i]
            Q[i,:] = griddata(points, values, xi)

        self.update_mdict(mdict)
        self.save(mdict, save_file)

        return Q

<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
	app
	~~~~~~~~~~~~~~

	Provides the flask application
"""

from __future__ import print_function

import re
import config

from inspect import isclass, getmembers
from functools import partial, update_wrapper
from importlib import import_module
from itertools import imap, repeat
from os import path as p, listdir
from sqlalchemy.exc import IntegrityError, OperationalError
from savalidation import ValidationError
from flask import Flask, render_template, g
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.bootstrap import Bootstrap
from flask.ext.restless import APIManager
from flask.ext.markdown import Markdown

API_EXCEPTIONS = [
	ValidationError, ValueError, AttributeError, TypeError, IntegrityError,
	OperationalError]

db = SQLAlchemy()
__DIR__ = p.dirname(__file__)

def _get_modules(dir):
	dirs = listdir(dir)
	modules = [
		d for d in dirs if p.isfile(p.join(dir, d, '__init__.py'))
		and d != 'tests']

	return modules

def _get_app_classes(module):
	classes = getmembers(module, isclass)
	app_classes = filter(lambda x: str(x[1]).startswith("<class 'app"), classes)
	return ['%s' % x[0] for x in app_classes]

def create_app(config_mode=None, config_file=None):
	# Create webapp instance
	app = Flask(__name__)
	db.init_app(app)
	Bootstrap(app)
	Markdown(app)

	if config_mode:
		app.config.from_object(getattr(config, config_mode))
	elif config_file:
		app.config.from_pyfile(config_file)
	else:
		app.config.from_envvar('APP_SETTINGS', silent=True)

	[app.register_blueprint(bp) for bp in blueprints]

	# set g variables
	@app.before_request
	def before_request():
		g.site = app.config['SITE']
		g.topnav = app.config['TOPNAV']
		g.hero = app.config['HERO']
		g.sub_units = app.config['SUB_UNITS']

	@app.errorhandler(404)
# 	@app.errorhandler(TypeError)
	def not_found(error):
		heading = 'Page not found.'
		subheading = "Sorry, your page isn't available!"
		kwargs = {
			'id': 404, 'title': '404', 'heading': heading,
			'subheading': subheading}

		return render_template('page.html', **kwargs), 404

	@app.context_processor
	def utility_processor():
		def currency(x):
			try:
				return '$%.2f' % x
			except TypeError:
				return x
		return dict(currency=currency)

# 	@app.template_filter()
# 	def currency(x):
# 		try:
# 			return '$%.2f' % x
# 		except TypeError:
# 			return x

# 	app.jinja_env.filters['currency'] = currency

	@app.route('/')
	def home():
		return render_template('home.html')

	# create markdown views
	mkd_pages = app.config['MKD_PAGES']
	mkd_folder = app.config['MKD_FOLDER']

	def template(kwargs):
		return render_template('markdown.html', **kwargs)

	for page in mkd_pages:
		path = p.join(__DIR__, mkd_folder, page['file'])
		text = open(path).read()
		pattern = '---'

		matches = [match for match in re.finditer(pattern, text)]

		if matches:
			cfg_start = matches[0].end() + 1
			cfg_end = matches[1].start() - 1
			parse = text[cfg_start:cfg_end].split('\n')
			cfg = dict([tuple(row.split(': ')) for row in parse])
			md = text[matches[1].end() + 1:]
		else:
			cfg = {}
			md = text

		kwargs = {'md': md, 'id': page['id'], 'cfg': cfg}
		endpoint = page['id']
		func = page['id']
		exec '%s = partial(template, kwargs)' % func in globals(), locals()
		update_wrapper(eval(func), template)
		eval(func).__name__ = func
		app.add_url_rule('/%s/' % endpoint, view_func=eval(func))

	# Create the Flask-Restless API manager.
	mgr = APIManager(app, flask_sqlalchemy_db=db)

	kwargs = {
		'methods': app.config['API_METHODS'],
		'validation_exceptions': API_EXCEPTIONS,
		'allow_functions': app.config['API_ALLOW_FUNCTIONS'],
		'allow_patch_many': app.config['API_ALLOW_PATCH_MANY']}

	# provides a nested list of class names grouped by model in the form [[],[]]
	# [[], ['Event', 'Type']]
	nested_classes = map(_get_app_classes, models)

	# provides a list of tuples (module, [list of class names])
	# in the form [(<module>,[]),(<module>,[])]
	# [(<module 'app.hermes.models' from '/path/to/models.pyc'>,
	# 	['Event', 'Type'])]
	sets = zip(models, nested_classes)

	# provides a nested iterator of classes in the expanded form of <class>
	# <class 'app.hermes.models.Event'>
	nested_tables = [imap(getattr, repeat(x[0]), x[1]) for x in sets]

	# Create API endpoints (available at /api/<tablename>)
	[[mgr.create_api(x, **kwargs) for x in tables] for tables in nested_tables]
	return app

# import app models and views
modules = _get_modules(__DIR__)
model_names = ['app.%s.models' % x for x in modules]
view_names = ['app.%s.views' % x for x in modules]
models = [import_module(x) for x in model_names]
views = [import_module(x) for x in view_names]
blueprints = map(getattr, views, modules)
<commit_msg>Edit comment<commit_after># -*- coding: utf-8 -*-
"""
	app
	~~~~~~~~~~~~~~

	Provides the flask application
"""

from __future__ import print_function

import re
import config

from inspect import isclass, getmembers
from functools import partial, update_wrapper
from importlib import import_module
from itertools import imap, repeat
from os import path as p, listdir
from sqlalchemy.exc import IntegrityError, OperationalError
from savalidation import ValidationError
from flask import Flask, render_template, g
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.bootstrap import Bootstrap
from flask.ext.restless import APIManager
from flask.ext.markdown import Markdown

API_EXCEPTIONS = [
	ValidationError, ValueError, AttributeError, TypeError, IntegrityError,
	OperationalError]

db = SQLAlchemy()
__DIR__ = p.dirname(__file__)

def _get_modules(dir):
	dirs = listdir(dir)
	modules = [
		d for d in dirs if p.isfile(p.join(dir, d, '__init__.py'))
		and d != 'tests']

	return modules

def _get_app_classes(module):
	classes = getmembers(module, isclass)
	app_classes = filter(lambda x: str(x[1]).startswith("<class 'app"), classes)
	return ['%s' % x[0] for x in app_classes]

def create_app(config_mode=None, config_file=None):
	# Create webapp instance
	app = Flask(__name__)
	db.init_app(app)
	Bootstrap(app)
	Markdown(app)

	if config_mode:
		app.config.from_object(getattr(config, config_mode))
	elif config_file:
		app.config.from_pyfile(config_file)
	else:
		app.config.from_envvar('APP_SETTINGS', silent=True)

	[app.register_blueprint(bp) for bp in blueprints]

	# set g variables
	@app.before_request
	def before_request():
		g.site = app.config['SITE']
		g.topnav = app.config['TOPNAV']
		g.hero = app.config['HERO']
		g.sub_units = app.config['SUB_UNITS']

	@app.errorhandler(404)
# 	@app.errorhandler(TypeError)
	def not_found(error):
		heading = 'Page not found.'
		subheading = "Sorry, your page isn't available!"
		kwargs = {
			'id': 404, 'title': '404', 'heading': heading,
			'subheading': subheading}

		return render_template('page.html', **kwargs), 404

	@app.context_processor
	def utility_processor():
		def currency(x):
			try:
				return '$%.2f' % x
			except TypeError:
				return x
		return dict(currency=currency)

# 	@app.template_filter()
# 	def currency(x):
# 		try:
# 			return '$%.2f' % x
# 		except TypeError:
# 			return x

# 	app.jinja_env.filters['currency'] = currency

	@app.route('/')
	def home():
		return render_template('home.html')

	# create markdown views
	mkd_pages = app.config['MKD_PAGES']
	mkd_folder = app.config['MKD_FOLDER']

	def template(kwargs):
		return render_template('markdown.html', **kwargs)

	for page in mkd_pages:
		path = p.join(__DIR__, mkd_folder, page['file'])
		text = open(path).read()
		pattern = '---'

		matches = [match for match in re.finditer(pattern, text)]

		if matches:
			cfg_start = matches[0].end() + 1
			cfg_end = matches[1].start() - 1
			parse = text[cfg_start:cfg_end].split('\n')
			cfg = dict([tuple(row.split(': ')) for row in parse])
			md = text[matches[1].end() + 1:]
		else:
			cfg = {}
			md = text

		kwargs = {'md': md, 'id': page['id'], 'cfg': cfg}
		endpoint = page['id']
		func = page['id']
		exec '%s = partial(template, kwargs)' % func in globals(), locals()
		update_wrapper(eval(func), template)
		eval(func).__name__ = func
		app.add_url_rule('/%s/' % endpoint, view_func=eval(func))

	# Create the Flask-Restless API manager.
	mgr = APIManager(app, flask_sqlalchemy_db=db)

	kwargs = {
		'methods': app.config['API_METHODS'],
		'validation_exceptions': API_EXCEPTIONS,
		'allow_functions': app.config['API_ALLOW_FUNCTIONS'],
		'allow_patch_many': app.config['API_ALLOW_PATCH_MANY']}

	# provides a nested list of class names grouped by model in the form [[],[]]
	# [[], ['Event', 'Type']]
	nested_classes = map(_get_app_classes, models)

	# provides a list of tuples (module, [list of class names])
	# in the form [(<module>,[]),(<module>,[])]
	# [(<module 'app.hermes.models' from '/path/to/models.pyc'>,
	# 	['Event', 'Type'])]
	sets = zip(models, nested_classes)

	# provides a nested iterator of classes in the expanded form of <class>
	# <class 'app.hermes.models.Event'>
	nested_tables = [imap(getattr, repeat(x[0]), x[1]) for x in sets]

	# Create API endpoints (available at /api/<tablename>)
	[[mgr.create_api(x, **kwargs) for x in tables] for tables in nested_tables]
	return app

# dynamically import app models and views
modules = _get_modules(__DIR__)
model_names = ['app.%s.models' % x for x in modules]
view_names = ['app.%s.views' % x for x in modules]
models = [import_module(x) for x in model_names]
views = [import_module(x) for x in view_names]
blueprints = map(getattr, views, modules)
<|endoftext|>


<commit_before>import os
from flask import Flask
from werkzeug.contrib.fixers import ProxyFix

app = Flask(__name__, static_url_path = '', static_folder='../public')

app.config.update(SEND_FILE_MAX_AGE_DEFAULT=0)
# any strange string here - this is key to generate tokens
app.config.update(SECRET_KEY='sadfwerusafgr-sesfgfgcret-jdddh')
app.config.update(BASEDIR=os.path.abspath(os.path.dirname(__file__)))

app.wsgi_app = ProxyFix(app.wsgi_app)
from app import views
<commit_msg>extend token expiration from 300 secs to 6 hours<commit_after>import os
from flask import Flask
from werkzeug.contrib.fixers import ProxyFix

app = Flask(__name__, static_url_path = '', static_folder='../public')

app.config.update(SEND_FILE_MAX_AGE_DEFAULT=0)
# any strange string here - this is key to generate tokens
app.config.update(SECRET_KEY='sadfwerusafgr-sesfgfgcret-jdddh')
app.config.update(BASEDIR=os.path.abspath(os.path.dirname(__file__)))
app.config.update(JWT_EXPIRATION_DELTA=129600)

app.wsgi_app = ProxyFix(app.wsgi_app)
from app import views
<|endoftext|>