<commit_before>'''Cocos tilemap editor!

Usage: editor.py <level.xml>

The level must contain at least one <rectmap> and one <tileset> (either
directly or via <requires>).

PALETTE:
- Click LMB in the palette to select the active tile.
- Use LMB dragging on the palette to drag it around the window.

MAP:
- Click LMB in the map to set the map to the active tile.
- Click RMB in the map to clear the map cell.
- Use the scroll-wheel to zoom in and out.
- Use LMB dragging to pan around the map. Alternatively use the arrow keys
  to pan around.

Hit "d" to turn some debugging information on (cell location, pixel location,
cell properties).

Hit control-s to save the map and quit.

Hit control-q, or escape, or the window close button to quit without saving.

'''

import pyglet
from pyglet.gl import *
import cocos
from cocos import tiles, actions
from cocos.director import director

class TileEditorLayer(tiles.ScrollableLayer):
    is_event_handler = True

    def __init__(self, manager, level_to_edit, selector, filename):
        super(TileEditorLayer, self).__init__()
        self.manager = manager
        self.level_to_edit = level_to_edit
        self.filename = filename
        self.highlight = None
        self.selector = selector
        self.tileset = selector.tileset
        w, h = director.get_window_size()

    def on_key_press(self, key, modifier):
        if modifier == pyglet.window.key.MOD_ACCEL:
            if key == pyglet.window.key.S:
                self.level_to_edit.save_xml(self.filename)
                director.pop()
            elif key == pyglet.window.key.Q:
                director.pop()
        if key == pyglet.window.key.D:
            m = self.selector.map_layer
            m.set_debug(not m.debug)

    _desired_scale = 1
    def on_mouse_scroll(self, x, y, dx, dy):
        if dy < 0:
            if self._desired_scale < .2: return True
            self._desired_scale -= .1
        elif dy > 0:
            if self._desired_scale > 2: return True
            self._desired_scale += .1
        if dy:
            self.manager.do(actions.ScaleTo(self._desired_scale, .1))
            return True

    def on_text_motion(self, motion):
        fx, fy = self.manager.fx, self.manager.fy
        if motion == pyglet.window.key.MOTION_UP:
            self.manager.set_focus(fx, fy+64/self._desired_scale)
        elif motion == pyglet.window.key.MOTION_DOWN:
            self.manager.set_focus(fx, fy-64/self._desired_scale)
        elif motion == pyglet.window.key.MOTION_LEFT:
            self.manager.set_focus(fx-64/self._desired_scale, fy)
        elif motion == pyglet.window.key.MOTION_RIGHT:
            self.manager.set_focus(fx+64/self._desired_scale, fy)
        else:
            return False
        return True

    _dragging = False
    def on_mouse_press(self, x, y, buttons, modifiers):
        self._drag_start = (x, y)
        self._dragging = False

    def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
        if not buttons & pyglet.window.mouse.LEFT:
            return False
        if not self._dragging:
            _x, _y = self._drag_start
            if abs(x - _x) + abs(y - _y) < 6:
                return False
        self._dragging = True
        self.manager.set_focus(self.manager.fx-dx/self._desired_scale,
            self.manager.fy-dy/self._desired_scale)

    def on_mouse_release(self, x, y, buttons, modifiers):
        if self._dragging:
            self._dragging = False
            return False
        m = self.selector.map_layer

        # get the cell and cell coordinate
        x, y = self.manager.pixel_from_screen(x, y)
        cell = m.get_at_pixel(x, y)
        if not cell:
            # click not in map
            return

        # now add the cell
        if buttons & pyglet.window.mouse.LEFT:
            cell.tile = self.selector.tileset[self.selector.current.tile_id]
            self.selector.map_layer.set_dirty()
        elif buttons & pyglet.window.mouse.RIGHT:
            cell.tile = None
            self.selector.map_layer.set_dirty()
        return True

    def on_mouse_motion(self, x, y, dx, dy):
        m = self.selector.map_layer
        cell = m.get_at_pixel(*self.manager.pixel_from_screen(x, y))
        if not cell:
            self.highlight = None
            return True
        x, y = cell.x, cell.y
        self.highlight = (x, y, x+m.tw, y+m.th)
        return True

    def draw(self):
        if self.highlight is None:
            return
        glPushMatrix()
        self.transform()
        glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glColor4f(1, 1, 0, .3)
        glRectf(*self.highlight)
        glPopAttrib()
        glPopMatrix()

class TileSetLayer(cocos.layer.Layer):
    is_event_handler = True

    TILE_SIZE = 32
    def __init__(self, level_to_edit):
        super(TileSetLayer, self).__init__()
        self.level_to_edit = level_to_edit
        self.map_layer = level_to_edit.find(tiles.MapLayer).next()[1]
        self.tileset = level_to_edit.findall(tiles.TileSet).next()[1]
        self.batch = pyglet.graphics.Batch()

        # labels
        ly = self.TILE_SIZE * 8 + 8
        self.tiles_label = pyglet.text.Label('Tiles', batch=self.batch, y=ly)
        self.active_tab = self.tiles_label
        w = self.tiles_label.content_width + 8
        h = self.tiles_label.content_height
        self.layers_label = pyglet.text.Label('Layers', batch=self.batch, y=ly,
            color=(200, 200, 200, 255))
        self.layers_label.x = w
        h = max(h, self.layers_label.content_height)
        w += self.layers_label.content_width + 8
        self.tilesets_label = pyglet.text.Label('Tilesets', batch=self.batch,
            y=ly, color=(200, 200, 200, 255))
        self.tilesets_label.x = w
        h = max(h, self.tilesets_label.content_height)
        w += self.tilesets_label.content_width

        self._width = (int(w) / self.TILE_SIZE) * self.TILE_SIZE + 8
        if int(w) % self.TILE_SIZE: self._width += self.TILE_SIZE
        self._height = h + 16 + self.TILE_SIZE * 8

        # set up the background
        bg = pyglet.image.SolidColorImagePattern((0, 0, 0, 200))
        bg = pyglet.image.create(self._width, self._height, pattern=bg)

        # set up the tiles
        self.active_batch = self.tiles_batch = pyglet.graphics.Batch()
        self.bg = pyglet.sprite.Sprite(bg, group=pyglet.graphics.OrderedGroup(0),
            batch=self.active_batch)
        self.tile_sprites = []
        x = y = 4
        for n, k in enumerate(self.tileset):
            s = pyglet.sprite.Sprite(self.tileset[k].image, y=y, x=x,
                batch=self.tiles_batch)
            if not n:
                self.current = s
            s.tile_id = k
            self.tile_sprites.append(s)
            s.scale = self.TILE_SIZE / float(s.width)
            if not n % 8:
                y = 4; x += self.TILE_SIZE
            else:
                y += self.TILE_SIZE

        # set up the layers buttons
        self.layers_batch = pyglet.graphics.Batch()
        self.layer_labels = []
        self.layer_visible = []
        y = 4
        for k,v in level_to_edit.find(tiles.MapLayer):
            l = pyglet.text.Label(k, batch=self.layers_batch, y=y,
                    color=(255,255,255,255))
            v.map_layer = l
            if v is self.map_layer:
                l.color = (255, 255, 200, 255)
            y += l.content_height + 2
            self.layer_labels.append(l)

        # set up the tilesets buttons
        self.tilesets_batch = pyglet.graphics.Batch()
        self.layer_labels = []
        y = 4
        for id, ts in self.level_to_edit.findall(tiles.TileSet):
            if id is None: id = '[no id]'
            l = pyglet.text.Label(id, batch=self.tilesets_batch,
                    color=(255,255,255,255), y=y, x=4)
            l._tileset = ts
            y += l.content_height + 2
            self.layer_labels.append(l)

        self.highlight = (4, 4)

    def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
        if not buttons & pyglet.window.mouse.LEFT:
            return False
        if self._drag_start is None:
            return False
        if not self._dragging:
            _x, _y = self._drag_start
            if abs(x - _x) + abs(y - _y) < 6:
                return False
        self._dragging = True
        x, y = self.position
        self.position = (x+dx, y+dy)
        return True

    def on_mouse_release(self, x, y, button, modifiers):
        if self._dragging:
            self._dragging = False
            self._drag_start = None
            return True

        lx, ly = self.position

        if self.active_tab is self.tiles_label:
            for s in self.tile_sprites:
                sx = s.x + lx
                sy = s.y + ly
                if x < sx or x > sx + s.width: continue
                if y < sy or y > sy + s.height: continue
                self.current = s
                self.highlight = (s.x, s.y)
                return True
        #elif self.active_tab is self.layers_label:
            #XXX handle clicks in there...

        _x = self.tiles_label.x+lx
        _y = self.tiles_label.y+ly
        if (x > _x and x < _x + self.tiles_label.content_width and
                y > _y and y < _y + self.tiles_label.content_height):
            self.active_tab.color = (200, 200, 200, 255)
            self.active_tab = self.tiles_label
            self.active_tab.color = (255, 255, 255, 255)
            self.active_batch = self.tiles_batch
            return True

        _x = self.layers_label.x+lx
        _y = self.layers_label.y+ly
        if (x > _x and x < _x + self.layers_label.content_width and
                y > _y and y < _y + self.layers_label.content_height):
            self.active_tab.color = (200, 200, 200, 255)
            self.active_tab = self.layers_label
            self.active_tab.color = (255, 255, 255, 255)
            self.active_batch = self.layers_batch
            return True

        _x = self.tilesets_label.x+lx
        _y = self.tilesets_label.y+ly
        if (x > _x and x < _x + self.tilesets_label.content_width and
                y > _y and y < _y + self.tilesets_label.content_height):
            self.active_tab.color = (200, 200, 200, 255)
            self.active_tab = self.tilesets_label
            self.active_tab.color = (255, 255, 255, 255)
            self.active_batch = self.tilesets_batch
            return True

        sx = self.bg.x + lx
        sy = self.bg.y + ly
        if x < sx or x > sx + self.bg.width: return False
        if y < sy or y > sy + self.bg.height: return False

        #self._dragging = True
        return True

    _dragging = False
    def on_mouse_press(self, x, y, buttons, modifiers):
        lx, ly = self.position
        _x = self.bg.x+lx
        _y = self.bg.y+ly
        if (x > _x and x < _x + self.bg.width and
                y > _y and y < _y + self.bg.height):
            self._drag_start = (x, y)
        else:
            self._drag_start = None
        self._dragging = False

    def draw(self):
        self.transform()
        self.active_batch.draw()
        #self.tilesets_batch.draw()

        if self.active_batch is self.tiles_batch:
            glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT)
            glEnable(GL_BLEND)
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
            glColor4f(1, 1, 1, .3)
            x, y = self.highlight
            glRectf(x, y, x+self.TILE_SIZE, y+self.TILE_SIZE)
            glPopAttrib()

class EditorScene(cocos.scene.Scene):

    def __init__(self, edit_level_xml):
        super(EditorScene, self).__init__()

        self.manager = tiles.ScrollingManager(director.window)
        #if bg_level_xml:
            #level = tiles.load(bg_level_xml)[bg_level_id]
            #self.manager.append(level)
            #level.opacity = 100
            #self.add(level, z=0)

        level_to_edit = tiles.load(edit_level_xml)

        mz = 0
        for id, layer in level_to_edit.find(tiles.MapLayer):
            self.manager.add(layer, z=layer.origin_z)
            mz = max(layer.origin_z, mz)
        self.add(self.manager)

        s = TileSetLayer(level_to_edit)
        self.add(s, z=mz+2)

        e = TileEditorLayer(self.manager, level_to_edit, s, edit_level_xml)
        self.manager.add(e, z=mz+1)

        self.manager.set_focus(0, 0)

    def edit_complete(self, layer):
        pyglet.app.exit()

