def keyReleaseEvent(self, ev):
        ev.accept()
        e = Event()
        e.type = '3'
        e.x = self.__lastX
        e.y = self.__lastY
        e.state = self._state(ev)
        e.num = 0
        e.keysym = self._keysym(ev)
        # qt doesn't report the character on KeyRelease, so
        #  we must generate it from the key code
        key = ev.key()
        if key >= 65 and key <= 90 and (e.state & 3) == 0:
            e.char = chr(key + 32)
        elif key < 256:
            e.char = chr(key)
        else:
            try:
                e.char = {0x1000: '\033',
                          0x1001: '\t',
                          0x1003: '\b',
                          0x1004: '\n',
                          0x1005: '\n',
                          0x1007: '\177'}[key]
            except KeyError:
                e.char = '\0'

        self.HandleEvent(e)
Example #2
0
 def _get_character_map_format4(self, offset):
     # This is absolutely, without question, the *worst* file
     # format ever.  Whoever the f*****t is that thought this up is
     # a f*****t. 
     header = _read_cmap_format4Header(self._data, offset)
     seg_count = header.seg_count_x2 // 2
     array_size = struct.calcsize('>%dH' % seg_count)
     end_count = self._read_array('>%dH' % seg_count, 
         offset + header.size)
     start_count = self._read_array('>%dH' % seg_count, 
         offset + header.size + array_size + 2)
     id_delta = self._read_array('>%dh' % seg_count,
         offset + header.size + array_size + 2 + array_size)
     id_range_offset_address = \
         offset + header.size + array_size + 2 + array_size + array_size
     id_range_offset = self._read_array('>%dH' % seg_count, 
         id_range_offset_address)
     character_map = {}
     for i in range(0, seg_count):
         if id_range_offset[i] != 0:
             if id_range_offset[i] == 65535:
                 continue  # Hack around a dodgy font (babelfish.ttf)
             for c in range(start_count[i], end_count[i] + 1):
                 addr = id_range_offset[i] + 2*(c - start_count[i]) + \
                     id_range_offset_address + 2*i
                 g = struct.unpack('>H', self._data[addr:addr+2])[0]
                 if g != 0:
                     character_map[chr(c)] = (g + id_delta[i]) % 65536
         else:
             for c in range(start_count[i], end_count[i] + 1):
                 g = (c + id_delta[i]) % 65536
                 if g != 0:
                     character_map[chr(c)] = g
     return character_map
Example #3
0
 def regioncodes_cleanup(value, engine):
     replace = {chr(225):"a", chr(233):"e", chr(237):"i", chr(243):"o"}
     newvalue = str(value)
     for key in list(replace.keys()):
         if key in newvalue:
             newvalue = newvalue.replace(key, replace[key])
     return newvalue
Example #4
0
    def update(self, reseed):
        """
        Update that trail!

        :param reseed: Whether we are in the normal reseed cycle or not.
        """
        if self._clear:
            for i in range(0, 3):
                self._screen.print_at(" ",
                                      self._x,
                                      self._screen.start_line + self._y + i)
            self._maybe_reseed(reseed)
        else:
            for i in range(0, 3):
                self._screen.print_at(chr(randint(32, 126)),
                                      self._x,
                                      self._screen.start_line + self._y + i,
                                      Screen.COLOUR_GREEN)
            for i in range(4, 6):
                self._screen.print_at(chr(randint(32, 126)),
                                      self._x,
                                      self._screen.start_line + self._y + i,
                                      Screen.COLOUR_GREEN,
                                      Screen.A_BOLD)
            self._maybe_reseed(reseed)
Example #5
0
def _emote(input_str):
    result = input_str
    result = result.replace(":-)", chr(9786))
    result = result.replace(":)", chr(9786))
    result = result.replace(":-(", chr(9785))
    result = result.replace(":(", chr(9785))
    return result
Example #6
0
 def _inject_key(screen, char):
     """
     Inject a specified character into the input buffers.
     """
     if sys.platform == "win32":
         event = win32console.PyINPUT_RECORDType(win32console.KEY_EVENT)
         event.RepeatCount = 1
         event.ControlKeyState = 0
         event.VirtualScanCode = 0
         if char >= 0:
             event.Char = chr(char)
             event.VirtualKeyCode = ord(chr(char).upper())
         else:
             # Lookup in mapping dicts
             reverse = dict((v, k) for k, v in
                            screen._EXTRA_KEY_MAP.items())
             if char in reverse:
                 event.VirtualKeyCode = reverse[char]
             else:
                 # Fudge key state required for BACK_TAB if needed.
                 if char == Screen.KEY_BACK_TAB:
                     char = Screen.KEY_TAB
                     event.ControlKeyState = win32con.SHIFT_PRESSED
                 reverse = dict((v, k) for k, v in
                                screen._KEY_MAP.items())
                 event.VirtualKeyCode = reverse[char]
         event.KeyDown = 1
         screen._stdin.WriteConsoleInput([event])
         event.KeyDown = 0
         screen._stdin.WriteConsoleInput([event])
     else:
         curses.ungetch(char)
Example #7
0
    def sendall(self, data):
        if self.connected:
            if self.__ota:
                # modified from https://github.com/shadowsocks/shadowsocks/blob/master/shadowsocks/tcprelay.py
                data_len = struct.pack(">H", len(data))
                index = struct.pack('>I', self._ota_chunk_idx)
                key = self.crypto.cipher_iv + index
                sha110 = hmac.new(key, data, hashlib.sha1).digest()[:10]
                self._ota_chunk_idx += 1
                data = data_len + sha110 + data
            self._sock.sendall(self.crypto.encrypt(data))
        else:
            # https://shadowsocks.org/en/spec/one-time-auth.html
            host, port = self.__address

            if self._http_obfs:
                d = {'host': self._http_obfs_host,
                     'UA': self._http_obfs_ua,
                     'ws_key': base64.b64encode(os.urandom(16)).decode()}
                self._sock.sendall(REQUEST_HEADER_WS.format(**d).encode())

            addrtype = 19 if self.__ota else 3
            header = b''.join([chr(addrtype).encode(),
                               chr(len(host)).encode('latin1'),
                               host.encode(),
                               struct.pack(b">H", port)])
            if self.__ota:
                key = self.crypto.cipher_iv + self.crypto.key
                header += hmac.new(key, header, hashlib.sha1).digest()[:10]
            self._sock.sendall(self.crypto.encrypt(header))
            self.connected = True
            if data:
                self.sendall(data)
Example #8
0
    def OnChar(self, evt):
        #keyname = keyMap.get(keycode, None)
        keycode = evt.GetKeyCode()
        keyname = 'unknown'
        if keycode < 256:
            if keycode == 0:
                keyname = "NUL"
            elif keycode < 27:
                keyname = "Ctrl-%s" % chr(ord('A') + keycode-1)
            else:
                #keyname = "\"%s\"" % chr(keycode)
                keyname = chr(keycode)
        else:
            keyname = "(%s)" % keycode        


        if keycode == wx.WXK_ESCAPE:
            exit()
        elif keyname == "F":
            if self.fullscreen:
                self.fullscreen = False
                self.ShowFullScreen(False)
            else:
                self.fullscreen = True
                self.ShowFullScreen(True)
        else:
            print(keyname)
Example #9
0
 def _angErrToStr(value):
     """helper method: converts angular error to string representation in deg or arcmin or arcsec"""
     arcsec = (value / DEG) * 3600
     if arcsec < 60:
         return chr(0xB1) + "%.2g\"" % arcsec
     elif arcsec < 3600:
         return chr(0xB1) + "%.2f'" % (arcsec * 60)
     else:
         return chr(0xB1) + "%.2f%s" % (arcsec * 3600, chr(0xB0))
Example #10
0
 def handle_charref(self, name):
     name = name.lower()
     try:
         if name.startswith('x'):
             self.handle_data(chr(int(name[1:], 16)))
         else:
             self.handle_data(chr(int(name)))
     except ValueError:
         pass
    def test_is_gsm_text_false(self):
        self.assertEqual(
            messaging.sms.gsm0338.is_gsm_text(chr(0x00a0)), False)

        for i in xrange(1, 0xffff + 1):
            if chr(i) not in MAP:
                # Note: it's a little odd, but on error we want to see values
                if messaging.sms.gsm0338.is_gsm_text(chr(i)) is not False:
                    self.assertEqual(BAD, i)
Example #12
0
    def OnChar(self, evt):
        cursor = wx.StockCursor(wx.CURSOR_BLANK)
        self.GetParent().SetCursor(cursor)

        #keyname = keyMap.get(keycode, None)
        keycode = evt.GetKeyCode()
        keyname = 'unknown'
        if keycode < 256:
            if keycode == 0:
                keyname = "NUL"
            elif keycode < 27:
                keyname = "Ctrl-%s" % chr(ord('A') + keycode-1)
            else:
                #keyname = "\"%s\"" % chr(keycode)
                keyname = chr(keycode)
        else:
            keyname = "(%s)" % keycode        


        if keycode == wx.WXK_ESCAPE:
            self.save()
            exit()
        elif evt.ControlDown() and keyname == "F":
            if self.GetParent().fullscreen:
                self.GetParent().fullscreen = False
                self.GetParent().ShowFullScreen(False)
            else:
                self.GetParent().fullscreen = True
                self.GetParent().ShowFullScreen(True)

        elif evt.ControlDown() and keyname == "S":
            self.save()
            
        # add a new datestamp
        elif evt.ControlDown() and keyname == "J":
            self.new_stamp()

        elif evt.ControlDown() and keyname == "E":
            #print "position: %s, line: %s" % (self.input.content.caret.position, self.input.content.caret.line)
            #print "text len: %s" % (len(self.input.content.text))
            buf = Buffer(self.textbox.GetValue())
            position = buf.end_of_line(self.textbox.GetInsertionPoint())
            #print "end of line: %s" % position
            self.textbox.SetInsertionPoint(position-1)
                
        elif evt.ControlDown() and keyname == "A":
            #print "position: %s, line: %s" % (self.input.content.caret.position, self.input.content.caret.line)
            #print "text len: %s" % (len(self.input.content.text))
            buf = Buffer(self.textbox.GetValue())
            position = buf.start_of_line(self.textbox.GetInsertionPoint())
            #print "start of line: %s" % position
            self.textbox.SetInsertionPoint(position)

        else:
            #print keyname
            evt.Skip()
Example #13
0
    def genImage(self):
        """Create a PNG from the contents of this flowable.

        Required so we can put inline math in paragraphs.
        Returns the file name.
        The file is caller's responsability.

        """

        dpi = 72
        scale = 10

        try:
            import Image
            import ImageFont
            import ImageDraw
            import ImageColor
        except ImportError:
            from PIL import (
                Image,
                ImageFont,
                ImageDraw,
                ImageColor,
            )

        if not HAS_MATPLOTLIB:
            img = Image.new('RGBA', (120, 120), (255,255,255,0))
        else:
            width, height, descent, glyphs,\
            rects, used_characters = self.parser.parse(
                enclose(self.s), dpi, prop=FontProperties(size=self.fontsize))
            img = Image.new('RGBA', (int(width*scale), int(height*scale)),(255,255,255,0))
            draw = ImageDraw.Draw(img)
            for ox, oy, fontname, fontsize, num, symbol_name in glyphs:
                font = ImageFont.truetype(fontname, int(fontsize*scale))
                tw, th = draw.textsize(chr(num), font=font)
                # No, I don't understand why that 4 is there.
                # As we used to say in the pure math
                # department, that was a numerical solution.
                col_conv=ColorConverter()
                fc=col_conv.to_rgb(self.color)
                rgb_color=(int(fc[0]*255),int(fc[1]*255),int(fc[2]*255))
                draw.text((ox*scale, (height - oy - fontsize + 4)*scale),
                           chr(num), font=font,fill=rgb_color)
            for ox, oy, w, h in rects:
                x1 = ox*scale
                x2 = x1 + w*scale
                y1 = (height - oy)*scale
                y2 = y1 + h*scale
                draw.rectangle([x1, y1, x2, y2],(0,0,0))

        fh, fn = tempfile.mkstemp(suffix=".png")
        os.close(fh)
        img.save(fn)
        return fn
Example #14
0
    def decode(self, text, location=None):
        self.doc = pyglet.text.document.FormattedDocument()

        self.length = 0
        self.attributes = {}
        next_trailing_space = True
        trailing_newline = True

        for m in _pattern.finditer(text):
            group = m.lastgroup
            trailing_space = True
            if group == 'text':
                t = m.group('text')
                self.append(t)
                trailing_space = t.endswith(' ')
                trailing_newline = False
            elif group == 'nl_soft':
                if not next_trailing_space:
                    self.append(' ')
                trailing_newline = False
            elif group in ('nl_hard1', 'nl_hard2'):
                self.append('\n')
                trailing_newline = True
            elif group == 'nl_para':
                self.append(m.group('nl_para')[1:]) # ignore the first \n
                trailing_newline = True
            elif group == 'attr':
                try:
                    ast = parser.expr(m.group('attr_val'))
                    if self.safe(ast):
                        val = eval(ast.compile())
                    else:
                        val = None
                except (parser.ParserError, SyntaxError):
                    val = None
                name = m.group('attr_name')
                if name[0] == '.':
                    if trailing_newline:
                        self.attributes[name[1:]] = val
                    else:
                        self.doc.set_paragraph_style(self.length, self.length, 
                                                     {name[1:]: val})
                else:
                    self.attributes[name] = val
            elif group == 'escape_dec':
                self.append(chr(int(m.group('escape_dec_val'))))
            elif group == 'escape_hex':
                self.append(chr(int(m.group('escape_hex_val'), 16)))
            elif group == 'escape_lbrace':
                self.append('{')
            elif group == 'escape_rbrace':
                self.append('}')
            next_trailing_space = trailing_space

        return self.doc
    def test_decoding_supported_unicode_gsm(self):
        for key in MAP.keys():
            i_gsm = MAP[key][1]
            if i_gsm <= 0xff:
                s_gsm = chr(i_gsm)
            elif i_gsm <= 0xffff:
                s_gsm = chr((i_gsm & 0xff00) >> 8)
                s_gsm += chr(i_gsm & 0x00ff)

            s_unicode = s_gsm.decode('gsm0338', 'strict')
            self.assertEqual(MAP[key][0], ord(s_unicode))
Example #16
0
def charref(name):
    if name[0] in ['x', 'X']:
        c = int(name[1:], 16)
    else:
        c = int(name)

    if not UNICODE_SNOB and c in list(unifiable_n.keys()):
        return unifiable_n[c]
    else:
        try:
            return chr(c)
        except NameError:  # Python3
            return chr(c)
Example #17
0
def entityref(c):
    if not UNICODE_SNOB and c in list(unifiable.keys()):
        return unifiable[c]
    else:
        try:
            name2cp(c)
        except KeyError:
            return "&" + c + ';'
        else:
            try:
                return chr(name2cp(c))
            except NameError:  # Python3
                return chr(name2cp(c))
Example #18
0
def find_gt_dirs(conf):
    lbl = h5py.File(conf.labelfile, 'r')
    exp_list = lbl['movieFilesAllGT'][conf.view,:]
    local_dirs = [u''.join(chr(c) for c in lbl[jj]) for jj in exp_list]
    sel_dirs = [True] * len(local_dirs)
    try:
        for k in lbl['projMacros'].keys():
            r_dir = u''.join(chr(c) for c in lbl['projMacros'][k])
            local_dirs = [s.replace('${}'.format(k), r_dir) for s in local_dirs]
    except:
        pass
    lbl.close()
    return local_dirs, sel_dirs
