<commit_before>#!/usr/bin/env python
# encoding: utf-8
from cadnano.gui.views.pathview import pathstyles as styles
from cadnano.enum import StrandType

import cadnano.util as util

from PyQt5.QtCore import QRectF, Qt, QPointF

from PyQt5.QtGui import QBrush, QPen, QFont, QColor, QFontMetricsF, QPainterPath
from PyQt5.QtGui import QMatrix3x3, QTextCursor
from PyQt5.QtWidgets  import QGraphicsItem, QGraphicsPathItem, QGraphicsRectItem
from PyQt5.QtWidgets  import QGraphicsTextItem, QLabel

_baseWidth = _bw = styles.PATH_BASE_WIDTH
_halfbaseWidth = _hbw = _baseWidth / 2
_offset1 = _baseWidth / 4
_defaultRect = QRectF(0, 0, _bw, _bw)
_bpen = QPen(styles.BLUE_STROKE, styles.INSERTWIDTH)
_rpen = QPen(styles.RED_STROKE, styles.SKIPWIDTH)
_noPen = QPen(Qt.NoPen)

def _insertGen(path, start, c1, p1, c2):
    path.moveTo(start)
    path.quadTo(c1, p1)
    path.quadTo(c2, start)
# end def

_pathStart = QPointF(_hbw, _hbw)
_pathMidUp = QPointF(_hbw, -_bw)
_pathUpUpCtrlPt = QPointF(-_hbw, -_bw)
_pathUpDownCtrlPt = QPointF(1.5 * _bw, -_bw)
_pathMidDown = QPointF(_hbw, 2 * _bw)
_pathDownDownCtrlPt = QPointF(-_hbw, 2 * _bw)
_pathDownUpCtrlPt = QPointF(1.5 * _bw, 2 * _bw)
_insertPathUp = QPainterPath()
_insertGen(_insertPathUp, _pathStart, _pathUpUpCtrlPt,\
         _pathMidUp, _pathUpDownCtrlPt)
_insertPathUp.translate(_offset1, 0)
_insertPathUpRect = _insertPathUp.boundingRect()
_insertPathDown = QPainterPath()
_insertGen(_insertPathDown, _pathStart, _pathDownDownCtrlPt,\
         _pathMidDown, _pathDownUpCtrlPt)
_insertPathDown.translate(_offset1, 0)
_insertPathDownRect = _insertPathDown.boundingRect()

_bigRect = _defaultRect.united(_insertPathUpRect)
_bigRect = _bigRect.united(_insertPathDownRect)
_bpen2 = QPen(styles.BLUE_STROKE, 2)
_offset2 = _bw*0.75
_font = QFont(styles.THE_FONT, 10, QFont.Bold)
_bigRect.adjust(-15, -15, 30, 30)
# Bases are drawn along and above the insert path.
# These calculations revolve around fixing the characters at a certain
# percentage of the total arclength.
# The fraction of the insert that comes before the first character and
# after the last character is the padding, and the rest is divided evenly.
_fractionInsertToPad = .10

class InsertionPath(object):
    """
    This is just the shape of the Insert item
    """

    def __init__(self):
        super(InsertionPath, self).__init__()
    # end def

    def getPen(self):
        return _bpen
    # end def

    def getInsert(self, istop):
        if istop:
            return _insertPathUp
        else:
            return _insertPathDown
    # end def
# end class

def _xGen(path, p1, p2, p3, p4):
    path.moveTo(p1)
    path.lineTo(p2)
    path.moveTo(p3)
    path.lineTo(p4)
# end def

_pathStart = QPointF(_hbw, _hbw)

class SkipPath(object):
    """
    This is just the shape of the Insert item
    """

    _skipPath = QPainterPath()
    _xGen(_skipPath, _defaultRect.bottomLeft(), _defaultRect.topRight(), \
                        _defaultRect.topLeft(), _defaultRect.bottomRight())

    def __init__(self):
        super(SkipPath, self).__init__()
    # end def

    def getPen(self):
        return _rpen
    # end def

    def getSkip(self):
        return self._skipPath
    # end def
# end class

_insertPath = InsertionPath()
_skipPath = SkipPath()

class InsertionItem(QGraphicsPathItem):
    """
    This is just the shape of the Insert item
    """
    def __init__(self, virtualHelixItem, strand, insertion):
        super(InsertionItem, self).__init__(virtualHelixItem)
        self.hide()
        self._strand = strand
        self._insertion = insertion
        self._seqItem = QGraphicsPathItem(parent=self)
        self._isOnTop = isOnTop = virtualHelixItem.isStrandOnTop(strand)
        y = 0 if isOnTop else _bw
        self.setPos(_bw*insertion.idx(), y)
        self.setZValue(styles.ZINSERTHANDLE)
        self._initLabel()
        self._initClickArea()
        self.updateItem()
        self.show()
    # end def

    def _initLabel(self):
        """Display the length of the insertion."""
        self._label = label = QGraphicsTextItem("", parent=self)
        label.setFont(_font)
        label.setTextInteractionFlags(Qt.TextEditorInteraction)
        label.inputMethodEvent = self.inputMethodEventHandler
        label.keyPressEvent = self.textkeyPressEvent
        label.mousePressEvent = self.labelMousePressEvent
        label.mouseDoubleClickEvent = self.mouseDoubleClickEvent
        label.setTextWidth(-1)

        self._label = label
        self._seqItem = QGraphicsPathItem(parent=self)
        self._seqText = None
        self.updateItem()
        self.show()
    # end def

    def _initClickArea(self):
        """docstring for _initClickArea"""
        self._clickArea = cA = QGraphicsRectItem(_defaultRect, self)
        cA.setPen(_noPen)
        cA.mousePressEvent = self.mousePressEvent
        cA.mouseDoubleClickEvent = self.mouseDoubleClickEvent
    # end def

    ### PUBLIC SUPPORT METHODS ###
    def remove(self):
        """
        Called from the following stranditem methods:
            strandRemovedSlot
            strandInsertionRemovedSlot
            refreshInsertionItems
        """
        scene = self.scene()
        self._label.setTextInteractionFlags(Qt.NoTextInteraction)
        self._label.clearFocus()
        scene.removeItem(self._label)
        self._label = None
        scene.removeItem(self._seqItem)
        self._seqItem = None
        scene.removeItem(self)
        self._insertion = None
        self._strand = None
    # end def

    def updateItem(self):
        self._updatePath()
        self._updateLabel()
        self._updateSequenceText()
        self._resetPosition()
    # end def

    ### PRIVATE SUPPORT METHODS ###
    def _focusOut(self):
        lbl = self._label
        if lbl == None:
            return
        cursor = lbl.textCursor()
        cursor.clearSelection()
        lbl.setTextCursor(cursor)
        lbl.clearFocus()
    # end def

    def _resetPosition(self):
        """
        Set the label position based on orientation and text alignment.
        """
        lbl = self._label
        if lbl == None:
            return
        txtOffset = lbl.boundingRect().width()/2
        insertion = self._insertion
        y = -_bw if self._isOnTop else _bw
        lbl.setPos(_offset2-txtOffset, y)
        if insertion.length() > 0:
            lbl.show()
        else:
            lbl.hide()
    # end def

    def _updateLabel(self):
        self._label.setPlainText("%d" % (self._insertion.length()))
    # end def

    def _updatePath(self):
        strand = self._strand
        if strand == None:
            self.hide()
            return
        else:
            self.show()
        isOnTop = self._isOnTop
        if self._insertion.length() > 0:
            self.setPen(QPen(QColor(strand.oligo().color()), styles.INSERTWIDTH))
            self.setBrush(QBrush(Qt.NoBrush))
            self.setPath(_insertPath.getInsert(isOnTop))
        else:  # insertionSize < 0 (a skip)
            self.setPen(_skipPath.getPen())
            self.setPath(_skipPath.getSkip())
    # end def

    def setSequence(self, sequence):
        self._seqText = sequence
        self._updateSequenceText()
        self._seqItem.show()
    # end def

    def hideSequence(self):
        self._seqItem.hide()
    # end def

    def _updateSequenceText(self):
        seqItem = self._seqItem
        isOnTop = self._isOnTop
        index = self._insertion.idx()
        baseText = self._seqText
        font = styles.SEQUENCEFONT
        seqFontH = styles.SEQUENCEFONTH
        insertW = styles.INSERTWIDTH
        seqFontCharW = styles.SEQUENCEFONTCHARWIDTH
        # draw sequence on the insert
        if baseText:  # only draw sequences if they exist i.e. not None!
            lenBT = len(baseText)
            if isOnTop:
                angleOffset = 0
            else:
                angleOffset = 180
            if lenBT > 20:
                baseText = baseText[:17] + '...'
                lenBT = len(baseText)
            fractionArclenPerChar = (1.0-2.0*_fractionInsertToPad)/(lenBT+1)
            seqItem.setPen(QPen(Qt.NoPen))
            seqItem.setBrush(QBrush(Qt.black))

            seqPath = QPainterPath()
            loopPath = self.path()
            for i in range(lenBT):
                frac = _fractionInsertToPad + (i+1)*fractionArclenPerChar
                pt = loopPath.pointAtPercent(frac)
                tangAng = loopPath.angleAtPercent(frac)

                tempPath = QPainterPath()
                # 1. draw the text
                tempPath.addText(0,0, font, baseText[i if isOnTop else -i-1])
                # 2. center it at the zero point different for top and bottom
                # strands
                if not isOnTop:
                    tempPath.translate(0, -seqFontH - insertW)

                tempPath.translate(QPointF(-seqFontCharW/2.,
                                          -2 if isOnTop else seqFontH))
                mat = QMatrix3x3()
                # 3. rotate it
                mat.rotate(-tangAng + angleOffset)
                rotatedPath = mat.map(tempPath)
                # 4. translate the rotate object to it's position on the part
                rotatedPath.translate(pt)
                seqPath.addPath(rotatedPath)
            # end for
            seqItem.setPath(seqPath)
        # end if
    # end def

    ### EVENT HANDLERS ###
    def mouseDoubleClickEvent(self, event):
        """Double clicks remove the insertion/skip."""
        self._strand.changeInsertion(self._insertion.idx(), 0)

    def mousePressEvent(self, event):
        """This needs to be present for mouseDoubleClickEvent to work."""
        pass

    def labelMousePressEvent(self, event):
        """
        Pre-selects the text for editing when you click
        the label.
        """
        lbl = self._label
        lbl.setTextInteractionFlags(Qt.TextEditorInteraction)
        cursor = lbl.textCursor()
        cursor.setPosition(0)
        cursor.movePosition(QTextCursor.End, QTextCursor.KeepAnchor)
        lbl.setTextCursor(cursor)

    def textkeyPressEvent(self, event):
        """
        Must intercept invalid input events.  Make changes here
        """
        a = event.key()
        text = event.text()
        if a in [Qt.Key_Space, Qt.Key_Tab]:
            return
        elif a in [Qt.Key_Return, Qt.Key_Enter]:
            self.inputMethodEventHandler(event)
            return
        # elif unicode(text).isalpha():
        elif text.isalpha():
            return
        else:
            return QGraphicsTextItem.keyPressEvent(self._label, event)

    def inputMethodEventHandler(self, event):
        """
        This is run on the label being changed
        or losing focus
        """
        lbl = self._label
        if lbl == None:
            return
        # test = unicode(lbl.toPlainText())
        test = lbl.toPlainText()
        try:
            insertionSize = int(test)
        except:
            insertionSize = None
        insertion = self._insertion
        length = insertion.length()
        if insertionSize != None and insertionSize != length:
            self._strand.changeInsertion(insertion.idx(), insertionSize)
            if insertion.length():
                self._resetPosition()
        else:
            self._updateLabel()
        # end if
        self._focusOut()
    # end def
