<commit_before>import datetime
import calendar
import dabo
dabo.ui.loadUI("wx")
from dabo.ui import dForm, dPanel, dSizer, dGridSizer, dButton, dEditBox, \
                    dTextBox, dControlMixin, callAfterInterval, dKeys, \
                    dLabel
from dabo.lib.dates import goMonth, goDate
import biz

__all__ = ["FrmCalendar"]

class BaseMixin(dControlMixin):
    """Base behavior for all the relevant controls."""
    def initProperties(self):
        self.BorderStyle = None

    def onGotFocus(self, evt):
        callAfterInterval(10, self.Parent.gotFocus)

    def onLostFocus(self, evt):
        callAfterInterval(10, self.Parent.lostFocus)

class PnlNavigation(dPanel):
    def afterInit(self):
        hs = self.Sizer = dSizer("h")
        but_props = {"FontBold": True, "BorderStyle": None,
                     "OnHit": self.onHit_but}
        left_but = dButton(self, Name="butLeft", Caption="<", **but_props)
        right_but = dButton(self, Name="butRight", Caption=">", **but_props)
        lbl = dLabel(self, Name="lblMonthYear", FontBold=True)
        hs.append(left_but)
        hs.appendSpacer(2)
        hs.append(lbl, alignment="middle")
        hs.appendSpacer(2)
        hs.append(right_but)

    def setCaption(self, val):
        self.lblMonthYear.Caption = val
        self.layout()

    def onHit_but(self, evt):
        pnlLayout = self.Form.pnlLayout
        interval = {"butLeft": -1, "butRight": 1}[evt.EventObject.Name]
        new_date = goMonth(datetime.date(pnlLayout.Year, pnlLayout.Month, 1),
                           interval)
        pnlLayout.Year = new_date.year
        pnlLayout.Month = new_date.month
        pnlLayout.setFocus()

class DummyTextBox(dTextBox, BaseMixin):
    """Invisible textbox simply to receive and respond to user actions."""
    def initProperties(self):
        ## Dabo doesn't yet offer an interface to set wx.TE_PROCESS_ENTER.
        import wx
        self.Size = (0, 0)
        self._addWindowStyleFlag(wx.TE_PROCESS_ENTER)

    def onKeyDown(self, evt):
        self.Parent.processDayKeyDown(evt)

class EditMixin(BaseMixin):
    """Base behavior for the edit boxes."""
    def initProperties(self):
        super(EditMixin, self).initProperties()
        self.Height = 5
        self.Width = 5
        self.DynamicBackColor = self.getBackColor

    def onLostFocus(self, evt):
        super(EditMixin, self).onLostFocus(evt)
        self.save()

    def save(self):
        """Subclasses must override if they want entered data to be saved."""
        pass

    def getBackColor(self):
        """Color depends on whether this day is in the current month."""
        try:
            return (
                "white" if self.Parent.Date.month == self.Parent.Parent.Month
                else "lightgrey")
        except StandardError:
            return "darkgrey"

class Day(dLabel):
    """The day number in the upper-left of each day panel."""
    def initProperties(self):
        self.Width = 30
        self.Height = 23
        self.Name = "day"
        self.ForeColor = "blue"

    def onMouseLeftClick(self, evt):
        self.Parent.setFocus()

    def onMouseLeftDoubleClick(self, evt):
        self.Parent.diary.setFocus()

class Static(dTextBox, EditMixin):
    """View/edit/save the diary entries that repeat on this day every year."""
    def initProperties(self):
        self.FontItalic = True
        self.Name = "static"
        super(Static, self).initProperties()

    def save(self):
        cal = self.Parent.Parent
        day = self.Parent
        bizStatic = cal.bizStatic
        monthday = "%s%s" % (day.Date.month, day.Date.day)
        if not bizStatic.locate(monthday, "monthday"):
            bizStatic.new()
            bizStatic.Record.monthday = monthday
        bizStatic.Record.diary = self.Value
        bizStatic.save()

class DiaryView(dEditBox, EditMixin):
    """The view of the day's diary (no unneeded scrollbars)."""
    def initProperties(self):
        ## dabo doesn't yet allow overriding the display of scrollbars.
        import wx
        self.Name = "diary"
        self._addWindowStyleFlag(wx.TE_NO_VSCROLL)
        super(DiaryView, self).initProperties()

    def onGotFocus(self, evt):
        """Switch to the edit control (with scrollbars)."""
        edit = self.Parent.diaryedit
        edit.Value = self.Value
        edit.Visible = True
        self.Visible = False
        self.Parent.layout()
        edit.setFocus()

    def onLostFocus(self, evt):
        ## overridden to avoid unneccesary save()
        pass

class DiaryEdit(dEditBox, EditMixin):
    """The editable view of the day's diary (with scrollbars)."""
    def initProperties(self):
        self.Name = "diaryedit"
        self.Visible = False
        super(DiaryEdit, self).initProperties()

    def save(self):
        cal = self.Parent.Parent
        day = self.Parent
        bizDaily = cal.bizDaily
        date = day.Date
        if not bizDaily.locate(date, "date"):
            bizDaily.new()
            bizDaily.Record.date = date
        bizDaily.Record.diary = self.Value
        bizDaily.save()

    def onLostFocus(self, evt):
        super(DiaryEdit, self).onLostFocus(evt)
        view = self.Parent.diary
        view.Value = self.Value
        view.Visible = True
        self.Visible = False
        self.Value = ""
        self.Parent.layout()

class PnlDay(dPanel):
    """Panel of a calendar day, including the day number and edit controls."""
    def initProperties(self):
        self.BorderStyle = "Raised"
        self.DynamicBackColor = self.getBackColor
        self._hadFocus = False

    def afterInit(self):
        self.dummy = DummyTextBox(self)
        vs = self.Sizer = dSizer("v")
        hs = dSizer("h")
        hs.append(Day(self), "expand")
        hs.append1x(Static(self))
        vs.append(hs, "expand")
        vs.append1x(DiaryView(self))
        vs.append1x(DiaryEdit(self))
        parent = self.Parent
        diary = self.diary
        self.key_actions = {
            (dKeys.key_Enter, dKeys.key_Numpad_enter): (diary.setFocus, ()),
            (ord("t"), ord("T")): (parent.setFocusToToday, ()),
            (ord("+"), ord("=")): (self.setFocusToInterval, ("days", 1)),
            (ord("-"),): (self.setFocusToInterval, ("days", -1)),
            (ord("["),): (self.setFocusToInterval, ("months", -1)),
            (ord("]"),): (self.setFocusToInterval, ("months", 1))}

    def gotFocus(self):
        day = self.day
        dummy = self.dummy
        if not self._hadFocus:
            day.FontBold = True
            day.ForeColor = "darkblue"
        self._hadFocus = True
        day.refresh()

    def lostFocus(self):
        if self.Form.ActiveControl not in self.Children:
            self._hadFocus = False
            day = self.day
            day.FontBold = False
            day.ForeColor = "blue"
            self.refresh()

    def setFocus(self):
        self.dummy.setFocus()

    def setFocusToInterval(self, mode, interval):
        """Go forward or backward by months or days."""
        assert mode in ("days", "months")
        func = {"days": goDate, "months": goMonth}[mode]
        date = self.Date
        self.Parent.setFocusToDate(func(date, interval))

    def processDayKeyDown(self, evt):
        """User is navigating the calendar; respond appropriately."""
        evtData = evt.EventData
        kc = evtData["keyCode"]
        ctrlDown = evtData["controlDown"]
        layout = self.Form.CalendarLayout
        for keys, func_args in self.key_actions.items():
            if kc in keys:
                func, args = func_args
                func(*args)
                evt.stop()
                return
        if kc not in [dKeys.key_Up, dKeys.key_Down,
                      dKeys.key_Left, dKeys.key_Right]:
            return
        evt.stop()
        if not ctrlDown:
            # move by day, wrapping around in the calendar
            x,y = self.Pos
            if kc == dKeys.key_Up and layout in ("month",):
                y -= 1
                if y < 0:
                    y = 5
            elif kc == dKeys.key_Down and layout in ("month",):
                y += 1
                if y > 5:
                    y = 0
            elif kc == dKeys.key_Left:
                x -= 1
                if x < 0:
                    x = 6
            elif kc == dKeys.key_Right:
                x += 1
                if x > 6:
                    x = 0
            new_ctrl = getattr(self.Parent, "day_%s_%s" % (x,y))
            new_ctrl.setFocus()
        else:
            year, month = self.Parent.Year, self.Parent.Month
            current_date = datetime.date(year, month, 1)
            if kc == dKeys.key_Left:
                new_date = goMonth(current_date, -1)
            elif kc == dKeys.key_Right:
                new_date = goMonth(current_date, 1)
            elif kc == dKeys.key_Up:
                new_date = goMonth(current_date, -12)
            elif kc == dKeys.key_Down:
                new_date = goMonth(current_date, 12)
            self.Parent.Year = new_date.year
            self.Parent.Month = new_date.month

    def getBackColor(self):
        try:
            return  ("white" if self.Date.month == self.Parent.Month
                     else "lightgrey")
        except StandardError:
            return "darkgrey"

    def _getPos(self):
        return self._pos

    def _setPos(self, val):
        self._pos = val
        self.Name = "day_%s_%s" % val

    def _getDate(self):
        return self._date

    def _setDate(self, val):
        self._date = val
        self.day.Caption = str(val.day)

    Pos = property(_getPos, _setPos)
    Date = property(_getDate, _setDate)