Example #19
0
def sid_to_key(sid):
    s1 = ""
    s1 += chr(sid & 0xFF)
    s1 += chr((sid >> 8) & 0xFF)
    s1 += chr((sid >> 16) & 0xFF)
    s1 += chr((sid >> 24) & 0xFF)
    s1 += s1[0]
    s1 += s1[1]
    s1 += s1[2]
    s2 = s1[3] + s1[0] + s1[1] + s1[2]
    s2 += s2[0] + s2[1] + s2[2]

    return str_to_key(s1), str_to_key(s2)
Example #20
0
def get_trx_files(lbl, local_dirs, on_gt=False):
    if on_gt:
        trx_files = [u''.join(chr(c) for c in lbl[jj]) for jj in lbl['trxFilesAllGT'][0]]
    else:
        trx_files = [u''.join(chr(c) for c in lbl[jj]) for jj in lbl['trxFilesAll'][0]]
    movdir = [os.path.dirname(a) for a in local_dirs]
    trx_files = [s.replace('$movdir', m) for (s, m) in zip(trx_files, movdir)]
    try:
        for k in lbl['projMacros'].keys():
            r_dir = u''.join(chr(c) for c in lbl['projMacros'][k])
            trx_files = [s.replace('${}'.format(k), r_dir) for s in trx_files]
    except:
        pass
    return trx_files
Example #21
0
def bind_code(co, globals):
    """
    Take a code object and a dictionnary and returns a new code object where
    the opcodes LOAD_GLOBAL are replaced by LOAD_CONST whenever the global's
    name appear in the dictionnary
    """
    consts = list(co.co_consts)
    assigned = {}
    
    code = co.co_code
    new_code = ""
    n = len(code)
    i = 0
    while i < n:
        c = code[i]
        op = ord(c)
        i += 1
        if op >= HAVE_ARGUMENT:
            oparg = ord(code[i]) + ord(code[i+1]) * 256
            i += 2
        else:
            oparg = None
        if op == LOAD_GLOBAL:
            name = co.co_names[oparg]
            if name in globals:
                k = assigned.get(name, None)
                if k == None:
                    k = len(consts)
                    assigned[name] = len(consts)
                    consts.append(globals[name])
                op = LOAD_CONST
                oparg = k
        new_code += chr(op)
        if oparg is not None:
            new_code += chr(oparg & 255)
            new_code += chr( (oparg>>8) & 255 )
            
    return make_code(co.co_argcount,
                     co.co_nlocals,
                     co.co_stacksize,
                     co.co_flags,
                     new_code,
                     tuple(consts),
                     co.co_names,
                     co.co_varnames,
                     co.co_filename,
                     co.co_name,
                     co.co_firstlineno,
                     co.co_lnotab )
Example #22
0
def rewrite_code(co, consts_dict, consts_tuple):
    """Take a code object and a dictionnary and returns a
    new code object where the opcodes LOAD_GLOBAL are replaced
    by LOAD_CONST whenever the global's name appear in the
    dictionnary"""
    code = co.co_code
    new_code = ""
    n = len(code)
    i = 0
    consts_list = list(consts_tuple)
    while i < n:
        c = code[i]
        op = ord(c)
        i += 1
        extended_arg = 0
        if op >= HAVE_ARGUMENT:
            oparg = ord(code[i]) + ord(code[i+1])*256+extended_arg
            extended_arg = 0
            i += 2
        else:
            oparg = None
        if op == EXTENDED_ARG:
            extended_arg = oparg*65536
        elif op == LOAD_GLOBAL:
            name = co.co_names[oparg]
            k = consts_dict.get(name)
            if k is not None:
                op = LOAD_CONST
                oparg = k
        elif op == LOAD_CONST:
            val = co.co_consts[oparg]
            oparg = consts_list.index(val)
        new_code += chr(op)
        if oparg is not None:
            new_code += chr(oparg & 255)
            new_code += chr( (oparg>>8) & 255 )
            
    return make_code(co.co_argcount,
                     co.co_nlocals,
                     co.co_stacksize,
                     co.co_flags,
                     new_code,
                     consts_tuple,
                     co.co_names,
                     co.co_varnames,
                     co.co_filename,
                     co.co_name,
                     co.co_firstlineno,
                     co.co_lnotab )
Example #23
0
    def download_complete_cb(ticket, status, content):
        if ticket not in download_tickets:
            logging.warning('Error! download ticket not exists')
            return

        if download_tickets[ticket] != status:
            logging.warning('Error! expect download status %d but %d got', download_tickets[ticket], status)
            return
        if status == 0:
            logging.debug('Download #%d success', ticket)
            logging.debug('Downloaded content: \n%s', ''.join([chr(b) for b in content]))
        else:
            logging.warning('Download #%d fail, msg: %s', ticket, ''.join([chr(b) for b in content]))
        del download_tickets[ticket]
        check_quit()
Example #24
0
def textexec(*arg, **kw):
    ''' Exec a subprocess, print lines, and also return
        them to caller
    '''
    logger = kw.pop('logger', default_logger)

    formatcmd = textwrap.TextWrapper(initial_indent='        ',
                                    subsequent_indent='        ',
                                    break_long_words=False).fill

    subproc = TextOutExec(*arg, **kw)
    args = subproc.args
    procname = args[0]
    starttime = time.time()
    result = []
    logger(result,
        'Process "%s" started on %s\n\n%s\n\n' % (
         procname, time.asctime(), formatcmd(' '.join(args))))
    errcode = 0
    badexit = '* ' + chr(1)
    for line in subproc:
        if line == badexit and subproc.is_python_proc:
            errcode = 1
            continue
        if not line.startswith('**'):
            logger(result, line)
            continue
        errcode = errcode or int(line.split()[-1])
        status = errcode and 'FAIL' or 'PASS'
        logger(result,
            '\nProgram %s exit code: %s (%d)   elapsed time: %s\n' %
            (procname, status, errcode, elapsedtime(starttime)))
        logger(result, None,
            'Cumulative execution time is %s\n' % elapsedtime())
    return errcode, result
Example #25
0
    def test_cog(self):
        """
        Check that Cog works.
        """
        # Check that Cog updates the Screen every other frame.
        screen = MagicMock(spec=Screen, colours=8, unicode_aware=False)
        canvas = Canvas(screen, 10, 40, 0, 0)
        effect = Cog(canvas, 10, 5, 5)
        effect.reset()
        self.assert_blank(canvas)
        my_buffer = [[(32, 7, 0, 0) for _ in range(40)] for _ in range(10)]
        for i in range(20):
            effect.update(i)
            self.assertEqual(self.check_canvas(
                canvas,
                my_buffer,
                lambda value: self.assertIn(
                    chr(value[0]), " ''^.|/7.\\|Ywbd#")),
                i % 2 == 0)

        # Check there is no stop frame by default.
        self.assertEqual(effect.stop_frame, 0)

        # This effect should ignore events.
        event = object()
        self.assertEqual(event, effect.process_event(event))
Example #26
0
 def _createStringForKey(self, keycode, modifier_state):
     keyboard_p = carbon.TISCopyCurrentKeyboardInputSource()
     keyboard = objcify(keyboard_p)
     layout_p = carbon.TISGetInputSourceProperty(keyboard_p,
                                                 kTISPropertyUnicodeKeyLayoutData)
     layout = objcify(layout_p)
     layoutbytes = layout.bytes()
     if hasattr(layoutbytes, 'tobytes') :
         layoutbytes_vp = layoutbytes.tobytes()
     else:
         layoutbytes_vp = memoryview(bytearray(layoutbytes)).tobytes()
     keysdown = ctypes.c_uint32()
     length = UniCharCount()
     chars = UniChar4()
     retval = carbon.UCKeyTranslate(layoutbytes_vp,
                                    keycode,
                                    kUCKeyActionDisplay,
                                    modifier_state,
                                    carbon.LMGetKbdType(),
                                    kUCKeyTranslateNoDeadKeysBit,
                                    ctypes.byref(keysdown),
                                    4,
                                    ctypes.byref(length),
                                    chars)
     s = u''.join(chr(chars[i]) for i in range(length.value))
     CoreFoundation.CFRelease(keyboard)
     return s
Example #27
0
    def _BuildLookupTable(self):
        """Create a fast lookup table mapping InfoMask -> minimum_offset.

        We are interested in the maximum distance between the _POOL_HEADER and
        _OBJECT_HEADER. This is dictated by the InfoMask field. Here we build a
        quick lookup table between the InfoMask field and the offset of the
        first optional header.
        """
        ObpInfoMaskToOffset = self.obj_session.GetParameter(
            "ObpInfoMaskToOffset")

        self.lookup["\x00"] = 0

        # Iterate over all the possible InfoMask values (Bytes can take on 256
        # values).
        for i in range(0x100):
            # Locate the largest offset from the start of
            # _OBJECT_HEADER. Starting with the largest bit position 1 << 7.
            bit_position = 0x80
            while bit_position > 0:
                # This is the optional header with the largest offset.
                if bit_position & i:
                    self.lookup[chr(i)] = ObpInfoMaskToOffset[
                        i & (bit_position | (bit_position - 1))]

                    break
                bit_position >>= 1
Example #28
0
    def close(self):
        logger.debug('hxsocks close, readable %s, writeable %s' % (self.readable, self.writeable))
        if self.pooled:
            try:
                self._rfile.close()
                self._sock.close()
            except Exception:
                pass
            return
        if self.writeable:
            logger.debug('hxsocks shutdown write, close')
            padding_len = random.randint(8, 255)
            data = chr(padding_len).encode('latin1') + b'\x01' * padding_len

            ct, mac = self.cipher.encrypt(data)
            data = self.pskcipher.encrypt(struct.pack('>H', len(ct))) + ct + mac
            self._sock_sendall(data)
            self.writeable = 0
        if self.readable:
            t = Thread(target=self._wait_close)
            t.daemon = True
            t.start()
        logger.debug('hxsocks add to pool')
        self.pooled = 1
        POOL.put(self.hxsServer.parse.hostname, self, self.hxsServer.name)
Example #29
0
    def test_wipe(self):
        """
        Check that Wipe works.
        """
        # Check that Wipe clears lines going down the screen.
        screen = MagicMock(spec=Screen, colours=8, unicode_aware=False)
        canvas = Canvas(screen, 10, 40, 0, 0)
        effect = Wipe(canvas)
        effect.reset()
        self.assert_blank(canvas)
        my_buffer = [[(32, 7, 0, 0) for _ in range(40)] for _ in range(10)]
        for x in range(canvas.width):
            for y in range(canvas.height):
                canvas.print_at(chr(randint(1, 128)), x, y)
                my_buffer[y][x] = canvas.get_from(x, y)
        for i in range(10):
            effect.update(i)
            self.assertEqual(self.check_canvas(
                canvas,
                my_buffer,
                lambda value: self.assertLess(value[0], 129)),
                i % 2 == 0)

        # Check there is no stop frame by default.
        self.assertEqual(effect.stop_frame, 0)

        # This effect should ignore events.
        event = object()
        self.assertEqual(event, effect.process_event(event))
Example #30
0
    def test_julia(self):
        """
        Check that Julia works.
        """
        # Check that Julia updates every frame.
        screen = MagicMock(spec=Screen, colours=8, unicode_aware=False)
        canvas = Canvas(screen, 10, 40, 0, 0)
        effect = Julia(canvas)
        effect.reset()
        self.assert_blank(canvas)
        my_buffer = [[(32, 7, 0, 0) for _ in range(40)] for _ in range(10)]
        for i in range(20):
            effect.update(i)
            self.assertEqual(self.check_canvas(
                canvas,
                my_buffer,
                lambda value: self.assertIn(chr(value[0]), '@&9#GHh32As;:. ')),
                True)

        # Check there is no stop frame by default.
        self.assertEqual(effect.stop_frame, 0)

        # This effect should ignore events.
        event = object()
        self.assertEqual(event, effect.process_event(event))
 def generate_null_packet(self):
     return [chr(0) for _ in range(self.packet_bytes)]
Example #32
0
# Make partials for start and end date. End date must be after start date
def FuzzyStartTime():
    return (FuzzyNaiveDateTime(
        datetime.datetime.now() - datetime.timedelta(days=40),
        datetime.datetime.now() - datetime.timedelta(days=20),
    ))


def FuzzyEndTime():
    return (FuzzyNaiveDateTime(
        datetime.datetime.now() - datetime.timedelta(days=19),
        datetime.datetime.now()))


all_unicode = ''.join(chr(i) for i in range(65536))
UNICODE_LETTERS = ''.join(
    c for c in all_unicode
    if unicodedata.category(c) == 'Lu' or unicodedata.category(c) == 'Ll')


class FaradayFactory(factory.alchemy.SQLAlchemyModelFactory):
    @classmethod
    def build_dict(cls, **kwargs):
        ret = factory.build(dict, FACTORY_CLASS=cls)
        try:
            # creator is an user instance, that isn't serializable. Ignore it
            del ret['creator']
        except KeyError:
            pass
        return ret