# end class
<commit_msg>style changes to insertionitem and fixed the fact that Qt5 uses QTransform for QMatrix from Qt4, close #14<commit_after>#!/usr/bin/env python
# encoding: utf-8
from cadnano.gui.views.pathview import pathstyles as styles
from cadnano.enum import StrandType

import cadnano.util as util

from PyQt5.QtCore import QRectF, Qt, QPointF

from PyQt5.QtGui import QBrush, QPen, QFont, QColor, QFontMetricsF, QPainterPath
from PyQt5.QtGui import QTransform, QTextCursor
from PyQt5.QtWidgets  import QGraphicsItem, QGraphicsPathItem, QGraphicsRectItem
from PyQt5.QtWidgets  import QGraphicsTextItem, QLabel

_BASE_WIDTH = _BW = styles.PATH_BASE_WIDTH
_HALF_BASE_WIDTH = _HBW = _BASE_WIDTH / 2
_OFFSET1 = _BASE_WIDTH / 4
_DEFAULT_RECT = QRectF(0, 0, _BW, _BW)
_B_PEN = QPen(styles.BLUE_STROKE, styles.INSERTWIDTH)
_R_PEN = QPen(styles.RED_STROKE, styles.SKIPWIDTH)
_NO_PEN = QPen(Qt.NoPen)

def _insertGen(path, start, c1, p1, c2):
    path.moveTo(start)
    path.quadTo(c1, p1)
    path.quadTo(c2, start)
# end def

_PATH_START = QPointF(_HBW, _HBW)
_PATH_MID_UP = QPointF(_HBW, -_BW)
_PATH_UP_UP_CTRL_PT = QPointF(-_HBW, -_BW)
_PATH_UP_DOWN_CTRL_PT = QPointF(1.5 * _BW, -_BW)
_PATH_MID_DOWN = QPointF(_HBW, 2 * _BW)
_PATH_DOWN_DOWN_CTRL_PT = QPointF(-_HBW, 2 * _BW)
_PATH_DOWN_UP_CTRL_PT = QPointF(1.5 * _BW, 2 * _BW)
_INSERT_PATH_UP = QPainterPath()
_insertGen(_INSERT_PATH_UP, _PATH_START, _PATH_UP_UP_CTRL_PT,\
         _PATH_MID_UP, _PATH_UP_DOWN_CTRL_PT)
_INSERT_PATH_UP.translate(_OFFSET1, 0)
_INSERT_PATH_UP_RECT = _INSERT_PATH_UP.boundingRect()
_INSERT_PATH_DOWN = QPainterPath()
_insertGen(_INSERT_PATH_DOWN, _PATH_START, _PATH_DOWN_DOWN_CTRL_PT,\
         _PATH_MID_DOWN, _PATH_DOWN_UP_CTRL_PT)
_INSERT_PATH_DOWN.translate(_OFFSET1, 0)
_INSERT_PATH_DOWNRect = _INSERT_PATH_DOWN.boundingRect()

_BIG_RECT = _DEFAULT_RECT.united(_INSERT_PATH_UP_RECT)
_BIG_RECT = _BIG_RECT.united(_INSERT_PATH_DOWNRect)
_B_PEN2 = QPen(styles.BLUE_STROKE, 2)
_OFFSET2   = _BW*0.75
_FONT = QFont(styles.THE_FONT, 10, QFont.Bold)
_BIG_RECT.adjust(-15, -15, 30, 30)
# Bases are drawn along and above the insert path.
# These calculations revolve around fixing the characters at a certain
# percentage of the total arclength.
# The fraction of the insert that comes before the first character and
# after the last character is the padding, and the rest is divided evenly.
_FRACTION_INSERT_TO_PAD = .10

class InsertionPath(object):
    """
    This is just the shape of the Insert item
    """

    def __init__(self):
        super(InsertionPath, self).__init__()
    # end def

    def getPen(self):
        return _B_PEN
    # end def

    def getInsert(self, is_top):
        if is_top:
            return _INSERT_PATH_UP
        else:
            return _INSERT_PATH_DOWN
    # end def
# end class

def _xGen(path, p1, p2, p3, p4):
    path.moveTo(p1)
    path.lineTo(p2)
    path.moveTo(p3)
    path.lineTo(p4)
# end def

_PATH_START = QPointF(_HBW, _HBW)

class SkipPath(object):
    """
    This is just the shape of the Insert item
    """

    _skipPath = QPainterPath()
    _xGen(_skipPath, _DEFAULT_RECT.bottomLeft(), _DEFAULT_RECT.topRight(), \
                        _DEFAULT_RECT.topLeft(), _DEFAULT_RECT.bottomRight())

    def __init__(self):
        super(SkipPath, self).__init__()
    # end def

    def getPen(self):
        return _R_PEN
    # end def

    def getSkip(self):
        return self._skipPath
    # end def
# end class

_insertPath = InsertionPath()
_skipPath = SkipPath()