if __name__ == '__main__':
    import sys

    import pyglet
    import cocos
    from cocos import tiles

    from cocos.director import director

    try:
        edit_level_xml = sys.argv[1]
    except:
        print 'Usage: %s <level.xml>'%sys.argv[0]
        sys.exit(0)

    #director.init(width=700, height=440)
    #director.init(fullscreen=True)
    director.init(width=1024, height=768)
    director.show_FPS = True

    pyglet.gl.glClearColor(1, 1, 1, 1)

    director.run(EditorScene(edit_level_xml))

<commit_msg>fix for multiple accels<commit_after>'''Cocos tilemap editor!

Usage: editor.py <level.xml>

The level must contain at least one <rectmap> and one <tileset> (either
directly or via <requires>).

PALETTE:
- Click LMB in the palette to select the active tile.
- Use LMB dragging on the palette to drag it around the window.

MAP:
- Click LMB in the map to set the map to the active tile.
- Click RMB in the map to clear the map cell.
- Use the scroll-wheel to zoom in and out.
- Use LMB dragging to pan around the map. Alternatively use the arrow keys
  to pan around.

Hit "d" to turn some debugging information on (cell location, pixel location,
cell properties).

Hit control-s to save the map and quit.

Hit control-q, or escape, or the window close button to quit without saving.

'''

import pyglet
from pyglet.gl import *
import cocos
from cocos import tiles, actions
from cocos.director import director

class TileEditorLayer(tiles.ScrollableLayer):
    is_event_handler = True

    def __init__(self, manager, level_to_edit, selector, filename):
        super(TileEditorLayer, self).__init__()
        self.manager = manager
        self.level_to_edit = level_to_edit
        self.filename = filename
        self.highlight = None
        self.selector = selector
        self.tileset = selector.tileset
        w, h = director.get_window_size()

    def on_key_press(self, key, modifier):
        if modifier & pyglet.window.key.MOD_ACCEL:
            if key == pyglet.window.key.S:
                self.level_to_edit.save_xml(self.filename)
                director.pop()
            elif key == pyglet.window.key.Q:
                director.pop()
        if key == pyglet.window.key.D:
            m = self.selector.map_layer
            m.set_debug(not m.debug)

    _desired_scale = 1
    def on_mouse_scroll(self, x, y, dx, dy):
        if dy < 0:
            if self._desired_scale < .2: return True
            self._desired_scale -= .1
        elif dy > 0:
            if self._desired_scale > 2: return True
            self._desired_scale += .1
        if dy:
            self.manager.do(actions.ScaleTo(self._desired_scale, .1))
            return True

    def on_text_motion(self, motion):
        fx, fy = self.manager.fx, self.manager.fy
        if motion == pyglet.window.key.MOTION_UP:
            self.manager.set_focus(fx, fy+64/self._desired_scale)
        elif motion == pyglet.window.key.MOTION_DOWN:
            self.manager.set_focus(fx, fy-64/self._desired_scale)
        elif motion == pyglet.window.key.MOTION_LEFT:
            self.manager.set_focus(fx-64/self._desired_scale, fy)
        elif motion == pyglet.window.key.MOTION_RIGHT:
            self.manager.set_focus(fx+64/self._desired_scale, fy)
        else:
            return False
        return True

    _dragging = False
    def on_mouse_press(self, x, y, buttons, modifiers):
        self._drag_start = (x, y)
        self._dragging = False

    def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
        if not buttons & pyglet.window.mouse.LEFT:
            return False
        if not self._dragging:
            _x, _y = self._drag_start
            if abs(x - _x) + abs(y - _y) < 6:
                return False
        self._dragging = True
        self.manager.set_focus(self.manager.fx-dx/self._desired_scale,
            self.manager.fy-dy/self._desired_scale)

    def on_mouse_release(self, x, y, buttons, modifiers):
        if self._dragging:
            self._dragging = False
            return False
        m = self.selector.map_layer

        # get the cell and cell coordinate
        x, y = self.manager.pixel_from_screen(x, y)
        cell = m.get_at_pixel(x, y)
        if not cell:
            # click not in map
            return

        # now add the cell
        if buttons & pyglet.window.mouse.LEFT:
            cell.tile = self.selector.tileset[self.selector.current.tile_id]
            self.selector.map_layer.set_dirty()
        elif buttons & pyglet.window.mouse.RIGHT:
            cell.tile = None
            self.selector.map_layer.set_dirty()
        return True

    def on_mouse_motion(self, x, y, dx, dy):
        m = self.selector.map_layer
        cell = m.get_at_pixel(*self.manager.pixel_from_screen(x, y))
        if not cell:
            self.highlight = None
            return True
        x, y = cell.x, cell.y
        self.highlight = (x, y, x+m.tw, y+m.th)
        return True

    def draw(self):
        if self.highlight is None:
            return
        glPushMatrix()
        self.transform()
        glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glColor4f(1, 1, 0, .3)
        glRectf(*self.highlight)
        glPopAttrib()
        glPopMatrix()

class TileSetLayer(cocos.layer.Layer):
    is_event_handler = True

    TILE_SIZE = 32
    def __init__(self, level_to_edit):
        super(TileSetLayer, self).__init__()
        self.level_to_edit = level_to_edit
        self.map_layer = level_to_edit.find(tiles.MapLayer).next()[1]
        self.tileset = level_to_edit.findall(tiles.TileSet).next()[1]
        self.batch = pyglet.graphics.Batch()

        # labels
        ly = self.TILE_SIZE * 8 + 8
        self.tiles_label = pyglet.text.Label('Tiles', batch=self.batch, y=ly)
        self.active_tab = self.tiles_label
        w = self.tiles_label.content_width + 8
        h = self.tiles_label.content_height
        self.layers_label = pyglet.text.Label('Layers', batch=self.batch, y=ly,
            color=(200, 200, 200, 255))
        self.layers_label.x = w
        h = max(h, self.layers_label.content_height)
        w += self.layers_label.content_width + 8
        self.tilesets_label = pyglet.text.Label('Tilesets', batch=self.batch,
            y=ly, color=(200, 200, 200, 255))
        self.tilesets_label.x = w
        h = max(h, self.tilesets_label.content_height)
        w += self.tilesets_label.content_width

        self._width = (int(w) / self.TILE_SIZE) * self.TILE_SIZE + 8
        if int(w) % self.TILE_SIZE: self._width += self.TILE_SIZE
        self._height = h + 16 + self.TILE_SIZE * 8

        # set up the background
        bg = pyglet.image.SolidColorImagePattern((0, 0, 0, 200))
        bg = pyglet.image.create(self._width, self._height, pattern=bg)

        # set up the tiles
        self.active_batch = self.tiles_batch = pyglet.graphics.Batch()
        self.bg = pyglet.sprite.Sprite(bg, group=pyglet.graphics.OrderedGroup(0),
            batch=self.active_batch)
        self.tile_sprites = []
        x = y = 4
        for n, k in enumerate(self.tileset):
            s = pyglet.sprite.Sprite(self.tileset[k].image, y=y, x=x,
                batch=self.tiles_batch)
            if not n:
                self.current = s
            s.tile_id = k
            self.tile_sprites.append(s)
            s.scale = self.TILE_SIZE / float(s.width)
            if not n % 8:
                y = 4; x += self.TILE_SIZE
            else:
                y += self.TILE_SIZE

        # set up the layers buttons
        self.layers_batch = pyglet.graphics.Batch()
        self.layer_labels = []
        self.layer_visible = []
        y = 4
        for k,v in level_to_edit.find(tiles.MapLayer):
            l = pyglet.text.Label(k, batch=self.layers_batch, y=y,
                    color=(255,255,255,255))
            v.map_layer = l
            if v is self.map_layer:
                l.color = (255, 255, 200, 255)
            y += l.content_height + 2
            self.layer_labels.append(l)

        # set up the tilesets buttons
        self.tilesets_batch = pyglet.graphics.Batch()
        self.layer_labels = []
        y = 4
        for id, ts in self.level_to_edit.findall(tiles.TileSet):
            if id is None: id = '[no id]'
            l = pyglet.text.Label(id, batch=self.tilesets_batch,
                    color=(255,255,255,255), y=y, x=4)
            l._tileset = ts
            y += l.content_height + 2
            self.layer_labels.append(l)

        self.highlight = (4, 4)

    def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
        if not buttons & pyglet.window.mouse.LEFT:
            return False
        if self._drag_start is None:
            return False
        if not self._dragging:
            _x, _y = self._drag_start
            if abs(x - _x) + abs(y - _y) < 6:
                return False
        self._dragging = True
        x, y = self.position
        self.position = (x+dx, y+dy)
        return True

    def on_mouse_release(self, x, y, button, modifiers):
        if self._dragging:
            self._dragging = False
            self._drag_start = None
            return True

        lx, ly = self.position

        if self.active_tab is self.tiles_label:
            for s in self.tile_sprites:
                sx = s.x + lx
                sy = s.y + ly
                if x < sx or x > sx + s.width: continue
                if y < sy or y > sy + s.height: continue
                self.current = s
                self.highlight = (s.x, s.y)
                return True
        #elif self.active_tab is self.layers_label:
            #XXX handle clicks in there...

        _x = self.tiles_label.x+lx
        _y = self.tiles_label.y+ly
        if (x > _x and x < _x + self.tiles_label.content_width and
                y > _y and y < _y + self.tiles_label.content_height):
            self.active_tab.color = (200, 200, 200, 255)
            self.active_tab = self.tiles_label
            self.active_tab.color = (255, 255, 255, 255)
            self.active_batch = self.tiles_batch
            return True

        _x = self.layers_label.x+lx
        _y = self.layers_label.y+ly
        if (x > _x and x < _x + self.layers_label.content_width and
                y > _y and y < _y + self.layers_label.content_height):
            self.active_tab.color = (200, 200, 200, 255)
            self.active_tab = self.layers_label
            self.active_tab.color = (255, 255, 255, 255)
            self.active_batch = self.layers_batch
            return True

        _x = self.tilesets_label.x+lx
        _y = self.tilesets_label.y+ly
        if (x > _x and x < _x + self.tilesets_label.content_width and
                y > _y and y < _y + self.tilesets_label.content_height):
            self.active_tab.color = (200, 200, 200, 255)
            self.active_tab = self.tilesets_label
            self.active_tab.color = (255, 255, 255, 255)
            self.active_batch = self.tilesets_batch
            return True

        sx = self.bg.x + lx
        sy = self.bg.y + ly
        if x < sx or x > sx + self.bg.width: return False
        if y < sy or y > sy + self.bg.height: return False

        #self._dragging = True
        return True

    _dragging = False
    def on_mouse_press(self, x, y, buttons, modifiers):
        lx, ly = self.position
        _x = self.bg.x+lx
        _y = self.bg.y+ly
        if (x > _x and x < _x + self.bg.width and
                y > _y and y < _y + self.bg.height):
            self._drag_start = (x, y)
        else:
            self._drag_start = None
        self._dragging = False

    def draw(self):
        self.transform()
        self.active_batch.draw()
        #self.tilesets_batch.draw()

        if self.active_batch is self.tiles_batch:
            glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT)
            glEnable(GL_BLEND)
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
            glColor4f(1, 1, 1, .3)
            x, y = self.highlight
            glRectf(x, y, x+self.TILE_SIZE, y+self.TILE_SIZE)
            glPopAttrib()