Example #33
0
class AlarmDecoder(object):
    """
    High-level wrapper around `AlarmDecoder`_ (AD2) devices.
    """

    # High-level Events
    on_arm = event.Event(
        "This event is called when the panel is armed.\n\n**Callback definition:** *def callback(device)*"
    )
    on_disarm = event.Event(
        "This event is called when the panel is disarmed.\n\n**Callback definition:** *def callback(device)*"
    )
    on_power_changed = event.Event(
        "This event is called when panel power switches between AC and DC.\n\n**Callback definition:** *def callback(device, status)*"
    )
    on_alarm = event.Event(
        "This event is called when the alarm is triggered.\n\n**Callback definition:** *def callback(device, zone)*"
    )
    on_alarm_restored = event.Event(
        "This event is called when the alarm stops sounding.\n\n**Callback definition:** *def callback(device, zone)*"
    )
    on_fire = event.Event(
        "This event is called when a fire is detected.\n\n**Callback definition:** *def callback(device, status)*"
    )
    on_bypass = event.Event(
        "This event is called when a zone is bypassed.  \n\n\n\n**Callback definition:** *def callback(device, status)*"
    )
    on_boot = event.Event(
        "This event is called when the device finishes booting.\n\n**Callback definition:** *def callback(device)*"
    )
    on_config_received = event.Event(
        "This event is called when the device receives its configuration. \n\n**Callback definition:** *def callback(device)*"
    )
    on_zone_fault = event.Event(
        "This event is called when :py:class:`~alarmdecoder.zonetracking.Zonetracker` detects a zone fault.\n\n**Callback definition:** *def callback(device, zone)*"
    )
    on_zone_restore = event.Event(
        "This event is called when :py:class:`~alarmdecoder.zonetracking.Zonetracker` detects that a fault is restored.\n\n**Callback definition:** *def callback(device, zone)*"
    )
    on_low_battery = event.Event(
        "This event is called when the device detects a low battery.\n\n**Callback definition:** *def callback(device, status)*"
    )
    on_panic = event.Event(
        "This event is called when the device detects a panic.\n\n**Callback definition:** *def callback(device, status)*"
    )
    on_relay_changed = event.Event(
        "This event is called when a relay is opened or closed on an expander board.\n\n**Callback definition:** *def callback(device, message)*"
    )

    # Mid-level Events
    on_message = event.Event(
        "This event is called when standard panel :py:class:`~alarmdecoder.messages.Message` is received.\n\n**Callback definition:** *def callback(device, message)*"
    )
    on_expander_message = event.Event(
        "This event is called when an :py:class:`~alarmdecoder.messages.ExpanderMessage` is received.\n\n**Callback definition:** *def callback(device, message)*"
    )
    on_lrr_message = event.Event(
        "This event is called when an :py:class:`~alarmdecoder.messages.LRRMessage` is received.\n\n**Callback definition:** *def callback(device, message)*"
    )
    on_rfx_message = event.Event(
        "This event is called when an :py:class:`~alarmdecoder.messages.RFMessage` is received.\n\n**Callback definition:** *def callback(device, message)*"
    )
    on_sending_received = event.Event(
        "This event is called when a !Sending.done message is received from the AlarmDecoder.\n\n**Callback definition:** *def callback(device, status, message)*"
    )

    # Low-level Events
    on_open = event.Event(
        "This event is called when the device has been opened.\n\n**Callback definition:** *def callback(device)*"
    )
    on_close = event.Event(
        "This event is called when the device has been closed.\n\n**Callback definition:** *def callback(device)*"
    )
    on_read = event.Event(
        "This event is called when a line has been read from the device.\n\n**Callback definition:** *def callback(device, data)*"
    )
    on_write = event.Event(
        "This event is called when data has been written to the device.\n\n**Callback definition:** *def callback(device, data)*"
    )

    # Constants
    KEY_F1 = chr(1) + chr(1) + chr(1)
    """Represents panel function key #1"""
    KEY_F2 = chr(2) + chr(2) + chr(2)
    """Represents panel function key #2"""
    KEY_F3 = chr(3) + chr(3) + chr(3)
    """Represents panel function key #3"""
    KEY_F4 = chr(4) + chr(4) + chr(4)
    """Represents panel function key #4"""
    KEY_PANIC = chr(5) + chr(5) + chr(5)
    """Represents a panic keypress"""

    BATTERY_TIMEOUT = 30
    """Default timeout (in seconds) before the battery status reverts."""
    FIRE_TIMEOUT = 30
    """Default tTimeout (in seconds) before the fire status reverts."""

    # Attributes
    address = 18
    """The keypad address in use by the device."""
    configbits = 0xFF00
    """The configuration bits set on the device."""
    address_mask = 0xFFFFFFFF
    """The address mask configured on the device."""
    emulate_zone = [False for _ in list(range(5))]
    """List containing the devices zone emulation status."""
    emulate_relay = [False for _ in list(range(4))]
    """List containing the devices relay emulation status."""
    emulate_lrr = False
    """The status of the devices LRR emulation."""
    deduplicate = False
    """The status of message deduplication as configured on the device."""
    mode = ADEMCO
    """The panel mode that the AlarmDecoder is in.  Currently supports ADEMCO and DSC."""

    #Version Information
    serial_number = 0xFFFFFFFF
    """The device serial number"""
    version_number = 'Unknown'
    """The device firmware version"""
    version_flags = ""
    """Device flags enabled"""
    def __init__(self, device):
        """
        Constructor

        :param device: The low-level device used for this `AlarmDecoder`_
                       interface.
        :type device: Device
        """
        self._device = device
        self._zonetracker = Zonetracker(self)

        self._battery_timeout = AlarmDecoder.BATTERY_TIMEOUT
        self._fire_timeout = AlarmDecoder.FIRE_TIMEOUT
        self._power_status = None
        self._alarm_status = None
        self._bypass_status = None
        self._armed_status = None
        self._armed_stay = False
        self._fire_status = (False, 0)
        self._battery_status = (False, 0)
        self._panic_status = False
        self._relay_status = {}
        self._internal_address_mask = 0xFFFFFFFF

        self.address = 18
        self.configbits = 0xFF00
        self.address_mask = 0xFFFFFFFF
        self.emulate_zone = [False for x in list(range(5))]
        self.emulate_relay = [False for x in list(range(4))]
        self.emulate_lrr = False
        self.deduplicate = False
        self.mode = ADEMCO

        self.serial_number = 0xFFFFFFFF
        self.version_number = 'Unknown'
        self.version_flags = ""

    def __enter__(self):
        """
        Support for context manager __enter__.
        """
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        """
        Support for context manager __exit__.
        """
        self.close()

        return False

    @property
    def id(self):
        """
        The ID of the `AlarmDecoder`_ device.

        :returns: identification string for the device
        """
        return self._device.id

    @property
    def battery_timeout(self):
        """
        Retrieves the timeout for restoring the battery status, in seconds.

        :returns: battery status timeout
        """
        return self._battery_timeout

    @battery_timeout.setter
    def battery_timeout(self, value):
        """
        Sets the timeout for restoring the battery status, in seconds.

        :param value: timeout in seconds
        :type value: int
        """
        self._battery_timeout = value

    @property
    def fire_timeout(self):
        """
        Retrieves the timeout for restoring the fire status, in seconds.

        :returns: fire status timeout
        """
        return self._fire_timeout

    @fire_timeout.setter
    def fire_timeout(self, value):
        """
        Sets the timeout for restoring the fire status, in seconds.

        :param value: timeout in seconds
        :type value: int
        """
        self._fire_timeout = value

    @property
    def internal_address_mask(self):
        """
        Retrieves the address mask used for updating internal status.

        :returns: address mask
        """
        return self._internal_address_mask

    @internal_address_mask.setter
    def internal_address_mask(self, value):
        """
        Sets the address mask used internally for updating status.

        :param value: address mask
        :type value: int
        """
        self._internal_address_mask = value

    def open(self, baudrate=None, no_reader_thread=False):
        """
        Opens the device.

        :param baudrate: baudrate used for the device.  Defaults to the lower-level device default.
        :type baudrate: int
        :param no_reader_thread: Specifies whether or not the automatic reader
                                 thread should be started.
        :type no_reader_thread: bool
        """
        self._wire_events()
        self._device.open(baudrate=baudrate, no_reader_thread=no_reader_thread)

        return self

    def close(self):
        """
        Closes the device.
        """
        if self._device:
            self._device.close()

        del self._device
        self._device = None

    def send(self, data):
        """
        Sends data to the `AlarmDecoder`_ device.

        :param data: data to send
        :type data: string
        """

        if self._device:
            if isinstance(data, str):
                data = str.encode(data)

            # Hack to support unicode under Python 2.x
            if sys.version_info < (3, ):
                if isinstance(data, unicode):
                    data = bytes(data)

            self._device.write(data)

    def get_config(self):
        """
        Retrieves the configuration from the device.  Called automatically by :py:meth:`_on_open`.
        """
        self.send("C\r")

    def save_config(self):
        """
        Sets configuration entries on the device.
        """
        self.send("C{0}\r".format(self.get_config_string()))

    def get_config_string(self):
        config_entries = []

        # HACK: This is ugly.. but I can't think of an elegant way of doing it.
        config_entries.append(('ADDRESS', '{0}'.format(self.address)))
        config_entries.append(('CONFIGBITS', '{0:x}'.format(self.configbits)))
        config_entries.append(('MASK', '{0:x}'.format(self.address_mask)))
        config_entries.append(
            ('EXP', ''.join(['Y' if z else 'N' for z in self.emulate_zone])))
        config_entries.append(
            ('REL', ''.join(['Y' if r else 'N' for r in self.emulate_relay])))
        config_entries.append(('LRR', 'Y' if self.emulate_lrr else 'N'))
        config_entries.append(
            ('DEDUPLICATE', 'Y' if self.deduplicate else 'N'))
        config_entries.append(
            ('MODE',
             list(PANEL_TYPES)[list(PANEL_TYPES.values()).index(self.mode)]))

        config_string = '&'.join(['='.join(t) for t in config_entries])

        return '&'.join(['='.join(t) for t in config_entries])

    def get_version(self):
        """
        Retrieves the version string from the device.  Called automatically by :py:meth:`_on_open`.
        """
        self.send("V\r")

    def reboot(self):
        """
        Reboots the device.
        """
        self.send('=')

    def fault_zone(self, zone, simulate_wire_problem=False):
        """
        Faults a zone if we are emulating a zone expander.

        :param zone: zone to fault
        :type zone: int
        :param simulate_wire_problem: Whether or not to simulate a wire fault
        :type simulate_wire_problem: bool
        """

        # Allow ourselves to also be passed an address/channel combination
        # for zone expanders.
        #
        # Format (expander index, channel)
        if isinstance(zone, tuple):
            expander_idx, channel = zone

            zone = self._zonetracker.expander_to_zone(expander_idx, channel)

        status = 2 if simulate_wire_problem else 1

        self.send("L{0:02}{1}\r".format(zone, status))

    def clear_zone(self, zone):
        """
        Clears a zone if we are emulating a zone expander.

        :param zone: zone to clear
        :type zone: int
        """
        self.send("L{0:02}0\r".format(zone))

    def _wire_events(self):
        """
        Wires up the internal device events.
        """
        self._device.on_open += self._on_open
        self._device.on_close += self._on_close
        self._device.on_read += self._on_read
        self._device.on_write += self._on_write
        self._zonetracker.on_fault += self._on_zone_fault
        self._zonetracker.on_restore += self._on_zone_restore

    def _handle_message(self, data):
        """
        Parses keypad messages from the panel.

        :param data: keypad data to parse
        :type data: string

        :returns: :py:class:`~alarmdecoder.messages.Message`
        """

        data = data.decode('utf-8')

        if data is not None:
            data = data.lstrip('\0')

        if data is None or data == '':
            raise InvalidMessageError()

        msg = None
        header = data[0:4]

        if header[0] != '!' or header == '!KPM':
            msg = self._handle_keypad_message(data)

        elif header == '!EXP' or header == '!REL':
            msg = self._handle_expander_message(data)

        elif header == '!RFX':
            msg = self._handle_rfx(data)

        elif header == '!LRR':
            msg = self._handle_lrr(data)

        elif data.startswith('!Ready'):
            self.on_boot()

        elif data.startswith('!CONFIG'):
            self._handle_config(data)

        elif data.startswith('!VER'):
            self._handle_version(data)

        elif data.startswith('!Sending'):
            self._handle_sending(data)

        return msg

    def _handle_keypad_message(self, data):
        """
        Handle keypad messages.

        :param data: keypad message to parse
        :type data: string

        :returns: :py:class:`~alarmdecoder.messages.Message`
        """
        msg = Message(data)

        if self._internal_address_mask & msg.mask > 0:
            self._update_internal_states(msg)

            self.on_message(message=msg)

        return msg

    def _handle_expander_message(self, data):
        """
        Handle expander messages.

        :param data: expander message to parse
        :type data: string

        :returns: :py:class:`~alarmdecoder.messages.ExpanderMessage`
        """
        msg = ExpanderMessage(data)

        self._update_internal_states(msg)
        self.on_expander_message(message=msg)

        return msg

    def _handle_rfx(self, data):
        """
        Handle RF messages.

        :param data: RF message to parse
        :type data: string

        :returns: :py:class:`~alarmdecoder.messages.RFMessage`
        """
        msg = RFMessage(data)

        self.on_rfx_message(message=msg)

        return msg

    def _handle_lrr(self, data):
        """
        Handle Long Range Radio messages.

        :param data: LRR message to parse
        :type data: string

        :returns: :py:class:`~alarmdecoder.messages.LRRMessage`
        """
        msg = LRRMessage(data)

        if msg.event_type == 'ALARM_PANIC':
            self._panic_status = True
            self.on_panic(status=True)

        elif msg.event_type == 'CANCEL':
            if self._panic_status is True:
                self._panic_status = False
                self.on_panic(status=False)

        self.on_lrr_message(message=msg)

        return msg

    def _handle_version(self, data):
        """
        Handles received version data.

        :param data: Version string to parse
        :type data: string
        """

        _, version_string = data.split(':')
        version_parts = version_string.split(',')

        self.serial_number = version_parts[0]
        self.version_number = version_parts[1]
        self.version_flags = version_parts[2]

    def _handle_config(self, data):
        """
        Handles received configuration data.

        :param data: Configuration string to parse
        :type data: string
        """
        _, config_string = data.split('>')
        for setting in config_string.split('&'):
            key, val = setting.split('=')

            if key == 'ADDRESS':
                self.address = int(val)
            elif key == 'CONFIGBITS':
                self.configbits = int(val, 16)
            elif key == 'MASK':
                self.address_mask = int(val, 16)
            elif key == 'EXP':
                self.emulate_zone = [val[z] == 'Y' for z in list(range(5))]
            elif key == 'REL':
                self.emulate_relay = [val[r] == 'Y' for r in list(range(4))]
            elif key == 'LRR':
                self.emulate_lrr = (val == 'Y')
            elif key == 'DEDUPLICATE':
                self.deduplicate = (val == 'Y')
            elif key == 'MODE':
                self.mode = PANEL_TYPES[val]

        self.on_config_received()

    def _handle_sending(self, data):
        """
        Handles results of a keypress send.

        :param data: Sending string to parse
        :type data: string
        """

        matches = re.match('^!Sending(\.{1,5})done.*', data)
        if matches is not None:
            good_send = False
            if len(matches.group(1)) < 5:
                good_send = True

            self.on_sending_received(status=good_send, message=data)

    def _update_internal_states(self, message):
        """
        Updates internal device states.

        :param message: :py:class:`~alarmdecoder.messages.Message` to update internal states with
        :type message: :py:class:`~alarmdecoder.messages.Message`, :py:class:`~alarmdecoder.messages.ExpanderMessage`, :py:class:`~alarmdecoder.messages.LRRMessage`, or :py:class:`~alarmdecoder.messages.RFMessage`
        """
        if isinstance(message, Message):
            self._update_power_status(message)
            self._update_alarm_status(message)
            self._update_zone_bypass_status(message)
            self._update_armed_status(message)
            self._update_battery_status(message)
            self._update_fire_status(message)

        elif isinstance(message, ExpanderMessage):
            self._update_expander_status(message)

        self._update_zone_tracker(message)

    def _update_power_status(self, message):
        """
        Uses the provided message to update the AC power state.

        :param message: message to use to update
        :type message: :py:class:`~alarmdecoder.messages.Message`

        :returns: bool indicating the new status
        """
        if message.ac_power != self._power_status:
            self._power_status, old_status = message.ac_power, self._power_status

            if old_status is not None:
                self.on_power_changed(status=self._power_status)

        return self._power_status

    def _update_alarm_status(self, message):
        """
        Uses the provided message to update the alarm state.

        :param message: message to use to update
        :type message: :py:class:`~alarmdecoder.messages.Message`

        :returns: bool indicating the new status
        """

        if message.alarm_sounding != self._alarm_status:
            self._alarm_status, old_status = message.alarm_sounding, self._alarm_status

            if old_status is not None:
                if self._alarm_status:
                    self.on_alarm(zone=message.numeric_code)
                else:
                    self.on_alarm_restored(zone=message.numeric_code)

        return self._alarm_status

    def _update_zone_bypass_status(self, message):
        """
        Uses the provided message to update the zone bypass state.

        :param message: message to use to update
        :type message: :py:class:`~alarmdecoder.messages.Message`

        :returns: bool indicating the new status
        """

        if message.zone_bypassed != self._bypass_status:
            self._bypass_status, old_status = message.zone_bypassed, self._bypass_status

            if old_status is not None:
                self.on_bypass(status=self._bypass_status)

        return self._bypass_status

    def _update_armed_status(self, message):
        """
        Uses the provided message to update the armed state.

        :param message: message to use to update
        :type message: :py:class:`~alarmdecoder.messages.Message`

        :returns: bool indicating the new status
        """

        self._armed_status, old_status = message.armed_away, self._armed_status
        self._armed_stay, old_stay = message.armed_home, self._armed_stay
        if message.armed_away != old_status or message.armed_home != old_stay:
            if old_status is not None:
                if self._armed_status or self._armed_stay:
                    self.on_arm(stay=message.armed_home)
                else:
                    self.on_disarm()

        return self._armed_status or self._armed_stay

    def _update_battery_status(self, message):
        """
        Uses the provided message to update the battery state.

        :param message: message to use to update
        :type message: :py:class:`~alarmdecoder.messages.Message`

        :returns: boolean indicating the new status
        """

        last_status, last_update = self._battery_status
        if message.battery_low == last_status:
            self._battery_status = (last_status, time.time())
        else:
            if message.battery_low is True or time.time(
            ) > last_update + self._battery_timeout:
                self._battery_status = (message.battery_low, time.time())
                self.on_low_battery(status=message.battery_low)

        return self._battery_status[0]

    def _update_fire_status(self, message):
        """
        Uses the provided message to update the fire alarm state.

        :param message: message to use to update
        :type message: :py:class:`~alarmdecoder.messages.Message`

        :returns: boolean indicating the new status
        """

        last_status, last_update = self._fire_status
        if message.fire_alarm == last_status:
            self._fire_status = (last_status, time.time())
        else:
            if message.fire_alarm is True or time.time(
            ) > last_update + self._fire_timeout:
                self._fire_status = (message.fire_alarm, time.time())
                self.on_fire(status=message.fire_alarm)

        return self._fire_status[0]

    def _update_expander_status(self, message):
        """
        Uses the provided message to update the expander states.

        :param message: message to use to update
        :type message: :py:class:`~alarmdecoder.messages.ExpanderMessage`

        :returns: boolean indicating the new status
        """

        if message.type == ExpanderMessage.RELAY:
            self._relay_status[(message.address,
                                message.channel)] = message.value

            self.on_relay_changed(message=message)

            return self._relay_status[(message.address, message.channel)]

    def _update_zone_tracker(self, message):
        """
        Trigger an update of the :py:class:`~alarmdecoder.messages.Zonetracker`.

        :param message: message to update the zonetracker with
        :type message: :py:class:`~alarmdecoder.messages.Message`, :py:class:`~alarmdecoder.messages.ExpanderMessage`, :py:class:`~alarmdecoder.messages.LRRMessage`, or :py:class:`~alarmdecoder.messages.RFMessage`
        """

        # Retrieve a list of faults.
        # NOTE: This only happens on first boot or after exiting programming mode.
        if isinstance(message, Message):
            if not message.ready and "* para fallos" in message.text:
                self.send('*')
                return

        self._zonetracker.update(message)

    def _on_open(self, sender, *args, **kwargs):
        """
        Internal handler for opening the device.
        """
        self.get_config()

        self.get_version()

        self.on_open()

    def _on_close(self, sender, *args, **kwargs):
        """
        Internal handler for closing the device.
        """
        self.on_close()

    def _on_read(self, sender, *args, **kwargs):
        """
        Internal handler for reading from the device.
        """
        data = kwargs.get('data', None)
        self.on_read(data=data)

        self._handle_message(data)

    def _on_write(self, sender, *args, **kwargs):
        """
        Internal handler for writing to the device.
        """
        self.on_write(data=kwargs.get('data', None))

    def _on_zone_fault(self, sender, *args, **kwargs):
        """
        Internal handler for zone faults.
        """
        self.on_zone_fault(*args, **kwargs)

    def _on_zone_restore(self, sender, *args, **kwargs):
        """
        Internal handler for zone restoration.
        """
        self.on_zone_restore(*args, **kwargs)