class PnlLayout(dPanel):
    """Superclass to handle common elements for views (day, month, week)."""
    _week_range = None

    def afterInit(self):
        con = self.Form.Connection
        gs = self.Sizer = dGridSizer(MaxCols=7)
        self.bizStatic = biz.BizStatic(con)
        self.bizDaily = biz.BizDaily(con)
        header = calendar.weekheader(3).split()
        for x in header:
            gs.append(dLabel(self, Caption=x), alignment="center")
        for y in range(self._week_range):
            for x in range(7):
                gs.append(PnlDay(self, Pos=(x,y)), "expand")
                gs.setColExpand(True, x)
            gs.setRowExpand(True, y+1)
        self.setFocusToToday()

    def afterDateChanged(self):
        self.setFormCaption()
        self.setDays()

    def setFormCaption(self):
        current_date = datetime.date(self.Year, self.Month, 1)
        self.Form.setCaption("%s %s" % (
                current_date.strftime(calendar.month_name.format), self.Year))

    def setDays(self):
        mv = biz.getMonthMatrix(self.Year, self.Month)
        bizStatic = self.bizStatic
        bizStatic.requery()
        bizDaily = self.bizDaily
        bizDaily.requery_for_dates(mv[0][0], mv[-1][-1])
        self.date_obj_map = {}
        for y in range(self._week_range):
            for x in range(7):
                o = getattr(self, "day_%s_%s" % (x,y))
                o.Date = mv[y][x]
                if bizStatic.locate("%s%s" % (
                        o.Date.month, o.Date.day), "monthday"):
                    o.static.Value = bizStatic.Record.diary
                else:
                    o.static.Value = ""
                if bizDaily.locate(o.Date, "date"):
                    o.diary.Value = bizDaily.Record.diary
                else:
                    o.diary.Value = ""
                self.date_obj_map[o.Date] = o
        self.update()

    def setFocusToToday(self):
        """Requerying the calendar if necessary, place cursor on today."""
        self.setFocusToDate(datetime.date.today())

    def setFocusToDate(self, date):
        """Requerying the calendar if necessary, place cursor on date."""
        try:
            self.date_obj_map[date].setFocus()
        except (KeyError, AttributeError):
            self.Year = date.year
            self.Month = date.month
            callAfterInterval(75, self.setFocusToDate, date)

    def _getMonth(self):
        return self._month

    def _setMonth(self, val):
        self._month = val
        callAfterInterval(50, self.afterDateChanged)

    def _getYear(self):
        return self._year

    def _setYear(self, val):
        self._year = val
        callAfterInterval(50, self.afterDateChanged)

    Month = property(_getMonth, _setMonth)
    Year = property(_getYear, _setYear)

class PnlMonth(PnlLayout):
    """Standard 7x6 month layout."""
    _week_range = 6

class PnlWeek(PnlLayout):
    """7x1 week layout (INCOMPLETE)."""
    _week_range = 1

class FrmCalendar(dForm):
    """The main containing form of the calendar."""
    def afterInit(self):
        self._appendCaption = ""
        dcon = self.Connection
        if dcon is None:
            # use in-memory test sqlite database
            dcon = self.Connection = dabo.db.connect(":memory:")
            con = dcon._connection
            con.executescript(open("./create_tables.sql").read())
            self._appendCaption = "Temporary Database"
        self._instantiatedLayouts = {}
        vs = self.Sizer = dSizer("v")
        vs.append(PnlNavigation(self, Name="pnlNavigation"), alignment="center")
        self.updateLayout()

    def updateLayout(self):
        """Draw the calendar on screen depending on self.Layout."""
        pnls = self._instantiatedLayouts
        PnlClass = {"month": PnlMonth, "week": PnlWeek}[self.CalendarLayout]
        vs = self.Sizer
        for pnl in pnls.values():
            pnl.Visible = False
        pnl = self.pnlLayout = pnls.setdefault(PnlClass, PnlClass(self))
        if pnl not in vs.ChildWindows:
            vs.append1x(pnl)
        self.layout()

    def setCaption(self, val):
        appendCaption = self._appendCaption
        if appendCaption:
            appendCaption = "[%s]" % appendCaption
        self.Caption = "%s %s" % (val, appendCaption)
        self.pnlNavigation.setCaption(val)

    def _getConnection(self):
        return getattr(self, "_connection", None)

    def _setConnection(self, val):
        self._connection = val

    def _getCalendarLayout(self):
        return getattr(self, "_calendar_layout", "month")

    def _setCalendarLayout(self, val):
        self._calendar_layout = val
        assert val in ("month", "week")
        dabo.ui.callAfterInterval(10, self.updateLayout())

    CalendarLayout = property(_getCalendarLayout, _setCalendarLayout, None,
            """Either "month" or "week".""")

    Connection = property(_getConnection, _setConnection, None,
            "Dabo dConnection instance.")

if __name__ == "__main__":
    # If you want Sunday to be the first weekday, you need code like
    # the following commented lines in your application prior to
    # importing pmcalendar:
    #import calendar
    #calendar.setfirstweekday(6)
    dabo.dApp(MainFormClass=FrmCalendar).start()

<commit_msg>Changed buttons to hyperlinks for x-platform feel.<commit_after>import datetime
import calendar
import dabo
dabo.ui.loadUI("wx")
from dabo.ui import dForm, dPanel, dSizer, dGridSizer, dButton, dEditBox, \
                    dTextBox, dControlMixin, callAfterInterval, dKeys, \
                    dLabel, dHyperLink
from dabo.lib.dates import goMonth, goDate
import biz

__all__ = ["FrmCalendar"]

class BaseMixin(dControlMixin):
    """Base behavior for all the relevant controls."""
    def initProperties(self):
        self.BorderStyle = None

    def onGotFocus(self, evt):
        callAfterInterval(10, self.Parent.gotFocus)

    def onLostFocus(self, evt):
        callAfterInterval(10, self.Parent.lostFocus)

class PnlNavigation(dPanel):
    def afterInit(self):
        hs = self.Sizer = dSizer("h")
        but_props = {"FontBold": True, "ShowInBrowser": False,
                     "OnHit": self.onHit_but, "VisitedUnderline": False,
                     "LinkUnderline": False, "VisitedColor": "black",
                     "HoverUnderline": False, "LinkColor": "black"}
        left_but = dHyperLink(self, Name="butLeft", Caption="<", **but_props)
        right_but = dHyperLink(self, Name="butRight", Caption=">", **but_props)
        lbl = dLabel(self, Name="lblMonthYear", FontBold=True)
        hs.append(left_but)
        hs.appendSpacer(20)
        hs.append(lbl, alignment="middle")
        hs.appendSpacer(20)
        hs.append(right_but)

    def setCaption(self, val):
        self.lblMonthYear.Caption = val
        self.layout()

    def onHit_but(self, evt):
        pnlLayout = self.Form.pnlLayout
        interval = {"butLeft": -1, "butRight": 1,}[evt.EventObject.Name]
        new_date = goMonth(datetime.date(pnlLayout.Year, pnlLayout.Month, 1),
                           interval)
        pnlLayout.Year = new_date.year
        pnlLayout.Month = new_date.month
        pnlLayout.setFocus()

class DummyTextBox(dTextBox, BaseMixin):
    """Invisible textbox simply to receive and respond to user actions."""
    def initProperties(self):
        ## Dabo doesn't yet offer an interface to set wx.TE_PROCESS_ENTER.
        import wx
        self.Size = (0, 0)
        self._addWindowStyleFlag(wx.TE_PROCESS_ENTER)

    def onKeyDown(self, evt):
        self.Parent.processDayKeyDown(evt)

class EditMixin(BaseMixin):
    """Base behavior for the edit boxes."""
    def initProperties(self):
        super(EditMixin, self).initProperties()
        self.Height = 5
        self.Width = 5
        self.DynamicBackColor = self.getBackColor

    def onLostFocus(self, evt):
        super(EditMixin, self).onLostFocus(evt)
        self.save()

    def save(self):
        """Subclasses must override if they want entered data to be saved."""
        pass

    def getBackColor(self):
        """Color depends on whether this day is in the current month."""
        try:
            return (
                "white" if self.Parent.Date.month == self.Parent.Parent.Month
                else "lightgrey")
        except StandardError:
            return "darkgrey"

class Day(dLabel):
    """The day number in the upper-left of each day panel."""
    def initProperties(self):
        self.Width = 30
        self.Height = 23
        self.Name = "day"
        self.ForeColor = "blue"

    def onMouseLeftClick(self, evt):
        self.Parent.setFocus()

    def onMouseLeftDoubleClick(self, evt):
        self.Parent.diary.setFocus()

class Static(dTextBox, EditMixin):
    """View/edit/save the diary entries that repeat on this day every year."""
    def initProperties(self):
        self.FontItalic = True
        self.Name = "static"
        super(Static, self).initProperties()

    def save(self):
        cal = self.Parent.Parent
        day = self.Parent
        bizStatic = cal.bizStatic
        monthday = "%s%s" % (day.Date.month, day.Date.day)
        if not bizStatic.locate(monthday, "monthday"):
            bizStatic.new()
            bizStatic.Record.monthday = monthday
        bizStatic.Record.diary = self.Value
        bizStatic.save()

class DiaryView(dEditBox, EditMixin):
    """The view of the day's diary (no unneeded scrollbars)."""
    def initProperties(self):
        ## dabo doesn't yet allow overriding the display of scrollbars.
        import wx
        self.Name = "diary"
        self._addWindowStyleFlag(wx.TE_NO_VSCROLL)
        super(DiaryView, self).initProperties()

    def onGotFocus(self, evt):
        """Switch to the edit control (with scrollbars)."""
        edit = self.Parent.diaryedit
        edit.Value = self.Value
        edit.Visible = True
        self.Visible = False
        self.Parent.layout()
        edit.setFocus()

    def onLostFocus(self, evt):
        ## overridden to avoid unneccesary save()
        pass

class DiaryEdit(dEditBox, EditMixin):
    """The editable view of the day's diary (with scrollbars)."""
    def initProperties(self):
        self.Name = "diaryedit"
        self.Visible = False
        super(DiaryEdit, self).initProperties()

    def save(self):
        cal = self.Parent.Parent
        day = self.Parent
        bizDaily = cal.bizDaily
        date = day.Date
        if not bizDaily.locate(date, "date"):
            bizDaily.new()
            bizDaily.Record.date = date
        bizDaily.Record.diary = self.Value
        bizDaily.save()

    def onLostFocus(self, evt):
        super(DiaryEdit, self).onLostFocus(evt)
        view = self.Parent.diary
        view.Value = self.Value
        view.Visible = True
        self.Visible = False
        self.Value = ""
        self.Parent.layout()