class InsertionItem(QGraphicsPathItem):
    """
    This is just the shape of the Insert item
    """
    def __init__(self, virtual_helix_item, strand, insertion):
        super(InsertionItem, self).__init__(virtual_helix_item)
        self.hide()
        self._strand = strand
        self._insertion = insertion
        self._seq_item = QGraphicsPathItem(parent=self)
        self._is_on_top = is_on_top = virtual_helix_item.isStrandOnTop(strand)
        y = 0 if is_on_top else _BW
        self.setPos(_BW*insertion.idx(), y)
        self.setZValue(styles.ZINSERTHANDLE)
        self._initLabel()
        self._initClickArea()
        self.updateItem()
        self.show()
    # end def

    def _initLabel(self):
        """Display the length of the insertion."""
        self._label = label = QGraphicsTextItem("", parent=self)
        label.setFont(_FONT)
        label.setTextInteractionFlags(Qt.TextEditorInteraction)
        label.inputMethodEvent = self.inputMethodEventHandler
        label.keyPressEvent = self.textkeyPressEvent
        label.mousePressEvent = self.labelMousePressEvent
        label.mouseDoubleClickEvent = self.mouseDoubleClickEvent
        label.setTextWidth(-1)

        self._label = label
        self._seq_item = QGraphicsPathItem(parent=self)
        self._seq_text = None
        self.updateItem()
        self.show()
    # end def

    def _initClickArea(self):
        """docstring for _initClickArea"""
        self._clickArea = cA = QGraphicsRectItem(_DEFAULT_RECT, self)
        cA.setPen(_NO_PEN)
        cA.mousePressEvent = self.mousePressEvent
        cA.mouseDoubleClickEvent = self.mouseDoubleClickEvent
    # end def

    ### PUBLIC SUPPORT METHODS ###
    def remove(self):
        """
        Called from the following stranditem methods:
            strandRemovedSlot
            strandInsertionRemovedSlot
            refreshInsertionItems
        """
        scene = self.scene()
        self._label.setTextInteractionFlags(Qt.NoTextInteraction)
        self._label.clearFocus()
        scene.removeItem(self._label)
        self._label = None
        scene.removeItem(self._seq_item)
        self._seq_item = None
        scene.removeItem(self)
        self._insertion = None
        self._strand = None
    # end def

    def updateItem(self):
        self._updatePath()
        self._updateLabel()
        self._updateSequenceText()
        self._resetPosition()
    # end def

    ### PRIVATE SUPPORT METHODS ###
    def _focusOut(self):
        lbl = self._label
        if lbl == None:
            return
        cursor = lbl.textCursor()
        cursor.clearSelection()
        lbl.setTextCursor(cursor)
        lbl.clearFocus()
    # end def

    def _resetPosition(self):
        """
        Set the label position based on orientation and text alignment.
        """
        lbl = self._label
        if lbl == None:
            return
        txt_offset = lbl.boundingRect().width()/2
        insertion = self._insertion
        y = -_BW if self._is_on_top else _BW
        lbl.setPos(_OFFSET2 - txt_offset, y)
        if insertion.length() > 0:
            lbl.show()
        else:
            lbl.hide()
    # end def

    def _updateLabel(self):
        self._label.setPlainText("%d" % (self._insertion.length()))
    # end def

    def _updatePath(self):
        strand = self._strand
        if strand == None:
            self.hide()
            return
        else:
            self.show()
        is_on_top = self._is_on_top
        if self._insertion.length() > 0:
            self.setPen(QPen(QColor(strand.oligo().color()), styles.INSERTWIDTH))
            self.setBrush(QBrush(Qt.NoBrush))
            self.setPath(_insertPath.getInsert(is_on_top))
        else:  # insertion_size < 0 (a skip)
            self.setPen(_skipPath.getPen())
            self.setPath(_skipPath.getSkip())
    # end def

    def setSequence(self, sequence):
        self._seq_text = sequence
        self._updateSequenceText()
        self._seq_item.show()
    # end def

    def hideSequence(self):
        self._seq_item.hide()
    # end def

    def _updateSequenceText(self):
        seq_item = self._seq_item
        is_on_top = self._is_on_top
        index = self._insertion.idx()
        base_text = self._seq_text
        font = styles.SEQUENCEFONT
        seq_font_h = styles.SEQUENCEFONTH
        insert_w = styles.INSERTWIDTH
        seq_font_char_w = styles.SEQUENCEFONTCHARWIDTH
        # draw sequence on the insert
        if base_text:  # only draw sequences if they exist i.e. not None!
            len_BT = len(base_text)
            if is_on_top:
                angle_offset = 0
            else:
                angle_offset = 180
            if len_BT > 20:
                base_text = base_text[:17] + '...'
                len_BT = len(base_text)
            fraction_arc_len_per_char = (1.0 - 2.0*_FRACTION_INSERT_TO_PAD) / (len_BT + 1)
            seq_item.setPen(QPen(Qt.NoPen))
            seq_item.setBrush(QBrush(Qt.black))

            seq_path = QPainterPath()
            loop_path = self.path()
            for i in range(len_BT):
                frac = _FRACTION_INSERT_TO_PAD + (i+1)*fraction_arc_len_per_char
                pt = loop_path.pointAtPercent(frac)
                tang_ang = loop_path.angleAtPercent(frac)

                temp_path = QPainterPath()
                # 1. draw the text
                temp_path.addText(0,0, font, base_text[i if is_on_top else -i-1])
                # 2. center it at the zero point different for top and bottom
                # strands
                if not is_on_top:
                    temp_path.translate(0, -seq_font_h - insert_w)

                temp_path.translate(QPointF(-seq_font_char_w / 2.,
                                          -2 if is_on_top else seq_font_h))

                mat = QTransform()
                # 3. rotate it
                mat.rotate(-tang_ang + angle_offset)

                rotated_path = mat.map(temp_path)
                # 4. translate the rotate object to it's position on the part
                rotated_path.translate(pt)
                seq_path.addPath(rotated_path)
            # end for
            seq_item.setPath(seq_path)
        # end if
    # end def

    ### EVENT HANDLERS ###
    def mouseDoubleClickEvent(self, event):
        """Double clicks remove the insertion/skip."""
        self._strand.changeInsertion(self._insertion.idx(), 0)

    def mousePressEvent(self, event):
        """This needs to be present for mouseDoubleClickEvent to work."""
        pass

    def labelMousePressEvent(self, event):
        """
        Pre-selects the text for editing when you click
        the label.
        """
        lbl = self._label
        lbl.setTextInteractionFlags(Qt.TextEditorInteraction)
        cursor = lbl.textCursor()
        cursor.setPosition(0)
        cursor.movePosition(QTextCursor.End, QTextCursor.KeepAnchor)
        lbl.setTextCursor(cursor)

    def textkeyPressEvent(self, event):
        """
        Must intercept invalid input events.  Make changes here
        """
        a = event.key()
        text = event.text()
        if a in [Qt.Key_Space, Qt.Key_Tab]:
            return
        elif a in [Qt.Key_Return, Qt.Key_Enter]:
            self.inputMethodEventHandler(event)
            return
        # elif unicode(text).isalpha():
        elif text.isalpha():
            return
        else:
            return QGraphicsTextItem.keyPressEvent(self._label, event)

    def inputMethodEventHandler(self, event):
        """
        This is run on the label being changed
        or losing focus
        """
        lbl = self._label
        if lbl == None:
            return
        # test = unicode(lbl.toPlainText())
        test = lbl.toPlainText()
        try:
            insertion_size = int(test)
        except:
            insertion_size = None
        insertion = self._insertion
        length = insertion.length()
        if insertion_size != None and insertion_size != length:
            self._strand.changeInsertion(insertion.idx(), insertion_size)
            if insertion.length():
                self._resetPosition()
        else:
            self._updateLabel()
        # end if
        self._focusOut()
    # end def
# end class
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
###############################################################################
#
#    Copyright (C) 2001-2014 Micronaet SRL (<http://www.micronaet.it>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as published
#    by the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
import os
import sys
import logging
import netsvc
import decimal_precision as dp
from osv import fields, osv, expression, orm
from datetime import datetime, timedelta
from tools.translate import _
from tools import (DEFAULT_SERVER_DATE_FORMAT,
    DEFAULT_SERVER_DATETIME_FORMAT,
    DATETIME_FORMATS_MAP,
    float_compare)

_logger = logging.getLogger(__name__)

class csv_base(osv.osv):
    ''' Add common function without fields/table
    '''
    _name = 'csv.base'
    _description = 'Base function'

    def get_create_partner_lite(self, cr, uid, ref, record=None, customer=True,
            context=None):
        ''' Search a partner with accounting code
            If not present create one partner with a lite record
        '''
        partner_pool = self.pool.get('res.partner')
        if customer:
            key = 'sql_customer_code'
        else:
            key = 'sql_supplier_code'

        partner_ids = partner_pool.search(cr, uid, [
            (key, '=', ref)], context=context)
        if partner_ids:
            return partner_ids[0]
        if record is None:
            record = {
                'name': 'Partner %s' % ref,
                key: ref,
                }
        _logger.warning("Create a lite partner: %s" % (record, ))
        return partner_pool.create(cr, uid, record, context=context)

    def decode_string(self, valore):
        ''' Return string value of asc passed
        '''
        if not valore:
            return ''
        valore = valore.decode('cp1252')
        valore = valore.encode('utf-8')
        return valore.strip()

    def decode_date(self, valore, with_slash=True):
        ''' Return date value of asc passed
        '''
        valore = valore.strip()
        if with_slash: # yet correct YYYY/MM/DD
            return valore or False
        else: # YYYYMMDD
            if len(valore) == 8:
                return "%s/%s/%s" % (
                    valore[:4], valore[4:6], valore[6:8])
        return False # when error

    def decode_float(self, valore):
        ''' Return float value of asc passed
        '''
        valore = valore.strip()
        if valore:
           return float(valore.replace(",", "."))
        else:
           return 0.0   # for empty values

    def decode_int(self, valore):
        ''' Return int value of asc passed
        '''
        valore = valore.strip()
        if valore:
           try:
               return int(valore)
           except:
               pass # next line:
        return False   # for empty values
csv_base()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
<commit_msg>correct import<commit_after># -*- coding: utf-8 -*-
###############################################################################
#
#    Copyright (C) 2001-2014 Micronaet SRL (<http://www.micronaet.it>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as published
#    by the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
import os
import sys
import logging
import netsvc
import decimal_precision as dp
from osv import fields, osv, expression, orm
from datetime import datetime, timedelta
from tools.translate import _
from tools import (DEFAULT_SERVER_DATE_FORMAT,
    DEFAULT_SERVER_DATETIME_FORMAT,
    DATETIME_FORMATS_MAP,
    )

_logger = logging.getLogger(__name__)

class csv_base(osv.osv):
    ''' Add common function without fields/table
    '''
    _name = 'csv.base'
    _description = 'Base function'

    def get_create_partner_lite(self, cr, uid, ref, record=None, customer=True,
            context=None):
        ''' Search a partner with accounting code
            If not present create one partner with a lite record
        '''
        partner_pool = self.pool.get('res.partner')
        if customer:
            key = 'sql_customer_code'
        else:
            key = 'sql_supplier_code'

        partner_ids = partner_pool.search(cr, uid, [
            (key, '=', ref)], context=context)
        if partner_ids:
            return partner_ids[0]
        if record is None:
            record = {
                'name': 'Partner %s' % ref,
                key: ref,
                }
        _logger.warning("Create a lite partner: %s" % (record, ))
        return partner_pool.create(cr, uid, record, context=context)

    def decode_string(self, valore):
        ''' Return string value of asc passed
        '''
        if not valore:
            return ''
        valore = valore.decode('cp1252')
        valore = valore.encode('utf-8')
        return valore.strip()

    def decode_date(self, valore, with_slash=True):
        ''' Return date value of asc passed
        '''
        valore = valore.strip()
        if with_slash: # yet correct YYYY/MM/DD
            return valore or False
        else: # YYYYMMDD
            if len(valore) == 8:
                return "%s/%s/%s" % (
                    valore[:4], valore[4:6], valore[6:8])
        return False # when error

    def decode_float(self, valore):
        ''' Return float value of asc passed
        '''
        valore = valore.strip()
        if valore:
           return float(valore.replace(",", "."))
        else:
           return 0.0   # for empty values

    def decode_int(self, valore):
        ''' Return int value of asc passed
        '''
        valore = valore.strip()
        if valore:
           try:
               return int(valore)
           except:
               pass # next line:
        return False   # for empty values
csv_base()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
<|endoftext|>


<commit_before>import sys

import json

from babbisch.client import ObjectVisitor
from babbisch.tag import parse_string
from babbisch.odict import odict

from wraplib.codegen import Codegen, CodegenBase, INDENT, DEDENT
from wraplib.pyclass import PyClass