Example #34
0
    algorithms_available = set(__always_supported)

    algorithms = __always_supported

    __all__ = __always_supported + ('new', 'algorithms_guaranteed',
                                    'algorithms_available', 'algorithms',
                                    'pbkdf2_hmac')

    try:
        # OpenSSL's PKCS5_PBKDF2_HMAC requires OpenSSL 1.0+ with HMAC and SHA
        from _hashlib import pbkdf2_hmac
    except ImportError:
        import binascii
        import struct

        _trans_5C = b''.join(chr(i ^ 0x5C) for i in range(256))
        _trans_36 = b''.join(chr(i ^ 0x36) for i in range(256))

        def pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None):
            """
            Password based key derivation function 2 (PKCS #5 v2.0)

            This Python implementations based on the hmac module about as fast
            as OpenSSL's PKCS5_PBKDF2_HMAC for short passwords and much faster
            for long passwords.
            """
            if not isinstance(hash_name, str):
                raise TypeError(hash_name)

            if not isinstance(password, (bytes, bytearray)):
                password = bytes(buffer(password))
Example #35
0
 def getkey_patched(self):
     c = self.enc_stdin.read(1)
     if c == chr(0x7f):
         c = chr(
             8)  # map the BS key (which yields DEL) to backspace
     return c
Example #36
0
    self._timestamp_coder_impl = TimestampCoderImpl()
    self._payload_coder_impl = payload_coder_impl

  def encode_to_stream(self, value, out, nested):
    self._timestamp_coder_impl.encode_to_stream(value['timestamp'], out, True)
    self._payload_coder_impl.encode_to_stream(value.get('payload'), out, True)

  def decode_from_stream(self, in_stream, nested):
    # TODO(robertwb): Consider using a concrete class rather than a dict here.
    return dict(
        timestamp=self._timestamp_coder_impl.decode_from_stream(
            in_stream, True),
        payload=self._payload_coder_impl.decode_from_stream(in_stream, True))


small_ints = [chr(_).encode('latin-1') for _ in range(128)]


class VarIntCoderImpl(StreamCoderImpl):
  """For internal use only; no backwards-compatibility guarantees.

  A coder for long/int objects."""

  def encode_to_stream(self, value, out, nested):
    out.write_var_int64(value)

  def decode_from_stream(self, in_stream, nested):
    return in_stream.read_var_int64()

  def encode(self, value):
    ivalue = value  # type cast
Example #37
0
 def read_string(self, timeout_ms=100):
     """Read an ASCII string."""
     return ''.join([chr(item) for item in self.read_bytes(MAX_INPUT_REPORT_SIZE, timeout_ms=timeout_ms) if item != 0])
Example #38
0
 def to_hx(c):
     h = int("%s" % c.groups(0), 16)
     if 19 < h < 160:
         return chr(h)
     else:
         return ""
Example #39
0
def solve_ilp(structure, gene, sam, solver):
    log.debug('== Initial Solver ==')

    structure, region_cn = structure
    log.debug('Solving {}', structure)
    if len(structure) == 0:  # only deletions
        print('>> {} -> 0 @ []'.format(dict(structure)))
        return 0, [([gene.deletion_allele] * 2, region_cn)]

    # More filtering
    alleles = []
    cnv_filter(sam, gene, region_cn)
    for an, a in sorted(list(gene.alleles.items()),
                        key=lambda x: sort_key(x[0])):
        remove = any(sam[m] <= 0 for m in a.functional_mutations)
        if remove:
            s = ['Extra Removing {:4}  '.format(an)]
            for m in a.functional_mutations:
                if sam[m] <= 0:
                    s.append('{} {}'.format(gene.region_at[m.pos], m))
            log.trace(s[0] + ',  '.join(s[1:]))
        elif a.cnv_configuration in structure:
            alleles.append(an)

    # Check for novel functional mutations
    novel_functional_mutations = set()
    for pos, c in sam.coverage.items():
        for op, cov in c.items():
            if op == '_':
                continue
            if (pos, op) in gene.mutations:
                continue
            # TODO: handle these regions as well
            if gene.region_at[pos][2:] not in gene.unique_regions:
                continue
            if region_cn[gene.region_at[pos]] == 0:
                continue
            # Require AT LEAST 80% coverage per copy
            if sam.percentage(Mutation(
                    pos, op)) < 80.0 / region_cn[gene.region_at[pos]]:
                continue
            if check_functional(gene, Mutation(pos, op)):
                log.debug('Novel mutation: {} {} {} ({} or {}%)',
                          gene.region_at[pos][2:], pos, op, cov,
                          sam.percentage(Mutation(pos, op)))
                novel_functional_mutations.add(Mutation(pos, op, True))
    # log.debug('Novel mutations: {}', list(novel_functional_mutations))

    if set(structure.keys()) - set(gene.alleles[a].cnv_configuration
                                   for a in alleles):
        print('>> {} -> inf @ []'.format(dict(structure)))
        return float('inf'), [
        ]  # Some structure has no matching allele; no solutions

    rejected = []
    if sam.PHASE:
        for a in alleles:
            muts = sorted(
                (m.pos, m.op) for m in gene.alleles[a].functional_mutations)
            for mi, m in enumerate(muts):
                for mj in range(mi + 1, len(muts)):
                    if abs(muts[mi][0] - muts[mj][0]) > 50:
                        continue
                    if sam.links[(muts[mi], muts[mj])] <= 1:
                        # Make sure that we have backup mutations to fall back upon
                        # TODO: find better way
                        other_mathcing = [
                            s for s in sam.links if s[0] == muts[mi]
                        ]
                        if len(other_mathcing) > 1:
                            rejected.append(a)
                            break
                if len(rejected) > 0 and rejected[-1] == a:
                    break
    log.debug('Rejected alleles: {}', rejected)
    alleles = {(a, 0): gene.alleles[a] for a in alleles if a not in rejected}

    c = lpinterface.model('aldy_major_allele', solver)

    log.debug('Possible candidates:')
    for a, _ in sorted(list(alleles.keys()), key=lambda x: sort_key(x[0])):
        log.debug('  {}*{}', gene.name, a)
        for m in sorted(alleles[(a, 0)].functional_mutations,
                        key=lambda m: m.pos):
            log.debug('    {} {} {:4} ({:3.0f}) {} {}', gene.region_at[m.pos],
                      m, sam[m], sam.percentage(m), 'F', m.aux['old'])
    # create special allele for any possible copy
    for a, _ in list(alleles.keys()):
        max_cn = sum(structure.values())
        log.trace('M  Max. CN for {} = {}', a, max_cn)
        for i in range(1, max_cn):
            alleles[(a, i)] = alleles[(a, 0)]

    # add one binary variable to model for any allele copy
    A = {a: c.addVar(vtype='B', name='A_{}_{}'.format(*a)) for a in alleles}
    # for any mutation, add error variable to expression
    constraints = {
        # m -> constraint, error_var
        m:
        [0, c.addVar(lb=-c.INF, ub=c.INF, name='MA_{}_{}_{}'.format(m, *a))]
        for a in alleles for m in alleles[a].functional_mutations
    }
    # add binary variable for any allele/mutation pair
    M = {
        a: {
            m: c.addVar(vtype='B', name='EXTRA_{}_{}_{}'.format(m, *a))
            for m in constraints if m not in alleles[a].functional_mutations
        }
        for a in alleles
    }
    # populate constraints
    for a in alleles:
        for m in alleles[a].functional_mutations:
            if region_cn[gene.region_at[m.pos]] == 0:
                coverage = 0
            else:
                coverage = max(1, sam.total(m.pos)) / float(
                    region_cn[gene.region_at[m.pos]])
            constraints[m][0] += coverage * A[a]
    for a in M:
        for m in M[a]:
            if region_cn[gene.region_at[m.pos]] != 0:
                constraints[m][0] += coverage * A[a] * M[a][m]
    # populate constraints for non-variations
    for m in list(constraints.keys()):
        if m.op[:3] == 'INS':
            continue  # no need for insertions...
        ref_m = Mutation(pos=m.pos, op='REF')
        if ref_m in constraints:
            ref_m = Mutation(pos=m.pos, op=ref_m.op + '#')
        if ref_m not in constraints:
            constraints[ref_m] = [
                0, c.addVar(lb=-c.INF, ub=c.INF, name=str(ref_m))
            ]

        if region_cn[gene.region_at[m.pos]] == 0:
            coverage = 0
        else:
            coverage = max(1, sam.total(m.pos)) / float(
                region_cn[gene.region_at[m.pos]])
        for a in alleles:
            constraints[ref_m][0] += coverage * A[a]

    # make sure that each constraint equals its coverage
    for m, (expr, err) in sorted(constraints.items()):
        log.trace('M  Contraint for {} {}: {} == {} + err', m,
                  gene.region_at[m.pos], sam[m], expr)
        c.addConstr(expr + err == sam[m])
        print('>> {}'.format(
            (m, gene.region_at[m.pos], sam[m], sam.total(m.pos))))

    # force alleles to be as much as needed
    for a, cnt in structure.items():
        expr = sum(A[y] for y in A if alleles[y].cnv_configuration == a)
        log.trace('M  CN contraint for {}: {} == {}', a, cnt, expr)
        c.addConstr(expr == cnt)

    # Make sure that A[i+1] <= A[i] (to avoid equivalent solutions)
    for a, ai in alleles:
        if ai != 0:
            continue
        for i in itertools.count(1):
            if (a, i) not in A:
                break
            log.trace('M  Sentinel contraint for {}: A_{} <= A_{}', a, i,
                      i - 1)
            c.addConstr(A[(a, i)] <= A[(a, i - 1)])

    # allele must express all of its functional functional_mutations
    for m in (m for a in alleles for m in alleles[a].functional_mutations
              if sam[m] > 0):
        expr = c.quicksum(
            [A[a] for a in alleles if m in alleles[a].functional_mutations])
        expr += c.quicksum([
            A[a] * M[a][m] for a in alleles
            if m not in alleles[a].functional_mutations
        ])
        log.trace('M  Contraint for {}: 1 <= {}', m, expr)
        c.addConstr(expr >= 1)

    # set objective: minimize absolute sum of errors
    # also make sure that every non-expressed snp gets heavily penalized
    penal = 100000
    objective = c.abssum([
        cx[1] for cx in constraints.values()
    ]) + penal * c.quicksum([M[a][m] for a in M for m in M[a]])
    log.trace('M  Objective: {}', objective)

    # solve ILP
    try:
        status, opt, solutions = c.solveAll(
            objective,
            dict([((k, ), v) for k, v in A.items()] + [((a, m), M[a][m])
                                                       for a in M
                                                       for m in M[a]]))
        log.debug('CN Solver status: {}, opt: {}', status, opt)
    except lpinterface.NoSolutionsError:
        print('>> {} -> inf @ []'.format(dict(structure)))
        return float('inf'), []

    unique_key = collections.defaultdict(str)
    for si, s in enumerate(solutions):
        sd = {
            x[0]: [y[1] for y in s if len(y) == 2 and y[0] == x[0]]
            for x in s if len(x) == 1
        }
        solutions[si] = []
        for (a, _), extra in sd.items():
            if len(extra) > 0:
                log.warn('Novel major star-allele (*{}-like) found!', a)
                extra = [
                    Mutation(m.pos, m.op, m.functional,
                             dict(list(m.aux.items()) + [('novel', True)]))
                    for m in extra
                ]
                an = Allele(
                    gene.alleles[a].name +
                    '+{};{}'.format(unique_key[gene.alleles[a].name], ','.join(
                        str(m)
                        for m in extra)), gene.alleles[a].cnv_configuration,
                    gene.alleles[a].functional_mutations | set(extra),
                    gene.alleles[a].suballeles)
                unique_key[gene.alleles[a].name] = 'a' if unique_key[
                    gene.alleles[a].name] == '' else chr(
                        ord(unique_key[gene.alleles[a].name]) + 1)
                gene.alleles[an.name] = an
                solutions[si].append(an.name)
            else:
                solutions[si].append(a)
    log.debug('  solution:')
    for s in solutions:
        log.debug('    {}', s)

    opt = round(opt, 2)
    print('>> {} -> {} @ {}'.format(dict(structure), opt, solutions))
    return opt, [(s, region_cn) for s in solutions]