class PnlDay(dPanel):
    """Panel of a calendar day, including the day number and edit controls."""
    def initProperties(self):
        self.BorderStyle = "Raised"
        self.DynamicBackColor = self.getBackColor
        self._hadFocus = False

    def afterInit(self):
        self.dummy = DummyTextBox(self)
        vs = self.Sizer = dSizer("v")
        hs = dSizer("h")
        hs.append(Day(self), "expand")
        hs.append1x(Static(self))
        vs.append(hs, "expand")
        vs.append1x(DiaryView(self))
        vs.append1x(DiaryEdit(self))
        parent = self.Parent
        diary = self.diary
        self.key_actions = {
            (dKeys.key_Enter, dKeys.key_Numpad_enter): (diary.setFocus, ()),
            (ord("t"), ord("T")): (parent.setFocusToToday, ()),
            (ord("+"), ord("=")): (self.setFocusToInterval, ("days", 1)),
            (ord("-"),): (self.setFocusToInterval, ("days", -1)),
            (ord("["),): (self.setFocusToInterval, ("months", -1)),
            (ord("]"),): (self.setFocusToInterval, ("months", 1))}

    def gotFocus(self):
        day = self.day
        dummy = self.dummy
        if not self._hadFocus:
            day.FontBold = True
            day.ForeColor = "darkblue"
        self._hadFocus = True
        day.refresh()

    def lostFocus(self):
        if self.Form.ActiveControl not in self.Children:
            self._hadFocus = False
            day = self.day
            day.FontBold = False
            day.ForeColor = "blue"
            self.refresh()

    def setFocus(self):
        self.dummy.setFocus()

    def setFocusToInterval(self, mode, interval):
        """Go forward or backward by months or days."""
        assert mode in ("days", "months")
        func = {"days": goDate, "months": goMonth}[mode]
        date = self.Date
        self.Parent.setFocusToDate(func(date, interval))

    def processDayKeyDown(self, evt):
        """User is navigating the calendar; respond appropriately."""
        evtData = evt.EventData
        kc = evtData["keyCode"]
        ctrlDown = evtData["controlDown"]
        layout = self.Form.CalendarLayout
        for keys, func_args in self.key_actions.items():
            if kc in keys:
                func, args = func_args
                func(*args)
                evt.stop()
                return
        if kc not in [dKeys.key_Up, dKeys.key_Down,
                      dKeys.key_Left, dKeys.key_Right]:
            return
        evt.stop()
        if not ctrlDown:
            # move by day, wrapping around in the calendar
            x,y = self.Pos
            if kc == dKeys.key_Up and layout in ("month",):
                y -= 1
                if y < 0:
                    y = 5
            elif kc == dKeys.key_Down and layout in ("month",):
                y += 1
                if y > 5:
                    y = 0
            elif kc == dKeys.key_Left:
                x -= 1
                if x < 0:
                    x = 6
            elif kc == dKeys.key_Right:
                x += 1
                if x > 6:
                    x = 0
            new_ctrl = getattr(self.Parent, "day_%s_%s" % (x,y))
            new_ctrl.setFocus()
        else:
            year, month = self.Parent.Year, self.Parent.Month
            current_date = datetime.date(year, month, 1)
            if kc == dKeys.key_Left:
                new_date = goMonth(current_date, -1)
            elif kc == dKeys.key_Right:
                new_date = goMonth(current_date, 1)
            elif kc == dKeys.key_Up:
                new_date = goMonth(current_date, -12)
            elif kc == dKeys.key_Down:
                new_date = goMonth(current_date, 12)
            self.Parent.Year = new_date.year
            self.Parent.Month = new_date.month

    def getBackColor(self):
        try:
            return  ("white" if self.Date.month == self.Parent.Month
                     else "lightgrey")
        except StandardError:
            return "darkgrey"

    def _getPos(self):
        return self._pos

    def _setPos(self, val):
        self._pos = val
        self.Name = "day_%s_%s" % val

    def _getDate(self):
        return self._date

    def _setDate(self, val):
        self._date = val
        self.day.Caption = str(val.day)

    Pos = property(_getPos, _setPos)
    Date = property(_getDate, _setDate)

class PnlLayout(dPanel):
    """Superclass to handle common elements for views (day, month, week)."""
    _week_range = None

    def afterInit(self):
        con = self.Form.Connection
        gs = self.Sizer = dGridSizer(MaxCols=7)
        self.bizStatic = biz.BizStatic(con)
        self.bizDaily = biz.BizDaily(con)
        header = calendar.weekheader(3).split()
        for x in header:
            gs.append(dLabel(self, Caption=x), alignment="center")
        for y in range(self._week_range):
            for x in range(7):
                gs.append(PnlDay(self, Pos=(x,y)), "expand")
                gs.setColExpand(True, x)
            gs.setRowExpand(True, y+1)
        self.setFocusToToday()

    def afterDateChanged(self):
        self.setFormCaption()
        self.setDays()

    def setFormCaption(self):
        current_date = datetime.date(self.Year, self.Month, 1)
        self.Form.setCaption("%s %s" % (
                current_date.strftime(calendar.month_name.format), self.Year))

    def setDays(self):
        mv = biz.getMonthMatrix(self.Year, self.Month)
        bizStatic = self.bizStatic
        bizStatic.requery()
        bizDaily = self.bizDaily
        bizDaily.requery_for_dates(mv[0][0], mv[-1][-1])
        self.date_obj_map = {}
        for y in range(self._week_range):
            for x in range(7):
                o = getattr(self, "day_%s_%s" % (x,y))
                o.Date = mv[y][x]
                if bizStatic.locate("%s%s" % (
                        o.Date.month, o.Date.day), "monthday"):
                    o.static.Value = bizStatic.Record.diary
                else:
                    o.static.Value = ""
                if bizDaily.locate(o.Date, "date"):
                    o.diary.Value = bizDaily.Record.diary
                else:
                    o.diary.Value = ""
                self.date_obj_map[o.Date] = o
        self.update()

    def setFocusToToday(self):
        """Requerying the calendar if necessary, place cursor on today."""
        self.setFocusToDate(datetime.date.today())

    def setFocusToDate(self, date):
        """Requerying the calendar if necessary, place cursor on date."""
        try:
            self.date_obj_map[date].setFocus()
        except (KeyError, AttributeError):
            self.Year = date.year
            self.Month = date.month
            callAfterInterval(75, self.setFocusToDate, date)

    def _getMonth(self):
        return self._month

    def _setMonth(self, val):
        self._month = val
        callAfterInterval(50, self.afterDateChanged)

    def _getYear(self):
        return self._year

    def _setYear(self, val):
        self._year = val
        callAfterInterval(50, self.afterDateChanged)

    Month = property(_getMonth, _setMonth)
    Year = property(_getYear, _setYear)

class PnlMonth(PnlLayout):
    """Standard 7x6 month layout."""
    _week_range = 6

class PnlWeek(PnlLayout):
    """7x1 week layout (INCOMPLETE)."""
    _week_range = 1

class FrmCalendar(dForm):
    """The main containing form of the calendar."""
    def afterInit(self):
        self._appendCaption = ""
        dcon = self.Connection
        if dcon is None:
            # use in-memory test sqlite database
            dcon = self.Connection = dabo.db.connect(":memory:")
            con = dcon._connection
            con.executescript(open("./create_tables.sql").read())
            self._appendCaption = "Temporary Database"
        self._instantiatedLayouts = {}
        vs = self.Sizer = dSizer("v")
        vs.appendSpacer(5)
        vs.append(PnlNavigation(self, Name="pnlNavigation"), alignment="center")
        vs.appendSpacer(5)
        self.updateLayout()

    def updateLayout(self):
        """Draw the calendar on screen depending on self.Layout."""
        pnls = self._instantiatedLayouts
        PnlClass = {"month": PnlMonth, "week": PnlWeek}[self.CalendarLayout]
        vs = self.Sizer
        for pnl in pnls.values():
            pnl.Visible = False
        pnl = self.pnlLayout = pnls.setdefault(PnlClass, PnlClass(self))
        if pnl not in vs.ChildWindows:
            vs.append1x(pnl)
        self.layout()

    def setCaption(self, val):
        appendCaption = self._appendCaption
        if appendCaption:
            appendCaption = "[%s]" % appendCaption
        self.Caption = "%s %s" % (val, appendCaption)
        self.pnlNavigation.setCaption(val)

    def _getConnection(self):
        return getattr(self, "_connection", None)

    def _setConnection(self, val):
        self._connection = val

    def _getCalendarLayout(self):
        return getattr(self, "_calendar_layout", "month")

    def _setCalendarLayout(self, val):
        self._calendar_layout = val
        assert val in ("month", "week")
        dabo.ui.callAfterInterval(10, self.updateLayout())

    CalendarLayout = property(_getCalendarLayout, _setCalendarLayout, None,
            """Either "month" or "week".""")

    Connection = property(_getConnection, _setConnection, None,
            "Dabo dConnection instance.")

if __name__ == "__main__":
    # If you want Sunday to be the first weekday, you need code like
    # the following commented lines in your application prior to
    # importing pmcalendar:
    #import calendar
    #calendar.setfirstweekday(6)
    dabo.dApp(MainFormClass=FrmCalendar).start()

<|endoftext|>


<commit_before>#!/usr/bin/env python

"""
Base neuron class used by LPU.
"""

from abc import ABCMeta, abstractmethod
import os.path
import numpy as np

import pycuda.gpuarray as garray
from pycuda.compiler import SourceModule

from neurokernel.LPU.utils.simpleio import *