ctypes_type_map = {
    'void': 'None',
    'signed int': 'c_int',
    'unsigned int': 'c_uint',
    'long int': 'c_long',
    'unsigned long': 'c_ulong',
    'unsigned long int': 'c_ulong',
    'long long': 'c_longlong',
    'long long int': 'c_longlong',
    'unsigned long long int': 'c_ulonglong',
    'unsigned long long': 'c_ulonglong',
    'signed char': 'c_char',
    'unsigned char': 'c_ubyte',
    'signed short': 'c_short',
    'unsigned short': 'c_ushort',
    'float': 'c_float',
    'double': 'c_double',
    'size_t': 'c_size_t',
    'int8_t': 'c_int8',
    'int16_t': 'c_int16',
    'int32_t': 'c_int32',
    'int64_t': 'c_int64',
    'uint8_t': 'c_uint8',
    'uint16_t': 'c_uint16',
    'uint32_t': 'c_uint32',
    'uint64_t': 'c_uint64',
    'wchar_t': 'c_wchar',
    'ptrdiff_t': 'c_ptrdiff_t',  # Requires definition in preamble
}

class CtypesClass(PyClass):
    def __init__(self, client, name, obj):
        PyClass.__init__(self, name)
        self.client = client
        self.obj = obj

class CtypesCompound(CtypesClass):
    def __init__(self, client, name, obj):
        CtypesClass.__init__(self, client, name, obj)
        self._build_code()

    def _build_code(self):
        members = []
        for name, obj in self.obj['members']:
            obj = self.client.resolve_object(obj)
            members.append('("%s", %s)' % (
                    name,
                    self.client.resolve_type(obj)
                    ))
        if members:
            self.epilog.append('%s._fields_ = [%s]' % (self.name, ', '.join(members)))
            self.epilog.append('')

class CtypesEnum(CodegenBase):
    def __init__(self, client, name, obj):
        self.client = client
        self.name = name
        self.obj = obj

    def generate_code(self):
        code = []
        # an enum is a c_int
        code.append('%s = c_int' % self.name)
        for name, value in self.obj['members']:
            code.append('%s = %s' % (name, value))
        code.append('')
        return code

class CtypesFunction(CodegenBase):
    def __init__(self, client, name, obj):
        self.client = client
        self.name = name
        self.obj = obj
        # resolve all argument types NOW
        self.client.resolve_type(self.obj['rettype'])
        for argtype in odict(self.obj['argtypes']).itervalues():
            self.client.resolve_type(argtype)

    def generate_code(self):
        code = []
        code.append('%s = _lib.%s' % (self.name, self.name))
        code.append('%s.restype = %s' % (
            self.name,
            self.client.resolve_type(self.obj['rettype'])
            ))
        code.append('%s.argtypes = [%s]' % (
            self.name,
            ', '.join(self.client.resolve_type(argtype) for argtype in odict(self.obj['argtypes']).itervalues())
            ))
        code.append('')
        return code

class CtypesStruct(CtypesCompound):
    def __init__(self, client, name, obj):
        CtypesCompound.__init__(self, client, name, obj)
        self.base = 'Structure'

    def _build_code(self):
        members = []
        for name, obj, bitsize in self.obj['members']:
            obj = self.client.resolve_object(obj)
            if bitsize is not None:
                members.append('("%s", %s, %d)' % (
                        name,
                        self.client.resolve_type(obj),
                        bitsize
                        ))
            else:
                members.append('("%s", %s)' % (
                        name,
                        self.client.resolve_type(obj)
                        ))
        if members:
            self.epilog.append('%s._fields_ = [%s]' % (self.name, ', '.join(members)))
            self.epilog.append('')

class CtypesUnion(CtypesCompound):
    def __init__(self, client, name, obj):
        CtypesCompound.__init__(self, client, name, obj)
        self.base = 'Union'

class CtypesTypedef(CodegenBase):
    def __init__(self, client, name, obj):
        self.client = client
        self.name = name
        self.obj = obj

        target = self.client.resolve_type(obj['target'])
        self.code = '%s = %s' % (obj['tag'], target)

    def generate_code(self):
        return self.code

def anon_namegen():
    i = 0
    while True:
        yield 'anon%d' % i
        i += 1

class CtypesClient(ObjectVisitor):
    def __init__(self, objects, libname):
        self.objects = objects
        self.libname = libname

        self.anon_namegen = anon_namegen()

        self.wrappers = ctypes_type_map.copy() # tag: Python name
        self.wrapper_classes = odict() # Python name: Wrapper class

        self.prolog = []
        self.epilog = []

        self._build_prolog()

    def format_name(self, name):
        if name == '!None':
            return self.anon_namegen.next()
        else:
            return name

    def _build_prolog(self):
        self.prolog.extend([
                '# generated by babbisch_ctypes'
                '',
                'import ctypes',
                'from ctypes import *',
                'from ctypes.util import find_library',
                '',
                '_libpath = find_library("%s")' % self.libname,
                'if _libpath is None:',
                INDENT,
                'raise RuntimeError("Couldn\'t find library %s")' % self.libname,
                DEDENT,
                '',
                '_lib = ctypes.CDLL(_libpath)',
                '',
                ]
                )

    def add_wrapper_class(self, tag, pycls):
        self.wrapper_classes[pycls.name] = pycls
        self.wrappers[tag] = pycls.name

    def visit_all(self):
        self.visit_objects(self.objects)

    def generate_code(self):
        return (self.prolog
                + [c.generate_code() for c in self.wrapper_classes.itervalues()]
                + self.epilog)

    def resolve_object(self, type):
        if isinstance(type, basestring):
            return self.objects[type]
        else:
            return type

    def add_type(self, type):
        klass = type['class']
        tag = type['tag']
        if klass == 'Pointer':
            # it's a new pointer type!
            target = self.resolve_type(type['type'])
            if target.startswith('CFUNCTYPE'): # it's a CFUNCTYPE.
                # function pointers in ctypes are not POINTER(CFUNCTYPE(...)),
                # but just CFUNCTYPE.
                self.wrappers[tag] = target
            elif target == 'c_char':
                # it's a char array = a string.
                self.wrappers[tag] = 'c_char_p'
            else:
                self.wrappers[tag] = 'POINTER(%s)' % target
        elif klass == 'Struct':
            # it's a struct, I suggest it's unnamed?
            self.visit_Struct(type)
        elif klass == 'Union':
            # it's an unnamed union
            self.visit_Union(type)
        elif klass == 'Array':
            # it's a new array type!
            arrtype = self.resolve_type(type['type'])
            if arrtype == 'c_char':
                # it's a char array = a string.
                type = 'c_char_p'
            elif type['size'] is None:
                type = 'POINTER(%s)' % arrtype
            else:
                type = '%s * %d' % (arrtype, type['size'])
            self.wrappers[tag] = type
        elif klass == 'FunctionType':
            pytype = 'CFUNCTYPE(%s)' % ', '.join(map(self.resolve_type, [type['rettype']] + type['argtypes']))
            self.wrappers[type['tag']] = pytype
        else:
            assert 0, "OH NO, what is that? %r" % type

    def resolve_type(self, type):
        if isinstance(type, basestring):
            # just a tag passed, let's hope it's already wrapped
            tag = type
        else:
            tag = type['tag']
            if tag not in self.wrappers:
                self.add_type(type)
        return self.wrappers[tag]

    def visit_Function(self, obj):
        name = obj['tag']
        # don't wrap functions with the "static" storage type
        if 'static' in obj['storage']:
            return
        wrapper = CtypesFunction(self, name, obj)
        self.add_wrapper_class(name, wrapper)

    def visit_Struct(self, obj):
        modifier, args = parse_string(obj['tag'])
        assert modifier == 'STRUCT'
        assert len(args) == 1
        name = 'struct_%s' % self.format_name(args[0])
        pycls = CtypesStruct(self, name, obj)
        self.add_wrapper_class(obj['tag'], pycls)

    def visit_Union(self, obj):
        modifier, args = parse_string(obj['tag'])
        assert modifier == 'UNION'
        assert len(args) == 1
        name = 'union_%s' % self.format_name(args[0])
        pycls = CtypesUnion(self, name, obj)
        self.add_wrapper_class(obj['tag'], pycls)

    def visit_Enum(self, obj):
        modifier, args = parse_string(obj['tag'])
        assert modifier == 'ENUM'
        assert len(args) == 1
        name = 'enum_%s' % self.format_name(args[0])
        wrapper = CtypesEnum(self, name, obj)
        self.add_wrapper_class(obj['tag'], wrapper)

    def visit_Typedef(self, obj):
        wrapper = CtypesTypedef(self, obj['tag'], obj)
        self.add_wrapper_class(obj['tag'], wrapper)

def code(c):
    return Codegen()(c.generate_code()).buf

with open(sys.argv[1], 'r') as f:
    visitor = CtypesClient(odict(json.load(f)), sys.argv[2])
    visitor.visit_all()
    print code(visitor)
<commit_msg>ctypes client: added support for __all__<commit_after>import sys

import json

from babbisch.client import ObjectVisitor
from babbisch.tag import parse_string
from babbisch.odict import odict

from wraplib.codegen import Codegen, CodegenBase, INDENT, DEDENT
from wraplib.pyclass import PyClass

ctypes_type_map = {
    'void': 'None',
    'signed int': 'c_int',
    'unsigned int': 'c_uint',
    'long int': 'c_long',
    'unsigned long': 'c_ulong',
    'unsigned long int': 'c_ulong',
    'long long': 'c_longlong',
    'long long int': 'c_longlong',
    'unsigned long long int': 'c_ulonglong',
    'unsigned long long': 'c_ulonglong',
    'signed char': 'c_char',
    'unsigned char': 'c_ubyte',
    'signed short': 'c_short',
    'unsigned short': 'c_ushort',
    'float': 'c_float',
    'double': 'c_double',
    'size_t': 'c_size_t',
    'int8_t': 'c_int8',
    'int16_t': 'c_int16',
    'int32_t': 'c_int32',
    'int64_t': 'c_int64',
    'uint8_t': 'c_uint8',
    'uint16_t': 'c_uint16',
    'uint32_t': 'c_uint32',
    'uint64_t': 'c_uint64',
    'wchar_t': 'c_wchar',
    'ptrdiff_t': 'c_ptrdiff_t',  # Requires definition in preamble
}