Example #40
0
def parse_utf_html(url=os.path.join(DATA_PATH, 'utf8_table.html')):
    """ Parse HTML table UTF8 char descriptions returning DataFrame with `ascii` and `mutliascii` """
    utf = pd.read_html(url)
    utf = [df for df in utf if len(df) > 1023 and len(df.columns) > 2][0]
    utf = utf.iloc[:1024] if len(utf) == 1025 else utf
    utf.columns = 'char name hex'.split()
    utf.name = utf.name.str.replace('<control>', 'CONTTROL CHARACTER')
    multiascii = [' '] * len(utf)
    asc = [' '] * len(utf)
    rows = []
    for i, name in enumerate(utf.name):
        if i < 128 and str.isprintable(chr(i)):
            asc[i] = chr(i)
        else:
            asc[i] = ' '
        big = re.findall(r'CAPITAL\ LETTER\ ([a-z0-9A-Z ]+$)', name)
        small = re.findall(r'SMALL\ LETTER\ ([a-z0-9A-Z ]+$)', name)
        pattern = r'(?P<description>' \
                      r'(?P<lang>LATIN|GREEK|COPTIC|CYRILLIC)?[\s]*' \
                      r'(?P<case>CAPITAL|SMALL)?[\s]*' \
                      r'(?P<length>CHARACTER|LETTER)?[\s]*' \
                      r'(?P<ukrainian>BYELORUSSIAN-UKRAINIAN)?[\s]*' \
                      r'(?P<name>[-_><a-z0-9A-Z\s ]+)[\s]*' \
                      r'\(?(?P<code_point>U\+[- a-fA-F0-9]{4,8})?\)?)[\s]*'  # noqa
        match = re.match(pattern, name)
        gd = match.groupdict()
        gd['char'] = chr(i)
        gd['suffix'] = None
        gd['wordwith'] = None

        withprefix = re.match(
            r'(?P<prefix>DOTLESS|TURNED|SMALL)(?P<name>.*)' +
            r'(?P<wordwith>WITH|SUPERSCRIPT|SUBSCRIPT|DIGRAPH)\s+(?P<suffix>[-_><a-z0-9A-Z\s ]+)',
            gd['name'])
        if withprefix:
            gd.update(withprefix.groupdict())

        withsuffix = re.match(
            r'(?P<name>.*)(?P<wordwith>WITH|SUPERSCRIPT|SUBSCRIPT|DIGRAPH)\s+'
            + r'(?P<suffix>[-_><a-z0-9A-Z\s ]+)', gd['name'])
        if withsuffix:
            gd.update(withsuffix.groupdict())

        gd['code_point'] = gd['code_point'] or format_hex(
            i, num_bytes=4, prefix='U+').upper()
        if i < 128:
            gd['ascii'] = chr(i)
        else:
            multiascii = gd['name']
            if gd['suffix'] and gd['wordwith']:
                multiascii = NAME_ACCENT.get(gd['suffix'], "'")
            else:
                if big:
                    m = big[0]
                    multiascii[i] = m
                    if len(m) == 1:
                        asc[i] = m
                elif small:
                    multiascii[i] = small[0].lower()
                    if len(multiascii[i]) == 1:
                        asc[i] = small[0].lower()
        rows.append(gd)
    df = pd.DataFrame(rows)
    df.multiascii = df.multiascii.str.strip()
    df['ascii'] = df['ascii'].str.strip()
    df.name = df.name.str.strip()
    return df
Example #41
0
    def test_makeKeyTokens_(self):
        # see http://www.w3.org/TR/REC-xml/#d0e804 for a list of valid characters

        invalidTokens = []
        validTokens = []

        # all test tokens will be generated by prepending or inserting characters to this token
        validBase = "valid"

        # some invalid characters, not allowed anywhere in a token
        # note that '/' must not be added here because it is taken as a separator by makeKeyTokens_()
        invalidChars = "+*,;<>|!$%()=?#\x01"

        # generate the characters that are allowed at the start of a token (and at every other position)
        validStartChars = ":_"
        charRanges = [
            (ord('a'), ord('z')),
            (ord('A'), ord('Z')),
            (0x00F8, 0x02FF),
            (0x0370, 0x037D),
            (0x037F, 0x1FFF),
            (0x200C, 0x200D),
            (0x2070, 0x218F),
            (0x2C00, 0x2FEF),
            (0x3001, 0xD7FF),
            (0xF900, 0xFDCF),
            (0xFDF0, 0xFFFD),
            #(0x10000, 0xEFFFF),   while actually valid, these are not yet accepted by makeKeyTokens_()
        ]
        for r in charRanges:
            for c in range(r[0], r[1]):
                validStartChars += chr(c)

        # generate the characters that are only allowed inside a token, not at the start
        validInlineChars = "-.\xB7"
        charRanges = [
            (ord('0'), ord('9')),
            (0x0300, 0x036F),
            (0x203F, 0x2040),
        ]
        for r in charRanges:
            for c in range(r[0], r[1]):
                validInlineChars += chr(c)

        # test forbidden start characters
        for c in invalidChars + validInlineChars:
            invalidTokens.append(c + validBase)

        # test forbidden inline characters
        for c in invalidChars:
            invalidTokens.append(validBase[:4] + c + validBase[4:])

        # test each allowed start character
        for c in validStartChars:
            validTokens.append(c + validBase)

        # test each allowed inline character
        for c in validInlineChars:
            validTokens.append(validBase[:4] + c + validBase[4:])

        logger = QgsMessageLog.instance()
        logger.messageReceived.connect(self.catchMessage)
        prj = QgsProject.instance()

        for token in validTokens:
            self.messageCaught = False
            prj.readEntry("test", token)
            myMessage = "valid token '%s' not accepted" % (token)
            assert not self.messageCaught, myMessage

        for token in invalidTokens:
            self.messageCaught = False
            prj.readEntry("test", token)
            myMessage = "invalid token '%s' accepted" % (token)
            assert self.messageCaught, myMessage

        logger.messageReceived.disconnect(self.catchMessage)
            imgFilename))
        continue
    else:
        print("Processing image {0} of {1}: {2}".format(
            imgFilenameIndex, len(imgFilenames), imgPath))

    # prepare image window and callback
    global_bboxes = []
    global_image, scaleFactor = imresizeMaxDim(imread(imgPath), drawingImgSize)
    cv2.namedWindow("AnnotationWindow")
    cv2.setMouseCallback("AnnotationWindow", event_cv2_drawRectangles)
    cv2.imshow("AnnotationWindow", global_image)

    # process user input
    while True:
        key = chr(cv2.waitKey())

        # undo/remove last rectangle
        if key == "u":
            if len(global_bboxes) >= 1:
                global_bboxes = global_bboxes[:-1]
                imgCopy = global_image.copy()
                drawRectangles(imgCopy, global_bboxes)
                cv2.imshow("AnnotationWindow", imgCopy)

        # skip image
        elif key == "s":
            if os.path.exists(bBoxPath):
                print("Skipping image hence deleting existing bbox file: " +
                      bBoxPath)
                os.remove(bBoxPath)
Example #43
0
    def populateView(self):
        """
        The UI
        """
        self.fillColor = getExtensionDefaultColor(self.DEFAULTKEY_FILLCOLOR,
                                                  self.FALLBACK_FILLCOLOR)
        self.strokeColor = getExtensionDefaultColor(
            self.DEFAULTKEY_STROKECOLOR, self.FALLBACK_STROKECOLOR)
        self.contextBefore = self.contextAfter = ''

        # Populating the view can only happen after the view is attached to the window,
        # or else the relative widths go wrong.
        view = self.getView()
        view.add = Button((-40, 3, 30, 22), '+', callback=self.addCallback)
        view.reset = Button((-40, 30, 30, 22),
                            chr(8634),
                            callback=self.resetCallback)
        # Flag to see if the selection list click is in progress. We are resetting the selection
        # ourselves, using the list "buttons", but changing that selection will cause another
        # list update, that should be ignored.
        self._selectionChanging = False
        # Indicate that we are a drawing module
        self._canDraw = True

        self.sources = []

        x = y = 4

        view.fontList = List(
            (C.C2, y, 250, -65),
            self.getFontItems(),
            selectionCallback=self.fontListCallback,
            drawFocusRing=False,
            enableDelete=False,
            allowsMultipleSelection=False,
            allowsEmptySelection=True,
            drawHorizontalLines=True,
            showColumnTitles=False,
            columnDescriptions=self.getPathListDescriptor(),
            rowHeight=16,
        )
        view.viewEnabled = CheckBox((x, y, C.BUTTON_WIDTH, 22),
                                    "Show",
                                    callback=self.viewCallback,
                                    sizeStyle=C.STYLE_CHECKBOXSIZE,
                                    value=True)
        y += C.L
        view.fill = CheckBox(
            (x, y, 60, 22),
            "Fill",
            sizeStyle=C.STYLE_CHECKBOXSIZE,
            #value=getExtensionDefault("%s.%s" %(self.DEFAULTKEY, "fill"), True),
            value=True,
            callback=self.fillCallback)
        y += C.L
        color = getExtensionDefaultColor(self.DEFAULTKEY_FILLCOLOR,
                                         self.FALLBACK_FILLCOLOR)
        view.color = ColorWell((x, y, 60, 22),
                               color=color,
                               callback=self.colorCallback)
        y += C.L + 5
        view.stroke = CheckBox(
            (x, y, 60, 22),
            "Stroke",
            sizeStyle=C.STYLE_CHECKBOXSIZE,
            #value=getExtensionDefault("%s.%s" %(self.DEFAULTKEY, "stroke"), False),
            value=False,
            callback=self.strokeCallback)

        y += C.LL
        view.alignText = TextBox((x, y, 90, 50),
                                 'Alignment',
                                 sizeStyle=C.STYLE_LABELSIZE)
        y += C.L
        view.align = RadioGroup((x, y, 90, 50), ['Left', 'Center', 'Right'],
                                isVertical=True,
                                sizeStyle=C.STYLE_RADIOSIZE,
                                callback=self.alignCallback)
        view.align.set(0)

        #view.contextLabel = TextBox((C.C2, -58, 90, 50), 'Contexts', sizeStyle=C.STYLE_LABELSIZE)

        view.viewCurrent = CheckBox((C.C2, -60, 150, 22),
                                    "Always View Current",
                                    sizeStyle=C.STYLE_CHECKBOXSIZE,
                                    value=False,
                                    callback=self.contextEditCallback)

        #view.contextUandlc = CheckBox((C.C2+170, -60, 85, 22), "Match Case", sizeStyle=C.STYLE_CHECKBOXSIZE,
        #    value = False,
        #    callback=self.contextEditCallback)

        view.contextBefore = EditText((C.C2, -30, 85, 20),
                                      callback=self.contextEditCallback,
                                      continuous=True,
                                      sizeStyle="small",
                                      placeholder='Left Context')
        view.contextCurrent = EditText(
            (C.C2 + 95, -30, 60, 20),
            callback=self.contextCurrentEditCallback,
            continuous=True,
            sizeStyle="small")
        view.contextAfter = EditText((C.C2 + 165, -30, 85, 20),
                                     callback=self.contextEditCallback,
                                     continuous=True,
                                     sizeStyle="small",
                                     placeholder='Right Context')
        self.activateModule()
        self.setUpBaseWindowBehavior()
Example #44
0
 def compressToUTF16(uncompressed):
     if uncompressed is None:
         return ""
     return _compress(uncompressed, 15, lambda a: chr(a + 32)) + " "
Example #45
0
    oct,
    open,
    pow,
    round,
    super,
    filter,
    map,
    zip)

import re
import string

from pugnlp import constants

# try to make constants string variables all uppercase and regex patterns lowercase
ASCII_CHARACTERS = ''.join([chr(i) for i in range(128)])

list_bullet = re.compile(r'^\s*[! \t@#%.?(*+=-_]*[0-9.]*[#-_.)]*\s+')
nondigit = re.compile(r"[^0-9]")
nonphrase = re.compile(r"[^-\w\s/&']")
parenthetical_time = re.compile(r'([^(]*)\(\s*(\d+)\s*(?:min)?\s*\)([^(]*)',
                                re.IGNORECASE)

fqdn = r'(\b[a-zA-Z0-9-.]+\b([.]' + r'|'.join(
    constants.tld_iana) + r'\b)\b)'  # noqa
fqdn_popular = r'(\b[a-zA-Z0-9-.]+\b([.]' + r'|'.join(
    constants.tld_popular) + r'\b)\b)'
username = r'(\b[a-zA-Z0-9-.!#$%&*+-/=?^_`{|}~]+\b)'