class BaseNeuron(object):
    __metaclass__ = ABCMeta

    def __init__(self, n_dict, neuron_state_p, debug=False, LPU_id=None):
        '''
        See initmethod for documentation of arguments
        '''
        self.__neuron_state_p = neuron_state_p
        num_neurons = len(n_dict['id'])

        num_dendrite_I = np.asarray([n_dict['num_dendrites_I'][i]
                                     for i in range(num_neurons)],
                                    dtype=np.int32).flatten()
        num_dendrite_g = np.asarray([n_dict['num_dendrites_g'][i]
                                     for i in range(num_neurons)],
                                    dtype=np.int32).flatten()

        self.__cum_num_dendrite_I = garray.to_gpu(np.concatenate((
                                np.asarray([0, ], dtype=np.int32),
                                np.cumsum(num_dendrite_I, dtype=np.int32))))
        self.__cum_num_dendrite_g = garray.to_gpu(np.concatenate((
                                np.asarray([0, ], dtype=np.int32),
                                np.cumsum(num_dendrite_g, dtype=np.int32))))
        self.__num_dendrite_I = garray.to_gpu(num_dendrite_I)
        self.__num_dendrite_g = garray.to_gpu(num_dendrite_g)
        self.__I_pre = garray.to_gpu(np.asarray(n_dict['I_pre'], dtype=np.int32))
        self.__g_pre = garray.to_gpu(np.asarray(n_dict['g_pre'], dtype=np.int32))

        self.__V_rev = garray.to_gpu(np.asarray(n_dict['V_rev'],
                                                dtype=np.double))

        self.__update_from_I = self.get_update_from_I_func(num_neurons)
        self.__update_from_g = self.get_update_from_g_func(num_neurons)
        self.__block_get_input = (32, 32, 1)
        self.__grid_get_input = ((num_neurons - 1) / 32 + 1, 1)

        self.__LPU_id = LPU_id
        self.__debug = debug
        self.__debug_setup()

    def __debug_setup(self):
        if self.__debug:
            if self.__LPU_id is None:
                self.__LPU_id = "default_LPU"

            i = 0
            while True:
                newfile = "{}_{}{}.h5".format(self.__LPU_id,
                                                 self.__class__.__name__, i)
                if not os.path.isfile(newfile):
                    self.__in_file = tables.openFile(newfile, mode="w")
                    self.__in_file.createEArray("/", "array",
                                                tables.Float64Atom(),
                                                (0, self.num_neurons))
                    break
                i+=1

    @abstractmethod
    def initneuron(cls, n_dict, neuron_state_p, dt, debug=False, LPU_id=None):
        '''
        This method is a wrapper of __init__ method but it is defined
        to enforce a specific constructor interface e.g. constructor
        of this base class does not use dt.

        Every neuron class should setup GPU data structures
        needed by it during initialization and provide their initial
        values.

        n_dict is a dictionary representing the parameters needed
        by the neuron class.
        For example, if a derived neuron class called IAF needs a
        parameter called bias, n_dict['bias'] will be vector containing
        the bias values for all the IAF neurons in a particular LPU.

        In addition if neuron uses base neuron initialization,
        n_dict will also contain:
        1. n_dict['cond_pre'] representing the conductance based synapses
           with connection to neurons represented by this class.
        2. n_dict['reverse'] containing the reverse potentials for the
           conductance based synapses.
        3. n_dict['num_dendrites_cond'] representing the number of dendrites for
           neuron in this class of the conductance type. For eg,
           n_dict['num_dendrites_cond'][0] will represent the number of
           conductance based synapses connecting to the neuron having index 0
           in this object
        4. n_dict['I_pre'] representing the indices of the non-conductance
           based synapses with connections to neurons represented by this
           object , eg:- synapses modelled by filters. This is also includes
           any external input to neurons of this class.
        5. n_dict['num_dendrites_I'] representing the number of dendrites for
           neuron in this class of the non-conductance type. E.g,
           n_dict['num_dendrites_I'][0] will represent the number of
           non conductance based synapses, connecting to the neuron
           having index 0.

        Note that you only need the above information if you plan to override the
        default update_internal_state method.

        neuron_state_p: is an integer representing the initial memory location
        on the GPU for storing the neuron states for this object.
        For graded potential neurons, the data type will be double whereas for
        spiking neurons, it will be int.

        dt: simulation time step

        debug: is a boolean and is intended to be used for debugging purposes.

        LPU_id: an identifier of LPU that will appear in logs so it should be unique
        for LPUs of a specific simulation
        '''
        cls(n_dict, neuron_state_p, debug, LPU_id)

    @abstractmethod
    def eval(self):
        '''
        This method should update the neuron states. A pointer to
        the start of the memory located will be provided at time of
        initialization.

        self.I.gpudata will be a pointer to the memory location
        where the input current to all the neurons at each step is updated
        if the child class does not override update_I() method
        '''
        pass

    @abstractmethod
    def update_internal_state(self, synapse_state_p, st=None, logger=None):
        '''
        This method should compute the internal state of each neuron
        based on the synapse state.

        BaseNeuron provides an implementation of this method.

        synapse_state_p:
        it will be an integer representing the initial memory
        location on the GPU reserved for the synapse states. The data
        type for synapse states will be double.
        In BaseNeuron implementation it may either
        contain conductances or currents.
        The information needed to compute the input state is provided in the
        dictionary n_dict at initialization.
        '''
        pass

    def update_internal_state_default(self, synapse_state_p, internal_state,
            st=None, logger=None):

        internal_state.fill(0)
        if self.__I_pre.size > 0:
            # synapse_state(I) -> internal_state(I)
            self.__update_from_I.prepared_async_call(
                self.__grid_get_input, self.__block_get_input, st,
                int(synapse_state_p), self.__cum_num_dendrite_I.gpudata,
                self.__num_dendrite_I.gpudata, self.__I_pre.gpudata,
                internal_state.gpudata)

        if self.__g_pre.size > 0:
            # synapse_state(g) -> internal_state(I)
            self.__update_from_g.prepared_async_call(
                self.__grid_get_input, self.__block_get_input, st,
                int(synapse_state_p), self.__cum_num_dendrite_g.gpudata,
                self.__num_dendrite_g.gpudata, self.__g_pre.gpudata,
                internal_state.gpudata, int(self.__neuron_state_p),
                self.__V_rev.gpudata)

        if self.__debug:
            self.__in_file.root.array.append(internal_state.get()
                                             .reshape((1, -1)))

    @abstractmethod
    def post_run(self):
        '''
        This method will be called at the end of the simulation.
        '''
        if self.__debug:
            self.__in_file.close()

    def get_update_from_g_func(self, num_neurons):
        template = """
        #define N 32
        #define NUM_NEURONS %(num_neurons)d

        __global__ void get_input(double* synapse, int* cum_num_dendrite,
                                  int* num_dendrite, int* pre, double* I_pre,
                                  double* V, double* V_rev)
        {
            int tidx = threadIdx.x;
            int tidy = threadIdx.y;
            int bid = blockIdx.x;

            int neuron;

            __shared__ int num_den[32];
            __shared__ int den_start[32];
            __shared__ double V_in[32];
            __shared__ double input[32][33];

            if(tidy == 0)
            {
                neuron = bid * N + tidx;
                if(neuron < NUM_NEURONS)
                {
                    num_den[tidx] = num_dendrite[neuron];
                    V_in[tidx] = V[neuron];
                }
            } else if(tidy == 1)
            {
                neuron = bid * N + tidx;
                if(neuron < NUM_NEURONS)
                {
                    den_start[tidx] = cum_num_dendrite[neuron];
                }
            }

            input[tidy][tidx] = 0.0;

            __syncthreads();

            neuron = bid * N + tidy ;
            if(neuron < NUM_NEURONS)
            {
               int n_den = num_den[tidy];
               int start = den_start[tidy];
               double VV = V_in[tidy];

               for(int i = tidx; i < n_den; i += N)
               {
                   input[tidy][tidx] += synapse[pre[start + i]] * (VV - V_rev[start + i]);
               }
            }

            __syncthreads();

            if(tidy < 8)
            {
                input[tidx][tidy] += input[tidx][tidy + 8];
                input[tidx][tidy] += input[tidx][tidy + 16];
                input[tidx][tidy] += input[tidx][tidy + 24];
            }

            __syncthreads();

            if(tidy < 4)
            {
                input[tidx][tidy] += input[tidx][tidy + 4];
            }

            __syncthreads();

            if(tidy < 2)
            {
                input[tidx][tidy] += input[tidx][tidy + 2];
            }

            __syncthreads();

            if(tidy == 0)
            {
                input[tidx][0] += input[tidx][1];
                neuron = bid*N+tidx;
                if(neuron < NUM_NEURONS)
                {
                    I_pre[neuron] -= input[tidx][0];
                }
            }
        }
        // can be improved
        """
        mod = SourceModule(template % {"num_neurons": num_neurons},
                           options = ["--ptxas-options=-v"])
        func = mod.get_function("get_input")
        func.prepare([np.intp, np.intp, np.intp, np.intp,
                      np.intp, np.intp, np.intp])
        return func

    def get_update_from_I_func(self, num_neurons):
        template = """
        #define N 32
        #define NUM_NEURONS %(num_neurons)d

        __global__ void get_input(double* synapse, int* cum_num_dendrite,
                                  int* num_dendrite, int* pre, double* I_pre)
        {
            // assumes block size is N, N, 1
            int tidx = threadIdx.x;
            int tidy = threadIdx.y;
            int bid = blockIdx.x;

            int neuron;

            __shared__ int num_den[N];
            __shared__ int den_start[N];
            __shared__ double input[N][N+1];

            neuron = bid * N + tidx;

            // tidy, tidx are interchangeable here
            if(tidy == 0)
            {
                if(neuron < NUM_NEURONS)
                {
                    num_den[tidx] = num_dendrite[neuron];
                    den_start[tidx] = cum_num_dendrite[neuron];
                }
            }

            input[tidx][tidy] = 0.0;

            __syncthreads();

            if(neuron < NUM_NEURONS){

               int n_den = num_den[tidx];
               int start = den_start[tidx];

               for(int i = tidy; i < n_den; i += N)
               {
                   input[tidx][tidy] += synapse[pre[start] + i];
               }
            }
            __syncthreads();

            if(tidy < 8)
            {
                input[tidx][tidy] += input[tidx][tidy + 8];
                input[tidx][tidy] += input[tidx][tidy + 16];
                input[tidx][tidy] += input[tidx][tidy + 24];
            }

            __syncthreads();

            if(tidy < 4)
            {
                input[tidx][tidy] += input[tidx][tidy + 4];
            }

            __syncthreads();

            if(tidy < 2)
            {
                input[tidx][tidy] += input[tidx][tidy + 2];
            }

            __syncthreads();

            if(tidy == 0)
            {
                input[tidx][0] += input[tidx][1];
                neuron = bid*N+tidx;
                if(neuron < NUM_NEURONS)
                {
                    I_pre[neuron] += input[tidx][0];
                }
            }

        }
        //can be improved
        """
        mod = SourceModule(template % {"num_neurons": num_neurons},
                           options = ["--ptxas-options=-v"])
        func = mod.get_function("get_input")
        func.prepare([np.intp, np.intp, np.intp, np.intp, np.intp])
        return func