class CtypesClass(PyClass):
    def __init__(self, client, name, obj):
        PyClass.__init__(self, name)
        self.client = client
        self.obj = obj

class CtypesCompound(CtypesClass):
    def __init__(self, client, name, obj):
        CtypesClass.__init__(self, client, name, obj)
        self._build_code()

    def _build_code(self):
        members = []
        for name, obj in self.obj['members']:
            obj = self.client.resolve_object(obj)
            members.append('("%s", %s)' % (
                    name,
                    self.client.resolve_type(obj)
                    ))
        if members:
            self.epilog.append('%s._fields_ = [%s]' % (self.name, ', '.join(members)))
            self.epilog.append('')

class CtypesEnum(CodegenBase):
    def __init__(self, client, name, obj):
        self.client = client
        self.name = name
        self.obj = obj

    def generate_code(self):
        code = []
        # an enum is a c_int
        code.append('%s = c_int' % self.name)
        for name, value in self.obj['members']:
            code.append('%s = %s' % (name, value))
        code.append('')
        return code

class CtypesFunction(CodegenBase):
    def __init__(self, client, name, obj):
        self.client = client
        self.name = name
        self.obj = obj
        # resolve all argument types NOW
        self.client.resolve_type(self.obj['rettype'])
        for argtype in odict(self.obj['argtypes']).itervalues():
            self.client.resolve_type(argtype)

    def generate_code(self):
        code = []
        code.append('%s = _lib.%s' % (self.name, self.name))
        code.append('%s.restype = %s' % (
            self.name,
            self.client.resolve_type(self.obj['rettype'])
            ))
        code.append('%s.argtypes = [%s]' % (
            self.name,
            ', '.join(self.client.resolve_type(argtype) for argtype in odict(self.obj['argtypes']).itervalues())
            ))
        code.append('')
        return code

class CtypesStruct(CtypesCompound):
    def __init__(self, client, name, obj):
        CtypesCompound.__init__(self, client, name, obj)
        self.base = 'Structure'

    def _build_code(self):
        members = []
        for name, obj, bitsize in self.obj['members']:
            obj = self.client.resolve_object(obj)
            if bitsize is not None:
                members.append('("%s", %s, %d)' % (
                        name,
                        self.client.resolve_type(obj),
                        bitsize
                        ))
            else:
                members.append('("%s", %s)' % (
                        name,
                        self.client.resolve_type(obj)
                        ))
        if members:
            self.epilog.append('%s._fields_ = [%s]' % (self.name, ', '.join(members)))
            self.epilog.append('')

class CtypesUnion(CtypesCompound):
    def __init__(self, client, name, obj):
        CtypesCompound.__init__(self, client, name, obj)
        self.base = 'Union'

class CtypesTypedef(CodegenBase):
    def __init__(self, client, name, obj):
        self.client = client
        self.name = name
        self.obj = obj

        target = self.client.resolve_type(obj['target'])
        self.code = '%s = %s' % (obj['tag'], target)

    def generate_code(self):
        return self.code

def anon_namegen():
    i = 0
    while True:
        yield 'anon%d' % i
        i += 1

class CtypesClient(ObjectVisitor):
    def __init__(self, objects, libname):
        self.objects = objects
        self.libname = libname

        self.anon_namegen = anon_namegen()

        self.wrappers = ctypes_type_map.copy() # tag: Python name
        self.wrapper_classes = odict() # Python name: Wrapper class

        self.prolog = []
        self.epilog = []
        self.all_names = []

        self._build_prolog()

    def format_name(self, name):
        if name == '!None':
            return self.anon_namegen.next()
        else:
            return name

    def _build_prolog(self):
        self.prolog.extend([
                '# generated by babbisch_ctypes'
                '',
                'import ctypes',
                'from ctypes import *',
                'from ctypes.util import find_library',
                '',
                '_libpath = find_library("%s")' % self.libname,
                'if _libpath is None:',
                INDENT,
                'raise RuntimeError("Couldn\'t find library %s")' % self.libname,
                DEDENT,
                '',
                '_lib = ctypes.CDLL(_libpath)',
                '',
                ]
                )

    def add_wrapper_class(self, tag, pycls):
        self.wrapper_classes[pycls.name] = pycls
        self.set_wrapper(tag, pycls.name)
        self.export_name(pycls.name)

    def set_wrapper(self, tag, name):
        self.wrappers[tag] = name

    def export_name(self, name):
        self.all_names.append(name)

    def visit_all(self):
        self.visit_objects(self.objects)

    def generate_code(self):
        return (self.prolog
                + [c.generate_code() for c in self.wrapper_classes.itervalues()]
                + ['__all__ = [%s]' % (', '.join("'%s'" % n for n in self.all_names))]
                + self.epilog)

    def resolve_object(self, type):
        if isinstance(type, basestring):
            return self.objects[type]
        else:
            return type

    def add_type(self, type):
        klass = type['class']
        tag = type['tag']
        if klass == 'Pointer':
            # it's a new pointer type!
            target = self.resolve_type(type['type'])
            if target.startswith('CFUNCTYPE'): # it's a CFUNCTYPE.
                # function pointers in ctypes are not POINTER(CFUNCTYPE(...)),
                # but just CFUNCTYPE.
                self.set_wrapper(tag, target)
            elif target == 'c_char':
                # it's a char array = a string.
                self.set_wrapper(tag, 'c_char_p')
            else:
                self.set_wrapper(tag, 'POINTER(%s)' % target)
        elif klass == 'Struct':
            # it's a struct, I suggest it's unnamed?
            self.visit_Struct(type)
        elif klass == 'Union':
            # it's an unnamed union
            self.visit_Union(type)
        elif klass == 'Array':
            # it's a new array type!
            arrtype = self.resolve_type(type['type'])
            if arrtype == 'c_char':
                # it's a char array = a string.
                type = 'c_char_p'
            elif type['size'] is None:
                type = 'POINTER(%s)' % arrtype
            else:
                type = '%s * %d' % (arrtype, type['size'])
            self.set_wrapper(tag, type)
        elif klass == 'FunctionType':
            pytype = 'CFUNCTYPE(%s)' % ', '.join(map(self.resolve_type, [type['rettype']] + type['argtypes']))
            self.set_wrapper(type['tag'], pytype)
        else:
            assert 0, "OH NO, what is that? %r" % type

    def resolve_type(self, type):
        if isinstance(type, basestring):
            # just a tag passed, let's hope it's already wrapped
            tag = type
        else:
            tag = type['tag']
            if tag not in self.wrappers:
                self.add_type(type)
        return self.wrappers[tag]

    def visit_Function(self, obj):
        name = obj['tag']
        # don't wrap functions with the "static" storage type
        if 'static' in obj['storage']:
            return
        wrapper = CtypesFunction(self, name, obj)
        self.add_wrapper_class(name, wrapper)

    def visit_Struct(self, obj):
        modifier, args = parse_string(obj['tag'])
        assert modifier == 'STRUCT'
        assert len(args) == 1
        name = 'struct_%s' % self.format_name(args[0])
        pycls = CtypesStruct(self, name, obj)
        self.add_wrapper_class(obj['tag'], pycls)

    def visit_Union(self, obj):
        modifier, args = parse_string(obj['tag'])
        assert modifier == 'UNION'
        assert len(args) == 1
        name = 'union_%s' % self.format_name(args[0])
        pycls = CtypesUnion(self, name, obj)
        self.add_wrapper_class(obj['tag'], pycls)

    def visit_Enum(self, obj):
        modifier, args = parse_string(obj['tag'])
        assert modifier == 'ENUM'
        assert len(args) == 1
        name = 'enum_%s' % self.format_name(args[0])
        wrapper = CtypesEnum(self, name, obj)
        self.add_wrapper_class(obj['tag'], wrapper)

    def visit_Typedef(self, obj):
        wrapper = CtypesTypedef(self, obj['tag'], obj)
        self.add_wrapper_class(obj['tag'], wrapper)

def code(c):
    return Codegen()(c.generate_code()).buf

with open(sys.argv[1], 'r') as f:
    visitor = CtypesClient(odict(json.load(f)), sys.argv[2])
    visitor.visit_all()
    print code(visitor)
<|endoftext|>


<commit_before>import os

from catalogService import errors
from catalogService.rest import baseDriver
from catalogService.rest.models import images
from catalogService.rest.models import instances

NovaAPI = None
xenprov = None
try:
    import novaclient
    from glance.client import Client
except ImportError:
    pass

class OpenStack_Image(images.BaseImage):
    "OpenStack Image"

# This is return by the api
class OpenStack_InstanceTypes(instances.InstanceTypes):
    "OpenStack Instance Types"

    idMap = [
        ('xenent.small', "Small"),
        ('xenent.medium', "Medium"),
    ]

# Nova address
# Nova port
# Glance address (until apis are integrated)
# Glance port
_configurationDescriptorXmlData = """<?xml version='1.0' encoding='UTF-8'?>
<descriptor xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.rpath.org/permanent/descriptor-1.0.xsd descriptor-1.0.xsd">
  <metadata>
    <displayName>OpenStack Configuration</displayName>
    <descriptions>
      <desc>Configure OpenStack</desc>
    </descriptions>
  </metadata>
  <dataFields>
    <field>
      <name>nova_server</name>
      <descriptions>
        <desc>Nova Server</desc>
      </descriptions>
      <type>str</type>
      <required>true</required>
      <help href='configuration/novaServerName.html'/>
    </field>
    <field>
      <name>nova_port</name>
      <descriptions>
        <desc>Nova Port</desc>
      </descriptions>
      <type>str</type>
      <required>true</required>
      <help href='configuration/novaPortNumber.html'/>
    </field>
    <field>
      <name>glance_server</name>
      <descriptions>
        <desc>Glance Server</desc>
      </descriptions>
      <type>str</type>
      <required>true</required>
      <help href='configuration/glanceServerName.html'/>
    </field>
    <field>
      <name>glance_port</name>
      <descriptions>
        <desc>Glance Port</desc>
      </descriptions>
      <type>str</type>
      <required>true</required>
      <help href='configuration/glancePortNumber.html'/>
    </field>
      <name>alias</name>
      <descriptions>
        <desc>Name</desc>
      </descriptions>
      <type>str</type>
      <required>true</required>
      <help href='configuration/alias.html'/>
    </field>
    <field>
      <name>description</name>
      <descriptions>
        <desc>Full Description</desc>
      </descriptions>
      <type>str</type>
      <required>true</required>
      <help href='configuration/description.html'/>
    </field>
  </dataFields>
</descriptor>"""