class EditorScene(cocos.scene.Scene):

    def __init__(self, edit_level_xml):
        super(EditorScene, self).__init__()

        self.manager = tiles.ScrollingManager(director.window)
        #if bg_level_xml:
            #level = tiles.load(bg_level_xml)[bg_level_id]
            #self.manager.append(level)
            #level.opacity = 100
            #self.add(level, z=0)

        level_to_edit = tiles.load(edit_level_xml)

        mz = 0
        for id, layer in level_to_edit.find(tiles.MapLayer):
            self.manager.add(layer, z=layer.origin_z)
            mz = max(layer.origin_z, mz)
        self.add(self.manager)

        s = TileSetLayer(level_to_edit)
        self.add(s, z=mz+2)

        e = TileEditorLayer(self.manager, level_to_edit, s, edit_level_xml)
        self.manager.add(e, z=mz+1)

        self.manager.set_focus(0, 0)

    def edit_complete(self, layer):
        pyglet.app.exit()

if __name__ == '__main__':
    import sys

    import pyglet
    import cocos
    from cocos import tiles

    from cocos.director import director

    try:
        edit_level_xml = sys.argv[1]
    except:
        print 'Usage: %s <level.xml>'%sys.argv[0]
        sys.exit(0)

    #director.init(width=700, height=440)
    #director.init(fullscreen=True)
    director.init(width=1024, height=768)
    director.show_FPS = True

    pyglet.gl.glClearColor(1, 1, 1, 1)

    director.run(EditorScene(edit_level_xml))

<|endoftext|>


<commit_before>import smtplib
import json
import datetime
import os
from email.mime.text import MIMEText

def send_email(regression, jobs, message, addition=None, deletion=None, admin=False, results=False):
    server = smtplib.SMTP('smtp.gmail.com:587')
    server.starttls()
    server.login("setamozilla","seta_mozilla")

    message = "We analyzed %s regressions and found %s jobs to disable - " % (regression, jobs) + message
    if addition and deletion:
        message += "\nThe jobs added to the current day compared to previous day are: ", addition
        message += "\nThe jobs deleted from the current day compared to previous day are: ", deletion

    msg = MIMEText(message)
    msg['Subject'] = "SETA Results - Date %s" % datetime.datetime.now().strftime("%Y-%m-%d")
    msg['From'] = "setamozilla@gmail.com"

    json_data = open(os.path.join(os.path.abspath(os.path.realpath(os.path.dirname(__file__))), "seta.cfg"), "r").read()
    data = json.loads(json_data)
    if admin:
        server.sendmail(msg['From'], data['admins'], msg.as_string())
    if results:
        server.sendmail(msg['From'], data['results'], msg.as_string())
<commit_msg>sync to master<commit_after>import smtplib
import json
import datetime
import os
from email.mime.text import MIMEText

def send_email(regression, jobs, message, addition=None, deletion=None, admin=False, results=False):
    server = smtplib.SMTP('smtp.gmail.com:587')
    server.starttls()
    server.login("setamozilla","seta_mozilla")

    message = "We analyzed %s regressions and found %s jobs to disable - " % (regression, jobs) + message
    if addition and deletion:
        message += "\nThe jobs added to the current day compared to previous day are:\n\n %s" % addition
        message += "\n\nThe jobs deleted from the current day compared to previous day are:\n\n %s" % deletion

    msg = MIMEText(message)
    msg['Subject'] = "SETA Results - Date %s" % datetime.datetime.now().strftime("%Y-%m-%d")
    msg['From'] = "setamozilla@gmail.com"

    json_data = open(os.path.join(os.path.abspath(os.path.realpath(os.path.dirname(__file__))), "seta.cfg"), "r").read()
    data = json.loads(json_data)
    if admin:
        server.sendmail(msg['From'], data['admins'], msg.as_string())
    if results:
        server.sendmail(msg['From'], data['results'], msg.as_string())
<|endoftext|>


<commit_before>#!/usr/bin/env python
#
# Original espota.py by Ivan Grokhotkov:
# https://gist.github.com/igrr/d35ab8446922179dc58c
#
# Modified since 2015-09-18 from Pascal Gollor (https://github.com/pgollor)
# Modified since 2015-11-09 from Hristo Gochkov (https://github.com/me-no-dev)
# Modified since 2016-01-03 from Matthew O'Gorman (https://githumb.com/mogorman)
#
# This script will push an OTA update to the ESP
# use it like: python espota.py -i <ESP_IP_address> -I <Host_IP_address> -p <ESP_port> -P <Host_port> [-a password] -f <sketch.bin>
# Or to upload SPIFFS image:
# python espota.py -i <ESP_IP_address> -I <Host_IP_address> -p <ESP_port> -P <HOST_port> [-a password] -s -f <spiffs.bin>
#
# Changes
# 2015-09-18:
# - Add option parser.
# - Add logging.
# - Send command to controller to differ between flashing and transmitting SPIFFS image.
#
# Changes
# 2015-11-09:
# - Added digest authentication
# - Enhanced error tracking and reporting
#
# Changes
# 2016-01-03:
# - Added more options to parser.
#

from __future__ import print_function
import socket
import sys
import os
import optparse
import logging
import hashlib
import random

# Commands
FLASH = 0
SPIFFS = 100
AUTH = 200
PROGRESS = False
# update_progress() : Displays or updates a console progress bar
## Accepts a float between 0 and 1. Any int will be converted to a float.
## A value under 0 represents a 'halt'.
## A value at 1 or bigger represents 100%
def update_progress(progress):
  if (PROGRESS):
    barLength = 60 # Modify this to change the length of the progress bar
    status = ""
    if isinstance(progress, int):
      progress = float(progress)
    if not isinstance(progress, float):
      progress = 0
      status = "error: progress var must be float\r\n"
    if progress < 0:
      progress = 0
      status = "Halt...\r\n"
    if progress >= 1:
      progress = 1
      status = "Done...\r\n"
    block = int(round(barLength*progress))
    text = "\rUploading: [{0}] {1}% {2}".format( "="*block + " "*(barLength-block), int(progress*100), status)
    sys.stderr.write(text)
    sys.stderr.flush()
  else:
    sys.stderr.write('.')
    sys.stderr.flush()

def serve(remoteAddr, localAddr, remotePort, localPort, password, filename, command = FLASH):
  # Create a TCP/IP socket
  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  server_address = (localAddr, localPort)
  logging.info('Starting on %s:%s', str(server_address[0]), str(server_address[1]))
  try:
    sock.bind(server_address)
    sock.listen(1)
  except:
    logging.error("Listen Failed")
    return 1

  content_size = os.path.getsize(filename)
  f = open(filename,'rb')
  file_md5 = hashlib.md5(f.read()).hexdigest()
  f.close()
  logging.info('Upload size: %d', content_size)
  message = '%d %d %d %s\n' % (command, localPort, content_size, file_md5)

  # Wait for a connection
  logging.info('Sending invitation to: %s', remoteAddr)
  sock2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  remote_address = (remoteAddr, int(remotePort))
  sent = sock2.sendto(message.encode(), remote_address)
  sock2.settimeout(10)
  try:
    data = sock2.recv(128).decode()
  except:
    logging.error('No Answer')
    sock2.close()
    return 1
  if (data != "OK"):
    if(data.startswith('AUTH')):
      nonce = data.split()[1]
      cnonce_text = '%s%u%s%s' % (filename, content_size, file_md5, remoteAddr)
      cnonce = hashlib.md5(cnonce_text.encode()).hexdigest()
      passmd5 = hashlib.md5(password.encode()).hexdigest()
      result_text = '%s:%s:%s' % (passmd5 ,nonce, cnonce)
      result = hashlib.md5(result_text.encode()).hexdigest()
      sys.stderr.write('Authenticating...')
      sys.stderr.flush()
      message = '%d %s %s\n' % (AUTH, cnonce, result)
      sock2.sendto(message.encode(), remote_address)
      sock2.settimeout(10)
      try:
        data = sock2.recv(32).decode()
      except:
        sys.stderr.write('FAIL\n')
        logging.error('No Answer to our Authentication')
        sock2.close()
        return 1
      if (data != "OK"):
        sys.stderr.write('FAIL\n')
        logging.error('%s', data)
        sock2.close()
        sys.exit(1);
        return 1
      sys.stderr.write('OK\n')
    else:
      logging.error('Bad Answer: %s', data)
      sock2.close()
      return 1
  sock2.close()

  logging.info('Waiting for device...')
  try:
    sock.settimeout(10)
    connection, client_address = sock.accept()
    sock.settimeout(None)
    connection.settimeout(None)
  except:
    logging.error('No response from device')
    sock.close()
    return 1

  received_ok = False

  try:
    f = open(filename, "rb")
    if (PROGRESS):
      update_progress(0)
    else:
      sys.stderr.write('Uploading')
      sys.stderr.flush()
    offset = 0
    while True:
      chunk = f.read(1460)
      if not chunk: break
      offset += len(chunk)
      update_progress(offset/float(content_size))
      connection.settimeout(10)
      try:
        connection.sendall(chunk)
        if connection.recv(32).decode().find('O') >= 0:
          # connection will receive only digits or 'OK'
          received_ok = True;
      except:
        sys.stderr.write('\n')
        logging.error('Error Uploading')
        connection.close()
        f.close()
        sock.close()
        return 1

    sys.stderr.write('\n')
    logging.info('Waiting for result...')
    # libraries/ArduinoOTA/ArduinoOTA.cpp L311 L320
    # only sends digits or 'OK'. We must not not close
    # the connection before receiving the 'O' of 'OK'
    try:
      connection.settimeout(60)
      while not received_ok:
        if connection.recv(32).decode().find('O') >= 0:
          # connection will receive only digits or 'OK'
          received_ok = True;
      logging.info('Result: OK')
      connection.close()
      f.close()
      sock.close()
      if (data != "OK"):
        sys.stderr.write('\n')
        logging.error('%s', data)
        return 1;
      return 0
    except:
      logging.error('No Result!')
      connection.close()
      f.close()
      sock.close()
      return 1

  finally:
    connection.close()
    f.close()

  sock.close()
  return 1
# end serve

def parser(unparsed_args):
  parser = optparse.OptionParser(
    usage = "%prog [options]",
    description = "Transmit image over the air to the esp8266 module with OTA support."
  )

  # destination ip and port
  group = optparse.OptionGroup(parser, "Destination")
  group.add_option("-i", "--ip",
    dest = "esp_ip",
    action = "store",
    help = "ESP8266 IP Address.",
    default = False
  )
  group.add_option("-I", "--host_ip",
    dest = "host_ip",
    action = "store",
    help = "Host IP Address.",
    default = "0.0.0.0"
  )
  group.add_option("-p", "--port",
    dest = "esp_port",
    type = "int",
    help = "ESP8266 ota Port. Default 8266",
    default = 8266
  )
  group.add_option("-P", "--host_port",
    dest = "host_port",
    type = "int",
    help = "Host server ota Port. Default random 10000-60000",
    default = random.randint(10000,60000)
  )
  parser.add_option_group(group)

  # auth
  group = optparse.OptionGroup(parser, "Authentication")
  group.add_option("-a", "--auth",
    dest = "auth",
    help = "Set authentication password.",
    action = "store",
    default = ""
  )
  parser.add_option_group(group)

  # image
  group = optparse.OptionGroup(parser, "Image")
  group.add_option("-f", "--file",
    dest = "image",
    help = "Image file.",
    metavar="FILE",
    default = None
  )
  group.add_option("-s", "--spiffs",
    dest = "spiffs",
    action = "store_true",
    help = "Use this option to transmit a SPIFFS image and do not flash the module.",
    default = False
  )
  parser.add_option_group(group)

  # output group
  group = optparse.OptionGroup(parser, "Output")
  group.add_option("-d", "--debug",
    dest = "debug",
    help = "Show debug output. And override loglevel with debug.",
    action = "store_true",
    default = False
  )
  group.add_option("-r", "--progress",
    dest = "progress",
    help = "Show progress output. Does not work for ArduinoIDE",
    action = "store_true",
    default = False
  )
  parser.add_option_group(group)

  (options, args) = parser.parse_args(unparsed_args)

  return options