<commit_msg>rewinded changes in baseneuron<commit_after>#!/usr/bin/env python

"""
Base neuron class used by LPU.
"""

from abc import ABCMeta, abstractmethod
import os.path
import numpy as np

import pycuda.gpuarray as garray
from pycuda.compiler import SourceModule

from neurokernel.LPU.utils.simpleio import *

class BaseNeuron(object):
    __metaclass__ = ABCMeta

    def __init__(self, n_dict, neuron_state_p, debug=False, LPU_id=None):
        '''
        See initmethod for documentation of arguments
        '''
        self.__neuron_state_p = neuron_state_p
        num_neurons = len(n_dict['id'])

        num_dendrite_I = np.asarray([n_dict['num_dendrites_I'][i]
                                     for i in range(num_neurons)],
                                    dtype=np.int32).flatten()
        num_dendrite_g = np.asarray([n_dict['num_dendrites_g'][i]
                                     for i in range(num_neurons)],
                                    dtype=np.int32).flatten()

        self.__cum_num_dendrite_I = garray.to_gpu(np.concatenate((
                                np.asarray([0, ], dtype=np.int32),
                                np.cumsum(num_dendrite_I, dtype=np.int32))))
        self.__cum_num_dendrite_g = garray.to_gpu(np.concatenate((
                                np.asarray([0, ], dtype=np.int32),
                                np.cumsum(num_dendrite_g, dtype=np.int32))))
        self.__num_dendrite_I = garray.to_gpu(num_dendrite_I)
        self.__num_dendrite_g = garray.to_gpu(num_dendrite_g)
        self.__I_pre = garray.to_gpu(np.asarray(n_dict['I_pre'], dtype=np.int32))
        self.__g_pre = garray.to_gpu(np.asarray(n_dict['g_pre'], dtype=np.int32))

        self.__V_rev = garray.to_gpu(np.asarray(n_dict['V_rev'],
                                                dtype=np.double))

        self.__update_from_I = self.get_update_from_I_func(num_neurons)
        self.__update_from_g = self.get_update_from_g_func(num_neurons)

        self.__LPU_id = LPU_id
        self.__debug = debug
        self.__debug_setup()

    def __debug_setup(self):
        if self.__debug:
            if self.__LPU_id is None:
                self.__LPU_id = "default_LPU"

            i = 0
            while True:
                newfile = "{}_{}{}.h5".format(self.__LPU_id,
                                                 self.__class__.__name__, i)
                if not os.path.isfile(newfile):
                    self.__in_file = tables.openFile(newfile, mode="w")
                    self.__in_file.createEArray("/", "array",
                                                tables.Float64Atom(),
                                                (0, self.num_neurons))
                    break
                i += 1

    @abstractmethod
    def initneuron(cls, n_dict, neuron_state_p, dt, debug=False, LPU_id=None):
        '''
        This method is a wrapper of __init__ method but it is defined
        to enforce a specific constructor interface e.g. constructor
        of this base class does not use dt.

        Every neuron class should setup GPU data structures
        needed by it during initialization and provide their initial
        values.

        n_dict is a dictionary representing the parameters needed
        by the neuron class.
        For example, if a derived neuron class called IAF needs a
        parameter called bias, n_dict['bias'] will be vector containing
        the bias values for all the IAF neurons in a particular LPU.

        In addition if neuron uses base neuron initialization,
        n_dict will also contain:
        1. n_dict['cond_pre'] representing the conductance based synapses
           with connection to neurons represented by this class.
        2. n_dict['reverse'] containing the reverse potentials for the
           conductance based synapses.
        3. n_dict['num_dendrites_cond'] representing the number of dendrites for
           neuron in this class of the conductance type. For eg,
           n_dict['num_dendrites_cond'][0] will represent the number of
           conductance based synapses connecting to the neuron having index 0
           in this object
        4. n_dict['I_pre'] representing the indices of the non-conductance
           based synapses with connections to neurons represented by this
           object , eg:- synapses modelled by filters. This is also includes
           any external input to neurons of this class.
        5. n_dict['num_dendrites_I'] representing the number of dendrites for
           neuron in this class of the non-conductance type. E.g,
           n_dict['num_dendrites_I'][0] will represent the number of
           non conductance based synapses, connecting to the neuron
           having index 0.

        Note that you only need the above information if you plan to override the
        default update_internal_state method.

        neuron_state_p: is an integer representing the initial memory location
        on the GPU for storing the neuron states for this object.
        For graded potential neurons, the data type will be double whereas for
        spiking neurons, it will be int.

        dt: simulation time step

        debug: is a boolean and is intended to be used for debugging purposes.

        LPU_id: an identifier of LPU that will appear in logs so it should be unique
        for LPUs of a specific simulation
        '''
        cls(n_dict, neuron_state_p, debug, LPU_id)

    @abstractmethod
    def eval(self):
        '''
        This method should update the neuron states. A pointer to
        the start of the memory located will be provided at time of
        initialization.

        self.I.gpudata will be a pointer to the memory location
        where the input current to all the neurons at each step is updated
        if the child class does not override update_I() method
        '''
        pass

    @abstractmethod
    def update_internal_state(self, synapse_state_p, st=None, logger=None):
        '''
        This method should compute the internal state of each neuron
        based on the synapse state.

        BaseNeuron provides an implementation of this method.

        synapse_state_p:
        it will be an integer representing the initial memory
        location on the GPU reserved for the synapse states. The data
        type for synapse states will be double.
        In BaseNeuron implementation it may either
        contain conductances or currents.
        The information needed to compute the input state is provided in the
        dictionary n_dict at initialization.
        '''
        pass

    def update_internal_state_default(self, synapse_state_p, internal_state,
            st=None, logger=None):

        internal_state.fill(0)
        if self.__I_pre.size > 0:
            # synapse_state(I) -> internal_state(I)
            self.__update_from_I.prepared_async_call(
                self.__grid_get_input_I, self.__block_get_input_I, st,
                int(synapse_state_p), self.__cum_num_dendrite_I.gpudata,
                self.__num_dendrite_I.gpudata, self.__I_pre.gpudata,
                internal_state.gpudata)

        if self.__g_pre.size > 0:
            # synapse_state(g) -> internal_state(I)
            self.__update_from_g.prepared_async_call(
                self.__grid_get_input_g, self.__block_get_input_g, st,
                int(synapse_state_p), self.__cum_num_dendrite_g.gpudata,
                self.__num_dendrite_g.gpudata, self.__g_pre.gpudata,
                internal_state.gpudata, int(self.__neuron_state_p),
                self.__V_rev.gpudata)

        if self.__debug:
            self.__in_file.root.array.append(internal_state.get()
                                             .reshape((1, -1)))

    @abstractmethod
    def post_run(self):
        '''
        This method will be called at the end of the simulation.
        '''
        if self.__debug:
            self.__in_file.close()

    def get_update_from_g_func(self, num_neurons):
        template = """
        #define NUM_NEURONS %(num_neurons)d

        __global__ void get_input(double* synapse, int* cum_num_dendrite,
                                  int* num_dendrite, int* pre, double* I_pre,
                                  double* V, double* V_rev)
        {
            // must use block size 32, 32, 1
            int tidx = threadIdx.x;
            int tidy = threadIdx.y;
            int bid = blockIdx.x;

            int neuron;

            __shared__ int num_den[32];
            __shared__ int den_start[32];
            __shared__ double V_in[32];
            __shared__ double input[32][33];

            if(tidy == 0)
            {
                neuron = bid * 32 + tidx;
                if(neuron < NUM_NEURONS)
                {
                    num_den[tidx] = num_dendrite[neuron];
                    V_in[tidx] = V[neuron];
                }
            } else if(tidy == 1)
            {
                neuron = bid * 32 + tidx;
                if(neuron < NUM_NEURONS)
                {
                    den_start[tidx] = cum_num_dendrite[neuron];
                }
            }

            input[tidy][tidx] = 0.0;

            __syncthreads();

            neuron = bid * 32 + tidy ;
            if(neuron < NUM_NEURONS)
            {
               int n_den = num_den[tidy];
               int start = den_start[tidy];
               double VV = V_in[tidy];

               for(int i = tidx; i < n_den; i += 32)
               {
                   input[tidy][tidx] += synapse[pre[start + i]] * (VV - V_rev[start + i]);
               }
            }

            __syncthreads();

            if(tidy < 8)
            {
                input[tidx][tidy] += input[tidx][tidy + 8];
                input[tidx][tidy] += input[tidx][tidy + 16];
                input[tidx][tidy] += input[tidx][tidy + 24];
            }

            __syncthreads();

            if(tidy < 4)
            {
                input[tidx][tidy] += input[tidx][tidy + 4];
            }

            __syncthreads();

            if(tidy < 2)
            {
                input[tidx][tidy] += input[tidx][tidy + 2];
            }

            __syncthreads();

            if(tidy == 0)
            {
                input[tidx][0] += input[tidx][1];
                neuron = bid*32+tidx;
                if(neuron < NUM_NEURONS)
                {
                    I_pre[neuron] -= input[tidx][0];
                }
            }
        }
        // can be improved
        """
        mod = SourceModule(template % {"num_neurons": num_neurons},
                           options = ["--ptxas-options=-v"])
        func = mod.get_function("get_input")
        func.prepare([np.intp, np.intp, np.intp, np.intp,
                      np.intp, np.intp, np.intp])
        self.__block_get_input_g = (32, 32, 1)
        self.__grid_get_input_g = ((num_neurons - 1) / 32 + 1, 1)
        return func

    def get_update_from_I_func(self, num_neurons):
        template = """
        #define NUM_NEURONS %(num_neurons)d

        __global__ void get_input(double* synapse, int* cum_num_dendrite,
                                  int* num_dendrite, int* pre, double* I_pre)
        {
            // must use block size 32, 32, 1
            int tidx = threadIdx.x;
            int tidy = threadIdx.y;
            int bid = blockIdx.x;

            int neuron;

            __shared__ int num_den[32];
            __shared__ int den_start[32];
            __shared__ double input[32][33];

            neuron = bid * 32 + tidx;

            if(tidy == 0)
            {
                if(neuron < NUM_NEURONS)
                {
                    num_den[tidx] = num_dendrite[neuron];
                }
            }else if(tidy == 1)
            {
                if(neuron < NUM_NEURONS)
                {
                    den_start[tidx] = cum_num_dendrite[neuron];
                }
            }

            input[tidx][tidy] = 0.0;

            __syncthreads();

            neuron = bid * 32 + tidy;

            if(neuron < NUM_NEURONS){

               int n_den = num_den[tidy];
               int start = den_start[tidy];

               for(int i = tidx; i < n_den; i += 32)
               {
                   input[tidy][tidx] += synapse[pre[start] + i];
               }
            }
            __syncthreads();

            if(tidy < 8)
            {
                input[tidx][tidy] += input[tidx][tidy + 8];
                input[tidx][tidy] += input[tidx][tidy + 16];
                input[tidx][tidy] += input[tidx][tidy + 24];
            }

            __syncthreads();

            if(tidy < 4)
            {
                input[tidx][tidy] += input[tidx][tidy + 4];
            }

            __syncthreads();

            if(tidy < 2)
            {
                input[tidx][tidy] += input[tidx][tidy + 2];
            }

            __syncthreads();

            if(tidy == 0)
            {
                input[tidx][0] += input[tidx][1];
                neuron = bid*32+tidx;
                if(neuron < NUM_NEURONS)
                {
                    I_pre[neuron] += input[tidx][0];
                }
            }

        }
        //can be improved
        """
        mod = SourceModule(template % {"num_neurons": num_neurons},
                           options = ["--ptxas-options=-v"])
        func = mod.get_function("get_input")
        func.prepare([np.intp, np.intp, np.intp, np.intp, np.intp])
        self.__block_get_input_I = (32, 32, 1)
        self.__grid_get_input_I = ((num_neurons - 1) / 32 + 1, 1)
        return func