# User Name
# Auth Token
_credentialsDescriptorXmlData = """<?xml version='1.0' encoding='UTF-8'?>
<descriptor xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.rpath.org/permanent/descriptor-1.0.xsd descriptor-1.0.xsd">
  <metadata>
    <displayName>Xen Enterprise User Credentials</displayName>
    <descriptions>
      <desc>User Credentials for Xen Enterprise</desc>
    </descriptions>
  </metadata>
  <dataFields>
    <field>
      <name>username</name>
      <descriptions>
        <desc>User Name</desc>
      </descriptions>
      <type>str</type>
      <constraints>
        <descriptions>
          <desc>Field must contain between 1 and 32 characters</desc>
        </descriptions>
        <length>255</length>
      </constraints>
      <required>true</required>
    </field>
    <field>
      <name>auth_token</name>
      <descriptions>
        <desc>Auth Token</desc>
      </descriptions>
      <type>str</type>
      <constraints>
        <descriptions>
          <desc>Field must contain between 1 and 32 characters</desc>
        </descriptions>
        <length>32</length>
      </constraints>
      <required>true</required>
      <password>true</password>
    </field>
  </dataFields>
</descriptor>
"""

class ConsolidatedClients(object):
    def __inst__(self, nova_client, glance_client):
        self.nova = nova_client
        self.glance = glance_client

class OpenStackClient(baseDriver.BaseDriver):
    Image = OpenStack_Image
    cloudType = 'openstack'

    configurationDescriptorXmlData = _configurationDescriptorXmlData
    credentialsDescriptorXmlData = _credentialsDescriptorXmlData

    RBUILDER_BUILD_TYPE = 'XEN_OVA'  # TODO: Determin appropriate rBuilder image type

    @classmethod
    def isDriverFunctional(cls):
        if not novaclient or not Client: #nova and glance clients
            return False
        return True

    # Right now 1.1 is the only version that is supported
    def _openstack_api_version(self):
        return 'v1.1'

    def drvCreateCloudClient(self, credentials):
        cloudConfig = self.getTargetConfiguration()
        server = cloudConfig.nova_server
        port = cloudConfig.nova_port
        glance_server = cloudConfig.glance_server
        glance_port = cloudConfig.glance_port
        api_version = self._openstack_api_version()
        try:
            # password is a ProtectedString, we have to convert to string
            nova_client = novaclient.OpenStack( credentials['username'],
                                            credentials['auth_token'],
                                            "http://%s:%s/%s/" %
                                            (server, port, api_version) )
            glance_client = Client(glance_server, glance_port)
            clients = ConsolidatedClients(nova_client, glance_client)
        # TODO: determine more specific list of exceptions to catch
        except:
            raise errors.PermissionDenied(message = \
                    "There was an error initializing Nova and Glance clients")
        return clients

    def drvVerifyCloudConfiguration(self, config):
        return

    def terminateInstances(self, instanceIds):
        running_instances = self.getInstances(instanceIds)
        for server in running_instances:
            server.delete() # there is no terminate method in novaclient

        insts = instances.BaseInstances()
        insts.extend(running_instances)
        # Set state
        for inst in insts:
            inst.setState("Terminating")
        return insts

    def terminateInstance(self, instanceId):
        return self.terminateInstances([instanceId])

    def _get_flavors(self):
        client = self.client.nova
        return client.flavors.list()

    # TODO: figure this out.  It is an option launch param.
    def _get_ipgroups(self):
        client = self.client.nova
        return client.ipgroup.list()

    # This also takes optional "ipgroup", "meta", and "files",
    # see novaclient/servers.py, ignoring for now.  TODO: really ignore?
    def drvPopulateLaunchDescriptor(self, descr):
        descr.setDisplayName("OpenStack Launch Parameters")
        descr.addDescription("OpenStack Launch Parameters")
        self.drvLaunchDescriptorCommonFields(descr)
        flavors = self._get_flavors()
        if not flavors:
            raise errors.CatalogError("No instance flavors defined")
        flavor_id_name_map = dict( (f.id, f.name) for f in flavors)
        flavor_id_name_map.keys().sort()
        descr.addDataField("flavor",
            descriptions = "Flavor",
            required = True,
            help = [
                ("launch/flavors.html", None)
            ],
            type = descr.EnumeratedType(
                descr.ValueWithDescription(id, descriptions = flavor_id_name_map[id])
                for x in flavor_id_name_map.keys()),
            default = flavor_id_name_map.keys()[0],
            )

        return descr

    # TODO: remove when novaclient has caught up to v1.1.
    # This pulls a resource id from from a resource ref url
    def _get_id_from_ref(self, resource_ref):
        return resource_ref.split('/')[-1]

    def drvGetInstances(self, instanceIds):
        client = self.client.nova
        cloudAlias = self.getCloudAlias()
        instanceList = instances.BaseInstances()
        for server in client.servers.list():

            instanceId = server.id
            image_id = self._get_id_from_ref(server.imageRef)

            inst = self._nodeFactory.newInstance(id = instanceId,
                imageId = image_id or 'UNKNOWN',
                instanceId = instanceId,
                instanceName = server.name,
                instanceDescription = 'UNDEFINED',
                reservationId = server.id, # Does this have an openstack equivalent
                dnsName = 'UNKNOWN',
                publicDnsName = ",".join(server.addresses['public']), # valid?
                privateDnsName = ",".join(server.addresses['private']), # valid?
                state = server.status,
                launchTime = server.created if hasattr(server, 'created') else 'UNKNOWN',
                cloudName = self.cloudName,
                cloudAlias = cloudAlias)

            instanceList.append(inst)
        instanceList.sort(key = lambda x: (x.getState(), x.getInstanceId()))
        return self.filterInstances(instanceIds, instanceList)

    #### PROGRESS INCOMPLETE THROUGH HERE ####

    def getLaunchInstanceParameters(self, image, descriptorData):
        params = baseDriver.BaseDriver.getLaunchInstanceParameters(self,
            image, descriptorData)
        getField = descriptorData.getField
        srUuid = getField('storageRepository')
        params['srUuid'] = srUuid
        return params

    def launchInstanceProcess(self, job, image, auth, **launchParams):
        ppop = launchParams.pop
        srUuid = ppop('srUuid')
        instanceName = ppop('instanceName')
        instanceDescription = ppop('instanceDescription')

        cloudConfig = self.getTargetConfiguration()
        nameLabel = image.getLongName()
        nameDescription = image.getBuildDescription()

        if not image.getIsDeployed():
            self._deployImage(job, image, auth, srUuid)

        imageId = image.getInternalTargetId()

        job.addHistoryEntry('Cloning template')
        realId = self.cloneTemplate(job, imageId, instanceName,
            instanceDescription)
        job.addHistoryEntry('Attaching credentials')
        try:
            self._attachCredentials(realId, srUuid)
        except Exception, e:
            self.log_exception("Exception attaching credentials: %s" % e)
        job.addHistoryEntry('Launching')
        self.startVm(realId)
        return self.client.xenapi.VM.get_uuid(realId)

    def getImagesFromTarget(self, imageIdsFilter):
        cloudAlias = self.getCloudAlias()
        instMap  = self.client.xenapi.VM.get_all_records()

        imageList = images.BaseImages()

        for vmRef, vm in instMap.items():
            if not vm['is_a_template']:
                continue

            imgChecksum = vm['other_config'].get('cloud-catalog-checksum')
            if imgChecksum:
                is_rBuilderImage = True
                imageId = imgChecksum
            else:
                is_rBuilderImage = False
                imageId = vm['uuid']

            if imageIdsFilter is not None and imageId not in imageIdsFilter:
                continue

            image = self._nodeFactory.newImage(id = imageId,
                    imageId = imageId, isDeployed = True,
                    is_rBuilderImage = is_rBuilderImage,
                    longName = vm['name_label'],
                    buildDescription = vm['name_description'],
                    cloudName = self.cloudName,
                    internalTargetId = vm['uuid'],
                    cloudAlias = cloudAlias)
            imageList.append(image)
        return imageList

    def cloneTemplate(self, job, imageId, instanceName, instanceDescription):
        client = self.client
        vmTemplateRef = self._cachedGet(imageId, client.xenapi.VM.get_by_uuid)
        imageId = os.path.basename(imageId)

        vmRef = client.xenapi.VM.clone(vmTemplateRef,
            instanceName)
        client.xenapi.VM.set_name_description(vmRef, instanceDescription)
        self._setVmMetadata(vmRef, templateUuid = imageId)

        # Get all physical interfaces
        pifs = client.xenapi.PIF.get_all_records()
        # Grab the lowest device (eth0)
        lowest = min((v['device'], k) for k, v in pifs.items())[1]

        networkRef = client.xenapi.PIF.get_network(lowest)

        self.addVIFtoVM(vmRef, networkRef)

        # Generate credentials image here
        return vmRef

    def startVm(self, vmRef):
        client = self.client
        client.xenapi.VM.provision(vmRef)
        startPaused = False
        force = False
        client.xenapi.VM.start(vmRef, startPaused, force)

    def addVIFtoVM(self, vmRef, networkRef):
        vifRec = {
            'device' : '0',
            'network' : networkRef,
            'VM' : vmRef,
            'MAC' : '',
            'MTU' : '1500',
            'qos_algorithm_type' : '',
            'qos_algorithm_params' : {},
            'other_config' : {},
        }
        try:
            self.client.xenapi.VIF.create(vifRec)
        except Exception, e:
            if e.details[0] != 'DEVICE_ALREADY_EXISTS':
                raise