# end parser

def main(args):
  # get options
  options = parser(args)

  # adapt log level
  loglevel = logging.WARNING
  if (options.debug):
    loglevel = logging.DEBUG
  # end if

  # logging
  logging.basicConfig(level = loglevel, format = '%(asctime)-8s [%(levelname)s]: %(message)s', datefmt = '%H:%M:%S')

  logging.debug("Options: %s", str(options))

  # check options
  global PROGRESS
  PROGRESS = options.progress
  if (not options.esp_ip or not options.image):
    logging.critical("Not enough arguments.")

    return 1
  # end if

  command = FLASH
  if (options.spiffs):
    command = SPIFFS
  # end if

  return serve(options.esp_ip, options.host_ip, options.esp_port, options.host_port, options.auth, options.image, command)
# end main

if __name__ == '__main__':
  sys.exit(main(sys.argv))
# end if
<commit_msg>tools: fixed bug to select signed bin (#6334)<commit_after>#!/usr/bin/env python
#
# Original espota.py by Ivan Grokhotkov:
# https://gist.github.com/igrr/d35ab8446922179dc58c
#
# Modified since 2015-09-18 from Pascal Gollor (https://github.com/pgollor)
# Modified since 2015-11-09 from Hristo Gochkov (https://github.com/me-no-dev)
# Modified since 2016-01-03 from Matthew O'Gorman (https://githumb.com/mogorman)
#
# This script will push an OTA update to the ESP
# use it like: python espota.py -i <ESP_IP_address> -I <Host_IP_address> -p <ESP_port> -P <Host_port> [-a password] -f <sketch.bin>
# Or to upload SPIFFS image:
# python espota.py -i <ESP_IP_address> -I <Host_IP_address> -p <ESP_port> -P <HOST_port> [-a password] -s -f <spiffs.bin>
#
# Changes
# 2015-09-18:
# - Add option parser.
# - Add logging.
# - Send command to controller to differ between flashing and transmitting SPIFFS image.
#
# Changes
# 2015-11-09:
# - Added digest authentication
# - Enhanced error tracking and reporting
#
# Changes
# 2016-01-03:
# - Added more options to parser.
#

from __future__ import print_function
import socket
import sys
import os
import optparse
import logging
import hashlib
import random

# Commands
FLASH = 0
SPIFFS = 100
AUTH = 200
PROGRESS = False
# update_progress() : Displays or updates a console progress bar
## Accepts a float between 0 and 1. Any int will be converted to a float.
## A value under 0 represents a 'halt'.
## A value at 1 or bigger represents 100%
def update_progress(progress):
  if (PROGRESS):
    barLength = 60 # Modify this to change the length of the progress bar
    status = ""
    if isinstance(progress, int):
      progress = float(progress)
    if not isinstance(progress, float):
      progress = 0
      status = "error: progress var must be float\r\n"
    if progress < 0:
      progress = 0
      status = "Halt...\r\n"
    if progress >= 1:
      progress = 1
      status = "Done...\r\n"
    block = int(round(barLength*progress))
    text = "\rUploading: [{0}] {1}% {2}".format( "="*block + " "*(barLength-block), int(progress*100), status)
    sys.stderr.write(text)
    sys.stderr.flush()
  else:
    sys.stderr.write('.')
    sys.stderr.flush()

def serve(remoteAddr, localAddr, remotePort, localPort, password, filename, command = FLASH):
  # Create a TCP/IP socket
  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  server_address = (localAddr, localPort)
  logging.info('Starting on %s:%s', str(server_address[0]), str(server_address[1]))
  try:
    sock.bind(server_address)
    sock.listen(1)
  except:
    logging.error("Listen Failed")
    return 1

  # Check whether Signed Update is used.
  if ( os.path.isfile(filename + '.signed') ):
    filename = filename + '.signed'
    file_check_msg = 'Detected Signed Update. %s will be uploaded instead.' % (filename)
    sys.stderr.write(file_check_msg + '\n')
    sys.stderr.flush()
    logging.info(file_check_msg)

  content_size = os.path.getsize(filename)
  f = open(filename,'rb')
  file_md5 = hashlib.md5(f.read()).hexdigest()
  f.close()
  logging.info('Upload size: %d', content_size)
  message = '%d %d %d %s\n' % (command, localPort, content_size, file_md5)

  # Wait for a connection
  logging.info('Sending invitation to: %s', remoteAddr)
  sock2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  remote_address = (remoteAddr, int(remotePort))
  sent = sock2.sendto(message.encode(), remote_address)
  sock2.settimeout(10)
  try:
    data = sock2.recv(128).decode()
  except:
    logging.error('No Answer')
    sock2.close()
    return 1
  if (data != "OK"):
    if(data.startswith('AUTH')):
      nonce = data.split()[1]
      cnonce_text = '%s%u%s%s' % (filename, content_size, file_md5, remoteAddr)
      cnonce = hashlib.md5(cnonce_text.encode()).hexdigest()
      passmd5 = hashlib.md5(password.encode()).hexdigest()
      result_text = '%s:%s:%s' % (passmd5 ,nonce, cnonce)
      result = hashlib.md5(result_text.encode()).hexdigest()
      sys.stderr.write('Authenticating...')
      sys.stderr.flush()
      message = '%d %s %s\n' % (AUTH, cnonce, result)
      sock2.sendto(message.encode(), remote_address)
      sock2.settimeout(10)
      try:
        data = sock2.recv(32).decode()
      except:
        sys.stderr.write('FAIL\n')
        logging.error('No Answer to our Authentication')
        sock2.close()
        return 1
      if (data != "OK"):
        sys.stderr.write('FAIL\n')
        logging.error('%s', data)
        sock2.close()
        sys.exit(1);
        return 1
      sys.stderr.write('OK\n')
    else:
      logging.error('Bad Answer: %s', data)
      sock2.close()
      return 1
  sock2.close()

  logging.info('Waiting for device...')
  try:
    sock.settimeout(10)
    connection, client_address = sock.accept()
    sock.settimeout(None)
    connection.settimeout(None)
  except:
    logging.error('No response from device')
    sock.close()
    return 1

  received_ok = False

  try:
    f = open(filename, "rb")
    if (PROGRESS):
      update_progress(0)
    else:
      sys.stderr.write('Uploading')
      sys.stderr.flush()
    offset = 0
    while True:
      chunk = f.read(1460)
      if not chunk: break
      offset += len(chunk)
      update_progress(offset/float(content_size))
      connection.settimeout(10)
      try:
        connection.sendall(chunk)
        if connection.recv(32).decode().find('O') >= 0:
          # connection will receive only digits or 'OK'
          received_ok = True;
      except:
        sys.stderr.write('\n')
        logging.error('Error Uploading')
        connection.close()
        f.close()
        sock.close()
        return 1

    sys.stderr.write('\n')
    logging.info('Waiting for result...')
    # libraries/ArduinoOTA/ArduinoOTA.cpp L311 L320
    # only sends digits or 'OK'. We must not not close
    # the connection before receiving the 'O' of 'OK'
    try:
      connection.settimeout(60)
      while not received_ok:
        if connection.recv(32).decode().find('O') >= 0:
          # connection will receive only digits or 'OK'
          received_ok = True;
      logging.info('Result: OK')
      connection.close()
      f.close()
      sock.close()
      if (data != "OK"):
        sys.stderr.write('\n')
        logging.error('%s', data)
        return 1;
      return 0
    except:
      logging.error('No Result!')
      connection.close()
      f.close()
      sock.close()
      return 1

  finally:
    connection.close()
    f.close()

  sock.close()
  return 1
# end serve

def parser(unparsed_args):
  parser = optparse.OptionParser(
    usage = "%prog [options]",
    description = "Transmit image over the air to the esp8266 module with OTA support."
  )

  # destination ip and port
  group = optparse.OptionGroup(parser, "Destination")
  group.add_option("-i", "--ip",
    dest = "esp_ip",
    action = "store",
    help = "ESP8266 IP Address.",
    default = False
  )
  group.add_option("-I", "--host_ip",
    dest = "host_ip",
    action = "store",
    help = "Host IP Address.",
    default = "0.0.0.0"
  )
  group.add_option("-p", "--port",
    dest = "esp_port",
    type = "int",
    help = "ESP8266 ota Port. Default 8266",
    default = 8266
  )
  group.add_option("-P", "--host_port",
    dest = "host_port",
    type = "int",
    help = "Host server ota Port. Default random 10000-60000",
    default = random.randint(10000,60000)
  )
  parser.add_option_group(group)

  # auth
  group = optparse.OptionGroup(parser, "Authentication")
  group.add_option("-a", "--auth",
    dest = "auth",
    help = "Set authentication password.",
    action = "store",
    default = ""
  )
  parser.add_option_group(group)

  # image
  group = optparse.OptionGroup(parser, "Image")
  group.add_option("-f", "--file",
    dest = "image",
    help = "Image file.",
    metavar="FILE",
    default = None
  )
  group.add_option("-s", "--spiffs",
    dest = "spiffs",
    action = "store_true",
    help = "Use this option to transmit a SPIFFS image and do not flash the module.",
    default = False
  )
  parser.add_option_group(group)

  # output group
  group = optparse.OptionGroup(parser, "Output")
  group.add_option("-d", "--debug",
    dest = "debug",
    help = "Show debug output. And override loglevel with debug.",
    action = "store_true",
    default = False
  )
  group.add_option("-r", "--progress",
    dest = "progress",
    help = "Show progress output. Does not work for ArduinoIDE",
    action = "store_true",
    default = False
  )
  parser.add_option_group(group)

  (options, args) = parser.parse_args(unparsed_args)

  return options
# end parser

def main(args):
  # get options
  options = parser(args)

  # adapt log level
  loglevel = logging.WARNING
  if (options.debug):
    loglevel = logging.DEBUG
  # end if

  # logging
  logging.basicConfig(level = loglevel, format = '%(asctime)-8s [%(levelname)s]: %(message)s', datefmt = '%H:%M:%S')

  logging.debug("Options: %s", str(options))

  # check options
  global PROGRESS
  PROGRESS = options.progress
  if (not options.esp_ip or not options.image):
    logging.critical("Not enough arguments.")

    return 1
  # end if

  command = FLASH
  if (options.spiffs):
    command = SPIFFS
  # end if

  return serve(options.esp_ip, options.host_ip, options.esp_port, options.host_port, options.auth, options.image, command)
# end main

if __name__ == '__main__':
  sys.exit(main(sys.argv))
# end if
<|endoftext|>


<commit_before>#!/usr/bin/env python
#
# Original espota.py by Ivan Grokhotkov:
# https://gist.github.com/igrr/d35ab8446922179dc58c
#
# Modified since 2015-09-18 from Pascal Gollor (https://github.com/pgollor)
# Modified since 2015-11-09 from Hristo Gochkov (https://github.com/me-no-dev)
# Modified since 2016-01-03 from Matthew O'Gorman (https://githumb.com/mogorman)
#
# This script will push an OTA update to the ESP
# use it like: python espota.py -i <ESP_IP_address> -I <Host_IP_address> -p <ESP_port> -P <Host_port> [-a password] -f <sketch.bin>
# Or to upload SPIFFS image:
# python espota.py -i <ESP_IP_address> -I <Host_IP_address> -p <ESP_port> -P <HOST_port> [-a password] -s -f <spiffs.bin>
#
# Changes
# 2015-09-18:
# - Add option parser.
# - Add logging.
# - Send command to controller to differ between flashing and transmitting SPIFFS image.
#
# Changes
# 2015-11-09:
# - Added digest authentication
# - Enchanced error tracking and reporting
#
# Changes
# 2016-01-03:
# - Added more options to parser.
#

from __future__ import print_function
import socket
import sys
import os
import optparse
import logging
import hashlib
import random

# Commands
FLASH = 0
SPIFFS = 100
AUTH = 200
PROGRESS = False
# update_progress() : Displays or updates a console progress bar
## Accepts a float between 0 and 1. Any int will be converted to a float.
## A value under 0 represents a 'halt'.
## A value at 1 or bigger represents 100%
def update_progress(progress):
  if (PROGRESS):
    barLength = 60 # Modify this to change the length of the progress bar
    status = ""
    if isinstance(progress, int):
      progress = float(progress)
    if not isinstance(progress, float):
      progress = 0
      status = "error: progress var must be float\r\n"
    if progress < 0:
      progress = 0
      status = "Halt...\r\n"
    if progress >= 1:
      progress = 1
      status = "Done...\r\n"
    block = int(round(barLength*progress))
    text = "\rUploading: [{0}] {1}% {2}".format( "="*block + " "*(barLength-block), int(progress*100), status)
    sys.stderr.write(text)
    sys.stderr.flush()
  else:
    sys.stderr.write('.')
    sys.stderr.flush()

def serve(remoteAddr, localAddr, remotePort, localPort, password, filename, command = FLASH):
  # Create a TCP/IP socket
  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  server_address = (localAddr, localPort)
  logging.info('Starting on %s:%s', str(server_address[0]), str(server_address[1]))
  try:
    sock.bind(server_address)
    sock.listen(1)
  except:
    logging.error("Listen Failed")
    return 1

  content_size = os.path.getsize(filename)
  f = open(filename,'rb')
  file_md5 = hashlib.md5(f.read()).hexdigest()
  f.close()
  logging.info('Upload size: %d', content_size)
  message = '%d %d %d %s\n' % (command, localPort, content_size, file_md5)

  # Wait for a connection
  logging.info('Sending invitation to: %s', remoteAddr)
  sock2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  remote_address = (remoteAddr, int(remotePort))
  sent = sock2.sendto(message.encode(), remote_address)
  sock2.settimeout(10)
  try:
    data = sock2.recv(37).decode()
  except:
    logging.error('No Answer')
    sock2.close()
    return 1
  if (data != "OK"):
    if(data.startswith('AUTH')):
      nonce = data.split()[1]
      cnonce_text = '%s%u%s%s' % (filename, content_size, file_md5, remoteAddr)
      cnonce = hashlib.md5(cnonce_text.encode()).hexdigest()
      passmd5 = hashlib.md5(password.encode()).hexdigest()
      result_text = '%s:%s:%s' % (passmd5 ,nonce, cnonce)
      result = hashlib.md5(result_text.encode()).hexdigest()
      sys.stderr.write('Authenticating...')
      sys.stderr.flush()
      message = '%d %s %s\n' % (AUTH, cnonce, result)
      sock2.sendto(message.encode(), remote_address)
      sock2.settimeout(10)
      try:
        data = sock2.recv(32).decode()
      except:
        sys.stderr.write('FAIL\n')
        logging.error('No Answer to our Authentication')
        sock2.close()
        return 1
      if (data != "OK"):
        sys.stderr.write('FAIL\n')
        logging.error('%s', data)
        sock2.close()
        sys.exit(1);
        return 1
      sys.stderr.write('OK\n')
    else:
      logging.error('Bad Answer: %s', data)
      sock2.close()
      return 1
  sock2.close()

  logging.info('Waiting for device...')
  try:
    sock.settimeout(10)
    connection, client_address = sock.accept()
    sock.settimeout(None)
    connection.settimeout(None)
  except:
    logging.error('No response from device')
    sock.close()
    return 1

  try:
    f = open(filename, "rb")
    if (PROGRESS):
      update_progress(0)
    else:
      sys.stderr.write('Uploading')
      sys.stderr.flush()
    offset = 0
    while True:
      chunk = f.read(1460)
      if not chunk: break
      offset += len(chunk)
      update_progress(offset/float(content_size))
      connection.settimeout(10)
      try:
        connection.sendall(chunk)
        res = connection.recv(4)
      except:
        sys.stderr.write('\n')
        logging.error('Error Uploading')
        connection.close()
        f.close()
        sock.close()
        return 1

    sys.stderr.write('\n')
    logging.info('Waiting for result...')
    try:
      connection.settimeout(60)
      data = connection.recv(32).decode()
      logging.info('Result: %s' ,data)
      connection.close()
      f.close()
      sock.close()
      if (data != "OK"):
        sys.stderr.write('\n')
        logging.error('%s', data)
        return 1;
      return 0
    except:
      logging.error('No Result!')
      connection.close()
      f.close()
      sock.close()
      return 1

  finally:
    connection.close()
    f.close()

  sock.close()
  return 1
# end serve

def parser():
  parser = optparse.OptionParser(
    usage = "%prog [options]",
    description = "Transmit image over the air to the esp8266 module with OTA support."
  )

  # destination ip and port
  group = optparse.OptionGroup(parser, "Destination")
  group.add_option("-i", "--ip",
    dest = "esp_ip",
    action = "store",
    help = "ESP8266 IP Address.",
    default = False
  )
  group.add_option("-I", "--host_ip",
    dest = "host_ip",
    action = "store",
    help = "Host IP Address.",
    default = "0.0.0.0"
  )
  group.add_option("-p", "--port",
    dest = "esp_port",
    type = "int",
    help = "ESP8266 ota Port. Default 8266",
    default = 8266
  )
  group.add_option("-P", "--host_port",
    dest = "host_port",
    type = "int",
    help = "Host server ota Port. Default random 10000-60000",
    default = random.randint(10000,60000)
  )
  parser.add_option_group(group)

  # auth
  group = optparse.OptionGroup(parser, "Authentication")
  group.add_option("-a", "--auth",
    dest = "auth",
    help = "Set authentication password.",
    action = "store",
    default = ""
  )
  parser.add_option_group(group)

  # image
  group = optparse.OptionGroup(parser, "Image")
  group.add_option("-f", "--file",
    dest = "image",
    help = "Image file.",
    metavar="FILE",
    default = None
  )
  group.add_option("-s", "--spiffs",
    dest = "spiffs",
    action = "store_true",
    help = "Use this option to transmit a SPIFFS image and do not flash the module.",
    default = False
  )
  parser.add_option_group(group)

  # output group
  group = optparse.OptionGroup(parser, "Output")
  group.add_option("-d", "--debug",
    dest = "debug",
    help = "Show debug output. And override loglevel with debug.",
    action = "store_true",
    default = False
  )
  group.add_option("-r", "--progress",
    dest = "progress",
    help = "Show progress output. Does not work for ArduinoIDE",
    action = "store_true",
    default = False
  )
  parser.add_option_group(group)

  (options, args) = parser.parse_args()

  return options
# end parser

def main(args):
  # get options
  options = parser()

  # adapt log level
  loglevel = logging.WARNING
  if (options.debug):
    loglevel = logging.DEBUG
  # end if

  # logging
  logging.basicConfig(level = loglevel, format = '%(asctime)-8s [%(levelname)s]: %(message)s', datefmt = '%H:%M:%S')

  logging.debug("Options: %s", str(options))

  # check options
  global PROGRESS
  PROGRESS = options.progress
  if (not options.esp_ip or not options.image):
    logging.critical("Not enough arguments.")

    return 1
  # end if

  command = FLASH
  if (options.spiffs):
    command = SPIFFS
  # end if

  return serve(options.esp_ip, options.host_ip, options.esp_port, options.host_port, options.auth, options.image, command)
# end main

if __name__ == '__main__':
  sys.exit(main(sys.argv))
# end if
<commit_msg>fixed argument passing (#2209)<commit_after>#!/usr/bin/env python
#
# Original espota.py by Ivan Grokhotkov:
# https://gist.github.com/igrr/d35ab8446922179dc58c
#
# Modified since 2015-09-18 from Pascal Gollor (https://github.com/pgollor)
# Modified since 2015-11-09 from Hristo Gochkov (https://github.com/me-no-dev)
# Modified since 2016-01-03 from Matthew O'Gorman (https://githumb.com/mogorman)
#
# This script will push an OTA update to the ESP
# use it like: python espota.py -i <ESP_IP_address> -I <Host_IP_address> -p <ESP_port> -P <Host_port> [-a password] -f <sketch.bin>
# Or to upload SPIFFS image:
# python espota.py -i <ESP_IP_address> -I <Host_IP_address> -p <ESP_port> -P <HOST_port> [-a password] -s -f <spiffs.bin>
#
# Changes
# 2015-09-18:
# - Add option parser.
# - Add logging.
# - Send command to controller to differ between flashing and transmitting SPIFFS image.
#
# Changes
# 2015-11-09:
# - Added digest authentication
# - Enhanced error tracking and reporting
#
# Changes
# 2016-01-03:
# - Added more options to parser.
#

from __future__ import print_function
import socket
import sys
import os
import optparse
import logging
import hashlib
import random

# Commands
FLASH = 0
SPIFFS = 100
AUTH = 200
PROGRESS = False
# update_progress() : Displays or updates a console progress bar
## Accepts a float between 0 and 1. Any int will be converted to a float.
## A value under 0 represents a 'halt'.
## A value at 1 or bigger represents 100%
def update_progress(progress):
  if (PROGRESS):
    barLength = 60 # Modify this to change the length of the progress bar
    status = ""
    if isinstance(progress, int):
      progress = float(progress)
    if not isinstance(progress, float):
      progress = 0
      status = "error: progress var must be float\r\n"
    if progress < 0:
      progress = 0
      status = "Halt...\r\n"
    if progress >= 1:
      progress = 1
      status = "Done...\r\n"
    block = int(round(barLength*progress))
    text = "\rUploading: [{0}] {1}% {2}".format( "="*block + " "*(barLength-block), int(progress*100), status)
    sys.stderr.write(text)
    sys.stderr.flush()
  else:
    sys.stderr.write('.')
    sys.stderr.flush()

def serve(remoteAddr, localAddr, remotePort, localPort, password, filename, command = FLASH):
  # Create a TCP/IP socket
  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  server_address = (localAddr, localPort)
  logging.info('Starting on %s:%s', str(server_address[0]), str(server_address[1]))
  try:
    sock.bind(server_address)
    sock.listen(1)
  except:
    logging.error("Listen Failed")
    return 1

  content_size = os.path.getsize(filename)
  f = open(filename,'rb')
  file_md5 = hashlib.md5(f.read()).hexdigest()
  f.close()
  logging.info('Upload size: %d', content_size)
  message = '%d %d %d %s\n' % (command, localPort, content_size, file_md5)

  # Wait for a connection
  logging.info('Sending invitation to: %s', remoteAddr)
  sock2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  remote_address = (remoteAddr, int(remotePort))
  sent = sock2.sendto(message.encode(), remote_address)
  sock2.settimeout(10)
  try:
    data = sock2.recv(37).decode()
  except:
    logging.error('No Answer')
    sock2.close()
    return 1
  if (data != "OK"):
    if(data.startswith('AUTH')):
      nonce = data.split()[1]
      cnonce_text = '%s%u%s%s' % (filename, content_size, file_md5, remoteAddr)
      cnonce = hashlib.md5(cnonce_text.encode()).hexdigest()
      passmd5 = hashlib.md5(password.encode()).hexdigest()
      result_text = '%s:%s:%s' % (passmd5 ,nonce, cnonce)
      result = hashlib.md5(result_text.encode()).hexdigest()
      sys.stderr.write('Authenticating...')
      sys.stderr.flush()
      message = '%d %s %s\n' % (AUTH, cnonce, result)
      sock2.sendto(message.encode(), remote_address)
      sock2.settimeout(10)
      try:
        data = sock2.recv(32).decode()
      except:
        sys.stderr.write('FAIL\n')
        logging.error('No Answer to our Authentication')
        sock2.close()
        return 1
      if (data != "OK"):
        sys.stderr.write('FAIL\n')
        logging.error('%s', data)
        sock2.close()
        sys.exit(1);
        return 1
      sys.stderr.write('OK\n')
    else:
      logging.error('Bad Answer: %s', data)
      sock2.close()
      return 1
  sock2.close()

  logging.info('Waiting for device...')
  try:
    sock.settimeout(10)
    connection, client_address = sock.accept()
    sock.settimeout(None)
    connection.settimeout(None)
  except:
    logging.error('No response from device')
    sock.close()
    return 1

  try:
    f = open(filename, "rb")
    if (PROGRESS):
      update_progress(0)
    else:
      sys.stderr.write('Uploading')
      sys.stderr.flush()
    offset = 0
    while True:
      chunk = f.read(1460)
      if not chunk: break
      offset += len(chunk)
      update_progress(offset/float(content_size))
      connection.settimeout(10)
      try:
        connection.sendall(chunk)
        res = connection.recv(4)
      except:
        sys.stderr.write('\n')
        logging.error('Error Uploading')
        connection.close()
        f.close()
        sock.close()
        return 1

    sys.stderr.write('\n')
    logging.info('Waiting for result...')
    try:
      connection.settimeout(60)
      data = connection.recv(32).decode()
      logging.info('Result: %s' ,data)
      connection.close()
      f.close()
      sock.close()
      if (data != "OK"):
        sys.stderr.write('\n')
        logging.error('%s', data)
        return 1;
      return 0
    except:
      logging.error('No Result!')
      connection.close()
      f.close()
      sock.close()
      return 1

  finally:
    connection.close()
    f.close()

  sock.close()
  return 1
# end serve

def parser(unparsed_args):
  parser = optparse.OptionParser(
    usage = "%prog [options]",
    description = "Transmit image over the air to the esp8266 module with OTA support."
  )

  # destination ip and port
  group = optparse.OptionGroup(parser, "Destination")
  group.add_option("-i", "--ip",
    dest = "esp_ip",
    action = "store",
    help = "ESP8266 IP Address.",
    default = False
  )
  group.add_option("-I", "--host_ip",
    dest = "host_ip",
    action = "store",
    help = "Host IP Address.",
    default = "0.0.0.0"
  )
  group.add_option("-p", "--port",
    dest = "esp_port",
    type = "int",
    help = "ESP8266 ota Port. Default 8266",
    default = 8266
  )
  group.add_option("-P", "--host_port",
    dest = "host_port",
    type = "int",
    help = "Host server ota Port. Default random 10000-60000",
    default = random.randint(10000,60000)
  )
  parser.add_option_group(group)

  # auth
  group = optparse.OptionGroup(parser, "Authentication")
  group.add_option("-a", "--auth",
    dest = "auth",
    help = "Set authentication password.",
    action = "store",
    default = ""
  )
  parser.add_option_group(group)

  # image
  group = optparse.OptionGroup(parser, "Image")
  group.add_option("-f", "--file",
    dest = "image",
    help = "Image file.",
    metavar="FILE",
    default = None
  )
  group.add_option("-s", "--spiffs",
    dest = "spiffs",
    action = "store_true",
    help = "Use this option to transmit a SPIFFS image and do not flash the module.",
    default = False
  )
  parser.add_option_group(group)

  # output group
  group = optparse.OptionGroup(parser, "Output")
  group.add_option("-d", "--debug",
    dest = "debug",
    help = "Show debug output. And override loglevel with debug.",
    action = "store_true",
    default = False
  )
  group.add_option("-r", "--progress",
    dest = "progress",
    help = "Show progress output. Does not work for ArduinoIDE",
    action = "store_true",
    default = False
  )
  parser.add_option_group(group)

  (options, args) = parser.parse_args(unparsed_args)

  return options
# end parser

def main(args):
  # get options
  options = parser(args)

  # adapt log level
  loglevel = logging.WARNING
  if (options.debug):
    loglevel = logging.DEBUG
  # end if

  # logging
  logging.basicConfig(level = loglevel, format = '%(asctime)-8s [%(levelname)s]: %(message)s', datefmt = '%H:%M:%S')

  logging.debug("Options: %s", str(options))

  # check options
  global PROGRESS
  PROGRESS = options.progress
  if (not options.esp_ip or not options.image):
    logging.critical("Not enough arguments.")

    return 1
  # end if

  command = FLASH
  if (options.spiffs):
    command = SPIFFS
  # end if

  return serve(options.esp_ip, options.host_ip, options.esp_port, options.host_port, options.auth, options.image, command)
# end main

if __name__ == '__main__':
  sys.exit(main(sys.argv))
# end if
<|endoftext|>


<commit_before>import httplib
import inspect
import json
import os
from subprocess import Popen, PIPE

import nipype

def is_git_repo():
    """Does the current nipype module have a git folder
    """
    sourcepath = os.path.realpath(os.path.join(os.path.dirname(nipype.__file__),
                                               os.path.pardir))
    gitpathgit = os.path.join(sourcepath, '.git')
    if os.path.exists(gitpathgit):
        return True
    else:
        return False

def get_local_branch():
    """Determine current branch
    """
    if is_git_repo():
        o, _ = Popen('git branch | grep "\* "', shell=True, stdout=PIPE,
                     cwd=os.path.dirname(nipype.__file__)).communicate()
        return o.strip()[2:]
    else:
        return None

def get_remote_branch():
    """Get remote branch for current branch
    """

    pass

def create_hash_map():
    """Create a hash map for all objects
    """

    hashmap = {}
    conn = httplib.HTTPSConnection("api.github.com")
    try:
        conn.request("GET", "/repos/nipy/nipype/git/trees/master?recursive=1")
    except:
        pass
    else:
        r1 = conn.getresponse()
        if r1.reason != 'OK':
            raise Exception('HTTP Response  %s:%s' % (r1.status, r1.reason))
        payload = json.loads(r1.read())
        for infodict in payload['tree']:
            if infodict['type'] == "blob":
                hashmap[infodict['sha']] = infodict['path']
    return hashmap

def get_repo_url(force_github=False):
    """Returns github url or local url

    Returns
    -------
    URI: str
       filesystem path or github repo url
    """
    sourcepath = os.path.realpath(os.path.join(os.path.dirname(nipype.__file__),
                                               os.path.pardir))
    gitpathgit = os.path.join(sourcepath, '.git')
    if not os.path.exists(gitpathgit) and not force_github:
        uri = 'file://%s' % sourcepath
    else:
        uri = 'http://github.com/nipy/nipype/blob/master'
    return uri

def get_file_url(object, hashmap):
    """Returns local or remote url for an object
    """
    filename = inspect.getsourcefile(object)
    lines = inspect.getsourcelines(object)
    uri = 'file://%s#L%d' % (filename, lines[1])
    if is_git_repo():
        o, _ = Popen('git hash-object %s' % filename, shell=True, stdout=PIPE,
                     cwd=os.path.dirname(nipype.__file__)).communicate()
        key = o.strip()
        if key in hashmap:
            uri = 'http://github.com/nipy/nipype/blob/master/' + \
                  hashmap[key] + '#L%d' % lines[1]
    return uri
<commit_msg>fix: github authentication<commit_after>import httplib
import inspect
import json
import os
from subprocess import Popen, PIPE

import nipype

def is_git_repo():
    """Does the current nipype module have a git folder
    """
    sourcepath = os.path.realpath(os.path.join(os.path.dirname(nipype.__file__),
                                               os.path.pardir))
    gitpathgit = os.path.join(sourcepath, '.git')
    if os.path.exists(gitpathgit):
        return True
    else:
        return False

def get_local_branch():
    """Determine current branch
    """
    if is_git_repo():
        o, _ = Popen('git branch | grep "\* "', shell=True, stdout=PIPE,
                     cwd=os.path.dirname(nipype.__file__)).communicate()
        return o.strip()[2:]
    else:
        return None

def get_remote_branch():
    """Get remote branch for current branch
    """

    pass

def create_hash_map():
    """Create a hash map for all objects
    """

    hashmap = {}
    from base64 import encodestring as base64
    import pwd
    login_name = pwd.getpwuid(os.geteuid())[0]
    conn = httplib.HTTPSConnection("api.github.com")
    conn.request("GET", "/repos/nipy/nipype",
                 headers={'Authorization': 'Basic %s' % base64(login_name)})
    try:
        conn.request("GET", "/repos/nipy/nipype/git/trees/master?recursive=1")
    except:
        pass
    else:
        r1 = conn.getresponse()
        if r1.reason != 'OK':
            raise Exception('HTTP Response  %s:%s' % (r1.status, r1.reason))
        payload = json.loads(r1.read())
        for infodict in payload['tree']:
            if infodict['type'] == "blob":
                hashmap[infodict['sha']] = infodict['path']
    return hashmap

def get_repo_url(force_github=False):
    """Returns github url or local url

    Returns
    -------
    URI: str
       filesystem path or github repo url
    """
    sourcepath = os.path.realpath(os.path.join(os.path.dirname(nipype.__file__),
                                               os.path.pardir))
    gitpathgit = os.path.join(sourcepath, '.git')
    if not os.path.exists(gitpathgit) and not force_github:
        uri = 'file://%s' % sourcepath
    else:
        uri = 'http://github.com/nipy/nipype/blob/master'
    return uri

def get_file_url(object, hashmap):
    """Returns local or remote url for an object
    """
    filename = inspect.getsourcefile(object)
    lines = inspect.getsourcelines(object)
    uri = 'file://%s#L%d' % (filename, lines[1])
    if is_git_repo():
        o, _ = Popen('git hash-object %s' % filename, shell=True, stdout=PIPE,
                     cwd=os.path.dirname(nipype.__file__)).communicate()
        key = o.strip()
        if key in hashmap:
            uri = 'http://github.com/nipy/nipype/blob/master/' + \
                  hashmap[key] + '#L%d' % lines[1]
    return uri
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

from gi.repository import GLib, Gtk, Vte
import signal
import os

class TerminalTab(Vte.Terminal):
    def __init__(self, notebook, host, *args, **kwargs):
        super(TerminalTab, self).__init__(*args, **kwargs)

        self.notebook = notebook
        self.host = host

        self.activator = Gtk.CheckButton()
        self.activator.set_active(True)
        self.activator.connect(
            'toggled',
            lambda s: self.emit('window-title-changed')
        )

        self.label = Gtk.Label()
        self.label.set_markup(self.get_term_title())

        self.connect('window-title-changed', self.on_title_changed)
        self.connect('child-exited', self.refresh)

    def get_tab(self):
        layout = Gtk.HBox(spacing=5)

        layout.pack_start(self.activator, False, True, 0)
        layout.pack_start(self.label, True, True, 0)

        refresh = Gtk.ToolButton.new_from_stock(Gtk.STOCK_REFRESH)
        refresh.connect('clicked', self.refresh)
        layout.pack_end(refresh, False, True, 0)

        layout.show_all()
        return layout

    def refresh(self, sender):
        try:
            os.kill(self.pid, signal.SIGINT)

        except OSError:
            pass

        self.reset(True, True)
        self()

    def get_term_title(self, nomarkup=False):
        title = self.get_window_title() or self.host

        if nomarkup:
            return title

        elif self.activator.get_active():
            return '{0}'.format(title)

        else:
            return '{0}'.format(title)

    def on_title_changed(self, sender):
        self.label.set_markup(self.get_term_title())

    def toggle_active(self, sender):
        self.activator.set_active(not self.activator.get_active())
        self.emit('window-title-changed')

    def __call__(self):
        _, self.pid = self.fork_command_full(
            Vte.PtyFlags.DEFAULT,
            os.environ['HOME'],
            [
                os.environ['SHELL'] or '/bin/sh',
                '-c',
                'ssh {0}'.format(self.host)
            ],
            [],
            GLib.SpawnFlags.DO_NOT_REAP_CHILD,
            None,
            None
        )

class Notebook(Gtk.Notebook):
    def __init__(self, hosts, *args, **kwargs):
        super(Notebook, self).__init__(*args, **kwargs)

        self.set_scrollable(True)

        for host in hosts:
            # Create VTE Terminal with SSH connection
            term = TerminalTab(self, host)
            term()

            self.append_page_menu(term, term.get_tab(), term.label)

    @property
    def current(self):
        return self.get_nth_page(self.get_current_page())
<commit_msg>add: custom tab title<commit_after># -*- coding: utf-8 -*-

from gi.repository import GLib, Gtk, Vte
import signal
import os

class TerminalTab(Vte.Terminal):
    def __init__(self, notebook, host, title=None, *args, **kwargs):
        super(TerminalTab, self).__init__(*args, **kwargs)

        self.notebook = notebook
        self.host = host
        self.title = title or host

        self.activator = Gtk.CheckButton()
        self.activator.set_active(True)
        self.activator.connect(
            'toggled',
            lambda s: self.emit('window-title-changed')
        )

        self.label = Gtk.Label()
        self.label.set_markup(self.get_term_title())

        self.connect('window-title-changed', self.on_title_changed)
        self.connect('child-exited', self.refresh)

    def get_tab(self):
        layout = Gtk.HBox(spacing=5)

        layout.pack_start(self.activator, False, True, 0)
        layout.pack_start(self.label, True, True, 0)

        refresh = Gtk.ToolButton.new_from_stock(Gtk.STOCK_REFRESH)
        refresh.connect('clicked', self.refresh)
        layout.pack_end(refresh, False, True, 0)

        layout.show_all()
        return layout

    def refresh(self, sender):
        try:
            os.kill(self.pid, signal.SIGINT)

        except OSError:
            pass

        self.reset(True, True)
        self()

    def get_term_title(self, nomarkup=False):
        title = self.get_window_title() or self.title

        if nomarkup:
            return title

        elif self.activator.get_active():
            return '{0}'.format(title)

        else:
            return '{0}'.format(title)

    def on_title_changed(self, sender):
        self.label.set_markup(self.get_term_title())

    def toggle_active(self, sender):
        self.activator.set_active(not self.activator.get_active())
        self.emit('window-title-changed')

    def __call__(self):
        _, self.pid = self.fork_command_full(
            Vte.PtyFlags.DEFAULT,
            os.environ['HOME'],
            [
                os.environ['SHELL'] or '/bin/sh',
                '-c',
                'ssh {0}'.format(self.host)
            ],
            [],
            GLib.SpawnFlags.DO_NOT_REAP_CHILD,
            None,
            None
        )

class Notebook(Gtk.Notebook):
    def __init__(self, hosts, *args, **kwargs):
        super(Notebook, self).__init__(*args, **kwargs)

        self.set_scrollable(True)

        for host in hosts:
            if isinstance(host, basestring):
                # Create VTE Terminal with SSH connection
                term = TerminalTab(self, host)

            elif isinstance(host, dict):
                term = TerminalTab(self, host['addr'], title=host['name'])

            term()

            self.append_page_menu(term, term.get_tab(), term.label)

    @property
    def current(self):
        return self.get_nth_page(self.get_current_page())
<|endoftext|>


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

import os
import subprocess
from subprocess import CalledProcessError, check_call
from mapdamage.version import __version__
import mapdamage
import logging
import time

def construct_path(name,folder="Rscripts"):
    """Construct a path to the mapdamage package data given the name"""
    return(os.path.join(mapdamage.__path__[0], folder, name))

def plot(opt):
  """
  Calls the R script to make the plots, takes in the arguments
  from parameter processing
  """
  # comp<-args[1]
  # pdfout<-args[2]
  # around<-as.numeric(args[3])
  # misincorp<-args[4]
  # lg<-as.numeric(args[5])
  # ymax<-as.numeric(args[6])
  # folder<-args[7]
  # title<-args[8]
  # version<-args[9]

  fmut = opt.folder+"/"+"misincorporation.txt"
  fcomp = opt.folder+"/"+"dnacomp.txt"
  title = opt.folder+"/"+"Fragmisincorporation_plot.pdf"

  script = construct_path("mapDamage.R")
  call = ["Rscript", script, fcomp, title, opt.refplot, fmut, opt.readplot, \
      opt.ymax, opt.folder, opt.title, __version__]
  code = subprocess.call(map(str, call))

  if code == 0:
    if not opt.quiet:
      print("pdf %s generated" % title)
    return 0
  else:
    print("Error: plotting with R failed")
    return 1

def opt_plots(opt):
  """ optional plots for length distribution
  and cumulative C>T mutations, per strand """

  fmut = opt.folder+"/"+"misincorporation.txt"
  flength = opt.folder+"/"+"lgdistribution.txt"
  output = opt.folder+"/"+"Length_plot.pdf"

  script = construct_path("lengths.R")
  call = ["Rscript", script, flength, output, fmut, opt.length, \
      opt.title, __version__, bool_to_int(opt.quiet)]
  code = subprocess.call(map(str, call))
  if code == 0:
    return 0
  else:
    print("Error: plotting with R failed")
    return 1

def check_R_one_lib(name):
    """Checks if a necessary R library is here."""
    with open(os.devnull, "w") as devnull:
        rpa = construct_path("stats/checkLibraries.R")
        return subprocess.call(["Rscript", rpa, "--args", name],
                               stdout = devnull,
                               stderr = devnull)

def check_R_lib():
    """
    Checks if the necessary R libraries are here, signal
    otherwise
    """
    libs = ["inline", "ggplot2", "gam", "Rcpp", "RcppGSL"]
    missing_lib = []
    for lib in libs:
        # Check the libraries
        if check_R_one_lib(lib):
            #found a missing library
            missing_lib.append(lib)
    if len(missing_lib) > 1:
        # Grammar Nazi has arrived
        last_ele = missing_lib.pop()
        print ("Missing the following R libraries '" + "', '".join(missing_lib) \
            + "' and '" + last_ele + "'")
        return 1
    elif len(missing_lib) == 1:
        print ("Missing the following R library "+missing_lib[0])
        return 1
    else :
        # No missing libraries
        return 0

def run_stats(opt):
    """
    Runs the Bayesian estimation program, using the options opt
    """
    arg = ["Rscript",                            \
         construct_path("stats/runGeneral.R"), \
         "--args",                               \
         opt.rand,                               \
         opt.burn,                               \
         opt.adjust,                             \
         opt.iter,                               \
         bool_to_int(opt.forward),               \
         bool_to_int(opt.reverse),               \
         bool_to_int(not opt.var_disp),              \
         bool_to_int(not opt.diff_hangs),            \
         0,                                      \
         bool_to_int(opt.fix_nicks),             \
         bool_to_int(not opt.single_stranded),       \
         opt.seq_length,                         \
         opt.folder+"/",                         \
         construct_path("stats/"),             \
         opt.folder+"/Stats_out",                \
         int(opt.verbose),                       \
         int(opt.quiet),                         \
         int(opt.jukes_cantor),                       \
         opt.folder+"/acgt_ratio.csv",            \
         int(opt.use_raw_nick_freq),                   \
         int(opt.theme_bw)                   \
         ]
    arg = [str(i) for i in arg]

    logger = logging.getLogger(__name__)
    logger.info("Performing Bayesian estimates")
    logger.debug("Call: %s" % (" ".join(arg),))
    start_time = time.time()

    try:
        check_call(arg)
    except CalledProcessError:
        logger.error("The Bayesian statistics program failed to finish")
        raise SystemError

    logger.debug("Bayesian estimates completed in %f seconds" % (time.time() - start_time,))
    return 0

def bool_to_int(boolean):
    """ return 0 for False and 1 for True """
    result = 1 if boolean else 0
    return result
<commit_msg>Reraise the error to keep the info<commit_after>#!/usr/bin/env python

import os
import subprocess
from subprocess import CalledProcessError, check_call
from mapdamage.version import __version__
import mapdamage
import logging
import time

def construct_path(name,folder="Rscripts"):
    """Construct a path to the mapdamage package data given the name"""
    return(os.path.join(mapdamage.__path__[0], folder, name))

def plot(opt):
  """
  Calls the R script to make the plots, takes in the arguments
  from parameter processing
  """
  # comp<-args[1]
  # pdfout<-args[2]
  # around<-as.numeric(args[3])
  # misincorp<-args[4]
  # lg<-as.numeric(args[5])
  # ymax<-as.numeric(args[6])
  # folder<-args[7]
  # title<-args[8]
  # version<-args[9]

  fmut = opt.folder+"/"+"misincorporation.txt"
  fcomp = opt.folder+"/"+"dnacomp.txt"
  title = opt.folder+"/"+"Fragmisincorporation_plot.pdf"

  script = construct_path("mapDamage.R")
  call = ["Rscript", script, fcomp, title, opt.refplot, fmut, opt.readplot, \
      opt.ymax, opt.folder, opt.title, __version__]
  code = subprocess.call(map(str, call))

  if code == 0:
    if not opt.quiet:
      print("pdf %s generated" % title)
    return 0
  else:
    print("Error: plotting with R failed")
    return 1

def opt_plots(opt):
  """ optional plots for length distribution
  and cumulative C>T mutations, per strand """

  fmut = opt.folder+"/"+"misincorporation.txt"
  flength = opt.folder+"/"+"lgdistribution.txt"
  output = opt.folder+"/"+"Length_plot.pdf"

  script = construct_path("lengths.R")
  call = ["Rscript", script, flength, output, fmut, opt.length, \
      opt.title, __version__, bool_to_int(opt.quiet)]
  code = subprocess.call(map(str, call))
  if code == 0:
    return 0
  else:
    print("Error: plotting with R failed")
    return 1

def check_R_one_lib(name):
    """Checks if a necessary R library is here."""
    with open(os.devnull, "w") as devnull:
        rpa = construct_path("stats/checkLibraries.R")
        return subprocess.call(["Rscript", rpa, "--args", name],
                               stdout = devnull,
                               stderr = devnull)

def check_R_lib():
    """
    Checks if the necessary R libraries are here, signal
    otherwise
    """
    libs = ["inline", "ggplot2", "gam", "Rcpp", "RcppGSL"]
    missing_lib = []
    for lib in libs:
        # Check the libraries
        if check_R_one_lib(lib):
            #found a missing library
            missing_lib.append(lib)
    if len(missing_lib) > 1:
        # Grammar Nazi has arrived
        last_ele = missing_lib.pop()
        print ("Missing the following R libraries '" + "', '".join(missing_lib) \
            + "' and '" + last_ele + "'")
        return 1
    elif len(missing_lib) == 1:
        print ("Missing the following R library "+missing_lib[0])
        return 1
    else :
        # No missing libraries
        return 0

def run_stats(opt):
    """
    Runs the Bayesian estimation program, using the options opt
    """
    arg = ["Rscript",                            \
         construct_path("stats/runGeneral.R"), \
         "--args",                               \
         opt.rand,                               \
         opt.burn,                               \
         opt.adjust,                             \
         opt.iter,                               \
         bool_to_int(opt.forward),               \
         bool_to_int(opt.reverse),               \
         bool_to_int(not opt.var_disp),              \
         bool_to_int(not opt.diff_hangs),            \
         0,                                      \
         bool_to_int(opt.fix_nicks),             \
         bool_to_int(not opt.single_stranded),       \
         opt.seq_length,                         \
         opt.folder+"/",                         \
         construct_path("stats/"),             \
         opt.folder+"/Stats_out",                \
         int(opt.verbose),                       \
         int(opt.quiet),                         \
         int(opt.jukes_cantor),                       \
         opt.folder+"/acgt_ratio.csv",            \
         int(opt.use_raw_nick_freq),                   \
         int(opt.theme_bw)                   \
         ]
    arg = [str(i) for i in arg]

    logger = logging.getLogger(__name__)
    logger.info("Performing Bayesian estimates")
    logger.debug("Call: %s" % (" ".join(arg),))
    start_time = time.time()

    try:
        check_call(arg)
    except CalledProcessError as e:
        logger.error("The Bayesian statistics program failed to finish")
        raise e

    logger.debug("Bayesian estimates completed in %f seconds" % (time.time() - start_time,))
    return 0

def bool_to_int(boolean):
    """ return 0 for False and 1 for True """
    result = 1 if boolean else 0
    return result
<|endoftext|>


<commit_before>from . import engine
from . import models
from . import tasks
from . import utils
from . import datapack
from . import losses
from .version import __version__
from .logger import logger
<commit_msg>Update __init__.py<commit_after>from . import engine
from . import models
from . import tasks
from . import utils
from . import preprocessor
from . import datapack
from . import losses
from .version import __version__
from .logger import logger
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pandas

__authors__ = 'Markus Englund'
__license__ = 'MIT'
__version__ = '0.1.2'

def frame_as_categorical(frame, include_categories=None):
    """
    Return a pandas DataFrame with each column treated as a
    categorical with unordered categories. The same categories
    are applied to all columns.

    Parameters
    ----------
    frame : pandas.DataFrame
    include_categories : list (default: None)
        Categories to add unless they are already present
        in `frame`.
    """
    include_categories = include_categories if include_categories else []
    current_categories = pandas.unique(frame.values.ravel())
    current_categories_notnull = (
        current_categories[pandas.notnull(current_categories)])
    categories = set(current_categories_notnull).union(include_categories)
    categorical = frame.apply(lambda x: pandas.Series(x, dtype='category'))
    unified_categorical = categorical.apply(
        lambda x: x.cat.set_categories(new_categories=categories))
    return unified_categorical

def frame_as_object(frame):
    """
    Return a pandas DataFrame as NumPy `dtype` ``object``.
    Useful for casting from a categorical frame.
    """
    return frame.apply(lambda x: x.astype('object'))

def from_bioalignment(bioalignment, categorical=True):
    """
    Convert a BioPython alignment to a pandas DataFrame.

    Parameters
    ----------
    bioalignment : Bio.Align.MultipleSeqAlignment
    categorical : bool (default: True)
        If True, the result will be returned as a categorical frame.
    """
    frame = pandas.DataFrame()
    dtype = 'category' if categorical else 'object'
    for record in bioalignment:
        s = pandas.Series(list(record.seq), name=record.id, dtype=dtype)
        frame = pandas.concat([frame, s], axis=1)
    return frame

def from_charmatrix(charmatrix, categorical=True):
    """
    Convert a DendroPy CharacterMatrix to a pandas DataFrame.

    Parameters
    ----------
    charmatrix : dendropy.CharacterMatrix
    categorical : bool (default: True)
        If True, the result will be returned as a categorical frame.
    """
    frame = pandas.DataFrame()
    for taxon, seq in charmatrix.items():
        s = pandas.Series(
            seq.symbols_as_list(), name=taxon.label)
        frame = pandas.concat([frame, s], axis=1)
    if categorical:
        state_alphabet = charmatrix.state_alphabets[0].symbols
        new_frame = frame_as_categorical(
            frame, include_categories=state_alphabet)
    else:
        new_frame = frame
    return new_frame

def to_bioalignment(frame, alphabet='generic_alphabet'):
    """
    Convert a pandas DataFrame to a BioPython MultipleSeqAlignment.

    Parameters
    ----------
    frame : pandas.DataFrame
    alphabet : str, default: 'generic_alignment'
        BioPython alphabet to use: 'generic_alphabet', 'generic_dna',
        'generic_nucleotide', 'generic_protein' or 'generic_rna')
    """
    if alphabet not in [
            'generic_alphabet', 'generic_dna',
            'generic_nucleotide', 'generic_protein', 'generic_rna']:
        raise ValueError(
            'Invalid BioPython alphabet: {}'
            .format(alphabet))
    try:
        import Bio.Alphabet
        from Bio.AlignIO import MultipleSeqAlignment
        from Bio.Seq import Seq
        from Bio.SeqRecord import SeqRecord
    except ImportError as ex:
        raise ImportError(
            '\'to_bioalignment\' requires BioPython.\n{ex}'.format(ex=str(ex)))
    alignment = MultipleSeqAlignment([])
    bio_alphabet = getattr(Bio.Alphabet, alphabet)
    for id, seq_series in frame.iteritems():
        seq_record = SeqRecord(
            Seq(''.join(seq_series), alphabet=bio_alphabet),
            id=id)
        alignment.append(seq_record)
    return alignment

def to_charmatrix(frame, data_type):
    """
    Convert a pandas DataFrame to a DendroPy CharacterMatrix.

    Parameters
    ----------
    frame : pandas.DataFrame
    data_type : str
        Type of CharacterMatrix to create: 'dna', 'rna',
        'protein' or 'standard'.
    """
    try:
        import dendropy
    except ImportError as ex:
        raise ImportError(
            '\'to_charmatrix\' requires DendroPy.\n{ex}'.format(ex=str(ex)))
    d = frame.apply(lambda x: ''.join(x), axis=0).to_dict()
    if data_type == 'standard':
        charmatrix = dendropy.StandardCharacterMatrix.from_dict(d)
    elif data_type == 'dna':
        charmatrix = dendropy.DnaCharacterMatrix.from_dict(d)
    elif data_type == 'rna':
        charmatrix = dendropy.RnaCharacterMatrix.from_dict(d)
    elif data_type == 'protein':
        charmatrix = dendropy.ProteinCharacterMatrix.from_dict(d)
    else:
        raise ValueError(
            '{} is not a valid data type'.format(repr(data_type)))
    # Preserve taxon name sort order
    taxon_names = list(frame.columns)
    charmatrix.taxon_namespace.sort(key=lambda x: taxon_names.index(x.label))
    return charmatrix
<commit_msg>Modify lambda function<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pandas

__authors__ = 'Markus Englund'
__license__ = 'MIT'
__version__ = '0.1.2'

def frame_as_categorical(frame, include_categories=None):
    """
    Return a pandas DataFrame with each column treated as a
    categorical with unordered categories. The same categories
    are applied to all columns.

    Parameters
    ----------
    frame : pandas.DataFrame
    include_categories : list (default: None)
        Categories to add unless they are already present
        in `frame`.
    """
    include_categories = include_categories if include_categories else []
    current_categories = pandas.unique(frame.values.ravel())
    current_categories_notnull = (
        current_categories[pandas.notnull(current_categories)])
    categories = set(current_categories_notnull).union(include_categories)
    categorical = frame.apply(lambda x: pandas.Series(x.astype('category')))
    unified_categorical = categorical.apply(
        lambda x: x.cat.set_categories(new_categories=categories))
    return unified_categorical

def frame_as_object(frame):
    """
    Return a pandas DataFrame as NumPy `dtype` ``object``.
    Useful for casting from a categorical frame.
    """
    return frame.apply(lambda x: x.astype('object'))

def from_bioalignment(bioalignment, categorical=True):
    """
    Convert a BioPython alignment to a pandas DataFrame.

    Parameters
    ----------
    bioalignment : Bio.Align.MultipleSeqAlignment
    categorical : bool (default: True)
        If True, the result will be returned as a categorical frame.
    """
    frame = pandas.DataFrame()
    dtype = 'category' if categorical else 'object'
    for record in bioalignment:
        s = pandas.Series(list(record.seq), name=record.id, dtype=dtype)
        frame = pandas.concat([frame, s], axis=1)
    return frame

def from_charmatrix(charmatrix, categorical=True):
    """
    Convert a DendroPy CharacterMatrix to a pandas DataFrame.

    Parameters
    ----------
    charmatrix : dendropy.CharacterMatrix
    categorical : bool (default: True)
        If True, the result will be returned as a categorical frame.
    """
    frame = pandas.DataFrame()
    for taxon, seq in charmatrix.items():
        s = pandas.Series(
            seq.symbols_as_list(), name=taxon.label)
        frame = pandas.concat([frame, s], axis=1)
    if categorical:
        state_alphabet = charmatrix.state_alphabets[0].symbols
        new_frame = frame_as_categorical(
            frame, include_categories=state_alphabet)
    else:
        new_frame = frame
    return new_frame

def to_bioalignment(frame, alphabet='generic_alphabet'):
    """
    Convert a pandas DataFrame to a BioPython MultipleSeqAlignment.

    Parameters
    ----------
    frame : pandas.DataFrame
    alphabet : str, default: 'generic_alignment'
        BioPython alphabet to use: 'generic_alphabet', 'generic_dna',
        'generic_nucleotide', 'generic_protein' or 'generic_rna')
    """
    if alphabet not in [
            'generic_alphabet', 'generic_dna',
            'generic_nucleotide', 'generic_protein', 'generic_rna']:
        raise ValueError(
            'Invalid BioPython alphabet: {}'
            .format(alphabet))
    try:
        import Bio.Alphabet
        from Bio.AlignIO import MultipleSeqAlignment
        from Bio.Seq import Seq
        from Bio.SeqRecord import SeqRecord
    except ImportError as ex:
        raise ImportError(
            '\'to_bioalignment\' requires BioPython.\n{ex}'.format(ex=str(ex)))
    alignment = MultipleSeqAlignment([])
    bio_alphabet = getattr(Bio.Alphabet, alphabet)
    for id, seq_series in frame.iteritems():
        seq_record = SeqRecord(
            Seq(''.join(seq_series), alphabet=bio_alphabet),
            id=id)
        alignment.append(seq_record)
    return alignment

def to_charmatrix(frame, data_type):
    """
    Convert a pandas DataFrame to a DendroPy CharacterMatrix.

    Parameters
    ----------
    frame : pandas.DataFrame
    data_type : str
        Type of CharacterMatrix to create: 'dna', 'rna',
        'protein' or 'standard'.
    """
    try:
        import dendropy
    except ImportError as ex:
        raise ImportError(
            '\'to_charmatrix\' requires DendroPy.\n{ex}'.format(ex=str(ex)))
    d = frame.apply(lambda x: ''.join(x), axis=0).to_dict()
    if data_type == 'standard':
        charmatrix = dendropy.StandardCharacterMatrix.from_dict(d)
    elif data_type == 'dna':
        charmatrix = dendropy.DnaCharacterMatrix.from_dict(d)
    elif data_type == 'rna':
        charmatrix = dendropy.RnaCharacterMatrix.from_dict(d)
    elif data_type == 'protein':
        charmatrix = dendropy.ProteinCharacterMatrix.from_dict(d)
    else:
        raise ValueError(
            '{} is not a valid data type'.format(repr(data_type)))
    # Preserve taxon name sort order
    taxon_names = list(frame.columns)
    charmatrix.taxon_namespace.sort(key=lambda x: taxon_names.index(x.label))
    return charmatrix
<|endoftext|>