<|endoftext|>


<commit_before>import numpy as np

class JaggedArray(object):
    def __init__(self, *args):
        """JaggedArray([row0, row1, ...])
        JaggedArray(values, values_per_row)
        """
        if len(args) == 1:
            values, values_per_row = (np.concatenate(args[0]),
                                      [len(row) for row in args[0]])
        else:
            values, values_per_row = (np.array(args[0]), args[1])

        self._values = values
        self._number_of_rows = len(values_per_row)
        self._offsets = JaggedArray._offsets_from_values_per_row(values_per_row)

    @property
    def size(self):
        return len(self._values)

    @property
    def number_of_rows(self):
        return self._number_of_rows

    @staticmethod
    def _offsets_from_values_per_row(values_per_row):
        offset = np.empty(len(values_per_row) + 1, dtype=int)
        np.cumsum(values_per_row, out=offset[1:])
        offset[0] = 0
        return offset

    def length_of_row(self, row):
        return self._offsets[row + 1] - self._offsets[row]

    def row(self, row):
        return self._values[self._offsets[row]:self._offsets[row + 1]]

    def iter(self):
        for n in xrange(self._number_of_rows):
            yield self.row(n)

<commit_msg>Added getters for array and offset arrays.<commit_after>import numpy as np

class JaggedArray(object):
    def __init__(self, *args):
        """JaggedArray([row0, row1, ...])
        JaggedArray(values, values_per_row)
        """
        if len(args) == 1:
            values, values_per_row = (np.concatenate(args[0]),
                                      [len(row) for row in args[0]])
        else:
            values, values_per_row = (np.array(args[0]), args[1])

        self._values = values
        self._number_of_rows = len(values_per_row)
        self._offsets = JaggedArray._offsets_from_values_per_row(values_per_row)

    @property
    def array(self):
        return self._values

    @property
    def offset(self):
        return self._offsets

    @property
    def size(self):
        return len(self._values)

    @property
    def number_of_rows(self):
        return self._number_of_rows

    @staticmethod
    def _offsets_from_values_per_row(values_per_row):
        offset = np.empty(len(values_per_row) + 1, dtype=int)
        np.cumsum(values_per_row, out=offset[1:])
        offset[0] = 0
        return offset

    def length_of_row(self, row):
        return self._offsets[row + 1] - self._offsets[row]

    def row(self, row):
        return self._values[self._offsets[row]:self._offsets[row + 1]]

    def iter(self):
        for n in xrange(self._number_of_rows):
            yield self.row(n)

<|endoftext|>


<commit_before>import ConfigParser
import random
import string
import re
import errno
import swagger_client
import os

__author__ = 'thauser'

config = ConfigParser.ConfigParser()
configfile = os.path.expanduser("~")+"/.config/pnc-cli/pnc-cli.conf"
configdir = os.path.dirname(configfile)
try:
    os.makedirs(configdir)
except OSError, e:
    if e.errno != errno.EEXIST:
        raise
found = config.read(os.path.join(configfile))
if not found:
    config.add_section('PNC')
    config.set('PNC', 'restEndpoint', 'http://localhost:8080/pnc-rest/rest')
    with open(os.path.join(configfile),'wb') as configfile:
        config.write(configfile)
pnc_rest_url = config.get('PNC', 'restEndpoint')
apiclient = swagger_client.api_client.ApiClient(pnc_rest_url)

def get_api_client():
    return apiclient

def is_valid_version(version):
    pattern = re.compile('\d*\.\w*')
    return pattern.match(version)
<commit_msg>Revert "refactor some methods in utils"<commit_after>import ConfigParser
import random
import string
import re
import swagger_client
import os

__author__ = 'thauser'

config = ConfigParser.ConfigParser()
configfilename = os.path.expanduser("~")+ "/.config/pnc-cli/pnc-cli.conf"
found = config.read(os.path.join(configfilename))
if not found:
    config.add_section('PNC')
    config.set('PNC', 'restEndpoint', 'http://localhost:8080/pnc-rest/rest')
    with open(os.path.join(configfilename),'wb') as configfile:
        config.write(configfile)
pnc_rest_url = config.get('PNC', 'restEndpoint')
apiclient = swagger_client.api_client.ApiClient(pnc_rest_url)

def get_api_client():
    return apiclient

def gen_random_name():
    return ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(10))

def is_valid_version(version):
    pattern = re.compile('\d*\.\w*')
    return pattern.match(version)
<|endoftext|>


<commit_before>import os
import fnmatch
import cv2
import numpy as np
import sys

if(len(sys.argv)<3):
	print('Insufficient arguments')
	quit()

#start=int(sys.argv[1])
#end=int(sys.argv[2])

names=[]
for i in range(1,len(sys.argv)):
	names.append(sys.argv[i])

path='/home/hassan/LipReading/GRID'

THRESH_FRAME_COUNT=76

file = open(path+'/valid_video_paths_face.txt','w')
file.close()

file = open(path+'/valid_aud_spec_paths_face.txt','w')
file.close()

for i in names:

	if i==21:
		continue

	print(i)

	os.chdir(path+'/Video/s'+str(i)+'/frames/face')
	numfiles=len(fnmatch.filter(os.listdir(path+'/Video/s'+str(i)+'/frames/face/'), '*.avi'))

	for j in range(1,numfiles+1):

		format_num1="{number:06}".format(number=j)
		cap = cv2.VideoCapture(str(format_num1)+'.avi')

		frameCount = int(cap.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT))+1

		if frameCount==1:
			numfiles+=1
			continue

		if not frameCount == THRESH_FRAME_COUNT:
			continue

		with open(path+'/valid_video_paths_face.txt', 'a') as file1:
			file1.write(path+'/Video/s'+str(i)+'/frames/face/'+str(format_num1)+'.avi\n')
		with open(path+'/valid_aud_spec_paths_face.txt', 'a') as file2:
			file2.write(path+'/Audio/s'+str(i)+'/AudSpecs/'+str(format_num1)+'.mat\n')

			#
<commit_msg>Update create_path_file_face.py<commit_after>import os
import fnmatch
import cv2
import numpy as np
import sys

if(len(sys.argv)<3):
	print('Insufficient arguments')
	quit()

#start=int(sys.argv[1])
#end=int(sys.argv[2])

names=[]
for i in range(1,len(sys.argv)):
	names.append(sys.argv[i])

path='/home/hassan/LipReading/GRID'

THRESH_FRAME_COUNT=76

file = open(path+'/valid_video_paths_face.txt','w')
file.close()

file = open(path+'/valid_aud_spec_paths_face.txt','w')
file.close()