<commit_msg>Commenting out instance types, adding to comments..<commit_after>import os

from catalogService import errors
from catalogService.rest import baseDriver
from catalogService.rest.models import images
from catalogService.rest.models import instances

NovaAPI = None
xenprov = None
try:
    import novaclient
    from glance.client import Client
except ImportError:
    pass

class OpenStack_Image(images.BaseImage):
    "OpenStack Image"

# This is provided by the nova api
#class OpenStack_InstanceTypes(instances.InstanceTypes):
#    "OpenStack Instance Types"
#
#    idMap = [
#        ('xenent.small', "Small"),
#        ('xenent.medium', "Medium"),
#    ]

# Nova address
# Nova port
# Glance address (until apis are integrated)
# Glance port
_configurationDescriptorXmlData = """<?xml version='1.0' encoding='UTF-8'?>
<descriptor xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.rpath.org/permanent/descriptor-1.0.xsd descriptor-1.0.xsd">
  <metadata>
    <displayName>OpenStack Configuration</displayName>
    <descriptions>
      <desc>Configure OpenStack</desc>
    </descriptions>
  </metadata>
  <dataFields>
    <field>
      <name>nova_server</name>
      <descriptions>
        <desc>Nova Server</desc>
      </descriptions>
      <type>str</type>
      <required>true</required>
      <help href='configuration/novaServerName.html'/>
    </field>
    <field>
      <name>nova_port</name>
      <descriptions>
        <desc>Nova Port</desc>
      </descriptions>
      <type>str</type>
      <required>true</required>
      <help href='configuration/novaPortNumber.html'/>
    </field>
    <field>
      <name>glance_server</name>
      <descriptions>
        <desc>Glance Server</desc>
      </descriptions>
      <type>str</type>
      <required>true</required>
      <help href='configuration/glanceServerName.html'/>
    </field>
    <field>
      <name>glance_port</name>
      <descriptions>
        <desc>Glance Port</desc>
      </descriptions>
      <type>str</type>
      <required>true</required>
      <help href='configuration/glancePortNumber.html'/>
    </field>
      <name>alias</name>
      <descriptions>
        <desc>Name</desc>
      </descriptions>
      <type>str</type>
      <required>true</required>
      <help href='configuration/alias.html'/>
    </field>
    <field>
      <name>description</name>
      <descriptions>
        <desc>Full Description</desc>
      </descriptions>
      <type>str</type>
      <required>true</required>
      <help href='configuration/description.html'/>
    </field>
  </dataFields>
</descriptor>"""

# User Name
# Auth Token
_credentialsDescriptorXmlData = """<?xml version='1.0' encoding='UTF-8'?>
<descriptor xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.rpath.org/permanent/descriptor-1.0.xsd descriptor-1.0.xsd">
  <metadata>
    <displayName>Xen Enterprise User Credentials</displayName>
    <descriptions>
      <desc>User Credentials for Xen Enterprise</desc>
    </descriptions>
  </metadata>
  <dataFields>
    <field>
      <name>username</name>
      <descriptions>
        <desc>User Name</desc>
      </descriptions>
      <type>str</type>
      <constraints>
        <descriptions>
          <desc>Field must contain between 1 and 32 characters</desc>
        </descriptions>
        <length>255</length>
      </constraints>
      <required>true</required>
    </field>
    <field>
      <name>auth_token</name>
      <descriptions>
        <desc>Auth Token</desc>
      </descriptions>
      <type>str</type>
      <constraints>
        <descriptions>
          <desc>Field must contain between 1 and 32 characters</desc>
        </descriptions>
        <length>32</length>
      </constraints>
      <required>true</required>
      <password>true</password>
    </field>
  </dataFields>
</descriptor>
"""

# http://glance.openstack.org/client.html
# http://pypi.python.org/pypi/python-novaclient
class ConsolidatedClients(object):
    def __inst__(self, nova_client, glance_client):
        self.nova = nova_client
        self.glance = glance_client

class OpenStackClient(baseDriver.BaseDriver):
    Image = OpenStack_Image
    cloudType = 'openstack'

    configurationDescriptorXmlData = _configurationDescriptorXmlData
    credentialsDescriptorXmlData = _credentialsDescriptorXmlData

    RBUILDER_BUILD_TYPE = 'XEN_OVA'  # TODO: Determin appropriate rBuilder image type

    @classmethod
    def isDriverFunctional(cls):
        if not novaclient or not Client: #nova and glance clients
            return False
        return True

    # Right now 1.1 is the only version that is supported
    def _openstack_api_version(self):
        return 'v1.1'

    def drvCreateCloudClient(self, credentials):
        cloudConfig = self.getTargetConfiguration()
        server = cloudConfig.nova_server
        port = cloudConfig.nova_port
        glance_server = cloudConfig.glance_server
        glance_port = cloudConfig.glance_port
        api_version = self._openstack_api_version()
        try:
            # password is a ProtectedString, we have to convert to string
            nova_client = novaclient.OpenStack( credentials['username'],
                                            credentials['auth_token'],
                                            "http://%s:%s/%s/" %
                                            (server, port, api_version) )
            glance_client = Client(glance_server, glance_port)
            clients = ConsolidatedClients(nova_client, glance_client)
        # TODO: determine more specific list of exceptions to catch
        except:
            raise errors.PermissionDenied(message = \
                    "There was an error initializing Nova and Glance clients")
        return clients

    def drvVerifyCloudConfiguration(self, config):
        return

    def terminateInstances(self, instanceIds):
        running_instances = self.getInstances(instanceIds)
        for server in running_instances:
            server.delete() # there is no terminate method in novaclient

        insts = instances.BaseInstances()
        insts.extend(running_instances)
        # Set state
        for inst in insts:
            inst.setState("Terminating")
        return insts

    def terminateInstance(self, instanceId):
        return self.terminateInstances([instanceId])

    def _get_flavors(self):
        client = self.client.nova
        return client.flavors.list()

    # TODO: figure this out.  It is an option launch param.
    def _get_ipgroups(self):
        client = self.client.nova
        return client.ipgroup.list()

    # This also takes optional "ipgroup", "meta", and "files",
    # see novaclient/servers.py, ignoring for now.  TODO: really ignore?
    def drvPopulateLaunchDescriptor(self, descr):
        descr.setDisplayName("OpenStack Launch Parameters")
        descr.addDescription("OpenStack Launch Parameters")
        self.drvLaunchDescriptorCommonFields(descr)
        flavors = self._get_flavors()
        if not flavors:
            raise errors.CatalogError("No instance flavors defined")
        flavor_id_name_map = dict( (f.id, f.name) for f in flavors)
        flavor_id_name_map.keys().sort()
        descr.addDataField("flavor",
            descriptions = "Flavor",
            required = True,
            help = [
                ("launch/flavors.html", None)
            ],
            type = descr.EnumeratedType(
                descr.ValueWithDescription(id, descriptions = flavor_id_name_map[id])
                for x in flavor_id_name_map.keys()),
            default = flavor_id_name_map.keys()[0],
            )

        return descr

    # TODO: remove when novaclient has caught up to v1.1.
    # This pulls a resource id from from a resource ref url
    def _get_id_from_ref(self, resource_ref):
        return resource_ref.split('/')[-1]

    def drvGetInstances(self, instanceIds):
        client = self.client.nova
        cloudAlias = self.getCloudAlias()
        instanceList = instances.BaseInstances()
        for server in client.servers.list():

            instanceId = server.id
            image_id = self._get_id_from_ref(server.imageRef)

            inst = self._nodeFactory.newInstance(id = instanceId,
                imageId = image_id or 'UNKNOWN',
                instanceId = instanceId,
                instanceName = server.name,
                instanceDescription = 'UNDEFINED',
                reservationId = server.id, # Does this have an openstack equivalent
                dnsName = 'UNKNOWN',
                publicDnsName = ",".join(server.addresses['public']), # valid?
                privateDnsName = ",".join(server.addresses['private']), # valid?
                state = server.status,
                launchTime = server.created if hasattr(server, 'created') else 'UNKNOWN',
                cloudName = self.cloudName,
                cloudAlias = cloudAlias)

            instanceList.append(inst)
        instanceList.sort(key = lambda x: (x.getState(), x.getInstanceId()))
        return self.filterInstances(instanceIds, instanceList)

    #### PROGRESS INCOMPLETE THROUGH HERE ####

    def getLaunchInstanceParameters(self, image, descriptorData):
        params = baseDriver.BaseDriver.getLaunchInstanceParameters(self,
            image, descriptorData)
        getField = descriptorData.getField
        srUuid = getField('storageRepository')
        params['srUuid'] = srUuid
        return params

    def launchInstanceProcess(self, job, image, auth, **launchParams):
        ppop = launchParams.pop
        srUuid = ppop('srUuid')
        instanceName = ppop('instanceName')
        instanceDescription = ppop('instanceDescription')

        cloudConfig = self.getTargetConfiguration()
        nameLabel = image.getLongName()
        nameDescription = image.getBuildDescription()

        if not image.getIsDeployed():
            self._deployImage(job, image, auth, srUuid)

        imageId = image.getInternalTargetId()

        job.addHistoryEntry('Cloning template')
        realId = self.cloneTemplate(job, imageId, instanceName,
            instanceDescription)
        job.addHistoryEntry('Attaching credentials')
        try:
            self._attachCredentials(realId, srUuid)
        except Exception, e:
            self.log_exception("Exception attaching credentials: %s" % e)
        job.addHistoryEntry('Launching')
        self.startVm(realId)
        return self.client.xenapi.VM.get_uuid(realId)

    def getImagesFromTarget(self, imageIdsFilter):
        cloudAlias = self.getCloudAlias()
        instMap  = self.client.xenapi.VM.get_all_records()

        imageList = images.BaseImages()

        for vmRef, vm in instMap.items():
            if not vm['is_a_template']:
                continue

            imgChecksum = vm['other_config'].get('cloud-catalog-checksum')
            if imgChecksum:
                is_rBuilderImage = True
                imageId = imgChecksum
            else:
                is_rBuilderImage = False
                imageId = vm['uuid']

            if imageIdsFilter is not None and imageId not in imageIdsFilter:
                continue

            image = self._nodeFactory.newImage(id = imageId,
                    imageId = imageId, isDeployed = True,
                    is_rBuilderImage = is_rBuilderImage,
                    longName = vm['name_label'],
                    buildDescription = vm['name_description'],
                    cloudName = self.cloudName,
                    internalTargetId = vm['uuid'],
                    cloudAlias = cloudAlias)
            imageList.append(image)
        return imageList

    def cloneTemplate(self, job, imageId, instanceName, instanceDescription):
        client = self.client
        vmTemplateRef = self._cachedGet(imageId, client.xenapi.VM.get_by_uuid)
        imageId = os.path.basename(imageId)

        vmRef = client.xenapi.VM.clone(vmTemplateRef,
            instanceName)
        client.xenapi.VM.set_name_description(vmRef, instanceDescription)
        self._setVmMetadata(vmRef, templateUuid = imageId)

        # Get all physical interfaces
        pifs = client.xenapi.PIF.get_all_records()
        # Grab the lowest device (eth0)
        lowest = min((v['device'], k) for k, v in pifs.items())[1]

        networkRef = client.xenapi.PIF.get_network(lowest)

        self.addVIFtoVM(vmRef, networkRef)

        # Generate credentials image here
        return vmRef

    def startVm(self, vmRef):
        client = self.client
        client.xenapi.VM.provision(vmRef)
        startPaused = False
        force = False
        client.xenapi.VM.start(vmRef, startPaused, force)

    def addVIFtoVM(self, vmRef, networkRef):
        vifRec = {
            'device' : '0',
            'network' : networkRef,
            'VM' : vmRef,
            'MAC' : '',
            'MTU' : '1500',
            'qos_algorithm_type' : '',
            'qos_algorithm_params' : {},
            'other_config' : {},
        }
        try:
            self.client.xenapi.VIF.create(vifRec)
        except Exception, e:
            if e.details[0] != 'DEVICE_ALREADY_EXISTS':
                raise