email = re.compile(r'(\b' + username + r'\b@\b' + fqdn + r'\b)')
email_popular = re.compile(r'(\b' + username + r'\b@\b' + fqdn_popular +
Example #46
0
def _decompress(length, resetValue, getNextValue):
    dictionary = {}
    enlargeIn = 4
    dictSize = 4
    numBits = 3
    entry = ""
    result = []

    data = Object(val=getNextValue(0), position=resetValue, index=1)

    for i in range(3):
        dictionary[i] = i

    bits = 0
    maxpower = math.pow(2, 2)
    power = 1

    while power != maxpower:
        resb = data.val & data.position
        data.position >>= 1
        if data.position == 0:
            data.position = resetValue
            data.val = getNextValue(data.index)
            data.index += 1

        bits |= power if resb > 0 else 0
        power <<= 1

    next = bits
    if next == 0:
        bits = 0
        maxpower = math.pow(2, 8)
        power = 1
        while power != maxpower:
            resb = data.val & data.position
            data.position >>= 1
            if data.position == 0:
                data.position = resetValue
                data.val = getNextValue(data.index)
                data.index += 1
            bits |= power if resb > 0 else 0
            power <<= 1
        c = chr(bits)
    elif next == 1:
        bits = 0
        maxpower = math.pow(2, 16)
        power = 1
        while power != maxpower:
            resb = data.val & data.position
            data.position >>= 1
            if data.position == 0:
                data.position = resetValue
                data.val = getNextValue(data.index)
                data.index += 1
            bits |= power if resb > 0 else 0
            power <<= 1
        c = chr(bits)
    elif next == 2:
        return ""

    dictionary[3] = c
    w = c
    result.append(c)
    counter = 0
    while True:
        counter += 1
        if data.index > length:
            return ""

        bits = 0
        maxpower = math.pow(2, numBits)
        power = 1
        while power != maxpower:
            resb = data.val & data.position
            data.position >>= 1
            if data.position == 0:
                data.position = resetValue
                data.val = getNextValue(data.index)
                data.index += 1
            bits |= power if resb > 0 else 0
            power <<= 1

        c = bits
        if c == 0:
            bits = 0
            maxpower = math.pow(2, 8)
            power = 1
            while power != maxpower:
                resb = data.val & data.position
                data.position >>= 1
                if data.position == 0:
                    data.position = resetValue
                    data.val = getNextValue(data.index)
                    data.index += 1
                bits |= power if resb > 0 else 0
                power <<= 1

            dictionary[dictSize] = chr(bits)
            dictSize += 1
            c = dictSize - 1
            enlargeIn -= 1
        elif c == 1:
            bits = 0
            maxpower = math.pow(2, 16)
            power = 1
            while power != maxpower:
                resb = data.val & data.position
                data.position >>= 1
                if data.position == 0:
                    data.position = resetValue
                    data.val = getNextValue(data.index)
                    data.index += 1
                bits |= power if resb > 0 else 0
                power <<= 1
            dictionary[dictSize] = chr(bits)
            dictSize += 1
            c = dictSize - 1
            enlargeIn -= 1
        elif c == 2:
            return "".join(result)

        if enlargeIn == 0:
            enlargeIn = math.pow(2, numBits)
            numBits += 1

        if c in dictionary:
            entry = dictionary[c]
        else:
            if c == dictSize:
                entry = w + w[0]
            else:
                return None
        result.append(entry)

        # Add w+entry[0] to the dictionary.
        dictionary[dictSize] = w + entry[0]
        dictSize += 1
        enlargeIn -= 1

        w = entry
        if enlargeIn == 0:
            enlargeIn = math.pow(2, numBits)
            numBits += 1
Example #47
0
    def eventFilter(self, watched, event):
        if not self.active:
            return False

        if event.type() == QtCore.QEvent.KeyRelease:
            key = event.key()
            modifiers = event.modifiers()
            if self.viewMode.handleKeyEvent(modifiers, key, event=event):
                self.update()

        if event.type() == QtCore.QEvent.KeyPress:
            #TODO: should we accept only certain keys ?
            key = event.key()
            modifiers = event.modifiers()
            if key == QtCore.Qt.Key_F2:
                if self.viewMode.isEditable():
                    if self.viewMode.isInEditMode():
                        self.viewMode.setEditMode(False)
                    else:
                        self.viewMode.setEditMode(True)

                    self.viewMode.draw(refresh=False)
            # switch view mode
            if key == QtCore.Qt.Key_V:
                print('SWITCH VIEW')
                offs = self.viewMode.getCursorOffsetInPage()
                base = self.viewMode.getDataModel().getOffset()
                self.switchViewMode()
                self._resize()
                self.viewMode.goTo(base + offs)
                self.update()

            if key == QtCore.Qt.Key_S:
                print('OPEN SOURCE')
                self.parent.openSourceWindow(self.dataModel.current_class)

            import pyperclip
            if event.modifiers() & QtCore.Qt.ControlModifier:
                if key == QtCore.Qt.Key_Insert:
                    if self.viewMode.selector.getCurrentSelection():
                        a, b = self.viewMode.selector.getCurrentSelection()

                        #print a, b
                        hx = ''
                        for s in self.dataModel.getStream(a, b):
                            hx += '{:02x}'.format(s)

                        pyperclip.copy(hx)
                        del pyperclip
                        #print pyperclip.paste()
                    #   print 'coppied'

            if event.modifiers() & QtCore.Qt.ShiftModifier:
                if key == QtCore.Qt.Key_Insert:
                    import re
                    hx = pyperclip.paste()
                    #print hx
                    L = re.findall(r'.{1,2}', hx, re.DOTALL)

                    array = ''
                    for s in L:
                        array += chr(int(s, 16))

                    #print 'write '
                    #print 'write'
                    #print array
                    self.dataModel.write(0, array)
                    self.viewMode.draw(True)
                    del pyperclip
                    #print array

                if key == QtCore.Qt.Key_F4:
                    self.unp = WUnpack(self, None)
                    self.unp.show()

            if key == QtCore.Qt.Key_F10:
                self.dataModel.flush()
                self.w = WHeaders(self, None)
                self.w.show()

            if not self.viewMode.isInEditMode():
                if key == QtCore.Qt.Key_Slash:
                    self.searchWindow.show()

                if key == QtCore.Qt.Key_N:
                    self.searchable.next(
                        self.viewMode.getCursorAbsolutePosition() + 1)

                if key == QtCore.Qt.Key_B:
                    self.searchable.previous(
                        self.viewMode.getCursorAbsolutePosition())

            # handle keys to view plugin
            if self.viewMode.handleKeyEvent(modifiers, key, event=event):
                event.accept()
                self.update()
                return True

        return False
Example #48
0
def chr(char):
    return builtins.chr(char)
Example #49
0
def py_to_a1_convert(pair):
    col = chr(pair[1] + 97)  # In ascii, 'a'=97
    row = str(
        8 - pair[0]
    )  # Chess counts from 1, not 0. (the row component of coords 'e2' to is 1, not 2.)
    return col + row
Example #50
0
class AlarmDecoder(object):
    """
    High-level wrapper around `AlarmDecoder`_ (AD2) devices.
    """

    # High-level Events
    on_arm = event.Event(
        "This event is called when the panel is armed.\n\n**Callback definition:** *def callback(device, stay)*"
    )
    on_disarm = event.Event(
        "This event is called when the panel is disarmed.\n\n**Callback definition:** *def callback(device)*"
    )
    on_power_changed = event.Event(
        "This event is called when panel power switches between AC and DC.\n\n**Callback definition:** *def callback(device, status)*"
    )
    on_ready_changed = event.Event(
        "This event is called when panel ready state changes.\n\n**Callback definition:** *def callback(device, status)*"
    )
    on_alarm = event.Event(
        "This event is called when the alarm is triggered.\n\n**Callback definition:** *def callback(device, zone)*"
    )
    on_alarm_restored = event.Event(
        "This event is called when the alarm stops sounding.\n\n**Callback definition:** *def callback(device, zone)*"
    )
    on_fire = event.Event(
        "This event is called when a fire is detected.\n\n**Callback definition:** *def callback(device, status)*"
    )
    on_bypass = event.Event(
        "This event is called when a zone is bypassed.  \n\n\n\n**Callback definition:** *def callback(device, status)*"
    )
    on_boot = event.Event(
        "This event is called when the device finishes booting.\n\n**Callback definition:** *def callback(device)*"
    )
    on_config_received = event.Event(
        "This event is called when the device receives its configuration. \n\n**Callback definition:** *def callback(device)*"
    )
    on_zone_fault = event.Event(
        "This event is called when :py:class:`~alarmdecoder.zonetracking.Zonetracker` detects a zone fault.\n\n**Callback definition:** *def callback(device, zone)*"
    )
    on_zone_restore = event.Event(
        "This event is called when :py:class:`~alarmdecoder.zonetracking.Zonetracker` detects that a fault is restored.\n\n**Callback definition:** *def callback(device, zone)*"
    )
    on_low_battery = event.Event(
        "This event is called when the device detects a low battery.\n\n**Callback definition:** *def callback(device, status)*"
    )
    on_panic = event.Event(
        "This event is called when the device detects a panic.\n\n**Callback definition:** *def callback(device, status)*"
    )
    on_relay_changed = event.Event(
        "This event is called when a relay is opened or closed on an expander board.\n\n**Callback definition:** *def callback(device, message)*"
    )
    on_chime_changed = event.Event(
        "This event is called when chime state changes.\n\n**Callback definition:** *def callback(device, message)*"
    )

    # Mid-level Events
    on_message = event.Event(
        "This event is called when standard panel :py:class:`~alarmdecoder.messages.Message` is received.\n\n**Callback definition:** *def callback(device, message)*"
    )
    on_expander_message = event.Event(
        "This event is called when an :py:class:`~alarmdecoder.messages.ExpanderMessage` is received.\n\n**Callback definition:** *def callback(device, message)*"
    )
    on_lrr_message = event.Event(
        "This event is called when an :py:class:`~alarmdecoder.messages.LRRMessage` is received.\n\n**Callback definition:** *def callback(device, message)*"
    )
    on_rfx_message = event.Event(
        "This event is called when an :py:class:`~alarmdecoder.messages.RFMessage` is received.\n\n**Callback definition:** *def callback(device, message)*"
    )
    on_sending_received = event.Event(
        "This event is called when a !Sending.done message is received from the AlarmDecoder.\n\n**Callback definition:** *def callback(device, status, message)*"
    )
    on_aui_message = event.Event(
        "This event is called when an :py:class`~alarmdecoder.messages.AUIMessage` is received\n\n**Callback definition:** *def callback(device, message)*"
    )

    # Low-level Events
    on_open = event.Event(
        "This event is called when the device has been opened.\n\n**Callback definition:** *def callback(device)*"
    )
    on_close = event.Event(
        "This event is called when the device has been closed.\n\n**Callback definition:** *def callback(device)*"
    )
    on_read = event.Event(
        "This event is called when a line has been read from the device.\n\n**Callback definition:** *def callback(device, data)*"
    )
    on_write = event.Event(
        "This event is called when data has been written to the device.\n\n**Callback definition:** *def callback(device, data)*"
    )

    # Constants
    KEY_F1 = chr(1) + chr(1) + chr(1)
    """Represents panel function key #1"""
    KEY_F2 = chr(2) + chr(2) + chr(2)
    """Represents panel function key #2"""
    KEY_F3 = chr(3) + chr(3) + chr(3)
    """Represents panel function key #3"""
    KEY_F4 = chr(4) + chr(4) + chr(4)
    """Represents panel function key #4"""
    KEY_PANIC = chr(2) + chr(2) + chr(2)
    """Represents a panic keypress"""
    KEY_S1 = chr(1) + chr(1) + chr(1)
    """Represents panel special key #1"""
    KEY_S2 = chr(2) + chr(2) + chr(2)
    """Represents panel special key #2"""
    KEY_S3 = chr(3) + chr(3) + chr(3)
    """Represents panel special key #3"""
    KEY_S4 = chr(4) + chr(4) + chr(4)
    """Represents panel special key #4"""
    KEY_S5 = chr(5) + chr(5) + chr(5)
    """Represents panel special key #5"""
    KEY_S6 = chr(6) + chr(6) + chr(6)
    """Represents panel special key #6"""
    KEY_S7 = chr(7) + chr(7) + chr(7)
    """Represents panel special key #7"""
    KEY_S8 = chr(8) + chr(8) + chr(8)
    """Represents panel special key #8"""

    BATTERY_TIMEOUT = 30
    """Default timeout (in seconds) before the battery status reverts."""
    FIRE_TIMEOUT = 30
    """Default tTimeout (in seconds) before the fire status reverts."""

    # Attributes
    address = 18
    """The keypad address in use by the device."""
    configbits = 0xFF00
    """The configuration bits set on the device."""
    address_mask = 0xFFFFFFFF
    """The address mask configured on the device."""
    emulate_zone = [False for _ in list(range(5))]
    """List containing the devices zone emulation status."""
    emulate_relay = [False for _ in list(range(4))]
    """List containing the devices relay emulation status."""
    emulate_lrr = False
    """The status of the devices LRR emulation."""
    deduplicate = False
    """The status of message deduplication as configured on the device."""
    mode = ADEMCO
    """The panel mode that the AlarmDecoder is in.  Currently supports ADEMCO and DSC."""
    emulate_com = False
    """The status of the devices COM emulation."""

    #Version Information
    serial_number = 'Unknown'
    """The device serial number"""
    version_number = 'Unknown'
    """The device firmware version"""
    version_flags = ""
    """Device flags enabled"""
    def __init__(self,
                 device,
                 ignore_message_states=False,
                 ignore_lrr_states=True):
        """
        Constructor

        :param device: The low-level device used for this `AlarmDecoder`_
                       interface.
        :type device: Device
        :param ignore_message_states: Ignore regular panel messages when updating internal states
        :type ignore_message_states: bool
        :param ignore_lrr_states: Ignore LRR panel messages when updating internal states
        :type ignore_lrr_states: bool
        """
        self._device = device
        self._zonetracker = Zonetracker(self)
        self._lrr_system = LRRSystem(self)

        self._ignore_message_states = ignore_message_states
        self._ignore_lrr_states = ignore_lrr_states
        self._battery_timeout = AlarmDecoder.BATTERY_TIMEOUT
        self._fire_timeout = AlarmDecoder.FIRE_TIMEOUT
        self._power_status = None
        self._chime_status = None
        self._ready_status = None
        self._alarm_status = None
        self._bypass_status = {}
        self._armed_status = None
        self._entry_delay_off_status = None
        self._perimeter_only_status = None
        self._armed_stay = False
        self._exit = False
        self._fire_status = False
        self._fire_status_timeout = 0
        self._battery_status = (False, 0)
        self._panic_status = False
        self._relay_status = {}
        self._internal_address_mask = 0xFFFFFFFF

        self.last_fault_expansion = 0
        self.fault_expansion_time_limit = 30  # Seconds

        self.address = 18
        self.configbits = 0xFF00
        self.address_mask = 0xFFFFFFFF
        self.emulate_zone = [False for x in list(range(5))]
        self.emulate_relay = [False for x in list(range(4))]
        self.emulate_lrr = False
        self.deduplicate = False
        self.mode = ADEMCO
        self.emulate_com = False

        self.serial_number = 'Unknown'
        self.version_number = 'Unknown'
        self.version_flags = ""

    def __enter__(self):
        """
        Support for context manager __enter__.
        """
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        """
        Support for context manager __exit__.
        """
        self.close()

        return False

    @property
    def id(self):
        """
        The ID of the `AlarmDecoder`_ device.

        :returns: identification string for the device
        """
        return self._device.id

    @property
    def battery_timeout(self):
        """
        Retrieves the timeout for restoring the battery status, in seconds.

        :returns: battery status timeout
        """
        return self._battery_timeout

    @battery_timeout.setter
    def battery_timeout(self, value):
        """
        Sets the timeout for restoring the battery status, in seconds.

        :param value: timeout in seconds
        :type value: int
        """
        self._battery_timeout = value

    @property
    def fire_timeout(self):
        """
        Retrieves the timeout for restoring the fire status, in seconds.

        :returns: fire status timeout
        """
        return self._fire_timeout

    @fire_timeout.setter
    def fire_timeout(self, value):
        """
        Sets the timeout for restoring the fire status, in seconds.

        :param value: timeout in seconds
        :type value: int
        """
        self._fire_timeout = value

    @property
    def internal_address_mask(self):
        """
        Retrieves the address mask used for updating internal status.

        :returns: address mask
        """
        return self._internal_address_mask

    @internal_address_mask.setter
    def internal_address_mask(self, value):
        """
        Sets the address mask used internally for updating status.

        :param value: address mask
        :type value: int
        """
        self._internal_address_mask = value

    def open(self, baudrate=None, no_reader_thread=False):
        """Opens the device.

        If the device cannot be opened, an exception is thrown.  In that
        case, open() can be called repeatedly to try and open the
        connection.

        :param baudrate: baudrate used for the device.  Defaults to the lower-level device default.
        :type baudrate: int
        :param no_reader_thread: Specifies whether or not the automatic reader
                                 thread should be started.
        :type no_reader_thread: bool
        """
        self._wire_events()
        try:
            self._device.open(baudrate=baudrate,
                              no_reader_thread=no_reader_thread)
        except:
            self._unwire_events
            raise

        return self

    def close(self):
        """
        Closes the device.
        """
        self._device.close()
        self._unwire_events()

    def send(self, data):
        """
        Sends data to the `AlarmDecoder`_ device.

        :param data: data to send
        :type data: string
        """

        if self._device:
            if isinstance(data, str):
                data = str.encode(data)

            # Hack to support unicode under Python 2.x
            if sys.version_info < (3, ):
                if isinstance(data, unicode):
                    data = bytes(data)

            self._device.write(data)

    def get_config(self):
        """
        Retrieves the configuration from the device.  Called automatically by :py:meth:`_on_open`.
        """
        self.send("C\r")

    def save_config(self):
        """
        Sets configuration entries on the device.
        """
        self.send("C{0}\r".format(self.get_config_string()))

    def get_config_string(self):
        """
        Build a configuration string that's compatible with the AlarmDecoder configuration
        command from the current values in the object.

        :returns: string
        """
        config_entries = []

        # HACK: This is ugly.. but I can't think of an elegant way of doing it.
        config_entries.append(('ADDRESS', '{0}'.format(self.address)))
        config_entries.append(('CONFIGBITS', '{0:x}'.format(self.configbits)))
        config_entries.append(('MASK', '{0:x}'.format(self.address_mask)))
        config_entries.append(
            ('EXP', ''.join(['Y' if z else 'N' for z in self.emulate_zone])))
        config_entries.append(
            ('REL', ''.join(['Y' if r else 'N' for r in self.emulate_relay])))
        config_entries.append(('LRR', 'Y' if self.emulate_lrr else 'N'))
        config_entries.append(
            ('DEDUPLICATE', 'Y' if self.deduplicate else 'N'))
        config_entries.append(
            ('MODE',
             list(PANEL_TYPES)[list(PANEL_TYPES.values()).index(self.mode)]))
        config_entries.append(('COM', 'Y' if self.emulate_com else 'N'))

        config_string = '&'.join(['='.join(t) for t in config_entries])

        return '&'.join(['='.join(t) for t in config_entries])

    def get_version(self):
        """
        Retrieves the version string from the device.  Called automatically by :py:meth:`_on_open`.
        """
        self.send("V\r")

    def reboot(self):
        """
        Reboots the device.
        """
        self.send('=')

    def fault_zone(self, zone, simulate_wire_problem=False):
        """
        Faults a zone if we are emulating a zone expander.

        :param zone: zone to fault
        :type zone: int
        :param simulate_wire_problem: Whether or not to simulate a wire fault
        :type simulate_wire_problem: bool
        """

        # Allow ourselves to also be passed an address/channel combination
        # for zone expanders.
        #
        # Format (expander index, channel)
        if isinstance(zone, tuple):
            expander_idx, channel = zone

            zone = self._zonetracker.expander_to_zone(expander_idx, channel)

        status = 2 if simulate_wire_problem else 1

        self.send("L{0:02}{1}\r".format(zone, status))

    def clear_zone(self, zone):
        """
        Clears a zone if we are emulating a zone expander.

        :param zone: zone to clear
        :type zone: int
        """
        self.send("L{0:02}0\r".format(zone))

    def _wire_events(self):
        """
        Wires up the internal device events.
        """
        self._device.on_open += self._on_open
        self._device.on_close += self._on_close
        self._device.on_read += self._on_read
        self._device.on_write += self._on_write
        self._zonetracker.on_fault += self._on_zone_fault
        self._zonetracker.on_restore += self._on_zone_restore

    def _unwire_events(self):
        """
        Wires up the internal device events.
        """
        self._device.on_open -= self._on_open
        self._device.on_close -= self._on_close
        self._device.on_read -= self._on_read
        self._device.on_write -= self._on_write
        self._zonetracker.on_fault -= self._on_zone_fault
        self._zonetracker.on_restore -= self._on_zone_restore

    def _handle_message(self, data):
        """
        Parses keypad messages from the panel.

        :param data: keypad data to parse
        :type data: string

        :returns: :py:class:`~alarmdecoder.messages.Message`
        """

        try:
            data = data.decode('utf-8')
        except:
            raise InvalidMessageError(
                'Decode failed for message: {0}'.format(data))

        if data is not None:
            data = data.lstrip('\0')

        if data is None or data == '':
            raise InvalidMessageError()

        msg = None
        header = data[0:4]

        if header[0] != '!' or header == '!KPM':
            msg = self._handle_keypad_message(data)

        elif header == '!EXP' or header == '!REL':
            msg = self._handle_expander_message(data)

        elif header == '!RFX':
            msg = self._handle_rfx(data)

        elif header == '!LRR':
            msg = self._handle_lrr(data)

        elif header == '!AUI':
            msg = self._handle_aui(data)

        elif data.startswith('!Ready'):
            self.on_boot()

        elif data.startswith('!CONFIG'):
            self._handle_config(data)

        elif data.startswith('!VER'):
            self._handle_version(data)

        elif data.startswith('!Sending'):
            self._handle_sending(data)

        return msg

    def _handle_keypad_message(self, data):
        """
        Handle keypad messages.

        :param data: keypad message to parse
        :type data: string

        :returns: :py:class:`~alarmdecoder.messages.Message`
        """

        msg = Message(data)

        if self._internal_address_mask & msg.mask > 0:
            if not self._ignore_message_states:
                self._update_internal_states(msg)

            self.on_message(message=msg)

        return msg

    def _handle_expander_message(self, data):
        """
        Handle expander messages.

        :param data: expander message to parse
        :type data: string

        :returns: :py:class:`~alarmdecoder.messages.ExpanderMessage`
        """
        msg = ExpanderMessage(data)

        self._update_internal_states(msg)
        self.on_expander_message(message=msg)

        return msg

    def _handle_rfx(self, data):
        """
        Handle RF messages.

        :param data: RF message to parse
        :type data: string

        :returns: :py:class:`~alarmdecoder.messages.RFMessage`
        """
        msg = RFMessage(data)

        self.on_rfx_message(message=msg)

        return msg

    def _handle_lrr(self, data):
        """
        Handle Long Range Radio messages.

        :param data: LRR message to parse
        :type data: string

        :returns: :py:class:`~alarmdecoder.messages.LRRMessage`
        """
        msg = LRRMessage(data)

        if not self._ignore_lrr_states:
            self._lrr_system.update(msg)
        self.on_lrr_message(message=msg)

        return msg

    def _handle_aui(self, data):
        """
        Handle AUI messages.

        :param data: RF message to parse
        :type data: string

        :returns: :py:class`~alarmdecoder.messages.AUIMessage`
        """
        msg = AUIMessage(data)

        self.on_aui_message(message=msg)

        return msg

    def _handle_version(self, data):
        """
        Handles received version data.

        :param data: Version string to parse
        :type data: string
        """

        _, version_string = data.split(':')
        version_parts = version_string.split(',')

        self.serial_number = version_parts[0]
        self.version_number = version_parts[1]
        self.version_flags = version_parts[2]

    def _handle_config(self, data):
        """
        Handles received configuration data.

        :param data: Configuration string to parse
        :type data: string
        """
        _, config_string = data.split('>')
        for setting in config_string.split('&'):
            key, val = setting.split('=')

            if key == 'ADDRESS':
                self.address = int(val)
            elif key == 'CONFIGBITS':
                self.configbits = int(val, 16)
            elif key == 'MASK':
                self.address_mask = int(val, 16)
            elif key == 'EXP':
                self.emulate_zone = [val[z] == 'Y' for z in list(range(5))]
            elif key == 'REL':
                self.emulate_relay = [val[r] == 'Y' for r in list(range(4))]
            elif key == 'LRR':
                self.emulate_lrr = (val == 'Y')
            elif key == 'DEDUPLICATE':
                self.deduplicate = (val == 'Y')
            elif key == 'MODE':
                self.mode = PANEL_TYPES[val]
            elif key == 'COM':
                self.emulate_com = (val == 'Y')

        self.on_config_received()

    def _handle_sending(self, data):
        """
        Handles results of a keypress send.

        :param data: Sending string to parse
        :type data: string
        """

        matches = re.match('^!Sending(\.{1,5})done.*', data)
        if matches is not None:
            good_send = False
            if len(matches.group(1)) < 5:
                good_send = True

            self.on_sending_received(status=good_send, message=data)

    def _update_internal_states(self, message):
        """
        Updates internal device states.

        :param message: :py:class:`~alarmdecoder.messages.Message` to update internal states with
        :type message: :py:class:`~alarmdecoder.messages.Message`, :py:class:`~alarmdecoder.messages.ExpanderMessage`, :py:class:`~alarmdecoder.messages.LRRMessage`, or :py:class:`~alarmdecoder.messages.RFMessage`
        """
        if isinstance(message, Message) and not self._ignore_message_states:
            self._update_armed_ready_status(message)
            self._update_power_status(message)
            self._update_chime_status(message)
            self._update_alarm_status(message)
            self._update_zone_bypass_status(message)
            self._update_battery_status(message)
            self._update_fire_status(message)

        elif isinstance(message, ExpanderMessage):
            self._update_expander_status(message)

        self._update_zone_tracker(message)

    def _update_power_status(self, message=None, status=None):
        """
        Uses the provided message to update the AC power state.

        :param message: message to use to update
        :type message: :py:class:`~alarmdecoder.messages.Message`
        :param status: power status, overrides message bits.
        :type status: bool

        :returns: bool indicating the new status
        """
        power_status = status
        if isinstance(message, Message):
            power_status = message.ac_power

        if power_status is None:
            return

        if power_status != self._power_status:
            self._power_status, old_status = power_status, self._power_status

            if old_status is not None:
                self.on_power_changed(status=self._power_status)

        return self._power_status

    def _update_chime_status(self, message=None, status=None):
        """
        Uses the provided message to update the Chime state.

        :param message: message to use to update
        :type message: :py:class:`~alarmdecoder.messages.Message`
        :param status: chime status, overrides message bits.
        :type status: bool

        :returns: bool indicating the new status
        """
        chime_status = status
        if isinstance(message, Message):
            chime_status = message.chime_on

        if chime_status is None:
            return

        if chime_status != self._chime_status:
            self._chime_status, old_status = chime_status, self._chime_status

            if old_status is not None:
                self.on_chime_changed(status=self._chime_status)

        return self._chime_status

    def _update_alarm_status(self,
                             message=None,
                             status=None,
                             zone=None,
                             user=None):
        """
        Uses the provided message to update the alarm state.

        :param message: message to use to update
        :type message: :py:class:`~alarmdecoder.messages.Message`
        :param status: alarm status, overrides message bits.
        :type status: bool
        :param user: user associated with alarm event
        :type user: string

        :returns: bool indicating the new status
        """

        alarm_status = status
        alarm_zone = zone
        if isinstance(message, Message):
            alarm_status = message.alarm_sounding
            alarm_zone = message.parse_numeric_code()

        if alarm_status != self._alarm_status:
            self._alarm_status, old_status = alarm_status, self._alarm_status

            if old_status is not None or status is not None:
                if self._alarm_status:
                    self.on_alarm(zone=alarm_zone)
                else:
                    self.on_alarm_restored(zone=alarm_zone, user=user)

        return self._alarm_status

    def _update_zone_bypass_status(self, message=None, status=None, zone=None):
        """
        Uses the provided message to update the zone bypass state.

        :param message: message to use to update
        :type message: :py:class:`~alarmdecoder.messages.Message`
        :param status: bypass status, overrides message bits.
        :type status: bool
        :param zone: zone associated with bypass event
        :type zone: int

        :returns: dictionary {Zone:True|False,...}
           Zone can be None if LRR CID Bypass checking is disabled
           or we do not know what zones but know something is bypassed.
        """
        bypass_status = status
        if isinstance(message, Message):
            bypass_status = message.zone_bypassed

        if bypass_status is None:
            return

        old_bypass_status = self._bypass_status.get(zone, None)

        if bypass_status != old_bypass_status:
            if bypass_status == False and zone is None:
                self._bypass_status = {}
            else:
                self._bypass_status[zone] = bypass_status

            if old_bypass_status is not None or message is None or (
                    old_bypass_status is None and bypass_status is True):
                self.on_bypass(status=bypass_status, zone=zone)

        return bypass_status

    def _update_armed_ready_status(self, message=None):
        """
        Uses the provided message to update the armed state
        and ready state at once as they can change in the same
        message and we want both events to have the same states.
        :param message: message to use to update
        :type message: :py:class:`~alarmdecoder.messages.Message`

        """

        arm_status = None
        stay_status = None
        exit = None
        ready_status = None
        entry_delay_off_status = None
        perimeter_only_status = None
        send_ready = False
        send_arm = False

        if isinstance(message, Message):
            arm_status = message.armed_away
            stay_status = message.armed_home
            ready_status = message.ready
            entry_delay_off_status = message.entry_delay_off
            perimeter_only_status = message.perimeter_only

        if arm_status is None or stay_status is None or ready_status is None:
            return

        # if we are armed we may be in exit mode
        if arm_status or stay_status:
            exit = False
            messageUp = message.text.upper()

            if self.mode == ADEMCO:
                # skip these messages
                if not messageUp.startswith(
                        "SYSTEM") and not messageUp.startswith("CHECK"):
                    if "MAY EXIT NOW" in messageUp:
                        exit = True
                else:
                    # preserve last state
                    exit = self._exit

            if self.mode == DSC:
                if any(s in messageUp for s in ("QUICK EXIT", "EXIT DELAY")):
                    exit = True
        else:
            exit = False

        self._armed_stay, old_stay = stay_status, self._armed_stay
        self._armed_status, old_arm = arm_status, self._armed_status
        self._ready_status, old_ready_status = ready_status, self._ready_status
        self._entry_delay_off_status, old_entry_delay_off_status = entry_delay_off_status, self._entry_delay_off_status
        self._perimeter_only_status, old_perimeter_only_status = perimeter_only_status, self._perimeter_only_status
        self._exit, old_exit = exit, self._exit

        if old_arm is not None:
            if arm_status != old_arm or stay_status != old_stay:
                send_arm = True

        # This bit is expected to change only when the ARMED bit changes.
        # But just in case watch for it to change
        if old_entry_delay_off_status is not None:
            if entry_delay_off_status != old_entry_delay_off_status:
                send_ready = True

        # This bit can change after the armed bit is set
        # this will treat it like AWAY/Stay transition as an additional
        # arming event.
        if old_perimeter_only_status is not None:
            if perimeter_only_status != old_perimeter_only_status:
                send_ready = True

        if old_ready_status is not None:
            if ready_status != old_ready_status:
                send_ready = True

        # Send exist status updates in ready event
        if old_exit is not None:
            if exit != old_exit:
                send_ready = True

        if send_ready:
            self.on_ready_changed(status=self._ready_status)

        if send_arm:
            if self._armed_status or self._armed_stay:
                self.on_arm(stay=stay_status)
            else:
                self.on_disarm()

    def _update_armed_status(self,
                             message=None,
                             status=None,
                             status_stay=None):
        """
        Uses the provided message to update the armed state.

        :param message: message to use to update
        :type message: :py:class:`~alarmdecoder.messages.Message`
        :param status: armed status, overrides message bits
        :type status: bool
        :param status_stay: armed stay status, overrides message bits
        :type status_stay: bool

        :returns: bool indicating the new status
        """
        arm_status = status
        stay_status = status_stay

        if isinstance(message, Message):
            arm_status = message.armed_away
            stay_status = message.armed_home

        if arm_status is None or stay_status is None:
            return

        self._armed_status, old_status = arm_status, self._armed_status
        self._armed_stay, old_stay = stay_status, self._armed_stay
        if arm_status != old_status or stay_status != old_stay:
            if old_status is not None or message is None:
                if self._armed_status or self._armed_stay:
                    self.on_arm(stay=stay_status)
                else:
                    self.on_disarm()

        return self._armed_status or self._armed_stay

    def _update_battery_status(self, message=None, status=None):
        """
        Uses the provided message to update the battery state.

        :param message: message to use to update
        :type message: :py:class:`~alarmdecoder.messages.Message`
        :param status: battery status, overrides message bits
        :type status: bool

        :returns: boolean indicating the new status
        """
        battery_status = status
        if isinstance(message, Message):
            battery_status = message.battery_low

        if battery_status is None:
            return

        last_status, last_update = self._battery_status
        if battery_status == last_status:
            self._battery_status = (last_status, time.time())
        else:
            if battery_status is True or time.time(
            ) > last_update + self._battery_timeout:
                self._battery_status = (battery_status, time.time())
                self.on_low_battery(status=battery_status)

        return self._battery_status[0]

    def _update_fire_status(self, message=None, status=None):
        """
        Uses the provided message to update the fire alarm state.

        :param message: message to use to update
        :type message: :py:class:`~alarmdecoder.messages.Message`
        :param status: fire status, overrides message bits
        :type status: bool

        :returns: boolean indicating the new status
        """
        fire_status = status

        last_status = self._fire_status
        last_update = self._fire_status_timeout

        # Quirk in Ademco panels. Fire bit goes on/off if other alarms are on or a system fault
        if isinstance(message, Message):
            if self.mode == ADEMCO:
                # if we did not have an alarm and we do now send event
                if message.fire_alarm and message.fire_alarm != self._fire_status:
                    fire_status = message.fire_alarm

                # if we had an alarm and the sticky bit was cleared then clear the alarm
                ## ignore sticky bit on these messages :(
                if (not message.text.startswith("SYSTEM")
                        and not message.text.startswith("CHECK")):
                    if self._fire_status and not message.alarm_event_occurred:
                        # fire restore
                        fire_status = False

                # if we had a fire event and it went away and we still have a sticky alarm bit
                # then it is not gone yet just restore it
                if not message.fire_alarm and self._fire_status:
                    if message.alarm_event_occurred:
                        fire_status = self._fire_status

                # if we had an alarm already and we get it again extend the timeout
                if message.fire_alarm and message.fire_alarm == self._fire_status:
                    self._fire_status = message.fire_alarm
                    self._fire_status_timeout = time.time()

                # if we timeout with an alarm set restore it
                if self._fire_status:
                    if time.time() > last_update + self._fire_timeout:
                        fire_status = False

            else:
                fire_status = message.fire_alarm

        if fire_status != self._fire_status:
            if fire_status is not None:
                self._fire_status = fire_status
                self._fire_status_timeout = time.time()
                self.on_fire(status=fire_status)

        return self._fire_status

    def _update_panic_status(self, status=None):
        """
        Updates the panic status of the alarm panel.

        :param status: status to use to update
        :type status: boolean

        :returns: boolean indicating the new status
        """
        if status is None:
            return

        if status != self._panic_status:
            self._panic_status, old_status = status, self._panic_status

            if old_status is not None:
                self.on_panic(status=self._panic_status)

        return self._panic_status

    def _update_expander_status(self, message):
        """
        Uses the provided message to update the expander states.

        :param message: message to use to update
        :type message: :py:class:`~alarmdecoder.messages.ExpanderMessage`

        :returns: boolean indicating the new status
        """

        if message.type == ExpanderMessage.RELAY:
            self._relay_status[(message.address,
                                message.channel)] = message.value

            self.on_relay_changed(message=message)

            return self._relay_status[(message.address, message.channel)]

    def _update_zone_tracker(self, message):
        """
        Trigger an update of the :py:class:`~alarmdecoder.messages.Zonetracker`.

        :param message: message to update the zonetracker with
        :type message: :py:class:`~alarmdecoder.messages.Message`, :py:class:`~alarmdecoder.messages.ExpanderMessage`, :py:class:`~alarmdecoder.messages.LRRMessage`, or :py:class:`~alarmdecoder.messages.RFMessage`
        """

        # Retrieve a list of faults.
        # NOTE: This only happens on first boot or after exiting programming mode.
        if isinstance(message, Message):
            if not message.ready and ("Hit * for faults" in message.text
                                      or "Press *  to show faults"
                                      in message.text):
                if time.time(
                ) > self.last_fault_expansion + self.fault_expansion_time_limit:
                    self.last_fault_expansion = time.time()
                    self.send('*')
                    return

        self._zonetracker.update(message)

    def _on_open(self, sender, *args, **kwargs):
        """
        Internal handler for opening the device.
        """
        self.get_config()
        self.get_version()

        self.on_open()

    def _on_close(self, sender, *args, **kwargs):
        """
        Internal handler for closing the device.
        """
        self.on_close()

    def _on_read(self, sender, *args, **kwargs):
        """
        Internal handler for reading from the device.
        """
        data = kwargs.get('data', None)
        self.on_read(data=data)

        self._handle_message(data)

    def _on_write(self, sender, *args, **kwargs):
        """
        Internal handler for writing to the device.
        """
        self.on_write(data=kwargs.get('data', None))

    def _on_zone_fault(self, sender, *args, **kwargs):
        """
        Internal handler for zone faults.
        """
        self.on_zone_fault(*args, **kwargs)

    def _on_zone_restore(self, sender, *args, **kwargs):
        """
        Internal handler for zone restoration.
        """
        self.on_zone_restore(*args, **kwargs)
Example #51
0
                    Added NullDBConn, NullDBCursor, for testing database code
                    without actually modifying databases.
                    Added formatFieldEqVal to help generate select commands.
2006-01-17 ROwen    formatFieldEqVal: added sepStr argument.
2006-01-20 ROwen    Removed getLastInsertedIDMySQL since it didn't work as advertised;
                    use the cursor's lastrowid instead; for more information, see the MySQLDb manual
                    entry for insert_id(). (Note: despite the 1.2.0 manual, insert_id() is an attribute
                    of the connection, but is used to create the cursor's lastrowid.)
2006-01-31 ROwen    Added rowcount, lastrowid to NullDBCursor.
2006-02-16 ROwen    Modified NullDBCursor output to restrict long entries to _MaxDiagnosticLen.
2015-09-24 ROwen    Replace "== None" with "is None" to modernize the code.
"""
import time

_DataSepStr = '","'
_ArraySepStr = chr(29)
_MaxDiagnosticLen = 200  # max length for diagnostic output string


class FieldDescr(object):
    """A description of a data field in a database. At present this is primarily used
    to convert data from a text file to data in a form suitable for importing into a database.
    """
    def __init__(self,
                 fieldName,
                 cnvFunc=str,
                 blankOK=False,
                 blankVal=None,
                 isArray=False,
                 arraySep=_ArraySepStr):
        """Create a new database field descriptor.
Example #52
0
 def _event_char(self, msg, wParam, lParam):
     text = chr(wParam)
     if unicodedata.category(text) != 'Cc' or text == '\r':
         self.dispatch_event('on_text', text)
     return 0
Example #53
0
def file_type(filename):
    p = subprocess.Popen(['file',filename],stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
    output, errors = p.communicate()
    return output.decode("utf-8")

def is_Elf64(filename):
    magic = file_type(filename)
    return "ELF" in magic and "executable" in magic and "64-bit" in magic

def is_Elf32(filename):
    magic = file_type(filename)
    return "ELF" in magic and "executable" in magic and "32-bit" in magic


# The end-of-transmission character
EOT = chr(4)

# Exit codes used by this program
exit_codes = {"SUCCESS" : 0,
              "PROGRAM_FAILURE" : 1,
              "TIMEOUT" : 66,
              "VM_PANIC" : 67,
              "CALLBACK_FAILED" : 68,
              "ABORT" : 70,
              "VM_EOT" : 71,
              "BOOT_FAILED": 72,
              "PARSE_ERROR": 73,
              "UNSAFE": 74
}

def get_exit_code_name (exit_code):
Example #54
0
    def get(self, default_input=""):
        """Get input from user.

        Notes
        -----
        This displays and updates the input box automatically. Pressing ENTER
        returns the user input. Pressing ESC quits, returning an empty string.

        Parameters
        ----------
        default_input : str, optional
            default input in the textbox

        Returns
        -------
        text_input: str or None
            returns the entered text string. If get() is interrupted by a
            CallbackQuitEvent from a registered wait-callback-function get()
            returns None.

        See Also
        --------
        design.experiment.register_wait_callback_function

        """

        if android_show_keyboard is not None:
            android_show_keyboard()
        self._user = []
        for char in default_input:
            self._user.append(char)
        self._create()
        self._update()
        if self._character_filter is None:
            filter = list(range(0, 256)) + constants.K_ALL_KEYPAD_DIGITS
        else:
            filter = self._character_filter

        while True:
            inkey, string = self._get_key()
            if isinstance(inkey, CallbackQuitEvent):
                return None
            elif inkey == pygame.K_BACKSPACE:
                self._user = self._user[0:-1]
            elif inkey == pygame.K_RETURN or inkey == pygame.K_KP_ENTER:
                break
            elif inkey != pygame.K_LCTRL or inkey != pygame.K_RCTRL:
                if not self._user_text_surface_size[0] >= self._max_size[0]:
                    if android is not None:
                        if inkey in filter:
                            if inkey in constants.K_ALL_KEYPAD_DIGITS:
                                inkey = numpad_digit_code2ascii(inkey)
                            self._user.append(chr(inkey))
                    else:
                        if inkey in constants.K_ALL_KEYPAD_DIGITS:
                            self._user.append(
                                chr(numpad_digit_code2ascii(inkey)))
                        elif string and ord(string) in filter:
                            self._user.append(string)
            self._update()
        got = "".join(self._user)
        if self._logging:
            _internals.active_exp._event_file_log(
                "TextInput,entered,{0}".format(unicode2byte(got)))
        if android_hide_keyboard is not None:
            android_hide_keyboard()
        return got
Example #55
0
This holds a series of classes and functions for helping to manipulate
ANSI color codes.

In general, Lyntin keeps the data from the mud intact without doing any
transformations on it letting the ui do the transformations it needs to
do to display the mud data.  The exception to this is when the user has
shut off mudansi using the #config command.  Then we'll whack any incoming
ANSI color stuff before moving it around.
"""
from builtins import str
from builtins import chr
from builtins import range
import re

# for finding ANSI color sequences
ANSI_COLOR_REGEXP = re.compile(chr(27) + '\[[0-9;]*[m]')

STYLE_NORMAL = 0
STYLE_BOLD = 1
STYLE_UNDERLINE = 4
STYLE_BLINK = 5
STYLE_REVERSE = 7

# enums for placement in the color list
PLACE_BOLD = 0
PLACE_UNDERLINE = 1
PLACE_BLINK = 2
PLACE_REVERSE = 3
PLACE_FG = 4
PLACE_BG = 5
Example #56
0
def escapecp(cp):
    return "&%s;" % codepoint2name[cp] if (cp in codepoint2name) else chr(cp)
Example #57
0
from itertools import groupby, chain

from builtins import range, chr

AtMentionRegex = re.compile(RE_MENTION)
urlRegex = re.compile(RE_URL)

# from http://bit.ly/2rdjgjE (UTF-8 encodings and Unicode chars)
VARIATION_SELECTORS = [
    u'\ufe00', u'\ufe01', u'\ufe02', u'\ufe03', u'\ufe04', u'\ufe05',
    u'\ufe06', u'\ufe07', u'\ufe08', u'\ufe09', u'\ufe0a', u'\ufe0b',
    u'\ufe0c', u'\ufe0d', u'\ufe0e', u'\ufe0f'
]

# from https://stackoverflow.com/questions/92438/stripping-non-printable-characters-from-a-string-in-python
ALL_CHARS = (chr(i) for i in range(sys.maxunicode))
CONTROL_CHARS = ''.join(map(chr, chain(range(0, 32), range(127, 160))))
CONTROL_CHAR_REGEX = re.compile('[%s]' % re.escape(CONTROL_CHARS))


def is_special_token(word):
    equal = False
    for spec in SPECIAL_TOKENS:
        if word == spec:
            equal = True
            break
    return equal


def mostly_english(words,
                   english,
Example #58
0
def strxor(a, b):
    return "".join([chr(ord(x) ^ ord(y)) for (x, y) in zip(a, b)])
Example #59
0
 def write_byte(self, val):
     self.data.append(chr(val).encode('latin-1'))
Example #60
0
    def runui(self):
        #
        # This is the loop for user input polling and for mud output.
        #
        global HELP_TEXT

        exported.add_help("cursesui", HELP_TEXT)

        stdscr = curses.initscr()
        try:

            if curses.has_colors():
                curses.start_color()
                for i in range(1, 64):
                    curses.init_pair(i, i % 8, old_div(i, 8))
            curses.raw()
            curses.noecho()
            curses.nonl()
            curses.meta(1)

            out = None
            edit = None
            scrollback = None

            lines = self.lines_

            exported.write_message(
                "For Cursesui help, type \"#help cursesui\".")
            exported.write_message(
                "For some commands help, type \"#help curses\".")

            dirty_count = 0
            timestamp = 0
            output_count = 0

            hotkey_buffer = ''
            keyboard_buffer = []

            select_timeout = 100
            keyboard_fd = sys.stdin.fileno()
            output_pipe_fd = self.output_[0]
            select_input_list = [keyboard_fd, output_pipe_fd]

            while self.running_:

                #
                # set output windows:
                #
                if not out:
                    stdscr = curses.initscr()
                    (screen_h, screen_w) = stdscr.getmaxyx()
                    win = curses.newwin(1, screen_w, screen_h - 1, 0)
                    if edit:
                        edit.attach(win)
                    else:
                        edit = inputbox(self, win)
                    if not scrollback:
                        out = scroller(
                            curses.newwin(screen_h - 1, screen_w, 0, 0), lines)
                    else:
                        scroll_h = int(screen_h / 3 * 2)
                        out_h = (screen_h - 2) - scroll_h
                        scrollback = scroller(
                            curses.newwin(scroll_h, screen_w, 0, 0), lines[:])
                        scrollback.redraw()
                        wborder = curses.newwin(1, screen_w, scroll_h, 0)
                        wborder.bkgd(curses.ACS_HLINE)
                        wborder.erase()
                        wborder.noutrefresh()
                        out = scroller(
                            curses.newwin(out_h, screen_w, scroll_h + 1, 0),
                            lines)
                    out.redraw()

                edit._align()

                if keyboard_buffer and not hotkey_buffer:
                    ch = keyboard_buffer.pop()
                else:
                    try:
                        ch = win.get_wch()
                    except:
                        ch = curses.ERR
                    if ch == curses.ERR:

                        # drop the hotkey buffer when the keyboard goes idle
                        hotkey_buffer = ''

                        # enter idle mode:
                        try:
                            (i, o, x) = select.select(select_input_list, [],
                                                      [], select_timeout)
                        except:
                            # It's probably stray EINTR - further investigation is needed
                            (i, o, x) = (None, None, None)

                        if not i:
                            # timeout was hit:
                            out.redraw(self.cfg_maxscrollback_)
                            select_timeout = 100
                            dirty_count = 0
                            continue
                        else:

                            if keyboard_fd in i:
                                ch = win.get_wch()

                            if output_pipe_fd in i:
                                line = os.read(output_pipe_fd, 1024)
                                dirty_count += len(line)

                            if ch == curses.ERR:
                                timestamp_now = time()
                                if ((timestamp_now - timestamp) >
                                        0.2) or (dirty_count > self.cfg_lazy_):
                                    out.redraw(self.cfg_maxscrollback_)
                                    select_timeout = 100
                                    dirty_count = 0
                                    output_count = 0
                                else:
                                    select_timeout = 0.2
                                    output_count += 1
                                timestamp = timestamp_now
                                continue

                    keyboard_buffer.insert(0, ch)
                    #print("character " + ch + str(ord(ch)))
                    if type(ch) == str:
                        ch = ord(ch)
                    if ch < 256:
                        keycodename = chr(ch)
                        hotkey_buffer += keycodename

                        if self.cfg_keydebug_:
                            if is_a_char(keycodename):
                                exported.write_message(keycodename)
                            elif ch == 0x1b:
                                exported.write_message("<ESC>")

                        binding = bindings.get(hotkey_buffer)
                        if binding:
                            hotkey_buffer = ''
                            keyboard_buffer = []
                            self.handleinput(binding[1], internal=1)
                            continue
                        elif not [
                                x for x in list(bindings.keys())
                                if x.startswith(hotkey_buffer)
                        ]:
                            hotkey_buffer = ''
                        continue
                    else:
                        keycodename = keytext.get(ch)
                        if keycodename:
                            if self.cfg_keydebug_:
                                exported.write_message(keycodename)
                            binding = bindings.get(keycodename)
                            if binding:
                                self.handleinput(binding[1], internal=1)
                                keyboard_buffer.pop()  # get it back
                        hotkey_buffer = ''
                        continue

                if ch == curses.KEY_PPAGE:
                    if not scrollback:
                        scrollback = 1  # create scrollback window at next iteration
                        out = None
                    else:
                        scrollback.redraw(scroll=-(old_div(scroll_h, 2) + 1))
                    continue
                if ch == curses.KEY_NPAGE:
                    if scrollback:
                        scrollback.redraw(scroll=old_div(scroll_h, 2) + 1)
                    continue

                if ch == curses.ascii.ESC and scrollback:
                    scrollback = None
                    out = None
                    continue

                ch = edit.do_command(ch)
                if type(ch) == str:
                    ch = ord(ch)

                if ch in (curses.ascii.CR, curses.ascii.LF):
                    edit_string = edit.get_string()
                    if edit_string.strip() == "#end":
                        break
                    self.handleinput(edit_string)
                    edit.set("")

                elif ch in (curses.KEY_RESIZE,
                            curses.ascii.FF):  # force screen redraw
                    out = None
                    continue

                elif ch == curses.ascii.ETX:  # Ctrl-C
                    break

        finally:
            endcurses()