for i in names:

	if i==21:
		continue

	print(i)

	os.chdir(path+'/Video/s'+str(i)+'/frames/face')
	numfiles=len(fnmatch.filter(os.listdir(path+'/Video/s'+str(i)+'/frames/face/'), '*.avi'))

	for j in range(1,numfiles+1):

		format_num1="{number:06}".format(number=j)
		cap = cv2.VideoCapture(str(format_num1)+'.avi')

		frameCount = int(cap.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT))+1

		if frameCount==1:
			numfiles+=1
			continue

		if not frameCount == THRESH_FRAME_COUNT:
			continue

		with open(path+'/valid_video_paths_face.txt', 'a') as file1:
			file1.write(path+'/Video/s'+str(i)+'/frames/face/'+str(format_num1)+'.avi\n')
		with open(path+'/valid_aud_spec_paths_face.txt', 'a') as file2:
			file2.write(path+'/Audio/s'+str(i)+'/AudSpecs/'+str(format_num1)+'.mat\n')

			#
<|endoftext|>


<commit_before>from launchkey import LAUNCHKEY_PRODUCTION
from .base import APIResponse, APIErrorResponse
import requests

class RequestsTransport(object):
    """
    Transport class for performing HTTP based queries using the requests library.
    """

    url = LAUNCHKEY_PRODUCTION
    testing = False
    verify_ssl = True

    def set_url(self, url, testing):
        """
        :param url: Base url for the querying LaunchKey API
        :param testing: Boolean stating whether testing mode is being performed. This will determine whether SSL should
        be verified.
        """
        self.url = url
        self.testing = testing
        self.verify_ssl = not self.testing

    @staticmethod
    def _parse_response(response):
        try:
            data = response.json()
        except ValueError:
            data = response.text

        try:
            response.raise_for_status()
        except requests.exceptions.HTTPError:
            if response.status_code < 500:
                return APIErrorResponse(data, response.headers, response.status_code, response.reason)
            else:
                raise

        return APIResponse(data, response.headers, response.status_code)

    def get(self, path, headers=None, data=None):
        """
        Performs an HTTP GET request against the LaunchKey API
        :param path: Path or endpoint that will be hit
        :param headers: Headers to add onto the request
        :param data: Dictionary or bytes to be sent in the query string for the request.
        :return:
        """
        return self._parse_response(requests.get(self.url + path, params=data, headers=headers, verify=self.verify_ssl))

    def post(self, path, headers=None, data=None):
        """
        Performs and HTTP POST request against the LaunchKey API
        :param path: Path or endpoint that will be hit
        :param headers: Headers to add onto the request
        :param data: Dictionary, bytes, or file-like object to send in the body of the request.
        :return:
        """
        return self._parse_response(requests.post(self.url + path, data=data, headers=headers, verify=self.verify_ssl))

    def put(self, path, headers=None, data=None):
        """
        Performs and HTTP PUT request against the LaunchKey API
        :param path: Path or endpoint that will be hit
        :param headers: Headers to add onto the request
        :param data: Dictionary, bytes, or file-like object to send in the body of the request.
        :return:
        """
        return self._parse_response(requests.put(self.url + path, data=data, headers=headers, verify=self.verify_ssl))

    def delete(self, path, headers=None, data=None):
        """
        Performs and HTTP DELETE request against the LaunchKey API
        :param path: Path or endpoint that will be hit
        :param headers: Headers to add onto the request
        :param data: Dictionary, bytes, or file-like object to send in the body of the request.
        :return:
        """
        return self._parse_response(
            requests.delete(self.url + path, data=data, headers=headers, verify=self.verify_ssl))
<commit_msg>Added patch to the HTTP transports<commit_after>from launchkey import LAUNCHKEY_PRODUCTION
from .base import APIResponse, APIErrorResponse
import requests

class RequestsTransport(object):
    """
    Transport class for performing HTTP based queries using the requests library.
    """

    url = LAUNCHKEY_PRODUCTION
    testing = False
    verify_ssl = True

    def set_url(self, url, testing):
        """
        :param url: Base url for the querying LaunchKey API
        :param testing: Boolean stating whether testing mode is being performed. This will determine whether SSL should
        be verified.
        """
        self.url = url
        self.testing = testing
        self.verify_ssl = not self.testing

    @staticmethod
    def _parse_response(response):
        try:
            data = response.json()
        except ValueError:
            data = response.text

        try:
            response.raise_for_status()
        except requests.exceptions.HTTPError:
            if response.status_code < 500:
                return APIErrorResponse(data, response.headers, response.status_code, response.reason)
            else:
                raise

        return APIResponse(data, response.headers, response.status_code)

    def get(self, path, headers=None, data=None):
        """
        Performs an HTTP GET request against the LaunchKey API
        :param path: Path or endpoint that will be hit
        :param headers: Headers to add onto the request
        :param data: Dictionary or bytes to be sent in the query string for the request.
        :return:
        """
        return self._parse_response(requests.get(self.url + path, params=data, headers=headers, verify=self.verify_ssl))

    def post(self, path, headers=None, data=None):
        """
        Performs and HTTP POST request against the LaunchKey API
        :param path: Path or endpoint that will be hit
        :param headers: Headers to add onto the request
        :param data: Dictionary, bytes, or file-like object to send in the body of the request.
        :return:
        """
        return self._parse_response(requests.post(self.url + path, data=data, headers=headers, verify=self.verify_ssl))

    def put(self, path, headers=None, data=None):
        """
        Performs and HTTP PUT request against the LaunchKey API
        :param path: Path or endpoint that will be hit
        :param headers: Headers to add onto the request
        :param data: Dictionary, bytes, or file-like object to send in the body of the request.
        :return:
        """
        return self._parse_response(requests.put(self.url + path, data=data, headers=headers, verify=self.verify_ssl))

    def delete(self, path, headers=None, data=None):
        """
        Performs and HTTP DELETE request against the LaunchKey API
        :param path: Path or endpoint that will be hit
        :param headers: Headers to add onto the request
        :param data: Dictionary, bytes, or file-like object to send in the body of the request.
        :return:
        """
        return self._parse_response(
            requests.delete(self.url + path, data=data, headers=headers, verify=self.verify_ssl))

    def patch(self, path, headers=None, data=None):
        """
        Performs and HTTP PATCH request against the LaunchKey API
        :param path: Path or endpoint that will be hit
        :param headers: Headers to add onto the request
        :param data: Dictionary, bytes, or file-like object to send in the body of the request.
        :return:
        """
        return self._parse_response(requests.patch(self.url + path, data=data, headers=headers, verify=self.verify_ssl))
<|endoftext|>


<commit_before>import logging
import typing
from datetime import datetime

import discord

from cogbot.types import ChannelId, RoleId

log = logging.getLogger(__name__)

class CogBotServerState:
    def __init__(self, bot, server: discord.Server, log_channel: ChannelId = None):
        self.bot = bot
        self.server: discord.Server = server

        # resolve log channel
        self.log_channel: discord.Channel = None
        if log_channel:
            self.log_channel = self.bot.get_channel(log_channel)
            if not self.log_channel:
                log.warning(
                    f"[{self.server}] Failed to resolve log channel <{log_channel}>"
                )

    async def mod_log(
        self,
        member: discord.Member = None,
        content: str = None,
        message: discord.Message = None,
        icon: str = None,
        title: str = None,
        icon_url: str = None,
        color: int = None,
        show_timestamp: bool = True,
        channel: discord.Channel = None,
        footer_text: str = None,
        notify_roles: typing.Iterable[discord.Role] = None,
        fields: typing.Dict[str, str] = None,
        compact: bool = False,
    ):
        if not self.log_channel:
            return

        actual_channel = channel or self.log_channel

        if compact:
            parts = []
            if icon:
                parts.append(icon)
            if notify_roles:
                roles_mention_str = " ".join(
                    [f"{role.mention}" for role in notify_roles]
                )
                outside_content = f"{roles_mention_str}"
            if title:
                parts.append(title)
            if member:
                parts.append(f"{member.mention}")
            if content:
                parts.append(content)
            if fields:
                fields_str = ", ".join([f"{k} `{v}`" for k, v in fields.items()])
                parts.append(fields_str)
            content = ">>> " + " ".join(parts)
            await self.bot.send_message(actual_channel, content=content)

        else:
            color = color or discord.Embed.Empty

            description_parts = []
            if member:
                description_parts.append(str(member.mention))
            if content:
                description_parts.append(content)
            description = " ".join(description_parts)

            if message:
                message_link = self.bot.make_message_link(message)
                icon = icon or ":arrow_right:"
                icon = f"[{icon}]({message_link})"

            if icon and not title:
                description = f"{icon} {description}"

            em = discord.Embed(description=description, color=color)

            if title:
                em.set_author(name=title, icon_url=icon_url)

            if fields:
                for field_name, field_value in fields.items():
                    em.add_field(name=field_name, value=field_value, inline=False)

            if show_timestamp:
                em.timestamp = datetime.utcnow()

            if footer_text:
                em.set_footer(text=footer_text, icon_url=icon_url)
            elif member and message:
                em.set_footer(
                    text=f"{member} in #{message.channel}", icon_url=member.avatar_url
                )
            elif member:
                em.set_footer(text=f"{member}", icon_url=member.avatar_url)

            outside_content = None
            if notify_roles:
                roles_mention_str = " ".join(
                    [f"{role.mention}" for role in notify_roles]
                )
                outside_content = f"{roles_mention_str}"

            await self.bot.send_message(
                actual_channel, content=outside_content, embed=em
            )
<commit_msg>Edit compact mod logs to avoid pings<commit_after>import logging
import typing
from datetime import datetime

import discord

from cogbot.types import ChannelId

log = logging.getLogger(__name__)