<|endoftext|>


<commit_before>import hexchat
import re

__module_name__ = "AdFilter"
__module_author__ = "PDog"
__module_version__ = "0.1"
__module_description__ = "Move fserve advertisements to a separate tab"

# Customize the name of the tab to your liking
tab_name = "(Ads)"

omenserve_regex = re.compile(".*?Type:\s+\W[\w-]+\s+For\sMy\sList\sOf:\s+[\d,]+\s+Files\s+.*?Slots:\s+\d+/\d+\s+.*?Queued:\s+\d+\s+.*?Speed:\s+[\d,]+cps\s+.*?Next:\s+\w+\s+.*?Served:\s+[\d,]+\s+.*?List:\s+[A-Z][a-z]+\s+\w+\s+.*?Search:\s+[A-Z]{2,3}\s+.*?Mode:\s+\w+\s+.*?$")
bwi_regex = re.compile("^(\[BWI\])\sType\s+\W[\w-]+\s+to\sget\sthe\slist\sof\s+[\d,]+\s+files\s\([\d\.]+\s+[A-Z]+\)\.\s+Updated\son\s+[\d+-]+\s+[\d:]+\s+Total\sSent\(channel\):\s+[\d,]+\s+\([\d\.]+\s+[A-Z]+(\))$")

ad_lst = [omenserve_regex, bwi_regex]

def find_adtab():
	context = hexchat.find_context(channel=tab_name)
	if context == None:
		hexchat.command("NEWSERVER -noconnect {0}".format(tab_name))
		return hexchat.find_context(channel=tab_name)
	else:
		return context

def adfilter_cb(word, word_eol, userdata):

	word = [(word[i] if len(word) > i else "") for i in range(4)]

	global ad_lst
	channel = hexchat.get_info("channel")
	stripped_msg = hexchat.strip(word[1], -1, 3)

	for ad in ad_lst:
		if ad.match(stripped_msg):
			ad_context = find_adtab()
			ad_context.prnt("{0}\t\00318<{4}{3}{1}>\00399 {2}".format(channel, *word))
			return hexchat.EAT_ALL
		else:
			return hexchat.EAT_NONE

def unload_cb(userdata):
	for chan in hexchat.get_list("channels"):
		if chan.type == 1 and chan.channel == tab_name:
			ad_context = hexchat.find_context(channel=tab_name)
			ad_context.command("CLOSE")
	hexchat.prnt(__module_name__ + " version " + __module_version__ + " unloaded")

hexchat.hook_print("Channel Message", adfilter_cb)
hexchat.hook_unload(unload_cb)

hexchat.prnt(__module_name__ + " version " + __module_version__ + " loaded")<commit_msg>Update adfilter.py<commit_after>import hexchat
import re

__module_name__ = "AdFilter"
__module_author__ = "PDog"
__module_version__ = "0.1.1"
__module_description__ = "Move fserve advertisements to a separate tab"

# Add channels from which you would like to filter ads, e.g. channels = ["#freenode", "#defocus", "##linux"]
channels = ["#ebooks"]

# Customize the name of the tab to your liking
tab_name = "(Ads)"

omenserve_regex = re.compile(".*?Type:\s+\W[\w-]+\s+For\sMy\sList\sOf:\s+[\d,]+\s+Files\s+.*?Slots:\s+\d+/\d+\s+.*?Queued:\s+\d+\s+.*?Speed:\s+[\d,]+cps\s+.*?Next:\s+\w+\s+.*?Served:\s+[\d,]+\s+.*?List:\s+[A-Z][a-z]+\s+\w+\s+.*?Search:\s+[A-Z]{2,3}\s+.*?Mode:\s+\w+\s+.*?$")
bwi_regex = re.compile("^(\[BWI\])\sType\s+\W[\w-]+\s+to\sget\sthe\slist\sof\s+[\d,]+\s+files\s\([\d\.]+\s+[A-Z]+\)\.\s+Updated\son\s+[\d+-]+\s+[\d:]+\s+Total\sSent\(channel\):\s+[\d,]+\s+\([\d\.]+\s+[A-Z]+(\))$")

ad_lst = [omenserve_regex, bwi_regex]

def find_adtab():
	context = hexchat.find_context(channel=tab_name)
	if context == None:
		hexchat.command("NEWSERVER -noconnect {0}".format(tab_name))
		return hexchat.find_context(channel=tab_name)
	else:
		return context

def adfilter_cb(word, word_eol, userdata):

	word = [(word[i] if len(word) > i else "") for i in range(4)]

	global channels
	global ad_lst
	channel = hexchat.get_info("channel")
	stripped_msg = hexchat.strip(word[1], -1, 3)

	for ad in ad_lst:
		if ad.match(stripped_msg) and channel in channels:
			ad_context = find_adtab()
			ad_context.prnt("{0}\t\00318<{4}{3}{1}>\00399 {2}".format(channel, *word))
			return hexchat.EAT_ALL

def unload_cb(userdata):
	for chan in hexchat.get_list("channels"):
		if chan.type == 1 and chan.channel == tab_name:
			ad_context = hexchat.find_context(channel=tab_name)
			ad_context.command("CLOSE")
	hexchat.prnt(__module_name__ + " version " + __module_version__ + " unloaded")

hexchat.hook_print("Channel Message", adfilter_cb)
hexchat.hook_unload(unload_cb)

hexchat.prnt(__module_name__ + " version " + __module_version__ + " loaded")<|endoftext|>


<commit_before>from abc import abstractmethod, abstractproperty, ABCMeta
from enum import Enum

class F(Enum):
    clientId = 1
    requestId = 2
    rootHash = 3
    leafData = 4
    leafDataHash = 5
    created = 6
    addedToTree = 7
    auditPath = 8
    serialNo = 9
    treeSize = 10

class ImmutableStore:
    """
    Interface for immutable stores.
    An immutable store is any storage system (database, flatfile, in-memory,
    etc.). It stores the transaction data and the relevant info from the
    Merkle Tree.
    """

    def start(self, loop):
        raise NotImplementedError()

    def stop(self):
        raise NotImplementedError()

    async def append(self, identifier: str, reply, txnId: str):
        raise NotImplementedError()

    async def get(self, identifier: str, reqId: int):
        raise NotImplementedError()

    def size(self) -> int:
        raise NotImplementedError()
<commit_msg>Added some constants in enum F.<commit_after>from abc import abstractmethod, abstractproperty, ABCMeta
from enum import Enum

class F(Enum):
    clientId = 1
    requestId = 2
    rootHash = 3
    leafData = 4
    leafDataHash = 5
    created = 6
    addedToTree = 7
    auditPath = 8
    serialNo = 9
    treeSize = 10
    leafHash = 11
    nodeHash = 12
    rowNo = 13

class ImmutableStore:
    """
    Interface for immutable stores.
    An immutable store is any storage system (database, flatfile, in-memory,
    etc.). It stores the transaction data and the relevant info from the
    Merkle Tree.
    """

    def start(self, loop):
        raise NotImplementedError()

    def stop(self):
        raise NotImplementedError()

    async def append(self, identifier: str, reply, txnId: str):
        raise NotImplementedError()

    async def get(self, identifier: str, reqId: int):
        raise NotImplementedError()

    def size(self) -> int:
        raise NotImplementedError()
<|endoftext|>