<commit_before>"""
platformer.py
Author: Hayden
Credit: Avery, Mr Denison
Assignment:
Write and submit a program that implements the sandbox platformer game:
https://github.com/HHS-IntroProgramming/Platformer
"""
from ggame import App, RectangleAsset, ImageAsset, Sprite, LineStyle, Color, Frame

SCREEN_WIDTH = 10000
SCREEN_HEIGHT = 800

# Background
black = Color(0, 1)
noline = LineStyle(0, black)
bg_asset = RectangleAsset(SCREEN_WIDTH, SCREEN_HEIGHT, noline, black)
bg = Sprite(bg_asset, (0,0))

class GravitySprite(Sprite):

    G = 50.0

    def __init__(self, asset, position, velocity):
        super().__init__(asset, position)
        self.vx = velocity[0]
        self.vy = velocity[1]
        self.mass = 1.0
        self.gravity = 1

    def step(self):
       self.x += self.vx
       self.vy += self.gravity
       self.y+= self.vy

class Floor(Sprite):

    def __init__(self, postion, BitMap):
        fl = ImageAsset(BitMap)
        super().__init__(fl, postion)

    def step(self):
        csprites = self.collidingWithSprites(Player)
        if len(csprites) > 0:
            csprites[0].vy = -1

class VerticalLinkPipe(Floor):
    def __init__(self, position):
        super().__init__(position, "VerticalLinkPipe.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2

class MetalBlock20x20(Floor):
    def __init__(self, position):
        super().__init__(position, "MetalBlock20x20.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2

class MetalPipe166x20(Floor):
    def __init__(self, position):
        super().__init__(position, "MetalPipe166x20.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2

class MetalPipeVertical20x72(Floor):
    def __init__(self, position):
        super().__init__(position, "MetalPipeVertical20x72.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2

class MetalPipeHorizantal103x20(Floor):
    def __init__(self, position):
        super().__init__(position, "MetalPipeHorizantal103x20.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2

class MetalPipeVertical20x103(Floor):
    def __init__(self, position):
        super().__init__(position, "MetalPipeVertical20x103.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2

class MetalPipeHorizantal296x20(Floor):
    def __init__(self, position):
        super().__init__(position, "MetalPipeHorizantal296x20.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2

class MetalPipeVertical20x296(Floor):
    def __init__(self, position):
        super().__init__(position, "MetalPipeVertical20x296.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2

class MetalPipeHorizantal72x20(Floor):
    def __init__(self, position):
        super().__init__(position, "MetalPipeHorizantal72x20.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2

class MetalPipeVertical20x172(Floor):
    def __init__(self, position):
        super().__init__(position, "MetalPipeVertical20x172.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2

class LavaStretched(Floor):
    def __init__(self, position):
        super().__init__(position, "MetalPipeVertical20x172.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2
    def __init__(self, position):
        super().__init__(position, "LavaStretched.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2

class UpsidedownSpikes(Floor):
    def __init__(self, position):
        super().__init__(position, "UpsidedownSpikes.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2

class Player(GravitySprite):
    TT = ImageAsset("PlayerTemplateScaledFixed.png",
    Frame(0,0,66,128), 12, "horizontal")

    def __init__(self, position):
        super().__init__(Player.TT, position, (0, 0))

        self.mass = 30*1000
        self.fxcenter = 0.5
        self.fycenter = 0.5

        self.tickCount = 0
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)
        self.fxcenter = self.fycenter = 0.5
        self.scale  = .4
        self.imagecount = 0
        self.AD = 1

    def step(self):
        super().step()

        self.tickCount += 1
        if self.tickCount %5 == 0:
            self.imagecount += self.AD

            if self.imagecount >=11:
                self.AD *= -1
            self.setImage(self.imagecount)
            if self.imagecount == 0:
                self.AD += 1

    def moveRight(self, event):
        self.x += 2

    def moveLeft(self, event):
        self.x -= 2

class Platformer(App):

    def __init__(self, width, height):
        super().__init__(width, height)
        self.p = Player((200,300))
        self.f1 = MetalPipeHorizantal296x20((34,199))
        self.f2 = MetalPipeHorizantal296x20((5,349))
        self.f3 = MetalPipeHorizantal296x20((589,349))
        self.f4 = MetalPipeHorizantal296x20((865,433))
        self.f5 = MetalPipeHorizantal296x20((1139,518))
        self.f6 = MetalPipeHorizantal296x20((1413,602))
        self.f7 = MetalPipeHorizantal296x20((1687,518))
        self.f8 = MetalPipeHorizantal296x20((1961,518))
        self.f9 = MetalPipeHorizantal296x20((2235,434))
        self.f10 = MetalPipeHorizantal296x20((310,147))
        self.f11 = MetalPipeHorizantal296x20((584,231))
        self.f12 = MetalPipeHorizantal296x20((943,231))
        self.f13 = MetalPipeHorizantal296x20((1217,180))
        self.f14 = MetalPipeHorizantal296x20((1677,127))
        self.f15 = MetalPipeHorizantal296x20((1953,127))

        self.f16 = MetalPipeHorizantal103x20((277,297))
        self.f17 = MetalPipeHorizantal103x20((860,147))
        self.f18 = MetalPipeHorizantal103x20((1228,317))
        self.f19 = MetalPipeHorizantal103x20((1393,279))
        self.f20 = MetalPipeHorizantal103x20((1690,333))
        self.f21 = MetalPipeHorizantal103x20((1819,244))
        self.f22 = MetalPipeHorizantal103x20((2019,243))
        self.f23 = MetalPipeHorizantal103x20((2157,325))

        self.f24 = MetalPipeVertical20x103((506,349))
        self.f25 = MetalPipeVertical20x103((589,349))
        self.f26 = MetalPipeVertical20x103((584,147))
        self.f27 = MetalPipeVertical20x103((860,147))
        self.f28 = MetalPipeVertical20x103((943,147))
        self.f29 = MetalPipeVertical20x103((867,349))
        self.f30 = MetalPipeVertical20x103((1139,350))
        self.f31 = MetalPipeVertical20x103((1139,434))
        self.f32 = MetalPipeVertical20x103((1413,434))
        self.f33 = MetalPipeVertical20x103((1413,518))
        self.f34 = MetalPipeVertical20x103((1687,518))
        self.f35 = MetalPipeVertical20x103((1687,434))
        self.f36 = MetalPipeVertical20x103((1961,434))
        self.f37 = MetalPipeVertical20x103((2235,434))

        self.f38 = MetalPipeVertical20x72((277,297))
        self.f39 = MetalPipeVertical20x72((360,297))
        self.f40 = MetalPipeVertical20x72((310,147))
        self.f41 = MetalPipeVertical20x72((1217,180))

        self.f42 = MetalPipeHorizantal103x20((277,297))
        self.f43 = MetalPipeHorizantal103x20((506,433))
        self.f44 = MetalPipeHorizantal103x20((860,147))

        self.f45 = MetalPipeHorizantal103x20((360,349))

        self.f46 = LavaStretched((883,360))
        self.f47 = LavaStretched((1156,450))
        self.f48 = LavaStretched((1430,523))
        self.f49 = LavaStretched((1704,440))
        self.f50 = LavaStretched((883,353))
        self.f51 = LavaStretched((1978,443))

        self.f52 = UpsidedownSpikes((1013,249))
        self.f53 = UpsidedownSpikes((1037,197))

    def step(self):
        self.p.step()
        self.f1.step()
        self.f2.step()
        self.f3.step()
        self.f4.step()
        self.f5.step()
        self.f6.step()
        self.f7.step()
        self.f8.step()
        self.f9.step()
        self.f10.step()
        self.f11.step()
        self.f12.step()
        self.f13.step()
        self.f14.step()
        self.f15.step()
        self.f16.step()
        self.f17.step()
        self.f18.step()
        self.f19.step()
        self.f20.step()
        self.f21.step()
        self.f22.step()
        self.f23.step()
        self.f24.step()
        self.f25.step()
        self.f26.step()
        self.f27.step()
        self.f27.step()
        self.f28.step()
        self.f29.step()
        self.f30.step()
        self.f31.step()
        self.f32.step()
        self.f33.step()
        self.f34.step()
        self.f35.step()
        self.f36.step()
        self.f37.step()
        self.f38.step()
        self.f39.step()
        self.f40.step()
        self.f41.step()
        self.f42.step()
        self.f43.step()
        self.f44.step()
        self.f45.step()
        self.f46.step()
        self.f47.step()
        self.f48.step()
        self.f49.step()
        self.f50.step()
        self.f51.step()
        self.f52.step()
        self.53.step()

myapp = Platformer(SCREEN_WIDTH, SCREEN_HEIGHT)
myapp.run()<commit_msg>Updated from Brython Server: 6/9/2016 1:27:51 PM<commit_after>"""
platformer.py
Author: Hayden
Credit: Avery, Mr Denison
Assignment:
Write and submit a program that implements the sandbox platformer game:
https://github.com/HHS-IntroProgramming/Platformer
"""
from ggame import App, RectangleAsset, ImageAsset, Sprite, LineStyle, Color, Frame

SCREEN_WIDTH = 10000
SCREEN_HEIGHT = 800

# Background
black = Color(0, 1)
noline = LineStyle(0, black)
bg_asset = RectangleAsset(SCREEN_WIDTH, SCREEN_HEIGHT, noline, black)
bg = Sprite(bg_asset, (0,0))

class GravitySprite(Sprite):

    G = 50.0

    def __init__(self, asset, position, velocity):
        super().__init__(asset, position)
        self.vx = velocity[0]
        self.vy = velocity[1]
        self.mass = 1.0
        self.gravity = 1

    def step(self):
       self.x += self.vx
       self.vy += self.gravity
       self.y+= self.vy

class Floor(Sprite):

    def __init__(self, postion, BitMap):
        fl = ImageAsset(BitMap)
        super().__init__(fl, postion)

    def step(self):
        csprites = self.collidingWithSprites(Player)
        if len(csprites) > 0:
            csprites[0].vy = -1

class VerticalLinkPipe(Floor):
    def __init__(self, position):
        super().__init__(position, "VerticalLinkPipe.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2

class MetalBlock20x20(Floor):
    def __init__(self, position):
        super().__init__(position, "MetalBlock20x20.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2

class MetalPipe166x20(Floor):
    def __init__(self, position):
        super().__init__(position, "MetalPipe166x20.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2

class MetalPipeVertical20x72(Floor):
    def __init__(self, position):
        super().__init__(position, "MetalPipeVertical20x72.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2

class MetalPipeHorizantal103x20(Floor):
    def __init__(self, position):
        super().__init__(position, "MetalPipeHorizantal103x20.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2

class MetalPipeVertical20x103(Floor):
    def __init__(self, position):
        super().__init__(position, "MetalPipeVertical20x103.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2

class MetalPipeHorizantal296x20(Floor):
    def __init__(self, position):
        super().__init__(position, "MetalPipeHorizantal296x20.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2

class MetalPipeVertical20x296(Floor):
    def __init__(self, position):
        super().__init__(position, "MetalPipeVertical20x296.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2

class MetalPipeHorizantal72x20(Floor):
    def __init__(self, position):
        super().__init__(position, "MetalPipeHorizantal72x20.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2

class MetalPipeVertical20x172(Floor):
    def __init__(self, position):
        super().__init__(position, "MetalPipeVertical20x172.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2

class LavaStretched(Floor):
    def __init__(self, position):
        super().__init__(position, "MetalPipeVertical20x172.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2
    def __init__(self, position):
        super().__init__(position, "LavaStretched.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2

class UpsidedownSpikes(Floor):
    def __init__(self, position):
        super().__init__(position, "UpsidedownSpikes.png")
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)

    def moveRight(self, event):
        self.x -= 2

    def moveLeft(self, event):
        self.x += 2

class Player(GravitySprite):
    TT = ImageAsset("PlayerTemplateScaledFixed.png",
    Frame(0,0,66,128), 12, "horizontal")

    def __init__(self, position):
        super().__init__(Player.TT, position, (0, 0))

        self.mass = 30*1000
        self.fxcenter = 0.5
        self.fycenter = 0.5

        self.tickCount = 0
        Platformer.listenKeyEvent("keydown", "d", self.moveRight)
        Platformer.listenKeyEvent("keydown", "a", self.moveLeft)
        self.fxcenter = self.fycenter = 0.5
        self.scale  = .4
        self.imagecount = 0
        self.AD = 1

    def step(self):
        super().step()

        self.tickCount += 1
        if self.tickCount %5 == 0:
            self.imagecount += self.AD

            if self.imagecount >=11:
                self.AD *= -1
            self.setImage(self.imagecount)
            if self.imagecount == 0:
                self.AD += 1

    def moveRight(self, event):
        self.x += 2

    def moveLeft(self, event):
        self.x -= 2

class Platformer(App):

    def __init__(self, width, height):
        super().__init__(width, height)
        self.p = Player((200,300))
        self.f1 = MetalPipeHorizantal296x20((34,199))
        self.f2 = MetalPipeHorizantal296x20((5,349))
        self.f3 = MetalPipeHorizantal296x20((589,349))
        self.f4 = MetalPipeHorizantal296x20((865,433))
        self.f5 = MetalPipeHorizantal296x20((1139,518))
        self.f6 = MetalPipeHorizantal296x20((1413,602))
        self.f7 = MetalPipeHorizantal296x20((1687,518))
        self.f8 = MetalPipeHorizantal296x20((1961,518))
        self.f9 = MetalPipeHorizantal296x20((2235,434))
        self.f10 = MetalPipeHorizantal296x20((310,147))
        self.f11 = MetalPipeHorizantal296x20((584,231))
        self.f12 = MetalPipeHorizantal296x20((943,231))
        self.f13 = MetalPipeHorizantal296x20((1217,180))
        self.f14 = MetalPipeHorizantal296x20((1677,127))
        self.f15 = MetalPipeHorizantal296x20((1953,127))

        self.f16 = MetalPipeHorizantal103x20((277,297))
        self.f17 = MetalPipeHorizantal103x20((860,147))
        self.f18 = MetalPipeHorizantal103x20((1228,317))
        self.f19 = MetalPipeHorizantal103x20((1393,279))
        self.f20 = MetalPipeHorizantal103x20((1690,333))
        self.f21 = MetalPipeHorizantal103x20((1819,244))
        self.f22 = MetalPipeHorizantal103x20((2019,243))
        self.f23 = MetalPipeHorizantal103x20((2157,325))

        self.f24 = MetalPipeVertical20x103((506,349))
        self.f25 = MetalPipeVertical20x103((589,349))
        self.f26 = MetalPipeVertical20x103((584,147))
        self.f27 = MetalPipeVertical20x103((860,147))
        self.f28 = MetalPipeVertical20x103((943,147))
        self.f29 = MetalPipeVertical20x103((867,349))
        self.f30 = MetalPipeVertical20x103((1139,350))
        self.f31 = MetalPipeVertical20x103((1139,434))
        self.f32 = MetalPipeVertical20x103((1413,434))
        self.f33 = MetalPipeVertical20x103((1413,518))
        self.f34 = MetalPipeVertical20x103((1687,518))
        self.f35 = MetalPipeVertical20x103((1687,434))
        self.f36 = MetalPipeVertical20x103((1961,434))
        self.f37 = MetalPipeVertical20x103((2235,434))

        self.f38 = MetalPipeVertical20x72((277,297))
        self.f39 = MetalPipeVertical20x72((360,297))
        self.f40 = MetalPipeVertical20x72((310,147))
        self.f41 = MetalPipeVertical20x72((1217,180))

        self.f42 = MetalPipeHorizantal103x20((277,297))
        self.f43 = MetalPipeHorizantal103x20((506,433))
        self.f44 = MetalPipeHorizantal103x20((860,147))

        self.f45 = MetalPipeHorizantal103x20((360,349))

        self.f46 = LavaStretched((883,360))
        self.f47 = LavaStretched((1156,450))
        self.f48 = LavaStretched((1430,523))
        self.f49 = LavaStretched((1704,440))
        self.f50 = LavaStretched((883,353))
        self.f51 = LavaStretched((1978,443))

        self.f52 = UpsidedownSpikes((1013,249))
        self.f53 = UpsidedownSpikes((1037,197))

    def step(self):
        self.p.step()
        self.f1.step()
        self.f2.step()
        self.f3.step()
        self.f4.step()
        self.f5.step()
        self.f6.step()
        self.f7.step()
        self.f8.step()
        self.f9.step()
        self.f10.step()
        self.f11.step()
        self.f12.step()
        self.f13.step()
        self.f14.step()
        self.f15.step()
        self.f16.step()
        self.f17.step()
        self.f18.step()
        self.f19.step()
        self.f20.step()
        self.f21.step()
        self.f22.step()
        self.f23.step()
        self.f24.step()
        self.f25.step()
        self.f26.step()
        self.f27.step()
        self.f27.step()
        self.f28.step()
        self.f29.step()
        self.f30.step()
        self.f31.step()
        self.f32.step()
        self.f33.step()
        self.f34.step()
        self.f35.step()
        self.f36.step()
        self.f37.step()
        self.f38.step()
        self.f39.step()
        self.f40.step()
        self.f41.step()
        self.f42.step()
        self.f43.step()
        self.f44.step()
        self.f45.step()
        self.f46.step()
        self.f47.step()
        self.f48.step()
        self.f49.step()
        self.f50.step()
        self.f51.step()
        self.f52.step()
        self.f53.step()

myapp = Platformer(SCREEN_WIDTH, SCREEN_HEIGHT)
myapp.run()<|endoftext|>


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

from flexbe_core.core.preemptable_state import PreemptableState
from flexbe_core.core.operatable_state_machine import OperatableStateMachine

from flexbe_core.proxy import ProxyPublisher, ProxySubscriberCached
from flexbe_msgs.msg import Container, OutcomeRequest
from std_msgs.msg import UInt8, String

from flexbe_core.state_logger import StateLogger

class OperatableState(PreemptableState):
    """
    A state that supports autonomy levels and silent mode.
    Also, it allows being tracked by a GUI or anything else
    as it reports each transition and its initial structure.
    An additional method is provided to report custom status messages to the widget.
    """

    def __init__(self, *args, **kwargs):
        super(OperatableState, self).__init__(*args, **kwargs)
        self.transitions = None
        self.autonomy = None

        self._mute = False  # is set to true when used in silent state machine (don't report transitions)
        self._sent_outcome_requests = []  # contains those outcomes that already requested a transition

        self._outcome_topic = 'flexbe/mirror/outcome'
        self._request_topic = 'flexbe/outcome_request'
        self._debug_topic = 'flexbe/debug/current_state'
        self._pub = ProxyPublisher()

        self.__execute = self.execute
        self.execute = self._operatable_execute

    def _build_msg(self, prefix, msg):
        """
        Adds this state to the initial structure message.

        @type prefix: string
        @param prefix: A path consisting of the container hierarchy containing this state.

        @type msg: ContainerStructure
        @param msg: The message that will finally contain the structure message.
        """

        # set path
        name = prefix + self.name

        # no children
        children = None

        # set outcomes
        outcomes = self._outcome_list

        # set transitions and autonomy levels
        transitions = []
        autonomy = []
        for i in range(len(outcomes)):
            outcome = outcomes[i]
            if outcome == 'preempted':          # set preempt transition
                transitions.append('preempted')
                autonomy.append(-1)
            else:
                transitions.append(str(self.transitions[outcome]))
                autonomy.append(self.autonomy[outcome])

        # add to message
        msg.containers.append(Container(name, children, outcomes, transitions, autonomy))

    def _operatable_execute(self, *args, **kwargs):
        outcome = self.__execute(*args, **kwargs)

        if self._is_controlled:
            log_requested_outcome = outcome

            # request outcome because autonomy level is too low
            if not self._force_transition and (self.autonomy.has_key(outcome) and self.autonomy[outcome] >= OperatableStateMachine.autonomy_level or
                                               outcome != OperatableState._loopback_name and
                                               self._get_path() in rospy.get_param('/flexbe/breakpoints', [])):
                if self._sent_outcome_requests.count(outcome) == 0:
                    self._pub.publish(self._request_topic, OutcomeRequest(outcome=self._outcome_list.index(outcome), target=self._parent._get_path() + "/" + self.name))
                    rospy.loginfo("<-- Want result: %s > %s", self.name, outcome)
                    StateLogger.log_state_execution(self._get_path(), self.__class__.__name__, outcome, not self._force_transition, False)
                    self._sent_outcome_requests.append(outcome)
                outcome = OperatableState._loopback_name

            # autonomy level is high enough, report the executed transition
            elif outcome != OperatableState._loopback_name:
                self._sent_outcome_requests = []
                rospy.loginfo("State result: %s > %s", self.name, outcome)
                self._pub.publish(self._outcome_topic, UInt8(self._outcome_list.index(outcome)))
                self._pub.publish(self._debug_topic, String("%s > %s" % (self._get_path(), outcome)))
                StateLogger.log_state_execution(self._get_path(), self.__class__.__name__, outcome, not self._force_transition, True)

        self._force_transition = False

        return outcome

    def _notify_skipped(self):
        super(OperatableState, self)._notify_skipped()

    def _enable_ros_control(self):
        super(OperatableState, self)._enable_ros_control()
        self._pub.createPublisher(self._outcome_topic, UInt8)
        self._pub.createPublisher(self._debug_topic, String)
        self._pub.createPublisher(self._request_topic, OutcomeRequest)

<commit_msg>[flexbe_core] Clear previous outcome requests on state loopback (see #93)<commit_after>#!/usr/bin/env python
import rospy

from flexbe_core.core.preemptable_state import PreemptableState
from flexbe_core.core.operatable_state_machine import OperatableStateMachine

from flexbe_core.proxy import ProxyPublisher, ProxySubscriberCached
from flexbe_msgs.msg import Container, OutcomeRequest
from std_msgs.msg import UInt8, String

from flexbe_core.state_logger import StateLogger

class OperatableState(PreemptableState):
    """
    A state that supports autonomy levels and silent mode.
    Also, it allows being tracked by a GUI or anything else
    as it reports each transition and its initial structure.
    An additional method is provided to report custom status messages to the widget.
    """

    def __init__(self, *args, **kwargs):
        super(OperatableState, self).__init__(*args, **kwargs)
        self.transitions = None
        self.autonomy = None

        self._mute = False  # is set to true when used in silent state machine (don't report transitions)
        self._last_requested_outcome = None

        self._outcome_topic = 'flexbe/mirror/outcome'
        self._request_topic = 'flexbe/outcome_request'
        self._debug_topic = 'flexbe/debug/current_state'
        self._pub = ProxyPublisher()

        self.__execute = self.execute
        self.execute = self._operatable_execute

    def _build_msg(self, prefix, msg):
        """
        Adds this state to the initial structure message.

        @type prefix: string
        @param prefix: A path consisting of the container hierarchy containing this state.

        @type msg: ContainerStructure
        @param msg: The message that will finally contain the structure message.
        """

        # set path
        name = prefix + self.name

        # no children
        children = None

        # set outcomes
        outcomes = self._outcome_list

        # set transitions and autonomy levels
        transitions = []
        autonomy = []
        for i in range(len(outcomes)):
            outcome = outcomes[i]
            if outcome == 'preempted':          # set preempt transition
                transitions.append('preempted')
                autonomy.append(-1)
            else:
                transitions.append(str(self.transitions[outcome]))
                autonomy.append(self.autonomy[outcome])

        # add to message
        msg.containers.append(Container(name, children, outcomes, transitions, autonomy))

    def _operatable_execute(self, *args, **kwargs):
        outcome = self.__execute(*args, **kwargs)

        if self._is_controlled:

            # reset previously requested outcome if applicable
            if self._last_requested_outcome is not None and outcome == OperatableState._loopback_name:
                self._pub.publish(self._request_topic, OutcomeRequest(outcome=255, target=self._parent._get_path() + "/" + self.name))
                self._last_requested_outcome = None

            # request outcome because autonomy level is too low
            if not self._force_transition and (self.autonomy.has_key(outcome) and self.autonomy[outcome] >= OperatableStateMachine.autonomy_level or
                                               outcome != OperatableState._loopback_name and
                                               self._get_path() in rospy.get_param('/flexbe/breakpoints', [])):
                if outcome != self._last_requested_outcome:
                    self._pub.publish(self._request_topic, OutcomeRequest(outcome=self._outcome_list.index(outcome), target=self._parent._get_path() + "/" + self.name))
                    rospy.loginfo("<-- Want result: %s > %s", self.name, outcome)
                    StateLogger.log_state_execution(self._get_path(), self.__class__.__name__, outcome, not self._force_transition, False)
                    self._last_requested_outcome = outcome
                outcome = OperatableState._loopback_name

            # autonomy level is high enough, report the executed transition
            elif outcome != OperatableState._loopback_name:
                self._sent_outcome_requests = []
                rospy.loginfo("State result: %s > %s", self.name, outcome)
                self._pub.publish(self._outcome_topic, UInt8(self._outcome_list.index(outcome)))
                self._pub.publish(self._debug_topic, String("%s > %s" % (self._get_path(), outcome)))
                StateLogger.log_state_execution(self._get_path(), self.__class__.__name__, outcome, not self._force_transition, True)

        self._force_transition = False

        return outcome

    def _notify_skipped(self):
        super(OperatableState, self)._notify_skipped()

    def _enable_ros_control(self):
        super(OperatableState, self)._enable_ros_control()
        self._pub.createPublisher(self._outcome_topic, UInt8)
        self._pub.createPublisher(self._debug_topic, String)
        self._pub.createPublisher(self._request_topic, OutcomeRequest)

<|endoftext|>


<commit_before># -*- Mode: Python -*-
# vi:si:et:sw=4:sts=4:ts=4

# Flumotion - a streaming media server
# Copyright (C) 2004,2005,2006,2007,2008,2009 Fluendo, S.L.
# Copyright (C) 2010,2011 Flumotion Services, S.A.
# All rights reserved.
#
# This file may be distributed and/or modified under the terms of
# the GNU Lesser General Public License version 2.1 as published by
# the Free Software Foundation.
# This file is distributed without any warranty; without even the implied
# warranty of merchantability or fitness for a particular purpose.
# See "LICENSE.LGPL" in the source distribution for more information.
#
# Headers in this file shall remain intact.

import os
from collections import deque

from Crypto.Cipher import AES

from twisted.internet import reactor
from flumotion.component.common.streamer.fragmentedresource import\
    FragmentNotAvailable, FragmentNotFound, PlaylistNotFound, KeyNotFound

class Playlister:
    """
    I write HTTP Live Streaming playlists based on added fragments.
    """

    def __init__(self):
        self._hostname = ''
        self.mainPlaylist = ''
        self.streamPlaylist = ''
        self.streamBitrate = 0
        self.title = ''
        self.fragmentPrefix = ''
        self.newFragmentTolerance = 0
        self.window = 0
        self.keysURI = ''
        self.filenameExt = 'webm'
        #FIXME: Make it a property
        self.allowCache = True
        self._fragments = []
        self._dummyFragments = []
        self._counter = 0
        self._isAutoUpdate = False

    def setHostname(self, hostname):
        if hostname.startswith('/'):
            hostname = hostname[1:]
        if not hostname.endswith('/'):
            hostname = hostname + '/'
        if not hostname.startswith('http://'):
            hostname = 'http://' + hostname
        self._hostname = hostname

    def setAllowCache(self, allowed):
        self.allowCache = allowed

    def _getFragmentName(self, sequenceNumber):
        return '%s-%s.%s' % (self.fragmentPrefix, sequenceNumber,
                             self.filenameExt)

    def _getTargetDuration(self):
        sorted_list = sorted(self._fragments, key=lambda fragment: fragment[1])
        return int(sorted_list[0][1])

    def _autoUpdate(self, count):
        if self._counter == count:
            self._isAutoUpdate = True
            self._dummyFragments.append(self._getFragmentName(count))
            self._addPlaylistFragment(count, self._duration, False)

    def _addPlaylistFragment(self, sequenceNumber, duration, encrypted):
        # Add the fragment to the playlist if it wasn't added before
        if not sequenceNumber in [frag[0] for frag in self._fragments]:
            # Add a discontinuity if the sequenceNumber is not the expected
            self._fragments.append((sequenceNumber, duration, encrypted,
                sequenceNumber != self._counter and self._counter != 0))
            self._counter = sequenceNumber + 1
            # Remove fragments that are out of the window
            while len(self._fragments) > self.window:
                # If it's a dummy fragment, remove it from the list too
                fragName = self._getFragmentName(self._fragments[0][0])
                if fragName in self._dummyFragments:
                    self._dummyFragments.remove(fragName)
                del self._fragments[0]

        # Auto update the playlist when the next fragment was not added
        # If the fragment was automatically added update again after 'duration'
        if self.newFragmentTolerance != 0:
            reactor.callLater(self._isAutoUpdate and
                    duration or duration * (1 + self.newFragmentTolerance),
                    self._autoUpdate, self._counter)
        self._isAutoUpdate= False

        return self._getFragmentName(sequenceNumber)

    def renderArgs(self, args):
        if 'FLUREQID' in args:
            del args['FLUREQID']
        if len(args) == 0:
            return ''

        return '?' + '&'.join(["%s=%s" % (k, v[0]) for k, v in
                              args.iteritems()])

    def _renderMainPlaylist(self, args):
        lines = []

        lines.append("#EXTM3U")
        #The bandwith value is not significant for single bitrate
        lines.append("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=%s" %
                self.streamBitrate)
        lines.append("".join([self._hostname, self.streamPlaylist,
            self.renderArgs(args)]))
        lines.append("")

        return "\n".join(lines)

    def _renderStreamPlaylist(self, args):
        lines = []

        lines.append("#EXTM3U")
        lines.append("#EXT-X-ALLOW-CACHE:%s" %
                (self.allowCache and 'YES' or 'NO'))
        lines.append("#EXT-X-TARGETDURATION:%d" % self._getTargetDuration())
        lines.append("#EXT-X-MEDIA-SEQUENCE:%s" % self._fragments[0][0])

        for sequenceNumber, duration, encrypted, discon in self._fragments:
            if discon:
                lines.append("#EXT-X-DISCONTINUITY")
            # FIXME: Not fully implemented yet
            if encrypted:
                lines.append('#EXT-X-KEY:METHOD=AES-128,URI="%s?key=%s"' %
                        (self.keysURI, fragment))
            lines.append("#EXTINF:%d,%s" % (duration, self.title))
            lines.append(''.join([self._hostname,
                self._getFragmentName(sequenceNumber), self.renderArgs(args)]))

        lines.append("")

        return "\n".join(lines)

    def renderPlaylist(self, playlist, args):
        '''
        Returns a string representation of the requested playlist or raise
        an Exception if the playlist is not found
        '''
        if playlist == self.mainPlaylist:
            return self._renderMainPlaylist(args)
        elif playlist == self.streamPlaylist:
            return self._renderStreamPlaylist(args)
        raise PlaylistNotFound()

class HLSRing(Playlister):
    '''
    I hold a ring with the fragments available in the playlist
    and update the playlist according to this.
    '''

    BLOCK_SIZE = 16
    PADDING = '0'

    def __init__(self, mainPlaylist, streamPlaylist,
            streamBitrate=300000, title='', fragmentPrefix='fragment',
            newFragTolerance = 0, window=5, maxExtraBuffers=None,
            keyInterval=0, keysURI=None):
        '''
        @param mainPlaylist:    resource name of the main playlist
        @type  mainPlaylist:    str
        @param streamPlaylists: resource names of the playlists
        @type  streamPlaylist:  str
        @param streamBitrate:   Bitrate of the stream in bps
        @type  streamBitrate:   int
        @param title:           description of the stream
        @type  title:           str
        @param fragmentPrefix:  fragment name prefix
        @type  fragmentPrefix:  str
        @param newFragTolerance:Tolerance to automatically add new fragments.
        @type  newFragTolerance:float
        @param window:          maximum number of fragments to buffer
        @type  window:          int
        @param maxExtraBuffers: maximum number of extra fragments to buffer
        @type  maxExtraBuffers: int
        @param keyInterval:     number of fragments sharing the same encryption
                                key. O if not using encryption
        @type  keyInterval:     int
        @param keysURI          URI used to retrieve the encription keys
        @type  keysURI          str
        '''

        Playlister.__init__(self)
        self.mainPlaylist = mainPlaylist
        self.streamPlaylist = streamPlaylist
        self.streamBitrate = streamBitrate
        self.title = title
        self.fragmentPrefix = fragmentPrefix
        self.newFragmentTolerance = newFragTolerance
        self.window = window
        if maxExtraBuffers is None:
            self.maxBuffers = 2 * window +1
        else:
            self.maxBuffers = window + maxExtraBuffers
        self.keyInterval = keyInterval
        self.keysURI = keysURI or self._hostname
        self._encrypted = (keyInterval != 0)
        self._fragmentsDict = {}
        self._keysDict = {}
        self._secret = ''
        self._availableFragments = deque('')
        self._lastSequence = None

    def _encryptFragment(self, fragment, secret, IV):
        # FIXME: Not tested
        right_pad = lambda s: s + (self.BLOCK_SIZE -len(s) % self.BLOCK_SIZE)\
                * self.PADDING
        left_pad = lambda s: (self.BLOCK_SIZE -len(s) % self.BLOCK_SIZE)\
                * self.PADDING + s
        EncodeAES = lambda c, s: c.encrypt(right_pad(s))

        cipher = AES.new(secret, AES.MODE_CBC, left_pad(str(IV)))
        return EncodeAES(cipher, fragment)

    def reset(self):
        self._fragmentsDict = {}
        self._keysDict = {}
        self._secret = ''
        self._availableFragments = deque('')
        self._fragments = []
        self._dummyFragments = []
        self._lastSequence = None
        self._counter = 0

    def addFragment(self, fragment, sequenceNumber, duration):
        '''
        Adds a fragment to the ring and updates the playlist.
        If the ring is full, removes the oldest fragment.

        @param fragment:        mpegts raw fragment
        @type  fragment:        array
        @param sequenceNumber:  sequence number relative to the stream's start
        @type  sequenceNumber:  int
        @param duration:        duration of the the segment in seconds
        @type  duration:        int

        @return:                the name used in the playlist for the fragment
        @rtype :                str
        '''

        # We only care about the name used in the playlist, we let the
        # playlister name it using an appropiate extension
        fragmentName = self._addPlaylistFragment(sequenceNumber, duration,
                self._encrypted)
        # Don't add duplicated fragments
        if fragmentName in self._availableFragments:
            return
        self._lastSequence = sequenceNumber

        # If the ring is full, delete the oldest segment.
        while len(self._fragmentsDict) >= self.maxBuffers:
            pop = self._availableFragments.popleft()
            del self._fragmentsDict[pop]
            if pop in self._keysDict:
                del self._keysDict[pop]

        self._availableFragments.append(fragmentName)
        if self._encrypted:
            if sequenceNumber % self.keyInterval == 0:
                self._secret = os.urandom(self.BLOCK_SIZE)
            fragment = self._encryptFragment(fragment, self._secret,
                    sequenceNumber)
            self._keysDict[fragmentName] = self._secret
        self._fragmentsDict[fragmentName] = fragment
        return fragmentName

    def getFragment(self, fragmentName):
        '''
        Returns a fragment of the playlist or raises an Exception
        if the fragment is not found

        @param fragmentName:    name of the fragment to retrieve
        @type  fragmentName:    str

        @return:                an mpegts raw fragment
        @rtype:                 array
        '''

        if fragmentName in self._fragmentsDict:
            return self._fragmentsDict[fragmentName]
        if fragmentName in self._dummyFragments:
            raise FragmentNotAvailable()
        raise FragmentNotFound()

    def getEncryptionKey(self, key):
        '''
        Returns an encryption key from the keys dict or raises an
        Exception if the key is not found

        @param key:     name of the key to retrieve
        @type  key:     str

        @return:        the encryption key
        @rtype:         str
        '''

        if key in self._keysDict:
            return self._keysDict[key]
        raise KeyNotFound()
<commit_msg>Fix a typo left when refractoring _duration attribute<commit_after># -*- Mode: Python -*-
# vi:si:et:sw=4:sts=4:ts=4

# Flumotion - a streaming media server
# Copyright (C) 2004,2005,2006,2007,2008,2009 Fluendo, S.L.
# Copyright (C) 2010,2011 Flumotion Services, S.A.
# All rights reserved.
#
# This file may be distributed and/or modified under the terms of
# the GNU Lesser General Public License version 2.1 as published by
# the Free Software Foundation.
# This file is distributed without any warranty; without even the implied
# warranty of merchantability or fitness for a particular purpose.
# See "LICENSE.LGPL" in the source distribution for more information.
#
# Headers in this file shall remain intact.

import os
from collections import deque

from Crypto.Cipher import AES

from twisted.internet import reactor
from flumotion.component.common.streamer.fragmentedresource import\
    FragmentNotAvailable, FragmentNotFound, PlaylistNotFound, KeyNotFound

class Playlister:
    """
    I write HTTP Live Streaming playlists based on added fragments.
    """

    def __init__(self):
        self._hostname = ''
        self.mainPlaylist = ''
        self.streamPlaylist = ''
        self.streamBitrate = 0
        self.title = ''
        self.fragmentPrefix = ''
        self.newFragmentTolerance = 0
        self.window = 0
        self.keysURI = ''
        self.filenameExt = 'webm'
        #FIXME: Make it a property
        self.allowCache = True
        self._fragments = []
        self._dummyFragments = []
        self._counter = 0
        self._isAutoUpdate = False

    def setHostname(self, hostname):
        if hostname.startswith('/'):
            hostname = hostname[1:]
        if not hostname.endswith('/'):
            hostname = hostname + '/'
        if not hostname.startswith('http://'):
            hostname = 'http://' + hostname
        self._hostname = hostname

    def setAllowCache(self, allowed):
        self.allowCache = allowed

    def _getFragmentName(self, sequenceNumber):
        return '%s-%s.%s' % (self.fragmentPrefix, sequenceNumber,
                             self.filenameExt)

    def _getTargetDuration(self):
        sorted_list = sorted(self._fragments, key=lambda fragment: fragment[1])
        return int(sorted_list[0][1])

    def _autoUpdate(self, count):
        if self._counter == count:
            self._isAutoUpdate = True
            self._dummyFragments.append(self._getFragmentName(count))
            self._addPlaylistFragment(count, self._getTargetDuration(), False)

    def _addPlaylistFragment(self, sequenceNumber, duration, encrypted):
        # Add the fragment to the playlist if it wasn't added before
        if not sequenceNumber in [frag[0] for frag in self._fragments]:
            # Add a discontinuity if the sequenceNumber is not the expected
            self._fragments.append((sequenceNumber, duration, encrypted,
                sequenceNumber != self._counter and self._counter != 0))
            self._counter = sequenceNumber + 1
            # Remove fragments that are out of the window
            while len(self._fragments) > self.window:
                # If it's a dummy fragment, remove it from the list too
                fragName = self._getFragmentName(self._fragments[0][0])
                if fragName in self._dummyFragments:
                    self._dummyFragments.remove(fragName)
                del self._fragments[0]

        # Auto update the playlist when the next fragment was not added
        # If the fragment was automatically added update again after 'duration'
        if self.newFragmentTolerance != 0:
            reactor.callLater(self._isAutoUpdate and
                    duration or duration * (1 + self.newFragmentTolerance),
                    self._autoUpdate, self._counter)
        self._isAutoUpdate= False

        return self._getFragmentName(sequenceNumber)

    def renderArgs(self, args):
        if 'FLUREQID' in args:
            del args['FLUREQID']
        if len(args) == 0:
            return ''

        return '?' + '&'.join(["%s=%s" % (k, v[0]) for k, v in
                              args.iteritems()])

    def _renderMainPlaylist(self, args):
        lines = []

        lines.append("#EXTM3U")
        #The bandwith value is not significant for single bitrate
        lines.append("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=%s" %
                self.streamBitrate)
        lines.append("".join([self._hostname, self.streamPlaylist,
            self.renderArgs(args)]))
        lines.append("")

        return "\n".join(lines)

    def _renderStreamPlaylist(self, args):
        lines = []

        lines.append("#EXTM3U")
        lines.append("#EXT-X-ALLOW-CACHE:%s" %
                (self.allowCache and 'YES' or 'NO'))
        lines.append("#EXT-X-TARGETDURATION:%d" % self._getTargetDuration())
        lines.append("#EXT-X-MEDIA-SEQUENCE:%s" % self._fragments[0][0])

        for sequenceNumber, duration, encrypted, discon in self._fragments:
            if discon:
                lines.append("#EXT-X-DISCONTINUITY")
            # FIXME: Not fully implemented yet
            if encrypted:
                lines.append('#EXT-X-KEY:METHOD=AES-128,URI="%s?key=%s"' %
                        (self.keysURI, fragment))
            lines.append("#EXTINF:%d,%s" % (duration, self.title))
            lines.append(''.join([self._hostname,
                self._getFragmentName(sequenceNumber), self.renderArgs(args)]))

        lines.append("")

        return "\n".join(lines)

    def renderPlaylist(self, playlist, args):
        '''
        Returns a string representation of the requested playlist or raise
        an Exception if the playlist is not found
        '''
        if playlist == self.mainPlaylist:
            return self._renderMainPlaylist(args)
        elif playlist == self.streamPlaylist:
            return self._renderStreamPlaylist(args)
        raise PlaylistNotFound()

class HLSRing(Playlister):
    '''
    I hold a ring with the fragments available in the playlist
    and update the playlist according to this.
    '''

    BLOCK_SIZE = 16
    PADDING = '0'

    def __init__(self, mainPlaylist, streamPlaylist,
            streamBitrate=300000, title='', fragmentPrefix='fragment',
            newFragTolerance = 0, window=5, maxExtraBuffers=None,
            keyInterval=0, keysURI=None):
        '''
        @param mainPlaylist:    resource name of the main playlist
        @type  mainPlaylist:    str
        @param streamPlaylists: resource names of the playlists
        @type  streamPlaylist:  str
        @param streamBitrate:   Bitrate of the stream in bps
        @type  streamBitrate:   int
        @param title:           description of the stream
        @type  title:           str
        @param fragmentPrefix:  fragment name prefix
        @type  fragmentPrefix:  str
        @param newFragTolerance:Tolerance to automatically add new fragments.
        @type  newFragTolerance:float
        @param window:          maximum number of fragments to buffer
        @type  window:          int
        @param maxExtraBuffers: maximum number of extra fragments to buffer
        @type  maxExtraBuffers: int
        @param keyInterval:     number of fragments sharing the same encryption
                                key. O if not using encryption
        @type  keyInterval:     int
        @param keysURI          URI used to retrieve the encription keys
        @type  keysURI          str
        '''

        Playlister.__init__(self)
        self.mainPlaylist = mainPlaylist
        self.streamPlaylist = streamPlaylist
        self.streamBitrate = streamBitrate
        self.title = title
        self.fragmentPrefix = fragmentPrefix
        self.newFragmentTolerance = newFragTolerance
        self.window = window
        if maxExtraBuffers is None:
            self.maxBuffers = 2 * window +1
        else:
            self.maxBuffers = window + maxExtraBuffers
        self.keyInterval = keyInterval
        self.keysURI = keysURI or self._hostname
        self._encrypted = (keyInterval != 0)
        self._fragmentsDict = {}
        self._keysDict = {}
        self._secret = ''
        self._availableFragments = deque('')
        self._lastSequence = None

    def _encryptFragment(self, fragment, secret, IV):
        # FIXME: Not tested
        right_pad = lambda s: s + (self.BLOCK_SIZE -len(s) % self.BLOCK_SIZE)\
                * self.PADDING
        left_pad = lambda s: (self.BLOCK_SIZE -len(s) % self.BLOCK_SIZE)\
                * self.PADDING + s
        EncodeAES = lambda c, s: c.encrypt(right_pad(s))

        cipher = AES.new(secret, AES.MODE_CBC, left_pad(str(IV)))
        return EncodeAES(cipher, fragment)

    def reset(self):
        self._fragmentsDict = {}
        self._keysDict = {}
        self._secret = ''
        self._availableFragments = deque('')
        self._fragments = []
        self._dummyFragments = []
        self._lastSequence = None
        self._counter = 0

    def addFragment(self, fragment, sequenceNumber, duration):
        '''
        Adds a fragment to the ring and updates the playlist.
        If the ring is full, removes the oldest fragment.

        @param fragment:        mpegts raw fragment
        @type  fragment:        array
        @param sequenceNumber:  sequence number relative to the stream's start
        @type  sequenceNumber:  int
        @param duration:        duration of the the segment in seconds
        @type  duration:        int

        @return:                the name used in the playlist for the fragment
        @rtype :                str
        '''

        # We only care about the name used in the playlist, we let the
        # playlister name it using an appropiate extension
        fragmentName = self._addPlaylistFragment(sequenceNumber, duration,
                self._encrypted)
        # Don't add duplicated fragments
        if fragmentName in self._availableFragments:
            return
        self._lastSequence = sequenceNumber

        # If the ring is full, delete the oldest segment.
        while len(self._fragmentsDict) >= self.maxBuffers:
            pop = self._availableFragments.popleft()
            del self._fragmentsDict[pop]
            if pop in self._keysDict:
                del self._keysDict[pop]

        self._availableFragments.append(fragmentName)
        if self._encrypted:
            if sequenceNumber % self.keyInterval == 0:
                self._secret = os.urandom(self.BLOCK_SIZE)
            fragment = self._encryptFragment(fragment, self._secret,
                    sequenceNumber)
            self._keysDict[fragmentName] = self._secret
        self._fragmentsDict[fragmentName] = fragment
        return fragmentName

    def getFragment(self, fragmentName):
        '''
        Returns a fragment of the playlist or raises an Exception
        if the fragment is not found

        @param fragmentName:    name of the fragment to retrieve
        @type  fragmentName:    str

        @return:                an mpegts raw fragment
        @rtype:                 array
        '''

        if fragmentName in self._fragmentsDict:
            return self._fragmentsDict[fragmentName]
        if fragmentName in self._dummyFragments:
            raise FragmentNotAvailable()
        raise FragmentNotFound()

    def getEncryptionKey(self, key):
        '''
        Returns an encryption key from the keys dict or raises an
        Exception if the key is not found

        @param key:     name of the key to retrieve
        @type  key:     str

        @return:        the encryption key
        @rtype:         str
        '''

        if key in self._keysDict:
            return self._keysDict[key]
        raise KeyNotFound()
<|endoftext|>


<commit_before>""" Test functions for linalg module
"""

from numpy.testing import *
from numpy import array, single, double, csingle, cdouble, dot, identity
from numpy import multiply, atleast_2d, inf, asarray, matrix
from numpy import linalg
from numpy.linalg import matrix_power

def ifthen(a, b):
    return not a or b

old_assert_almost_equal = assert_almost_equal
def imply(a, b):
    return not a or b

def assert_almost_equal(a, b, **kw):
    if asarray(a).dtype.type in (single, csingle):
        decimal = 6
    else:
        decimal = 12
    old_assert_almost_equal(a, b, decimal=decimal, **kw)

class LinalgTestCase:
    def test_single(self):
        a = array([[1.,2.], [3.,4.]], dtype=single)
        b = array([2., 1.], dtype=single)
        self.do(a, b)

    def test_double(self):
        a = array([[1.,2.], [3.,4.]], dtype=double)
        b = array([2., 1.], dtype=double)
        self.do(a, b)

    def test_csingle(self):
        a = array([[1.+2j,2+3j], [3+4j,4+5j]], dtype=csingle)
        b = array([2.+1j, 1.+2j], dtype=csingle)
        self.do(a, b)

    def test_cdouble(self):
        a = array([[1.+2j,2+3j], [3+4j,4+5j]], dtype=cdouble)
        b = array([2.+1j, 1.+2j], dtype=cdouble)
        self.do(a, b)

    def test_empty(self):
        a = atleast_2d(array([], dtype = double))
        b = atleast_2d(array([], dtype = double))
        try:
            self.do(a, b)
            raise AssertionError("%s should fail with empty matrices", self.__name__[5:])
        except linalg.LinAlgError, e:
            pass

    def test_nonarray(self):
        a = [[1,2], [3,4]]
        b = [2, 1]
        self.do(a,b)

    def test_matrix_b_only(self):
        """Check that matrix type is preserved."""
        a = array([[1.,2.], [3.,4.]])
        b = matrix([2., 1.]).T
        self.do(a, b)

    def test_matrix_a_and_b(self):
        """Check that matrix type is preserved."""
        a = matrix([[1.,2.], [3.,4.]])
        b = matrix([2., 1.]).T
        self.do(a, b)

class TestSolve(LinalgTestCase, TestCase):
    def do(self, a, b):
        x = linalg.solve(a, b)
        assert_almost_equal(b, dot(a, x))
        assert imply(isinstance(b, matrix), isinstance(x, matrix))

class TestInv(LinalgTestCase, TestCase):
    def do(self, a, b):
        a_inv = linalg.inv(a)
        assert_almost_equal(dot(a, a_inv), identity(asarray(a).shape[0]))
        assert imply(isinstance(a, matrix), isinstance(a_inv, matrix))

class TestEigvals(LinalgTestCase, TestCase):
    def do(self, a, b):
        ev = linalg.eigvals(a)
        evalues, evectors = linalg.eig(a)
        assert_almost_equal(ev, evalues)

class TestEig(LinalgTestCase, TestCase):
    def do(self, a, b):
        evalues, evectors = linalg.eig(a)
        assert_almost_equal(dot(a, evectors), multiply(evectors, evalues))
        assert imply(isinstance(a, matrix), isinstance(evectors, matrix))

class TestSVD(LinalgTestCase, TestCase):
    def do(self, a, b):
        u, s, vt = linalg.svd(a, 0)
        assert_almost_equal(a, dot(multiply(u, s), vt))
        assert imply(isinstance(a, matrix), isinstance(u, matrix))
        assert imply(isinstance(a, matrix), isinstance(vt, matrix))

class TestCondSVD(LinalgTestCase, TestCase):
    def do(self, a, b):
        c = asarray(a) # a might be a matrix
        s = linalg.svd(c, compute_uv=False)
        old_assert_almost_equal(s[0]/s[-1], linalg.cond(a), decimal=5)

class TestCond2(LinalgTestCase, TestCase):
    def do(self, a, b):
        c = asarray(a) # a might be a matrix
        s = linalg.svd(c, compute_uv=False)
        old_assert_almost_equal(s[0]/s[-1], linalg.cond(a,2), decimal=5)

class TestCondInf(TestCase):
    def test(self):
        A = array([[1.,0,0],[0,-2.,0],[0,0,3.]])
        assert_almost_equal(linalg.cond(A,inf),3.)

class TestPinv(LinalgTestCase, TestCase):
    def do(self, a, b):
        a_ginv = linalg.pinv(a)
        assert_almost_equal(dot(a, a_ginv), identity(asarray(a).shape[0]))
        assert imply(isinstance(a, matrix), isinstance(a_ginv, matrix))

class TestDet(LinalgTestCase, TestCase):
    def do(self, a, b):
        d = linalg.det(a)
        if asarray(a).dtype.type in (single, double):
            ad = asarray(a).astype(double)
        else:
            ad = asarray(a).astype(cdouble)
        ev = linalg.eigvals(ad)
        assert_almost_equal(d, multiply.reduce(ev))

class TestLstsq(LinalgTestCase, TestCase):
    def do(self, a, b):
        u, s, vt = linalg.svd(a, 0)
        x, residuals, rank, sv = linalg.lstsq(a, b)
        assert_almost_equal(b, dot(a, x))
        assert_equal(rank, asarray(a).shape[0])
        assert_almost_equal(sv, sv.__array_wrap__(s))
        assert imply(isinstance(b, matrix), isinstance(x, matrix))
        assert imply(isinstance(b, matrix), isinstance(residuals, matrix))

class TestMatrixPower(TestCase):
    R90 = array([[0,1],[-1,0]])
    Arb22 = array([[4,-7],[-2,10]])
    noninv = array([[1,0],[0,0]])
    arbfloat = array([[0.1,3.2],[1.2,0.7]])

    large = identity(10)
    t = large[1,:].copy()
    large[1,:] = large[0,:]
    large[0,:] = t

    def test_large_power(self):
        assert_equal(matrix_power(self.R90,2L**100+2**10+2**5+1),self.R90)

    def test_large_power_trailing_zero(self):
        assert_equal(matrix_power(self.R90,2L**100+2**10+2**5),identity(2))

    def testip_zero(self):
        def tz(M):
            mz = matrix_power(M,0)
            assert_equal(mz, identity(M.shape[0]))
            assert_equal(mz.dtype, M.dtype)
        for M in [self.Arb22, self.arbfloat, self.large]:
            yield tz, M

    def testip_one(self):
        def tz(M):
            mz = matrix_power(M,1)
            assert_equal(mz, M)
            assert_equal(mz.dtype, M.dtype)
        for M in [self.Arb22, self.arbfloat, self.large]:
            yield tz, M

    def testip_two(self):
        def tz(M):
            mz = matrix_power(M,2)
            assert_equal(mz, dot(M,M))
            assert_equal(mz.dtype, M.dtype)
        for M in [self.Arb22, self.arbfloat, self.large]:
            yield tz, M

    def testip_invert(self):
        def tz(M):
            mz = matrix_power(M,-1)
            assert_almost_equal(identity(M.shape[0]), dot(mz,M))
        for M in [self.R90, self.Arb22, self.arbfloat, self.large]:
            yield tz, M

    def test_invert_noninvertible(self):
        import numpy.linalg
        self.assertRaises(numpy.linalg.linalg.LinAlgError,
                lambda: matrix_power(self.noninv,-1))

class TestBoolPower(TestCase):
    def test_square(self):
        A = array([[True,False],[True,True]])
        assert_equal(matrix_power(A,2),A)

class HermitianTestCase(object):
    def test_single(self):
        a = array([[1.,2.], [2.,1.]], dtype=single)
        self.do(a)

    def test_double(self):
        a = array([[1.,2.], [2.,1.]], dtype=double)
        self.do(a)

    def test_csingle(self):
        a = array([[1.,2+3j], [2-3j,1]], dtype=csingle)
        self.do(a)

    def test_cdouble(self):
        a = array([[1.,2+3j], [2-3j,1]], dtype=cdouble)
        self.do(a)

    def test_empty(self):
        a = atleast_2d(array([], dtype = double))
        assert_raises(linalg.LinAlgError, self.do, a)

    def test_nonarray(self):
        a = [[1,2], [2,1]]
        self.do(a)

    def test_matrix_b_only(self):
        """Check that matrix type is preserved."""
        a = array([[1.,2.], [2.,1.]])
        self.do(a)

    def test_matrix_a_and_b(self):
        """Check that matrix type is preserved."""
        a = matrix([[1.,2.], [2.,1.]])
        self.do(a)

class TestEigvalsh(HermitianTestCase, TestCase):
    def do(self, a):
        ev = linalg.eigvalsh(a)
        # flip resulting eigenvalue array, since they are returned in
        # reverse order from the values given by linal.eig
        ev = ev[::-1]

        evalues, evectors = linalg.eig(a)
        assert_almost_equal(ev, evalues)

class TestEigh(HermitianTestCase, TestCase):
    def do(self, a):
        ev, evc = linalg.eigh(a)
        # flip resulting eigenvalue array, since they are returned in
        # reverse order from the values given by linal.eig
        ev = ev[::-1]

        evalues, evectors = linalg.eig(a)
        assert_almost_equal(ev, evalues)

if __name__ == "__main__":
    run_module_suite()
<commit_msg>TEST: add tests for norm from #763.<commit_after>""" Test functions for linalg module
"""

from numpy.testing import *
from numpy import array, single, double, csingle, cdouble, dot, identity
from numpy import multiply, atleast_2d, inf, asarray, matrix
from numpy import linalg
from numpy.linalg import matrix_power, norm

def ifthen(a, b):
    return not a or b

old_assert_almost_equal = assert_almost_equal
def imply(a, b):
    return not a or b

def assert_almost_equal(a, b, **kw):
    if asarray(a).dtype.type in (single, csingle):
        decimal = 6
    else:
        decimal = 12
    old_assert_almost_equal(a, b, decimal=decimal, **kw)

class LinalgTestCase:
    def test_single(self):
        a = array([[1.,2.], [3.,4.]], dtype=single)
        b = array([2., 1.], dtype=single)
        self.do(a, b)

    def test_double(self):
        a = array([[1.,2.], [3.,4.]], dtype=double)
        b = array([2., 1.], dtype=double)
        self.do(a, b)

    def test_csingle(self):
        a = array([[1.+2j,2+3j], [3+4j,4+5j]], dtype=csingle)
        b = array([2.+1j, 1.+2j], dtype=csingle)
        self.do(a, b)

    def test_cdouble(self):
        a = array([[1.+2j,2+3j], [3+4j,4+5j]], dtype=cdouble)
        b = array([2.+1j, 1.+2j], dtype=cdouble)
        self.do(a, b)

    def test_empty(self):
        a = atleast_2d(array([], dtype = double))
        b = atleast_2d(array([], dtype = double))
        try:
            self.do(a, b)
            raise AssertionError("%s should fail with empty matrices", self.__name__[5:])
        except linalg.LinAlgError, e:
            pass

    def test_nonarray(self):
        a = [[1,2], [3,4]]
        b = [2, 1]
        self.do(a,b)

    def test_matrix_b_only(self):
        """Check that matrix type is preserved."""
        a = array([[1.,2.], [3.,4.]])
        b = matrix([2., 1.]).T
        self.do(a, b)

    def test_matrix_a_and_b(self):
        """Check that matrix type is preserved."""
        a = matrix([[1.,2.], [3.,4.]])
        b = matrix([2., 1.]).T
        self.do(a, b)

class TestSolve(LinalgTestCase, TestCase):
    def do(self, a, b):
        x = linalg.solve(a, b)
        assert_almost_equal(b, dot(a, x))
        assert imply(isinstance(b, matrix), isinstance(x, matrix))

class TestInv(LinalgTestCase, TestCase):
    def do(self, a, b):
        a_inv = linalg.inv(a)
        assert_almost_equal(dot(a, a_inv), identity(asarray(a).shape[0]))
        assert imply(isinstance(a, matrix), isinstance(a_inv, matrix))

class TestEigvals(LinalgTestCase, TestCase):
    def do(self, a, b):
        ev = linalg.eigvals(a)
        evalues, evectors = linalg.eig(a)
        assert_almost_equal(ev, evalues)

class TestEig(LinalgTestCase, TestCase):
    def do(self, a, b):
        evalues, evectors = linalg.eig(a)
        assert_almost_equal(dot(a, evectors), multiply(evectors, evalues))
        assert imply(isinstance(a, matrix), isinstance(evectors, matrix))

class TestSVD(LinalgTestCase, TestCase):
    def do(self, a, b):
        u, s, vt = linalg.svd(a, 0)
        assert_almost_equal(a, dot(multiply(u, s), vt))
        assert imply(isinstance(a, matrix), isinstance(u, matrix))
        assert imply(isinstance(a, matrix), isinstance(vt, matrix))

class TestCondSVD(LinalgTestCase, TestCase):
    def do(self, a, b):
        c = asarray(a) # a might be a matrix
        s = linalg.svd(c, compute_uv=False)
        old_assert_almost_equal(s[0]/s[-1], linalg.cond(a), decimal=5)

class TestCond2(LinalgTestCase, TestCase):
    def do(self, a, b):
        c = asarray(a) # a might be a matrix
        s = linalg.svd(c, compute_uv=False)
        old_assert_almost_equal(s[0]/s[-1], linalg.cond(a,2), decimal=5)

class TestCondInf(TestCase):
    def test(self):
        A = array([[1.,0,0],[0,-2.,0],[0,0,3.]])
        assert_almost_equal(linalg.cond(A,inf),3.)

class TestPinv(LinalgTestCase, TestCase):
    def do(self, a, b):
        a_ginv = linalg.pinv(a)
        assert_almost_equal(dot(a, a_ginv), identity(asarray(a).shape[0]))
        assert imply(isinstance(a, matrix), isinstance(a_ginv, matrix))

class TestDet(LinalgTestCase, TestCase):
    def do(self, a, b):
        d = linalg.det(a)
        if asarray(a).dtype.type in (single, double):
            ad = asarray(a).astype(double)
        else:
            ad = asarray(a).astype(cdouble)
        ev = linalg.eigvals(ad)
        assert_almost_equal(d, multiply.reduce(ev))

class TestLstsq(LinalgTestCase, TestCase):
    def do(self, a, b):
        u, s, vt = linalg.svd(a, 0)
        x, residuals, rank, sv = linalg.lstsq(a, b)
        assert_almost_equal(b, dot(a, x))
        assert_equal(rank, asarray(a).shape[0])
        assert_almost_equal(sv, sv.__array_wrap__(s))
        assert imply(isinstance(b, matrix), isinstance(x, matrix))
        assert imply(isinstance(b, matrix), isinstance(residuals, matrix))

class TestMatrixPower(TestCase):
    R90 = array([[0,1],[-1,0]])
    Arb22 = array([[4,-7],[-2,10]])
    noninv = array([[1,0],[0,0]])
    arbfloat = array([[0.1,3.2],[1.2,0.7]])

    large = identity(10)
    t = large[1,:].copy()
    large[1,:] = large[0,:]
    large[0,:] = t

    def test_large_power(self):
        assert_equal(matrix_power(self.R90,2L**100+2**10+2**5+1),self.R90)

    def test_large_power_trailing_zero(self):
        assert_equal(matrix_power(self.R90,2L**100+2**10+2**5),identity(2))

    def testip_zero(self):
        def tz(M):
            mz = matrix_power(M,0)
            assert_equal(mz, identity(M.shape[0]))
            assert_equal(mz.dtype, M.dtype)
        for M in [self.Arb22, self.arbfloat, self.large]:
            yield tz, M

    def testip_one(self):
        def tz(M):
            mz = matrix_power(M,1)
            assert_equal(mz, M)
            assert_equal(mz.dtype, M.dtype)
        for M in [self.Arb22, self.arbfloat, self.large]:
            yield tz, M

    def testip_two(self):
        def tz(M):
            mz = matrix_power(M,2)
            assert_equal(mz, dot(M,M))
            assert_equal(mz.dtype, M.dtype)
        for M in [self.Arb22, self.arbfloat, self.large]:
            yield tz, M

    def testip_invert(self):
        def tz(M):
            mz = matrix_power(M,-1)
            assert_almost_equal(identity(M.shape[0]), dot(mz,M))
        for M in [self.R90, self.Arb22, self.arbfloat, self.large]:
            yield tz, M

    def test_invert_noninvertible(self):
        import numpy.linalg
        self.assertRaises(numpy.linalg.linalg.LinAlgError,
                lambda: matrix_power(self.noninv,-1))

class TestBoolPower(TestCase):
    def test_square(self):
        A = array([[True,False],[True,True]])
        assert_equal(matrix_power(A,2),A)

class HermitianTestCase(object):
    def test_single(self):
        a = array([[1.,2.], [2.,1.]], dtype=single)
        self.do(a)

    def test_double(self):
        a = array([[1.,2.], [2.,1.]], dtype=double)
        self.do(a)

    def test_csingle(self):
        a = array([[1.,2+3j], [2-3j,1]], dtype=csingle)
        self.do(a)

    def test_cdouble(self):
        a = array([[1.,2+3j], [2-3j,1]], dtype=cdouble)
        self.do(a)

    def test_empty(self):
        a = atleast_2d(array([], dtype = double))
        assert_raises(linalg.LinAlgError, self.do, a)

    def test_nonarray(self):
        a = [[1,2], [2,1]]
        self.do(a)

    def test_matrix_b_only(self):
        """Check that matrix type is preserved."""
        a = array([[1.,2.], [2.,1.]])
        self.do(a)

    def test_matrix_a_and_b(self):
        """Check that matrix type is preserved."""
        a = matrix([[1.,2.], [2.,1.]])
        self.do(a)

class TestEigvalsh(HermitianTestCase, TestCase):
    def do(self, a):
        ev = linalg.eigvalsh(a)
        # flip resulting eigenvalue array, since they are returned in
        # reverse order from the values given by linal.eig
        ev = ev[::-1]

        evalues, evectors = linalg.eig(a)
        assert_almost_equal(ev, evalues)

class TestEigh(HermitianTestCase, TestCase):
    def do(self, a):
        ev, evc = linalg.eigh(a)
        # flip resulting eigenvalue array, since they are returned in
        # reverse order from the values given by linal.eig
        ev = ev[::-1]

        evalues, evectors = linalg.eig(a)
        assert_almost_equal(ev, evalues)

class TestNorm(TestCase):
    def check_empty(self):
        assert_equal(norm([]), 0.0)
        assert_equal(norm(array([], dtype = double)), 0.0)
        assert_equal(norm(atleast_2d(array([], dtype = double))), 0.0)

    def test_vector(self):
        a = [1.0,2.0,3.0,4.0]
        b = [-1.0,-2.0,-3.0,-4.0]
        c = [-1.0, 2.0,-3.0, 4.0]
        for v in (a,array(a),b,array(b),c,array(c)):
            assert_almost_equal(norm(v), 30**0.5)
            assert_almost_equal(norm(v,inf), 4.0)
            assert_almost_equal(norm(v,-inf), 1.0)
            assert_almost_equal(norm(v,1), 10.0)
            assert_almost_equal(norm(v,-1), 12.0/25)
            assert_almost_equal(norm(v,2), 30**0.5)
            assert_almost_equal(norm(v,-2), (205./144)**-0.5)

    @dec.knownfailureif(True, "#786: FIXME")
    def test_vector_badarg(self):
        """Regression for #786: Froebenius norm for vectors raises
        TypeError."""
        self.assertRaises(ValueError, norm, array([1., 2., 3.]), 'fro')

    def test_matrix(self):
        A = matrix([[1.,3.],[5.,7.]], dtype=single)
        A = matrix([[1.,3.],[5.,7.]], dtype=single)
        assert_almost_equal(norm(A), 84**0.5)
        assert_almost_equal(norm(A,'fro'), 84**0.5)
        assert_almost_equal(norm(A,inf), 12.0)
        assert_almost_equal(norm(A,-inf), 4.0)
        assert_almost_equal(norm(A,1), 10.0)
        assert_almost_equal(norm(A,-1), 6.0)
        assert_almost_equal(norm(A,2), 9.12310563)
        assert_almost_equal(norm(A,-2), 0.87689437)

        self.assertRaises(ValueError, norm, A, 'nofro')
        self.assertRaises(ValueError, norm, A, -3)

if __name__ == "__main__":
    run_module_suite()
<|endoftext|>


<commit_before>from __future__ import absolute_import

import urwid
import urwid.util
import os

from netlib.http import CONTENT_MISSING
import netlib.utils

from .. import utils
from ..models import decoded
from . import signals

try:
    import pyperclip
except:
    pyperclip = False

VIEW_FLOW_REQUEST = 0
VIEW_FLOW_RESPONSE = 1

METHOD_OPTIONS = [
    ("get", "g"),
    ("post", "p"),
    ("put", "u"),
    ("head", "h"),
    ("trace", "t"),
    ("delete", "d"),
    ("options", "o"),
    ("edit raw", "e"),
]

def is_keypress(k):
    """
        Is this input event a keypress?
    """
    if isinstance(k, basestring):
        return True

def highlight_key(str, key, textattr="text", keyattr="key"):
    l = []
    parts = str.split(key, 1)
    if parts[0]:
        l.append((textattr, parts[0]))
    l.append((keyattr, key))
    if parts[1]:
        l.append((textattr, parts[1]))
    return l

KEY_MAX = 30

def format_keyvals(lst, key="key", val="text", indent=0):
    """
        Format a list of (key, value) tuples.

        If key is None, it's treated specially:
            - We assume a sub-value, and add an extra indent.
            - The value is treated as a pre-formatted list of directives.
    """
    ret = []
    if lst:
        maxk = min(max(len(i[0]) for i in lst if i and i[0]), KEY_MAX)
        for i, kv in enumerate(lst):
            if kv is None:
                ret.append(urwid.Text(""))
            else:
                if isinstance(kv[1], urwid.Widget):
                    v = kv[1]
                elif kv[1] is None:
                    v = urwid.Text("")
                else:
                    v = urwid.Text([(val, kv[1])])
                ret.append(
                    urwid.Columns(
                        [
                            ("fixed", indent, urwid.Text("")),
                            (
                                "fixed",
                                maxk,
                                urwid.Text([(key, kv[0] or "")])
                            ),
                            v
                        ],
                        dividechars = 2
                    )
                )
    return ret

def shortcuts(k):
    if k == " ":
        k = "page down"
    elif k == "ctrl f":
        k = "page down"
    elif k == "ctrl b":
        k = "page up"
    elif k == "j":
        k = "down"
    elif k == "k":
        k = "up"
    return k

def fcol(s, attr):
    s = unicode(s)
    return (
        "fixed",
        len(s),
        urwid.Text(
            [
                (attr, s)
            ]
        )
    )

if urwid.util.detected_encoding:
    SYMBOL_REPLAY = u"\u21ba"
    SYMBOL_RETURN = u"\u2190"
    SYMBOL_MARK = u"\u25cf"
else:
    SYMBOL_REPLAY = u"[r]"
    SYMBOL_RETURN = u"<-"
    SYMBOL_MARK = "[m]"

def raw_format_flow(f, focus, extended, padding):
    f = dict(f)
    pile = []
    req = []
    if extended:
        req.append(
            fcol(
                utils.format_timestamp(f["req_timestamp"]),
                "highlight"
            )
        )
    else:
        req.append(fcol(">>" if focus else "  ", "focus"))

    if f["marked"]:
        req.append(fcol(SYMBOL_MARK, "mark"))

    if f["req_is_replay"]:
        req.append(fcol(SYMBOL_REPLAY, "replay"))
    req.append(fcol(f["req_method"], "method"))

    preamble = sum(i[1] for i in req) + len(req) - 1

    if f["intercepted"] and not f["acked"]:
        uc = "intercept"
    elif f["resp_code"] or f["err_msg"]:
        uc = "text"
    else:
        uc = "title"

    req.append(
        urwid.Text([(uc, f["req_url"])])
    )

    pile.append(urwid.Columns(req, dividechars=1))

    resp = []
    resp.append(
        ("fixed", preamble, urwid.Text(""))
    )

    if f["resp_code"]:
        codes = {
            2: "code_200",
            3: "code_300",
            4: "code_400",
            5: "code_500",
        }
        ccol = codes.get(f["resp_code"] / 100, "code_other")
        resp.append(fcol(SYMBOL_RETURN, ccol))
        if f["resp_is_replay"]:
            resp.append(fcol(SYMBOL_REPLAY, "replay"))
        resp.append(fcol(f["resp_code"], ccol))
        if f["intercepted"] and f["resp_code"] and not f["acked"]:
            rc = "intercept"
        else:
            rc = "text"

        if f["resp_ctype"]:
            resp.append(fcol(f["resp_ctype"], rc))
        resp.append(fcol(f["resp_clen"], rc))
        resp.append(fcol(f["roundtrip"], rc))

    elif f["err_msg"]:
        resp.append(fcol(SYMBOL_RETURN, "error"))
        resp.append(
            urwid.Text([
                (
                    "error",
                    f["err_msg"]
                )
            ])
        )
    pile.append(urwid.Columns(resp, dividechars=1))
    return urwid.Pile(pile)

# Save file to disk
def save_data(path, data):
    if not path:
        return
    try:
        with file(path, "wb") as f:
            f.write(data)
    except IOError as v:
        signals.status_message.send(message=v.strerror)

def ask_save_overwrite(path, data):
    if not path:
        return
    path = os.path.expanduser(path)
    if os.path.exists(path):
        def save_overwrite(k):
            if k == "y":
                save_data(path, data)

        signals.status_prompt_onekey.send(
            prompt = "'" + path + "' already exists. Overwrite?",
            keys = (
                ("yes", "y"),
                ("no", "n"),
            ),
            callback = save_overwrite
        )
    else:
        save_data(path, data)

def ask_save_path(prompt, data):
    signals.status_prompt_path.send(
        prompt = prompt,
        callback = ask_save_overwrite,
        args = (data)
    )

def copy_flow_format_data(part, scope, flow):
    if part == "u":
        data = flow.request.url
    else:
        data = ""
        if scope in ("q", "a"):
            if flow.request.content is None or flow.request.content == CONTENT_MISSING:
                return None, "Request content is missing"
            with decoded(flow.request):
                if part == "h":
                    data += netlib.http.http1.assemble_request(flow.request)
                elif part == "c":
                    data += flow.request.content
                else:
                    raise ValueError("Unknown part: {}".format(part))
        if scope == "a" and flow.request.content and flow.response:
            # Add padding between request and response
            data += "\r\n" * 2
        if scope in ("s", "a") and flow.response:
            if flow.response.content is None or flow.response.content == CONTENT_MISSING:
                return None, "Response content is missing"
            with decoded(flow.response):
                if part == "h":
                    data += netlib.http.http1.assemble_response(flow.response)
                elif part == "c":
                    data += flow.response.content
                else:
                    raise ValueError("Unknown part: {}".format(part))
    return data, False

def copy_as_curl_command(flow):

    if flow.request.content is None or flow.request.content == CONTENT_MISSING:
        return None, "Request content is missing"

    headerString = ""
    for k,v in flow.request.headers:
      headerString += " -H '" + k + ":" + v + "' "

    data = "curl"

    if flow.request.method != "GET":
      data += " -X " + flow.request.method

    full_url = flow.request.scheme + "://" + flow.request.host + flow.request.path
    data += " " + headerString + "'" + full_url + "'"

    if flow.request.content != None and flow.request.content != "":
      data += " --data-binary " + "'" + flow.request.content + "'"

    copy_to_clipboard_or_prompt(data)

def copy_to_clipboard_or_prompt(data):
    # pyperclip calls encode('utf-8') on data to be copied without checking.
    # if data are already encoded that way UnicodeDecodeError is thrown.
    toclip = ""
    try:
        toclip = data.decode('utf-8')
    except (UnicodeDecodeError):
        toclip = data

    try:
        pyperclip.copy(toclip)
    except (RuntimeError, UnicodeDecodeError, AttributeError):
        def save(k):
            if k == "y":
                ask_save_path("Save data", data)
        signals.status_prompt_onekey.send(
            prompt = "Cannot copy data to clipboard. Save as file?",
            keys = (
                ("yes", "y"),
                ("no", "n"),
            ),
            callback = save
        )

def copy_flow(part, scope, flow, master, state):
    """
    part: _c_ontent, _h_eaders+content, _u_rl
    scope: _a_ll, re_q_uest, re_s_ponse
    """
    data, err = copy_flow_format_data(part, scope, flow)

    if err:
        signals.status_message.send(message=err)
        return

    if not data:
        if scope == "q":
            signals.status_message.send(message="No request content to copy.")
        elif scope == "s":
            signals.status_message.send(message="No response content to copy.")
        else:
            signals.status_message.send(message="No contents to copy.")
        return

    copy_to_clipboard_or_prompt(data)

def ask_copy_part(scope, flow, master, state):
    choices = [
        ("content", "c"),
        ("headers+content", "h")
    ]
    if scope != "s":
        choices.append(("url", "u"))

    signals.status_prompt_onekey.send(
        prompt = "Copy",
        keys = choices,
        callback = copy_flow,
        args = (scope, flow, master, state)
    )

def ask_save_body(part, master, state, flow):
    """
    Save either the request or the response body to disk. part can either be
    "q" (request), "s" (response) or None (ask user if necessary).
    """

    request_has_content = flow.request and flow.request.content
    response_has_content = flow.response and flow.response.content

    if part is None:
        # We first need to determine whether we want to save the request or the
        # response content.
        if request_has_content and response_has_content:
            signals.status_prompt_onekey.send(
                prompt = "Save",
                keys = (
                    ("request", "q"),
                    ("response", "s"),
                ),
                callback = ask_save_body,
                args = (master, state, flow)
            )
        elif response_has_content:
            ask_save_body("s", master, state, flow)
        else:
            ask_save_body("q", master, state, flow)

    elif part == "q" and request_has_content:
        ask_save_path(
            "Save request content",
            flow.request.get_decoded_content()
        )
    elif part == "s" and response_has_content:
        ask_save_path(
            "Save response content",
            flow.response.get_decoded_content()
        )
    else:
        signals.status_message.send(message="No content to save.")

flowcache = utils.LRUCache(800)

def format_flow(f, focus, extended=False, hostheader=False, padding=2,
        marked=False):
    d = dict(
        intercepted = f.intercepted,
        acked = f.reply.acked,

        req_timestamp = f.request.timestamp_start,
        req_is_replay = f.request.is_replay,
        req_method = f.request.method,
        req_url = f.request.pretty_url if hostheader else f.request.url,

        err_msg = f.error.msg if f.error else None,
        resp_code = f.response.status_code if f.response else None,

        marked = marked,
    )
    if f.response:
        if f.response.content:
            contentdesc = netlib.utils.pretty_size(len(f.response.content))
        elif f.response.content == CONTENT_MISSING:
            contentdesc = "[content missing]"
        else:
            contentdesc = "[no content]"
        duration = 0
        if f.response.timestamp_end and f.request.timestamp_start:
            duration = f.response.timestamp_end - f.request.timestamp_start
        roundtrip = utils.pretty_duration(duration)

        d.update(dict(
            resp_code = f.response.status_code,
            resp_is_replay = f.response.is_replay,
            resp_clen = contentdesc,
            roundtrip = roundtrip,
        ))
        t = f.response.headers.get("content-type")
        if t:
            d["resp_ctype"] = t.split(";")[0]
        else:
            d["resp_ctype"] = ""
    return flowcache.get(
        raw_format_flow,
        tuple(sorted(d.items())), focus, extended, padding
    )
<commit_msg>fixed TypeError: ask_save_overwrite() takes exactly 2 arguments (xxxxx given)<commit_after>from __future__ import absolute_import

import urwid
import urwid.util
import os

from netlib.http import CONTENT_MISSING
import netlib.utils

from .. import utils
from ..models import decoded
from . import signals

try:
    import pyperclip
except:
    pyperclip = False

VIEW_FLOW_REQUEST = 0
VIEW_FLOW_RESPONSE = 1

METHOD_OPTIONS = [
    ("get", "g"),
    ("post", "p"),
    ("put", "u"),
    ("head", "h"),
    ("trace", "t"),
    ("delete", "d"),
    ("options", "o"),
    ("edit raw", "e"),
]

def is_keypress(k):
    """
        Is this input event a keypress?
    """
    if isinstance(k, basestring):
        return True

def highlight_key(str, key, textattr="text", keyattr="key"):
    l = []
    parts = str.split(key, 1)
    if parts[0]:
        l.append((textattr, parts[0]))
    l.append((keyattr, key))
    if parts[1]:
        l.append((textattr, parts[1]))
    return l

KEY_MAX = 30

def format_keyvals(lst, key="key", val="text", indent=0):
    """
        Format a list of (key, value) tuples.

        If key is None, it's treated specially:
            - We assume a sub-value, and add an extra indent.
            - The value is treated as a pre-formatted list of directives.
    """
    ret = []
    if lst:
        maxk = min(max(len(i[0]) for i in lst if i and i[0]), KEY_MAX)
        for i, kv in enumerate(lst):
            if kv is None:
                ret.append(urwid.Text(""))
            else:
                if isinstance(kv[1], urwid.Widget):
                    v = kv[1]
                elif kv[1] is None:
                    v = urwid.Text("")
                else:
                    v = urwid.Text([(val, kv[1])])
                ret.append(
                    urwid.Columns(
                        [
                            ("fixed", indent, urwid.Text("")),
                            (
                                "fixed",
                                maxk,
                                urwid.Text([(key, kv[0] or "")])
                            ),
                            v
                        ],
                        dividechars = 2
                    )
                )
    return ret

def shortcuts(k):
    if k == " ":
        k = "page down"
    elif k == "ctrl f":
        k = "page down"
    elif k == "ctrl b":
        k = "page up"
    elif k == "j":
        k = "down"
    elif k == "k":
        k = "up"
    return k

def fcol(s, attr):
    s = unicode(s)
    return (
        "fixed",
        len(s),
        urwid.Text(
            [
                (attr, s)
            ]
        )
    )

if urwid.util.detected_encoding:
    SYMBOL_REPLAY = u"\u21ba"
    SYMBOL_RETURN = u"\u2190"
    SYMBOL_MARK = u"\u25cf"
else:
    SYMBOL_REPLAY = u"[r]"
    SYMBOL_RETURN = u"<-"
    SYMBOL_MARK = "[m]"

def raw_format_flow(f, focus, extended, padding):
    f = dict(f)
    pile = []
    req = []
    if extended:
        req.append(
            fcol(
                utils.format_timestamp(f["req_timestamp"]),
                "highlight"
            )
        )
    else:
        req.append(fcol(">>" if focus else "  ", "focus"))

    if f["marked"]:
        req.append(fcol(SYMBOL_MARK, "mark"))

    if f["req_is_replay"]:
        req.append(fcol(SYMBOL_REPLAY, "replay"))
    req.append(fcol(f["req_method"], "method"))

    preamble = sum(i[1] for i in req) + len(req) - 1

    if f["intercepted"] and not f["acked"]:
        uc = "intercept"
    elif f["resp_code"] or f["err_msg"]:
        uc = "text"
    else:
        uc = "title"

    req.append(
        urwid.Text([(uc, f["req_url"])])
    )

    pile.append(urwid.Columns(req, dividechars=1))

    resp = []
    resp.append(
        ("fixed", preamble, urwid.Text(""))
    )

    if f["resp_code"]:
        codes = {
            2: "code_200",
            3: "code_300",
            4: "code_400",
            5: "code_500",
        }
        ccol = codes.get(f["resp_code"] / 100, "code_other")
        resp.append(fcol(SYMBOL_RETURN, ccol))
        if f["resp_is_replay"]:
            resp.append(fcol(SYMBOL_REPLAY, "replay"))
        resp.append(fcol(f["resp_code"], ccol))
        if f["intercepted"] and f["resp_code"] and not f["acked"]:
            rc = "intercept"
        else:
            rc = "text"

        if f["resp_ctype"]:
            resp.append(fcol(f["resp_ctype"], rc))
        resp.append(fcol(f["resp_clen"], rc))
        resp.append(fcol(f["roundtrip"], rc))

    elif f["err_msg"]:
        resp.append(fcol(SYMBOL_RETURN, "error"))
        resp.append(
            urwid.Text([
                (
                    "error",
                    f["err_msg"]
                )
            ])
        )
    pile.append(urwid.Columns(resp, dividechars=1))
    return urwid.Pile(pile)

# Save file to disk
def save_data(path, data):
    if not path:
        return
    try:
        with file(path, "wb") as f:
            f.write(data)
    except IOError as v:
        signals.status_message.send(message=v.strerror)

def ask_save_overwrite(path, data):
    if not path:
        return
    path = os.path.expanduser(path)
    if os.path.exists(path):
        def save_overwrite(k):
            if k == "y":
                save_data(path, data)

        signals.status_prompt_onekey.send(
            prompt = "'" + path + "' already exists. Overwrite?",
            keys = (
                ("yes", "y"),
                ("no", "n"),
            ),
            callback = save_overwrite
        )
    else:
        save_data(path, data)

def ask_save_path(prompt, data):
    signals.status_prompt_path.send(
        prompt = prompt,
        callback = ask_save_overwrite,
        args =  (data, )
    )

def copy_flow_format_data(part, scope, flow):
    if part == "u":
        data = flow.request.url
    else:
        data = ""
        if scope in ("q", "a"):
            if flow.request.content is None or flow.request.content == CONTENT_MISSING:
                return None, "Request content is missing"
            with decoded(flow.request):
                if part == "h":
                    data += netlib.http.http1.assemble_request(flow.request)
                elif part == "c":
                    data += flow.request.content
                else:
                    raise ValueError("Unknown part: {}".format(part))
        if scope == "a" and flow.request.content and flow.response:
            # Add padding between request and response
            data += "\r\n" * 2
        if scope in ("s", "a") and flow.response:
            if flow.response.content is None or flow.response.content == CONTENT_MISSING:
                return None, "Response content is missing"
            with decoded(flow.response):
                if part == "h":
                    data += netlib.http.http1.assemble_response(flow.response)
                elif part == "c":
                    data += flow.response.content
                else:
                    raise ValueError("Unknown part: {}".format(part))
    return data, False

def copy_as_curl_command(flow):

    if flow.request.content is None or flow.request.content == CONTENT_MISSING:
        return None, "Request content is missing"

    headerString = ""
    for k,v in flow.request.headers:
      headerString += " -H '" + k + ":" + v + "' "

    data = "curl"

    if flow.request.method != "GET":
      data += " -X " + flow.request.method

    full_url = flow.request.scheme + "://" + flow.request.host + flow.request.path
    data += " " + headerString + "'" + full_url + "'"

    if flow.request.content != None and flow.request.content != "":
      data += " --data-binary " + "'" + flow.request.content + "'"

    copy_to_clipboard_or_prompt(data)

def copy_to_clipboard_or_prompt(data):
    # pyperclip calls encode('utf-8') on data to be copied without checking.
    # if data are already encoded that way UnicodeDecodeError is thrown.
    toclip = ""
    try:
        toclip = data.decode('utf-8')
    except (UnicodeDecodeError):
        toclip = data

    try:
        pyperclip.copy(toclip)
    except (RuntimeError, UnicodeDecodeError, AttributeError):
        def save(k):
            if k == "y":
                ask_save_path("Save data", data)
        signals.status_prompt_onekey.send(
            prompt = "Cannot copy data to clipboard. Save as file?",
            keys = (
                ("yes", "y"),
                ("no", "n"),
            ),
            callback = save
        )

def copy_flow(part, scope, flow, master, state):
    """
    part: _c_ontent, _h_eaders+content, _u_rl
    scope: _a_ll, re_q_uest, re_s_ponse
    """
    data, err = copy_flow_format_data(part, scope, flow)

    if err:
        signals.status_message.send(message=err)
        return

    if not data:
        if scope == "q":
            signals.status_message.send(message="No request content to copy.")
        elif scope == "s":
            signals.status_message.send(message="No response content to copy.")
        else:
            signals.status_message.send(message="No contents to copy.")
        return

    copy_to_clipboard_or_prompt(data)

def ask_copy_part(scope, flow, master, state):
    choices = [
        ("content", "c"),
        ("headers+content", "h")
    ]
    if scope != "s":
        choices.append(("url", "u"))

    signals.status_prompt_onekey.send(
        prompt = "Copy",
        keys = choices,
        callback = copy_flow,
        args = (scope, flow, master, state)
    )

def ask_save_body(part, master, state, flow):
    """
    Save either the request or the response body to disk. part can either be
    "q" (request), "s" (response) or None (ask user if necessary).
    """

    request_has_content = flow.request and flow.request.content
    response_has_content = flow.response and flow.response.content

    if part is None:
        # We first need to determine whether we want to save the request or the
        # response content.
        if request_has_content and response_has_content:
            signals.status_prompt_onekey.send(
                prompt = "Save",
                keys = (
                    ("request", "q"),
                    ("response", "s"),
                ),
                callback = ask_save_body,
                args = (master, state, flow)
            )
        elif response_has_content:
            ask_save_body("s", master, state, flow)
        else:
            ask_save_body("q", master, state, flow)

    elif part == "q" and request_has_content:
        ask_save_path(
            "Save request content",
            flow.request.get_decoded_content()
        )
    elif part == "s" and response_has_content:
        ask_save_path(
            "Save response content",
            flow.response.get_decoded_content()
        )
    else:
        signals.status_message.send(message="No content to save.")

flowcache = utils.LRUCache(800)

def format_flow(f, focus, extended=False, hostheader=False, padding=2,
        marked=False):
    d = dict(
        intercepted = f.intercepted,
        acked = f.reply.acked,

        req_timestamp = f.request.timestamp_start,
        req_is_replay = f.request.is_replay,
        req_method = f.request.method,
        req_url = f.request.pretty_url if hostheader else f.request.url,

        err_msg = f.error.msg if f.error else None,
        resp_code = f.response.status_code if f.response else None,

        marked = marked,
    )
    if f.response:
        if f.response.content:
            contentdesc = netlib.utils.pretty_size(len(f.response.content))
        elif f.response.content == CONTENT_MISSING:
            contentdesc = "[content missing]"
        else:
            contentdesc = "[no content]"
        duration = 0
        if f.response.timestamp_end and f.request.timestamp_start:
            duration = f.response.timestamp_end - f.request.timestamp_start
        roundtrip = utils.pretty_duration(duration)

        d.update(dict(
            resp_code = f.response.status_code,
            resp_is_replay = f.response.is_replay,
            resp_clen = contentdesc,
            roundtrip = roundtrip,
        ))
        t = f.response.headers.get("content-type")
        if t:
            d["resp_ctype"] = t.split(";")[0]
        else:
            d["resp_ctype"] = ""
    return flowcache.get(
        raw_format_flow,
        tuple(sorted(d.items())), focus, extended, padding
    )
<|endoftext|>


<commit_before>from stack import Stack
from max import Max
from tile import Tile
from floating import Floating
from ratiotile import RatioTile
from tree import TreeTab
from slice import Slice
<commit_msg>Add MonadTall to layout module proper.<commit_after>from stack import Stack
from max import Max
from tile import Tile
from floating import Floating
from ratiotile import RatioTile
from tree import TreeTab
from slice import Slice
from xmonad import MonadTall
<|endoftext|>