class CogBotServerState:
    def __init__(self, bot, server: discord.Server, log_channel: ChannelId = None):
        self.bot = bot
        self.server: discord.Server = server

        # resolve log channel
        self.log_channel: discord.Channel = None
        if log_channel:
            self.log_channel = self.bot.get_channel(log_channel)
            if not self.log_channel:
                log.warning(f"[{self.server}] Failed to resolve log channel <{log_channel}>")

    async def mod_log(
        self,
        member: discord.Member = None,
        content: str = None,
        message: discord.Message = None,
        icon: str = None,
        title: str = None,
        icon_url: str = None,
        color: int = None,
        show_timestamp: bool = True,
        channel: discord.Channel = None,
        footer_text: str = None,
        notify_roles: typing.Iterable[discord.Role] = None,
        fields: typing.Dict[str, str] = None,
        compact: bool = False,
    ):
        if not self.log_channel:
            return

        actual_channel = channel or self.log_channel

        if compact:
            parts = []
            if icon:
                parts.append(icon)
            if notify_roles:
                roles_mention_str = " ".join([f"{role.mention}" for role in notify_roles])
                outside_content = f"{roles_mention_str}"
            if title:
                parts.append(title)
            if member:
                parts.append(f"{member.mention}")
            if content:
                parts.append(content)
            if fields:
                fields_str = ", ".join([f"{k} `{v}`" for k, v in fields.items()])
                parts.append(fields_str)
            content = " ".join(parts)
            # send a dummy message and then edit it so that people don't get pinged
            log_message = await self.bot.send_message(actual_channel, content="🤖")
            await self.bot.edit_message(log_message, new_content=content)

        else:
            color = color or discord.Embed.Empty

            description_parts = []
            if member:
                description_parts.append(str(member.mention))
            if content:
                description_parts.append(content)
            description = " ".join(description_parts)

            if message:
                message_link = self.bot.make_message_link(message)
                icon = icon or ":arrow_right:"
                icon = f"[{icon}]({message_link})"

            if icon and not title:
                description = f"{icon} {description}"

            em = discord.Embed(description=description, color=color)

            if title:
                em.set_author(name=title, icon_url=icon_url)

            if fields:
                for field_name, field_value in fields.items():
                    em.add_field(name=field_name, value=field_value, inline=False)

            if show_timestamp:
                em.timestamp = datetime.utcnow()

            if footer_text:
                em.set_footer(text=footer_text, icon_url=icon_url)
            elif member and message:
                em.set_footer(text=f"{member} in #{message.channel}", icon_url=member.avatar_url)
            elif member:
                em.set_footer(text=f"{member}", icon_url=member.avatar_url)

            outside_content = None
            if notify_roles:
                roles_mention_str = " ".join([f"{role.mention}" for role in notify_roles])
                outside_content = f"{roles_mention_str}"

            await self.bot.send_message(actual_channel, content=outside_content, embed=em)
<|endoftext|>


<commit_before>import json

from django.contrib.auth.models import User
from django.db import models
from django.utils.translation import ugettext as _

class DeviceType(models.Model):
    """
    A class of device, for example a pandaboard or a snowball.
    """

    name = models.SlugField(primary_key=True)

    def __unicode__(self):
        return self.name

    # We will probably hang uboot command and such off here...

class Device(models.Model):
    """
    A device that we can run tests on.
    """

    OFFLINE = 0
    IDLE = 1
    RUNNING = 2

    STATUS_CHOICES = (
        (OFFLINE, 'Offline'),
        (IDLE, 'Idle'),
        (RUNNING, 'Running'),
    )

    hostname = models.CharField(
        verbose_name = _(u"Hostname"),
        max_length = 200,
        primary_key = True,
    )

    device_type = models.ForeignKey(
        DeviceType, verbose_name=_(u"Device type"))

    current_job = models.ForeignKey(
        "TestJob", blank=True, unique=True, null=True)

    status = models.IntegerField(
        choices = STATUS_CHOICES,
        default = IDLE,
        verbose_name = _(u"Device status"),
    )

    def __unicode__(self):
        return self.hostname

    #@classmethod
    #def find_devices_by_type(cls, device_type):
    #    return device_type.device_set.all()

class TestJob(models.Model):
    """
    A test job is a test process that will be run on a Device.
    """

    SUBMITTED = 0
    RUNNING = 1
    COMPLETE = 2
    INCOMPLETE = 3
    CANCELED = 4

    STATUS_CHOICES = (
        (SUBMITTED, 'Submitted'),
        (RUNNING, 'Running'),
        (COMPLETE, 'Complete'),
        (INCOMPLETE, 'Incomplete'),
        (CANCELED, 'Canceled'),
    )

    id = models.IntegerField(primary_key=True)

    submitter = models.ForeignKey(
        User,
        verbose_name = _(u"Submitter"),
    )

    #description = models.CharField(
    #    verbose_name = _(u"Description"),
    #    max_length = 200
    #)

    target = models.ForeignKey(Device, null=True)
    device_type = models.ForeignKey(DeviceType)

    #priority = models.IntegerField(
    #    verbose_name = _(u"Priority"),
    #    default=0)
    submit_time = models.DateTimeField(
        verbose_name = _(u"Submit time"),
        auto_now = False,
        auto_now_add = True
    )
    start_time = models.DateTimeField(
        verbose_name = _(u"Start time"),
        auto_now = False,
        auto_now_add = False,
        null = True,
        blank = True,
        editable = False
    )
    end_time = models.DateTimeField(
        verbose_name = _(u"End time"),
        auto_now = False,
        auto_now_add = False,
        null = True,
        blank = True,
        editable = False
    )
    status = models.IntegerField(
        choices = STATUS_CHOICES,
        default = SUBMITTED,
        verbose_name = _(u"Status"),
    )
    definition = models.TextField(
        editable = False,
    )

    def __unicode__(self):
        r = "%s test job" % self.get_status_display()
        if self.target:
            r += " for %s" % (self.target.hostname,)
        return r

    @classmethod
    def from_json_and_user(cls, json_data, user):
        job_data = json.loads(json_data)
        if 'target' in job_data:
            target = Device.objects.get(hostname=job_data['target'])
            device_type = target.device_type
        else:
            target = None
            device_type = DeviceType.objects.get(name=job_data['device_type'])
        job = TestJob(
            definition=json_data, submitter=user, device_type=device_type,
            target=target)
        job.save()
        return job
<commit_msg>fix tests (sorry)<commit_after>import json

from django.contrib.auth.models import User
from django.db import models
from django.utils.translation import ugettext as _

class DeviceType(models.Model):
    """
    A class of device, for example a pandaboard or a snowball.
    """

    name = models.SlugField(primary_key=True)

    def __unicode__(self):
        return self.name

    # We will probably hang uboot command and such off here...

class Device(models.Model):
    """
    A device that we can run tests on.
    """

    OFFLINE = 0
    IDLE = 1
    RUNNING = 2

    STATUS_CHOICES = (
        (OFFLINE, 'Offline'),
        (IDLE, 'Idle'),
        (RUNNING, 'Running'),
    )

    hostname = models.CharField(
        verbose_name = _(u"Hostname"),
        max_length = 200,
        primary_key = True,
    )

    device_type = models.ForeignKey(
        DeviceType, verbose_name=_(u"Device type"))

    current_job = models.ForeignKey(
        "TestJob", blank=True, unique=True, null=True)

    status = models.IntegerField(
        choices = STATUS_CHOICES,
        default = IDLE,
        verbose_name = _(u"Device status"),
    )

    def __unicode__(self):
        return self.hostname

    #@classmethod
    #def find_devices_by_type(cls, device_type):
    #    return device_type.device_set.all()

class TestJob(models.Model):
    """
    A test job is a test process that will be run on a Device.
    """

    SUBMITTED = 0
    RUNNING = 1
    COMPLETE = 2
    INCOMPLETE = 3
    CANCELED = 4

    STATUS_CHOICES = (
        (SUBMITTED, 'Submitted'),
        (RUNNING, 'Running'),
        (COMPLETE, 'Complete'),
        (INCOMPLETE, 'Incomplete'),
        (CANCELED, 'Canceled'),
    )

    id = models.AutoField(primary_key=True)

    submitter = models.ForeignKey(
        User,
        verbose_name = _(u"Submitter"),
    )

    #description = models.CharField(
    #    verbose_name = _(u"Description"),
    #    max_length = 200
    #)

    target = models.ForeignKey(Device, null=True)
    device_type = models.ForeignKey(DeviceType)

    #priority = models.IntegerField(
    #    verbose_name = _(u"Priority"),
    #    default=0)
    submit_time = models.DateTimeField(
        verbose_name = _(u"Submit time"),
        auto_now = False,
        auto_now_add = True
    )
    start_time = models.DateTimeField(
        verbose_name = _(u"Start time"),
        auto_now = False,
        auto_now_add = False,
        null = True,
        blank = True,
        editable = False
    )
    end_time = models.DateTimeField(
        verbose_name = _(u"End time"),
        auto_now = False,
        auto_now_add = False,
        null = True,
        blank = True,
        editable = False
    )
    status = models.IntegerField(
        choices = STATUS_CHOICES,
        default = SUBMITTED,
        verbose_name = _(u"Status"),
    )
    definition = models.TextField(
        editable = False,
    )

    def __unicode__(self):
        r = "%s test job" % self.get_status_display()
        if self.target:
            r += " for %s" % (self.target.hostname,)
        return r

    @classmethod
    def from_json_and_user(cls, json_data, user):
        job_data = json.loads(json_data)
        if 'target' in job_data:
            target = Device.objects.get(hostname=job_data['target'])
            device_type = target.device_type
        else:
            target = None
            device_type = DeviceType.objects.get(name=job_data['device_type'])
        job = TestJob(
            definition=json_data, submitter=user, device_type=device_type,
            target=target)
        job.save()
        return job
<|endoftext|>


<commit_before>#!/usr/bin/env python
# encoding: utf-8
import logging
logger = logging.getLogger(__name__)

from bottle import request

request_logger = logging.getLogger('request.params')

def logplugin(callback):

    def wrapper(*args, **kwargs):
        request_logger.info(request.params)
        body = callback(*args, **kwargs)
        request_logger.info(body)
        return body

    return wrapper

<commit_msg>fix gevent remote addr<commit_after>#!/usr/bin/env python
# encoding: utf-8
import logging
logger = logging.getLogger(__name__)

from bottle import request

request_logger = logging.getLogger('request.params')

def logplugin(callback):

    def wrapper(*args, **kwargs):
        request_logger.info(request.params)
        request.remote_addr = request.environ.get("X_FORWARDED_FOR", request.remote_addr)
        body = callback(*args, **kwargs)
        request_logger.info(body)
        return body

    return wrapper

<|endoftext|>